From 95131df80f1fbd886c94e0cc99fc03b0ad340493 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 24 Sep 2024 22:35:12 +0200 Subject: [PATCH 01/87] Init --- compiler/.eslintconfig.json | 16 + compiler/.github/workflows/ci.yml | 26 + compiler/.gitignore | 27 + compiler/README.md | 6 + compiler/eslint.config.mjs | 46 + compiler/gen.sh | 13 + compiler/index.html | 60 + compiler/jest.config.ts | 203 + compiler/package.json | 40 + compiler/parser-gen/JackLexer.g4 | 61 + compiler/parser-gen/JackParser.g4 | 96 + compiler/parser-gen/Main.jack | 78 + compiler/parser-gen/Makefile | 10 + compiler/parser-gen/jack.ohm | 78 + compiler/pnpm-lock.yaml | 3489 +++++++++++++++++ compiler/public/vite.svg | 1 + compiler/src/VIsitor.ts | 55 + compiler/src/compiler.ts | 6 + compiler/src/error.listener.ts | 22 + compiler/src/generated/JackLexer.interp | 155 + compiler/src/generated/JackLexer.tokens | 84 + compiler/src/generated/JackLexer.ts | 278 ++ compiler/src/generated/JackParser.interp | 136 + compiler/src/generated/JackParser.tokens | 84 + compiler/src/generated/JackParser.ts | 3088 +++++++++++++++ compiler/src/generated/JackParserListener.ts | 479 +++ compiler/src/generated/JackParserVisitor.ts | 325 ++ compiler/src/main.ts | 18 + compiler/src/symbol.table.istener.ts | 97 + compiler/src/symbol.table.ts | 26 + compiler/src/vite-env.d.ts | 1 + compiler/test/parser.test.ts | 87 + compiler/test/resources/Average/Main.jack | 27 + .../test/resources/ComplexArrays/Main.jack | 69 + .../test/resources/ConvertToBin/Main.jack | 79 + .../test/resources/Fraction/Fraction.jack | 65 + compiler/test/resources/Fraction/Main.jack | 16 + compiler/test/resources/HelloWorld/Main.jack | 14 + compiler/test/resources/List/List.jack | 48 + compiler/test/resources/List/Main.jack | 17 + compiler/test/resources/Pong/Ball.jack | 202 + compiler/test/resources/Pong/Ball.vm | 435 ++ compiler/test/resources/Pong/Bat.jack | 103 + compiler/test/resources/Pong/Bat.vm | 208 + compiler/test/resources/Pong/Main.jack | 18 + compiler/test/resources/Pong/Main.vm | 13 + compiler/test/resources/Pong/PongGame.jack | 136 + compiler/test/resources/Pong/PongGame.vm | 321 ++ compiler/test/resources/Square/Main.jack | 15 + compiler/test/resources/Square/Square.jack | 113 + .../test/resources/Square/SquareGame.jack | 76 + compiler/test/symbol.table.test.ts | 10 + compiler/tsconfig.json | 40 + 53 files changed, 11216 insertions(+) create mode 100644 compiler/.eslintconfig.json create mode 100644 compiler/.github/workflows/ci.yml create mode 100644 compiler/.gitignore create mode 100644 compiler/README.md create mode 100644 compiler/eslint.config.mjs create mode 100644 compiler/gen.sh create mode 100644 compiler/index.html create mode 100644 compiler/jest.config.ts create mode 100644 compiler/package.json create mode 100644 compiler/parser-gen/JackLexer.g4 create mode 100644 compiler/parser-gen/JackParser.g4 create mode 100644 compiler/parser-gen/Main.jack create mode 100644 compiler/parser-gen/Makefile create mode 100644 compiler/parser-gen/jack.ohm create mode 100644 compiler/pnpm-lock.yaml create mode 100644 compiler/public/vite.svg create mode 100644 compiler/src/VIsitor.ts create mode 100644 compiler/src/compiler.ts create mode 100644 compiler/src/error.listener.ts create mode 100644 compiler/src/generated/JackLexer.interp create mode 100644 compiler/src/generated/JackLexer.tokens create mode 100644 compiler/src/generated/JackLexer.ts create mode 100644 compiler/src/generated/JackParser.interp create mode 100644 compiler/src/generated/JackParser.tokens create mode 100644 compiler/src/generated/JackParser.ts create mode 100644 compiler/src/generated/JackParserListener.ts create mode 100644 compiler/src/generated/JackParserVisitor.ts create mode 100644 compiler/src/main.ts create mode 100644 compiler/src/symbol.table.istener.ts create mode 100644 compiler/src/symbol.table.ts create mode 100644 compiler/src/vite-env.d.ts create mode 100644 compiler/test/parser.test.ts create mode 100644 compiler/test/resources/Average/Main.jack create mode 100644 compiler/test/resources/ComplexArrays/Main.jack create mode 100644 compiler/test/resources/ConvertToBin/Main.jack create mode 100644 compiler/test/resources/Fraction/Fraction.jack create mode 100644 compiler/test/resources/Fraction/Main.jack create mode 100644 compiler/test/resources/HelloWorld/Main.jack create mode 100644 compiler/test/resources/List/List.jack create mode 100644 compiler/test/resources/List/Main.jack create mode 100644 compiler/test/resources/Pong/Ball.jack create mode 100644 compiler/test/resources/Pong/Ball.vm create mode 100644 compiler/test/resources/Pong/Bat.jack create mode 100644 compiler/test/resources/Pong/Bat.vm create mode 100644 compiler/test/resources/Pong/Main.jack create mode 100644 compiler/test/resources/Pong/Main.vm create mode 100644 compiler/test/resources/Pong/PongGame.jack create mode 100644 compiler/test/resources/Pong/PongGame.vm create mode 100644 compiler/test/resources/Square/Main.jack create mode 100644 compiler/test/resources/Square/Square.jack create mode 100644 compiler/test/resources/Square/SquareGame.jack create mode 100644 compiler/test/symbol.table.test.ts create mode 100644 compiler/tsconfig.json diff --git a/compiler/.eslintconfig.json b/compiler/.eslintconfig.json new file mode 100644 index 00000000..33b6926c --- /dev/null +++ b/compiler/.eslintconfig.json @@ -0,0 +1,16 @@ +{ + "extends": [ + "react-app", + "react-app/jest" + ], + "rules": { + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + "args": "none", + "destructuredArrayIgnorePattern": "^_" + } + ] + } +} \ No newline at end of file diff --git a/compiler/.github/workflows/ci.yml b/compiler/.github/workflows/ci.yml new file mode 100644 index 00000000..17e9acff --- /dev/null +++ b/compiler/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: Tests + +on: [push] + +jobs: + build: + runs-on: ubuntu-22.04 + strategy: + matrix: + node-version: [20] + steps: + - uses: actions/checkout@v4 + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + - name: Install dependencies + run: pnpm install + - uses: actions/checkout@v1 + - name: Run Jest + uses: stefanoeb/jest-action@1.0.3 \ No newline at end of file diff --git a/compiler/.gitignore b/compiler/.gitignore new file mode 100644 index 00000000..115dabf4 --- /dev/null +++ b/compiler/.gitignore @@ -0,0 +1,27 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.coverage +docs +parser-gen/.antlr \ No newline at end of file diff --git a/compiler/README.md b/compiler/README.md new file mode 100644 index 00000000..69510622 --- /dev/null +++ b/compiler/README.md @@ -0,0 +1,6 @@ +TODO: +- add compiled code +- add symbol tbl +- add validations + - Constructor has return this + - \ No newline at end of file diff --git a/compiler/eslint.config.mjs b/compiler/eslint.config.mjs new file mode 100644 index 00000000..c29682fe --- /dev/null +++ b/compiler/eslint.config.mjs @@ -0,0 +1,46 @@ +import typescriptEslint from "@typescript-eslint/eslint-plugin"; +import globals from "globals"; +import tsParser from "@typescript-eslint/parser"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default [ + ...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"), + { + plugins: { + "@typescript-eslint": typescriptEslint, + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.jest, + ...globals.node, + }, + + parser: tsParser, + ecmaVersion: "latest", + sourceType: "module", + }, + + settings: { + react: { + version: "detect", + }, + }, + + rules: { + "react/react-in-jsx-scope": 0, + }, + }, +]; \ No newline at end of file diff --git a/compiler/gen.sh b/compiler/gen.sh new file mode 100644 index 00000000..07de373a --- /dev/null +++ b/compiler/gen.sh @@ -0,0 +1,13 @@ +#!/bin/bash +echo "Generating" +cd parser-gen +antlr4ts -Werror -visitor JackLexer.g4 JackParser.g4 -o ../src/generated +cd ../src/generated +sed -i -e 's/public get serializedATN(/public override get serializedATN\(/g' JackLexer.ts +sed -i -e 's/public get serializedATN(/public override get serializedATN\(/g' JackParser.ts +sed -i -e 's/public sempred(/public override sempred\(/g' JackParser.ts +sed -i -e 's/public get ruleIndex(/public override get ruleIndex\(/g' JackParser.ts +sed -i -e 's/public enterRule(/public override enterRule\(/g' JackParser.ts +sed -i -e 's/public exitRule(/public override exitRule\(/g' JackParser.ts +sed -i -e 's/public accept(/public override accept\(/g' JackParser.ts +sed -i -e 's/public copyFrom(/public override copyFrom\(/g' JackParser.ts \ No newline at end of file diff --git a/compiler/index.html b/compiler/index.html new file mode 100644 index 00000000..8fb68e12 --- /dev/null +++ b/compiler/index.html @@ -0,0 +1,60 @@ + + + + + + + + + Jack image converter + + + + + + + + + + + Jack image converter + + + + +
+
+
+ + +
+ + +
+
+
+
+ +
+
+ + + +
+ +
+ + + + + + + + + + \ No newline at end of file diff --git a/compiler/jest.config.ts b/compiler/jest.config.ts new file mode 100644 index 00000000..ff8a25d8 --- /dev/null +++ b/compiler/jest.config.ts @@ -0,0 +1,203 @@ +/** + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ + +/** @type {import('jest').Config} */ +const config = { + + + + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "/tmp/jest_rs", + + // Automatically clear mock calls, instances, contexts and results before every test + // clearMocks: false, + + // Indicates whether the coverage information should be collected while executing the test + // collectCoverage: false, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, + + // The directory where Jest should output its coverage files + // coverageDirectory: undefined, + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "/node_modules/" + // ], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "v8", + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + errorOnDeprecated: true, + + // The default configuration for fake timers + // fakeTimers: { + // "enableGlobally": false + // }, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + moduleDirectories: [ + "node_modules" + ], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "mjs", + // "cjs", + // "jsx", + // "ts", + // "tsx", + // "json", + // "node" + // ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + // moduleNameMapper: {}, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + //TODO: try out + notify: true, + + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + preset: 'ts-jest', + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state before every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state and implementation before every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + // setupFilesAfterEnv: [], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + testEnvironment: 'node', + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + // testMatch: [ + // "**/__tests__/**/*.[jt]s?(x)", + // "**/?(*.)+(spec|test).[tj]s?(x)" + // ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + testPathIgnorePatterns: [ + "/node_modules/" + ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", + + // A map from regular expressions to paths to transformers + // transform: undefined, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "/node_modules/", + // "\\.pnp\\.[^\\/]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + verbose: true, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + watchman: true, +}; + +export default config; diff --git a/compiler/package.json b/compiler/package.json new file mode 100644 index 00000000..95c6ad0b --- /dev/null +++ b/compiler/package.json @@ -0,0 +1,40 @@ +{ + "name": "compiler", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview", + "test": "jest", + "test-w": "jest --watchAll", + "fix": "eslint --fix", + "gen": "bash gen.sh", + "watch": "nodemon -e jack,ts -w src -w test -x \"npm run test \"" + }, + "nodemonConfig": { + "delay": 700 + }, + "modulePaths": [ + "/src/" + ], + "devDependencies": { + "@types/jest": "^29.5.13", + "@types/node": "^22.5.5", + "antlr4ts-cli": "0.5.0-alpha.4", + "jest": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-text-transformer": "^1.0.4", + "node-notifier": "^10.0.1", + "nodemon": "^3.1.7", + "npm-watch": "^0.13.0", + "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", + "typescript": "^5.5.3", + "vite": "^5.4.1" + }, + "dependencies": { + "antlr4ts": "0.5.0-alpha.4" + } +} diff --git a/compiler/parser-gen/JackLexer.g4 b/compiler/parser-gen/JackLexer.g4 new file mode 100644 index 00000000..7ad3e5ca --- /dev/null +++ b/compiler/parser-gen/JackLexer.g4 @@ -0,0 +1,61 @@ +lexer grammar JackLexer; + +CLASS: 'class'; +CONSTRUCTOR: 'constructor'; +FUNCTION: 'function'; +METHOD: 'method'; +FIELD: 'field'; +STATIC: 'static'; +VAR: 'var'; +INT: 'int'; +CHAR: 'char'; +BOOLEAN: 'boolean'; +VOID: 'void'; + +LET: 'let'; +DO: 'do'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +RETURN: 'return'; + + +LBRACE: '{'; +RBRACE: '}'; +LPAREN: '('; +RPAREN: ')'; +LBRACKET: '['; +RBRACKET: ']'; +DOT: '.'; +COMMA: ','; +SEMICOLON: ';'; + +EQUALS: '='; +PLUS: '+'; +MINUS: '-'; +MUL: '*'; +DIV: '/'; +AND: '&'; +OR: '|'; +TILDE: '~'; +LESS_THAN: '<'; +GREATER_THAN: '>'; + +WS: [ \t\r\n]+ -> skip; +COMMENT: '/*' .*? '*/' -> skip; +LINE_COMMENT: '//' ~[\r\n]* -> skip; + +INTEGER_LITERAL: [0-9]+; +BOOLEAN_LITERAL: 'true' | 'false'; +NULL_LITERAL: 'null'; +THIS_LITERAL: 'this'; + +IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; + +STRING_LITERAL + : UnterminatedStringLiteral '"' + ; +UnterminatedStringLiteral + : '"' ~["\\\r\n]* + ; + diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/parser-gen/JackParser.g4 new file mode 100644 index 00000000..4634c7b2 --- /dev/null +++ b/compiler/parser-gen/JackParser.g4 @@ -0,0 +1,96 @@ +parser grammar JackParser; + +options { + tokenVocab = JackLexer; +} + +program: classDeclaration EOF; + +classDeclaration: + CLASS className LBRACE classVarDec* subroutineDec* RBRACE; +className: IDENTIFIER; +classVarDec: + STATIC fieldList SEMICOLON # staticFieldDeclaration + | FIELD fieldList SEMICOLON # fieldDeclaration; +fieldList: varType fieldName ( COMMA fieldName)*; +fieldName: IDENTIFIER; +subroutineDec: {console.log("Subroutine")} + CONSTRUCTOR subroutineDecWithoutType # constructor + | METHOD subroutineDecWithoutType # method + | FUNCTION subroutineDecWithoutType # function; +subroutineDecWithoutType: + subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; +subroutineName: IDENTIFIER; +subroutineReturnType: varType | VOID; + +varType: INT | CHAR | BOOLEAN | IDENTIFIER; + +parameterList: (parameter (COMMA parameter)*)?; +parameter: varType parameterName; +parameterName: IDENTIFIER; +subroutineBody: + LBRACE varDec* statements RBRACE; + +varDec: VAR varType varName (COMMA IDENTIFIER)* SEMICOLON; +varName: IDENTIFIER; +statements: statement*; +statement: + letStatement + | ifStatement + | whileStatement + | doStatement + | returnStatement; + +letStatement: + LET (IDENTIFIER | arrayAccess) EQUALS expression SEMICOLON; //TODO: check right assoc for this + +ifStatement: + IF LPAREN expression RPAREN LBRACE statements RBRACE ( + ELSE LBRACE statements RBRACE + )?; + +whileStatement: + WHILE LPAREN expression RPAREN LBRACE statements RBRACE; + +doStatement: DO subroutineCall SEMICOLON; + +subroutineCall: + IDENTIFIER LPAREN expressionList RPAREN + | (IDENTIFIER | THIS_LITERAL) DOT IDENTIFIER LPAREN expressionList RPAREN; + +returnStatement: RETURN expression? SEMICOLON; + +expressionList: (expression (COMMA expression)*)?; + +expression: + binaryOperation = expression binaryOperator expression + | constant + | IDENTIFIER + | subroutineCall + | arrayAccess + | unaryOp + | groupedExpression; + +groupedExpression: LPAREN expression RPAREN; +unaryOp: unaryOperator expression; +arrayAccess: IDENTIFIER LBRACKET expression RBRACKET; + +constant: + INTEGER_LITERAL + | STRING_LITERAL + | BOOLEAN_LITERAL + | NULL_LITERAL + | THIS_LITERAL; + +unaryOperator: TILDE | MINUS; +binaryOperator: + PLUS + | MINUS + | MUL + | DIV + | AND + | OR + | LESS_THAN + | GREATER_THAN + | EQUALS; + diff --git a/compiler/parser-gen/Main.jack b/compiler/parser-gen/Main.jack new file mode 100644 index 00000000..d3400ca1 --- /dev/null +++ b/compiler/parser-gen/Main.jack @@ -0,0 +1,78 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/ConvertToBin/Main.jack +/** + * Unpacks a 16-bit number into its binary representation: + * Takes the 16-bit number stored in RAM[8000] and stores its individual + * bits in RAM[8001]..RAM[8016] (each location will contain 0 or 1). + * Before the conversion, RAM[8001]..RAM[8016] are initialized to -1. + * + * The program should be tested as follows: + * 1) Load the compiled program into the supplied VM emulator + * 2) Put some value in RAM[8000] + * 3) Switch to "no animation" + * 4) Run the program (give it enough time to run) + * 5) Stop the program + * 6) Check that RAM[8001]..RAM[8016] contains the correct binary result, and + * that none of these memory locations contains -1. + */ +class Main { + /** Initializes RAM[8001]..RAM[8016] to -1, + * and converts the value in RAM[8000] to binary. */ + function void main() { + var int value; + do Main.fillMemory(8001, 16, -1); // sets RAM[8001]..RAM[8016] to -1 + let value = Memory.peek(8000); // reads a value from RAM[8000] + do Main.convert(value); // performs the conversion + return; + } + + /** Converts the given decimal value to binary, and puts + * the resulting bits in RAM[8001]..RAM[8016]. */ + function void convert(int value) { + var int mask, position; + var boolean loop; + + let loop = true; + while (loop) { + let position = position + 1; + let mask = Main.nextMask(mask); + + if (~(position > 16)) { + + if (~((value & mask) = 0)) { + do Memory.poke(8000 + position, 1); + } + else { + do Memory.poke(8000 + position, 0); + } + } + else { + let loop = false; + } + } + return; + } + + /** Returns the next mask (the mask that should follow the given mask). */ + function int nextMask(int mask) { + if (mask = 0) { + return 1; + } + else { + return mask * 2; + } + } + + /** Fills 'length' consecutive memory locations with 'value', + * starting at 'startAddress'. */ + function void fillMemory(int startAddress, int length, int value) { + while (length > 0) { + do Memory.poke(startAddress, value); + let length = length - 1; + let startAddress = startAddress + 1; + } + return; + } +} diff --git a/compiler/parser-gen/Makefile b/compiler/parser-gen/Makefile new file mode 100644 index 00000000..8be4b949 --- /dev/null +++ b/compiler/parser-gen/Makefile @@ -0,0 +1,10 @@ +trace: + antlr4-parse JackLexer.g4 JackParser.g4 program -tokens -trace< Main.jack + +tokens: + antlr4-parse JackLexer.g4 JackParser.g4 program -tokens < Main.jack + +gui: + antlr4-parse JackLexer.g4 JackParser.g4 program -gui < Main.jack +gen: + antlr4 JackLexer.g4 JackParser.g4 -o ./output \ No newline at end of file diff --git a/compiler/parser-gen/jack.ohm b/compiler/parser-gen/jack.ohm new file mode 100644 index 00000000..f313b9e8 --- /dev/null +++ b/compiler/parser-gen/jack.ohm @@ -0,0 +1,78 @@ +Jack <: Base { + Root := Class + + whitespace = (lineComment | comment | space) + + class = "class" whitespace+ + Class = class jackIdentifier OpenBrace ClassVarDec* SubroutineDec* CloseBrace + + type = ("int" | "char" | "boolean" | jackIdentifier) whitespace+ + + classVarType = ("static" | "field") whitespace+ + ClassVarDec = classVarType type jackIdentifier TrailingIdentifier* Semi + TrailingIdentifier = Comma jackIdentifier + + void = "void" whitespace+ + returnType = (type | void) + subroutineType = ("constructor" | "function" | "method") whitespace+ + SubroutineDec = subroutineType returnType jackIdentifier OpenParen ParameterList CloseParen SubroutineBody + + + Parameter = type jackIdentifier + Parameters = Parameter TrailingParameter* + TrailingParameter = Comma Parameter + ParameterList = Parameters? + + SubroutineBody = OpenBrace VarDec* Statement* CloseBrace + + var = "var" whitespace+ + VarDec = var type jackIdentifier TrailingIdentifier* Semi + + Statement = LetStatement | IfStatement | WhileStatement | DoStatement | ReturnStatement + + arrayAccessStart = jackIdentifier openSquare + ArrayAccess = arrayAccessStart Expression CloseSquare + + let = "let" whitespace+ + LetTarget = ArrayAccess | jackIdentifier + LetStatement = let LetTarget Equal Expression Semi + + IfStatement = "if" OpenParen Expression CloseParen OpenBrace Statement* CloseBrace ElseBlock? + ElseBlock = "else" OpenBrace Statement* CloseBrace + + WhileStatement = "while" OpenParen Expression CloseParen OpenBrace Statement* CloseBrace + + do = "do" whitespace+ + DoStatement = do SubroutineCall Semi + + return = "return" + returnWithSpace = "return" whitespace+ + ReturnStatement = EmptyReturn | ReturnValue + EmptyReturn = return Semi + ReturnValue = returnWithSpace Expression Semi + + op = "+" | "-" | "*" | "/" | "&" | "|" | "<" | ">" | "=" + ExpressionPart = op Term + Expression = Term ExpressionPart* + + integerConstant = digit+ + stringConstant = doubleQuote (~doubleQuote ~newline any)* doubleQuote + keywordConstant = "true" | "false" | "null" | "this" + + GroupedExpression = OpenParen Expression CloseParen + + unaryOp = "-" | "~" + UnaryExpression = unaryOp Term + + Term = integerConstant | stringConstant | keywordConstant | SubroutineCall | ArrayAccess | jackIdentifier | GroupedExpression | UnaryExpression + + compoundIdentifier = jackIdentifier dot jackIdentifier + SubroutineName = compoundIdentifier | jackIdentifier + SubroutineCall = SubroutineName OpenParen ExpressionList CloseParen + + ExpressionList = Expressions? + Expressions = Expression TrailingExpression* + TrailingExpression = Comma Expression + + jackIdentifier = letter (alnum | underscore)* +} \ No newline at end of file diff --git a/compiler/pnpm-lock.yaml b/compiler/pnpm-lock.yaml new file mode 100644 index 00000000..64b3bc0d --- /dev/null +++ b/compiler/pnpm-lock.yaml @@ -0,0 +1,3489 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + antlr4ts: + specifier: 0.5.0-alpha.4 + version: 0.5.0-alpha.4 + devDependencies: + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 + '@types/node': + specifier: ^22.5.5 + version: 22.5.5 + antlr4ts-cli: + specifier: 0.5.0-alpha.4 + version: 0.5.0-alpha.4 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + jest-matcher-utils: + specifier: ^29.7.0 + version: 29.7.0 + jest-text-transformer: + specifier: ^1.0.4 + version: 1.0.4 + node-notifier: + specifier: ^10.0.1 + version: 10.0.1 + nodemon: + specifier: ^3.1.7 + version: 3.1.7 + npm-watch: + specifier: ^0.13.0 + version: 0.13.0 + ts-jest: + specifier: ^29.2.5 + version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)))(typescript@5.6.2) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@22.5.5)(typescript@5.6.2) + typescript: + specifier: ^5.5.3 + version: 5.6.2 + vite: + specifier: ^5.4.1 + version: 5.4.7(@types/node@22.5.5) + +packages: + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.25.4': + resolution: {integrity: sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.25.2': + resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.25.6': + resolution: {integrity: sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.25.2': + resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.24.7': + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.25.2': + resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.24.8': + resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-simple-access@7.24.7': + resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.24.8': + resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.24.8': + resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.25.6': + resolution: {integrity: sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.25.6': + resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.25.6': + resolution: {integrity: sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.24.7': + resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.4': + resolution: {integrity: sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.25.0': + resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.25.6': + resolution: {integrity: sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.25.6': + resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@29.7.0': + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/core@29.7.0': + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/reporters@29.7.0': + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/source-map@29.6.3': + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-result@29.7.0': + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-sequencer@29.7.0': + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@rollup/rollup-android-arm-eabi@4.22.4': + resolution: {integrity: sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.22.4': + resolution: {integrity: sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.22.4': + resolution: {integrity: sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.22.4': + resolution: {integrity: sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.22.4': + resolution: {integrity: sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.22.4': + resolution: {integrity: sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.22.4': + resolution: {integrity: sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.22.4': + resolution: {integrity: sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': + resolution: {integrity: sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.22.4': + resolution: {integrity: sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.22.4': + resolution: {integrity: sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.22.4': + resolution: {integrity: sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.22.4': + resolution: {integrity: sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.22.4': + resolution: {integrity: sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.22.4': + resolution: {integrity: sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.22.4': + resolution: {integrity: sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==} + cpu: [x64] + os: [win32] + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.13': + resolution: {integrity: sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==} + + '@types/node@22.5.5': + resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + antlr4ts-cli@0.5.0-alpha.4: + resolution: {integrity: sha512-lVPVBTA2CVHRYILSKilL6Jd4hAumhSZZWA7UbQNQrmaSSj7dPmmYaN4bOmZG79cOy0lS00i4LY68JZZjZMWVrw==} + hasBin: true + + antlr4ts@0.5.0-alpha.4: + resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.23.3: + resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001662: + resolution: {integrity: sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.27: + resolution: {integrity: sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + growly@1.3.0: + resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + + jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@29.7.0: + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-text-transformer@1.0.4: + resolution: {integrity: sha512-Qi3FpWP6EFxZimSD05Zlmd/WER8l/3agVG7e5voHgdnM2vTs45sxS/i8qMWMO/dBkoxajndrGXfJTvhEENnjqw==} + engines: {node: '>=9.5.0', npm: '>=5.8.0'} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-notifier@10.0.1: + resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==} + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + + nodemon@3.1.7: + resolution: {integrity: sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==} + engines: {node: '>=10'} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + npm-watch@0.13.0: + resolution: {integrity: sha512-MYcgocqCzYA44feZhFoYj69FfSaO0EeRE1gcRcmPaXIpNhUMAhNJ1pwic2C4Hn0OPOQmZKSl90CPgmwvOsVhTg==} + hasBin: true + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + engines: {node: ^10 || ^12 || >=14} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + rollup@4.22.4: + resolution: {integrity: sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shellwords@0.1.1: + resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + touch@3.1.1: + resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} + hasBin: true + + ts-jest@29.2.5: + resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/transform': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} + engines: {node: '>=14.17'} + hasBin: true + + undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + update-browserslist-db@1.1.0: + resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + + vite@5.4.7: + resolution: {integrity: sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.1.0 + + '@babel/compat-data@7.25.4': {} + + '@babel/core@7.25.2': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.6 + '@babel/helper-compilation-targets': 7.25.2 + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) + '@babel/helpers': 7.25.6 + '@babel/parser': 7.25.6 + '@babel/template': 7.25.0 + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 + convert-source-map: 2.0.0 + debug: 4.3.7(supports-color@5.5.0) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.25.6': + dependencies: + '@babel/types': 7.25.6 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + + '@babel/helper-compilation-targets@7.25.2': + dependencies: + '@babel/compat-data': 7.25.4 + '@babel/helper-validator-option': 7.24.8 + browserslist: 4.23.3 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-module-imports@7.24.7': + dependencies: + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + '@babel/traverse': 7.25.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.24.8': {} + + '@babel/helper-simple-access@7.24.7': + dependencies: + '@babel/traverse': 7.25.6 + '@babel/types': 7.25.6 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.24.8': {} + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/helper-validator-option@7.24.8': {} + + '@babel/helpers@7.25.6': + dependencies: + '@babel/template': 7.25.0 + '@babel/types': 7.25.6 + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.1.0 + + '@babel/parser@7.25.6': + dependencies: + '@babel/types': 7.25.6 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-import-attributes@7.25.6(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + + '@babel/template@7.25.0': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 + + '@babel/traverse@7.25.6': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.25.6 + '@babel/parser': 7.25.6 + '@babel/template': 7.25.0 + '@babel/types': 7.25.6 + debug: 4.3.7(supports-color@5.5.0) + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.25.6': + dependencies: + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@bcoe/v8-coverage@0.2.3': {} + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + + '@jest/core@29.7.0(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0(node-notifier@10.0.1) + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + optionalDependencies: + node-notifier: 10.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + jest-mock: 29.7.0 + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 22.5.5 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/reporters@29.7.0(node-notifier@10.0.1)': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + '@types/node': 22.5.5 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + optionalDependencies: + node-notifier: 10.0.1 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.25.2 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.5.5 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@rollup/rollup-android-arm-eabi@4.22.4': + optional: true + + '@rollup/rollup-android-arm64@4.22.4': + optional: true + + '@rollup/rollup-darwin-arm64@4.22.4': + optional: true + + '@rollup/rollup-darwin-x64@4.22.4': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.22.4': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.22.4': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.22.4': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-x64-musl@4.22.4': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.22.4': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.22.4': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.22.4': + optional: true + + '@sinclair/typebox@0.27.8': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.25.6 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.25.6 + '@babel/types': 7.25.6 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.25.6 + + '@types/estree@1.0.5': {} + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 22.5.5 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.13': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + + '@types/node@22.5.5': + dependencies: + undici-types: 6.19.8 + + '@types/stack-utils@2.0.3': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + + acorn-walk@8.3.4: + dependencies: + acorn: 8.12.1 + + acorn@8.12.1: {} + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + antlr4ts-cli@0.5.0-alpha.4: {} + + antlr4ts@0.5.0-alpha.4: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@4.1.3: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + async@3.2.6: {} + + babel-jest@29.7.0(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.25.2) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.24.8 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.25.0 + '@babel/types': 7.25.6 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-import-attributes': 7.25.6(@babel/core@7.25.2) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.2) + + babel-preset-jest@29.6.3(@babel/core@7.25.2): + dependencies: + '@babel/core': 7.25.2 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.2) + + balanced-match@1.0.2: {} + + binary-extensions@2.3.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.23.3: + dependencies: + caniuse-lite: 1.0.30001662 + electron-to-chromium: 1.5.27 + node-releases: 2.0.18 + update-browserslist-db: 1.1.0(browserslist@4.23.3) + + bs-logger@0.2.6: + dependencies: + fast-json-stable-stringify: 2.1.0 + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + callsites@3.1.0: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001662: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + char-regex@1.0.2: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + ci-info@3.9.0: {} + + cjs-module-lexer@1.4.1: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + co@4.6.0: {} + + collect-v8-coverage@1.0.2: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + concat-map@0.0.1: {} + + convert-source-map@2.0.0: {} + + create-jest@29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + create-require@1.1.1: {} + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + debug@4.3.7(supports-color@5.5.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 5.5.0 + + dedent@1.5.3: {} + + deepmerge@4.3.1: {} + + detect-newline@3.1.0: {} + + diff-sequences@29.6.3: {} + + diff@4.0.2: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-to-chromium@1.5.27: {} + + emittery@0.13.1: {} + + emoji-regex@8.0.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + esprima@4.0.1: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exit@0.1.2: {} + + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + + fast-json-stable-stringify@2.1.0: {} + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-package-type@0.1.0: {} + + get-stream@6.0.1: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@11.12.0: {} + + graceful-fs@4.2.11: {} + + growly@1.3.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + html-escaper@2.0.2: {} + + human-signals@2.1.0: {} + + ignore-by-default@1.0.1: {} + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-docker@2.2.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-fn@2.1.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-stream@2.0.1: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isexe@2.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.25.2 + '@babel/parser': 7.25.6 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.25.2 + '@babel/parser': 7.25.6 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.3.7(supports-color@5.5.0) + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + + jest-changed-files@29.7.0: + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + + jest-circus@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)): + dependencies: + '@jest/core': 29.7.0(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + optionalDependencies: + node-notifier: 10.0.1 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-config@29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)): + dependencies: + '@babel/core': 7.25.2 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.25.2) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.5.5 + ts-node: 10.9.2(@types/node@22.5.5)(typescript@5.6.2) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + jest-get-type@29.6.3: {} + + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.5.5 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-leak-detector@29.7.0: + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.24.7 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + jest-util: 29.7.0 + + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-resolve-dependencies@29.7.0: + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + jest-resolve@29.7.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.8 + resolve.exports: 2.0.2 + slash: 3.0.0 + + jest-runner@29.7.0: + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + chalk: 4.1.2 + cjs-module-lexer: 1.4.1 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.25.2 + '@babel/generator': 7.25.6 + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) + '@babel/types': 7.25.6 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.2) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + jest-text-transformer@1.0.4: + dependencies: + uuid: 3.4.0 + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.5.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + + jest-worker@29.7.0: + dependencies: + '@types/node': 22.5.5 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)): + dependencies: + '@jest/core': 29.7.0(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + optionalDependencies: + node-notifier: 10.0.1 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + jsesc@2.5.2: {} + + json-parse-even-better-errors@2.3.1: {} + + json5@2.2.3: {} + + kleur@3.0.3: {} + + leven@3.1.0: {} + + lines-and-columns@1.2.4: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + lodash.memoize@4.1.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + make-dir@4.0.0: + dependencies: + semver: 7.6.3 + + make-error@1.3.6: {} + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + merge-stream@2.0.0: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mimic-fn@2.1.0: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + ms@2.1.3: {} + + nanoid@3.3.7: {} + + natural-compare@1.4.0: {} + + node-int64@0.4.0: {} + + node-notifier@10.0.1: + dependencies: + growly: 1.3.0 + is-wsl: 2.2.0 + semver: 7.6.3 + shellwords: 0.1.1 + uuid: 8.3.2 + which: 2.0.2 + + node-releases@2.0.18: {} + + nodemon@3.1.7: + dependencies: + chokidar: 3.6.0 + debug: 4.3.7(supports-color@5.5.0) + ignore-by-default: 1.0.1 + minimatch: 3.1.2 + pstree.remy: 1.1.8 + semver: 7.6.3 + simple-update-notifier: 2.0.0 + supports-color: 5.5.0 + touch: 3.1.1 + undefsafe: 2.0.5 + + normalize-path@3.0.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + npm-watch@0.13.0: + dependencies: + nodemon: 3.1.7 + through2: 4.0.2 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-try@2.2.0: {} + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.24.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + picocolors@1.1.0: {} + + picomatch@2.3.1: {} + + pirates@4.0.6: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + postcss@8.4.47: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.0 + source-map-js: 1.2.1 + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + pstree.remy@1.1.8: {} + + pure-rand@6.1.0: {} + + react-is@18.3.1: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + require-directory@2.1.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@5.0.0: {} + + resolve.exports@2.0.2: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + rollup@4.22.4: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.22.4 + '@rollup/rollup-android-arm64': 4.22.4 + '@rollup/rollup-darwin-arm64': 4.22.4 + '@rollup/rollup-darwin-x64': 4.22.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.22.4 + '@rollup/rollup-linux-arm-musleabihf': 4.22.4 + '@rollup/rollup-linux-arm64-gnu': 4.22.4 + '@rollup/rollup-linux-arm64-musl': 4.22.4 + '@rollup/rollup-linux-powerpc64le-gnu': 4.22.4 + '@rollup/rollup-linux-riscv64-gnu': 4.22.4 + '@rollup/rollup-linux-s390x-gnu': 4.22.4 + '@rollup/rollup-linux-x64-gnu': 4.22.4 + '@rollup/rollup-linux-x64-musl': 4.22.4 + '@rollup/rollup-win32-arm64-msvc': 4.22.4 + '@rollup/rollup-win32-ia32-msvc': 4.22.4 + '@rollup/rollup-win32-x64-msvc': 4.22.4 + fsevents: 2.3.3 + + safe-buffer@5.2.1: {} + + semver@6.3.1: {} + + semver@7.6.3: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shellwords@0.1.1: {} + + signal-exit@3.0.7: {} + + simple-update-notifier@2.0.0: + dependencies: + semver: 7.6.3 + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + source-map-js@1.2.1: {} + + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + sprintf-js@1.0.3: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-bom@4.0.0: {} + + strip-final-newline@2.0.0: {} + + strip-json-comments@3.1.1: {} + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + through2@4.0.2: + dependencies: + readable-stream: 3.6.2 + + tmpl@1.0.5: {} + + to-fast-properties@2.0.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + touch@3.1.1: {} + + ts-jest@29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)))(typescript@5.6.2): + dependencies: + bs-logger: 0.2.6 + ejs: 3.1.10 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) + jest-util: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.6.3 + typescript: 5.6.2 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.25.2 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.25.2) + + ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.5.5 + acorn: 8.12.1 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.6.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + type-detect@4.0.8: {} + + type-fest@0.21.3: {} + + typescript@5.6.2: {} + + undefsafe@2.0.5: {} + + undici-types@6.19.8: {} + + update-browserslist-db@1.1.0(browserslist@4.23.3): + dependencies: + browserslist: 4.23.3 + escalade: 3.2.0 + picocolors: 1.1.0 + + util-deprecate@1.0.2: {} + + uuid@3.4.0: {} + + uuid@8.3.2: {} + + v8-compile-cache-lib@3.0.1: {} + + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + + vite@5.4.7(@types/node@22.5.5): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.47 + rollup: 4.22.4 + optionalDependencies: + '@types/node': 22.5.5 + fsevents: 2.3.3 + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yn@3.1.1: {} + + yocto-queue@0.1.0: {} diff --git a/compiler/public/vite.svg b/compiler/public/vite.svg new file mode 100644 index 00000000..e7b8dfb1 --- /dev/null +++ b/compiler/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/compiler/src/VIsitor.ts b/compiler/src/VIsitor.ts new file mode 100644 index 00000000..04de7b8f --- /dev/null +++ b/compiler/src/VIsitor.ts @@ -0,0 +1,55 @@ +import { ClassDeclarationContext, ClassNameContext, SubroutineDecContext } from './generated/JackParser'; +import { JackParserVisitor } from './generated/JackParserVisitor'; +import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor' + +export class Visitor extends AbstractParseTreeVisitor implements JackParserVisitor { + protected override defaultResult(): string { + return ""; + } + + override aggregateResult(aggregate: string, nextResult: string) { + return aggregate + nextResult + } + visitSubroutineDec(ctx: SubroutineDecContext): string { + const c = ctx.parent + return "" + super.visitChildren(ctx); + }; + +} + +/** + * // Compiled Main.jack: +function Main.main 0 + push constant 12 + call String.new 1 + push constant 72 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 111 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 119 + call String.appendChar 2 + push constant 111 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 100 + call String.appendChar 2 + push constant 33 + call String.appendChar 2 + call Output.printString 1 + pop temp 0 + call Output.println 0 + pop temp 0 + push constant 0 + return + */ \ No newline at end of file diff --git a/compiler/src/compiler.ts b/compiler/src/compiler.ts new file mode 100644 index 00000000..141124a9 --- /dev/null +++ b/compiler/src/compiler.ts @@ -0,0 +1,6 @@ + +export default class Compiler { + static compile(source: string): string { + return ""; + } +} \ No newline at end of file diff --git a/compiler/src/error.listener.ts b/compiler/src/error.listener.ts new file mode 100644 index 00000000..c632a718 --- /dev/null +++ b/compiler/src/error.listener.ts @@ -0,0 +1,22 @@ +import { ANTLRErrorListener, RecognitionException, Recognizer } from 'antlr4ts'; +export class ErrorListener implements ANTLRErrorListener { + static instance: ErrorListener; + public filepath: string = ""; + public error: boolean = false; + static getInstance(): ErrorListener { + if (this.instance == null) { + this.instance = new ErrorListener() + } + return this.instance; + } + + + // constructor(private filepath: string, ) { }; + /** + * Provides a default instance of {@link ConsoleErrorListener}. + */ + syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number, charPositionInLine: number, msg: string, e: RecognitionException | undefined) { + this.error = true; + console.error(`${this.filepath}:${line}:${charPositionInLine} \n${msg}`); + }; +} \ No newline at end of file diff --git a/compiler/src/generated/JackLexer.interp b/compiler/src/generated/JackLexer.interp new file mode 100644 index 00000000..42ef73e8 --- /dev/null +++ b/compiler/src/generated/JackLexer.interp @@ -0,0 +1,155 @@ +token literal names: +null +'class' +'constructor' +'function' +'method' +'field' +'static' +'var' +'int' +'char' +'boolean' +'void' +'let' +'do' +'if' +'else' +'while' +'return' +'{' +'}' +'(' +')' +'[' +']' +'.' +',' +';' +'=' +'+' +'-' +'*' +'/' +'&' +'|' +'~' +'<' +'>' +null +null +null +null +null +'null' +'this' +null +null +null + +token symbolic names: +null +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +BOOLEAN_LITERAL +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +rule names: +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +BOOLEAN_LITERAL +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 48, 309, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 6, 38, 236, 10, 38, 13, 38, 14, 38, 237, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 7, 39, 246, 10, 39, 12, 39, 14, 39, 249, 11, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 7, 40, 260, 10, 40, 12, 40, 14, 40, 263, 11, 40, 3, 40, 3, 40, 3, 41, 6, 41, 268, 10, 41, 13, 41, 14, 41, 269, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 5, 42, 281, 10, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 7, 45, 295, 10, 45, 12, 45, 14, 45, 298, 11, 45, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 7, 47, 305, 10, 47, 12, 47, 14, 47, 308, 11, 47, 3, 247, 2, 2, 48, 3, 2, 3, 5, 2, 4, 7, 2, 5, 9, 2, 6, 11, 2, 7, 13, 2, 8, 15, 2, 9, 17, 2, 10, 19, 2, 11, 21, 2, 12, 23, 2, 13, 25, 2, 14, 27, 2, 15, 29, 2, 16, 31, 2, 17, 33, 2, 18, 35, 2, 19, 37, 2, 20, 39, 2, 21, 41, 2, 22, 43, 2, 23, 45, 2, 24, 47, 2, 25, 49, 2, 26, 51, 2, 27, 53, 2, 28, 55, 2, 29, 57, 2, 30, 59, 2, 31, 61, 2, 32, 63, 2, 33, 65, 2, 34, 67, 2, 35, 69, 2, 36, 71, 2, 37, 73, 2, 38, 75, 2, 39, 77, 2, 40, 79, 2, 41, 81, 2, 42, 83, 2, 43, 85, 2, 44, 87, 2, 45, 89, 2, 46, 91, 2, 47, 93, 2, 48, 3, 2, 8, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 6, 2, 50, 59, 67, 92, 97, 97, 99, 124, 6, 2, 12, 12, 15, 15, 36, 36, 94, 94, 2, 315, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2, 2, 91, 3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 3, 95, 3, 2, 2, 2, 5, 101, 3, 2, 2, 2, 7, 113, 3, 2, 2, 2, 9, 122, 3, 2, 2, 2, 11, 129, 3, 2, 2, 2, 13, 135, 3, 2, 2, 2, 15, 142, 3, 2, 2, 2, 17, 146, 3, 2, 2, 2, 19, 150, 3, 2, 2, 2, 21, 155, 3, 2, 2, 2, 23, 163, 3, 2, 2, 2, 25, 168, 3, 2, 2, 2, 27, 172, 3, 2, 2, 2, 29, 175, 3, 2, 2, 2, 31, 178, 3, 2, 2, 2, 33, 183, 3, 2, 2, 2, 35, 189, 3, 2, 2, 2, 37, 196, 3, 2, 2, 2, 39, 198, 3, 2, 2, 2, 41, 200, 3, 2, 2, 2, 43, 202, 3, 2, 2, 2, 45, 204, 3, 2, 2, 2, 47, 206, 3, 2, 2, 2, 49, 208, 3, 2, 2, 2, 51, 210, 3, 2, 2, 2, 53, 212, 3, 2, 2, 2, 55, 214, 3, 2, 2, 2, 57, 216, 3, 2, 2, 2, 59, 218, 3, 2, 2, 2, 61, 220, 3, 2, 2, 2, 63, 222, 3, 2, 2, 2, 65, 224, 3, 2, 2, 2, 67, 226, 3, 2, 2, 2, 69, 228, 3, 2, 2, 2, 71, 230, 3, 2, 2, 2, 73, 232, 3, 2, 2, 2, 75, 235, 3, 2, 2, 2, 77, 241, 3, 2, 2, 2, 79, 255, 3, 2, 2, 2, 81, 267, 3, 2, 2, 2, 83, 280, 3, 2, 2, 2, 85, 282, 3, 2, 2, 2, 87, 287, 3, 2, 2, 2, 89, 292, 3, 2, 2, 2, 91, 299, 3, 2, 2, 2, 93, 302, 3, 2, 2, 2, 95, 96, 7, 101, 2, 2, 96, 97, 7, 110, 2, 2, 97, 98, 7, 99, 2, 2, 98, 99, 7, 117, 2, 2, 99, 100, 7, 117, 2, 2, 100, 4, 3, 2, 2, 2, 101, 102, 7, 101, 2, 2, 102, 103, 7, 113, 2, 2, 103, 104, 7, 112, 2, 2, 104, 105, 7, 117, 2, 2, 105, 106, 7, 118, 2, 2, 106, 107, 7, 116, 2, 2, 107, 108, 7, 119, 2, 2, 108, 109, 7, 101, 2, 2, 109, 110, 7, 118, 2, 2, 110, 111, 7, 113, 2, 2, 111, 112, 7, 116, 2, 2, 112, 6, 3, 2, 2, 2, 113, 114, 7, 104, 2, 2, 114, 115, 7, 119, 2, 2, 115, 116, 7, 112, 2, 2, 116, 117, 7, 101, 2, 2, 117, 118, 7, 118, 2, 2, 118, 119, 7, 107, 2, 2, 119, 120, 7, 113, 2, 2, 120, 121, 7, 112, 2, 2, 121, 8, 3, 2, 2, 2, 122, 123, 7, 111, 2, 2, 123, 124, 7, 103, 2, 2, 124, 125, 7, 118, 2, 2, 125, 126, 7, 106, 2, 2, 126, 127, 7, 113, 2, 2, 127, 128, 7, 102, 2, 2, 128, 10, 3, 2, 2, 2, 129, 130, 7, 104, 2, 2, 130, 131, 7, 107, 2, 2, 131, 132, 7, 103, 2, 2, 132, 133, 7, 110, 2, 2, 133, 134, 7, 102, 2, 2, 134, 12, 3, 2, 2, 2, 135, 136, 7, 117, 2, 2, 136, 137, 7, 118, 2, 2, 137, 138, 7, 99, 2, 2, 138, 139, 7, 118, 2, 2, 139, 140, 7, 107, 2, 2, 140, 141, 7, 101, 2, 2, 141, 14, 3, 2, 2, 2, 142, 143, 7, 120, 2, 2, 143, 144, 7, 99, 2, 2, 144, 145, 7, 116, 2, 2, 145, 16, 3, 2, 2, 2, 146, 147, 7, 107, 2, 2, 147, 148, 7, 112, 2, 2, 148, 149, 7, 118, 2, 2, 149, 18, 3, 2, 2, 2, 150, 151, 7, 101, 2, 2, 151, 152, 7, 106, 2, 2, 152, 153, 7, 99, 2, 2, 153, 154, 7, 116, 2, 2, 154, 20, 3, 2, 2, 2, 155, 156, 7, 100, 2, 2, 156, 157, 7, 113, 2, 2, 157, 158, 7, 113, 2, 2, 158, 159, 7, 110, 2, 2, 159, 160, 7, 103, 2, 2, 160, 161, 7, 99, 2, 2, 161, 162, 7, 112, 2, 2, 162, 22, 3, 2, 2, 2, 163, 164, 7, 120, 2, 2, 164, 165, 7, 113, 2, 2, 165, 166, 7, 107, 2, 2, 166, 167, 7, 102, 2, 2, 167, 24, 3, 2, 2, 2, 168, 169, 7, 110, 2, 2, 169, 170, 7, 103, 2, 2, 170, 171, 7, 118, 2, 2, 171, 26, 3, 2, 2, 2, 172, 173, 7, 102, 2, 2, 173, 174, 7, 113, 2, 2, 174, 28, 3, 2, 2, 2, 175, 176, 7, 107, 2, 2, 176, 177, 7, 104, 2, 2, 177, 30, 3, 2, 2, 2, 178, 179, 7, 103, 2, 2, 179, 180, 7, 110, 2, 2, 180, 181, 7, 117, 2, 2, 181, 182, 7, 103, 2, 2, 182, 32, 3, 2, 2, 2, 183, 184, 7, 121, 2, 2, 184, 185, 7, 106, 2, 2, 185, 186, 7, 107, 2, 2, 186, 187, 7, 110, 2, 2, 187, 188, 7, 103, 2, 2, 188, 34, 3, 2, 2, 2, 189, 190, 7, 116, 2, 2, 190, 191, 7, 103, 2, 2, 191, 192, 7, 118, 2, 2, 192, 193, 7, 119, 2, 2, 193, 194, 7, 116, 2, 2, 194, 195, 7, 112, 2, 2, 195, 36, 3, 2, 2, 2, 196, 197, 7, 125, 2, 2, 197, 38, 3, 2, 2, 2, 198, 199, 7, 127, 2, 2, 199, 40, 3, 2, 2, 2, 200, 201, 7, 42, 2, 2, 201, 42, 3, 2, 2, 2, 202, 203, 7, 43, 2, 2, 203, 44, 3, 2, 2, 2, 204, 205, 7, 93, 2, 2, 205, 46, 3, 2, 2, 2, 206, 207, 7, 95, 2, 2, 207, 48, 3, 2, 2, 2, 208, 209, 7, 48, 2, 2, 209, 50, 3, 2, 2, 2, 210, 211, 7, 46, 2, 2, 211, 52, 3, 2, 2, 2, 212, 213, 7, 61, 2, 2, 213, 54, 3, 2, 2, 2, 214, 215, 7, 63, 2, 2, 215, 56, 3, 2, 2, 2, 216, 217, 7, 45, 2, 2, 217, 58, 3, 2, 2, 2, 218, 219, 7, 47, 2, 2, 219, 60, 3, 2, 2, 2, 220, 221, 7, 44, 2, 2, 221, 62, 3, 2, 2, 2, 222, 223, 7, 49, 2, 2, 223, 64, 3, 2, 2, 2, 224, 225, 7, 40, 2, 2, 225, 66, 3, 2, 2, 2, 226, 227, 7, 126, 2, 2, 227, 68, 3, 2, 2, 2, 228, 229, 7, 128, 2, 2, 229, 70, 3, 2, 2, 2, 230, 231, 7, 62, 2, 2, 231, 72, 3, 2, 2, 2, 232, 233, 7, 64, 2, 2, 233, 74, 3, 2, 2, 2, 234, 236, 9, 2, 2, 2, 235, 234, 3, 2, 2, 2, 236, 237, 3, 2, 2, 2, 237, 235, 3, 2, 2, 2, 237, 238, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 240, 8, 38, 2, 2, 240, 76, 3, 2, 2, 2, 241, 242, 7, 49, 2, 2, 242, 243, 7, 44, 2, 2, 243, 247, 3, 2, 2, 2, 244, 246, 11, 2, 2, 2, 245, 244, 3, 2, 2, 2, 246, 249, 3, 2, 2, 2, 247, 248, 3, 2, 2, 2, 247, 245, 3, 2, 2, 2, 248, 250, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 250, 251, 7, 44, 2, 2, 251, 252, 7, 49, 2, 2, 252, 253, 3, 2, 2, 2, 253, 254, 8, 39, 2, 2, 254, 78, 3, 2, 2, 2, 255, 256, 7, 49, 2, 2, 256, 257, 7, 49, 2, 2, 257, 261, 3, 2, 2, 2, 258, 260, 10, 3, 2, 2, 259, 258, 3, 2, 2, 2, 260, 263, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 261, 262, 3, 2, 2, 2, 262, 264, 3, 2, 2, 2, 263, 261, 3, 2, 2, 2, 264, 265, 8, 40, 2, 2, 265, 80, 3, 2, 2, 2, 266, 268, 9, 4, 2, 2, 267, 266, 3, 2, 2, 2, 268, 269, 3, 2, 2, 2, 269, 267, 3, 2, 2, 2, 269, 270, 3, 2, 2, 2, 270, 82, 3, 2, 2, 2, 271, 272, 7, 118, 2, 2, 272, 273, 7, 116, 2, 2, 273, 274, 7, 119, 2, 2, 274, 281, 7, 103, 2, 2, 275, 276, 7, 104, 2, 2, 276, 277, 7, 99, 2, 2, 277, 278, 7, 110, 2, 2, 278, 279, 7, 117, 2, 2, 279, 281, 7, 103, 2, 2, 280, 271, 3, 2, 2, 2, 280, 275, 3, 2, 2, 2, 281, 84, 3, 2, 2, 2, 282, 283, 7, 112, 2, 2, 283, 284, 7, 119, 2, 2, 284, 285, 7, 110, 2, 2, 285, 286, 7, 110, 2, 2, 286, 86, 3, 2, 2, 2, 287, 288, 7, 118, 2, 2, 288, 289, 7, 106, 2, 2, 289, 290, 7, 107, 2, 2, 290, 291, 7, 117, 2, 2, 291, 88, 3, 2, 2, 2, 292, 296, 9, 5, 2, 2, 293, 295, 9, 6, 2, 2, 294, 293, 3, 2, 2, 2, 295, 298, 3, 2, 2, 2, 296, 294, 3, 2, 2, 2, 296, 297, 3, 2, 2, 2, 297, 90, 3, 2, 2, 2, 298, 296, 3, 2, 2, 2, 299, 300, 5, 93, 47, 2, 300, 301, 7, 36, 2, 2, 301, 92, 3, 2, 2, 2, 302, 306, 7, 36, 2, 2, 303, 305, 10, 7, 2, 2, 304, 303, 3, 2, 2, 2, 305, 308, 3, 2, 2, 2, 306, 304, 3, 2, 2, 2, 306, 307, 3, 2, 2, 2, 307, 94, 3, 2, 2, 2, 308, 306, 3, 2, 2, 2, 10, 2, 237, 247, 261, 269, 280, 296, 306, 3, 8, 2, 2] \ No newline at end of file diff --git a/compiler/src/generated/JackLexer.tokens b/compiler/src/generated/JackLexer.tokens new file mode 100644 index 00000000..8292b05c --- /dev/null +++ b/compiler/src/generated/JackLexer.tokens @@ -0,0 +1,84 @@ +CLASS=1 +CONSTRUCTOR=2 +FUNCTION=3 +METHOD=4 +FIELD=5 +STATIC=6 +VAR=7 +INT=8 +CHAR=9 +BOOLEAN=10 +VOID=11 +LET=12 +DO=13 +IF=14 +ELSE=15 +WHILE=16 +RETURN=17 +LBRACE=18 +RBRACE=19 +LPAREN=20 +RPAREN=21 +LBRACKET=22 +RBRACKET=23 +DOT=24 +COMMA=25 +SEMICOLON=26 +EQUALS=27 +PLUS=28 +MINUS=29 +MUL=30 +DIV=31 +AND=32 +OR=33 +TILDE=34 +LESS_THAN=35 +GREATER_THAN=36 +WS=37 +COMMENT=38 +LINE_COMMENT=39 +INTEGER_LITERAL=40 +BOOLEAN_LITERAL=41 +NULL_LITERAL=42 +THIS_LITERAL=43 +IDENTIFIER=44 +STRING_LITERAL=45 +UnterminatedStringLiteral=46 +'class'=1 +'constructor'=2 +'function'=3 +'method'=4 +'field'=5 +'static'=6 +'var'=7 +'int'=8 +'char'=9 +'boolean'=10 +'void'=11 +'let'=12 +'do'=13 +'if'=14 +'else'=15 +'while'=16 +'return'=17 +'{'=18 +'}'=19 +'('=20 +')'=21 +'['=22 +']'=23 +'.'=24 +','=25 +';'=26 +'='=27 +'+'=28 +'-'=29 +'*'=30 +'/'=31 +'&'=32 +'|'=33 +'~'=34 +'<'=35 +'>'=36 +'null'=42 +'this'=43 diff --git a/compiler/src/generated/JackLexer.ts b/compiler/src/generated/JackLexer.ts new file mode 100644 index 00000000..65243b37 --- /dev/null +++ b/compiler/src/generated/JackLexer.ts @@ -0,0 +1,278 @@ +// Generated from JackLexer.g4 by ANTLR 4.9.0-SNAPSHOT + + +import { ATN } from "antlr4ts/atn/ATN"; +import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; +import { CharStream } from "antlr4ts/CharStream"; +import { Lexer } from "antlr4ts/Lexer"; +import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator"; +import { NotNull } from "antlr4ts/Decorators"; +import { Override } from "antlr4ts/Decorators"; +import { RuleContext } from "antlr4ts/RuleContext"; +import { Vocabulary } from "antlr4ts/Vocabulary"; +import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; + +import * as Utils from "antlr4ts/misc/Utils"; + + +export class JackLexer extends Lexer { + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WS = 37; + public static readonly COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly BOOLEAN_LITERAL = 41; + public static readonly NULL_LITERAL = 42; + public static readonly THIS_LITERAL = 43; + public static readonly IDENTIFIER = 44; + public static readonly STRING_LITERAL = 45; + public static readonly UnterminatedStringLiteral = 46; + + // tslint:disable:no-trailing-whitespace + public static readonly channelNames: string[] = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN", + ]; + + // tslint:disable:no-trailing-whitespace + public static readonly modeNames: string[] = [ + "DEFAULT_MODE", + ]; + + public static readonly ruleNames: string[] = [ + "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", "VAR", + "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", + "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", + "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", + "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", + "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", + "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral", + ]; + + private static readonly _LITERAL_NAMES: Array = [ + undefined, "'class'", "'constructor'", "'function'", "'method'", "'field'", + "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", + "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", + "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", + "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", undefined, undefined, undefined, + undefined, undefined, "'null'", "'this'", + ]; + private static readonly _SYMBOLIC_NAMES: Array = [ + undefined, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", + "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", + "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", + "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", + "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", + "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", + "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral", + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(JackLexer._LITERAL_NAMES, JackLexer._SYMBOLIC_NAMES, []); + + // @Override + // @NotNull + public get vocabulary(): Vocabulary { + return JackLexer.VOCABULARY; + } + // tslint:enable:no-trailing-whitespace + + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(JackLexer._ATN, this); + } + + // @Override + public get grammarFileName(): string { return "JackLexer.g4"; } + + // @Override + public get ruleNames(): string[] { return JackLexer.ruleNames; } + + // @Override + public override get serializedATN(): string { return JackLexer._serializedATN; } + + // @Override + public get channelNames(): string[] { return JackLexer.channelNames; } + + // @Override + public get modeNames(): string[] { return JackLexer.modeNames; } + + public static readonly _serializedATN: string = + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x020\u0135\b\x01" + + "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + + "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + + "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + + "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + + "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + + "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t" + + "\"\x04#\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x04)\t)\x04*\t*\x04" + + "+\t+\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x03\x02\x03\x02\x03\x02\x03\x02\x03" + + "\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" + + "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03" + + "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03" + + "\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\b\x03\b\x03\b" + + "\x03\b\x03\t\x03\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03" + + "\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03\f\x03\f\x03\f\x03" + + "\r\x03\r\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03" + + "\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03" + + "\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03" + + "\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16\x03\x17\x03" + + "\x17\x03\x18\x03\x18\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + + "\x1C\x03\x1C\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03 \x03" + + " \x03!\x03!\x03\"\x03\"\x03#\x03#\x03$\x03$\x03%\x03%\x03&\x06&\xEC\n" + + "&\r&\x0E&\xED\x03&\x03&\x03\'\x03\'\x03\'\x03\'\x07\'\xF6\n\'\f\'\x0E" + + "\'\xF9\v\'\x03\'\x03\'\x03\'\x03\'\x03\'\x03(\x03(\x03(\x03(\x07(\u0104" + + "\n(\f(\x0E(\u0107\v(\x03(\x03(\x03)\x06)\u010C\n)\r)\x0E)\u010D\x03*\x03" + + "*\x03*\x03*\x03*\x03*\x03*\x03*\x03*\x05*\u0119\n*\x03+\x03+\x03+\x03" + + "+\x03+\x03,\x03,\x03,\x03,\x03,\x03-\x03-\x07-\u0127\n-\f-\x0E-\u012A" + + "\v-\x03.\x03.\x03.\x03/\x03/\x07/\u0131\n/\f/\x0E/\u0134\v/\x03\xF7\x02" + + "\x020\x03\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b" + + "\x0F\x02\t\x11\x02\n\x13\x02\v\x15\x02\f\x17\x02\r\x19\x02\x0E\x1B\x02" + + "\x0F\x1D\x02\x10\x1F\x02\x11!\x02\x12#\x02\x13%\x02\x14\'\x02\x15)\x02" + + "\x16+\x02\x17-\x02\x18/\x02\x191\x02\x1A3\x02\x1B5\x02\x1C7\x02\x1D9\x02" + + "\x1E;\x02\x1F=\x02 ?\x02!A\x02\"C\x02#E\x02$G\x02%I\x02&K\x02\'M\x02(" + + "O\x02)Q\x02*S\x02+U\x02,W\x02-Y\x02.[\x02/]\x020\x03\x02\b\x05\x02\v\f" + + "\x0F\x0F\"\"\x04\x02\f\f\x0F\x0F\x03\x022;\x05\x02C\\aac|\x06\x022;C\\" + + "aac|\x06\x02\f\f\x0F\x0F$$^^\x02\u013B\x02\x03\x03\x02\x02\x02\x02\x05" + + "\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02\x02\v\x03" + + "\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02\x11\x03" + + "\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x15\x03\x02\x02\x02\x02\x17\x03" + + "\x02\x02\x02\x02\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03" + + "\x02\x02\x02\x02\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02" + + "\x02\x02\x02%\x03\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02" + + "\x02+\x03\x02\x02\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03" + + "\x02\x02\x02\x023\x03\x02\x02\x02\x025\x03\x02\x02\x02\x027\x03\x02\x02" + + "\x02\x029\x03\x02\x02\x02\x02;\x03\x02\x02\x02\x02=\x03\x02\x02\x02\x02" + + "?\x03\x02\x02\x02\x02A\x03\x02\x02\x02\x02C\x03\x02\x02\x02\x02E\x03\x02" + + "\x02\x02\x02G\x03\x02\x02\x02\x02I\x03\x02\x02\x02\x02K\x03\x02\x02\x02" + + "\x02M\x03\x02\x02\x02\x02O\x03\x02\x02\x02\x02Q\x03\x02\x02\x02\x02S\x03" + + "\x02\x02\x02\x02U\x03\x02\x02\x02\x02W\x03\x02\x02\x02\x02Y\x03\x02\x02" + + "\x02\x02[\x03\x02\x02\x02\x02]\x03\x02\x02\x02\x03_\x03\x02\x02\x02\x05" + + "e\x03\x02\x02\x02\x07q\x03\x02\x02\x02\tz\x03\x02\x02\x02\v\x81\x03\x02" + + "\x02\x02\r\x87\x03\x02\x02\x02\x0F\x8E\x03\x02\x02\x02\x11\x92\x03\x02" + + "\x02\x02\x13\x96\x03\x02\x02\x02\x15\x9B\x03\x02\x02\x02\x17\xA3\x03\x02" + + "\x02\x02\x19\xA8\x03\x02\x02\x02\x1B\xAC\x03\x02\x02\x02\x1D\xAF\x03\x02" + + "\x02\x02\x1F\xB2\x03\x02\x02\x02!\xB7\x03\x02\x02\x02#\xBD\x03\x02\x02" + + "\x02%\xC4\x03\x02\x02\x02\'\xC6\x03\x02\x02\x02)\xC8\x03\x02\x02\x02+" + + "\xCA\x03\x02\x02\x02-\xCC\x03\x02\x02\x02/\xCE\x03\x02\x02\x021\xD0\x03" + + "\x02\x02\x023\xD2\x03\x02\x02\x025\xD4\x03\x02\x02\x027\xD6\x03\x02\x02" + + "\x029\xD8\x03\x02\x02\x02;\xDA\x03\x02\x02\x02=\xDC\x03\x02\x02\x02?\xDE" + + "\x03\x02\x02\x02A\xE0\x03\x02\x02\x02C\xE2\x03\x02\x02\x02E\xE4\x03\x02" + + "\x02\x02G\xE6\x03\x02\x02\x02I\xE8\x03\x02\x02\x02K\xEB\x03\x02\x02\x02" + + "M\xF1\x03\x02\x02\x02O\xFF\x03\x02\x02\x02Q\u010B\x03\x02\x02\x02S\u0118" + + "\x03\x02\x02\x02U\u011A\x03\x02\x02\x02W\u011F\x03\x02\x02\x02Y\u0124" + + "\x03\x02\x02\x02[\u012B\x03\x02\x02\x02]\u012E\x03\x02\x02\x02_`\x07e" + + "\x02\x02`a\x07n\x02\x02ab\x07c\x02\x02bc\x07u\x02\x02cd\x07u\x02\x02d" + + "\x04\x03\x02\x02\x02ef\x07e\x02\x02fg\x07q\x02\x02gh\x07p\x02\x02hi\x07" + + "u\x02\x02ij\x07v\x02\x02jk\x07t\x02\x02kl\x07w\x02\x02lm\x07e\x02\x02" + + "mn\x07v\x02\x02no\x07q\x02\x02op\x07t\x02\x02p\x06\x03\x02\x02\x02qr\x07" + + "h\x02\x02rs\x07w\x02\x02st\x07p\x02\x02tu\x07e\x02\x02uv\x07v\x02\x02" + + "vw\x07k\x02\x02wx\x07q\x02\x02xy\x07p\x02\x02y\b\x03\x02\x02\x02z{\x07" + + "o\x02\x02{|\x07g\x02\x02|}\x07v\x02\x02}~\x07j\x02\x02~\x7F\x07q\x02\x02" + + "\x7F\x80\x07f\x02\x02\x80\n\x03\x02\x02\x02\x81\x82\x07h\x02\x02\x82\x83" + + "\x07k\x02\x02\x83\x84\x07g\x02\x02\x84\x85\x07n\x02\x02\x85\x86\x07f\x02" + + "\x02\x86\f\x03\x02\x02\x02\x87\x88\x07u\x02\x02\x88\x89\x07v\x02\x02\x89" + + "\x8A\x07c\x02\x02\x8A\x8B\x07v\x02\x02\x8B\x8C\x07k\x02\x02\x8C\x8D\x07" + + "e\x02\x02\x8D\x0E\x03\x02\x02\x02\x8E\x8F\x07x\x02\x02\x8F\x90\x07c\x02" + + "\x02\x90\x91\x07t\x02\x02\x91\x10\x03\x02\x02\x02\x92\x93\x07k\x02\x02" + + "\x93\x94\x07p\x02\x02\x94\x95\x07v\x02\x02\x95\x12\x03\x02\x02\x02\x96" + + "\x97\x07e\x02\x02\x97\x98\x07j\x02\x02\x98\x99\x07c\x02\x02\x99\x9A\x07" + + "t\x02\x02\x9A\x14\x03\x02\x02\x02\x9B\x9C\x07d\x02\x02\x9C\x9D\x07q\x02" + + "\x02\x9D\x9E\x07q\x02\x02\x9E\x9F\x07n\x02\x02\x9F\xA0\x07g\x02\x02\xA0" + + "\xA1\x07c\x02\x02\xA1\xA2\x07p\x02\x02\xA2\x16\x03\x02\x02\x02\xA3\xA4" + + "\x07x\x02\x02\xA4\xA5\x07q\x02\x02\xA5\xA6\x07k\x02\x02\xA6\xA7\x07f\x02" + + "\x02\xA7\x18\x03\x02\x02\x02\xA8\xA9\x07n\x02\x02\xA9\xAA\x07g\x02\x02" + + "\xAA\xAB\x07v\x02\x02\xAB\x1A\x03\x02\x02\x02\xAC\xAD\x07f\x02\x02\xAD" + + "\xAE\x07q\x02\x02\xAE\x1C\x03\x02\x02\x02\xAF\xB0\x07k\x02\x02\xB0\xB1" + + "\x07h\x02\x02\xB1\x1E\x03\x02\x02\x02\xB2\xB3\x07g\x02\x02\xB3\xB4\x07" + + "n\x02\x02\xB4\xB5\x07u\x02\x02\xB5\xB6\x07g\x02\x02\xB6 \x03\x02\x02\x02" + + "\xB7\xB8\x07y\x02\x02\xB8\xB9\x07j\x02\x02\xB9\xBA\x07k\x02\x02\xBA\xBB" + + "\x07n\x02\x02\xBB\xBC\x07g\x02\x02\xBC\"\x03\x02\x02\x02\xBD\xBE\x07t" + + "\x02\x02\xBE\xBF\x07g\x02\x02\xBF\xC0\x07v\x02\x02\xC0\xC1\x07w\x02\x02" + + "\xC1\xC2\x07t\x02\x02\xC2\xC3\x07p\x02\x02\xC3$\x03\x02\x02\x02\xC4\xC5" + + "\x07}\x02\x02\xC5&\x03\x02\x02\x02\xC6\xC7\x07\x7F\x02\x02\xC7(\x03\x02" + + "\x02\x02\xC8\xC9\x07*\x02\x02\xC9*\x03\x02\x02\x02\xCA\xCB\x07+\x02\x02" + + "\xCB,\x03\x02\x02\x02\xCC\xCD\x07]\x02\x02\xCD.\x03\x02\x02\x02\xCE\xCF" + + "\x07_\x02\x02\xCF0\x03\x02\x02\x02\xD0\xD1\x070\x02\x02\xD12\x03\x02\x02" + + "\x02\xD2\xD3\x07.\x02\x02\xD34\x03\x02\x02\x02\xD4\xD5\x07=\x02\x02\xD5" + + "6\x03\x02\x02\x02\xD6\xD7\x07?\x02\x02\xD78\x03\x02\x02\x02\xD8\xD9\x07" + + "-\x02\x02\xD9:\x03\x02\x02\x02\xDA\xDB\x07/\x02\x02\xDB<\x03\x02\x02\x02" + + "\xDC\xDD\x07,\x02\x02\xDD>\x03\x02\x02\x02\xDE\xDF\x071\x02\x02\xDF@\x03" + + "\x02\x02\x02\xE0\xE1\x07(\x02\x02\xE1B\x03\x02\x02\x02\xE2\xE3\x07~\x02" + + "\x02\xE3D\x03\x02\x02\x02\xE4\xE5\x07\x80\x02\x02\xE5F\x03\x02\x02\x02" + + "\xE6\xE7\x07>\x02\x02\xE7H\x03\x02\x02\x02\xE8\xE9\x07@\x02\x02\xE9J\x03" + + "\x02\x02\x02\xEA\xEC\t\x02\x02\x02\xEB\xEA\x03\x02\x02\x02\xEC\xED\x03" + + "\x02\x02\x02\xED\xEB\x03\x02\x02\x02\xED\xEE\x03\x02\x02\x02\xEE\xEF\x03" + + "\x02\x02\x02\xEF\xF0\b&\x02\x02\xF0L\x03\x02\x02\x02\xF1\xF2\x071\x02" + + "\x02\xF2\xF3\x07,\x02\x02\xF3\xF7\x03\x02\x02\x02\xF4\xF6\v\x02\x02\x02" + + "\xF5\xF4\x03\x02\x02\x02\xF6\xF9\x03\x02\x02\x02\xF7\xF8\x03\x02\x02\x02" + + "\xF7\xF5\x03\x02\x02\x02\xF8\xFA\x03\x02\x02\x02\xF9\xF7\x03\x02\x02\x02" + + "\xFA\xFB\x07,\x02\x02\xFB\xFC\x071\x02\x02\xFC\xFD\x03\x02\x02\x02\xFD" + + "\xFE\b\'\x02\x02\xFEN\x03\x02\x02\x02\xFF\u0100\x071\x02\x02\u0100\u0101" + + "\x071\x02\x02\u0101\u0105\x03\x02\x02\x02\u0102\u0104\n\x03\x02\x02\u0103" + + "\u0102\x03\x02\x02\x02\u0104\u0107\x03\x02\x02\x02\u0105\u0103\x03\x02" + + "\x02\x02\u0105\u0106\x03\x02\x02\x02\u0106\u0108\x03\x02\x02\x02\u0107" + + "\u0105\x03\x02\x02\x02\u0108\u0109\b(\x02\x02\u0109P\x03\x02\x02\x02\u010A" + + "\u010C\t\x04\x02\x02\u010B\u010A\x03\x02\x02\x02\u010C\u010D\x03\x02\x02" + + "\x02\u010D\u010B\x03\x02\x02\x02\u010D\u010E\x03\x02\x02\x02\u010ER\x03" + + "\x02\x02\x02\u010F\u0110\x07v\x02\x02\u0110\u0111\x07t\x02\x02\u0111\u0112" + + "\x07w\x02\x02\u0112\u0119\x07g\x02\x02\u0113\u0114\x07h\x02\x02\u0114" + + "\u0115\x07c\x02\x02\u0115\u0116\x07n\x02\x02\u0116\u0117\x07u\x02\x02" + + "\u0117\u0119\x07g\x02\x02\u0118\u010F\x03\x02\x02\x02\u0118\u0113\x03" + + "\x02\x02\x02\u0119T\x03\x02\x02\x02\u011A\u011B\x07p\x02\x02\u011B\u011C" + + "\x07w\x02\x02\u011C\u011D\x07n\x02\x02\u011D\u011E\x07n\x02\x02\u011E" + + "V\x03\x02\x02\x02\u011F\u0120\x07v\x02\x02\u0120\u0121\x07j\x02\x02\u0121" + + "\u0122\x07k\x02\x02\u0122\u0123\x07u\x02\x02\u0123X\x03\x02\x02\x02\u0124" + + "\u0128\t\x05\x02\x02\u0125\u0127\t\x06\x02\x02\u0126\u0125\x03\x02\x02" + + "\x02\u0127\u012A\x03\x02\x02\x02\u0128\u0126\x03\x02\x02\x02\u0128\u0129" + + "\x03\x02\x02\x02\u0129Z\x03\x02\x02\x02\u012A\u0128\x03\x02\x02\x02\u012B" + + "\u012C\x05]/\x02\u012C\u012D\x07$\x02\x02\u012D\\\x03\x02\x02\x02\u012E" + + "\u0132\x07$\x02\x02\u012F\u0131\n\x07\x02\x02\u0130\u012F\x03\x02\x02" + + "\x02\u0131\u0134\x03\x02\x02\x02\u0132\u0130\x03\x02\x02\x02\u0132\u0133" + + "\x03\x02\x02\x02\u0133^\x03\x02\x02\x02\u0134\u0132\x03\x02\x02\x02\n" + + "\x02\xED\xF7\u0105\u010D\u0118\u0128\u0132\x03\b\x02\x02"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!JackLexer.__ATN) { + JackLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(JackLexer._serializedATN)); + } + + return JackLexer.__ATN; + } + +} + diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp new file mode 100644 index 00000000..9df49bb4 --- /dev/null +++ b/compiler/src/generated/JackParser.interp @@ -0,0 +1,136 @@ +token literal names: +null +'class' +'constructor' +'function' +'method' +'field' +'static' +'var' +'int' +'char' +'boolean' +'void' +'let' +'do' +'if' +'else' +'while' +'return' +'{' +'}' +'(' +')' +'[' +']' +'.' +',' +';' +'=' +'+' +'-' +'*' +'/' +'&' +'|' +'~' +'<' +'>' +null +null +null +null +null +'null' +'this' +null +null +null + +token symbolic names: +null +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +BOOLEAN_LITERAL +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +rule names: +program +classDeclaration +className +classVarDec +fieldList +fieldName +subroutineDec +subroutineDecWithoutType +subroutineName +subroutineReturnType +varType +parameterList +parameter +parameterName +subroutineBody +varDec +varName +statements +statement +letStatement +ifStatement +whileStatement +doStatement +subroutineCall +returnStatement +expressionList +expression +groupedExpression +unaryOp +arrayAccess +constant +unaryOperator +binaryOperator + + +atn: +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 289, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 76, 10, 3, 12, 3, 14, 3, 79, 11, 3, 3, 3, 7, 3, 82, 10, 3, 12, 3, 14, 3, 85, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 99, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 105, 10, 6, 12, 6, 14, 6, 108, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 119, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 132, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 139, 10, 13, 12, 13, 14, 13, 142, 11, 13, 5, 13, 144, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 153, 10, 16, 12, 16, 14, 16, 156, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 166, 10, 17, 12, 17, 14, 17, 169, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 7, 19, 176, 10, 19, 12, 19, 14, 19, 179, 11, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 186, 10, 20, 3, 21, 3, 21, 3, 21, 5, 21, 191, 10, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 209, 10, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 5, 25, 235, 10, 25, 3, 26, 3, 26, 5, 26, 239, 10, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 7, 27, 246, 10, 27, 12, 27, 14, 27, 249, 11, 27, 5, 27, 251, 10, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 260, 10, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 266, 10, 28, 12, 28, 14, 28, 269, 11, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 2, 2, 3, 54, 35, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 2, 7, 4, 2, 10, 12, 46, 46, 3, 2, 45, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 283, 2, 68, 3, 2, 2, 2, 4, 71, 3, 2, 2, 2, 6, 88, 3, 2, 2, 2, 8, 98, 3, 2, 2, 2, 10, 100, 3, 2, 2, 2, 12, 109, 3, 2, 2, 2, 14, 118, 3, 2, 2, 2, 16, 120, 3, 2, 2, 2, 18, 127, 3, 2, 2, 2, 20, 131, 3, 2, 2, 2, 22, 133, 3, 2, 2, 2, 24, 143, 3, 2, 2, 2, 26, 145, 3, 2, 2, 2, 28, 148, 3, 2, 2, 2, 30, 150, 3, 2, 2, 2, 32, 160, 3, 2, 2, 2, 34, 172, 3, 2, 2, 2, 36, 177, 3, 2, 2, 2, 38, 185, 3, 2, 2, 2, 40, 187, 3, 2, 2, 2, 42, 196, 3, 2, 2, 2, 44, 210, 3, 2, 2, 2, 46, 218, 3, 2, 2, 2, 48, 234, 3, 2, 2, 2, 50, 236, 3, 2, 2, 2, 52, 250, 3, 2, 2, 2, 54, 259, 3, 2, 2, 2, 56, 270, 3, 2, 2, 2, 58, 274, 3, 2, 2, 2, 60, 277, 3, 2, 2, 2, 62, 282, 3, 2, 2, 2, 64, 284, 3, 2, 2, 2, 66, 286, 3, 2, 2, 2, 68, 69, 5, 4, 3, 2, 69, 70, 7, 2, 2, 3, 70, 3, 3, 2, 2, 2, 71, 72, 7, 3, 2, 2, 72, 73, 5, 6, 4, 2, 73, 77, 7, 20, 2, 2, 74, 76, 5, 8, 5, 2, 75, 74, 3, 2, 2, 2, 76, 79, 3, 2, 2, 2, 77, 75, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 83, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 80, 82, 5, 14, 8, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 86, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 87, 7, 21, 2, 2, 87, 5, 3, 2, 2, 2, 88, 89, 7, 46, 2, 2, 89, 7, 3, 2, 2, 2, 90, 91, 7, 8, 2, 2, 91, 92, 5, 10, 6, 2, 92, 93, 7, 28, 2, 2, 93, 99, 3, 2, 2, 2, 94, 95, 7, 7, 2, 2, 95, 96, 5, 10, 6, 2, 96, 97, 7, 28, 2, 2, 97, 99, 3, 2, 2, 2, 98, 90, 3, 2, 2, 2, 98, 94, 3, 2, 2, 2, 99, 9, 3, 2, 2, 2, 100, 101, 5, 22, 12, 2, 101, 106, 5, 12, 7, 2, 102, 103, 7, 27, 2, 2, 103, 105, 5, 12, 7, 2, 104, 102, 3, 2, 2, 2, 105, 108, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 106, 107, 3, 2, 2, 2, 107, 11, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 109, 110, 7, 46, 2, 2, 110, 13, 3, 2, 2, 2, 111, 112, 8, 8, 1, 2, 112, 113, 7, 4, 2, 2, 113, 119, 5, 16, 9, 2, 114, 115, 7, 6, 2, 2, 115, 119, 5, 16, 9, 2, 116, 117, 7, 5, 2, 2, 117, 119, 5, 16, 9, 2, 118, 111, 3, 2, 2, 2, 118, 114, 3, 2, 2, 2, 118, 116, 3, 2, 2, 2, 119, 15, 3, 2, 2, 2, 120, 121, 5, 20, 11, 2, 121, 122, 5, 18, 10, 2, 122, 123, 7, 22, 2, 2, 123, 124, 5, 24, 13, 2, 124, 125, 7, 23, 2, 2, 125, 126, 5, 30, 16, 2, 126, 17, 3, 2, 2, 2, 127, 128, 7, 46, 2, 2, 128, 19, 3, 2, 2, 2, 129, 132, 5, 22, 12, 2, 130, 132, 7, 13, 2, 2, 131, 129, 3, 2, 2, 2, 131, 130, 3, 2, 2, 2, 132, 21, 3, 2, 2, 2, 133, 134, 9, 2, 2, 2, 134, 23, 3, 2, 2, 2, 135, 140, 5, 26, 14, 2, 136, 137, 7, 27, 2, 2, 137, 139, 5, 26, 14, 2, 138, 136, 3, 2, 2, 2, 139, 142, 3, 2, 2, 2, 140, 138, 3, 2, 2, 2, 140, 141, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 143, 135, 3, 2, 2, 2, 143, 144, 3, 2, 2, 2, 144, 25, 3, 2, 2, 2, 145, 146, 5, 22, 12, 2, 146, 147, 5, 28, 15, 2, 147, 27, 3, 2, 2, 2, 148, 149, 7, 46, 2, 2, 149, 29, 3, 2, 2, 2, 150, 154, 7, 20, 2, 2, 151, 153, 5, 32, 17, 2, 152, 151, 3, 2, 2, 2, 153, 156, 3, 2, 2, 2, 154, 152, 3, 2, 2, 2, 154, 155, 3, 2, 2, 2, 155, 157, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 157, 158, 5, 36, 19, 2, 158, 159, 7, 21, 2, 2, 159, 31, 3, 2, 2, 2, 160, 161, 7, 9, 2, 2, 161, 162, 5, 22, 12, 2, 162, 167, 5, 34, 18, 2, 163, 164, 7, 27, 2, 2, 164, 166, 7, 46, 2, 2, 165, 163, 3, 2, 2, 2, 166, 169, 3, 2, 2, 2, 167, 165, 3, 2, 2, 2, 167, 168, 3, 2, 2, 2, 168, 170, 3, 2, 2, 2, 169, 167, 3, 2, 2, 2, 170, 171, 7, 28, 2, 2, 171, 33, 3, 2, 2, 2, 172, 173, 7, 46, 2, 2, 173, 35, 3, 2, 2, 2, 174, 176, 5, 38, 20, 2, 175, 174, 3, 2, 2, 2, 176, 179, 3, 2, 2, 2, 177, 175, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2, 178, 37, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 180, 186, 5, 40, 21, 2, 181, 186, 5, 42, 22, 2, 182, 186, 5, 44, 23, 2, 183, 186, 5, 46, 24, 2, 184, 186, 5, 50, 26, 2, 185, 180, 3, 2, 2, 2, 185, 181, 3, 2, 2, 2, 185, 182, 3, 2, 2, 2, 185, 183, 3, 2, 2, 2, 185, 184, 3, 2, 2, 2, 186, 39, 3, 2, 2, 2, 187, 190, 7, 14, 2, 2, 188, 191, 7, 46, 2, 2, 189, 191, 5, 60, 31, 2, 190, 188, 3, 2, 2, 2, 190, 189, 3, 2, 2, 2, 191, 192, 3, 2, 2, 2, 192, 193, 7, 29, 2, 2, 193, 194, 5, 54, 28, 2, 194, 195, 7, 28, 2, 2, 195, 41, 3, 2, 2, 2, 196, 197, 7, 16, 2, 2, 197, 198, 7, 22, 2, 2, 198, 199, 5, 54, 28, 2, 199, 200, 7, 23, 2, 2, 200, 201, 7, 20, 2, 2, 201, 202, 5, 36, 19, 2, 202, 208, 7, 21, 2, 2, 203, 204, 7, 17, 2, 2, 204, 205, 7, 20, 2, 2, 205, 206, 5, 36, 19, 2, 206, 207, 7, 21, 2, 2, 207, 209, 3, 2, 2, 2, 208, 203, 3, 2, 2, 2, 208, 209, 3, 2, 2, 2, 209, 43, 3, 2, 2, 2, 210, 211, 7, 18, 2, 2, 211, 212, 7, 22, 2, 2, 212, 213, 5, 54, 28, 2, 213, 214, 7, 23, 2, 2, 214, 215, 7, 20, 2, 2, 215, 216, 5, 36, 19, 2, 216, 217, 7, 21, 2, 2, 217, 45, 3, 2, 2, 2, 218, 219, 7, 15, 2, 2, 219, 220, 5, 48, 25, 2, 220, 221, 7, 28, 2, 2, 221, 47, 3, 2, 2, 2, 222, 223, 7, 46, 2, 2, 223, 224, 7, 22, 2, 2, 224, 225, 5, 52, 27, 2, 225, 226, 7, 23, 2, 2, 226, 235, 3, 2, 2, 2, 227, 228, 9, 3, 2, 2, 228, 229, 7, 26, 2, 2, 229, 230, 7, 46, 2, 2, 230, 231, 7, 22, 2, 2, 231, 232, 5, 52, 27, 2, 232, 233, 7, 23, 2, 2, 233, 235, 3, 2, 2, 2, 234, 222, 3, 2, 2, 2, 234, 227, 3, 2, 2, 2, 235, 49, 3, 2, 2, 2, 236, 238, 7, 19, 2, 2, 237, 239, 5, 54, 28, 2, 238, 237, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 241, 7, 28, 2, 2, 241, 51, 3, 2, 2, 2, 242, 247, 5, 54, 28, 2, 243, 244, 7, 27, 2, 2, 244, 246, 5, 54, 28, 2, 245, 243, 3, 2, 2, 2, 246, 249, 3, 2, 2, 2, 247, 245, 3, 2, 2, 2, 247, 248, 3, 2, 2, 2, 248, 251, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 250, 242, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 53, 3, 2, 2, 2, 252, 253, 8, 28, 1, 2, 253, 260, 5, 62, 32, 2, 254, 260, 7, 46, 2, 2, 255, 260, 5, 48, 25, 2, 256, 260, 5, 60, 31, 2, 257, 260, 5, 58, 30, 2, 258, 260, 5, 56, 29, 2, 259, 252, 3, 2, 2, 2, 259, 254, 3, 2, 2, 2, 259, 255, 3, 2, 2, 2, 259, 256, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 258, 3, 2, 2, 2, 260, 267, 3, 2, 2, 2, 261, 262, 12, 9, 2, 2, 262, 263, 5, 66, 34, 2, 263, 264, 5, 54, 28, 10, 264, 266, 3, 2, 2, 2, 265, 261, 3, 2, 2, 2, 266, 269, 3, 2, 2, 2, 267, 265, 3, 2, 2, 2, 267, 268, 3, 2, 2, 2, 268, 55, 3, 2, 2, 2, 269, 267, 3, 2, 2, 2, 270, 271, 7, 22, 2, 2, 271, 272, 5, 54, 28, 2, 272, 273, 7, 23, 2, 2, 273, 57, 3, 2, 2, 2, 274, 275, 5, 64, 33, 2, 275, 276, 5, 54, 28, 2, 276, 59, 3, 2, 2, 2, 277, 278, 7, 46, 2, 2, 278, 279, 7, 24, 2, 2, 279, 280, 5, 54, 28, 2, 280, 281, 7, 25, 2, 2, 281, 61, 3, 2, 2, 2, 282, 283, 9, 4, 2, 2, 283, 63, 3, 2, 2, 2, 284, 285, 9, 5, 2, 2, 285, 65, 3, 2, 2, 2, 286, 287, 9, 6, 2, 2, 287, 67, 3, 2, 2, 2, 22, 77, 83, 98, 106, 118, 131, 140, 143, 154, 167, 177, 185, 190, 208, 234, 238, 247, 250, 259, 267] \ No newline at end of file diff --git a/compiler/src/generated/JackParser.tokens b/compiler/src/generated/JackParser.tokens new file mode 100644 index 00000000..8292b05c --- /dev/null +++ b/compiler/src/generated/JackParser.tokens @@ -0,0 +1,84 @@ +CLASS=1 +CONSTRUCTOR=2 +FUNCTION=3 +METHOD=4 +FIELD=5 +STATIC=6 +VAR=7 +INT=8 +CHAR=9 +BOOLEAN=10 +VOID=11 +LET=12 +DO=13 +IF=14 +ELSE=15 +WHILE=16 +RETURN=17 +LBRACE=18 +RBRACE=19 +LPAREN=20 +RPAREN=21 +LBRACKET=22 +RBRACKET=23 +DOT=24 +COMMA=25 +SEMICOLON=26 +EQUALS=27 +PLUS=28 +MINUS=29 +MUL=30 +DIV=31 +AND=32 +OR=33 +TILDE=34 +LESS_THAN=35 +GREATER_THAN=36 +WS=37 +COMMENT=38 +LINE_COMMENT=39 +INTEGER_LITERAL=40 +BOOLEAN_LITERAL=41 +NULL_LITERAL=42 +THIS_LITERAL=43 +IDENTIFIER=44 +STRING_LITERAL=45 +UnterminatedStringLiteral=46 +'class'=1 +'constructor'=2 +'function'=3 +'method'=4 +'field'=5 +'static'=6 +'var'=7 +'int'=8 +'char'=9 +'boolean'=10 +'void'=11 +'let'=12 +'do'=13 +'if'=14 +'else'=15 +'while'=16 +'return'=17 +'{'=18 +'}'=19 +'('=20 +')'=21 +'['=22 +']'=23 +'.'=24 +','=25 +';'=26 +'='=27 +'+'=28 +'-'=29 +'*'=30 +'/'=31 +'&'=32 +'|'=33 +'~'=34 +'<'=35 +'>'=36 +'null'=42 +'this'=43 diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts new file mode 100644 index 00000000..4d61a407 --- /dev/null +++ b/compiler/src/generated/JackParser.ts @@ -0,0 +1,3088 @@ +// Generated from JackParser.g4 by ANTLR 4.9.0-SNAPSHOT + + +import { ATN } from "antlr4ts/atn/ATN"; +import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; +import { FailedPredicateException } from "antlr4ts/FailedPredicateException"; +import { NotNull } from "antlr4ts/Decorators"; +import { NoViableAltException } from "antlr4ts/NoViableAltException"; +import { Override } from "antlr4ts/Decorators"; +import { Parser } from "antlr4ts/Parser"; +import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; +import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator"; +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; +import { RecognitionException } from "antlr4ts/RecognitionException"; +import { RuleContext } from "antlr4ts/RuleContext"; +//import { RuleVersion } from "antlr4ts/RuleVersion"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { Token } from "antlr4ts/Token"; +import { TokenStream } from "antlr4ts/TokenStream"; +import { Vocabulary } from "antlr4ts/Vocabulary"; +import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; + +import * as Utils from "antlr4ts/misc/Utils"; + +import { JackParserListener } from "./JackParserListener"; +import { JackParserVisitor } from "./JackParserVisitor"; + + +export class JackParser extends Parser { + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WS = 37; + public static readonly COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly BOOLEAN_LITERAL = 41; + public static readonly NULL_LITERAL = 42; + public static readonly THIS_LITERAL = 43; + public static readonly IDENTIFIER = 44; + public static readonly STRING_LITERAL = 45; + public static readonly UnterminatedStringLiteral = 46; + public static readonly RULE_program = 0; + public static readonly RULE_classDeclaration = 1; + public static readonly RULE_className = 2; + public static readonly RULE_classVarDec = 3; + public static readonly RULE_fieldList = 4; + public static readonly RULE_fieldName = 5; + public static readonly RULE_subroutineDec = 6; + public static readonly RULE_subroutineDecWithoutType = 7; + public static readonly RULE_subroutineName = 8; + public static readonly RULE_subroutineReturnType = 9; + public static readonly RULE_varType = 10; + public static readonly RULE_parameterList = 11; + public static readonly RULE_parameter = 12; + public static readonly RULE_parameterName = 13; + public static readonly RULE_subroutineBody = 14; + public static readonly RULE_varDec = 15; + public static readonly RULE_varName = 16; + public static readonly RULE_statements = 17; + public static readonly RULE_statement = 18; + public static readonly RULE_letStatement = 19; + public static readonly RULE_ifStatement = 20; + public static readonly RULE_whileStatement = 21; + public static readonly RULE_doStatement = 22; + public static readonly RULE_subroutineCall = 23; + public static readonly RULE_returnStatement = 24; + public static readonly RULE_expressionList = 25; + public static readonly RULE_expression = 26; + public static readonly RULE_groupedExpression = 27; + public static readonly RULE_unaryOp = 28; + public static readonly RULE_arrayAccess = 29; + public static readonly RULE_constant = 30; + public static readonly RULE_unaryOperator = 31; + public static readonly RULE_binaryOperator = 32; + // tslint:disable:no-trailing-whitespace + public static readonly ruleNames: string[] = [ + "program", "classDeclaration", "className", "classVarDec", "fieldList", + "fieldName", "subroutineDec", "subroutineDecWithoutType", "subroutineName", + "subroutineReturnType", "varType", "parameterList", "parameter", "parameterName", + "subroutineBody", "varDec", "varName", "statements", "statement", "letStatement", + "ifStatement", "whileStatement", "doStatement", "subroutineCall", "returnStatement", + "expressionList", "expression", "groupedExpression", "unaryOp", "arrayAccess", + "constant", "unaryOperator", "binaryOperator", + ]; + + private static readonly _LITERAL_NAMES: Array = [ + undefined, "'class'", "'constructor'", "'function'", "'method'", "'field'", + "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", + "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", + "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", + "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", undefined, undefined, undefined, + undefined, undefined, "'null'", "'this'", + ]; + private static readonly _SYMBOLIC_NAMES: Array = [ + undefined, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", + "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", + "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", + "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", + "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", + "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", + "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral", + ]; + public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(JackParser._LITERAL_NAMES, JackParser._SYMBOLIC_NAMES, []); + + // @Override + // @NotNull + public get vocabulary(): Vocabulary { + return JackParser.VOCABULARY; + } + // tslint:enable:no-trailing-whitespace + + // @Override + public get grammarFileName(): string { return "JackParser.g4"; } + + // @Override + public get ruleNames(): string[] { return JackParser.ruleNames; } + + // @Override + public override get serializedATN(): string { return JackParser._serializedATN; } + + protected createFailedPredicateException(predicate?: string, message?: string): FailedPredicateException { + return new FailedPredicateException(this, predicate, message); + } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(JackParser._ATN, this); + } + // @RuleVersion(0) + public program(): ProgramContext { + let _localctx: ProgramContext = new ProgramContext(this._ctx, this.state); + this.enterRule(_localctx, 0, JackParser.RULE_program); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 66; + this.classDeclaration(); + this.state = 67; + this.match(JackParser.EOF); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public classDeclaration(): ClassDeclarationContext { + let _localctx: ClassDeclarationContext = new ClassDeclarationContext(this._ctx, this.state); + this.enterRule(_localctx, 2, JackParser.RULE_classDeclaration); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 69; + this.match(JackParser.CLASS); + this.state = 70; + this.className(); + this.state = 71; + this.match(JackParser.LBRACE); + this.state = 75; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === JackParser.FIELD || _la === JackParser.STATIC) { + { + { + this.state = 72; + this.classVarDec(); + } + } + this.state = 77; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 81; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0)) { + { + { + this.state = 78; + this.subroutineDec(); + } + } + this.state = 83; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 84; + this.match(JackParser.RBRACE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public className(): ClassNameContext { + let _localctx: ClassNameContext = new ClassNameContext(this._ctx, this.state); + this.enterRule(_localctx, 4, JackParser.RULE_className); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 86; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public classVarDec(): ClassVarDecContext { + let _localctx: ClassVarDecContext = new ClassVarDecContext(this._ctx, this.state); + this.enterRule(_localctx, 6, JackParser.RULE_classVarDec); + try { + this.state = 96; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case JackParser.STATIC: + _localctx = new StaticFieldDeclarationContext(_localctx); + this.enterOuterAlt(_localctx, 1); + { + this.state = 88; + this.match(JackParser.STATIC); + this.state = 89; + this.fieldList(); + this.state = 90; + this.match(JackParser.SEMICOLON); + } + break; + case JackParser.FIELD: + _localctx = new FieldDeclarationContext(_localctx); + this.enterOuterAlt(_localctx, 2); + { + this.state = 92; + this.match(JackParser.FIELD); + this.state = 93; + this.fieldList(); + this.state = 94; + this.match(JackParser.SEMICOLON); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public fieldList(): FieldListContext { + let _localctx: FieldListContext = new FieldListContext(this._ctx, this.state); + this.enterRule(_localctx, 8, JackParser.RULE_fieldList); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 98; + this.varType(); + this.state = 99; + this.fieldName(); + this.state = 104; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === JackParser.COMMA) { + { + { + this.state = 100; + this.match(JackParser.COMMA); + this.state = 101; + this.fieldName(); + } + } + this.state = 106; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public fieldName(): FieldNameContext { + let _localctx: FieldNameContext = new FieldNameContext(this._ctx, this.state); + this.enterRule(_localctx, 10, JackParser.RULE_fieldName); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 107; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subroutineDec(): SubroutineDecContext { + let _localctx: SubroutineDecContext = new SubroutineDecContext(this._ctx, this.state); + this.enterRule(_localctx, 12, JackParser.RULE_subroutineDec); + try { + this.state = 116; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case JackParser.CONSTRUCTOR: + _localctx = new ConstructorContext(_localctx); + this.enterOuterAlt(_localctx, 1); + { + console.log("Subroutine") + this.state = 110; + this.match(JackParser.CONSTRUCTOR); + this.state = 111; + this.subroutineDecWithoutType(); + } + break; + case JackParser.METHOD: + _localctx = new MethodContext(_localctx); + this.enterOuterAlt(_localctx, 2); + { + this.state = 112; + this.match(JackParser.METHOD); + this.state = 113; + this.subroutineDecWithoutType(); + } + break; + case JackParser.FUNCTION: + _localctx = new FunctionContext(_localctx); + this.enterOuterAlt(_localctx, 3); + { + this.state = 114; + this.match(JackParser.FUNCTION); + this.state = 115; + this.subroutineDecWithoutType(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + let _localctx: SubroutineDecWithoutTypeContext = new SubroutineDecWithoutTypeContext(this._ctx, this.state); + this.enterRule(_localctx, 14, JackParser.RULE_subroutineDecWithoutType); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 118; + this.subroutineReturnType(); + this.state = 119; + this.subroutineName(); + this.state = 120; + this.match(JackParser.LPAREN); + this.state = 121; + this.parameterList(); + this.state = 122; + this.match(JackParser.RPAREN); + this.state = 123; + this.subroutineBody(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subroutineName(): SubroutineNameContext { + let _localctx: SubroutineNameContext = new SubroutineNameContext(this._ctx, this.state); + this.enterRule(_localctx, 16, JackParser.RULE_subroutineName); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 125; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subroutineReturnType(): SubroutineReturnTypeContext { + let _localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this._ctx, this.state); + this.enterRule(_localctx, 18, JackParser.RULE_subroutineReturnType); + try { + this.state = 129; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case JackParser.INT: + case JackParser.CHAR: + case JackParser.BOOLEAN: + case JackParser.IDENTIFIER: + this.enterOuterAlt(_localctx, 1); + { + this.state = 127; + this.varType(); + } + break; + case JackParser.VOID: + this.enterOuterAlt(_localctx, 2); + { + this.state = 128; + this.match(JackParser.VOID); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public varType(): VarTypeContext { + let _localctx: VarTypeContext = new VarTypeContext(this._ctx, this.state); + this.enterRule(_localctx, 20, JackParser.RULE_varType); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 131; + _la = this._input.LA(1); + if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public parameterList(): ParameterListContext { + let _localctx: ParameterListContext = new ParameterListContext(this._ctx, this.state); + this.enterRule(_localctx, 22, JackParser.RULE_parameterList); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 141; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER) { + { + this.state = 133; + this.parameter(); + this.state = 138; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === JackParser.COMMA) { + { + { + this.state = 134; + this.match(JackParser.COMMA); + this.state = 135; + this.parameter(); + } + } + this.state = 140; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public parameter(): ParameterContext { + let _localctx: ParameterContext = new ParameterContext(this._ctx, this.state); + this.enterRule(_localctx, 24, JackParser.RULE_parameter); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 143; + this.varType(); + this.state = 144; + this.parameterName(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public parameterName(): ParameterNameContext { + let _localctx: ParameterNameContext = new ParameterNameContext(this._ctx, this.state); + this.enterRule(_localctx, 26, JackParser.RULE_parameterName); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 146; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subroutineBody(): SubroutineBodyContext { + let _localctx: SubroutineBodyContext = new SubroutineBodyContext(this._ctx, this.state); + this.enterRule(_localctx, 28, JackParser.RULE_subroutineBody); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 148; + this.match(JackParser.LBRACE); + this.state = 152; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === JackParser.VAR) { + { + { + this.state = 149; + this.varDec(); + } + } + this.state = 154; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 155; + this.statements(); + this.state = 156; + this.match(JackParser.RBRACE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public varDec(): VarDecContext { + let _localctx: VarDecContext = new VarDecContext(this._ctx, this.state); + this.enterRule(_localctx, 30, JackParser.RULE_varDec); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 158; + this.match(JackParser.VAR); + this.state = 159; + this.varType(); + this.state = 160; + this.varName(); + this.state = 165; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === JackParser.COMMA) { + { + { + this.state = 161; + this.match(JackParser.COMMA); + this.state = 162; + this.match(JackParser.IDENTIFIER); + } + } + this.state = 167; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 168; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public varName(): VarNameContext { + let _localctx: VarNameContext = new VarNameContext(this._ctx, this.state); + this.enterRule(_localctx, 32, JackParser.RULE_varName); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 170; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public statements(): StatementsContext { + let _localctx: StatementsContext = new StatementsContext(this._ctx, this.state); + this.enterRule(_localctx, 34, JackParser.RULE_statements); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 175; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.LET) | (1 << JackParser.DO) | (1 << JackParser.IF) | (1 << JackParser.WHILE) | (1 << JackParser.RETURN))) !== 0)) { + { + { + this.state = 172; + this.statement(); + } + } + this.state = 177; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public statement(): StatementContext { + let _localctx: StatementContext = new StatementContext(this._ctx, this.state); + this.enterRule(_localctx, 36, JackParser.RULE_statement); + try { + this.state = 183; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case JackParser.LET: + this.enterOuterAlt(_localctx, 1); + { + this.state = 178; + this.letStatement(); + } + break; + case JackParser.IF: + this.enterOuterAlt(_localctx, 2); + { + this.state = 179; + this.ifStatement(); + } + break; + case JackParser.WHILE: + this.enterOuterAlt(_localctx, 3); + { + this.state = 180; + this.whileStatement(); + } + break; + case JackParser.DO: + this.enterOuterAlt(_localctx, 4); + { + this.state = 181; + this.doStatement(); + } + break; + case JackParser.RETURN: + this.enterOuterAlt(_localctx, 5); + { + this.state = 182; + this.returnStatement(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public letStatement(): LetStatementContext { + let _localctx: LetStatementContext = new LetStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 38, JackParser.RULE_letStatement); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 185; + this.match(JackParser.LET); + this.state = 188; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 12, this._ctx) ) { + case 1: + { + this.state = 186; + this.match(JackParser.IDENTIFIER); + } + break; + + case 2: + { + this.state = 187; + this.arrayAccess(); + } + break; + } + this.state = 190; + this.match(JackParser.EQUALS); + this.state = 191; + this.expression(0); + this.state = 192; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public ifStatement(): IfStatementContext { + let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 40, JackParser.RULE_ifStatement); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 194; + this.match(JackParser.IF); + this.state = 195; + this.match(JackParser.LPAREN); + this.state = 196; + this.expression(0); + this.state = 197; + this.match(JackParser.RPAREN); + this.state = 198; + this.match(JackParser.LBRACE); + this.state = 199; + this.statements(); + this.state = 200; + this.match(JackParser.RBRACE); + this.state = 206; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === JackParser.ELSE) { + { + this.state = 201; + this.match(JackParser.ELSE); + this.state = 202; + this.match(JackParser.LBRACE); + this.state = 203; + this.statements(); + this.state = 204; + this.match(JackParser.RBRACE); + } + } + + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public whileStatement(): WhileStatementContext { + let _localctx: WhileStatementContext = new WhileStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 42, JackParser.RULE_whileStatement); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 208; + this.match(JackParser.WHILE); + this.state = 209; + this.match(JackParser.LPAREN); + this.state = 210; + this.expression(0); + this.state = 211; + this.match(JackParser.RPAREN); + this.state = 212; + this.match(JackParser.LBRACE); + this.state = 213; + this.statements(); + this.state = 214; + this.match(JackParser.RBRACE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public doStatement(): DoStatementContext { + let _localctx: DoStatementContext = new DoStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 44, JackParser.RULE_doStatement); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 216; + this.match(JackParser.DO); + this.state = 217; + this.subroutineCall(); + this.state = 218; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subroutineCall(): SubroutineCallContext { + let _localctx: SubroutineCallContext = new SubroutineCallContext(this._ctx, this.state); + this.enterRule(_localctx, 46, JackParser.RULE_subroutineCall); + let _la: number; + try { + this.state = 232; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { + case 1: + this.enterOuterAlt(_localctx, 1); + { + this.state = 220; + this.match(JackParser.IDENTIFIER); + this.state = 221; + this.match(JackParser.LPAREN); + this.state = 222; + this.expressionList(); + this.state = 223; + this.match(JackParser.RPAREN); + } + break; + + case 2: + this.enterOuterAlt(_localctx, 2); + { + this.state = 225; + _la = this._input.LA(1); + if (!(_la === JackParser.THIS_LITERAL || _la === JackParser.IDENTIFIER)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 226; + this.match(JackParser.DOT); + this.state = 227; + this.match(JackParser.IDENTIFIER); + this.state = 228; + this.match(JackParser.LPAREN); + this.state = 229; + this.expressionList(); + this.state = 230; + this.match(JackParser.RPAREN); + } + break; + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public returnStatement(): ReturnStatementContext { + let _localctx: ReturnStatementContext = new ReturnStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 48, JackParser.RULE_returnStatement); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 234; + this.match(JackParser.RETURN); + this.state = 236; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { + { + this.state = 235; + this.expression(0); + } + } + + this.state = 238; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public expressionList(): ExpressionListContext { + let _localctx: ExpressionListContext = new ExpressionListContext(this._ctx, this.state); + this.enterRule(_localctx, 50, JackParser.RULE_expressionList); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 248; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { + { + this.state = 240; + this.expression(0); + this.state = 245; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === JackParser.COMMA) { + { + { + this.state = 241; + this.match(JackParser.COMMA); + this.state = 242; + this.expression(0); + } + } + this.state = 247; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + + public expression(): ExpressionContext; + public expression(_p: number): ExpressionContext; + // @RuleVersion(0) + public expression(_p?: number): ExpressionContext { + if (_p === undefined) { + _p = 0; + } + + let _parentctx: ParserRuleContext = this._ctx; + let _parentState: number = this.state; + let _localctx: ExpressionContext = new ExpressionContext(this._ctx, _parentState); + let _prevctx: ExpressionContext = _localctx; + let _startState: number = 52; + this.enterRecursionRule(_localctx, 52, JackParser.RULE_expression, _p); + try { + let _alt: number; + this.enterOuterAlt(_localctx, 1); + { + this.state = 257; + this._errHandler.sync(this); + switch ( this.interpreter.adaptivePredict(this._input, 18, this._ctx) ) { + case 1: + { + this.state = 251; + this.constant(); + } + break; + + case 2: + { + this.state = 252; + this.match(JackParser.IDENTIFIER); + } + break; + + case 3: + { + this.state = 253; + this.subroutineCall(); + } + break; + + case 4: + { + this.state = 254; + this.arrayAccess(); + } + break; + + case 5: + { + this.state = 255; + this.unaryOp(); + } + break; + + case 6: + { + this.state = 256; + this.groupedExpression(); + } + break; + } + this._ctx._stop = this._input.tryLT(-1); + this.state = 265; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners != null) { + this.triggerExitRuleEvent(); + } + _prevctx = _localctx; + { + { + _localctx = new ExpressionContext(_parentctx, _parentState); + _localctx._binaryOperation = _prevctx; + this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); + this.state = 259; + if (!(this.precpred(this._ctx, 7))) { + throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); + } + this.state = 260; + this.binaryOperator(); + this.state = 261; + this.expression(8); + } + } + } + this.state = 267; + this._errHandler.sync(this); + _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.unrollRecursionContexts(_parentctx); + } + return _localctx; + } + // @RuleVersion(0) + public groupedExpression(): GroupedExpressionContext { + let _localctx: GroupedExpressionContext = new GroupedExpressionContext(this._ctx, this.state); + this.enterRule(_localctx, 54, JackParser.RULE_groupedExpression); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 268; + this.match(JackParser.LPAREN); + this.state = 269; + this.expression(0); + this.state = 270; + this.match(JackParser.RPAREN); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public unaryOp(): UnaryOpContext { + let _localctx: UnaryOpContext = new UnaryOpContext(this._ctx, this.state); + this.enterRule(_localctx, 56, JackParser.RULE_unaryOp); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 272; + this.unaryOperator(); + this.state = 273; + this.expression(0); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public arrayAccess(): ArrayAccessContext { + let _localctx: ArrayAccessContext = new ArrayAccessContext(this._ctx, this.state); + this.enterRule(_localctx, 58, JackParser.RULE_arrayAccess); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 275; + this.match(JackParser.IDENTIFIER); + this.state = 276; + this.match(JackParser.LBRACKET); + this.state = 277; + this.expression(0); + this.state = 278; + this.match(JackParser.RBRACKET); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public constant(): ConstantContext { + let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); + this.enterRule(_localctx, 60, JackParser.RULE_constant); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 280; + _la = this._input.LA(1); + if (!(((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & ((1 << (JackParser.INTEGER_LITERAL - 40)) | (1 << (JackParser.BOOLEAN_LITERAL - 40)) | (1 << (JackParser.NULL_LITERAL - 40)) | (1 << (JackParser.THIS_LITERAL - 40)) | (1 << (JackParser.STRING_LITERAL - 40)))) !== 0))) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public unaryOperator(): UnaryOperatorContext { + let _localctx: UnaryOperatorContext = new UnaryOperatorContext(this._ctx, this.state); + this.enterRule(_localctx, 62, JackParser.RULE_unaryOperator); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 282; + _la = this._input.LA(1); + if (!(_la === JackParser.MINUS || _la === JackParser.TILDE)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public binaryOperator(): BinaryOperatorContext { + let _localctx: BinaryOperatorContext = new BinaryOperatorContext(this._ctx, this.state); + this.enterRule(_localctx, 64, JackParser.RULE_binaryOperator); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 284; + _la = this._input.LA(1); + if (!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & ((1 << (JackParser.EQUALS - 27)) | (1 << (JackParser.PLUS - 27)) | (1 << (JackParser.MINUS - 27)) | (1 << (JackParser.MUL - 27)) | (1 << (JackParser.DIV - 27)) | (1 << (JackParser.AND - 27)) | (1 << (JackParser.OR - 27)) | (1 << (JackParser.LESS_THAN - 27)) | (1 << (JackParser.GREATER_THAN - 27)))) !== 0))) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; + } + + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + + public override sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { + switch (ruleIndex) { + case 26: + return this.expression_sempred(_localctx as ExpressionContext, predIndex); + } + return true; + } + private expression_sempred(_localctx: ExpressionContext, predIndex: number): boolean { + switch (predIndex) { + case 0: + return this.precpred(this._ctx, 7); + } + return true; + } + + public static readonly _serializedATN: string = + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u0121\x04\x02" + + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + + "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + + "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x03\x02" + + "\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x07\x03L\n\x03\f\x03" + + "\x0E\x03O\v\x03\x03\x03\x07\x03R\n\x03\f\x03\x0E\x03U\v\x03\x03\x03\x03" + + "\x03\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + + "\x05\x03\x05\x05\x05c\n\x05\x03\x06\x03\x06\x03\x06\x03\x06\x07\x06i\n" + + "\x06\f\x06\x0E\x06l\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\b\x03" + + "\b\x03\b\x03\b\x05\bw\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03" + + "\n\x03\n\x03\v\x03\v\x05\v\x84\n\v\x03\f\x03\f\x03\r\x03\r\x03\r\x07\r" + + "\x8B\n\r\f\r\x0E\r\x8E\v\r\x05\r\x90\n\r\x03\x0E\x03\x0E\x03\x0E\x03\x0F" + + "\x03\x0F\x03\x10\x03\x10\x07\x10\x99\n\x10\f\x10\x0E\x10\x9C\v\x10\x03" + + "\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x07\x11\xA6" + + "\n\x11\f\x11\x0E\x11\xA9\v\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x13" + + "\x07\x13\xB0\n\x13\f\x13\x0E\x13\xB3\v\x13\x03\x14\x03\x14\x03\x14\x03" + + "\x14\x03\x14\x05\x14\xBA\n\x14\x03\x15\x03\x15\x03\x15\x05\x15\xBF\n\x15" + + "\x03\x15\x03\x15\x03\x15\x03\x15\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16" + + "\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x05\x16\xD1\n" + + "\x16\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03" + + "\x18\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03" + + "\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x05\x19\xEB\n\x19" + + "\x03\x1A\x03\x1A\x05\x1A\xEF\n\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + + "\x1B\x07\x1B\xF6\n\x1B\f\x1B\x0E\x1B\xF9\v\x1B\x05\x1B\xFB\n\x1B\x03\x1C" + + "\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x05\x1C\u0104\n\x1C\x03" + + "\x1C\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u010A\n\x1C\f\x1C\x0E\x1C\u010D\v" + + "\x1C\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1F\x03" + + "\x1F\x03\x1F\x03\x1F\x03\x1F\x03 \x03 \x03!\x03!\x03\"\x03\"\x03\"\x02" + + "\x02\x036#\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12" + + "\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&" + + "\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02" + + "B\x02\x02\x07\x04\x02\n\f..\x03\x02-.\x04\x02*-//\x04\x02\x1F\x1F$$\x04" + + "\x02\x1D#%&\x02\u011B\x02D\x03\x02\x02\x02\x04G\x03\x02\x02\x02\x06X\x03" + + "\x02\x02\x02\bb\x03\x02\x02\x02\nd\x03\x02\x02\x02\fm\x03\x02\x02\x02" + + "\x0Ev\x03\x02\x02\x02\x10x\x03\x02\x02\x02\x12\x7F\x03\x02\x02\x02\x14" + + "\x83\x03\x02\x02\x02\x16\x85\x03\x02\x02\x02\x18\x8F\x03\x02\x02\x02\x1A" + + "\x91\x03\x02\x02\x02\x1C\x94\x03\x02\x02\x02\x1E\x96\x03\x02\x02\x02 " + + "\xA0\x03\x02\x02\x02\"\xAC\x03\x02\x02\x02$\xB1\x03\x02\x02\x02&\xB9\x03" + + "\x02\x02\x02(\xBB\x03\x02\x02\x02*\xC4\x03\x02\x02\x02,\xD2\x03\x02\x02" + + "\x02.\xDA\x03\x02\x02\x020\xEA\x03\x02\x02\x022\xEC\x03\x02\x02\x024\xFA" + + "\x03\x02\x02\x026\u0103\x03\x02\x02\x028\u010E\x03\x02\x02\x02:\u0112" + + "\x03\x02\x02\x02<\u0115\x03\x02\x02\x02>\u011A\x03\x02\x02\x02@\u011C" + + "\x03\x02\x02\x02B\u011E\x03\x02\x02\x02DE\x05\x04\x03\x02EF\x07\x02\x02" + + "\x03F\x03\x03\x02\x02\x02GH\x07\x03\x02\x02HI\x05\x06\x04\x02IM\x07\x14" + + "\x02\x02JL\x05\b\x05\x02KJ\x03\x02\x02\x02LO\x03\x02\x02\x02MK\x03\x02" + + "\x02\x02MN\x03\x02\x02\x02NS\x03\x02\x02\x02OM\x03\x02\x02\x02PR\x05\x0E" + + "\b\x02QP\x03\x02\x02\x02RU\x03\x02\x02\x02SQ\x03\x02\x02\x02ST\x03\x02" + + "\x02\x02TV\x03\x02\x02\x02US\x03\x02\x02\x02VW\x07\x15\x02\x02W\x05\x03" + + "\x02\x02\x02XY\x07.\x02\x02Y\x07\x03\x02\x02\x02Z[\x07\b\x02\x02[\\\x05" + + "\n\x06\x02\\]\x07\x1C\x02\x02]c\x03\x02\x02\x02^_\x07\x07\x02\x02_`\x05" + + "\n\x06\x02`a\x07\x1C\x02\x02ac\x03\x02\x02\x02bZ\x03\x02\x02\x02b^\x03" + + "\x02\x02\x02c\t\x03\x02\x02\x02de\x05\x16\f\x02ej\x05\f\x07\x02fg\x07" + + "\x1B\x02\x02gi\x05\f\x07\x02hf\x03\x02\x02\x02il\x03\x02\x02\x02jh\x03" + + "\x02\x02\x02jk\x03\x02\x02\x02k\v\x03\x02\x02\x02lj\x03\x02\x02\x02mn" + + "\x07.\x02\x02n\r\x03\x02\x02\x02op\b\b\x01\x02pq\x07\x04\x02\x02qw\x05" + + "\x10\t\x02rs\x07\x06\x02\x02sw\x05\x10\t\x02tu\x07\x05\x02\x02uw\x05\x10" + + "\t\x02vo\x03\x02\x02\x02vr\x03\x02\x02\x02vt\x03\x02\x02\x02w\x0F\x03" + + "\x02\x02\x02xy\x05\x14\v\x02yz\x05\x12\n\x02z{\x07\x16\x02\x02{|\x05\x18" + + "\r\x02|}\x07\x17\x02\x02}~\x05\x1E\x10\x02~\x11\x03\x02\x02\x02\x7F\x80" + + "\x07.\x02\x02\x80\x13\x03\x02\x02\x02\x81\x84\x05\x16\f\x02\x82\x84\x07" + + "\r\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82\x03\x02\x02\x02\x84\x15\x03" + + "\x02\x02\x02\x85\x86\t\x02\x02\x02\x86\x17\x03\x02\x02\x02\x87\x8C\x05" + + "\x1A\x0E\x02\x88\x89\x07\x1B\x02\x02\x89\x8B\x05\x1A\x0E\x02\x8A\x88\x03" + + "\x02\x02\x02\x8B\x8E\x03\x02\x02\x02\x8C\x8A\x03\x02\x02\x02\x8C\x8D\x03" + + "\x02\x02\x02\x8D\x90\x03\x02\x02\x02\x8E\x8C\x03\x02\x02\x02\x8F\x87\x03" + + "\x02\x02\x02\x8F\x90\x03\x02\x02\x02\x90\x19\x03\x02\x02\x02\x91\x92\x05" + + "\x16\f\x02\x92\x93\x05\x1C\x0F\x02\x93\x1B\x03\x02\x02\x02\x94\x95\x07" + + ".\x02\x02\x95\x1D\x03\x02\x02\x02\x96\x9A\x07\x14\x02\x02\x97\x99\x05" + + " \x11\x02\x98\x97\x03\x02\x02\x02\x99\x9C\x03\x02\x02\x02\x9A\x98\x03" + + "\x02\x02\x02\x9A\x9B\x03\x02\x02\x02\x9B\x9D\x03\x02\x02\x02\x9C\x9A\x03" + + "\x02\x02\x02\x9D\x9E\x05$\x13\x02\x9E\x9F\x07\x15\x02\x02\x9F\x1F\x03" + + "\x02\x02\x02\xA0\xA1\x07\t\x02\x02\xA1\xA2\x05\x16\f\x02\xA2\xA7\x05\"" + + "\x12\x02\xA3\xA4\x07\x1B\x02\x02\xA4\xA6\x07.\x02\x02\xA5\xA3\x03\x02" + + "\x02\x02\xA6\xA9\x03\x02\x02\x02\xA7\xA5\x03\x02\x02\x02\xA7\xA8\x03\x02" + + "\x02\x02\xA8\xAA\x03\x02\x02\x02\xA9\xA7\x03\x02\x02\x02\xAA\xAB\x07\x1C" + + "\x02\x02\xAB!\x03\x02\x02\x02\xAC\xAD\x07.\x02\x02\xAD#\x03\x02\x02\x02" + + "\xAE\xB0\x05&\x14\x02\xAF\xAE\x03\x02\x02\x02\xB0\xB3\x03\x02\x02\x02" + + "\xB1\xAF\x03\x02\x02\x02\xB1\xB2\x03\x02\x02\x02\xB2%\x03\x02\x02\x02" + + "\xB3\xB1\x03\x02\x02\x02\xB4\xBA\x05(\x15\x02\xB5\xBA\x05*\x16\x02\xB6" + + "\xBA\x05,\x17\x02\xB7\xBA\x05.\x18\x02\xB8\xBA\x052\x1A\x02\xB9\xB4\x03" + + "\x02\x02\x02\xB9\xB5\x03\x02\x02\x02\xB9\xB6\x03\x02\x02\x02\xB9\xB7\x03" + + "\x02\x02\x02\xB9\xB8\x03\x02\x02\x02\xBA\'\x03\x02\x02\x02\xBB\xBE\x07" + + "\x0E\x02\x02\xBC\xBF\x07.\x02\x02\xBD\xBF\x05<\x1F\x02\xBE\xBC\x03\x02" + + "\x02\x02\xBE\xBD\x03\x02\x02\x02\xBF\xC0\x03\x02\x02\x02\xC0\xC1\x07\x1D" + + "\x02\x02\xC1\xC2\x056\x1C\x02\xC2\xC3\x07\x1C\x02\x02\xC3)\x03\x02\x02" + + "\x02\xC4\xC5\x07\x10\x02\x02\xC5\xC6\x07\x16\x02\x02\xC6\xC7\x056\x1C" + + "\x02\xC7\xC8\x07\x17\x02\x02\xC8\xC9\x07\x14\x02\x02\xC9\xCA\x05$\x13" + + "\x02\xCA\xD0\x07\x15\x02\x02\xCB\xCC\x07\x11\x02\x02\xCC\xCD\x07\x14\x02" + + "\x02\xCD\xCE\x05$\x13\x02\xCE\xCF\x07\x15\x02\x02\xCF\xD1\x03\x02\x02" + + "\x02\xD0\xCB\x03\x02\x02\x02\xD0\xD1\x03\x02\x02\x02\xD1+\x03\x02\x02" + + "\x02\xD2\xD3\x07\x12\x02\x02\xD3\xD4\x07\x16\x02\x02\xD4\xD5\x056\x1C" + + "\x02\xD5\xD6\x07\x17\x02\x02\xD6\xD7\x07\x14\x02\x02\xD7\xD8\x05$\x13" + + "\x02\xD8\xD9\x07\x15\x02\x02\xD9-\x03\x02\x02\x02\xDA\xDB\x07\x0F\x02" + + "\x02\xDB\xDC\x050\x19\x02\xDC\xDD\x07\x1C\x02\x02\xDD/\x03\x02\x02\x02" + + "\xDE\xDF\x07.\x02\x02\xDF\xE0\x07\x16\x02\x02\xE0\xE1\x054\x1B\x02\xE1" + + "\xE2\x07\x17\x02\x02\xE2\xEB\x03\x02\x02\x02\xE3\xE4\t\x03\x02\x02\xE4" + + "\xE5\x07\x1A\x02\x02\xE5\xE6\x07.\x02\x02\xE6\xE7\x07\x16\x02\x02\xE7" + + "\xE8\x054\x1B\x02\xE8\xE9\x07\x17\x02\x02\xE9\xEB\x03\x02\x02\x02\xEA" + + "\xDE\x03\x02\x02\x02\xEA\xE3\x03\x02\x02\x02\xEB1\x03\x02\x02\x02\xEC" + + "\xEE\x07\x13\x02\x02\xED\xEF\x056\x1C\x02\xEE\xED\x03\x02\x02\x02\xEE" + + "\xEF\x03\x02\x02\x02\xEF\xF0\x03\x02\x02\x02\xF0\xF1\x07\x1C\x02\x02\xF1" + + "3\x03\x02\x02\x02\xF2\xF7\x056\x1C\x02\xF3\xF4\x07\x1B\x02\x02\xF4\xF6" + + "\x056\x1C\x02\xF5\xF3\x03\x02\x02\x02\xF6\xF9\x03\x02\x02\x02\xF7\xF5" + + "\x03\x02\x02\x02\xF7\xF8\x03\x02\x02\x02\xF8\xFB\x03\x02\x02\x02\xF9\xF7" + + "\x03\x02\x02\x02\xFA\xF2\x03\x02\x02\x02\xFA\xFB\x03\x02\x02\x02\xFB5" + + "\x03\x02\x02\x02\xFC\xFD\b\x1C\x01\x02\xFD\u0104\x05> \x02\xFE\u0104\x07" + + ".\x02\x02\xFF\u0104\x050\x19\x02\u0100\u0104\x05<\x1F\x02\u0101\u0104" + + "\x05:\x1E\x02\u0102\u0104\x058\x1D\x02\u0103\xFC\x03\x02\x02\x02\u0103" + + "\xFE\x03\x02\x02\x02\u0103\xFF\x03\x02\x02\x02\u0103\u0100\x03\x02\x02" + + "\x02\u0103\u0101\x03\x02\x02\x02\u0103\u0102\x03\x02\x02\x02\u0104\u010B" + + "\x03\x02\x02\x02\u0105\u0106\f\t\x02\x02\u0106\u0107\x05B\"\x02\u0107" + + "\u0108\x056\x1C\n\u0108\u010A\x03\x02\x02\x02\u0109\u0105\x03\x02\x02" + + "\x02\u010A\u010D\x03\x02\x02\x02\u010B\u0109\x03\x02\x02\x02\u010B\u010C" + + "\x03\x02\x02\x02\u010C7\x03\x02\x02\x02\u010D\u010B\x03\x02\x02\x02\u010E" + + "\u010F\x07\x16\x02\x02\u010F\u0110\x056\x1C\x02\u0110\u0111\x07\x17\x02" + + "\x02\u01119\x03\x02\x02\x02\u0112\u0113\x05@!\x02\u0113\u0114\x056\x1C" + + "\x02\u0114;\x03\x02\x02\x02\u0115\u0116\x07.\x02\x02\u0116\u0117\x07\x18" + + "\x02\x02\u0117\u0118\x056\x1C\x02\u0118\u0119\x07\x19\x02\x02\u0119=\x03" + + "\x02\x02\x02\u011A\u011B\t\x04\x02\x02\u011B?\x03\x02\x02\x02\u011C\u011D" + + "\t\x05\x02\x02\u011DA\x03\x02\x02\x02\u011E\u011F\t\x06\x02\x02\u011F" + + "C\x03\x02\x02\x02\x16MSbjv\x83\x8C\x8F\x9A\xA7\xB1\xB9\xBE\xD0\xEA\xEE" + + "\xF7\xFA\u0103\u010B"; + public static __ATN: ATN; + public static get _ATN(): ATN { + if (!JackParser.__ATN) { + JackParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(JackParser._serializedATN)); + } + + return JackParser.__ATN; + } + +} + +export class ProgramContext extends ParserRuleContext { + public classDeclaration(): ClassDeclarationContext { + return this.getRuleContext(0, ClassDeclarationContext); + } + public EOF(): TerminalNode { return this.getToken(JackParser.EOF, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_program; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterProgram) { + listener.enterProgram(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitProgram) { + listener.exitProgram(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitProgram) { + return visitor.visitProgram(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ClassDeclarationContext extends ParserRuleContext { + public CLASS(): TerminalNode { return this.getToken(JackParser.CLASS, 0); } + public className(): ClassNameContext { + return this.getRuleContext(0, ClassNameContext); + } + public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } + public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + public classVarDec(): ClassVarDecContext[]; + public classVarDec(i: number): ClassVarDecContext; + public classVarDec(i?: number): ClassVarDecContext | ClassVarDecContext[] { + if (i === undefined) { + return this.getRuleContexts(ClassVarDecContext); + } else { + return this.getRuleContext(i, ClassVarDecContext); + } + } + public subroutineDec(): SubroutineDecContext[]; + public subroutineDec(i: number): SubroutineDecContext; + public subroutineDec(i?: number): SubroutineDecContext | SubroutineDecContext[] { + if (i === undefined) { + return this.getRuleContexts(SubroutineDecContext); + } else { + return this.getRuleContext(i, SubroutineDecContext); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_classDeclaration; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterClassDeclaration) { + listener.enterClassDeclaration(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitClassDeclaration) { + listener.exitClassDeclaration(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitClassDeclaration) { + return visitor.visitClassDeclaration(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ClassNameContext extends ParserRuleContext { + public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_className; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterClassName) { + listener.enterClassName(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitClassName) { + listener.exitClassName(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitClassName) { + return visitor.visitClassName(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ClassVarDecContext extends ParserRuleContext { + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_classVarDec; } + public override copyFrom(ctx: ClassVarDecContext): void { + super.copyFrom(ctx); + } +} +export class StaticFieldDeclarationContext extends ClassVarDecContext { + public STATIC(): TerminalNode { return this.getToken(JackParser.STATIC, 0); } + public fieldList(): FieldListContext { + return this.getRuleContext(0, FieldListContext); + } + public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } + constructor(ctx: ClassVarDecContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterStaticFieldDeclaration) { + listener.enterStaticFieldDeclaration(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitStaticFieldDeclaration) { + listener.exitStaticFieldDeclaration(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitStaticFieldDeclaration) { + return visitor.visitStaticFieldDeclaration(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class FieldDeclarationContext extends ClassVarDecContext { + public FIELD(): TerminalNode { return this.getToken(JackParser.FIELD, 0); } + public fieldList(): FieldListContext { + return this.getRuleContext(0, FieldListContext); + } + public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } + constructor(ctx: ClassVarDecContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterFieldDeclaration) { + listener.enterFieldDeclaration(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitFieldDeclaration) { + listener.exitFieldDeclaration(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitFieldDeclaration) { + return visitor.visitFieldDeclaration(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class FieldListContext extends ParserRuleContext { + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext); + } + public fieldName(): FieldNameContext[]; + public fieldName(i: number): FieldNameContext; + public fieldName(i?: number): FieldNameContext | FieldNameContext[] { + if (i === undefined) { + return this.getRuleContexts(FieldNameContext); + } else { + return this.getRuleContext(i, FieldNameContext); + } + } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_fieldList; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterFieldList) { + listener.enterFieldList(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitFieldList) { + listener.exitFieldList(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitFieldList) { + return visitor.visitFieldList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class FieldNameContext extends ParserRuleContext { + public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_fieldName; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterFieldName) { + listener.enterFieldName(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitFieldName) { + listener.exitFieldName(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitFieldName) { + return visitor.visitFieldName(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class SubroutineDecContext extends ParserRuleContext { + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_subroutineDec; } + public override copyFrom(ctx: SubroutineDecContext): void { + super.copyFrom(ctx); + } +} +export class ConstructorContext extends SubroutineDecContext { + public CONSTRUCTOR(): TerminalNode { return this.getToken(JackParser.CONSTRUCTOR, 0); } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + return this.getRuleContext(0, SubroutineDecWithoutTypeContext); + } + constructor(ctx: SubroutineDecContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterConstructor) { + listener.enterConstructor(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitConstructor) { + listener.exitConstructor(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitConstructor) { + return visitor.visitConstructor(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class MethodContext extends SubroutineDecContext { + public METHOD(): TerminalNode { return this.getToken(JackParser.METHOD, 0); } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + return this.getRuleContext(0, SubroutineDecWithoutTypeContext); + } + constructor(ctx: SubroutineDecContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterMethod) { + listener.enterMethod(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitMethod) { + listener.exitMethod(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitMethod) { + return visitor.visitMethod(this); + } else { + return visitor.visitChildren(this); + } + } +} +export class FunctionContext extends SubroutineDecContext { + public FUNCTION(): TerminalNode { return this.getToken(JackParser.FUNCTION, 0); } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + return this.getRuleContext(0, SubroutineDecWithoutTypeContext); + } + constructor(ctx: SubroutineDecContext) { + super(ctx.parent, ctx.invokingState); + this.copyFrom(ctx); + } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterFunction) { + listener.enterFunction(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitFunction) { + listener.exitFunction(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitFunction) { + return visitor.visitFunction(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class SubroutineDecWithoutTypeContext extends ParserRuleContext { + public subroutineReturnType(): SubroutineReturnTypeContext { + return this.getRuleContext(0, SubroutineReturnTypeContext); + } + public subroutineName(): SubroutineNameContext { + return this.getRuleContext(0, SubroutineNameContext); + } + public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } + public parameterList(): ParameterListContext { + return this.getRuleContext(0, ParameterListContext); + } + public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } + public subroutineBody(): SubroutineBodyContext { + return this.getRuleContext(0, SubroutineBodyContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_subroutineDecWithoutType; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineDecWithoutType) { + listener.enterSubroutineDecWithoutType(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineDecWithoutType) { + listener.exitSubroutineDecWithoutType(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitSubroutineDecWithoutType) { + return visitor.visitSubroutineDecWithoutType(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class SubroutineNameContext extends ParserRuleContext { + public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_subroutineName; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineName) { + listener.enterSubroutineName(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineName) { + listener.exitSubroutineName(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitSubroutineName) { + return visitor.visitSubroutineName(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class SubroutineReturnTypeContext extends ParserRuleContext { + public varType(): VarTypeContext | undefined { + return this.tryGetRuleContext(0, VarTypeContext); + } + public VOID(): TerminalNode | undefined { return this.tryGetToken(JackParser.VOID, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_subroutineReturnType; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineReturnType) { + listener.enterSubroutineReturnType(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineReturnType) { + listener.exitSubroutineReturnType(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitSubroutineReturnType) { + return visitor.visitSubroutineReturnType(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class VarTypeContext extends ParserRuleContext { + public INT(): TerminalNode | undefined { return this.tryGetToken(JackParser.INT, 0); } + public CHAR(): TerminalNode | undefined { return this.tryGetToken(JackParser.CHAR, 0); } + public BOOLEAN(): TerminalNode | undefined { return this.tryGetToken(JackParser.BOOLEAN, 0); } + public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(JackParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_varType; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterVarType) { + listener.enterVarType(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitVarType) { + listener.exitVarType(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitVarType) { + return visitor.visitVarType(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ParameterListContext extends ParserRuleContext { + public parameter(): ParameterContext[]; + public parameter(i: number): ParameterContext; + public parameter(i?: number): ParameterContext | ParameterContext[] { + if (i === undefined) { + return this.getRuleContexts(ParameterContext); + } else { + return this.getRuleContext(i, ParameterContext); + } + } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_parameterList; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterParameterList) { + listener.enterParameterList(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitParameterList) { + listener.exitParameterList(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitParameterList) { + return visitor.visitParameterList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ParameterContext extends ParserRuleContext { + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext); + } + public parameterName(): ParameterNameContext { + return this.getRuleContext(0, ParameterNameContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_parameter; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterParameter) { + listener.enterParameter(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitParameter) { + listener.exitParameter(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitParameter) { + return visitor.visitParameter(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ParameterNameContext extends ParserRuleContext { + public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_parameterName; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterParameterName) { + listener.enterParameterName(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitParameterName) { + listener.exitParameterName(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitParameterName) { + return visitor.visitParameterName(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class SubroutineBodyContext extends ParserRuleContext { + public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext); + } + public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + public varDec(): VarDecContext[]; + public varDec(i: number): VarDecContext; + public varDec(i?: number): VarDecContext | VarDecContext[] { + if (i === undefined) { + return this.getRuleContexts(VarDecContext); + } else { + return this.getRuleContext(i, VarDecContext); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_subroutineBody; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineBody) { + listener.enterSubroutineBody(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineBody) { + listener.exitSubroutineBody(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitSubroutineBody) { + return visitor.visitSubroutineBody(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class VarDecContext extends ParserRuleContext { + public VAR(): TerminalNode { return this.getToken(JackParser.VAR, 0); } + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext); + } + public varName(): VarNameContext { + return this.getRuleContext(0, VarNameContext); + } + public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public IDENTIFIER(): TerminalNode[]; + public IDENTIFIER(i: number): TerminalNode; + public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.IDENTIFIER); + } else { + return this.getToken(JackParser.IDENTIFIER, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_varDec; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterVarDec) { + listener.enterVarDec(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitVarDec) { + listener.exitVarDec(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitVarDec) { + return visitor.visitVarDec(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class VarNameContext extends ParserRuleContext { + public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_varName; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterVarName) { + listener.enterVarName(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitVarName) { + listener.exitVarName(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitVarName) { + return visitor.visitVarName(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class StatementsContext extends ParserRuleContext { + public statement(): StatementContext[]; + public statement(i: number): StatementContext; + public statement(i?: number): StatementContext | StatementContext[] { + if (i === undefined) { + return this.getRuleContexts(StatementContext); + } else { + return this.getRuleContext(i, StatementContext); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_statements; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterStatements) { + listener.enterStatements(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitStatements) { + listener.exitStatements(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitStatements) { + return visitor.visitStatements(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class StatementContext extends ParserRuleContext { + public letStatement(): LetStatementContext | undefined { + return this.tryGetRuleContext(0, LetStatementContext); + } + public ifStatement(): IfStatementContext | undefined { + return this.tryGetRuleContext(0, IfStatementContext); + } + public whileStatement(): WhileStatementContext | undefined { + return this.tryGetRuleContext(0, WhileStatementContext); + } + public doStatement(): DoStatementContext | undefined { + return this.tryGetRuleContext(0, DoStatementContext); + } + public returnStatement(): ReturnStatementContext | undefined { + return this.tryGetRuleContext(0, ReturnStatementContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_statement; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterStatement) { + listener.enterStatement(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitStatement) { + listener.exitStatement(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitStatement) { + return visitor.visitStatement(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class LetStatementContext extends ParserRuleContext { + public LET(): TerminalNode { return this.getToken(JackParser.LET, 0); } + public EQUALS(): TerminalNode { return this.getToken(JackParser.EQUALS, 0); } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext); + } + public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } + public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(JackParser.IDENTIFIER, 0); } + public arrayAccess(): ArrayAccessContext | undefined { + return this.tryGetRuleContext(0, ArrayAccessContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_letStatement; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterLetStatement) { + listener.enterLetStatement(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitLetStatement) { + listener.exitLetStatement(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitLetStatement) { + return visitor.visitLetStatement(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class IfStatementContext extends ParserRuleContext { + public IF(): TerminalNode { return this.getToken(JackParser.IF, 0); } + public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext); + } + public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } + public LBRACE(): TerminalNode[]; + public LBRACE(i: number): TerminalNode; + public LBRACE(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.LBRACE); + } else { + return this.getToken(JackParser.LBRACE, i); + } + } + public statements(): StatementsContext[]; + public statements(i: number): StatementsContext; + public statements(i?: number): StatementsContext | StatementsContext[] { + if (i === undefined) { + return this.getRuleContexts(StatementsContext); + } else { + return this.getRuleContext(i, StatementsContext); + } + } + public RBRACE(): TerminalNode[]; + public RBRACE(i: number): TerminalNode; + public RBRACE(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.RBRACE); + } else { + return this.getToken(JackParser.RBRACE, i); + } + } + public ELSE(): TerminalNode | undefined { return this.tryGetToken(JackParser.ELSE, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_ifStatement; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterIfStatement) { + listener.enterIfStatement(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitIfStatement) { + listener.exitIfStatement(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitIfStatement) { + return visitor.visitIfStatement(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class WhileStatementContext extends ParserRuleContext { + public WHILE(): TerminalNode { return this.getToken(JackParser.WHILE, 0); } + public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext); + } + public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } + public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext); + } + public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_whileStatement; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterWhileStatement) { + listener.enterWhileStatement(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitWhileStatement) { + listener.exitWhileStatement(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitWhileStatement) { + return visitor.visitWhileStatement(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class DoStatementContext extends ParserRuleContext { + public DO(): TerminalNode { return this.getToken(JackParser.DO, 0); } + public subroutineCall(): SubroutineCallContext { + return this.getRuleContext(0, SubroutineCallContext); + } + public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_doStatement; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterDoStatement) { + listener.enterDoStatement(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitDoStatement) { + listener.exitDoStatement(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitDoStatement) { + return visitor.visitDoStatement(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class SubroutineCallContext extends ParserRuleContext { + public IDENTIFIER(): TerminalNode[]; + public IDENTIFIER(i: number): TerminalNode; + public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.IDENTIFIER); + } else { + return this.getToken(JackParser.IDENTIFIER, i); + } + } + public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } + public expressionList(): ExpressionListContext { + return this.getRuleContext(0, ExpressionListContext); + } + public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } + public DOT(): TerminalNode | undefined { return this.tryGetToken(JackParser.DOT, 0); } + public THIS_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.THIS_LITERAL, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_subroutineCall; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineCall) { + listener.enterSubroutineCall(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineCall) { + listener.exitSubroutineCall(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitSubroutineCall) { + return visitor.visitSubroutineCall(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ReturnStatementContext extends ParserRuleContext { + public RETURN(): TerminalNode { return this.getToken(JackParser.RETURN, 0); } + public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } + public expression(): ExpressionContext | undefined { + return this.tryGetRuleContext(0, ExpressionContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_returnStatement; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterReturnStatement) { + listener.enterReturnStatement(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitReturnStatement) { + listener.exitReturnStatement(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitReturnStatement) { + return visitor.visitReturnStatement(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ExpressionListContext extends ParserRuleContext { + public expression(): ExpressionContext[]; + public expression(i: number): ExpressionContext; + public expression(i?: number): ExpressionContext | ExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(ExpressionContext); + } else { + return this.getRuleContext(i, ExpressionContext); + } + } + public COMMA(): TerminalNode[]; + public COMMA(i: number): TerminalNode; + public COMMA(i?: number): TerminalNode | TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_expressionList; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterExpressionList) { + listener.enterExpressionList(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitExpressionList) { + listener.exitExpressionList(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitExpressionList) { + return visitor.visitExpressionList(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ExpressionContext extends ParserRuleContext { + public _binaryOperation!: ExpressionContext; + public binaryOperator(): BinaryOperatorContext | undefined { + return this.tryGetRuleContext(0, BinaryOperatorContext); + } + public expression(): ExpressionContext[]; + public expression(i: number): ExpressionContext; + public expression(i?: number): ExpressionContext | ExpressionContext[] { + if (i === undefined) { + return this.getRuleContexts(ExpressionContext); + } else { + return this.getRuleContext(i, ExpressionContext); + } + } + public constant(): ConstantContext | undefined { + return this.tryGetRuleContext(0, ConstantContext); + } + public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(JackParser.IDENTIFIER, 0); } + public subroutineCall(): SubroutineCallContext | undefined { + return this.tryGetRuleContext(0, SubroutineCallContext); + } + public arrayAccess(): ArrayAccessContext | undefined { + return this.tryGetRuleContext(0, ArrayAccessContext); + } + public unaryOp(): UnaryOpContext | undefined { + return this.tryGetRuleContext(0, UnaryOpContext); + } + public groupedExpression(): GroupedExpressionContext | undefined { + return this.tryGetRuleContext(0, GroupedExpressionContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_expression; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterExpression) { + listener.enterExpression(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitExpression) { + listener.exitExpression(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitExpression) { + return visitor.visitExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class GroupedExpressionContext extends ParserRuleContext { + public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext); + } + public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_groupedExpression; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterGroupedExpression) { + listener.enterGroupedExpression(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitGroupedExpression) { + listener.exitGroupedExpression(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitGroupedExpression) { + return visitor.visitGroupedExpression(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UnaryOpContext extends ParserRuleContext { + public unaryOperator(): UnaryOperatorContext { + return this.getRuleContext(0, UnaryOperatorContext); + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_unaryOp; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterUnaryOp) { + listener.enterUnaryOp(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitUnaryOp) { + listener.exitUnaryOp(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitUnaryOp) { + return visitor.visitUnaryOp(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ArrayAccessContext extends ParserRuleContext { + public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } + public LBRACKET(): TerminalNode { return this.getToken(JackParser.LBRACKET, 0); } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext); + } + public RBRACKET(): TerminalNode { return this.getToken(JackParser.RBRACKET, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_arrayAccess; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterArrayAccess) { + listener.enterArrayAccess(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitArrayAccess) { + listener.exitArrayAccess(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitArrayAccess) { + return visitor.visitArrayAccess(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ConstantContext extends ParserRuleContext { + public INTEGER_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.INTEGER_LITERAL, 0); } + public STRING_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.STRING_LITERAL, 0); } + public BOOLEAN_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.BOOLEAN_LITERAL, 0); } + public NULL_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.NULL_LITERAL, 0); } + public THIS_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.THIS_LITERAL, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_constant; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterConstant) { + listener.enterConstant(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitConstant) { + listener.exitConstant(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitConstant) { + return visitor.visitConstant(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class UnaryOperatorContext extends ParserRuleContext { + public TILDE(): TerminalNode | undefined { return this.tryGetToken(JackParser.TILDE, 0); } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(JackParser.MINUS, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_unaryOperator; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterUnaryOperator) { + listener.enterUnaryOperator(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitUnaryOperator) { + listener.exitUnaryOperator(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitUnaryOperator) { + return visitor.visitUnaryOperator(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class BinaryOperatorContext extends ParserRuleContext { + public PLUS(): TerminalNode | undefined { return this.tryGetToken(JackParser.PLUS, 0); } + public MINUS(): TerminalNode | undefined { return this.tryGetToken(JackParser.MINUS, 0); } + public MUL(): TerminalNode | undefined { return this.tryGetToken(JackParser.MUL, 0); } + public DIV(): TerminalNode | undefined { return this.tryGetToken(JackParser.DIV, 0); } + public AND(): TerminalNode | undefined { return this.tryGetToken(JackParser.AND, 0); } + public OR(): TerminalNode | undefined { return this.tryGetToken(JackParser.OR, 0); } + public LESS_THAN(): TerminalNode | undefined { return this.tryGetToken(JackParser.LESS_THAN, 0); } + public GREATER_THAN(): TerminalNode | undefined { return this.tryGetToken(JackParser.GREATER_THAN, 0); } + public EQUALS(): TerminalNode | undefined { return this.tryGetToken(JackParser.EQUALS, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_binaryOperator; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterBinaryOperator) { + listener.enterBinaryOperator(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitBinaryOperator) { + listener.exitBinaryOperator(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitBinaryOperator) { + return visitor.visitBinaryOperator(this); + } else { + return visitor.visitChildren(this); + } + } +} + + diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts new file mode 100644 index 00000000..36c33cfc --- /dev/null +++ b/compiler/src/generated/JackParserListener.ts @@ -0,0 +1,479 @@ +// Generated from JackParser.g4 by ANTLR 4.9.0-SNAPSHOT + + +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; + +import { ConstructorContext } from "./JackParser"; +import { MethodContext } from "./JackParser"; +import { FunctionContext } from "./JackParser"; +import { StaticFieldDeclarationContext } from "./JackParser"; +import { FieldDeclarationContext } from "./JackParser"; +import { ProgramContext } from "./JackParser"; +import { ClassDeclarationContext } from "./JackParser"; +import { ClassNameContext } from "./JackParser"; +import { ClassVarDecContext } from "./JackParser"; +import { FieldListContext } from "./JackParser"; +import { FieldNameContext } from "./JackParser"; +import { SubroutineDecContext } from "./JackParser"; +import { SubroutineDecWithoutTypeContext } from "./JackParser"; +import { SubroutineNameContext } from "./JackParser"; +import { SubroutineReturnTypeContext } from "./JackParser"; +import { VarTypeContext } from "./JackParser"; +import { ParameterListContext } from "./JackParser"; +import { ParameterContext } from "./JackParser"; +import { ParameterNameContext } from "./JackParser"; +import { SubroutineBodyContext } from "./JackParser"; +import { VarDecContext } from "./JackParser"; +import { VarNameContext } from "./JackParser"; +import { StatementsContext } from "./JackParser"; +import { StatementContext } from "./JackParser"; +import { LetStatementContext } from "./JackParser"; +import { IfStatementContext } from "./JackParser"; +import { WhileStatementContext } from "./JackParser"; +import { DoStatementContext } from "./JackParser"; +import { SubroutineCallContext } from "./JackParser"; +import { ReturnStatementContext } from "./JackParser"; +import { ExpressionListContext } from "./JackParser"; +import { ExpressionContext } from "./JackParser"; +import { GroupedExpressionContext } from "./JackParser"; +import { UnaryOpContext } from "./JackParser"; +import { ArrayAccessContext } from "./JackParser"; +import { ConstantContext } from "./JackParser"; +import { UnaryOperatorContext } from "./JackParser"; +import { BinaryOperatorContext } from "./JackParser"; + + +/** + * This interface defines a complete listener for a parse tree produced by + * `JackParser`. + */ +export interface JackParserListener extends ParseTreeListener { + /** + * Enter a parse tree produced by the `constructor` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + */ + enterConstructor?: (ctx: ConstructorContext) => void; + /** + * Exit a parse tree produced by the `constructor` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + */ + exitConstructor?: (ctx: ConstructorContext) => void; + + /** + * Enter a parse tree produced by the `method` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + */ + enterMethod?: (ctx: MethodContext) => void; + /** + * Exit a parse tree produced by the `method` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + */ + exitMethod?: (ctx: MethodContext) => void; + + /** + * Enter a parse tree produced by the `function` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + */ + enterFunction?: (ctx: FunctionContext) => void; + /** + * Exit a parse tree produced by the `function` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + */ + exitFunction?: (ctx: FunctionContext) => void; + + /** + * Enter a parse tree produced by the `staticFieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. + * @param ctx the parse tree + */ + enterStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => void; + /** + * Exit a parse tree produced by the `staticFieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. + * @param ctx the parse tree + */ + exitStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => void; + + /** + * Enter a parse tree produced by the `fieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. + * @param ctx the parse tree + */ + enterFieldDeclaration?: (ctx: FieldDeclarationContext) => void; + /** + * Exit a parse tree produced by the `fieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. + * @param ctx the parse tree + */ + exitFieldDeclaration?: (ctx: FieldDeclarationContext) => void; + + /** + * Enter a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + enterProgram?: (ctx: ProgramContext) => void; + /** + * Exit a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + exitProgram?: (ctx: ProgramContext) => void; + + /** + * Enter a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; + + /** + * Enter a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + enterClassName?: (ctx: ClassNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + exitClassName?: (ctx: ClassNameContext) => void; + + /** + * Enter a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + enterClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Exit a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + exitClassVarDec?: (ctx: ClassVarDecContext) => void; + + /** + * Enter a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + enterFieldList?: (ctx: FieldListContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + exitFieldList?: (ctx: FieldListContext) => void; + + /** + * Enter a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + enterFieldName?: (ctx: FieldNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + exitFieldName?: (ctx: FieldNameContext) => void; + + /** + * Enter a parse tree produced by `JackParser.subroutineDec`. + * @param ctx the parse tree + */ + enterSubroutineDec?: (ctx: SubroutineDecContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDec`. + * @param ctx the parse tree + */ + exitSubroutineDec?: (ctx: SubroutineDecContext) => void; + + /** + * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + enterSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; + + /** + * Enter a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + enterSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + exitSubroutineName?: (ctx: SubroutineNameContext) => void; + + /** + * Enter a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + + /** + * Enter a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + enterVarType?: (ctx: VarTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + exitVarType?: (ctx: VarTypeContext) => void; + + /** + * Enter a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + enterParameterList?: (ctx: ParameterListContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + exitParameterList?: (ctx: ParameterListContext) => void; + + /** + * Enter a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + enterParameter?: (ctx: ParameterContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + exitParameter?: (ctx: ParameterContext) => void; + + /** + * Enter a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + enterParameterName?: (ctx: ParameterNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + exitParameterName?: (ctx: ParameterNameContext) => void; + + /** + * Enter a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; + + /** + * Enter a parse tree produced by `JackParser.varDec`. + * @param ctx the parse tree + */ + enterVarDec?: (ctx: VarDecContext) => void; + /** + * Exit a parse tree produced by `JackParser.varDec`. + * @param ctx the parse tree + */ + exitVarDec?: (ctx: VarDecContext) => void; + + /** + * Enter a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + enterVarName?: (ctx: VarNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + exitVarName?: (ctx: VarNameContext) => void; + + /** + * Enter a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + enterStatements?: (ctx: StatementsContext) => void; + /** + * Exit a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + exitStatements?: (ctx: StatementsContext) => void; + + /** + * Enter a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + enterStatement?: (ctx: StatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + exitStatement?: (ctx: StatementContext) => void; + + /** + * Enter a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + enterLetStatement?: (ctx: LetStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + exitLetStatement?: (ctx: LetStatementContext) => void; + + /** + * Enter a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + enterIfStatement?: (ctx: IfStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + exitIfStatement?: (ctx: IfStatementContext) => void; + + /** + * Enter a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + enterWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + exitWhileStatement?: (ctx: WhileStatementContext) => void; + + /** + * Enter a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + enterDoStatement?: (ctx: DoStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + exitDoStatement?: (ctx: DoStatementContext) => void; + + /** + * Enter a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + enterSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + exitSubroutineCall?: (ctx: SubroutineCallContext) => void; + + /** + * Enter a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + enterReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + exitReturnStatement?: (ctx: ReturnStatementContext) => void; + + /** + * Enter a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + enterExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Exit a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + exitExpressionList?: (ctx: ExpressionListContext) => void; + + /** + * Enter a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + enterExpression?: (ctx: ExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + exitExpression?: (ctx: ExpressionContext) => void; + + /** + * Enter a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; + + /** + * Enter a parse tree produced by `JackParser.unaryOp`. + * @param ctx the parse tree + */ + enterUnaryOp?: (ctx: UnaryOpContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOp`. + * @param ctx the parse tree + */ + exitUnaryOp?: (ctx: UnaryOpContext) => void; + + /** + * Enter a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + enterArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Exit a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + exitArrayAccess?: (ctx: ArrayAccessContext) => void; + + /** + * Enter a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + enterConstant?: (ctx: ConstantContext) => void; + /** + * Exit a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + exitConstant?: (ctx: ConstantContext) => void; + + /** + * Enter a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; + + /** + * Enter a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; +} + diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts new file mode 100644 index 00000000..1317cc2c --- /dev/null +++ b/compiler/src/generated/JackParserVisitor.ts @@ -0,0 +1,325 @@ +// Generated from JackParser.g4 by ANTLR 4.9.0-SNAPSHOT + + +import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; + +import { ConstructorContext } from "./JackParser"; +import { MethodContext } from "./JackParser"; +import { FunctionContext } from "./JackParser"; +import { StaticFieldDeclarationContext } from "./JackParser"; +import { FieldDeclarationContext } from "./JackParser"; +import { ProgramContext } from "./JackParser"; +import { ClassDeclarationContext } from "./JackParser"; +import { ClassNameContext } from "./JackParser"; +import { ClassVarDecContext } from "./JackParser"; +import { FieldListContext } from "./JackParser"; +import { FieldNameContext } from "./JackParser"; +import { SubroutineDecContext } from "./JackParser"; +import { SubroutineDecWithoutTypeContext } from "./JackParser"; +import { SubroutineNameContext } from "./JackParser"; +import { SubroutineReturnTypeContext } from "./JackParser"; +import { VarTypeContext } from "./JackParser"; +import { ParameterListContext } from "./JackParser"; +import { ParameterContext } from "./JackParser"; +import { ParameterNameContext } from "./JackParser"; +import { SubroutineBodyContext } from "./JackParser"; +import { VarDecContext } from "./JackParser"; +import { VarNameContext } from "./JackParser"; +import { StatementsContext } from "./JackParser"; +import { StatementContext } from "./JackParser"; +import { LetStatementContext } from "./JackParser"; +import { IfStatementContext } from "./JackParser"; +import { WhileStatementContext } from "./JackParser"; +import { DoStatementContext } from "./JackParser"; +import { SubroutineCallContext } from "./JackParser"; +import { ReturnStatementContext } from "./JackParser"; +import { ExpressionListContext } from "./JackParser"; +import { ExpressionContext } from "./JackParser"; +import { GroupedExpressionContext } from "./JackParser"; +import { UnaryOpContext } from "./JackParser"; +import { ArrayAccessContext } from "./JackParser"; +import { ConstantContext } from "./JackParser"; +import { UnaryOperatorContext } from "./JackParser"; +import { BinaryOperatorContext } from "./JackParser"; + + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by `JackParser`. + * + * @param The return type of the visit operation. Use `void` for + * operations with no return type. + */ +export interface JackParserVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by the `constructor` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + * @return the visitor result + */ + visitConstructor?: (ctx: ConstructorContext) => Result; + + /** + * Visit a parse tree produced by the `method` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + * @return the visitor result + */ + visitMethod?: (ctx: MethodContext) => Result; + + /** + * Visit a parse tree produced by the `function` + * labeled alternative in `JackParser.subroutineDec`. + * @param ctx the parse tree + * @return the visitor result + */ + visitFunction?: (ctx: FunctionContext) => Result; + + /** + * Visit a parse tree produced by the `staticFieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => Result; + + /** + * Visit a parse tree produced by the `fieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. + * @param ctx the parse tree + * @return the visitor result + */ + visitFieldDeclaration?: (ctx: FieldDeclarationContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + * @return the visitor result + */ + visitProgram?: (ctx: ProgramContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + * @return the visitor result + */ + visitClassDeclaration?: (ctx: ClassDeclarationContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + * @return the visitor result + */ + visitClassName?: (ctx: ClassNameContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + * @return the visitor result + */ + visitClassVarDec?: (ctx: ClassVarDecContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitFieldList?: (ctx: FieldListContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + * @return the visitor result + */ + visitFieldName?: (ctx: FieldNameContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.subroutineDec`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSubroutineDec?: (ctx: SubroutineDecContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSubroutineName?: (ctx: SubroutineNameContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVarType?: (ctx: VarTypeContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitParameterList?: (ctx: ParameterListContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + * @return the visitor result + */ + visitParameter?: (ctx: ParameterContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + * @return the visitor result + */ + visitParameterName?: (ctx: ParameterNameContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSubroutineBody?: (ctx: SubroutineBodyContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.varDec`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVarDec?: (ctx: VarDecContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVarName?: (ctx: VarNameContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStatements?: (ctx: StatementsContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitStatement?: (ctx: StatementContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitLetStatement?: (ctx: LetStatementContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIfStatement?: (ctx: IfStatementContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitWhileStatement?: (ctx: WhileStatementContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitDoStatement?: (ctx: DoStatementContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSubroutineCall?: (ctx: SubroutineCallContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitReturnStatement?: (ctx: ReturnStatementContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + * @return the visitor result + */ + visitExpressionList?: (ctx: ExpressionListContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitExpression?: (ctx: ExpressionContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + * @return the visitor result + */ + visitGroupedExpression?: (ctx: GroupedExpressionContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.unaryOp`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUnaryOp?: (ctx: UnaryOpContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + * @return the visitor result + */ + visitArrayAccess?: (ctx: ArrayAccessContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + * @return the visitor result + */ + visitConstant?: (ctx: ConstantContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + * @return the visitor result + */ + visitUnaryOperator?: (ctx: UnaryOperatorContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + * @return the visitor result + */ + visitBinaryOperator?: (ctx: BinaryOperatorContext) => Result; +} + diff --git a/compiler/src/main.ts b/compiler/src/main.ts new file mode 100644 index 00000000..b1176014 --- /dev/null +++ b/compiler/src/main.ts @@ -0,0 +1,18 @@ +import Compiler from "./compiler"; + +function compile() { + console.log('Compiling ...'); + const code = document.querySelector('#input')?.value ?? ""; + const res = Compiler.compile(code); + console.log(res); + document.querySelector('#output')!.value = res; +} +document.querySelector('#compile')?.addEventListener('click', () => compile()); + +// function error(line: number, message: string): string { +// return report(line, "", message); +// } + +// function report(line: number, where: string, message: string): string { +// return `[line ${line} Error ${where}:${message}`; +// } diff --git a/compiler/src/symbol.table.istener.ts b/compiler/src/symbol.table.istener.ts new file mode 100644 index 00000000..f8ee0602 --- /dev/null +++ b/compiler/src/symbol.table.istener.ts @@ -0,0 +1,97 @@ +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { ClassDeclarationContext, ClassVarDecContext, ConstructorContext, FunctionContext, JackParser, MethodContext, StaticFieldDeclarationContext, SubroutineDecContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDecContext, VarTypeContext } from "./generated/JackParser"; +import { JackParserListener } from "./generated/JackParserListener"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; + +const primitives = new Set(["int", "boolean", "char"] as const); +export type Primitive = typeof primitives extends Set ? S : never; + +/** + * Generic symbol. Can be used for both class and function symbols + */ +interface GenericSymbol extends Symbol { + subroutineParameterCount?: number; +} +/** + * Symbol table. Key represents class name or . + */ +interface SymbolTale { + [key: string]: GenericSymbol; +} + +export class SymbolTableListener implements JackParserListener, ParseTreeListener { + + //wh do we need that? + // to check if symbol exists (function or class) and also check subroutine declaration so that we are are supplying right ammount of params + public globalSymbolTable: SymbolTale = {}; + //track class variables, local vars, function args + // localSymbolTable = []; + className = ""; + public errors: string[] = [] + // fix compiler error + visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; + + enterClassDeclaration(ctx: ClassDeclarationContext) { + if (this.globalSymbolTable[ctx.className()!.text] != undefined) { + this.errors.push(`Class "${ctx.className()!.text}" already defined.`); + return; + } + this.globalSymbolTable[ctx.className()!.text] = {} as GenericSymbol; + this.className = ctx.className()?.text; + console.log(`Entering class ${ctx.className()?.text}`); + }; + enterStaticFieldDeclaration(ctx: StaticFieldDeclarationContext) { + const fieldList = ctx.fieldList(); + console.log(`static field: ${fieldList.varType().text} ${fieldList.fieldName().map(t => t.text).join(",")}`); + }; + + + enterVarDec(ctx: VarDecContext) { + const names = ctx.IDENTIFIER(); + console.log(`Function var: ${this.getType(ctx.varType())} ${names.join(",")}`); + }; + + enterConstructor(ctx: ConstructorContext) { + this.addSymbol(ctx.subroutineDecWithoutType()) + this.printSubroutine("Ctor", ctx.subroutineDecWithoutType()) + }; + addSymbol(c: SubroutineDecWithoutTypeContext) { + const subroutineName = c.subroutineName().text + const id = this.className + "." + subroutineName + if (this.globalSymbolTable[id] != undefined) { + this.errors.push(`Subroutine "${subroutineName}" is already defined.`); + } + this.globalSymbolTable[id] = { + subroutineParameterCount: c.parameterList().parameter().length + } as GenericSymbol; + } + enterMethod(ctx: MethodContext) { + this.addSymbol(ctx.subroutineDecWithoutType()) + this.printSubroutine("Method", ctx.subroutineDecWithoutType()) + }; + enterFunction(ctx: FunctionContext) { + this.addSymbol(ctx.subroutineDecWithoutType()) + this.printSubroutine("Function", ctx.subroutineDecWithoutType()) + }; + + printSubroutine(type: string, c: SubroutineDecWithoutTypeContext) { + const returnType = this.getSubroutineReturnType(c.subroutineReturnType()) + const paramList = c.parameterList().parameter().map(t => t.varType().text + " " + t.parameterName().text).join(","); + console.log(`${type}: ${returnType} ${c.subroutineName().text} (${paramList})`); + } + + getType(ctx: VarTypeContext): string { + return ctx.BOOLEAN() ? "boolean" : + ctx.INT() ? "int" : + ctx.CHAR() ? "char" : + ctx.IDENTIFIER() ? ctx.IDENTIFIER()!.text : + "unknown"; + } + + getSubroutineReturnType(ctx: SubroutineReturnTypeContext): string { + return ctx.VOID() ? "void" : this.getType(ctx.varType()!); + } + resetErrors() { + this.errors = []; + } +} diff --git a/compiler/src/symbol.table.ts b/compiler/src/symbol.table.ts new file mode 100644 index 00000000..b0f84a5a --- /dev/null +++ b/compiler/src/symbol.table.ts @@ -0,0 +1,26 @@ +export enum Scope { + local, + static, + argument, +} +export class SymbolTableEntry { + constructor(public name: string, public type: string, public scope: Scope) { + + } +} +export class SymbolTable { + constructor(private entries: SymbolTableEntry[] = [], private scopes: Scope[] = [], private scopeStack: Scope[] = []) { } + insert(entry: SymbolTableEntry) { + this.entries.push(entry); + } + lookup(name: string) { + //TODO: look for entries in enclosed scopes + return this.entries.find(entry => entry.name === name); + } + pushScope(scope: Scope) { + this.scopeStack.push(scope); + } + popScope() { + this.scopeStack.pop(); + } +} \ No newline at end of file diff --git a/compiler/src/vite-env.d.ts b/compiler/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/compiler/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts new file mode 100644 index 00000000..6e15a3f5 --- /dev/null +++ b/compiler/test/parser.test.ts @@ -0,0 +1,87 @@ +import { JackLexer } from "../src/generated/JackLexer"; +import { JackParser } from "../src/generated/JackParser"; +import { SymbolTableListener } from "../src/symbol.table.istener"; +import fs from 'fs'; +import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker' + +import { CommonTokenStream, BufferedTokenStream, CharStreams } from 'antlr4ts'; +import path from "path"; +import { ErrorListener } from "../src/error.listener"; +describe('Parser', () => { + const jestConsole = console; + + beforeEach(() => { + global.console = require('console'); + }); + + afterEach(() => { + global.console = jestConsole; + }); + const dirs: string[] = [ + "Average", + "ConvertToBin", + "Fraction", + "HelloWorld", + "List", + "Pong", + "Square" + ] + test.each(dirs)('%s', (dir: string) => { + console.log("Testing " + dir) + testJack(dir); + // console.log("File", f) + }); + +}); +function testJack(testName: string, trace = false) { + var filePath = path.join(__dirname, "resources", testName); + testJackDir(filePath); +} +function testJackDir(testFolder: string) { + + const globalSymbolsListener = new SymbolTableListener(); + const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); + for (const filePath of files) { + + const f = fs.readFileSync(filePath, 'utf8'); + // console.log(f); + // Create the lexer and parser + const inputStream = CharStreams.fromString(f); + const lexer = new JackLexer(inputStream); + const errorListener = ErrorListener.getInstance(); + errorListener.filepath = filePath; + lexer.removeErrorListeners(); + lexer.addErrorListener(errorListener); + + const tokenStream = new CommonTokenStream(lexer); + // const tokens = tokenStream.getTokens() + // console.log("Tokens ", ) + expect(tokenStream.getTokens.length).toBeGreaterThan(0) + const parser = new JackParser(tokenStream); + // parser.isTrace = true; + parser.removeErrorListeners(); + parser.addErrorListener(errorListener); + // Parse the input, where `compilationUnit` is whatever entry point you defined + const tree = parser.program(); + // expect(errorListener.error).toBe(false) + // console.log(tree.toStringTree(parser.ruleNames)); + + // Create the visitor + // const v = new Visitor(); + // // Use the visitor entry point + // const res = v.visit(tree); + // console.log("Res", res); + ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); + const symbolsErrors = globalSymbolsListener.errors.join("\n") + try { + expect(globalSymbolsListener.errors.length,).toBe(0) + } + catch (e) { + throw new Error(symbolsErrors); + } + + globalSymbolsListener.resetErrors(); + + } + console.log("GlobalSymbolTable", globalSymbolsListener.globalSymbolTable) +} \ No newline at end of file diff --git a/compiler/test/resources/Average/Main.jack b/compiler/test/resources/Average/Main.jack new file mode 100644 index 00000000..d53093a2 --- /dev/null +++ b/compiler/test/resources/Average/Main.jack @@ -0,0 +1,27 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Average/Main.jack + +// Inputs some numbers and computes their average +class Main { + function void main() { + var Array a; + var int length; + var int i, sum; + + let length = Keyboard.readInt("How many numbers? "); + let a = Array.new(length); // constructs the array + + let i = 0; + while (i < length) { + let a[i] = Keyboard.readInt("Enter a number: "); + let sum = sum + a[i]; + let i = i + 1; + } + + do Output.printString("The average is "); + do Output.printInt(sum / length); + return; + } +} diff --git a/compiler/test/resources/ComplexArrays/Main.jack b/compiler/test/resources/ComplexArrays/Main.jack new file mode 100644 index 00000000..b4d7dca2 --- /dev/null +++ b/compiler/test/resources/ComplexArrays/Main.jack @@ -0,0 +1,69 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/ComplexArrays/Main.jack +/** + * Performs several complex array processing tests. + * For each test, the expected result is printed, along with the + * actual result. In each test, the two results should be equal. + */ +class Main { + + function void main() { + var Array a, b, c; + + let a = Array.new(10); + let b = Array.new(5); + let c = Array.new(1); + + let a[3] = 2; + let a[4] = 8; + let a[5] = 4; + let b[a[3]] = a[3] + 3; // b[2] = 5 + let a[b[a[3]]] = a[a[5]] * b[((7 - a[3]) - Main.double(2)) + 1]; // a[5] = 8 * 5 = 40 + let c[0] = null; + let c = c[0]; + + do Output.printString("Test 1: expected result: 5; actual result: "); + do Output.printInt(b[2]); + do Output.println(); + do Output.printString("Test 2: expected result: 40; actual result: "); + do Output.printInt(a[5]); + do Output.println(); + do Output.printString("Test 3: expected result: 0; actual result: "); + do Output.printInt(c); + do Output.println(); + + let c = null; + + if (c = null) { + do Main.fill(a, 10); + let c = a[3]; + let c[1] = 33; + let c = a[7]; + let c[1] = 77; + let b = a[3]; + let b[1] = b[1] + c[1]; // b[1] = 33 + 77 = 110; + } + + do Output.printString("Test 4: expected result: 77; actual result: "); + do Output.printInt(c[1]); + do Output.println(); + do Output.printString("Test 5: expected result: 110; actual result: "); + do Output.printInt(b[1]); + do Output.println(); + return; + } + + function int double(int a) { + return a * 2; + } + + function void fill(Array a, int size) { + while (size > 0) { + let size = size - 1; + let a[size] = Array.new(3); + } + return; + } +} diff --git a/compiler/test/resources/ConvertToBin/Main.jack b/compiler/test/resources/ConvertToBin/Main.jack new file mode 100644 index 00000000..12ce3ce6 --- /dev/null +++ b/compiler/test/resources/ConvertToBin/Main.jack @@ -0,0 +1,79 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/ConvertToBin/Main.jack +/** + * Unpacks a 16-bit number into its binary representation: + * Takes the 16-bit number stored in RAM[8000] and stores its individual + * bits in RAM[8001]..RAM[8016] (each location will contain 0 or 1). + * Before the conversion, RAM[8001]..RAM[8016] are initialized to -1. + * + * The program should be tested as follows: + * 1) Load the compiled program into the supplied VM emulator + * 2) Put some value in RAM[8000] + * 3) Switch to "no animation" + * 4) Run the program (give it enough time to run) + * 5) Stop the program + * 6) Check that RAM[8001]..RAM[8016] contains the correct binary result, and + * that none of these memory locations contains -1. + */ +class Main { + /** Initializes RAM[8001]..RAM[8016] to -1, + * and converts the value in RAM[8000] to binary. */ + function void main() { + var int value; + do Main.fillMemory(8001, 16, -1); // sets RAM[8001]..RAM[8016] to -1 + let value = Memory.peek(8000); // reads a value from RAM[8000] + do Main.convert(value); // performs the conversion + return; + } + + /** Converts the given decimal value to binary, and puts + * the resulting bits in RAM[8001]..RAM[8016]. */ + function void convert(int value) { + var int mask, position; + var boolean loop; + + let loop = true; + while (loop) { + let position = position + 1; + let mask = Main.nextMask(mask); + + if (~(position > 16)) { + + if (~((value & mask) = 0)) { + do Memory.poke(8000 + position, 1); + } + else { + do Memory.poke(8000 + position, 0); + } + } + else { + let loop = false; + } + } + return; + } + + /** Returns the next mask (the mask that should follow the given mask). */ + function int nextMask(int mask) { + if (mask = 0) { + return 1; + } + else { + return mask * 2; + } + } + + /** Fills 'length' consecutive memory locations with 'value', + * starting at 'startAddress'. */ + function void fillMemory(int startAddress, int length, int value) { + while (length > 0) { + do Memory.poke(startAddress, value); + let length = length - 1; + let startAddress = startAddress + 1; + } + return; + } + +} diff --git a/compiler/test/resources/Fraction/Fraction.jack b/compiler/test/resources/Fraction/Fraction.jack new file mode 100644 index 00000000..939df83f --- /dev/null +++ b/compiler/test/resources/Fraction/Fraction.jack @@ -0,0 +1,65 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Fraction/Fraction.jack + +/** Represents the Fraction type and related operations. */ +class Fraction { + field int numerator, denominator; // field = property = member variable. + + /** Constructs a (reduced) fraction from the given numerator and denominator. */ + constructor Fraction new(int x, int y) { + let numerator = x; + let denominator = y; + do reduce(); // reduces the fraction + return this; // a constructor is expected to return a reference to the new object + } + + // Reduces this fraction. + method void reduce() { + var int g; + let g = Fraction.gcd(numerator, denominator); + if (g > 1) { + let numerator = numerator / g; + let denominator = denominator / g; + } + return; + } + + /** Accessors. */ + method int getNumerator() { return numerator; } + method int getDenominator() { return denominator; } + + /** Returns the sum of this fraction and the other one. */ + method Fraction plus(Fraction other) { + var int sum; + let sum = (numerator * other.getDenominator()) + (other.getNumerator() * denominator); + return Fraction.new(sum, denominator * other.getDenominator()); + } + + // More fraction-related methods (minus, times, div, invert, etc.) can be added here. + + /** Disposes this fraction. */ + method void dispose() { + do Memory.deAlloc(this); // uses an OS routine to recycle the memory held by the object + return; + } + + /** Prints this fraction in the format x/y. */ + method void print() { + do Output.printInt(numerator); + do Output.printString("/"); + do Output.printInt(denominator); + return; + } + + // Computes the greatest common divisor of the given integers. + function int gcd(int a, int b) { + var int r; + while (~(b = 0)) { // applies Euclid's algorithm + let r = a - (b * (a / b)); // r = remainder of the integer division a/b + let a = b; let b = r; + } + return a; + } +} diff --git a/compiler/test/resources/Fraction/Main.jack b/compiler/test/resources/Fraction/Main.jack new file mode 100644 index 00000000..293bc917 --- /dev/null +++ b/compiler/test/resources/Fraction/Main.jack @@ -0,0 +1,16 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Fraction/Main.jack + +// Computes and prints the sum of 2/3 and 1/5. +class Main { + function void main() { + var Fraction a, b, c; + let a = Fraction.new(2,3); + let b = Fraction.new(1,5); + let c = a.plus(b); // Computes c = a + b + do c.print(); // Prints "13/15" + return; + } +} diff --git a/compiler/test/resources/HelloWorld/Main.jack b/compiler/test/resources/HelloWorld/Main.jack new file mode 100644 index 00000000..6cb47f47 --- /dev/null +++ b/compiler/test/resources/HelloWorld/Main.jack @@ -0,0 +1,14 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/HelloWorld/Main.jack + +/** Hello World program. */ +class Main { + function void main() { + /* Prints some text using the standard library. */ + do Output.printString("Hello world!"); + do Output.println(); // New line + return; + } +} diff --git a/compiler/test/resources/List/List.jack b/compiler/test/resources/List/List.jack new file mode 100644 index 00000000..49bc54a8 --- /dev/null +++ b/compiler/test/resources/List/List.jack @@ -0,0 +1,48 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/List/List.jack + +/** Represents a linked list of integers. */ +class List { + field int data; // an int value, + field List next; // followed by a list of int values + + /* Creates a List. */ + constructor List new(int car, List cdr) { + let data = car; // the identifiers car and cdr are used in + let next = cdr; // memory of the Lisp programming language + return this; + } + + /** Accessors. */ + method int getData() { return data; } + method int getNext() { return next; } + + /** Prints this list. */ + method void print() { + // Sets current to the first element of this list + var List current; + let current = this; + while (~(current = null)) { + do Output.printInt(current.getData()); + do Output.printChar(32); // prints a space + let current = current.getNext(); + } + return; + } + + /** Disposes this List. */ + // By recursively disposing its tail. + method void dispose() { + if (~(next = null)) { + do next.dispose(); + } + // Calls an OS routine to free the memory of this object. + do Memory.deAlloc(this); + return; + } + + // More list processing methods can come here. + +} diff --git a/compiler/test/resources/List/Main.jack b/compiler/test/resources/List/Main.jack new file mode 100644 index 00000000..54a39a97 --- /dev/null +++ b/compiler/test/resources/List/Main.jack @@ -0,0 +1,17 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/List/Main.jack + +/** An example of creating and using List objects. */ +class Main { + function void main() { + // Creates and uses the list (2,3,5). + var List v; + let v = List.new(5,null); + let v = List.new(2,List.new(3,v)); + do v.print(); // prints 2 3 5 + do v.dispose(); // disposes the list + return; + } +} diff --git a/compiler/test/resources/Pong/Ball.jack b/compiler/test/resources/Pong/Ball.jack new file mode 100644 index 00000000..f65a9075 --- /dev/null +++ b/compiler/test/resources/Pong/Ball.jack @@ -0,0 +1,202 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Pong/Ball.jack +/** + * A graphical ball in a Pong game. Characterized by a screen location and + * distance of last destination. Has methods for drawing, erasing and moving + * on the screen. The ball is displayed as a filled, 6-by-6 pixles rectangle. + */ +class Ball { + + field int x, y; // the ball's screen location (in pixels) + field int lengthx, lengthy; // distance of last destination (in pixels) + + field int d, straightD, diagonalD; // used for straight line movement computation + field boolean invert, positivex, positivey; // (same) + + field int leftWall, rightWall, topWall, bottomWall; // wall locations + + field int wall; // last wall that the ball was bounced off of + + /** Constructs a new ball with the given initial location and wall locations. */ + constructor Ball new(int Ax, int Ay, + int AleftWall, int ArightWall, int AtopWall, int AbottomWall) { + let x = Ax; + let y = Ay; + let leftWall = AleftWall; + let rightWall = ArightWall - 6; // -6 for ball size + let topWall = AtopWall; + let bottomWall = AbottomWall - 6; // -6 for ball size + let wall = 0; + do show(); + return this; + } + + /** Deallocates the Ball's memory. */ + method void dispose() { + do Memory.deAlloc(this); + return; + } + + /** Shows the ball. */ + method void show() { + do Screen.setColor(true); + do draw(); + return; + } + + /** Hides the ball. */ + method void hide() { + do Screen.setColor(false); + do draw(); + return; + } + + /** Draws the ball. */ + method void draw() { + do Screen.drawRectangle(x, y, x + 5, y + 5); + return; + } + + /** Returns the ball's left edge. */ + method int getLeft() { + return x; + } + + /** Returns the ball's right edge. */ + method int getRight() { + return x + 5; + } + + /** Computes and sets the ball's destination. */ + method void setDestination(int destx, int desty) { + var int dx, dy, temp; + let lengthx = destx - x; + let lengthy = desty - y; + let dx = Math.abs(lengthx); + let dy = Math.abs(lengthy); + let invert = (dx < dy); + + if (invert) { + let temp = dx; // swap dx, dy + let dx = dy; + let dy = temp; + let positivex = (y < desty); + let positivey = (x < destx); + } + else { + let positivex = (x < destx); + let positivey = (y < desty); + } + + let d = (2 * dy) - dx; + let straightD = 2 * dy; + let diagonalD = 2 * (dy - dx); + + return; + } + + /** + * Moves the ball one step towards its destination. + * If the ball has reached a wall, returns 0. + * Else, returns a value according to the wall: + * 1 (left wall), 2 (right wall), 3 (top wall), 4 (bottom wall). + */ + method int move() { + + do hide(); + + if (d < 0) { let d = d + straightD; } + else { + let d = d + diagonalD; + + if (positivey) { + if (invert) { let x = x + 4; } + else { let y = y + 4; } + } + else { + if (invert) { let x = x - 4; } + else { let y = y - 4; } + } + } + + if (positivex) { + if (invert) { let y = y + 4; } + else { let x = x + 4; } + } + else { + if (invert) { let y = y - 4; } + else { let x = x - 4; } + } + + if (~(x > leftWall)) { + let wall = 1; + let x = leftWall; + } + if (~(x < rightWall)) { + let wall = 2; + let x = rightWall; + } + if (~(y > topWall)) { + let wall = 3; + let y = topWall; + } + if (~(y < bottomWall)) { + let wall = 4; + let y = bottomWall; + } + + do show(); + + return wall; + } + + /** + * Bounces off the current wall: sets the new destination + * of the ball according to the ball's angle and the given + * bouncing direction (-1/0/1=left/center/right or up/center/down). + */ + method void bounce(int bouncingDirection) { + var int newx, newy, divLengthx, divLengthy, factor; + + // Since results are too big, divides by 10 + let divLengthx = lengthx / 10; + let divLengthy = lengthy / 10; + if (bouncingDirection = 0) { let factor = 10; } + else { + if (((~(lengthx < 0)) & (bouncingDirection = 1)) | ((lengthx < 0) & (bouncingDirection = (-1)))) { + let factor = 20; // bounce direction is in ball direction + } + else { let factor = 5; } // bounce direction is against ball direction + } + + if (wall = 1) { + let newx = 506; + let newy = (divLengthy * (-50)) / divLengthx; + let newy = y + (newy * factor); + } + else { + if (wall = 2) { + let newx = 0; + let newy = (divLengthy * 50) / divLengthx; + let newy = y + (newy * factor); + } + else { + if (wall = 3) { + let newy = 250; + let newx = (divLengthx * (-25)) / divLengthy; + let newx = x + (newx * factor); + } + else { // assumes wall = 4 + let newy = 0; + let newx = (divLengthx * 25) / divLengthy; + let newx = x + (newx * factor); + } + } + } + + do setDestination(newx, newy); + return; + } +} diff --git a/compiler/test/resources/Pong/Ball.vm b/compiler/test/resources/Pong/Ball.vm new file mode 100644 index 00000000..9471908f --- /dev/null +++ b/compiler/test/resources/Pong/Ball.vm @@ -0,0 +1,435 @@ +function Ball.new 0 + push constant 15 + call Memory.alloc 1 + pop pointer 0 + push argument 0 + pop this 0 + push argument 1 + pop this 1 + push argument 2 + pop this 10 + push argument 3 + push constant 6 + sub + pop this 11 + push argument 4 + pop this 12 + push argument 5 + push constant 6 + sub + pop this 13 + push constant 0 + pop this 14 + push pointer 0 + call Ball.show 1 + pop temp 0 + push pointer 0 + return +function Ball.dispose 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Memory.deAlloc 1 + pop temp 0 + push constant 0 + return +function Ball.show 0 + push argument 0 + pop pointer 0 + push constant 1 + neg + call Screen.setColor 1 + pop temp 0 + push pointer 0 + call Ball.draw 1 + pop temp 0 + push constant 0 + return +function Ball.hide 0 + push argument 0 + pop pointer 0 + push constant 0 + call Screen.setColor 1 + pop temp 0 + push pointer 0 + call Ball.draw 1 + pop temp 0 + push constant 0 + return +function Ball.draw 0 + push argument 0 + pop pointer 0 + push this 0 + push this 1 + push this 0 + push constant 5 + add + push this 1 + push constant 5 + add + call Screen.drawRectangle 4 + pop temp 0 + push constant 0 + return +function Ball.getLeft 0 + push argument 0 + pop pointer 0 + push this 0 + return +function Ball.getRight 0 + push argument 0 + pop pointer 0 + push this 0 + push constant 5 + add + return +function Ball.setDestination 3 + push argument 0 + pop pointer 0 + push argument 1 + push this 0 + sub + pop this 2 + push argument 2 + push this 1 + sub + pop this 3 + push this 2 + call Math.abs 1 + pop local 0 + push this 3 + call Math.abs 1 + pop local 1 + push local 0 + push local 1 + lt + pop this 7 + push this 7 + not + if-goto L1 + push local 0 + pop local 2 + push local 1 + pop local 0 + push local 2 + pop local 1 + push this 1 + push argument 2 + lt + pop this 8 + push this 0 + push argument 1 + lt + pop this 9 + goto L0 +label L1 + push this 0 + push argument 1 + lt + pop this 8 + push this 1 + push argument 2 + lt + pop this 9 +label L0 + push constant 2 + push local 1 + call Math.multiply 2 + push local 0 + sub + pop this 4 + push constant 2 + push local 1 + call Math.multiply 2 + pop this 5 + push constant 2 + push local 1 + push local 0 + sub + call Math.multiply 2 + pop this 6 + push constant 0 + return +function Ball.move 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Ball.hide 1 + pop temp 0 + push this 4 + push constant 0 + lt + not + if-goto L3 + push this 4 + push this 5 + add + pop this 4 + goto L2 +label L3 + push this 4 + push this 6 + add + pop this 4 + push this 9 + not + if-goto L5 + push this 7 + not + if-goto L7 + push this 0 + push constant 4 + add + pop this 0 + goto L6 +label L7 + push this 1 + push constant 4 + add + pop this 1 +label L6 + goto L4 +label L5 + push this 7 + not + if-goto L9 + push this 0 + push constant 4 + sub + pop this 0 + goto L8 +label L9 + push this 1 + push constant 4 + sub + pop this 1 +label L8 +label L4 +label L2 + push this 8 + not + if-goto L11 + push this 7 + not + if-goto L13 + push this 1 + push constant 4 + add + pop this 1 + goto L12 +label L13 + push this 0 + push constant 4 + add + pop this 0 +label L12 + goto L10 +label L11 + push this 7 + not + if-goto L15 + push this 1 + push constant 4 + sub + pop this 1 + goto L14 +label L15 + push this 0 + push constant 4 + sub + pop this 0 +label L14 +label L10 + push this 0 + push this 10 + gt + not + not + if-goto L17 + push constant 1 + pop this 14 + push this 10 + pop this 0 + goto L16 +label L17 +label L16 + push this 0 + push this 11 + lt + not + not + if-goto L19 + push constant 2 + pop this 14 + push this 11 + pop this 0 + goto L18 +label L19 +label L18 + push this 1 + push this 12 + gt + not + not + if-goto L21 + push constant 3 + pop this 14 + push this 12 + pop this 1 + goto L20 +label L21 +label L20 + push this 1 + push this 13 + lt + not + not + if-goto L23 + push constant 4 + pop this 14 + push this 13 + pop this 1 + goto L22 +label L23 +label L22 + push pointer 0 + call Ball.show 1 + pop temp 0 + push this 14 + return +function Ball.bounce 5 + push argument 0 + pop pointer 0 + push this 2 + push constant 10 + call Math.divide 2 + pop local 2 + push this 3 + push constant 10 + call Math.divide 2 + pop local 3 + push argument 1 + push constant 0 + eq + not + if-goto L25 + push constant 10 + pop local 4 + goto L24 +label L25 + push this 2 + push constant 0 + lt + not + push argument 1 + push constant 1 + eq + and + push this 2 + push constant 0 + lt + push argument 1 + push constant 1 + neg + eq + and + or + not + if-goto L27 + push constant 20 + pop local 4 + goto L26 +label L27 + push constant 5 + pop local 4 +label L26 +label L24 + push this 14 + push constant 1 + eq + not + if-goto L29 + push constant 506 + pop local 0 + push local 3 + push constant 50 + neg + call Math.multiply 2 + push local 2 + call Math.divide 2 + pop local 1 + push this 1 + push local 1 + push local 4 + call Math.multiply 2 + add + pop local 1 + goto L28 +label L29 + push this 14 + push constant 2 + eq + not + if-goto L31 + push constant 0 + pop local 0 + push local 3 + push constant 50 + call Math.multiply 2 + push local 2 + call Math.divide 2 + pop local 1 + push this 1 + push local 1 + push local 4 + call Math.multiply 2 + add + pop local 1 + goto L30 +label L31 + push this 14 + push constant 3 + eq + not + if-goto L33 + push constant 250 + pop local 1 + push local 2 + push constant 25 + neg + call Math.multiply 2 + push local 3 + call Math.divide 2 + pop local 0 + push this 0 + push local 0 + push local 4 + call Math.multiply 2 + add + pop local 0 + goto L32 +label L33 + push constant 0 + pop local 1 + push local 2 + push constant 25 + call Math.multiply 2 + push local 3 + call Math.divide 2 + pop local 0 + push this 0 + push local 0 + push local 4 + call Math.multiply 2 + add + pop local 0 +label L32 +label L30 +label L28 + push pointer 0 + push local 0 + push local 1 + call Ball.setDestination 3 + pop temp 0 + push constant 0 + return \ No newline at end of file diff --git a/compiler/test/resources/Pong/Bat.jack b/compiler/test/resources/Pong/Bat.jack new file mode 100644 index 00000000..b449c2c5 --- /dev/null +++ b/compiler/test/resources/Pong/Bat.jack @@ -0,0 +1,103 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Pong/Bat.jack +/** + * A graphical bat in a Pong game. + * Displayed as a filled horizontal rectangle that has a screen location, + * a width and a height. + * Has methods for drawing, erasing, moving left and right, and changing + * its width (to make the hitting action more challenging). + * This class should have been called "Paddle", following the + * standard Pong terminology. Unaware of this terminology, + * we called it "bat", and the name stuck. + */ +class Bat { + + field int x, y; // the bat's screen location + field int width, height; // the bat's width and height + field int direction; // direction of the bat's movement + // (1 = left, 2 = right) + + /** Constructs a new bat with the given location and width. */ + constructor Bat new(int Ax, int Ay, int Awidth, int Aheight) { + let x = Ax; + let y = Ay; + let width = Awidth; + let height = Aheight; + let direction = 2; + do show(); + return this; + } + + /** Deallocates the object's memory. */ + method void dispose() { + do Memory.deAlloc(this); + return; + } + + /** Shows the bat. */ + method void show() { + do Screen.setColor(true); + do draw(); + return; + } + + /** Hides the bat. */ + method void hide() { + do Screen.setColor(false); + do draw(); + return; + } + + /** Draws the bat. */ + method void draw() { + do Screen.drawRectangle(x, y, x + width, y + height); + return; + } + + /** Sets the bat's direction (0=stop, 1=left, 2=right). */ + method void setDirection(int Adirection) { + let direction = Adirection; + return; + } + + /** Returns the bat's left edge. */ + method int getLeft() { + return x; + } + + /** Returns the bat's right edge. */ + method int getRight() { + return x + width; + } + + /** Sets the bat's width. */ + method void setWidth(int Awidth) { + do hide(); + let width = Awidth; + do show(); + return; + } + + /** Moves the bat one step in the bat's direction. */ + method void move() { + if (direction = 1) { + let x = x - 4; + if (x < 0) { let x = 0; } + do Screen.setColor(false); + do Screen.drawRectangle((x + width) + 1, y, (x + width) + 4, y + height); + do Screen.setColor(true); + do Screen.drawRectangle(x, y, x + 3, y + height); + } + else { + let x = x + 4; + if ((x + width) > 511) { let x = 511 - width; } + do Screen.setColor(false); + do Screen.drawRectangle(x - 4, y, x - 1, y + height); + do Screen.setColor(true); + do Screen.drawRectangle((x + width) - 3, y, x + width, y + height); + } + return; + } +} diff --git a/compiler/test/resources/Pong/Bat.vm b/compiler/test/resources/Pong/Bat.vm new file mode 100644 index 00000000..043e10a7 --- /dev/null +++ b/compiler/test/resources/Pong/Bat.vm @@ -0,0 +1,208 @@ +function Bat.new 0 + push constant 5 + call Memory.alloc 1 + pop pointer 0 + push argument 0 + pop this 0 + push argument 1 + pop this 1 + push argument 2 + pop this 2 + push argument 3 + pop this 3 + push constant 2 + pop this 4 + push pointer 0 + call Bat.show 1 + pop temp 0 + push pointer 0 + return +function Bat.dispose 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Memory.deAlloc 1 + pop temp 0 + push constant 0 + return +function Bat.show 0 + push argument 0 + pop pointer 0 + push constant 1 + neg + call Screen.setColor 1 + pop temp 0 + push pointer 0 + call Bat.draw 1 + pop temp 0 + push constant 0 + return +function Bat.hide 0 + push argument 0 + pop pointer 0 + push constant 0 + call Screen.setColor 1 + pop temp 0 + push pointer 0 + call Bat.draw 1 + pop temp 0 + push constant 0 + return +function Bat.draw 0 + push argument 0 + pop pointer 0 + push this 0 + push this 1 + push this 0 + push this 2 + add + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + pop temp 0 + push constant 0 + return +function Bat.setDirection 0 + push argument 0 + pop pointer 0 + push argument 1 + pop this 4 + push constant 0 + return +function Bat.getLeft 0 + push argument 0 + pop pointer 0 + push this 0 + return +function Bat.getRight 0 + push argument 0 + pop pointer 0 + push this 0 + push this 2 + add + return +function Bat.setWidth 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Bat.hide 1 + pop temp 0 + push argument 1 + pop this 2 + push pointer 0 + call Bat.show 1 + pop temp 0 + push constant 0 + return +function Bat.move 0 + push argument 0 + pop pointer 0 + push this 4 + push constant 1 + eq + not + if-goto L1 + push this 0 + push constant 4 + sub + pop this 0 + push this 0 + push constant 0 + lt + not + if-goto L3 + push constant 0 + pop this 0 + goto L2 +label L3 +label L2 + push constant 0 + call Screen.setColor 1 + pop temp 0 + push this 0 + push this 2 + add + push constant 1 + add + push this 1 + push this 0 + push this 2 + add + push constant 4 + add + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + pop temp 0 + push constant 1 + neg + call Screen.setColor 1 + pop temp 0 + push this 0 + push this 1 + push this 0 + push constant 3 + add + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + pop temp 0 + goto L0 +label L1 + push this 0 + push constant 4 + add + pop this 0 + push this 0 + push this 2 + add + push constant 511 + gt + not + if-goto L5 + push constant 511 + push this 2 + sub + pop this 0 + goto L4 +label L5 +label L4 + push constant 0 + call Screen.setColor 1 + pop temp 0 + push this 0 + push constant 4 + sub + push this 1 + push this 0 + push constant 1 + sub + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + pop temp 0 + push constant 1 + neg + call Screen.setColor 1 + pop temp 0 + push this 0 + push this 2 + add + push constant 3 + sub + push this 1 + push this 0 + push this 2 + add + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + pop temp 0 +label L0 + push constant 0 + return \ No newline at end of file diff --git a/compiler/test/resources/Pong/Main.jack b/compiler/test/resources/Pong/Main.jack new file mode 100644 index 00000000..9e65ceb7 --- /dev/null +++ b/compiler/test/resources/Pong/Main.jack @@ -0,0 +1,18 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Pong/Main.jack +/** + * Main class of the Pong game. + */ +class Main { + /** Initializes a Pong game and starts running it. */ + function void main() { + var PongGame game; + do PongGame.newInstance(); + let game = PongGame.getInstance(); + do game.run(); + do game.dispose(); + return; + } +} diff --git a/compiler/test/resources/Pong/Main.vm b/compiler/test/resources/Pong/Main.vm new file mode 100644 index 00000000..ef29075b --- /dev/null +++ b/compiler/test/resources/Pong/Main.vm @@ -0,0 +1,13 @@ +function Main.main 1 + call PongGame.newInstance 0 + pop temp 0 + call PongGame.getInstance 0 + pop local 0 + push local 0 + call PongGame.run 1 + pop temp 0 + push local 0 + call PongGame.dispose 1 + pop temp 0 + push constant 0 + return \ No newline at end of file diff --git a/compiler/test/resources/Pong/PongGame.jack b/compiler/test/resources/Pong/PongGame.jack new file mode 100644 index 00000000..515ead4a --- /dev/null +++ b/compiler/test/resources/Pong/PongGame.jack @@ -0,0 +1,136 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Pong/PongGame.jack +/** + * Represents a Pong game. + */ +class PongGame { + + static PongGame instance; // A Pong game + field Bat bat; // bat + field Ball ball; // ball + field int wall; // current wall that the ball is bouncing off of + field boolean exit; // true when the game is over + field int score; // current score + field int lastWall; // last wall that the ball bounced off of + + // The current width of the bat + field int batWidth; + + /** Constructs a new Pong game. */ + constructor PongGame new() { + do Screen.clearScreen(); + let batWidth = 50; // initial bat size + let bat = Bat.new(230, 229, batWidth, 7); + let ball = Ball.new(253, 222, 0, 511, 0, 229); + do ball.setDestination(400,0); + do Screen.drawRectangle(0, 238, 511, 240); + do Output.moveCursor(22,0); + do Output.printString("Score: 0"); + + let exit = false; + let score = 0; + let wall = 0; + let lastWall = 0; + + return this; + } + + /** Deallocates the object's memory. */ + method void dispose() { + do bat.dispose(); + do ball.dispose(); + do Memory.deAlloc(this); + return; + } + + /** Creates an instance of a Pong game. */ + function void newInstance() { + let instance = PongGame.new(); + return; + } + + /** Returns this Pong game. */ + function PongGame getInstance() { + return instance; + } + + /** Starts the game, and handles inputs from the user that control + * the bat's movement direction. */ + method void run() { + var char key; + + while (~exit) { + // waits for a key to be pressed. + while ((key = 0) & (~exit)) { + let key = Keyboard.keyPressed(); + do bat.move(); + do moveBall(); + do Sys.wait(50); + } + + if (key = 130) { do bat.setDirection(1); } + else { + if (key = 132) { do bat.setDirection(2); } + else { + if (key = 140) { let exit = true; } + } + } + + // Waits for the key to be released. + while ((~(key = 0)) & (~exit)) { + let key = Keyboard.keyPressed(); + do bat.move(); + do moveBall(); + do Sys.wait(50); + } + } + + if (exit) { + do Output.moveCursor(10,27); + do Output.printString("Game Over"); + } + + return; + } + + /** + * Handles ball movement, including bouncing. + * If the ball bounces off a wall, finds its new direction. + * If the ball bounces off the bat, increases the score by one + * and shrinks the bat's size, to make the game more challenging. + */ + method void moveBall() { + var int bouncingDirection, batLeft, batRight, ballLeft, ballRight; + + let wall = ball.move(); + + if ((wall > 0) & (~(wall = lastWall))) { + let lastWall = wall; + let bouncingDirection = 0; + let batLeft = bat.getLeft(); + let batRight = bat.getRight(); + let ballLeft = ball.getLeft(); + let ballRight = ball.getRight(); + + if (wall = 4) { + let exit = (batLeft > ballRight) | (batRight < ballLeft); + if (~exit) { + if (ballRight < (batLeft + 10)) { let bouncingDirection = -1; } + else { + if (ballLeft > (batRight - 10)) { let bouncingDirection = 1; } + } + + let batWidth = batWidth - 2; + do bat.setWidth(batWidth); + let score = score + 1; + do Output.moveCursor(22,7); + do Output.printInt(score); + } + } + do ball.bounce(bouncingDirection); + } + return; + } +} \ No newline at end of file diff --git a/compiler/test/resources/Pong/PongGame.vm b/compiler/test/resources/Pong/PongGame.vm new file mode 100644 index 00000000..82fb88a5 --- /dev/null +++ b/compiler/test/resources/Pong/PongGame.vm @@ -0,0 +1,321 @@ +function PongGame.new 0 + push constant 7 + call Memory.alloc 1 + pop pointer 0 + call Screen.clearScreen 0 + pop temp 0 + push constant 50 + pop this 6 + push constant 230 + push constant 229 + push this 6 + push constant 7 + call Bat.new 4 + pop this 0 + push constant 253 + push constant 222 + push constant 0 + push constant 511 + push constant 0 + push constant 229 + call Ball.new 6 + pop this 1 + push this 1 + push constant 400 + push constant 0 + call Ball.setDestination 3 + pop temp 0 + push constant 0 + push constant 238 + push constant 511 + push constant 240 + call Screen.drawRectangle 4 + pop temp 0 + push constant 22 + push constant 0 + call Output.moveCursor 2 + pop temp 0 + push constant 8 + call String.new 1 + push constant 83 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 111 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 48 + call String.appendChar 2 + call Output.printString 1 + pop temp 0 + push constant 0 + pop this 3 + push constant 0 + pop this 4 + push constant 0 + pop this 2 + push constant 0 + pop this 5 + push pointer 0 + return +function PongGame.dispose 0 + push argument 0 + pop pointer 0 + push this 0 + call Bat.dispose 1 + pop temp 0 + push this 1 + call Ball.dispose 1 + pop temp 0 + push pointer 0 + call Memory.deAlloc 1 + pop temp 0 + push constant 0 + return +function PongGame.newInstance 0 + call PongGame.new 0 + pop static 0 + push constant 0 + return +function PongGame.getInstance 0 + push static 0 + return +function PongGame.run 1 + push argument 0 + pop pointer 0 +label L0 + push this 3 + not + not + if-goto L1 +label L2 + push local 0 + push constant 0 + eq + push this 3 + not + and + not + if-goto L3 + call Keyboard.keyPressed 0 + pop local 0 + push this 0 + call Bat.move 1 + pop temp 0 + push pointer 0 + call PongGame.moveBall 1 + pop temp 0 + push constant 50 + call Sys.wait 1 + pop temp 0 + goto L2 +label L3 + push local 0 + push constant 130 + eq + not + if-goto L5 + push this 0 + push constant 1 + call Bat.setDirection 2 + pop temp 0 + goto L4 +label L5 + push local 0 + push constant 132 + eq + not + if-goto L7 + push this 0 + push constant 2 + call Bat.setDirection 2 + pop temp 0 + goto L6 +label L7 + push local 0 + push constant 140 + eq + not + if-goto L9 + push constant 1 + neg + pop this 3 + goto L8 +label L9 +label L8 +label L6 +label L4 +label L10 + push local 0 + push constant 0 + eq + not + push this 3 + not + and + not + if-goto L11 + call Keyboard.keyPressed 0 + pop local 0 + push this 0 + call Bat.move 1 + pop temp 0 + push pointer 0 + call PongGame.moveBall 1 + pop temp 0 + push constant 50 + call Sys.wait 1 + pop temp 0 + goto L10 +label L11 + goto L0 +label L1 + push this 3 + not + if-goto L13 + push constant 10 + push constant 27 + call Output.moveCursor 2 + pop temp 0 + push constant 9 + call String.new 1 + push constant 71 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 109 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 79 + call String.appendChar 2 + push constant 118 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + call Output.printString 1 + pop temp 0 + goto L12 +label L13 +label L12 + push constant 0 + return +function PongGame.moveBall 5 + push argument 0 + pop pointer 0 + push this 1 + call Ball.move 1 + pop this 2 + push this 2 + push constant 0 + gt + push this 2 + push this 5 + eq + not + and + not + if-goto L15 + push this 2 + pop this 5 + push constant 0 + pop local 0 + push this 0 + call Bat.getLeft 1 + pop local 1 + push this 0 + call Bat.getRight 1 + pop local 2 + push this 1 + call Ball.getLeft 1 + pop local 3 + push this 1 + call Ball.getRight 1 + pop local 4 + push this 2 + push constant 4 + eq + not + if-goto L17 + push local 1 + push local 4 + gt + push local 2 + push local 3 + lt + or + pop this 3 + push this 3 + not + not + if-goto L19 + push local 4 + push local 1 + push constant 10 + add + lt + not + if-goto L21 + push constant 1 + neg + pop local 0 + goto L20 +label L21 + push local 3 + push local 2 + push constant 10 + sub + gt + not + if-goto L23 + push constant 1 + pop local 0 + goto L22 +label L23 +label L22 +label L20 + push this 6 + push constant 2 + sub + pop this 6 + push this 0 + push this 6 + call Bat.setWidth 2 + pop temp 0 + push this 4 + push constant 1 + add + pop this 4 + push constant 22 + push constant 7 + call Output.moveCursor 2 + pop temp 0 + push this 4 + call Output.printInt 1 + pop temp 0 + goto L18 +label L19 +label L18 + goto L16 +label L17 +label L16 + push this 1 + push local 0 + call Ball.bounce 2 + pop temp 0 + goto L14 +label L15 +label L14 + push constant 0 + return \ No newline at end of file diff --git a/compiler/test/resources/Square/Main.jack b/compiler/test/resources/Square/Main.jack new file mode 100644 index 00000000..bc6732e0 --- /dev/null +++ b/compiler/test/resources/Square/Main.jack @@ -0,0 +1,15 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Square/Main.jack + +/** Initializes a new Square game and starts running it. */ +class Main { + function void main() { + var SquareGame game; + let game = SquareGame.new(); + do game.run(); + do game.dispose(); + return; + } +} diff --git a/compiler/test/resources/Square/Square.jack b/compiler/test/resources/Square/Square.jack new file mode 100644 index 00000000..e4a6590d --- /dev/null +++ b/compiler/test/resources/Square/Square.jack @@ -0,0 +1,113 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Square/Square.jack + +/** Implements a graphical square. + The square has top-left x and y coordinates, and a size. */ +class Square { + + field int x, y; // screen location of the top-left corner of this square + field int size; // length of this square, in pixels + + /** Constructs and draws a new square with a given location and size. */ + constructor Square new(int ax, int ay, int asize) { + let x = ax; + let y = ay; + let size = asize; + do draw(); + return this; + } + + /** Disposes this square. */ + method void dispose() { + do Memory.deAlloc(this); + return; + } + + /** Draws this square in its current (x,y) location */ + method void draw() { + // Draws the square using the color black + do Screen.setColor(true); + do Screen.drawRectangle(x, y, x + size, y + size); + return; + } + + /** Erases this square. */ + method void erase() { + // Draws the square using the color white (background color) + do Screen.setColor(false); + do Screen.drawRectangle(x, y, x + size, y + size); + return; + } + + /** Increments the square size by 2 pixels (if possible). */ + method void incSize() { + if (((y + size) < 254) & ((x + size) < 510)) { + do erase(); + let size = size + 2; + do draw(); + } + return; + } + + /** Decrements the square size by 2 pixels (if possible). */ + method void decSize() { + if (size > 2) { + do erase(); + let size = size - 2; + do draw(); + } + return; + } + + /** Moves this square up by 2 pixels (if possible). */ + method void moveUp() { + if (y > 1) { + // Erases the bottom two rows of this square in its current location + do Screen.setColor(false); + do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size); + let y = y - 2; + // Draws the top two rows of this square in its new location + do Screen.setColor(true); + do Screen.drawRectangle(x, y, x + size, y + 1); + } + return; + } + + /** Moves the square down by 2 pixels (if possible). */ + method void moveDown() { + if ((y + size) < 254) { + do Screen.setColor(false); + do Screen.drawRectangle(x, y, x + size, y + 1); + let y = y + 2; + do Screen.setColor(true); + do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size); + } + return; + } + + /** Moves the square left by 2 pixels (if possible). */ + method void moveLeft() { + if (x > 1) { + do Screen.setColor(false); + do Screen.drawRectangle((x + size) - 1, y, x + size, y + size); + let x = x - 2; + do Screen.setColor(true); + do Screen.drawRectangle(x, y, x + 1, y + size); + } + return; + } + + /** Moves the square right by 2 pixels (if possible). */ + method void moveRight() { + if ((x + size) < 510) { + do Screen.setColor(false); + do Screen.drawRectangle(x, y, x + 1, y + size); + let x = x + 2; + do Screen.setColor(true); + do Screen.drawRectangle((x + size) - 1, y, x + size, y + size); + } + return; + } +} diff --git a/compiler/test/resources/Square/SquareGame.jack b/compiler/test/resources/Square/SquareGame.jack new file mode 100644 index 00000000..fa4ce93e --- /dev/null +++ b/compiler/test/resources/Square/SquareGame.jack @@ -0,0 +1,76 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/09/Square/SquareGame.jack +/** + * Implements the Square game. + * This simple game allows the user to move a black square around + * the screen, and change the square's size during the movement. + * When the game starts, a square of 30 by 30 pixels is shown at the + * top-left corner of the screen. The user controls the square as follows. + * The 4 arrow keys are used to move the square up, down, left, and right. + * The 'z' and 'x' keys are used, respectively, to decrement and increment + * the square's size. The 'q' key is used to quit the game. + */ +class SquareGame { + field Square square; // the square of this game + field int direction; // the square's current direction: + // 0=none, 1=up, 2=down, 3=left, 4=right + + /** Constructs a new square game. */ + constructor SquareGame new() { + // The initial square is located in (0,0), has size 30, and is not moving. + let square = Square.new(0, 0, 30); + let direction = 0; + return this; + } + + /** Disposes this game. */ + method void dispose() { + do square.dispose(); + do Memory.deAlloc(this); + return; + } + + /** Moves the square in the current direction. */ + method void moveSquare() { + if (direction = 1) { do square.moveUp(); } + if (direction = 2) { do square.moveDown(); } + if (direction = 3) { do square.moveLeft(); } + if (direction = 4) { do square.moveRight(); } + do Sys.wait(5); // delays the next movement + return; + } + + /** Runs the game: handles the user's inputs and moves the square accordingly */ + method void run() { + var char key; // the key currently pressed by the user + var boolean exit; + let exit = false; + + while (~exit) { + // waits for a key to be pressed + while (key = 0) { + let key = Keyboard.keyPressed(); + do moveSquare(); + } + if (key = 81) { let exit = true; } // q key + if (key = 90) { do square.decSize(); } // z key + if (key = 88) { do square.incSize(); } // x key + if (key = 131) { let direction = 1; } // up arrow + if (key = 133) { let direction = 2; } // down arrow + if (key = 130) { let direction = 3; } // left arrow + if (key = 132) { let direction = 4; } // right arrow + + // waits for the key to be released + while (~(key = 0)) { + let key = Keyboard.keyPressed(); + do moveSquare(); + } + } // while + return; + } +} + + + diff --git a/compiler/test/symbol.table.test.ts b/compiler/test/symbol.table.test.ts new file mode 100644 index 00000000..42cc120f --- /dev/null +++ b/compiler/test/symbol.table.test.ts @@ -0,0 +1,10 @@ +import { Scope, SymbolTable, SymbolTableEntry } from "../src/symbol.table"; + +describe('symbol table', () => { + test('basic', () => { + const symbolTable = new SymbolTable(); + symbolTable.insert(new SymbolTableEntry('test', 'int', Scope.local)); + expect(symbolTable.lookup('test')).toEqual(new SymbolTableEntry('test', 'int', Scope.local)); + expect(symbolTable.lookup('a')).toBeUndefined(); + }); +}); \ No newline at end of file diff --git a/compiler/tsconfig.json b/compiler/tsconfig.json new file mode 100644 index 00000000..4116586e --- /dev/null +++ b/compiler/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + // Workspace projects + "composite": true, + + // Assume browser environment & esm + "lib": ["es2022", "DOM", "DOM.Iterable"], + "target": "es2022", + "module": "ESNext", + "moduleResolution": "node", + "allowJs": true, + "checkJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": false, + "jsx": "react-jsx", + "sourceMap": true, + + // Checks and strictness + "strict": true, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + // "exactOptionalPropertyTypes": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + // "noPropertyAccessFromIndexSignature": true, + // "noUncheckedIndexedAccess": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + + "incremental": true, + "declaration": true, + + }, + +} From 53b5a0bb80c188ae7d5749ffdc0cf69f55dff992 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Wed, 25 Sep 2024 00:06:33 +0200 Subject: [PATCH 02/87] WIP --- compiler/src/error.ts | 17 + compiler/src/symbol.table.istener.ts | 87 +--- compiler/src/symbol.table.ts | 26 -- compiler/test/parser.test.ts | 62 +-- .../test/resources/DuplicatedSubroutine.jack | 8 + compiler/test/resources/Pong/Ball.vm | 435 ------------------ compiler/test/resources/Pong/Bat.vm | 208 --------- compiler/test/resources/Pong/Main.vm | 13 - compiler/test/resources/Pong/PongGame.vm | 321 ------------- compiler/test/symbol.table.listener.test.ts | 57 +++ compiler/test/symbol.table.test.ts | 10 - compiler/test/test.helper.ts | 30 ++ 12 files changed, 154 insertions(+), 1120 deletions(-) create mode 100644 compiler/src/error.ts delete mode 100644 compiler/src/symbol.table.ts create mode 100644 compiler/test/resources/DuplicatedSubroutine.jack delete mode 100644 compiler/test/resources/Pong/Ball.vm delete mode 100644 compiler/test/resources/Pong/Bat.vm delete mode 100644 compiler/test/resources/Pong/Main.vm delete mode 100644 compiler/test/resources/Pong/PongGame.vm create mode 100644 compiler/test/symbol.table.listener.test.ts delete mode 100644 compiler/test/symbol.table.test.ts create mode 100644 compiler/test/test.helper.ts diff --git a/compiler/src/error.ts b/compiler/src/error.ts new file mode 100644 index 00000000..52ad716d --- /dev/null +++ b/compiler/src/error.ts @@ -0,0 +1,17 @@ +export class JackCompilerError extends Error { + constructor(msg: string) { + super(msg); + + // Set the prototype explicitly. + Object.setPrototypeOf(this, JackCompilerError.prototype); + } +} +export class DuplicatedSubroutineError extends JackCompilerError { + constructor(msg: string) { + super(msg); + + // Set the prototype explicitly. + Object.setPrototypeOf(this, DuplicatedSubroutineError.prototype); + } + +} \ No newline at end of file diff --git a/compiler/src/symbol.table.istener.ts b/compiler/src/symbol.table.istener.ts index f8ee0602..13daab87 100644 --- a/compiler/src/symbol.table.istener.ts +++ b/compiler/src/symbol.table.istener.ts @@ -1,97 +1,60 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; -import { ClassDeclarationContext, ClassVarDecContext, ConstructorContext, FunctionContext, JackParser, MethodContext, StaticFieldDeclarationContext, SubroutineDecContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDecContext, VarTypeContext } from "./generated/JackParser"; -import { JackParserListener } from "./generated/JackParserListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; - +import { ClassDeclarationContext, ConstructorContext, FunctionContext, MethodContext, SubroutineDecWithoutTypeContext } from "./generated/JackParser"; +import { JackParserListener } from "./generated/JackParserListener"; +import { DuplicatedSubroutineError } from './error' const primitives = new Set(["int", "boolean", "char"] as const); export type Primitive = typeof primitives extends Set ? S : never; /** * Generic symbol. Can be used for both class and function symbols */ -interface GenericSymbol extends Symbol { +export interface GenericSymbol extends Symbol { subroutineParameterCount?: number; } -/** - * Symbol table. Key represents class name or . - */ -interface SymbolTale { - [key: string]: GenericSymbol; -} export class SymbolTableListener implements JackParserListener, ParseTreeListener { - //wh do we need that? - // to check if symbol exists (function or class) and also check subroutine declaration so that we are are supplying right ammount of params - public globalSymbolTable: SymbolTale = {}; + // key can be class or . + public globalSymbolTable: Record = {}; //track class variables, local vars, function args - // localSymbolTable = []; - className = ""; - public errors: string[] = [] - // fix compiler error + public className = ""; + public errors: DuplicatedSubroutineError[] = [] + + //to fix compiler error visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; enterClassDeclaration(ctx: ClassDeclarationContext) { if (this.globalSymbolTable[ctx.className()!.text] != undefined) { - this.errors.push(`Class "${ctx.className()!.text}" already defined.`); + this.errors.push(new DuplicatedSubroutineError(`Class "${ctx.className()!.text}" already defined.`)); return; } this.globalSymbolTable[ctx.className()!.text] = {} as GenericSymbol; this.className = ctx.className()?.text; - console.log(`Entering class ${ctx.className()?.text}`); - }; - enterStaticFieldDeclaration(ctx: StaticFieldDeclarationContext) { - const fieldList = ctx.fieldList(); - console.log(`static field: ${fieldList.varType().text} ${fieldList.fieldName().map(t => t.text).join(",")}`); - }; - - - enterVarDec(ctx: VarDecContext) { - const names = ctx.IDENTIFIER(); - console.log(`Function var: ${this.getType(ctx.varType())} ${names.join(",")}`); }; enterConstructor(ctx: ConstructorContext) { - this.addSymbol(ctx.subroutineDecWithoutType()) - this.printSubroutine("Ctor", ctx.subroutineDecWithoutType()) + this.#addSymbol(ctx.subroutineDecWithoutType()) }; - addSymbol(c: SubroutineDecWithoutTypeContext) { - const subroutineName = c.subroutineName().text - const id = this.className + "." + subroutineName - if (this.globalSymbolTable[id] != undefined) { - this.errors.push(`Subroutine "${subroutineName}" is already defined.`); - } - this.globalSymbolTable[id] = { - subroutineParameterCount: c.parameterList().parameter().length - } as GenericSymbol; - } enterMethod(ctx: MethodContext) { - this.addSymbol(ctx.subroutineDecWithoutType()) - this.printSubroutine("Method", ctx.subroutineDecWithoutType()) + this.#addSymbol(ctx.subroutineDecWithoutType()) }; enterFunction(ctx: FunctionContext) { - this.addSymbol(ctx.subroutineDecWithoutType()) - this.printSubroutine("Function", ctx.subroutineDecWithoutType()) + this.#addSymbol(ctx.subroutineDecWithoutType()) }; - printSubroutine(type: string, c: SubroutineDecWithoutTypeContext) { - const returnType = this.getSubroutineReturnType(c.subroutineReturnType()) - const paramList = c.parameterList().parameter().map(t => t.varType().text + " " + t.parameterName().text).join(","); - console.log(`${type}: ${returnType} ${c.subroutineName().text} (${paramList})`); - } - - getType(ctx: VarTypeContext): string { - return ctx.BOOLEAN() ? "boolean" : - ctx.INT() ? "int" : - ctx.CHAR() ? "char" : - ctx.IDENTIFIER() ? ctx.IDENTIFIER()!.text : - "unknown"; - } - - getSubroutineReturnType(ctx: SubroutineReturnTypeContext): string { - return ctx.VOID() ? "void" : this.getType(ctx.varType()!); - } resetErrors() { this.errors = []; } + + #addSymbol(c: SubroutineDecWithoutTypeContext) { + const subroutineName = c.subroutineName().text + const id = this.className + "." + subroutineName + if (this.globalSymbolTable[id] != undefined) { + this.errors.push(new DuplicatedSubroutineError(`Subroutine "${subroutineName}" is already defined.`)); + } + this.globalSymbolTable[id] = { + subroutineParameterCount: c.parameterList().parameter().length + } as GenericSymbol; + } } diff --git a/compiler/src/symbol.table.ts b/compiler/src/symbol.table.ts deleted file mode 100644 index b0f84a5a..00000000 --- a/compiler/src/symbol.table.ts +++ /dev/null @@ -1,26 +0,0 @@ -export enum Scope { - local, - static, - argument, -} -export class SymbolTableEntry { - constructor(public name: string, public type: string, public scope: Scope) { - - } -} -export class SymbolTable { - constructor(private entries: SymbolTableEntry[] = [], private scopes: Scope[] = [], private scopeStack: Scope[] = []) { } - insert(entry: SymbolTableEntry) { - this.entries.push(entry); - } - lookup(name: string) { - //TODO: look for entries in enclosed scopes - return this.entries.find(entry => entry.name === name); - } - pushScope(scope: Scope) { - this.scopeStack.push(scope); - } - popScope() { - this.scopeStack.pop(); - } -} \ No newline at end of file diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index 6e15a3f5..7e27d739 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -1,12 +1,12 @@ -import { JackLexer } from "../src/generated/JackLexer"; -import { JackParser } from "../src/generated/JackParser"; -import { SymbolTableListener } from "../src/symbol.table.istener"; +import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker'; import fs from 'fs'; -import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker' +import { SymbolTableListener } from "../src/symbol.table.istener"; -import { CommonTokenStream, BufferedTokenStream, CharStreams } from 'antlr4ts'; import path from "path"; import { ErrorListener } from "../src/error.listener"; +import { getTestResourcePath, parseJack } from "./test.helper"; + + describe('Parser', () => { const jestConsole = console; @@ -17,6 +17,7 @@ describe('Parser', () => { afterEach(() => { global.console = jestConsole; }); + const dirs: string[] = [ "Average", "ConvertToBin", @@ -24,64 +25,35 @@ describe('Parser', () => { "HelloWorld", "List", "Pong", - "Square" + "Square", + "ComplexArrays" ] test.each(dirs)('%s', (dir: string) => { console.log("Testing " + dir) - testJack(dir); - // console.log("File", f) + testJackDir(path.join(__dirname, "resources", dir)); }); - }); -function testJack(testName: string, trace = false) { - var filePath = path.join(__dirname, "resources", testName); - testJackDir(filePath); -} -function testJackDir(testFolder: string) { + +function testJackDir(testFolder: string): void { const globalSymbolsListener = new SymbolTableListener(); const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); for (const filePath of files) { - - const f = fs.readFileSync(filePath, 'utf8'); - // console.log(f); - // Create the lexer and parser - const inputStream = CharStreams.fromString(f); - const lexer = new JackLexer(inputStream); - const errorListener = ErrorListener.getInstance(); + const errorListener = ErrorListener.getInstance() errorListener.filepath = filePath; - lexer.removeErrorListeners(); - lexer.addErrorListener(errorListener); - - const tokenStream = new CommonTokenStream(lexer); - // const tokens = tokenStream.getTokens() - // console.log("Tokens ", ) - expect(tokenStream.getTokens.length).toBeGreaterThan(0) - const parser = new JackParser(tokenStream); - // parser.isTrace = true; - parser.removeErrorListeners(); - parser.addErrorListener(errorListener); - // Parse the input, where `compilationUnit` is whatever entry point you defined - const tree = parser.program(); - // expect(errorListener.error).toBe(false) + const tree = parseJack(filePath, errorListener); + expect(errorListener.error).toBe(false) // console.log(tree.toStringTree(parser.ruleNames)); - // Create the visitor - // const v = new Visitor(); - // // Use the visitor entry point - // const res = v.visit(tree); - // console.log("Res", res); ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); const symbolsErrors = globalSymbolsListener.errors.join("\n") try { - expect(globalSymbolsListener.errors.length,).toBe(0) + expect(globalSymbolsListener.errors.length).toBe(0) } catch (e) { throw new Error(symbolsErrors); } - globalSymbolsListener.resetErrors(); - } - console.log("GlobalSymbolTable", globalSymbolsListener.globalSymbolTable) -} \ No newline at end of file + //TODO: improve this +} diff --git a/compiler/test/resources/DuplicatedSubroutine.jack b/compiler/test/resources/DuplicatedSubroutine.jack new file mode 100644 index 00000000..b56aa83a --- /dev/null +++ b/compiler/test/resources/DuplicatedSubroutine.jack @@ -0,0 +1,8 @@ +class DuplicatedSubroutine { + function void f(){ + return; + } + function int f(){ + return 1; + } +} \ No newline at end of file diff --git a/compiler/test/resources/Pong/Ball.vm b/compiler/test/resources/Pong/Ball.vm deleted file mode 100644 index 9471908f..00000000 --- a/compiler/test/resources/Pong/Ball.vm +++ /dev/null @@ -1,435 +0,0 @@ -function Ball.new 0 - push constant 15 - call Memory.alloc 1 - pop pointer 0 - push argument 0 - pop this 0 - push argument 1 - pop this 1 - push argument 2 - pop this 10 - push argument 3 - push constant 6 - sub - pop this 11 - push argument 4 - pop this 12 - push argument 5 - push constant 6 - sub - pop this 13 - push constant 0 - pop this 14 - push pointer 0 - call Ball.show 1 - pop temp 0 - push pointer 0 - return -function Ball.dispose 0 - push argument 0 - pop pointer 0 - push pointer 0 - call Memory.deAlloc 1 - pop temp 0 - push constant 0 - return -function Ball.show 0 - push argument 0 - pop pointer 0 - push constant 1 - neg - call Screen.setColor 1 - pop temp 0 - push pointer 0 - call Ball.draw 1 - pop temp 0 - push constant 0 - return -function Ball.hide 0 - push argument 0 - pop pointer 0 - push constant 0 - call Screen.setColor 1 - pop temp 0 - push pointer 0 - call Ball.draw 1 - pop temp 0 - push constant 0 - return -function Ball.draw 0 - push argument 0 - pop pointer 0 - push this 0 - push this 1 - push this 0 - push constant 5 - add - push this 1 - push constant 5 - add - call Screen.drawRectangle 4 - pop temp 0 - push constant 0 - return -function Ball.getLeft 0 - push argument 0 - pop pointer 0 - push this 0 - return -function Ball.getRight 0 - push argument 0 - pop pointer 0 - push this 0 - push constant 5 - add - return -function Ball.setDestination 3 - push argument 0 - pop pointer 0 - push argument 1 - push this 0 - sub - pop this 2 - push argument 2 - push this 1 - sub - pop this 3 - push this 2 - call Math.abs 1 - pop local 0 - push this 3 - call Math.abs 1 - pop local 1 - push local 0 - push local 1 - lt - pop this 7 - push this 7 - not - if-goto L1 - push local 0 - pop local 2 - push local 1 - pop local 0 - push local 2 - pop local 1 - push this 1 - push argument 2 - lt - pop this 8 - push this 0 - push argument 1 - lt - pop this 9 - goto L0 -label L1 - push this 0 - push argument 1 - lt - pop this 8 - push this 1 - push argument 2 - lt - pop this 9 -label L0 - push constant 2 - push local 1 - call Math.multiply 2 - push local 0 - sub - pop this 4 - push constant 2 - push local 1 - call Math.multiply 2 - pop this 5 - push constant 2 - push local 1 - push local 0 - sub - call Math.multiply 2 - pop this 6 - push constant 0 - return -function Ball.move 0 - push argument 0 - pop pointer 0 - push pointer 0 - call Ball.hide 1 - pop temp 0 - push this 4 - push constant 0 - lt - not - if-goto L3 - push this 4 - push this 5 - add - pop this 4 - goto L2 -label L3 - push this 4 - push this 6 - add - pop this 4 - push this 9 - not - if-goto L5 - push this 7 - not - if-goto L7 - push this 0 - push constant 4 - add - pop this 0 - goto L6 -label L7 - push this 1 - push constant 4 - add - pop this 1 -label L6 - goto L4 -label L5 - push this 7 - not - if-goto L9 - push this 0 - push constant 4 - sub - pop this 0 - goto L8 -label L9 - push this 1 - push constant 4 - sub - pop this 1 -label L8 -label L4 -label L2 - push this 8 - not - if-goto L11 - push this 7 - not - if-goto L13 - push this 1 - push constant 4 - add - pop this 1 - goto L12 -label L13 - push this 0 - push constant 4 - add - pop this 0 -label L12 - goto L10 -label L11 - push this 7 - not - if-goto L15 - push this 1 - push constant 4 - sub - pop this 1 - goto L14 -label L15 - push this 0 - push constant 4 - sub - pop this 0 -label L14 -label L10 - push this 0 - push this 10 - gt - not - not - if-goto L17 - push constant 1 - pop this 14 - push this 10 - pop this 0 - goto L16 -label L17 -label L16 - push this 0 - push this 11 - lt - not - not - if-goto L19 - push constant 2 - pop this 14 - push this 11 - pop this 0 - goto L18 -label L19 -label L18 - push this 1 - push this 12 - gt - not - not - if-goto L21 - push constant 3 - pop this 14 - push this 12 - pop this 1 - goto L20 -label L21 -label L20 - push this 1 - push this 13 - lt - not - not - if-goto L23 - push constant 4 - pop this 14 - push this 13 - pop this 1 - goto L22 -label L23 -label L22 - push pointer 0 - call Ball.show 1 - pop temp 0 - push this 14 - return -function Ball.bounce 5 - push argument 0 - pop pointer 0 - push this 2 - push constant 10 - call Math.divide 2 - pop local 2 - push this 3 - push constant 10 - call Math.divide 2 - pop local 3 - push argument 1 - push constant 0 - eq - not - if-goto L25 - push constant 10 - pop local 4 - goto L24 -label L25 - push this 2 - push constant 0 - lt - not - push argument 1 - push constant 1 - eq - and - push this 2 - push constant 0 - lt - push argument 1 - push constant 1 - neg - eq - and - or - not - if-goto L27 - push constant 20 - pop local 4 - goto L26 -label L27 - push constant 5 - pop local 4 -label L26 -label L24 - push this 14 - push constant 1 - eq - not - if-goto L29 - push constant 506 - pop local 0 - push local 3 - push constant 50 - neg - call Math.multiply 2 - push local 2 - call Math.divide 2 - pop local 1 - push this 1 - push local 1 - push local 4 - call Math.multiply 2 - add - pop local 1 - goto L28 -label L29 - push this 14 - push constant 2 - eq - not - if-goto L31 - push constant 0 - pop local 0 - push local 3 - push constant 50 - call Math.multiply 2 - push local 2 - call Math.divide 2 - pop local 1 - push this 1 - push local 1 - push local 4 - call Math.multiply 2 - add - pop local 1 - goto L30 -label L31 - push this 14 - push constant 3 - eq - not - if-goto L33 - push constant 250 - pop local 1 - push local 2 - push constant 25 - neg - call Math.multiply 2 - push local 3 - call Math.divide 2 - pop local 0 - push this 0 - push local 0 - push local 4 - call Math.multiply 2 - add - pop local 0 - goto L32 -label L33 - push constant 0 - pop local 1 - push local 2 - push constant 25 - call Math.multiply 2 - push local 3 - call Math.divide 2 - pop local 0 - push this 0 - push local 0 - push local 4 - call Math.multiply 2 - add - pop local 0 -label L32 -label L30 -label L28 - push pointer 0 - push local 0 - push local 1 - call Ball.setDestination 3 - pop temp 0 - push constant 0 - return \ No newline at end of file diff --git a/compiler/test/resources/Pong/Bat.vm b/compiler/test/resources/Pong/Bat.vm deleted file mode 100644 index 043e10a7..00000000 --- a/compiler/test/resources/Pong/Bat.vm +++ /dev/null @@ -1,208 +0,0 @@ -function Bat.new 0 - push constant 5 - call Memory.alloc 1 - pop pointer 0 - push argument 0 - pop this 0 - push argument 1 - pop this 1 - push argument 2 - pop this 2 - push argument 3 - pop this 3 - push constant 2 - pop this 4 - push pointer 0 - call Bat.show 1 - pop temp 0 - push pointer 0 - return -function Bat.dispose 0 - push argument 0 - pop pointer 0 - push pointer 0 - call Memory.deAlloc 1 - pop temp 0 - push constant 0 - return -function Bat.show 0 - push argument 0 - pop pointer 0 - push constant 1 - neg - call Screen.setColor 1 - pop temp 0 - push pointer 0 - call Bat.draw 1 - pop temp 0 - push constant 0 - return -function Bat.hide 0 - push argument 0 - pop pointer 0 - push constant 0 - call Screen.setColor 1 - pop temp 0 - push pointer 0 - call Bat.draw 1 - pop temp 0 - push constant 0 - return -function Bat.draw 0 - push argument 0 - pop pointer 0 - push this 0 - push this 1 - push this 0 - push this 2 - add - push this 1 - push this 3 - add - call Screen.drawRectangle 4 - pop temp 0 - push constant 0 - return -function Bat.setDirection 0 - push argument 0 - pop pointer 0 - push argument 1 - pop this 4 - push constant 0 - return -function Bat.getLeft 0 - push argument 0 - pop pointer 0 - push this 0 - return -function Bat.getRight 0 - push argument 0 - pop pointer 0 - push this 0 - push this 2 - add - return -function Bat.setWidth 0 - push argument 0 - pop pointer 0 - push pointer 0 - call Bat.hide 1 - pop temp 0 - push argument 1 - pop this 2 - push pointer 0 - call Bat.show 1 - pop temp 0 - push constant 0 - return -function Bat.move 0 - push argument 0 - pop pointer 0 - push this 4 - push constant 1 - eq - not - if-goto L1 - push this 0 - push constant 4 - sub - pop this 0 - push this 0 - push constant 0 - lt - not - if-goto L3 - push constant 0 - pop this 0 - goto L2 -label L3 -label L2 - push constant 0 - call Screen.setColor 1 - pop temp 0 - push this 0 - push this 2 - add - push constant 1 - add - push this 1 - push this 0 - push this 2 - add - push constant 4 - add - push this 1 - push this 3 - add - call Screen.drawRectangle 4 - pop temp 0 - push constant 1 - neg - call Screen.setColor 1 - pop temp 0 - push this 0 - push this 1 - push this 0 - push constant 3 - add - push this 1 - push this 3 - add - call Screen.drawRectangle 4 - pop temp 0 - goto L0 -label L1 - push this 0 - push constant 4 - add - pop this 0 - push this 0 - push this 2 - add - push constant 511 - gt - not - if-goto L5 - push constant 511 - push this 2 - sub - pop this 0 - goto L4 -label L5 -label L4 - push constant 0 - call Screen.setColor 1 - pop temp 0 - push this 0 - push constant 4 - sub - push this 1 - push this 0 - push constant 1 - sub - push this 1 - push this 3 - add - call Screen.drawRectangle 4 - pop temp 0 - push constant 1 - neg - call Screen.setColor 1 - pop temp 0 - push this 0 - push this 2 - add - push constant 3 - sub - push this 1 - push this 0 - push this 2 - add - push this 1 - push this 3 - add - call Screen.drawRectangle 4 - pop temp 0 -label L0 - push constant 0 - return \ No newline at end of file diff --git a/compiler/test/resources/Pong/Main.vm b/compiler/test/resources/Pong/Main.vm deleted file mode 100644 index ef29075b..00000000 --- a/compiler/test/resources/Pong/Main.vm +++ /dev/null @@ -1,13 +0,0 @@ -function Main.main 1 - call PongGame.newInstance 0 - pop temp 0 - call PongGame.getInstance 0 - pop local 0 - push local 0 - call PongGame.run 1 - pop temp 0 - push local 0 - call PongGame.dispose 1 - pop temp 0 - push constant 0 - return \ No newline at end of file diff --git a/compiler/test/resources/Pong/PongGame.vm b/compiler/test/resources/Pong/PongGame.vm deleted file mode 100644 index 82fb88a5..00000000 --- a/compiler/test/resources/Pong/PongGame.vm +++ /dev/null @@ -1,321 +0,0 @@ -function PongGame.new 0 - push constant 7 - call Memory.alloc 1 - pop pointer 0 - call Screen.clearScreen 0 - pop temp 0 - push constant 50 - pop this 6 - push constant 230 - push constant 229 - push this 6 - push constant 7 - call Bat.new 4 - pop this 0 - push constant 253 - push constant 222 - push constant 0 - push constant 511 - push constant 0 - push constant 229 - call Ball.new 6 - pop this 1 - push this 1 - push constant 400 - push constant 0 - call Ball.setDestination 3 - pop temp 0 - push constant 0 - push constant 238 - push constant 511 - push constant 240 - call Screen.drawRectangle 4 - pop temp 0 - push constant 22 - push constant 0 - call Output.moveCursor 2 - pop temp 0 - push constant 8 - call String.new 1 - push constant 83 - call String.appendChar 2 - push constant 99 - call String.appendChar 2 - push constant 111 - call String.appendChar 2 - push constant 114 - call String.appendChar 2 - push constant 101 - call String.appendChar 2 - push constant 58 - call String.appendChar 2 - push constant 32 - call String.appendChar 2 - push constant 48 - call String.appendChar 2 - call Output.printString 1 - pop temp 0 - push constant 0 - pop this 3 - push constant 0 - pop this 4 - push constant 0 - pop this 2 - push constant 0 - pop this 5 - push pointer 0 - return -function PongGame.dispose 0 - push argument 0 - pop pointer 0 - push this 0 - call Bat.dispose 1 - pop temp 0 - push this 1 - call Ball.dispose 1 - pop temp 0 - push pointer 0 - call Memory.deAlloc 1 - pop temp 0 - push constant 0 - return -function PongGame.newInstance 0 - call PongGame.new 0 - pop static 0 - push constant 0 - return -function PongGame.getInstance 0 - push static 0 - return -function PongGame.run 1 - push argument 0 - pop pointer 0 -label L0 - push this 3 - not - not - if-goto L1 -label L2 - push local 0 - push constant 0 - eq - push this 3 - not - and - not - if-goto L3 - call Keyboard.keyPressed 0 - pop local 0 - push this 0 - call Bat.move 1 - pop temp 0 - push pointer 0 - call PongGame.moveBall 1 - pop temp 0 - push constant 50 - call Sys.wait 1 - pop temp 0 - goto L2 -label L3 - push local 0 - push constant 130 - eq - not - if-goto L5 - push this 0 - push constant 1 - call Bat.setDirection 2 - pop temp 0 - goto L4 -label L5 - push local 0 - push constant 132 - eq - not - if-goto L7 - push this 0 - push constant 2 - call Bat.setDirection 2 - pop temp 0 - goto L6 -label L7 - push local 0 - push constant 140 - eq - not - if-goto L9 - push constant 1 - neg - pop this 3 - goto L8 -label L9 -label L8 -label L6 -label L4 -label L10 - push local 0 - push constant 0 - eq - not - push this 3 - not - and - not - if-goto L11 - call Keyboard.keyPressed 0 - pop local 0 - push this 0 - call Bat.move 1 - pop temp 0 - push pointer 0 - call PongGame.moveBall 1 - pop temp 0 - push constant 50 - call Sys.wait 1 - pop temp 0 - goto L10 -label L11 - goto L0 -label L1 - push this 3 - not - if-goto L13 - push constant 10 - push constant 27 - call Output.moveCursor 2 - pop temp 0 - push constant 9 - call String.new 1 - push constant 71 - call String.appendChar 2 - push constant 97 - call String.appendChar 2 - push constant 109 - call String.appendChar 2 - push constant 101 - call String.appendChar 2 - push constant 32 - call String.appendChar 2 - push constant 79 - call String.appendChar 2 - push constant 118 - call String.appendChar 2 - push constant 101 - call String.appendChar 2 - push constant 114 - call String.appendChar 2 - call Output.printString 1 - pop temp 0 - goto L12 -label L13 -label L12 - push constant 0 - return -function PongGame.moveBall 5 - push argument 0 - pop pointer 0 - push this 1 - call Ball.move 1 - pop this 2 - push this 2 - push constant 0 - gt - push this 2 - push this 5 - eq - not - and - not - if-goto L15 - push this 2 - pop this 5 - push constant 0 - pop local 0 - push this 0 - call Bat.getLeft 1 - pop local 1 - push this 0 - call Bat.getRight 1 - pop local 2 - push this 1 - call Ball.getLeft 1 - pop local 3 - push this 1 - call Ball.getRight 1 - pop local 4 - push this 2 - push constant 4 - eq - not - if-goto L17 - push local 1 - push local 4 - gt - push local 2 - push local 3 - lt - or - pop this 3 - push this 3 - not - not - if-goto L19 - push local 4 - push local 1 - push constant 10 - add - lt - not - if-goto L21 - push constant 1 - neg - pop local 0 - goto L20 -label L21 - push local 3 - push local 2 - push constant 10 - sub - gt - not - if-goto L23 - push constant 1 - pop local 0 - goto L22 -label L23 -label L22 -label L20 - push this 6 - push constant 2 - sub - pop this 6 - push this 0 - push this 6 - call Bat.setWidth 2 - pop temp 0 - push this 4 - push constant 1 - add - pop this 4 - push constant 22 - push constant 7 - call Output.moveCursor 2 - pop temp 0 - push this 4 - call Output.printInt 1 - pop temp 0 - goto L18 -label L19 -label L18 - goto L16 -label L17 -label L16 - push this 1 - push local 0 - call Ball.bounce 2 - pop temp 0 - goto L14 -label L15 -label L14 - push constant 0 - return \ No newline at end of file diff --git a/compiler/test/symbol.table.listener.test.ts b/compiler/test/symbol.table.listener.test.ts new file mode 100644 index 00000000..571e0656 --- /dev/null +++ b/compiler/test/symbol.table.listener.test.ts @@ -0,0 +1,57 @@ +import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; +import { ErrorListener } from "../src/error.listener"; +import { GenericSymbol, SymbolTableListener } from "../src/symbol.table.istener"; +import { DuplicatedSubroutineError } from "../src/error"; +import { parseJack, getTestResourcePath } from "./test.helper"; +import fs from 'fs'; +import path from "path"; + +describe('Global symbol table', () => { + + test("should fail on duplicated subroutine", () => { + const filePath = getTestResourcePath("DuplicatedSubroutine.jack"); + const errorListener = ErrorListener.getInstance() + const globalSymbolsListener = traverseTree(errorListener, filePath); + const symbolsErrors = globalSymbolsListener.errors + expect(globalSymbolsListener.errors.length).toBe(1) + expect(symbolsErrors[0]).toBeInstanceOf(DuplicatedSubroutineError) + }) + + test("basic", () => { + const expected = { + 'Fraction': {}, + 'Fraction.new': { subroutineParameterCount: 2 }, + 'Fraction.reduce': { subroutineParameterCount: 0 }, + 'Fraction.getNumerator': { subroutineParameterCount: 0 }, + 'Fraction.getDenominator': { subroutineParameterCount: 0 }, + 'Fraction.plus': { subroutineParameterCount: 1 }, + 'Fraction.dispose': { subroutineParameterCount: 0 }, + 'Fraction.print': { subroutineParameterCount: 0 }, + 'Fraction.gcd': { subroutineParameterCount: 2 }, + 'Main': {}, + 'Main.main': { subroutineParameterCount: 0 } + } + let globalSymbolsListener = new SymbolTableListener() + + const testFolder = getTestResourcePath("Fraction"); + const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); + const symbols = [] + for (const filePath of files) { + + const errorListener = ErrorListener.getInstance() + globalSymbolsListener = traverseTree(errorListener, filePath, globalSymbolsListener); + } + expect(globalSymbolsListener.globalSymbolTable).toEqual(expected) + + }) +}) +function traverseTree(errorListener: ErrorListener, filePath: string, globalSymbolsListener = new SymbolTableListener()) { + errorListener.filepath = filePath; + const tree = parseJack(filePath, errorListener); + + expect(errorListener.error).toBe(false); + + ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); + return globalSymbolsListener; +} + diff --git a/compiler/test/symbol.table.test.ts b/compiler/test/symbol.table.test.ts deleted file mode 100644 index 42cc120f..00000000 --- a/compiler/test/symbol.table.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Scope, SymbolTable, SymbolTableEntry } from "../src/symbol.table"; - -describe('symbol table', () => { - test('basic', () => { - const symbolTable = new SymbolTable(); - symbolTable.insert(new SymbolTableEntry('test', 'int', Scope.local)); - expect(symbolTable.lookup('test')).toEqual(new SymbolTableEntry('test', 'int', Scope.local)); - expect(symbolTable.lookup('a')).toBeUndefined(); - }); -}); \ No newline at end of file diff --git a/compiler/test/test.helper.ts b/compiler/test/test.helper.ts new file mode 100644 index 00000000..974fbd1d --- /dev/null +++ b/compiler/test/test.helper.ts @@ -0,0 +1,30 @@ +import { ANTLRErrorListener, CharStreams, CommonTokenStream } from "antlr4ts"; +import { JackParser } from "../src/generated/JackParser"; +import { JackLexer } from "../src/generated/JackLexer"; +import fs from 'fs'; +import path from "path"; + +export function parseJack(filePath: string, errorListener?: ANTLRErrorListener, trace = false) { + const f = fs.readFileSync(filePath, 'utf8'); + const inputStream = CharStreams.fromString(f); + const lexer = new JackLexer(inputStream); + if (errorListener) { + + lexer.removeErrorListeners(); + lexer.addErrorListener(errorListener); + } + + const tokenStream = new CommonTokenStream(lexer); + expect(tokenStream.getTokens.length).toBeGreaterThan(0) + const parser = new JackParser(tokenStream); + parser.isTrace = trace; + if (errorListener != undefined) { + parser.removeErrorListeners(); + parser.addErrorListener(errorListener); + } + return parser.program(); +} + +export function getTestResourcePath(relativePath: string) { + return path.join(__dirname, "resources", relativePath); +} From 1f3b3f458da7b86a75e50735a8231d28acc16096 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Wed, 25 Sep 2024 00:27:15 +0200 Subject: [PATCH 03/87] WIP --- compiler/src/compiler.ts | 58 ++++++++++++++++++++++++++++-- compiler/src/validator.listener.ts | 32 +++++++++++++++++ compiler/test/parser.test.ts | 1 - 3 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 compiler/src/validator.listener.ts diff --git a/compiler/src/compiler.ts b/compiler/src/compiler.ts index 141124a9..5da9b80b 100644 --- a/compiler/src/compiler.ts +++ b/compiler/src/compiler.ts @@ -1,6 +1,60 @@ - +import path from "path"; +import { SymbolTableListener } from "./symbol.table.istener"; +import fs from "fs"; +import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; +import { JackParser } from "./generated/JackParser"; +import { CharStreams, CommonTokenStream } from "antlr4ts"; +import { JackLexer } from "./generated/JackLexer"; +import { ErrorListener } from "./error.listener"; +import { ValidatorListener } from "./validator.listener"; export default class Compiler { - static compile(source: string): string { + static compile(dir: string): string { + + const globalSymbolsListener = new SymbolTableListener(); + const files = fs.readdirSync(dir).filter(file => file.endsWith(".jack")).map(file => path.join(dir, file)); + for (const filePath of files) { + const errorListener = ErrorListener.getInstance() + errorListener.filepath = filePath; const f = fs.readFileSync(filePath, 'utf8'); + const inputStream = CharStreams.fromString(f); + const lexer = new JackLexer(inputStream); + if (errorListener) { + + lexer.removeErrorListeners(); + lexer.addErrorListener(errorListener); + } + + const tokenStream = new CommonTokenStream(lexer); + expect(tokenStream.getTokens.length).toBeGreaterThan(0) + const parser = new JackParser(tokenStream); + // parser.isTrace = trace; + if (errorListener != undefined) { + parser.removeErrorListeners(); + parser.addErrorListener(errorListener); + } + const tree = parser.program(); + //TODO add error handling here + if (errorListener.error) { + console.error(errorListener.filepath + " has syntax errors"); + continue + } + // console.log(tree.toStringTree(parser.ruleNames)); + + ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); + const symbolsErrors = globalSymbolsListener.errors.join("\n") + try { + expect(globalSymbolsListener.errors.length).toBe(0) + } + catch (e) { + throw new Error(symbolsErrors); + } + globalSymbolsListener.resetErrors(); + if (globalSymbolsListener.className != path.parse(filePath).name) { + console.log("Class name does not match file name: " + globalSymbolsListener.className + " vs " + path.parse(filePath).name); + } + + //TODO: add OS builtin functions + const validator = new ValidatorListener(globalSymbolsListener.globalSymbolTable); + } return ""; } } \ No newline at end of file diff --git a/compiler/src/validator.listener.ts b/compiler/src/validator.listener.ts new file mode 100644 index 00000000..5fe5161c --- /dev/null +++ b/compiler/src/validator.listener.ts @@ -0,0 +1,32 @@ +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { JackParserListener } from "./generated/JackParserListener"; +import { GenericSymbol } from "./symbol.table.istener"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; + +export class ValidatorListener implements JackParserListener, ParseTreeListener { + /** + * List of validations rules: + * - variable declaration - validate duplicate variable declarations + * - let statement - validate variable is declared + * - `Subroutine ${subroutine.name.value}: not all code paths return a value`, + * - `A non void subroutine must return a value`, + * - Undeclared variable + * - Unknown type for return type, class variable, or method local var + * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface + * - validate arg number + * - `Method ${className}.${subroutineName} was called as a function/constructor` + * - Subroutine was called as a method + * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` + * - `Class ${className} doesn't exist` + */ + + //TODO: change + localSymbolTable: Record = {}; + constructor(private globalSymbolTable: Record) { } + + + + + //to fix compiler error + visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; +} \ No newline at end of file diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index 7e27d739..c594162a 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -55,5 +55,4 @@ function testJackDir(testFolder: string): void { } globalSymbolsListener.resetErrors(); } - //TODO: improve this } From 240aedc5eaccf00ca24c3c02b0ac4999b92ee62e Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:00:47 +0200 Subject: [PATCH 04/87] WIP --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0bf2afcb..f55ad197 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ out npm-debug.log* yarn-debug.log* yarn-error.log* +*/.vscode \ No newline at end of file From 3d6f8be5c578e07cf1a53a7a140912ededb1131c Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:01:24 +0200 Subject: [PATCH 05/87] WIP --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f55ad197..94b737c6 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ out npm-debug.log* yarn-debug.log* yarn-error.log* -*/.vscode \ No newline at end of file +*/.vscode/numbered-bookmars.json \ No newline at end of file From 49075d705b86643d10aec3a31b15bcaa3398bfee Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:01:46 +0200 Subject: [PATCH 06/87] WIP --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 94b737c6..ec425396 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,4 @@ out npm-debug.log* yarn-debug.log* yarn-error.log* -*/.vscode/numbered-bookmars.json \ No newline at end of file +**/.vscode/numbered-bookmars.json \ No newline at end of file From f9dab02aa3fbc8cec7b2b189d1a839803a0acf97 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:02:27 +0200 Subject: [PATCH 07/87] Add symbol table. Add validator skeleton --- compiler/parser-gen/JackParser.g4 | 15 +- compiler/src/VIsitor.ts | 102 +-- compiler/src/compiler.ts | 4 +- compiler/src/error.ts | 12 +- compiler/src/generated/JackParser.interp | 6 +- compiler/src/generated/JackParser.ts | 583 +++++++++--------- compiler/src/generated/JackParserListener.ts | 84 +-- compiler/src/generated/JackParserVisitor.ts | 46 +- compiler/src/{ => listener}/error.listener.ts | 0 .../symbol.table.listener.ts} | 8 +- compiler/src/listener/validator.listener.ts | 82 +++ compiler/src/validator.listener.ts | 32 - compiler/test/local.symbol.table.test.ts | 37 ++ compiler/test/parser.test.ts | 14 +- compiler/test/symbol.table.listener.test.ts | 29 +- compiler/test/test.helper.ts | 20 +- compiler/test/validator.listener.test.ts | 20 + 17 files changed, 604 insertions(+), 490 deletions(-) rename compiler/src/{ => listener}/error.listener.ts (100%) rename compiler/src/{symbol.table.istener.ts => listener/symbol.table.listener.ts} (87%) create mode 100644 compiler/src/listener/validator.listener.ts delete mode 100644 compiler/src/validator.listener.ts create mode 100644 compiler/test/local.symbol.table.test.ts create mode 100644 compiler/test/validator.listener.test.ts diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/parser-gen/JackParser.g4 index 4634c7b2..242c8066 100644 --- a/compiler/parser-gen/JackParser.g4 +++ b/compiler/parser-gen/JackParser.g4 @@ -7,21 +7,21 @@ options { program: classDeclaration EOF; classDeclaration: - CLASS className LBRACE classVarDec* subroutineDec* RBRACE; + CLASS className LBRACE classVarDec* subroutineDeclaration* RBRACE; className: IDENTIFIER; classVarDec: STATIC fieldList SEMICOLON # staticFieldDeclaration | FIELD fieldList SEMICOLON # fieldDeclaration; fieldList: varType fieldName ( COMMA fieldName)*; fieldName: IDENTIFIER; -subroutineDec: {console.log("Subroutine")} +subroutineDeclaration: CONSTRUCTOR subroutineDecWithoutType # constructor | METHOD subroutineDecWithoutType # method | FUNCTION subroutineDecWithoutType # function; subroutineDecWithoutType: subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; subroutineName: IDENTIFIER; -subroutineReturnType: varType | VOID; +subroutineReturnType: varType | VOID; varType: INT | CHAR | BOOLEAN | IDENTIFIER; @@ -29,9 +29,9 @@ parameterList: (parameter (COMMA parameter)*)?; parameter: varType parameterName; parameterName: IDENTIFIER; subroutineBody: - LBRACE varDec* statements RBRACE; + LBRACE varDeclaration* statements RBRACE; -varDec: VAR varType varName (COMMA IDENTIFIER)* SEMICOLON; +varDeclaration: VAR varType varName (COMMA varName)* SEMICOLON; varName: IDENTIFIER; statements: statement*; statement: @@ -63,7 +63,7 @@ returnStatement: RETURN expression? SEMICOLON; expressionList: (expression (COMMA expression)*)?; expression: - binaryOperation = expression binaryOperator expression + binaryOperation = expression binaryOperator expression | constant | IDENTIFIER | subroutineCall @@ -92,5 +92,4 @@ binaryOperator: | OR | LESS_THAN | GREATER_THAN - | EQUALS; - + | EQUALS; \ No newline at end of file diff --git a/compiler/src/VIsitor.ts b/compiler/src/VIsitor.ts index 04de7b8f..32486b53 100644 --- a/compiler/src/VIsitor.ts +++ b/compiler/src/VIsitor.ts @@ -1,55 +1,55 @@ -import { ClassDeclarationContext, ClassNameContext, SubroutineDecContext } from './generated/JackParser'; -import { JackParserVisitor } from './generated/JackParserVisitor'; -import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor' +// import { ClassDeclarationContext, ClassNameContext, SubroutineDecContext } from './generated/JackParser'; +// import { JackParserVisitor } from './generated/JackParserVisitor'; +// import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor' -export class Visitor extends AbstractParseTreeVisitor implements JackParserVisitor { - protected override defaultResult(): string { - return ""; - } +// export class Visitor extends AbstractParseTreeVisitor implements JackParserVisitor { +// protected override defaultResult(): string { +// return ""; +// } - override aggregateResult(aggregate: string, nextResult: string) { - return aggregate + nextResult - } - visitSubroutineDec(ctx: SubroutineDecContext): string { - const c = ctx.parent - return "" + super.visitChildren(ctx); - }; +// override aggregateResult(aggregate: string, nextResult: string) { +// return aggregate + nextResult +// } +// visitSubroutineDec(ctx: SubroutineDecContext): string { +// const c = ctx.parent +// return "" + super.visitChildren(ctx); +// }; -} +// } -/** - * // Compiled Main.jack: -function Main.main 0 - push constant 12 - call String.new 1 - push constant 72 - call String.appendChar 2 - push constant 101 - call String.appendChar 2 - push constant 108 - call String.appendChar 2 - push constant 108 - call String.appendChar 2 - push constant 111 - call String.appendChar 2 - push constant 32 - call String.appendChar 2 - push constant 119 - call String.appendChar 2 - push constant 111 - call String.appendChar 2 - push constant 114 - call String.appendChar 2 - push constant 108 - call String.appendChar 2 - push constant 100 - call String.appendChar 2 - push constant 33 - call String.appendChar 2 - call Output.printString 1 - pop temp 0 - call Output.println 0 - pop temp 0 - push constant 0 - return - */ \ No newline at end of file +// /** +// * // Compiled Main.jack: +// function Main.main 0 +// push constant 12 +// call String.new 1 +// push constant 72 +// call String.appendChar 2 +// push constant 101 +// call String.appendChar 2 +// push constant 108 +// call String.appendChar 2 +// push constant 108 +// call String.appendChar 2 +// push constant 111 +// call String.appendChar 2 +// push constant 32 +// call String.appendChar 2 +// push constant 119 +// call String.appendChar 2 +// push constant 111 +// call String.appendChar 2 +// push constant 114 +// call String.appendChar 2 +// push constant 108 +// call String.appendChar 2 +// push constant 100 +// call String.appendChar 2 +// push constant 33 +// call String.appendChar 2 +// call Output.printString 1 +// pop temp 0 +// call Output.println 0 +// pop temp 0 +// push constant 0 +// return +// */ \ No newline at end of file diff --git a/compiler/src/compiler.ts b/compiler/src/compiler.ts index 5da9b80b..9a2e92bf 100644 --- a/compiler/src/compiler.ts +++ b/compiler/src/compiler.ts @@ -5,8 +5,8 @@ import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; import { JackParser } from "./generated/JackParser"; import { CharStreams, CommonTokenStream } from "antlr4ts"; import { JackLexer } from "./generated/JackLexer"; -import { ErrorListener } from "./error.listener"; -import { ValidatorListener } from "./validator.listener"; +import { ErrorListener } from "./listener/error.listener"; +import { ValidatorListener } from "./listener/validator.listener"; export default class Compiler { static compile(dir: string): string { diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 52ad716d..7ab2df10 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -14,4 +14,14 @@ export class DuplicatedSubroutineError extends JackCompilerError { Object.setPrototypeOf(this, DuplicatedSubroutineError.prototype); } -} \ No newline at end of file +} + +export class DuplicatedVarException extends JackCompilerError { + constructor(varName: string) { + super("Duplicated variable " + varName); + + // Set the prototype explicitly. + Object.setPrototypeOf(this, DuplicatedSubroutineError.prototype); + } + +} diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp index 9df49bb4..3b0a4aa4 100644 --- a/compiler/src/generated/JackParser.interp +++ b/compiler/src/generated/JackParser.interp @@ -103,7 +103,7 @@ className classVarDec fieldList fieldName -subroutineDec +subroutineDeclaration subroutineDecWithoutType subroutineName subroutineReturnType @@ -112,7 +112,7 @@ parameterList parameter parameterName subroutineBody -varDec +varDeclaration varName statements statement @@ -133,4 +133,4 @@ binaryOperator atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 289, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 76, 10, 3, 12, 3, 14, 3, 79, 11, 3, 3, 3, 7, 3, 82, 10, 3, 12, 3, 14, 3, 85, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 99, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 105, 10, 6, 12, 6, 14, 6, 108, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 119, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 132, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 139, 10, 13, 12, 13, 14, 13, 142, 11, 13, 5, 13, 144, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 153, 10, 16, 12, 16, 14, 16, 156, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 166, 10, 17, 12, 17, 14, 17, 169, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 7, 19, 176, 10, 19, 12, 19, 14, 19, 179, 11, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 186, 10, 20, 3, 21, 3, 21, 3, 21, 5, 21, 191, 10, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 209, 10, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 5, 25, 235, 10, 25, 3, 26, 3, 26, 5, 26, 239, 10, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 7, 27, 246, 10, 27, 12, 27, 14, 27, 249, 11, 27, 5, 27, 251, 10, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 260, 10, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 266, 10, 28, 12, 28, 14, 28, 269, 11, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 2, 2, 3, 54, 35, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 2, 7, 4, 2, 10, 12, 46, 46, 3, 2, 45, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 283, 2, 68, 3, 2, 2, 2, 4, 71, 3, 2, 2, 2, 6, 88, 3, 2, 2, 2, 8, 98, 3, 2, 2, 2, 10, 100, 3, 2, 2, 2, 12, 109, 3, 2, 2, 2, 14, 118, 3, 2, 2, 2, 16, 120, 3, 2, 2, 2, 18, 127, 3, 2, 2, 2, 20, 131, 3, 2, 2, 2, 22, 133, 3, 2, 2, 2, 24, 143, 3, 2, 2, 2, 26, 145, 3, 2, 2, 2, 28, 148, 3, 2, 2, 2, 30, 150, 3, 2, 2, 2, 32, 160, 3, 2, 2, 2, 34, 172, 3, 2, 2, 2, 36, 177, 3, 2, 2, 2, 38, 185, 3, 2, 2, 2, 40, 187, 3, 2, 2, 2, 42, 196, 3, 2, 2, 2, 44, 210, 3, 2, 2, 2, 46, 218, 3, 2, 2, 2, 48, 234, 3, 2, 2, 2, 50, 236, 3, 2, 2, 2, 52, 250, 3, 2, 2, 2, 54, 259, 3, 2, 2, 2, 56, 270, 3, 2, 2, 2, 58, 274, 3, 2, 2, 2, 60, 277, 3, 2, 2, 2, 62, 282, 3, 2, 2, 2, 64, 284, 3, 2, 2, 2, 66, 286, 3, 2, 2, 2, 68, 69, 5, 4, 3, 2, 69, 70, 7, 2, 2, 3, 70, 3, 3, 2, 2, 2, 71, 72, 7, 3, 2, 2, 72, 73, 5, 6, 4, 2, 73, 77, 7, 20, 2, 2, 74, 76, 5, 8, 5, 2, 75, 74, 3, 2, 2, 2, 76, 79, 3, 2, 2, 2, 77, 75, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 83, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 80, 82, 5, 14, 8, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 86, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 87, 7, 21, 2, 2, 87, 5, 3, 2, 2, 2, 88, 89, 7, 46, 2, 2, 89, 7, 3, 2, 2, 2, 90, 91, 7, 8, 2, 2, 91, 92, 5, 10, 6, 2, 92, 93, 7, 28, 2, 2, 93, 99, 3, 2, 2, 2, 94, 95, 7, 7, 2, 2, 95, 96, 5, 10, 6, 2, 96, 97, 7, 28, 2, 2, 97, 99, 3, 2, 2, 2, 98, 90, 3, 2, 2, 2, 98, 94, 3, 2, 2, 2, 99, 9, 3, 2, 2, 2, 100, 101, 5, 22, 12, 2, 101, 106, 5, 12, 7, 2, 102, 103, 7, 27, 2, 2, 103, 105, 5, 12, 7, 2, 104, 102, 3, 2, 2, 2, 105, 108, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 106, 107, 3, 2, 2, 2, 107, 11, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 109, 110, 7, 46, 2, 2, 110, 13, 3, 2, 2, 2, 111, 112, 8, 8, 1, 2, 112, 113, 7, 4, 2, 2, 113, 119, 5, 16, 9, 2, 114, 115, 7, 6, 2, 2, 115, 119, 5, 16, 9, 2, 116, 117, 7, 5, 2, 2, 117, 119, 5, 16, 9, 2, 118, 111, 3, 2, 2, 2, 118, 114, 3, 2, 2, 2, 118, 116, 3, 2, 2, 2, 119, 15, 3, 2, 2, 2, 120, 121, 5, 20, 11, 2, 121, 122, 5, 18, 10, 2, 122, 123, 7, 22, 2, 2, 123, 124, 5, 24, 13, 2, 124, 125, 7, 23, 2, 2, 125, 126, 5, 30, 16, 2, 126, 17, 3, 2, 2, 2, 127, 128, 7, 46, 2, 2, 128, 19, 3, 2, 2, 2, 129, 132, 5, 22, 12, 2, 130, 132, 7, 13, 2, 2, 131, 129, 3, 2, 2, 2, 131, 130, 3, 2, 2, 2, 132, 21, 3, 2, 2, 2, 133, 134, 9, 2, 2, 2, 134, 23, 3, 2, 2, 2, 135, 140, 5, 26, 14, 2, 136, 137, 7, 27, 2, 2, 137, 139, 5, 26, 14, 2, 138, 136, 3, 2, 2, 2, 139, 142, 3, 2, 2, 2, 140, 138, 3, 2, 2, 2, 140, 141, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 143, 135, 3, 2, 2, 2, 143, 144, 3, 2, 2, 2, 144, 25, 3, 2, 2, 2, 145, 146, 5, 22, 12, 2, 146, 147, 5, 28, 15, 2, 147, 27, 3, 2, 2, 2, 148, 149, 7, 46, 2, 2, 149, 29, 3, 2, 2, 2, 150, 154, 7, 20, 2, 2, 151, 153, 5, 32, 17, 2, 152, 151, 3, 2, 2, 2, 153, 156, 3, 2, 2, 2, 154, 152, 3, 2, 2, 2, 154, 155, 3, 2, 2, 2, 155, 157, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 157, 158, 5, 36, 19, 2, 158, 159, 7, 21, 2, 2, 159, 31, 3, 2, 2, 2, 160, 161, 7, 9, 2, 2, 161, 162, 5, 22, 12, 2, 162, 167, 5, 34, 18, 2, 163, 164, 7, 27, 2, 2, 164, 166, 7, 46, 2, 2, 165, 163, 3, 2, 2, 2, 166, 169, 3, 2, 2, 2, 167, 165, 3, 2, 2, 2, 167, 168, 3, 2, 2, 2, 168, 170, 3, 2, 2, 2, 169, 167, 3, 2, 2, 2, 170, 171, 7, 28, 2, 2, 171, 33, 3, 2, 2, 2, 172, 173, 7, 46, 2, 2, 173, 35, 3, 2, 2, 2, 174, 176, 5, 38, 20, 2, 175, 174, 3, 2, 2, 2, 176, 179, 3, 2, 2, 2, 177, 175, 3, 2, 2, 2, 177, 178, 3, 2, 2, 2, 178, 37, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 180, 186, 5, 40, 21, 2, 181, 186, 5, 42, 22, 2, 182, 186, 5, 44, 23, 2, 183, 186, 5, 46, 24, 2, 184, 186, 5, 50, 26, 2, 185, 180, 3, 2, 2, 2, 185, 181, 3, 2, 2, 2, 185, 182, 3, 2, 2, 2, 185, 183, 3, 2, 2, 2, 185, 184, 3, 2, 2, 2, 186, 39, 3, 2, 2, 2, 187, 190, 7, 14, 2, 2, 188, 191, 7, 46, 2, 2, 189, 191, 5, 60, 31, 2, 190, 188, 3, 2, 2, 2, 190, 189, 3, 2, 2, 2, 191, 192, 3, 2, 2, 2, 192, 193, 7, 29, 2, 2, 193, 194, 5, 54, 28, 2, 194, 195, 7, 28, 2, 2, 195, 41, 3, 2, 2, 2, 196, 197, 7, 16, 2, 2, 197, 198, 7, 22, 2, 2, 198, 199, 5, 54, 28, 2, 199, 200, 7, 23, 2, 2, 200, 201, 7, 20, 2, 2, 201, 202, 5, 36, 19, 2, 202, 208, 7, 21, 2, 2, 203, 204, 7, 17, 2, 2, 204, 205, 7, 20, 2, 2, 205, 206, 5, 36, 19, 2, 206, 207, 7, 21, 2, 2, 207, 209, 3, 2, 2, 2, 208, 203, 3, 2, 2, 2, 208, 209, 3, 2, 2, 2, 209, 43, 3, 2, 2, 2, 210, 211, 7, 18, 2, 2, 211, 212, 7, 22, 2, 2, 212, 213, 5, 54, 28, 2, 213, 214, 7, 23, 2, 2, 214, 215, 7, 20, 2, 2, 215, 216, 5, 36, 19, 2, 216, 217, 7, 21, 2, 2, 217, 45, 3, 2, 2, 2, 218, 219, 7, 15, 2, 2, 219, 220, 5, 48, 25, 2, 220, 221, 7, 28, 2, 2, 221, 47, 3, 2, 2, 2, 222, 223, 7, 46, 2, 2, 223, 224, 7, 22, 2, 2, 224, 225, 5, 52, 27, 2, 225, 226, 7, 23, 2, 2, 226, 235, 3, 2, 2, 2, 227, 228, 9, 3, 2, 2, 228, 229, 7, 26, 2, 2, 229, 230, 7, 46, 2, 2, 230, 231, 7, 22, 2, 2, 231, 232, 5, 52, 27, 2, 232, 233, 7, 23, 2, 2, 233, 235, 3, 2, 2, 2, 234, 222, 3, 2, 2, 2, 234, 227, 3, 2, 2, 2, 235, 49, 3, 2, 2, 2, 236, 238, 7, 19, 2, 2, 237, 239, 5, 54, 28, 2, 238, 237, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 241, 7, 28, 2, 2, 241, 51, 3, 2, 2, 2, 242, 247, 5, 54, 28, 2, 243, 244, 7, 27, 2, 2, 244, 246, 5, 54, 28, 2, 245, 243, 3, 2, 2, 2, 246, 249, 3, 2, 2, 2, 247, 245, 3, 2, 2, 2, 247, 248, 3, 2, 2, 2, 248, 251, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 250, 242, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 53, 3, 2, 2, 2, 252, 253, 8, 28, 1, 2, 253, 260, 5, 62, 32, 2, 254, 260, 7, 46, 2, 2, 255, 260, 5, 48, 25, 2, 256, 260, 5, 60, 31, 2, 257, 260, 5, 58, 30, 2, 258, 260, 5, 56, 29, 2, 259, 252, 3, 2, 2, 2, 259, 254, 3, 2, 2, 2, 259, 255, 3, 2, 2, 2, 259, 256, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 258, 3, 2, 2, 2, 260, 267, 3, 2, 2, 2, 261, 262, 12, 9, 2, 2, 262, 263, 5, 66, 34, 2, 263, 264, 5, 54, 28, 10, 264, 266, 3, 2, 2, 2, 265, 261, 3, 2, 2, 2, 266, 269, 3, 2, 2, 2, 267, 265, 3, 2, 2, 2, 267, 268, 3, 2, 2, 2, 268, 55, 3, 2, 2, 2, 269, 267, 3, 2, 2, 2, 270, 271, 7, 22, 2, 2, 271, 272, 5, 54, 28, 2, 272, 273, 7, 23, 2, 2, 273, 57, 3, 2, 2, 2, 274, 275, 5, 64, 33, 2, 275, 276, 5, 54, 28, 2, 276, 59, 3, 2, 2, 2, 277, 278, 7, 46, 2, 2, 278, 279, 7, 24, 2, 2, 279, 280, 5, 54, 28, 2, 280, 281, 7, 25, 2, 2, 281, 61, 3, 2, 2, 2, 282, 283, 9, 4, 2, 2, 283, 63, 3, 2, 2, 2, 284, 285, 9, 5, 2, 2, 285, 65, 3, 2, 2, 2, 286, 287, 9, 6, 2, 2, 287, 67, 3, 2, 2, 2, 22, 77, 83, 98, 106, 118, 131, 140, 143, 154, 167, 177, 185, 190, 208, 234, 238, 247, 250, 259, 267] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 288, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 76, 10, 3, 12, 3, 14, 3, 79, 11, 3, 3, 3, 7, 3, 82, 10, 3, 12, 3, 14, 3, 85, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 99, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 105, 10, 6, 12, 6, 14, 6, 108, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 118, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 131, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 138, 10, 13, 12, 13, 14, 13, 141, 11, 13, 5, 13, 143, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 152, 10, 16, 12, 16, 14, 16, 155, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 165, 10, 17, 12, 17, 14, 17, 168, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 7, 19, 175, 10, 19, 12, 19, 14, 19, 178, 11, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 185, 10, 20, 3, 21, 3, 21, 3, 21, 5, 21, 190, 10, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 208, 10, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 5, 25, 234, 10, 25, 3, 26, 3, 26, 5, 26, 238, 10, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 7, 27, 245, 10, 27, 12, 27, 14, 27, 248, 11, 27, 5, 27, 250, 10, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 259, 10, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 265, 10, 28, 12, 28, 14, 28, 268, 11, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 2, 2, 3, 54, 35, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 2, 7, 4, 2, 10, 12, 46, 46, 3, 2, 45, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 282, 2, 68, 3, 2, 2, 2, 4, 71, 3, 2, 2, 2, 6, 88, 3, 2, 2, 2, 8, 98, 3, 2, 2, 2, 10, 100, 3, 2, 2, 2, 12, 109, 3, 2, 2, 2, 14, 117, 3, 2, 2, 2, 16, 119, 3, 2, 2, 2, 18, 126, 3, 2, 2, 2, 20, 130, 3, 2, 2, 2, 22, 132, 3, 2, 2, 2, 24, 142, 3, 2, 2, 2, 26, 144, 3, 2, 2, 2, 28, 147, 3, 2, 2, 2, 30, 149, 3, 2, 2, 2, 32, 159, 3, 2, 2, 2, 34, 171, 3, 2, 2, 2, 36, 176, 3, 2, 2, 2, 38, 184, 3, 2, 2, 2, 40, 186, 3, 2, 2, 2, 42, 195, 3, 2, 2, 2, 44, 209, 3, 2, 2, 2, 46, 217, 3, 2, 2, 2, 48, 233, 3, 2, 2, 2, 50, 235, 3, 2, 2, 2, 52, 249, 3, 2, 2, 2, 54, 258, 3, 2, 2, 2, 56, 269, 3, 2, 2, 2, 58, 273, 3, 2, 2, 2, 60, 276, 3, 2, 2, 2, 62, 281, 3, 2, 2, 2, 64, 283, 3, 2, 2, 2, 66, 285, 3, 2, 2, 2, 68, 69, 5, 4, 3, 2, 69, 70, 7, 2, 2, 3, 70, 3, 3, 2, 2, 2, 71, 72, 7, 3, 2, 2, 72, 73, 5, 6, 4, 2, 73, 77, 7, 20, 2, 2, 74, 76, 5, 8, 5, 2, 75, 74, 3, 2, 2, 2, 76, 79, 3, 2, 2, 2, 77, 75, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 83, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 80, 82, 5, 14, 8, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 86, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 87, 7, 21, 2, 2, 87, 5, 3, 2, 2, 2, 88, 89, 7, 46, 2, 2, 89, 7, 3, 2, 2, 2, 90, 91, 7, 8, 2, 2, 91, 92, 5, 10, 6, 2, 92, 93, 7, 28, 2, 2, 93, 99, 3, 2, 2, 2, 94, 95, 7, 7, 2, 2, 95, 96, 5, 10, 6, 2, 96, 97, 7, 28, 2, 2, 97, 99, 3, 2, 2, 2, 98, 90, 3, 2, 2, 2, 98, 94, 3, 2, 2, 2, 99, 9, 3, 2, 2, 2, 100, 101, 5, 22, 12, 2, 101, 106, 5, 12, 7, 2, 102, 103, 7, 27, 2, 2, 103, 105, 5, 12, 7, 2, 104, 102, 3, 2, 2, 2, 105, 108, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 106, 107, 3, 2, 2, 2, 107, 11, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 109, 110, 7, 46, 2, 2, 110, 13, 3, 2, 2, 2, 111, 112, 7, 4, 2, 2, 112, 118, 5, 16, 9, 2, 113, 114, 7, 6, 2, 2, 114, 118, 5, 16, 9, 2, 115, 116, 7, 5, 2, 2, 116, 118, 5, 16, 9, 2, 117, 111, 3, 2, 2, 2, 117, 113, 3, 2, 2, 2, 117, 115, 3, 2, 2, 2, 118, 15, 3, 2, 2, 2, 119, 120, 5, 20, 11, 2, 120, 121, 5, 18, 10, 2, 121, 122, 7, 22, 2, 2, 122, 123, 5, 24, 13, 2, 123, 124, 7, 23, 2, 2, 124, 125, 5, 30, 16, 2, 125, 17, 3, 2, 2, 2, 126, 127, 7, 46, 2, 2, 127, 19, 3, 2, 2, 2, 128, 131, 5, 22, 12, 2, 129, 131, 7, 13, 2, 2, 130, 128, 3, 2, 2, 2, 130, 129, 3, 2, 2, 2, 131, 21, 3, 2, 2, 2, 132, 133, 9, 2, 2, 2, 133, 23, 3, 2, 2, 2, 134, 139, 5, 26, 14, 2, 135, 136, 7, 27, 2, 2, 136, 138, 5, 26, 14, 2, 137, 135, 3, 2, 2, 2, 138, 141, 3, 2, 2, 2, 139, 137, 3, 2, 2, 2, 139, 140, 3, 2, 2, 2, 140, 143, 3, 2, 2, 2, 141, 139, 3, 2, 2, 2, 142, 134, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 25, 3, 2, 2, 2, 144, 145, 5, 22, 12, 2, 145, 146, 5, 28, 15, 2, 146, 27, 3, 2, 2, 2, 147, 148, 7, 46, 2, 2, 148, 29, 3, 2, 2, 2, 149, 153, 7, 20, 2, 2, 150, 152, 5, 32, 17, 2, 151, 150, 3, 2, 2, 2, 152, 155, 3, 2, 2, 2, 153, 151, 3, 2, 2, 2, 153, 154, 3, 2, 2, 2, 154, 156, 3, 2, 2, 2, 155, 153, 3, 2, 2, 2, 156, 157, 5, 36, 19, 2, 157, 158, 7, 21, 2, 2, 158, 31, 3, 2, 2, 2, 159, 160, 7, 9, 2, 2, 160, 161, 5, 22, 12, 2, 161, 166, 5, 34, 18, 2, 162, 163, 7, 27, 2, 2, 163, 165, 5, 34, 18, 2, 164, 162, 3, 2, 2, 2, 165, 168, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 166, 167, 3, 2, 2, 2, 167, 169, 3, 2, 2, 2, 168, 166, 3, 2, 2, 2, 169, 170, 7, 28, 2, 2, 170, 33, 3, 2, 2, 2, 171, 172, 7, 46, 2, 2, 172, 35, 3, 2, 2, 2, 173, 175, 5, 38, 20, 2, 174, 173, 3, 2, 2, 2, 175, 178, 3, 2, 2, 2, 176, 174, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 37, 3, 2, 2, 2, 178, 176, 3, 2, 2, 2, 179, 185, 5, 40, 21, 2, 180, 185, 5, 42, 22, 2, 181, 185, 5, 44, 23, 2, 182, 185, 5, 46, 24, 2, 183, 185, 5, 50, 26, 2, 184, 179, 3, 2, 2, 2, 184, 180, 3, 2, 2, 2, 184, 181, 3, 2, 2, 2, 184, 182, 3, 2, 2, 2, 184, 183, 3, 2, 2, 2, 185, 39, 3, 2, 2, 2, 186, 189, 7, 14, 2, 2, 187, 190, 7, 46, 2, 2, 188, 190, 5, 60, 31, 2, 189, 187, 3, 2, 2, 2, 189, 188, 3, 2, 2, 2, 190, 191, 3, 2, 2, 2, 191, 192, 7, 29, 2, 2, 192, 193, 5, 54, 28, 2, 193, 194, 7, 28, 2, 2, 194, 41, 3, 2, 2, 2, 195, 196, 7, 16, 2, 2, 196, 197, 7, 22, 2, 2, 197, 198, 5, 54, 28, 2, 198, 199, 7, 23, 2, 2, 199, 200, 7, 20, 2, 2, 200, 201, 5, 36, 19, 2, 201, 207, 7, 21, 2, 2, 202, 203, 7, 17, 2, 2, 203, 204, 7, 20, 2, 2, 204, 205, 5, 36, 19, 2, 205, 206, 7, 21, 2, 2, 206, 208, 3, 2, 2, 2, 207, 202, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 43, 3, 2, 2, 2, 209, 210, 7, 18, 2, 2, 210, 211, 7, 22, 2, 2, 211, 212, 5, 54, 28, 2, 212, 213, 7, 23, 2, 2, 213, 214, 7, 20, 2, 2, 214, 215, 5, 36, 19, 2, 215, 216, 7, 21, 2, 2, 216, 45, 3, 2, 2, 2, 217, 218, 7, 15, 2, 2, 218, 219, 5, 48, 25, 2, 219, 220, 7, 28, 2, 2, 220, 47, 3, 2, 2, 2, 221, 222, 7, 46, 2, 2, 222, 223, 7, 22, 2, 2, 223, 224, 5, 52, 27, 2, 224, 225, 7, 23, 2, 2, 225, 234, 3, 2, 2, 2, 226, 227, 9, 3, 2, 2, 227, 228, 7, 26, 2, 2, 228, 229, 7, 46, 2, 2, 229, 230, 7, 22, 2, 2, 230, 231, 5, 52, 27, 2, 231, 232, 7, 23, 2, 2, 232, 234, 3, 2, 2, 2, 233, 221, 3, 2, 2, 2, 233, 226, 3, 2, 2, 2, 234, 49, 3, 2, 2, 2, 235, 237, 7, 19, 2, 2, 236, 238, 5, 54, 28, 2, 237, 236, 3, 2, 2, 2, 237, 238, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 240, 7, 28, 2, 2, 240, 51, 3, 2, 2, 2, 241, 246, 5, 54, 28, 2, 242, 243, 7, 27, 2, 2, 243, 245, 5, 54, 28, 2, 244, 242, 3, 2, 2, 2, 245, 248, 3, 2, 2, 2, 246, 244, 3, 2, 2, 2, 246, 247, 3, 2, 2, 2, 247, 250, 3, 2, 2, 2, 248, 246, 3, 2, 2, 2, 249, 241, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 53, 3, 2, 2, 2, 251, 252, 8, 28, 1, 2, 252, 259, 5, 62, 32, 2, 253, 259, 7, 46, 2, 2, 254, 259, 5, 48, 25, 2, 255, 259, 5, 60, 31, 2, 256, 259, 5, 58, 30, 2, 257, 259, 5, 56, 29, 2, 258, 251, 3, 2, 2, 2, 258, 253, 3, 2, 2, 2, 258, 254, 3, 2, 2, 2, 258, 255, 3, 2, 2, 2, 258, 256, 3, 2, 2, 2, 258, 257, 3, 2, 2, 2, 259, 266, 3, 2, 2, 2, 260, 261, 12, 9, 2, 2, 261, 262, 5, 66, 34, 2, 262, 263, 5, 54, 28, 10, 263, 265, 3, 2, 2, 2, 264, 260, 3, 2, 2, 2, 265, 268, 3, 2, 2, 2, 266, 264, 3, 2, 2, 2, 266, 267, 3, 2, 2, 2, 267, 55, 3, 2, 2, 2, 268, 266, 3, 2, 2, 2, 269, 270, 7, 22, 2, 2, 270, 271, 5, 54, 28, 2, 271, 272, 7, 23, 2, 2, 272, 57, 3, 2, 2, 2, 273, 274, 5, 64, 33, 2, 274, 275, 5, 54, 28, 2, 275, 59, 3, 2, 2, 2, 276, 277, 7, 46, 2, 2, 277, 278, 7, 24, 2, 2, 278, 279, 5, 54, 28, 2, 279, 280, 7, 25, 2, 2, 280, 61, 3, 2, 2, 2, 281, 282, 9, 4, 2, 2, 282, 63, 3, 2, 2, 2, 283, 284, 9, 5, 2, 2, 284, 65, 3, 2, 2, 2, 285, 286, 9, 6, 2, 2, 286, 67, 3, 2, 2, 2, 22, 77, 83, 98, 106, 117, 130, 139, 142, 153, 166, 176, 184, 189, 207, 233, 237, 246, 249, 258, 266] \ No newline at end of file diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts index 4d61a407..487618d5 100644 --- a/compiler/src/generated/JackParser.ts +++ b/compiler/src/generated/JackParser.ts @@ -80,7 +80,7 @@ export class JackParser extends Parser { public static readonly RULE_classVarDec = 3; public static readonly RULE_fieldList = 4; public static readonly RULE_fieldName = 5; - public static readonly RULE_subroutineDec = 6; + public static readonly RULE_subroutineDeclaration = 6; public static readonly RULE_subroutineDecWithoutType = 7; public static readonly RULE_subroutineName = 8; public static readonly RULE_subroutineReturnType = 9; @@ -89,7 +89,7 @@ export class JackParser extends Parser { public static readonly RULE_parameter = 12; public static readonly RULE_parameterName = 13; public static readonly RULE_subroutineBody = 14; - public static readonly RULE_varDec = 15; + public static readonly RULE_varDeclaration = 15; public static readonly RULE_varName = 16; public static readonly RULE_statements = 17; public static readonly RULE_statement = 18; @@ -110,12 +110,12 @@ export class JackParser extends Parser { // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ "program", "classDeclaration", "className", "classVarDec", "fieldList", - "fieldName", "subroutineDec", "subroutineDecWithoutType", "subroutineName", + "fieldName", "subroutineDeclaration", "subroutineDecWithoutType", "subroutineName", "subroutineReturnType", "varType", "parameterList", "parameter", "parameterName", - "subroutineBody", "varDec", "varName", "statements", "statement", "letStatement", - "ifStatement", "whileStatement", "doStatement", "subroutineCall", "returnStatement", - "expressionList", "expression", "groupedExpression", "unaryOp", "arrayAccess", - "constant", "unaryOperator", "binaryOperator", + "subroutineBody", "varDeclaration", "varName", "statements", "statement", + "letStatement", "ifStatement", "whileStatement", "doStatement", "subroutineCall", + "returnStatement", "expressionList", "expression", "groupedExpression", + "unaryOp", "arrayAccess", "constant", "unaryOperator", "binaryOperator", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -223,7 +223,7 @@ export class JackParser extends Parser { { { this.state = 78; - this.subroutineDec(); + this.subroutineDeclaration(); } } this.state = 83; @@ -393,21 +393,20 @@ export class JackParser extends Parser { return _localctx; } // @RuleVersion(0) - public subroutineDec(): SubroutineDecContext { - let _localctx: SubroutineDecContext = new SubroutineDecContext(this._ctx, this.state); - this.enterRule(_localctx, 12, JackParser.RULE_subroutineDec); + public subroutineDeclaration(): SubroutineDeclarationContext { + let _localctx: SubroutineDeclarationContext = new SubroutineDeclarationContext(this._ctx, this.state); + this.enterRule(_localctx, 12, JackParser.RULE_subroutineDeclaration); try { - this.state = 116; + this.state = 115; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.CONSTRUCTOR: _localctx = new ConstructorContext(_localctx); this.enterOuterAlt(_localctx, 1); { - console.log("Subroutine") - this.state = 110; + this.state = 109; this.match(JackParser.CONSTRUCTOR); - this.state = 111; + this.state = 110; this.subroutineDecWithoutType(); } break; @@ -415,9 +414,9 @@ export class JackParser extends Parser { _localctx = new MethodContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 112; + this.state = 111; this.match(JackParser.METHOD); - this.state = 113; + this.state = 112; this.subroutineDecWithoutType(); } break; @@ -425,9 +424,9 @@ export class JackParser extends Parser { _localctx = new FunctionContext(_localctx); this.enterOuterAlt(_localctx, 3); { - this.state = 114; + this.state = 113; this.match(JackParser.FUNCTION); - this.state = 115; + this.state = 114; this.subroutineDecWithoutType(); } break; @@ -456,17 +455,17 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 118; + this.state = 117; this.subroutineReturnType(); - this.state = 119; + this.state = 118; this.subroutineName(); - this.state = 120; + this.state = 119; this.match(JackParser.LPAREN); - this.state = 121; + this.state = 120; this.parameterList(); - this.state = 122; + this.state = 121; this.match(JackParser.RPAREN); - this.state = 123; + this.state = 122; this.subroutineBody(); } } @@ -491,7 +490,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 125; + this.state = 124; this.match(JackParser.IDENTIFIER); } } @@ -514,7 +513,7 @@ export class JackParser extends Parser { let _localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this._ctx, this.state); this.enterRule(_localctx, 18, JackParser.RULE_subroutineReturnType); try { - this.state = 129; + this.state = 128; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.INT: @@ -523,14 +522,14 @@ export class JackParser extends Parser { case JackParser.IDENTIFIER: this.enterOuterAlt(_localctx, 1); { - this.state = 127; + this.state = 126; this.varType(); } break; case JackParser.VOID: this.enterOuterAlt(_localctx, 2); { - this.state = 128; + this.state = 127; this.match(JackParser.VOID); } break; @@ -560,7 +559,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 131; + this.state = 130; _la = this._input.LA(1); if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER)) { this._errHandler.recoverInline(this); @@ -596,26 +595,26 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 141; + this.state = 140; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER) { { - this.state = 133; + this.state = 132; this.parameter(); - this.state = 138; + this.state = 137; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 134; + this.state = 133; this.match(JackParser.COMMA); - this.state = 135; + this.state = 134; this.parameter(); } } - this.state = 140; + this.state = 139; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -645,9 +644,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 143; + this.state = 142; this.varType(); - this.state = 144; + this.state = 143; this.parameterName(); } } @@ -672,7 +671,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 146; + this.state = 145; this.match(JackParser.IDENTIFIER); } } @@ -698,25 +697,25 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 148; + this.state = 147; this.match(JackParser.LBRACE); - this.state = 152; + this.state = 151; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.VAR) { { { - this.state = 149; - this.varDec(); + this.state = 148; + this.varDeclaration(); } } - this.state = 154; + this.state = 153; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 155; + this.state = 154; this.statements(); - this.state = 156; + this.state = 155; this.match(JackParser.RBRACE); } } @@ -735,36 +734,36 @@ export class JackParser extends Parser { return _localctx; } // @RuleVersion(0) - public varDec(): VarDecContext { - let _localctx: VarDecContext = new VarDecContext(this._ctx, this.state); - this.enterRule(_localctx, 30, JackParser.RULE_varDec); + public varDeclaration(): VarDeclarationContext { + let _localctx: VarDeclarationContext = new VarDeclarationContext(this._ctx, this.state); + this.enterRule(_localctx, 30, JackParser.RULE_varDeclaration); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 158; + this.state = 157; this.match(JackParser.VAR); - this.state = 159; + this.state = 158; this.varType(); - this.state = 160; + this.state = 159; this.varName(); - this.state = 165; + this.state = 164; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 161; + this.state = 160; this.match(JackParser.COMMA); - this.state = 162; - this.match(JackParser.IDENTIFIER); + this.state = 161; + this.varName(); } } - this.state = 167; + this.state = 166; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 168; + this.state = 167; this.match(JackParser.SEMICOLON); } } @@ -789,7 +788,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 170; + this.state = 169; this.match(JackParser.IDENTIFIER); } } @@ -815,17 +814,17 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 175; + this.state = 174; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.LET) | (1 << JackParser.DO) | (1 << JackParser.IF) | (1 << JackParser.WHILE) | (1 << JackParser.RETURN))) !== 0)) { { { - this.state = 172; + this.state = 171; this.statement(); } } - this.state = 177; + this.state = 176; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -850,41 +849,41 @@ export class JackParser extends Parser { let _localctx: StatementContext = new StatementContext(this._ctx, this.state); this.enterRule(_localctx, 36, JackParser.RULE_statement); try { - this.state = 183; + this.state = 182; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.LET: this.enterOuterAlt(_localctx, 1); { - this.state = 178; + this.state = 177; this.letStatement(); } break; case JackParser.IF: this.enterOuterAlt(_localctx, 2); { - this.state = 179; + this.state = 178; this.ifStatement(); } break; case JackParser.WHILE: this.enterOuterAlt(_localctx, 3); { - this.state = 180; + this.state = 179; this.whileStatement(); } break; case JackParser.DO: this.enterOuterAlt(_localctx, 4); { - this.state = 181; + this.state = 180; this.doStatement(); } break; case JackParser.RETURN: this.enterOuterAlt(_localctx, 5); { - this.state = 182; + this.state = 181; this.returnStatement(); } break; @@ -913,30 +912,30 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 185; + this.state = 184; this.match(JackParser.LET); - this.state = 188; + this.state = 187; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 12, this._ctx) ) { case 1: { - this.state = 186; + this.state = 185; this.match(JackParser.IDENTIFIER); } break; case 2: { - this.state = 187; + this.state = 186; this.arrayAccess(); } break; } - this.state = 190; + this.state = 189; this.match(JackParser.EQUALS); - this.state = 191; + this.state = 190; this.expression(0); - this.state = 192; + this.state = 191; this.match(JackParser.SEMICOLON); } } @@ -962,32 +961,32 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 194; + this.state = 193; this.match(JackParser.IF); - this.state = 195; + this.state = 194; this.match(JackParser.LPAREN); - this.state = 196; + this.state = 195; this.expression(0); - this.state = 197; + this.state = 196; this.match(JackParser.RPAREN); - this.state = 198; + this.state = 197; this.match(JackParser.LBRACE); - this.state = 199; + this.state = 198; this.statements(); - this.state = 200; + this.state = 199; this.match(JackParser.RBRACE); - this.state = 206; + this.state = 205; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === JackParser.ELSE) { { - this.state = 201; + this.state = 200; this.match(JackParser.ELSE); - this.state = 202; + this.state = 201; this.match(JackParser.LBRACE); - this.state = 203; + this.state = 202; this.statements(); - this.state = 204; + this.state = 203; this.match(JackParser.RBRACE); } } @@ -1015,19 +1014,19 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 208; + this.state = 207; this.match(JackParser.WHILE); - this.state = 209; + this.state = 208; this.match(JackParser.LPAREN); - this.state = 210; + this.state = 209; this.expression(0); - this.state = 211; + this.state = 210; this.match(JackParser.RPAREN); - this.state = 212; + this.state = 211; this.match(JackParser.LBRACE); - this.state = 213; + this.state = 212; this.statements(); - this.state = 214; + this.state = 213; this.match(JackParser.RBRACE); } } @@ -1052,11 +1051,11 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 216; + this.state = 215; this.match(JackParser.DO); - this.state = 217; + this.state = 216; this.subroutineCall(); - this.state = 218; + this.state = 217; this.match(JackParser.SEMICOLON); } } @@ -1080,19 +1079,19 @@ export class JackParser extends Parser { this.enterRule(_localctx, 46, JackParser.RULE_subroutineCall); let _la: number; try { - this.state = 232; + this.state = 231; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 220; + this.state = 219; this.match(JackParser.IDENTIFIER); - this.state = 221; + this.state = 220; this.match(JackParser.LPAREN); - this.state = 222; + this.state = 221; this.expressionList(); - this.state = 223; + this.state = 222; this.match(JackParser.RPAREN); } break; @@ -1100,7 +1099,7 @@ export class JackParser extends Parser { case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 225; + this.state = 224; _la = this._input.LA(1); if (!(_la === JackParser.THIS_LITERAL || _la === JackParser.IDENTIFIER)) { this._errHandler.recoverInline(this); @@ -1112,15 +1111,15 @@ export class JackParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 226; + this.state = 225; this.match(JackParser.DOT); - this.state = 227; + this.state = 226; this.match(JackParser.IDENTIFIER); - this.state = 228; + this.state = 227; this.match(JackParser.LPAREN); - this.state = 229; + this.state = 228; this.expressionList(); - this.state = 230; + this.state = 229; this.match(JackParser.RPAREN); } break; @@ -1148,19 +1147,19 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 234; + this.state = 233; this.match(JackParser.RETURN); - this.state = 236; + this.state = 235; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 235; + this.state = 234; this.expression(0); } } - this.state = 238; + this.state = 237; this.match(JackParser.SEMICOLON); } } @@ -1186,26 +1185,26 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 248; + this.state = 247; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 240; + this.state = 239; this.expression(0); - this.state = 245; + this.state = 244; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 241; + this.state = 240; this.match(JackParser.COMMA); - this.state = 242; + this.state = 241; this.expression(0); } } - this.state = 247; + this.state = 246; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1247,53 +1246,53 @@ export class JackParser extends Parser { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 257; + this.state = 256; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 18, this._ctx) ) { case 1: { - this.state = 251; + this.state = 250; this.constant(); } break; case 2: { - this.state = 252; + this.state = 251; this.match(JackParser.IDENTIFIER); } break; case 3: { - this.state = 253; + this.state = 252; this.subroutineCall(); } break; case 4: { - this.state = 254; + this.state = 253; this.arrayAccess(); } break; case 5: { - this.state = 255; + this.state = 254; this.unaryOp(); } break; case 6: { - this.state = 256; + this.state = 255; this.groupedExpression(); } break; } this._ctx._stop = this._input.tryLT(-1); - this.state = 265; + this.state = 264; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -1307,18 +1306,18 @@ export class JackParser extends Parser { _localctx = new ExpressionContext(_parentctx, _parentState); _localctx._binaryOperation = _prevctx; this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); - this.state = 259; + this.state = 258; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 260; + this.state = 259; this.binaryOperator(); - this.state = 261; + this.state = 260; this.expression(8); } } } - this.state = 267; + this.state = 266; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); } @@ -1345,11 +1344,11 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 268; + this.state = 267; this.match(JackParser.LPAREN); - this.state = 269; + this.state = 268; this.expression(0); - this.state = 270; + this.state = 269; this.match(JackParser.RPAREN); } } @@ -1374,9 +1373,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 272; + this.state = 271; this.unaryOperator(); - this.state = 273; + this.state = 272; this.expression(0); } } @@ -1401,13 +1400,13 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 275; + this.state = 274; this.match(JackParser.IDENTIFIER); - this.state = 276; + this.state = 275; this.match(JackParser.LBRACKET); - this.state = 277; + this.state = 276; this.expression(0); - this.state = 278; + this.state = 277; this.match(JackParser.RBRACKET); } } @@ -1433,7 +1432,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 280; + this.state = 279; _la = this._input.LA(1); if (!(((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & ((1 << (JackParser.INTEGER_LITERAL - 40)) | (1 << (JackParser.BOOLEAN_LITERAL - 40)) | (1 << (JackParser.NULL_LITERAL - 40)) | (1 << (JackParser.THIS_LITERAL - 40)) | (1 << (JackParser.STRING_LITERAL - 40)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1469,7 +1468,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 282; + this.state = 281; _la = this._input.LA(1); if (!(_la === JackParser.MINUS || _la === JackParser.TILDE)) { this._errHandler.recoverInline(this); @@ -1505,7 +1504,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 284; + this.state = 283; _la = this._input.LA(1); if (!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & ((1 << (JackParser.EQUALS - 27)) | (1 << (JackParser.PLUS - 27)) | (1 << (JackParser.MINUS - 27)) | (1 << (JackParser.MUL - 27)) | (1 << (JackParser.DIV - 27)) | (1 << (JackParser.AND - 27)) | (1 << (JackParser.OR - 27)) | (1 << (JackParser.LESS_THAN - 27)) | (1 << (JackParser.GREATER_THAN - 27)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1550,7 +1549,7 @@ export class JackParser extends Parser { } public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u0121\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u0120\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + @@ -1562,119 +1561,118 @@ export class JackParser extends Parser { "\x03\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + "\x05\x03\x05\x05\x05c\n\x05\x03\x06\x03\x06\x03\x06\x03\x06\x07\x06i\n" + "\x06\f\x06\x0E\x06l\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\b\x03" + - "\b\x03\b\x03\b\x05\bw\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03" + - "\n\x03\n\x03\v\x03\v\x05\v\x84\n\v\x03\f\x03\f\x03\r\x03\r\x03\r\x07\r" + - "\x8B\n\r\f\r\x0E\r\x8E\v\r\x05\r\x90\n\r\x03\x0E\x03\x0E\x03\x0E\x03\x0F" + - "\x03\x0F\x03\x10\x03\x10\x07\x10\x99\n\x10\f\x10\x0E\x10\x9C\v\x10\x03" + - "\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x07\x11\xA6" + - "\n\x11\f\x11\x0E\x11\xA9\v\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x13" + - "\x07\x13\xB0\n\x13\f\x13\x0E\x13\xB3\v\x13\x03\x14\x03\x14\x03\x14\x03" + - "\x14\x03\x14\x05\x14\xBA\n\x14\x03\x15\x03\x15\x03\x15\x05\x15\xBF\n\x15" + - "\x03\x15\x03\x15\x03\x15\x03\x15\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16" + - "\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x05\x16\xD1\n" + - "\x16\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03" + - "\x18\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03" + - "\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x05\x19\xEB\n\x19" + - "\x03\x1A\x03\x1A\x05\x1A\xEF\n\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1B\x07\x1B\xF6\n\x1B\f\x1B\x0E\x1B\xF9\v\x1B\x05\x1B\xFB\n\x1B\x03\x1C" + - "\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x05\x1C\u0104\n\x1C\x03" + - "\x1C\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u010A\n\x1C\f\x1C\x0E\x1C\u010D\v" + - "\x1C\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1F\x03" + - "\x1F\x03\x1F\x03\x1F\x03\x1F\x03 \x03 \x03!\x03!\x03\"\x03\"\x03\"\x02" + - "\x02\x036#\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12" + - "\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&" + - "\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02" + - "B\x02\x02\x07\x04\x02\n\f..\x03\x02-.\x04\x02*-//\x04\x02\x1F\x1F$$\x04" + - "\x02\x1D#%&\x02\u011B\x02D\x03\x02\x02\x02\x04G\x03\x02\x02\x02\x06X\x03" + - "\x02\x02\x02\bb\x03\x02\x02\x02\nd\x03\x02\x02\x02\fm\x03\x02\x02\x02" + - "\x0Ev\x03\x02\x02\x02\x10x\x03\x02\x02\x02\x12\x7F\x03\x02\x02\x02\x14" + - "\x83\x03\x02\x02\x02\x16\x85\x03\x02\x02\x02\x18\x8F\x03\x02\x02\x02\x1A" + - "\x91\x03\x02\x02\x02\x1C\x94\x03\x02\x02\x02\x1E\x96\x03\x02\x02\x02 " + - "\xA0\x03\x02\x02\x02\"\xAC\x03\x02\x02\x02$\xB1\x03\x02\x02\x02&\xB9\x03" + - "\x02\x02\x02(\xBB\x03\x02\x02\x02*\xC4\x03\x02\x02\x02,\xD2\x03\x02\x02" + - "\x02.\xDA\x03\x02\x02\x020\xEA\x03\x02\x02\x022\xEC\x03\x02\x02\x024\xFA" + - "\x03\x02\x02\x026\u0103\x03\x02\x02\x028\u010E\x03\x02\x02\x02:\u0112" + - "\x03\x02\x02\x02<\u0115\x03\x02\x02\x02>\u011A\x03\x02\x02\x02@\u011C" + - "\x03\x02\x02\x02B\u011E\x03\x02\x02\x02DE\x05\x04\x03\x02EF\x07\x02\x02" + - "\x03F\x03\x03\x02\x02\x02GH\x07\x03\x02\x02HI\x05\x06\x04\x02IM\x07\x14" + - "\x02\x02JL\x05\b\x05\x02KJ\x03\x02\x02\x02LO\x03\x02\x02\x02MK\x03\x02" + - "\x02\x02MN\x03\x02\x02\x02NS\x03\x02\x02\x02OM\x03\x02\x02\x02PR\x05\x0E" + - "\b\x02QP\x03\x02\x02\x02RU\x03\x02\x02\x02SQ\x03\x02\x02\x02ST\x03\x02" + - "\x02\x02TV\x03\x02\x02\x02US\x03\x02\x02\x02VW\x07\x15\x02\x02W\x05\x03" + - "\x02\x02\x02XY\x07.\x02\x02Y\x07\x03\x02\x02\x02Z[\x07\b\x02\x02[\\\x05" + - "\n\x06\x02\\]\x07\x1C\x02\x02]c\x03\x02\x02\x02^_\x07\x07\x02\x02_`\x05" + - "\n\x06\x02`a\x07\x1C\x02\x02ac\x03\x02\x02\x02bZ\x03\x02\x02\x02b^\x03" + - "\x02\x02\x02c\t\x03\x02\x02\x02de\x05\x16\f\x02ej\x05\f\x07\x02fg\x07" + - "\x1B\x02\x02gi\x05\f\x07\x02hf\x03\x02\x02\x02il\x03\x02\x02\x02jh\x03" + - "\x02\x02\x02jk\x03\x02\x02\x02k\v\x03\x02\x02\x02lj\x03\x02\x02\x02mn" + - "\x07.\x02\x02n\r\x03\x02\x02\x02op\b\b\x01\x02pq\x07\x04\x02\x02qw\x05" + - "\x10\t\x02rs\x07\x06\x02\x02sw\x05\x10\t\x02tu\x07\x05\x02\x02uw\x05\x10" + - "\t\x02vo\x03\x02\x02\x02vr\x03\x02\x02\x02vt\x03\x02\x02\x02w\x0F\x03" + - "\x02\x02\x02xy\x05\x14\v\x02yz\x05\x12\n\x02z{\x07\x16\x02\x02{|\x05\x18" + - "\r\x02|}\x07\x17\x02\x02}~\x05\x1E\x10\x02~\x11\x03\x02\x02\x02\x7F\x80" + - "\x07.\x02\x02\x80\x13\x03\x02\x02\x02\x81\x84\x05\x16\f\x02\x82\x84\x07" + - "\r\x02\x02\x83\x81\x03\x02\x02\x02\x83\x82\x03\x02\x02\x02\x84\x15\x03" + - "\x02\x02\x02\x85\x86\t\x02\x02\x02\x86\x17\x03\x02\x02\x02\x87\x8C\x05" + - "\x1A\x0E\x02\x88\x89\x07\x1B\x02\x02\x89\x8B\x05\x1A\x0E\x02\x8A\x88\x03" + - "\x02\x02\x02\x8B\x8E\x03\x02\x02\x02\x8C\x8A\x03\x02\x02\x02\x8C\x8D\x03" + - "\x02\x02\x02\x8D\x90\x03\x02\x02\x02\x8E\x8C\x03\x02\x02\x02\x8F\x87\x03" + - "\x02\x02\x02\x8F\x90\x03\x02\x02\x02\x90\x19\x03\x02\x02\x02\x91\x92\x05" + - "\x16\f\x02\x92\x93\x05\x1C\x0F\x02\x93\x1B\x03\x02\x02\x02\x94\x95\x07" + - ".\x02\x02\x95\x1D\x03\x02\x02\x02\x96\x9A\x07\x14\x02\x02\x97\x99\x05" + - " \x11\x02\x98\x97\x03\x02\x02\x02\x99\x9C\x03\x02\x02\x02\x9A\x98\x03" + - "\x02\x02\x02\x9A\x9B\x03\x02\x02\x02\x9B\x9D\x03\x02\x02\x02\x9C\x9A\x03" + - "\x02\x02\x02\x9D\x9E\x05$\x13\x02\x9E\x9F\x07\x15\x02\x02\x9F\x1F\x03" + - "\x02\x02\x02\xA0\xA1\x07\t\x02\x02\xA1\xA2\x05\x16\f\x02\xA2\xA7\x05\"" + - "\x12\x02\xA3\xA4\x07\x1B\x02\x02\xA4\xA6\x07.\x02\x02\xA5\xA3\x03\x02" + - "\x02\x02\xA6\xA9\x03\x02\x02\x02\xA7\xA5\x03\x02\x02\x02\xA7\xA8\x03\x02" + - "\x02\x02\xA8\xAA\x03\x02\x02\x02\xA9\xA7\x03\x02\x02\x02\xAA\xAB\x07\x1C" + - "\x02\x02\xAB!\x03\x02\x02\x02\xAC\xAD\x07.\x02\x02\xAD#\x03\x02\x02\x02" + - "\xAE\xB0\x05&\x14\x02\xAF\xAE\x03\x02\x02\x02\xB0\xB3\x03\x02\x02\x02" + - "\xB1\xAF\x03\x02\x02\x02\xB1\xB2\x03\x02\x02\x02\xB2%\x03\x02\x02\x02" + - "\xB3\xB1\x03\x02\x02\x02\xB4\xBA\x05(\x15\x02\xB5\xBA\x05*\x16\x02\xB6" + - "\xBA\x05,\x17\x02\xB7\xBA\x05.\x18\x02\xB8\xBA\x052\x1A\x02\xB9\xB4\x03" + - "\x02\x02\x02\xB9\xB5\x03\x02\x02\x02\xB9\xB6\x03\x02\x02\x02\xB9\xB7\x03" + - "\x02\x02\x02\xB9\xB8\x03\x02\x02\x02\xBA\'\x03\x02\x02\x02\xBB\xBE\x07" + - "\x0E\x02\x02\xBC\xBF\x07.\x02\x02\xBD\xBF\x05<\x1F\x02\xBE\xBC\x03\x02" + - "\x02\x02\xBE\xBD\x03\x02\x02\x02\xBF\xC0\x03\x02\x02\x02\xC0\xC1\x07\x1D" + - "\x02\x02\xC1\xC2\x056\x1C\x02\xC2\xC3\x07\x1C\x02\x02\xC3)\x03\x02\x02" + - "\x02\xC4\xC5\x07\x10\x02\x02\xC5\xC6\x07\x16\x02\x02\xC6\xC7\x056\x1C" + - "\x02\xC7\xC8\x07\x17\x02\x02\xC8\xC9\x07\x14\x02\x02\xC9\xCA\x05$\x13" + - "\x02\xCA\xD0\x07\x15\x02\x02\xCB\xCC\x07\x11\x02\x02\xCC\xCD\x07\x14\x02" + - "\x02\xCD\xCE\x05$\x13\x02\xCE\xCF\x07\x15\x02\x02\xCF\xD1\x03\x02\x02" + - "\x02\xD0\xCB\x03\x02\x02\x02\xD0\xD1\x03\x02\x02\x02\xD1+\x03\x02\x02" + - "\x02\xD2\xD3\x07\x12\x02\x02\xD3\xD4\x07\x16\x02\x02\xD4\xD5\x056\x1C" + - "\x02\xD5\xD6\x07\x17\x02\x02\xD6\xD7\x07\x14\x02\x02\xD7\xD8\x05$\x13" + - "\x02\xD8\xD9\x07\x15\x02\x02\xD9-\x03\x02\x02\x02\xDA\xDB\x07\x0F\x02" + - "\x02\xDB\xDC\x050\x19\x02\xDC\xDD\x07\x1C\x02\x02\xDD/\x03\x02\x02\x02" + - "\xDE\xDF\x07.\x02\x02\xDF\xE0\x07\x16\x02\x02\xE0\xE1\x054\x1B\x02\xE1" + - "\xE2\x07\x17\x02\x02\xE2\xEB\x03\x02\x02\x02\xE3\xE4\t\x03\x02\x02\xE4" + - "\xE5\x07\x1A\x02\x02\xE5\xE6\x07.\x02\x02\xE6\xE7\x07\x16\x02\x02\xE7" + - "\xE8\x054\x1B\x02\xE8\xE9\x07\x17\x02\x02\xE9\xEB\x03\x02\x02\x02\xEA" + - "\xDE\x03\x02\x02\x02\xEA\xE3\x03\x02\x02\x02\xEB1\x03\x02\x02\x02\xEC" + - "\xEE\x07\x13\x02\x02\xED\xEF\x056\x1C\x02\xEE\xED\x03\x02\x02\x02\xEE" + - "\xEF\x03\x02\x02\x02\xEF\xF0\x03\x02\x02\x02\xF0\xF1\x07\x1C\x02\x02\xF1" + - "3\x03\x02\x02\x02\xF2\xF7\x056\x1C\x02\xF3\xF4\x07\x1B\x02\x02\xF4\xF6" + - "\x056\x1C\x02\xF5\xF3\x03\x02\x02\x02\xF6\xF9\x03\x02\x02\x02\xF7\xF5" + - "\x03\x02\x02\x02\xF7\xF8\x03\x02\x02\x02\xF8\xFB\x03\x02\x02\x02\xF9\xF7" + - "\x03\x02\x02\x02\xFA\xF2\x03\x02\x02\x02\xFA\xFB\x03\x02\x02\x02\xFB5" + - "\x03\x02\x02\x02\xFC\xFD\b\x1C\x01\x02\xFD\u0104\x05> \x02\xFE\u0104\x07" + - ".\x02\x02\xFF\u0104\x050\x19\x02\u0100\u0104\x05<\x1F\x02\u0101\u0104" + - "\x05:\x1E\x02\u0102\u0104\x058\x1D\x02\u0103\xFC\x03\x02\x02\x02\u0103" + - "\xFE\x03\x02\x02\x02\u0103\xFF\x03\x02\x02\x02\u0103\u0100\x03\x02\x02" + - "\x02\u0103\u0101\x03\x02\x02\x02\u0103\u0102\x03\x02\x02\x02\u0104\u010B" + - "\x03\x02\x02\x02\u0105\u0106\f\t\x02\x02\u0106\u0107\x05B\"\x02\u0107" + - "\u0108\x056\x1C\n\u0108\u010A\x03\x02\x02\x02\u0109\u0105\x03\x02\x02" + - "\x02\u010A\u010D\x03\x02\x02\x02\u010B\u0109\x03\x02\x02\x02\u010B\u010C" + - "\x03\x02\x02\x02\u010C7\x03\x02\x02\x02\u010D\u010B\x03\x02\x02\x02\u010E" + - "\u010F\x07\x16\x02\x02\u010F\u0110\x056\x1C\x02\u0110\u0111\x07\x17\x02" + - "\x02\u01119\x03\x02\x02\x02\u0112\u0113\x05@!\x02\u0113\u0114\x056\x1C" + - "\x02\u0114;\x03\x02\x02\x02\u0115\u0116\x07.\x02\x02\u0116\u0117\x07\x18" + - "\x02\x02\u0117\u0118\x056\x1C\x02\u0118\u0119\x07\x19\x02\x02\u0119=\x03" + - "\x02\x02\x02\u011A\u011B\t\x04\x02\x02\u011B?\x03\x02\x02\x02\u011C\u011D" + - "\t\x05\x02\x02\u011DA\x03\x02\x02\x02\u011E\u011F\t\x06\x02\x02\u011F" + - "C\x03\x02\x02\x02\x16MSbjv\x83\x8C\x8F\x9A\xA7\xB1\xB9\xBE\xD0\xEA\xEE" + - "\xF7\xFA\u0103\u010B"; + "\b\x03\b\x05\bv\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\n\x03" + + "\n\x03\v\x03\v\x05\v\x83\n\v\x03\f\x03\f\x03\r\x03\r\x03\r\x07\r\x8A\n" + + "\r\f\r\x0E\r\x8D\v\r\x05\r\x8F\n\r\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03" + + "\x0F\x03\x10\x03\x10\x07\x10\x98\n\x10\f\x10\x0E\x10\x9B\v\x10\x03\x10" + + "\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x07\x11\xA5\n" + + "\x11\f\x11\x0E\x11\xA8\v\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x13\x07" + + "\x13\xAF\n\x13\f\x13\x0E\x13\xB2\v\x13\x03\x14\x03\x14\x03\x14\x03\x14" + + "\x03\x14\x05\x14\xB9\n\x14\x03\x15\x03\x15\x03\x15\x05\x15\xBE\n\x15\x03" + + "\x15\x03\x15\x03\x15\x03\x15\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03" + + "\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x05\x16\xD0\n\x16" + + "\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18" + + "\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19" + + "\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x05\x19\xEA\n\x19\x03" + + "\x1A\x03\x1A\x05\x1A\xEE\n\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03\x1B" + + "\x07\x1B\xF5\n\x1B\f\x1B\x0E\x1B\xF8\v\x1B\x05\x1B\xFA\n\x1B\x03\x1C\x03" + + "\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x05\x1C\u0103\n\x1C\x03\x1C" + + "\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u0109\n\x1C\f\x1C\x0E\x1C\u010C\v\x1C" + + "\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F" + + "\x03\x1F\x03\x1F\x03\x1F\x03 \x03 \x03!\x03!\x03\"\x03\"\x03\"\x02\x02" + + "\x036#\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02" + + "\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02" + + "(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02" + + "\x02\x07\x04\x02\n\f..\x03\x02-.\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02" + + "\x1D#%&\x02\u011A\x02D\x03\x02\x02\x02\x04G\x03\x02\x02\x02\x06X\x03\x02" + + "\x02\x02\bb\x03\x02\x02\x02\nd\x03\x02\x02\x02\fm\x03\x02\x02\x02\x0E" + + "u\x03\x02\x02\x02\x10w\x03\x02\x02\x02\x12~\x03\x02\x02\x02\x14\x82\x03" + + "\x02\x02\x02\x16\x84\x03\x02\x02\x02\x18\x8E\x03\x02\x02\x02\x1A\x90\x03" + + "\x02\x02\x02\x1C\x93\x03\x02\x02\x02\x1E\x95\x03\x02\x02\x02 \x9F\x03" + + "\x02\x02\x02\"\xAB\x03\x02\x02\x02$\xB0\x03\x02\x02\x02&\xB8\x03\x02\x02" + + "\x02(\xBA\x03\x02\x02\x02*\xC3\x03\x02\x02\x02,\xD1\x03\x02\x02\x02.\xD9" + + "\x03\x02\x02\x020\xE9\x03\x02\x02\x022\xEB\x03\x02\x02\x024\xF9\x03\x02" + + "\x02\x026\u0102\x03\x02\x02\x028\u010D\x03\x02\x02\x02:\u0111\x03\x02" + + "\x02\x02<\u0114\x03\x02\x02\x02>\u0119\x03\x02\x02\x02@\u011B\x03\x02" + + "\x02\x02B\u011D\x03\x02\x02\x02DE\x05\x04\x03\x02EF\x07\x02\x02\x03F\x03" + + "\x03\x02\x02\x02GH\x07\x03\x02\x02HI\x05\x06\x04\x02IM\x07\x14\x02\x02" + + "JL\x05\b\x05\x02KJ\x03\x02\x02\x02LO\x03\x02\x02\x02MK\x03\x02\x02\x02" + + "MN\x03\x02\x02\x02NS\x03\x02\x02\x02OM\x03\x02\x02\x02PR\x05\x0E\b\x02" + + "QP\x03\x02\x02\x02RU\x03\x02\x02\x02SQ\x03\x02\x02\x02ST\x03\x02\x02\x02" + + "TV\x03\x02\x02\x02US\x03\x02\x02\x02VW\x07\x15\x02\x02W\x05\x03\x02\x02" + + "\x02XY\x07.\x02\x02Y\x07\x03\x02\x02\x02Z[\x07\b\x02\x02[\\\x05\n\x06" + + "\x02\\]\x07\x1C\x02\x02]c\x03\x02\x02\x02^_\x07\x07\x02\x02_`\x05\n\x06" + + "\x02`a\x07\x1C\x02\x02ac\x03\x02\x02\x02bZ\x03\x02\x02\x02b^\x03\x02\x02" + + "\x02c\t\x03\x02\x02\x02de\x05\x16\f\x02ej\x05\f\x07\x02fg\x07\x1B\x02" + + "\x02gi\x05\f\x07\x02hf\x03\x02\x02\x02il\x03\x02\x02\x02jh\x03\x02\x02" + + "\x02jk\x03\x02\x02\x02k\v\x03\x02\x02\x02lj\x03\x02\x02\x02mn\x07.\x02" + + "\x02n\r\x03\x02\x02\x02op\x07\x04\x02\x02pv\x05\x10\t\x02qr\x07\x06\x02" + + "\x02rv\x05\x10\t\x02st\x07\x05\x02\x02tv\x05\x10\t\x02uo\x03\x02\x02\x02" + + "uq\x03\x02\x02\x02us\x03\x02\x02\x02v\x0F\x03\x02\x02\x02wx\x05\x14\v" + + "\x02xy\x05\x12\n\x02yz\x07\x16\x02\x02z{\x05\x18\r\x02{|\x07\x17\x02\x02" + + "|}\x05\x1E\x10\x02}\x11\x03\x02\x02\x02~\x7F\x07.\x02\x02\x7F\x13\x03" + + "\x02\x02\x02\x80\x83\x05\x16\f\x02\x81\x83\x07\r\x02\x02\x82\x80\x03\x02" + + "\x02\x02\x82\x81\x03\x02\x02\x02\x83\x15\x03\x02\x02\x02\x84\x85\t\x02" + + "\x02\x02\x85\x17\x03\x02\x02\x02\x86\x8B\x05\x1A\x0E\x02\x87\x88\x07\x1B" + + "\x02\x02\x88\x8A\x05\x1A\x0E\x02\x89\x87\x03\x02\x02\x02\x8A\x8D\x03\x02" + + "\x02\x02\x8B\x89\x03\x02\x02\x02\x8B\x8C\x03\x02\x02\x02\x8C\x8F\x03\x02" + + "\x02\x02\x8D\x8B\x03\x02\x02\x02\x8E\x86\x03\x02\x02\x02\x8E\x8F\x03\x02" + + "\x02\x02\x8F\x19\x03\x02\x02\x02\x90\x91\x05\x16\f\x02\x91\x92\x05\x1C" + + "\x0F\x02\x92\x1B\x03\x02\x02\x02\x93\x94\x07.\x02\x02\x94\x1D\x03\x02" + + "\x02\x02\x95\x99\x07\x14\x02\x02\x96\x98\x05 \x11\x02\x97\x96\x03\x02" + + "\x02\x02\x98\x9B\x03\x02\x02\x02\x99\x97\x03\x02\x02\x02\x99\x9A\x03\x02" + + "\x02\x02\x9A\x9C\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9C\x9D\x05$" + + "\x13\x02\x9D\x9E\x07\x15\x02\x02\x9E\x1F\x03\x02\x02\x02\x9F\xA0\x07\t" + + "\x02\x02\xA0\xA1\x05\x16\f\x02\xA1\xA6\x05\"\x12\x02\xA2\xA3\x07\x1B\x02" + + "\x02\xA3\xA5\x05\"\x12\x02\xA4\xA2\x03\x02\x02\x02\xA5\xA8\x03\x02\x02" + + "\x02\xA6\xA4\x03\x02\x02\x02\xA6\xA7\x03\x02\x02\x02\xA7\xA9\x03\x02\x02" + + "\x02\xA8\xA6\x03\x02\x02\x02\xA9\xAA\x07\x1C\x02\x02\xAA!\x03\x02\x02" + + "\x02\xAB\xAC\x07.\x02\x02\xAC#\x03\x02\x02\x02\xAD\xAF\x05&\x14\x02\xAE" + + "\xAD\x03\x02\x02\x02\xAF\xB2\x03\x02\x02\x02\xB0\xAE\x03\x02\x02\x02\xB0" + + "\xB1\x03\x02\x02\x02\xB1%\x03\x02\x02\x02\xB2\xB0\x03\x02\x02\x02\xB3" + + "\xB9\x05(\x15\x02\xB4\xB9\x05*\x16\x02\xB5\xB9\x05,\x17\x02\xB6\xB9\x05" + + ".\x18\x02\xB7\xB9\x052\x1A\x02\xB8\xB3\x03\x02\x02\x02\xB8\xB4\x03\x02" + + "\x02\x02\xB8\xB5\x03\x02\x02\x02\xB8\xB6\x03\x02\x02\x02\xB8\xB7\x03\x02" + + "\x02\x02\xB9\'\x03\x02\x02\x02\xBA\xBD\x07\x0E\x02\x02\xBB\xBE\x07.\x02" + + "\x02\xBC\xBE\x05<\x1F\x02\xBD\xBB\x03\x02\x02\x02\xBD\xBC\x03\x02\x02" + + "\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0\x07\x1D\x02\x02\xC0\xC1\x056\x1C" + + "\x02\xC1\xC2\x07\x1C\x02\x02\xC2)\x03\x02\x02\x02\xC3\xC4\x07\x10\x02" + + "\x02\xC4\xC5\x07\x16\x02\x02\xC5\xC6\x056\x1C\x02\xC6\xC7\x07\x17\x02" + + "\x02\xC7\xC8\x07\x14\x02\x02\xC8\xC9\x05$\x13\x02\xC9\xCF\x07\x15\x02" + + "\x02\xCA\xCB\x07\x11\x02\x02\xCB\xCC\x07\x14\x02\x02\xCC\xCD\x05$\x13" + + "\x02\xCD\xCE\x07\x15\x02\x02\xCE\xD0\x03\x02\x02\x02\xCF\xCA\x03\x02\x02" + + "\x02\xCF\xD0\x03\x02\x02\x02\xD0+\x03\x02\x02\x02\xD1\xD2\x07\x12\x02" + + "\x02\xD2\xD3\x07\x16\x02\x02\xD3\xD4\x056\x1C\x02\xD4\xD5\x07\x17\x02" + + "\x02\xD5\xD6\x07\x14\x02\x02\xD6\xD7\x05$\x13\x02\xD7\xD8\x07\x15\x02" + + "\x02\xD8-\x03\x02\x02\x02\xD9\xDA\x07\x0F\x02\x02\xDA\xDB\x050\x19\x02" + + "\xDB\xDC\x07\x1C\x02\x02\xDC/\x03\x02\x02\x02\xDD\xDE\x07.\x02\x02\xDE" + + "\xDF\x07\x16\x02\x02\xDF\xE0\x054\x1B\x02\xE0\xE1\x07\x17\x02\x02\xE1" + + "\xEA\x03\x02\x02\x02\xE2\xE3\t\x03\x02\x02\xE3\xE4\x07\x1A\x02\x02\xE4" + + "\xE5\x07.\x02\x02\xE5\xE6\x07\x16\x02\x02\xE6\xE7\x054\x1B\x02\xE7\xE8" + + "\x07\x17\x02\x02\xE8\xEA\x03\x02\x02\x02\xE9\xDD\x03\x02\x02\x02\xE9\xE2" + + "\x03\x02\x02\x02\xEA1\x03\x02\x02\x02\xEB\xED\x07\x13\x02\x02\xEC\xEE" + + "\x056\x1C\x02\xED\xEC\x03\x02\x02\x02\xED\xEE\x03\x02\x02\x02\xEE\xEF" + + "\x03\x02\x02\x02\xEF\xF0\x07\x1C\x02\x02\xF03\x03\x02\x02\x02\xF1\xF6" + + "\x056\x1C\x02\xF2\xF3\x07\x1B\x02\x02\xF3\xF5\x056\x1C\x02\xF4\xF2\x03" + + "\x02\x02\x02\xF5\xF8\x03\x02\x02\x02\xF6\xF4\x03\x02\x02\x02\xF6\xF7\x03" + + "\x02\x02\x02\xF7\xFA\x03\x02\x02\x02\xF8\xF6\x03\x02\x02\x02\xF9\xF1\x03" + + "\x02\x02\x02\xF9\xFA\x03\x02\x02\x02\xFA5\x03\x02\x02\x02\xFB\xFC\b\x1C" + + "\x01\x02\xFC\u0103\x05> \x02\xFD\u0103\x07.\x02\x02\xFE\u0103\x050\x19" + + "\x02\xFF\u0103\x05<\x1F\x02\u0100\u0103\x05:\x1E\x02\u0101\u0103\x058" + + "\x1D\x02\u0102\xFB\x03\x02\x02\x02\u0102\xFD\x03\x02\x02\x02\u0102\xFE" + + "\x03\x02\x02\x02\u0102\xFF\x03\x02\x02\x02\u0102\u0100\x03\x02\x02\x02" + + "\u0102\u0101\x03\x02\x02\x02\u0103\u010A\x03\x02\x02\x02\u0104\u0105\f" + + "\t\x02\x02\u0105\u0106\x05B\"\x02\u0106\u0107\x056\x1C\n\u0107\u0109\x03" + + "\x02\x02\x02\u0108\u0104\x03\x02\x02\x02\u0109\u010C\x03\x02\x02\x02\u010A" + + "\u0108\x03\x02\x02\x02\u010A\u010B\x03\x02\x02\x02\u010B7\x03\x02\x02" + + "\x02\u010C\u010A\x03\x02\x02\x02\u010D\u010E\x07\x16\x02\x02\u010E\u010F" + + "\x056\x1C\x02\u010F\u0110\x07\x17\x02\x02\u01109\x03\x02\x02\x02\u0111" + + "\u0112\x05@!\x02\u0112\u0113\x056\x1C\x02\u0113;\x03\x02\x02\x02\u0114" + + "\u0115\x07.\x02\x02\u0115\u0116\x07\x18\x02\x02\u0116\u0117\x056\x1C\x02" + + "\u0117\u0118\x07\x19\x02\x02\u0118=\x03\x02\x02\x02\u0119\u011A\t\x04" + + "\x02\x02\u011A?\x03\x02\x02\x02\u011B\u011C\t\x05\x02\x02\u011CA\x03\x02" + + "\x02\x02\u011D\u011E\t\x06\x02\x02\u011EC\x03\x02\x02\x02\x16MSbju\x82" + + "\x8B\x8E\x99\xA6\xB0\xB8\xBD\xCF\xE9\xED\xF6\xF9\u0102\u010A"; public static __ATN: ATN; public static get _ATN(): ATN { if (!JackParser.__ATN) { @@ -1735,13 +1733,13 @@ export class ClassDeclarationContext extends ParserRuleContext { return this.getRuleContext(i, ClassVarDecContext); } } - public subroutineDec(): SubroutineDecContext[]; - public subroutineDec(i: number): SubroutineDecContext; - public subroutineDec(i?: number): SubroutineDecContext | SubroutineDecContext[] { + public subroutineDeclaration(): SubroutineDeclarationContext[]; + public subroutineDeclaration(i: number): SubroutineDeclarationContext; + public subroutineDeclaration(i?: number): SubroutineDeclarationContext | SubroutineDeclarationContext[] { if (i === undefined) { - return this.getRuleContexts(SubroutineDecContext); + return this.getRuleContexts(SubroutineDeclarationContext); } else { - return this.getRuleContext(i, SubroutineDecContext); + return this.getRuleContext(i, SubroutineDeclarationContext); } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { @@ -1956,22 +1954,22 @@ export class FieldNameContext extends ParserRuleContext { } -export class SubroutineDecContext extends ParserRuleContext { +export class SubroutineDeclarationContext extends ParserRuleContext { constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineDec; } - public override copyFrom(ctx: SubroutineDecContext): void { + public override get ruleIndex(): number { return JackParser.RULE_subroutineDeclaration; } + public override copyFrom(ctx: SubroutineDeclarationContext): void { super.copyFrom(ctx); } } -export class ConstructorContext extends SubroutineDecContext { +export class ConstructorContext extends SubroutineDeclarationContext { public CONSTRUCTOR(): TerminalNode { return this.getToken(JackParser.CONSTRUCTOR, 0); } public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { return this.getRuleContext(0, SubroutineDecWithoutTypeContext); } - constructor(ctx: SubroutineDecContext) { + constructor(ctx: SubroutineDeclarationContext) { super(ctx.parent, ctx.invokingState); this.copyFrom(ctx); } @@ -1996,12 +1994,12 @@ export class ConstructorContext extends SubroutineDecContext { } } } -export class MethodContext extends SubroutineDecContext { +export class MethodContext extends SubroutineDeclarationContext { public METHOD(): TerminalNode { return this.getToken(JackParser.METHOD, 0); } public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { return this.getRuleContext(0, SubroutineDecWithoutTypeContext); } - constructor(ctx: SubroutineDecContext) { + constructor(ctx: SubroutineDeclarationContext) { super(ctx.parent, ctx.invokingState); this.copyFrom(ctx); } @@ -2026,12 +2024,12 @@ export class MethodContext extends SubroutineDecContext { } } } -export class FunctionContext extends SubroutineDecContext { +export class FunctionContext extends SubroutineDeclarationContext { public FUNCTION(): TerminalNode { return this.getToken(JackParser.FUNCTION, 0); } public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { return this.getRuleContext(0, SubroutineDecWithoutTypeContext); } - constructor(ctx: SubroutineDecContext) { + constructor(ctx: SubroutineDeclarationContext) { super(ctx.parent, ctx.invokingState); this.copyFrom(ctx); } @@ -2315,13 +2313,13 @@ export class SubroutineBodyContext extends ParserRuleContext { return this.getRuleContext(0, StatementsContext); } public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } - public varDec(): VarDecContext[]; - public varDec(i: number): VarDecContext; - public varDec(i?: number): VarDecContext | VarDecContext[] { + public varDeclaration(): VarDeclarationContext[]; + public varDeclaration(i: number): VarDeclarationContext; + public varDeclaration(i?: number): VarDeclarationContext | VarDeclarationContext[] { if (i === undefined) { - return this.getRuleContexts(VarDecContext); + return this.getRuleContexts(VarDeclarationContext); } else { - return this.getRuleContext(i, VarDecContext); + return this.getRuleContext(i, VarDeclarationContext); } } constructor(parent: ParserRuleContext | undefined, invokingState: number) { @@ -2352,13 +2350,19 @@ export class SubroutineBodyContext extends ParserRuleContext { } -export class VarDecContext extends ParserRuleContext { +export class VarDeclarationContext extends ParserRuleContext { public VAR(): TerminalNode { return this.getToken(JackParser.VAR, 0); } public varType(): VarTypeContext { return this.getRuleContext(0, VarTypeContext); } - public varName(): VarNameContext { - return this.getRuleContext(0, VarNameContext); + public varName(): VarNameContext[]; + public varName(i: number): VarNameContext; + public varName(i?: number): VarNameContext | VarNameContext[] { + if (i === undefined) { + return this.getRuleContexts(VarNameContext); + } else { + return this.getRuleContext(i, VarNameContext); + } } public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } public COMMA(): TerminalNode[]; @@ -2370,36 +2374,27 @@ export class VarDecContext extends ParserRuleContext { return this.getToken(JackParser.COMMA, i); } } - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.IDENTIFIER); - } else { - return this.getToken(JackParser.IDENTIFIER, i); - } - } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } // @Override - public override get ruleIndex(): number { return JackParser.RULE_varDec; } + public override get ruleIndex(): number { return JackParser.RULE_varDeclaration; } // @Override public override enterRule(listener: JackParserListener): void { - if (listener.enterVarDec) { - listener.enterVarDec(this); + if (listener.enterVarDeclaration) { + listener.enterVarDeclaration(this); } } // @Override public override exitRule(listener: JackParserListener): void { - if (listener.exitVarDec) { - listener.exitVarDec(this); + if (listener.exitVarDeclaration) { + listener.exitVarDeclaration(this); } } // @Override public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitVarDec) { - return visitor.visitVarDec(this); + if (visitor.visitVarDeclaration) { + return visitor.visitVarDeclaration(this); } else { return visitor.visitChildren(this); } diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts index 36c33cfc..160ac157 100644 --- a/compiler/src/generated/JackParserListener.ts +++ b/compiler/src/generated/JackParserListener.ts @@ -3,18 +3,18 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { StaticFieldDeclarationContext } from "./JackParser"; +import { FieldDeclarationContext } from "./JackParser"; import { ConstructorContext } from "./JackParser"; import { MethodContext } from "./JackParser"; import { FunctionContext } from "./JackParser"; -import { StaticFieldDeclarationContext } from "./JackParser"; -import { FieldDeclarationContext } from "./JackParser"; import { ProgramContext } from "./JackParser"; import { ClassDeclarationContext } from "./JackParser"; import { ClassNameContext } from "./JackParser"; import { ClassVarDecContext } from "./JackParser"; import { FieldListContext } from "./JackParser"; import { FieldNameContext } from "./JackParser"; -import { SubroutineDecContext } from "./JackParser"; +import { SubroutineDeclarationContext } from "./JackParser"; import { SubroutineDecWithoutTypeContext } from "./JackParser"; import { SubroutineNameContext } from "./JackParser"; import { SubroutineReturnTypeContext } from "./JackParser"; @@ -23,7 +23,7 @@ import { ParameterListContext } from "./JackParser"; import { ParameterContext } from "./JackParser"; import { ParameterNameContext } from "./JackParser"; import { SubroutineBodyContext } from "./JackParser"; -import { VarDecContext } from "./JackParser"; +import { VarDeclarationContext } from "./JackParser"; import { VarNameContext } from "./JackParser"; import { StatementsContext } from "./JackParser"; import { StatementContext } from "./JackParser"; @@ -49,69 +49,69 @@ import { BinaryOperatorContext } from "./JackParser"; */ export interface JackParserListener extends ParseTreeListener { /** - * Enter a parse tree produced by the `constructor` - * labeled alternative in `JackParser.subroutineDec`. + * Enter a parse tree produced by the `staticFieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. * @param ctx the parse tree */ - enterConstructor?: (ctx: ConstructorContext) => void; + enterStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => void; /** - * Exit a parse tree produced by the `constructor` - * labeled alternative in `JackParser.subroutineDec`. + * Exit a parse tree produced by the `staticFieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. * @param ctx the parse tree */ - exitConstructor?: (ctx: ConstructorContext) => void; + exitStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => void; /** - * Enter a parse tree produced by the `method` - * labeled alternative in `JackParser.subroutineDec`. + * Enter a parse tree produced by the `fieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. * @param ctx the parse tree */ - enterMethod?: (ctx: MethodContext) => void; + enterFieldDeclaration?: (ctx: FieldDeclarationContext) => void; /** - * Exit a parse tree produced by the `method` - * labeled alternative in `JackParser.subroutineDec`. + * Exit a parse tree produced by the `fieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. * @param ctx the parse tree */ - exitMethod?: (ctx: MethodContext) => void; + exitFieldDeclaration?: (ctx: FieldDeclarationContext) => void; /** - * Enter a parse tree produced by the `function` - * labeled alternative in `JackParser.subroutineDec`. + * Enter a parse tree produced by the `constructor` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree */ - enterFunction?: (ctx: FunctionContext) => void; + enterConstructor?: (ctx: ConstructorContext) => void; /** - * Exit a parse tree produced by the `function` - * labeled alternative in `JackParser.subroutineDec`. + * Exit a parse tree produced by the `constructor` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree */ - exitFunction?: (ctx: FunctionContext) => void; + exitConstructor?: (ctx: ConstructorContext) => void; /** - * Enter a parse tree produced by the `staticFieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. + * Enter a parse tree produced by the `method` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree */ - enterStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => void; + enterMethod?: (ctx: MethodContext) => void; /** - * Exit a parse tree produced by the `staticFieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. + * Exit a parse tree produced by the `method` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree */ - exitStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => void; + exitMethod?: (ctx: MethodContext) => void; /** - * Enter a parse tree produced by the `fieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. + * Enter a parse tree produced by the `function` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree */ - enterFieldDeclaration?: (ctx: FieldDeclarationContext) => void; + enterFunction?: (ctx: FunctionContext) => void; /** - * Exit a parse tree produced by the `fieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. + * Exit a parse tree produced by the `function` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree */ - exitFieldDeclaration?: (ctx: FieldDeclarationContext) => void; + exitFunction?: (ctx: FunctionContext) => void; /** * Enter a parse tree produced by `JackParser.program`. @@ -180,15 +180,15 @@ export interface JackParserListener extends ParseTreeListener { exitFieldName?: (ctx: FieldNameContext) => void; /** - * Enter a parse tree produced by `JackParser.subroutineDec`. + * Enter a parse tree produced by `JackParser.subroutineDeclaration`. * @param ctx the parse tree */ - enterSubroutineDec?: (ctx: SubroutineDecContext) => void; + enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; /** - * Exit a parse tree produced by `JackParser.subroutineDec`. + * Exit a parse tree produced by `JackParser.subroutineDeclaration`. * @param ctx the parse tree */ - exitSubroutineDec?: (ctx: SubroutineDecContext) => void; + exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; /** * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. @@ -279,15 +279,15 @@ export interface JackParserListener extends ParseTreeListener { exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; /** - * Enter a parse tree produced by `JackParser.varDec`. + * Enter a parse tree produced by `JackParser.varDeclaration`. * @param ctx the parse tree */ - enterVarDec?: (ctx: VarDecContext) => void; + enterVarDeclaration?: (ctx: VarDeclarationContext) => void; /** - * Exit a parse tree produced by `JackParser.varDec`. + * Exit a parse tree produced by `JackParser.varDeclaration`. * @param ctx the parse tree */ - exitVarDec?: (ctx: VarDecContext) => void; + exitVarDeclaration?: (ctx: VarDeclarationContext) => void; /** * Enter a parse tree produced by `JackParser.varName`. diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts index 1317cc2c..6910d487 100644 --- a/compiler/src/generated/JackParserVisitor.ts +++ b/compiler/src/generated/JackParserVisitor.ts @@ -3,18 +3,18 @@ import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; +import { StaticFieldDeclarationContext } from "./JackParser"; +import { FieldDeclarationContext } from "./JackParser"; import { ConstructorContext } from "./JackParser"; import { MethodContext } from "./JackParser"; import { FunctionContext } from "./JackParser"; -import { StaticFieldDeclarationContext } from "./JackParser"; -import { FieldDeclarationContext } from "./JackParser"; import { ProgramContext } from "./JackParser"; import { ClassDeclarationContext } from "./JackParser"; import { ClassNameContext } from "./JackParser"; import { ClassVarDecContext } from "./JackParser"; import { FieldListContext } from "./JackParser"; import { FieldNameContext } from "./JackParser"; -import { SubroutineDecContext } from "./JackParser"; +import { SubroutineDeclarationContext } from "./JackParser"; import { SubroutineDecWithoutTypeContext } from "./JackParser"; import { SubroutineNameContext } from "./JackParser"; import { SubroutineReturnTypeContext } from "./JackParser"; @@ -23,7 +23,7 @@ import { ParameterListContext } from "./JackParser"; import { ParameterContext } from "./JackParser"; import { ParameterNameContext } from "./JackParser"; import { SubroutineBodyContext } from "./JackParser"; -import { VarDecContext } from "./JackParser"; +import { VarDeclarationContext } from "./JackParser"; import { VarNameContext } from "./JackParser"; import { StatementsContext } from "./JackParser"; import { StatementContext } from "./JackParser"; @@ -52,44 +52,44 @@ import { BinaryOperatorContext } from "./JackParser"; */ export interface JackParserVisitor extends ParseTreeVisitor { /** - * Visit a parse tree produced by the `constructor` - * labeled alternative in `JackParser.subroutineDec`. + * Visit a parse tree produced by the `staticFieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. * @param ctx the parse tree * @return the visitor result */ - visitConstructor?: (ctx: ConstructorContext) => Result; + visitStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => Result; /** - * Visit a parse tree produced by the `method` - * labeled alternative in `JackParser.subroutineDec`. + * Visit a parse tree produced by the `fieldDeclaration` + * labeled alternative in `JackParser.classVarDec`. * @param ctx the parse tree * @return the visitor result */ - visitMethod?: (ctx: MethodContext) => Result; + visitFieldDeclaration?: (ctx: FieldDeclarationContext) => Result; /** - * Visit a parse tree produced by the `function` - * labeled alternative in `JackParser.subroutineDec`. + * Visit a parse tree produced by the `constructor` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree * @return the visitor result */ - visitFunction?: (ctx: FunctionContext) => Result; + visitConstructor?: (ctx: ConstructorContext) => Result; /** - * Visit a parse tree produced by the `staticFieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. + * Visit a parse tree produced by the `method` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree * @return the visitor result */ - visitStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => Result; + visitMethod?: (ctx: MethodContext) => Result; /** - * Visit a parse tree produced by the `fieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. + * Visit a parse tree produced by the `function` + * labeled alternative in `JackParser.subroutineDeclaration`. * @param ctx the parse tree * @return the visitor result */ - visitFieldDeclaration?: (ctx: FieldDeclarationContext) => Result; + visitFunction?: (ctx: FunctionContext) => Result; /** * Visit a parse tree produced by `JackParser.program`. @@ -134,11 +134,11 @@ export interface JackParserVisitor extends ParseTreeVisitor { visitFieldName?: (ctx: FieldNameContext) => Result; /** - * Visit a parse tree produced by `JackParser.subroutineDec`. + * Visit a parse tree produced by `JackParser.subroutineDeclaration`. * @param ctx the parse tree * @return the visitor result */ - visitSubroutineDec?: (ctx: SubroutineDecContext) => Result; + visitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => Result; /** * Visit a parse tree produced by `JackParser.subroutineDecWithoutType`. @@ -197,11 +197,11 @@ export interface JackParserVisitor extends ParseTreeVisitor { visitSubroutineBody?: (ctx: SubroutineBodyContext) => Result; /** - * Visit a parse tree produced by `JackParser.varDec`. + * Visit a parse tree produced by `JackParser.varDeclaration`. * @param ctx the parse tree * @return the visitor result */ - visitVarDec?: (ctx: VarDecContext) => Result; + visitVarDeclaration?: (ctx: VarDeclarationContext) => Result; /** * Visit a parse tree produced by `JackParser.varName`. diff --git a/compiler/src/error.listener.ts b/compiler/src/listener/error.listener.ts similarity index 100% rename from compiler/src/error.listener.ts rename to compiler/src/listener/error.listener.ts diff --git a/compiler/src/symbol.table.istener.ts b/compiler/src/listener/symbol.table.listener.ts similarity index 87% rename from compiler/src/symbol.table.istener.ts rename to compiler/src/listener/symbol.table.listener.ts index 13daab87..31eba1ec 100644 --- a/compiler/src/symbol.table.istener.ts +++ b/compiler/src/listener/symbol.table.listener.ts @@ -1,8 +1,8 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ClassDeclarationContext, ConstructorContext, FunctionContext, MethodContext, SubroutineDecWithoutTypeContext } from "./generated/JackParser"; -import { JackParserListener } from "./generated/JackParserListener"; -import { DuplicatedSubroutineError } from './error' +import { ClassDeclarationContext, ConstructorContext, FunctionContext, MethodContext, SubroutineDecWithoutTypeContext } from "../generated/JackParser"; +import { JackParserListener } from "../generated/JackParserListener"; +import { DuplicatedSubroutineError } from '../error' const primitives = new Set(["int", "boolean", "char"] as const); export type Primitive = typeof primitives extends Set ? S : never; @@ -13,7 +13,7 @@ export interface GenericSymbol extends Symbol { subroutineParameterCount?: number; } -export class SymbolTableListener implements JackParserListener, ParseTreeListener { +export class GlobalSymbolTableListener implements JackParserListener, ParseTreeListener { // key can be class or . public globalSymbolTable: Record = {}; diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts new file mode 100644 index 00000000..422c13d3 --- /dev/null +++ b/compiler/src/listener/validator.listener.ts @@ -0,0 +1,82 @@ +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { DuplicatedVarException, JackCompilerError } from "../error"; +import { FieldDeclarationContext, SubroutineBodyContext, VarDeclarationContext } from "../generated/JackParser"; +import { JackParserListener } from "../generated/JackParserListener"; +import { GenericSymbol } from "./symbol.table.listener"; + + +export class ValidatorListener implements JackParserListener, ParseTreeListener { + + /** + * List of validations rules: + * - variable declaration - validate duplicate variable declarations + * Let: + * - Undeclared variable + * - `Subroutine ${subroutine.name.value}: not all code paths return a value`, + * - `A non void subroutine must return a value`, + * - Unknown type for return type, class variable, or method local var + * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface + * - validate arg number + * - `Method ${className}.${subroutineName} was called as a function/constructor` + * - Subroutine was called as a method + * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` + * - `Class ${className} doesn't exist` + */ + + //why do we need local symbol table? this vars, arguments, local vars. What about types? + localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); + constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } + + enterFieldDeclaration(ctx: FieldDeclarationContext) { + for (const fieldName of ctx.fieldList().fieldName().map(v=>v.text)) { + this.localSymbolTableAdd(fieldName); + } + }; + + enterSubroutineBody(ctx: SubroutineBodyContext) { + this.localSymbolTable.pushStack(); + }; + + enterVarDec(ctx: VarDeclarationContext) { + //validate duplicate variable declarations + const varNames = ctx.varName().map(v => v.text) + for (const varName of varNames) { + this.localSymbolTable.add(varName); + } + }; + exitSubroutineBody(ctx: SubroutineBodyContext) { + this.localSymbolTable.popStack(); + }; + + localSymbolTableAdd(name: string) { + if (this.localSymbolTable.lookup(name)) { + this.errors.push(new DuplicatedVarException(name)); + } + } + //to fix compiler error + visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; +} + +export class LocalSymbolTable { + constructor(private scopeVarDecs: string[][] = [[]]) { + + } + lookup(name: string): boolean { + for (let i = this.scopeVarDecs.length - 1; i >= 0; i--) { + if (this.scopeVarDecs[i].includes(name)) { + return true; + } + } + return false; + } + add(varName: string) { + this.scopeVarDecs[this.scopeVarDecs.length - 1].push(varName); + } + pushStack() { + this.scopeVarDecs.push([]); + } + popStack() { + this.scopeVarDecs.pop(); + } +} \ No newline at end of file diff --git a/compiler/src/validator.listener.ts b/compiler/src/validator.listener.ts deleted file mode 100644 index 5fe5161c..00000000 --- a/compiler/src/validator.listener.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; -import { JackParserListener } from "./generated/JackParserListener"; -import { GenericSymbol } from "./symbol.table.istener"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; - -export class ValidatorListener implements JackParserListener, ParseTreeListener { - /** - * List of validations rules: - * - variable declaration - validate duplicate variable declarations - * - let statement - validate variable is declared - * - `Subroutine ${subroutine.name.value}: not all code paths return a value`, - * - `A non void subroutine must return a value`, - * - Undeclared variable - * - Unknown type for return type, class variable, or method local var - * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface - * - validate arg number - * - `Method ${className}.${subroutineName} was called as a function/constructor` - * - Subroutine was called as a method - * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` - * - `Class ${className} doesn't exist` - */ - - //TODO: change - localSymbolTable: Record = {}; - constructor(private globalSymbolTable: Record) { } - - - - - //to fix compiler error - visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; -} \ No newline at end of file diff --git a/compiler/test/local.symbol.table.test.ts b/compiler/test/local.symbol.table.test.ts new file mode 100644 index 00000000..cb604d00 --- /dev/null +++ b/compiler/test/local.symbol.table.test.ts @@ -0,0 +1,37 @@ +import { LocalSymbolTable } from "../src/listener/validator.listener"; + +describe('LocalSymbolTable', () => { + test('add', () => { + const localSymbolTable = new LocalSymbolTable(); + const variableNames = ['testVariable1', 'testVariable2', 'testVariable3']; + + variableNames.forEach(variableName => { + localSymbolTable.add(variableName) + expect(localSymbolTable.lookup(variableName)).toBe(true); + expect(localSymbolTable.lookup(variableName + "_")).toBe(false); + + }); + + }) + test('push and pop stack', () => { + const localSymbolTable = new LocalSymbolTable(); + const classVar = 'a'; + const functionVar = 'b'; + + localSymbolTable.add(classVar); + + + localSymbolTable.pushStack(); + localSymbolTable.add(functionVar); + + expect(localSymbolTable.lookup(classVar )).toBe(true); + expect(localSymbolTable.lookup(functionVar)).toBe(true); + + localSymbolTable.popStack(); + + expect(localSymbolTable.lookup(classVar)).toBe(true); + expect(localSymbolTable.lookup(functionVar)).toBe(false); + + }) + +}); \ No newline at end of file diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index c594162a..35af6ae2 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -1,10 +1,10 @@ import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker'; import fs from 'fs'; -import { SymbolTableListener } from "../src/symbol.table.istener"; +import { GlobalSymbolTableListener } from "../src/listener/symbol.table.listener"; import path from "path"; -import { ErrorListener } from "../src/error.listener"; -import { getTestResourcePath, parseJack } from "./test.helper"; +import { ErrorListener } from "../src/listener/error.listener"; +import { getTestResourcePath, parseJackFile, traverseTree } from "./test.helper"; describe('Parser', () => { @@ -35,17 +35,13 @@ describe('Parser', () => { }); function testJackDir(testFolder: string): void { - - const globalSymbolsListener = new SymbolTableListener(); const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); for (const filePath of files) { const errorListener = ErrorListener.getInstance() errorListener.filepath = filePath; - const tree = parseJack(filePath, errorListener); + const tree = parseJackFile(filePath, errorListener); expect(errorListener.error).toBe(false) - // console.log(tree.toStringTree(parser.ruleNames)); - - ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); + const globalSymbolsListener = traverseTree(tree, new GlobalSymbolTableListener()); const symbolsErrors = globalSymbolsListener.errors.join("\n") try { expect(globalSymbolsListener.errors.length).toBe(0) diff --git a/compiler/test/symbol.table.listener.test.ts b/compiler/test/symbol.table.listener.test.ts index 571e0656..155918b6 100644 --- a/compiler/test/symbol.table.listener.test.ts +++ b/compiler/test/symbol.table.listener.test.ts @@ -1,8 +1,8 @@ import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; -import { ErrorListener } from "../src/error.listener"; -import { GenericSymbol, SymbolTableListener } from "../src/symbol.table.istener"; +import { ErrorListener } from "../src/listener/error.listener"; +import { GenericSymbol, GlobalSymbolTableListener } from "../src/listener/symbol.table.listener"; import { DuplicatedSubroutineError } from "../src/error"; -import { parseJack, getTestResourcePath } from "./test.helper"; +import { parseJackFile, getTestResourcePath, traverseTree } from "./test.helper"; import fs from 'fs'; import path from "path"; @@ -11,7 +11,11 @@ describe('Global symbol table', () => { test("should fail on duplicated subroutine", () => { const filePath = getTestResourcePath("DuplicatedSubroutine.jack"); const errorListener = ErrorListener.getInstance() - const globalSymbolsListener = traverseTree(errorListener, filePath); + errorListener.filepath = filePath; + const tree = parseJackFile(filePath, errorListener); + expect(errorListener.error).toBe(false) + const globalSymbolsListener = new GlobalSymbolTableListener() + traverseTree(tree, globalSymbolsListener) const symbolsErrors = globalSymbolsListener.errors expect(globalSymbolsListener.errors.length).toBe(1) expect(symbolsErrors[0]).toBeInstanceOf(DuplicatedSubroutineError) @@ -31,27 +35,18 @@ describe('Global symbol table', () => { 'Main': {}, 'Main.main': { subroutineParameterCount: 0 } } - let globalSymbolsListener = new SymbolTableListener() + let globalSymbolsListener = new GlobalSymbolTableListener() const testFolder = getTestResourcePath("Fraction"); const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); - const symbols = [] for (const filePath of files) { - const errorListener = ErrorListener.getInstance() - globalSymbolsListener = traverseTree(errorListener, filePath, globalSymbolsListener); + const tree = parseJackFile(filePath, errorListener); + globalSymbolsListener = traverseTree(tree, globalSymbolsListener); + console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) } expect(globalSymbolsListener.globalSymbolTable).toEqual(expected) }) }) -function traverseTree(errorListener: ErrorListener, filePath: string, globalSymbolsListener = new SymbolTableListener()) { - errorListener.filepath = filePath; - const tree = parseJack(filePath, errorListener); - - expect(errorListener.error).toBe(false); - - ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); - return globalSymbolsListener; -} diff --git a/compiler/test/test.helper.ts b/compiler/test/test.helper.ts index 974fbd1d..784ef3c3 100644 --- a/compiler/test/test.helper.ts +++ b/compiler/test/test.helper.ts @@ -1,12 +1,19 @@ import { ANTLRErrorListener, CharStreams, CommonTokenStream } from "antlr4ts"; -import { JackParser } from "../src/generated/JackParser"; +import { JackParser, ProgramContext } from "../src/generated/JackParser"; import { JackLexer } from "../src/generated/JackLexer"; import fs from 'fs'; import path from "path"; +import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; +import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; -export function parseJack(filePath: string, errorListener?: ANTLRErrorListener, trace = false) { +export function parseJackFile(filePath: string, errorListener?: ANTLRErrorListener, trace = false) { const f = fs.readFileSync(filePath, 'utf8'); - const inputStream = CharStreams.fromString(f); + return parseJackText(f, errorListener, trace); +} + +export function parseJackText(source: string, errorListener: ANTLRErrorListener | undefined, trace: boolean = false) { + console.log("Source", source) + const inputStream = CharStreams.fromString(source); const lexer = new JackLexer(inputStream); if (errorListener) { @@ -15,7 +22,7 @@ export function parseJack(filePath: string, errorListener?: ANTLRErrorListener(tree: ProgramContext, listener: T) { + ParseTreeWalker.DEFAULT.walk(listener, tree); + return listener; +} diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts new file mode 100644 index 00000000..df3b1fc7 --- /dev/null +++ b/compiler/test/validator.listener.test.ts @@ -0,0 +1,20 @@ +import { ErrorListener } from "../src/listener/error.listener" +import { GenericSymbol } from "../src/listener/symbol.table.listener" +import { ValidatorListener } from "../src/listener/validator.listener" +import { parseJackFile, parseJackText } from "./test.helper" + +describe('ValidatorListener', () => { + test('Duplicate variable declaration', () => { + const src = ` + class Main { + static int a; + field int a; + }` + const errorListener = ErrorListener.getInstance(); + const tree = parseJackText(src, errorListener) + expect(errorListener.error).toBe(false) + const validator = new ValidatorListener({} as Record); + + + }) +}) \ No newline at end of file From 029f124d3e6b982f8258c564264a8ce83a5802eb Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 26 Sep 2024 14:10:38 +0200 Subject: [PATCH 08/87] Add more validations --- compiler/src/compiler.ts | 6 +- compiler/src/error.ts | 34 ++++++++-- compiler/src/listener/error.listener.ts | 5 +- .../src/listener/symbol.table.listener.ts | 7 +- compiler/src/listener/validator.listener.ts | 34 +++++----- compiler/test/parser.test.ts | 9 +-- compiler/test/symbol.table.listener.test.ts | 17 ++--- compiler/test/test.helper.ts | 34 +++++++--- compiler/test/validator.listener.test.ts | 64 +++++++++++++++---- 9 files changed, 143 insertions(+), 67 deletions(-) diff --git a/compiler/src/compiler.ts b/compiler/src/compiler.ts index 9a2e92bf..8d73ad0f 100644 --- a/compiler/src/compiler.ts +++ b/compiler/src/compiler.ts @@ -1,5 +1,5 @@ import path from "path"; -import { SymbolTableListener } from "./symbol.table.istener"; +import { GlobalSymbolTableListener } from "./listener/symbol.table.listener"; import fs from "fs"; import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; import { JackParser } from "./generated/JackParser"; @@ -10,7 +10,7 @@ import { ValidatorListener } from "./listener/validator.listener"; export default class Compiler { static compile(dir: string): string { - const globalSymbolsListener = new SymbolTableListener(); + const globalSymbolsListener = new GlobalSymbolTableListener(); const files = fs.readdirSync(dir).filter(file => file.endsWith(".jack")).map(file => path.join(dir, file)); for (const filePath of files) { const errorListener = ErrorListener.getInstance() @@ -33,7 +33,7 @@ export default class Compiler { } const tree = parser.program(); //TODO add error handling here - if (errorListener.error) { + if (errorListener.errors.length > 0) { console.error(errorListener.filepath + " has syntax errors"); continue } diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 7ab2df10..9ee5bb52 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -1,27 +1,47 @@ export class JackCompilerError extends Error { - constructor(msg: string) { + /** + * + * @param line - line number + * @param charPositionInLine - charPositionInLine in the line + * @param msg - error message + */ + constructor(public line: number, public charPositionInLine: number, public msg: string) { super(msg); // Set the prototype explicitly. Object.setPrototypeOf(this, JackCompilerError.prototype); } } -export class DuplicatedSubroutineError extends JackCompilerError { - constructor(msg: string) { +export class LexerOrParserError extends Error { + /** + * + * @param line - line number + * @param charPositionInLine - charPositionInLine in the line + * @param msg - error message + */ + constructor(public filepath: string, public line: number, public charPositionInLine: number, public msg: string) { super(msg); + // Set the prototype explicitly. + Object.setPrototypeOf(this, LexerOrParserError.prototype); + } +} +export class DuplicatedSubroutineError extends JackCompilerError { + constructor(line: number, charPositionInLine: number, msg: string) { + super(line, charPositionInLine, msg); + // Set the prototype explicitly. Object.setPrototypeOf(this, DuplicatedSubroutineError.prototype); } } -export class DuplicatedVarException extends JackCompilerError { - constructor(varName: string) { - super("Duplicated variable " + varName); +export class DuplicatedVariableException extends JackCompilerError { + constructor(line: number, charPositionInLine: number, variableName: string) { + super(line, charPositionInLine, "Duplicated variable " + variableName); // Set the prototype explicitly. - Object.setPrototypeOf(this, DuplicatedSubroutineError.prototype); + Object.setPrototypeOf(this, DuplicatedVariableException.prototype); } } diff --git a/compiler/src/listener/error.listener.ts b/compiler/src/listener/error.listener.ts index c632a718..17c9b60d 100644 --- a/compiler/src/listener/error.listener.ts +++ b/compiler/src/listener/error.listener.ts @@ -1,8 +1,9 @@ import { ANTLRErrorListener, RecognitionException, Recognizer } from 'antlr4ts'; +import { JackCompilerError, LexerOrParserError } from '../error'; export class ErrorListener implements ANTLRErrorListener { static instance: ErrorListener; public filepath: string = ""; - public error: boolean = false; + public errors: JackCompilerError[] = []; static getInstance(): ErrorListener { if (this.instance == null) { this.instance = new ErrorListener() @@ -16,7 +17,7 @@ export class ErrorListener implements ANTLRErrorListener { * Provides a default instance of {@link ConsoleErrorListener}. */ syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number, charPositionInLine: number, msg: string, e: RecognitionException | undefined) { - this.error = true; + this.errors.push(new LexerOrParserError(this.filepath, line, charPositionInLine, msg)); console.error(`${this.filepath}:${line}:${charPositionInLine} \n${msg}`); }; } \ No newline at end of file diff --git a/compiler/src/listener/symbol.table.listener.ts b/compiler/src/listener/symbol.table.listener.ts index 31eba1ec..911a35eb 100644 --- a/compiler/src/listener/symbol.table.listener.ts +++ b/compiler/src/listener/symbol.table.listener.ts @@ -26,7 +26,7 @@ export class GlobalSymbolTableListener implements JackParserListener, ParseTreeL enterClassDeclaration(ctx: ClassDeclarationContext) { if (this.globalSymbolTable[ctx.className()!.text] != undefined) { - this.errors.push(new DuplicatedSubroutineError(`Class "${ctx.className()!.text}" already defined.`)); + this.errors.push(new DuplicatedSubroutineError(ctx.start.line, ctx.start.startIndex, `Class "${ctx.className()!.text}" already defined.`)); return; } this.globalSymbolTable[ctx.className()!.text] = {} as GenericSymbol; @@ -48,10 +48,11 @@ export class GlobalSymbolTableListener implements JackParserListener, ParseTreeL } #addSymbol(c: SubroutineDecWithoutTypeContext) { - const subroutineName = c.subroutineName().text + const ctx = c.subroutineName() + const subroutineName = ctx.text const id = this.className + "." + subroutineName if (this.globalSymbolTable[id] != undefined) { - this.errors.push(new DuplicatedSubroutineError(`Subroutine "${subroutineName}" is already defined.`)); + this.errors.push(new DuplicatedSubroutineError(ctx.start.line, ctx.start.startIndex, `Subroutine "${subroutineName}" is already defined.`)); } this.globalSymbolTable[id] = { subroutineParameterCount: c.parameterList().parameter().length diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 422c13d3..eba86ae1 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,13 +1,14 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { DuplicatedVarException, JackCompilerError } from "../error"; -import { FieldDeclarationContext, SubroutineBodyContext, VarDeclarationContext } from "../generated/JackParser"; +import { DuplicatedVariableException, JackCompilerError } from "../error"; +import { FieldDeclarationContext, FieldNameContext, ParameterContext, ParameterNameContext, SubroutineBodyContext, SubroutineDeclarationContext, VarDeclarationContext, VarNameContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol } from "./symbol.table.listener"; export class ValidatorListener implements JackParserListener, ParseTreeListener { + /** * List of validations rules: * - variable declaration - validate duplicate variable declarations @@ -28,30 +29,29 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } - enterFieldDeclaration(ctx: FieldDeclarationContext) { - for (const fieldName of ctx.fieldList().fieldName().map(v=>v.text)) { - this.localSymbolTableAdd(fieldName); - } + enterFieldName(ctx: FieldNameContext) { + this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); }; - enterSubroutineBody(ctx: SubroutineBodyContext) { + enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { this.localSymbolTable.pushStack(); }; - - enterVarDec(ctx: VarDeclarationContext) { - //validate duplicate variable declarations - const varNames = ctx.varName().map(v => v.text) - for (const varName of varNames) { - this.localSymbolTable.add(varName); - } + + enterParameterName(ctx: ParameterNameContext) { + this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); + } + + enterVarName(ctx: VarNameContext) { + this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); }; exitSubroutineBody(ctx: SubroutineBodyContext) { this.localSymbolTable.popStack(); }; - - localSymbolTableAdd(name: string) { + localSymbolTableAdd(line: number, position: number, name: string) { if (this.localSymbolTable.lookup(name)) { - this.errors.push(new DuplicatedVarException(name)); + this.errors.push(new DuplicatedVariableException(line, position, name)); + } else { + this.localSymbolTable.add(name); } } //to fix compiler error diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index 35af6ae2..cc6cea83 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -4,7 +4,9 @@ import { GlobalSymbolTableListener } from "../src/listener/symbol.table.listener import path from "path"; import { ErrorListener } from "../src/listener/error.listener"; -import { getTestResourcePath, parseJackFile, traverseTree } from "./test.helper"; +import { getTestResourcePath, listenToTheTree, parseJackText, handleErrors, parseJackFile } from "./test.helper"; +import { ProgramContext } from '../src/generated/JackParser'; +import { JackCompilerError } from '../src/error'; describe('Parser', () => { @@ -39,9 +41,8 @@ function testJackDir(testFolder: string): void { for (const filePath of files) { const errorListener = ErrorListener.getInstance() errorListener.filepath = filePath; - const tree = parseJackFile(filePath, errorListener); - expect(errorListener.error).toBe(false) - const globalSymbolsListener = traverseTree(tree, new GlobalSymbolTableListener()); + const tree = parseJackFile(filePath) + const globalSymbolsListener = listenToTheTree(tree, new GlobalSymbolTableListener()); const symbolsErrors = globalSymbolsListener.errors.join("\n") try { expect(globalSymbolsListener.errors.length).toBe(0) diff --git a/compiler/test/symbol.table.listener.test.ts b/compiler/test/symbol.table.listener.test.ts index 155918b6..eb729520 100644 --- a/compiler/test/symbol.table.listener.test.ts +++ b/compiler/test/symbol.table.listener.test.ts @@ -1,21 +1,19 @@ import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; import { ErrorListener } from "../src/listener/error.listener"; import { GenericSymbol, GlobalSymbolTableListener } from "../src/listener/symbol.table.listener"; -import { DuplicatedSubroutineError } from "../src/error"; -import { parseJackFile, getTestResourcePath, traverseTree } from "./test.helper"; +import { DuplicatedSubroutineError, JackCompilerError } from "../src/error"; +import { getTestResourcePath, listenToTheTree, handleErrors, parseJackText, parseJackFile } from "./test.helper"; import fs from 'fs'; import path from "path"; +import { ProgramContext } from "../src/generated/JackParser"; describe('Global symbol table', () => { test("should fail on duplicated subroutine", () => { const filePath = getTestResourcePath("DuplicatedSubroutine.jack"); - const errorListener = ErrorListener.getInstance() - errorListener.filepath = filePath; - const tree = parseJackFile(filePath, errorListener); - expect(errorListener.error).toBe(false) + const tree = parseJackFile(filePath) const globalSymbolsListener = new GlobalSymbolTableListener() - traverseTree(tree, globalSymbolsListener) + listenToTheTree(tree, globalSymbolsListener) const symbolsErrors = globalSymbolsListener.errors expect(globalSymbolsListener.errors.length).toBe(1) expect(symbolsErrors[0]).toBeInstanceOf(DuplicatedSubroutineError) @@ -40,9 +38,8 @@ describe('Global symbol table', () => { const testFolder = getTestResourcePath("Fraction"); const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); for (const filePath of files) { - const errorListener = ErrorListener.getInstance() - const tree = parseJackFile(filePath, errorListener); - globalSymbolsListener = traverseTree(tree, globalSymbolsListener); + const tree = parseJackFile(filePath) + globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) } expect(globalSymbolsListener.globalSymbolTable).toEqual(expected) diff --git a/compiler/test/test.helper.ts b/compiler/test/test.helper.ts index 784ef3c3..0bb90da2 100644 --- a/compiler/test/test.helper.ts +++ b/compiler/test/test.helper.ts @@ -1,22 +1,27 @@ -import { ANTLRErrorListener, CharStreams, CommonTokenStream } from "antlr4ts"; +import { ANTLRErrorListener, CharStreams, CommonTokenStream, ParserRuleContext } from "antlr4ts"; import { JackParser, ProgramContext } from "../src/generated/JackParser"; import { JackLexer } from "../src/generated/JackLexer"; import fs from 'fs'; import path from "path"; import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; +import { JackCompilerError } from "../src/error"; +import { ErrorListener } from "../src/listener/error.listener"; -export function parseJackFile(filePath: string, errorListener?: ANTLRErrorListener, trace = false) { +export function parseJackFile(filePath: string, trace = false) { + const errorListener: ErrorListener = ErrorListener.getInstance() + errorListener.filepath = filePath const f = fs.readFileSync(filePath, 'utf8'); return parseJackText(f, errorListener, trace); } -export function parseJackText(source: string, errorListener: ANTLRErrorListener | undefined, trace: boolean = false) { - console.log("Source", source) - const inputStream = CharStreams.fromString(source); +export function parseJackText(src: string, errorListener?: ErrorListener, trace: boolean = false): ProgramContext { + if (errorListener === undefined) { + errorListener = ErrorListener.getInstance(); + } + const inputStream = CharStreams.fromString(src); const lexer = new JackLexer(inputStream); if (errorListener) { - lexer.removeErrorListeners(); lexer.addErrorListener(errorListener); } @@ -29,14 +34,27 @@ export function parseJackText(source: string, errorListener: ANTLRErrorListener< parser.removeErrorListeners(); parser.addErrorListener(errorListener); } - return parser.program(); + const tree = parser.program() + if (errorListener.errors.length > 0) { + handleErrors(src, errorListener.errors); + } + return tree; } export function getTestResourcePath(relativePath: string) { return path.join(__dirname, "resources", relativePath); } -export function traverseTree(tree: ProgramContext, listener: T) { +export function listenToTheTree(tree: ProgramContext, listener: T) { ParseTreeWalker.DEFAULT.walk(listener, tree); return listener; } + + +export function handleErrors(src: string, errors: JackCompilerError[]) { + const msg = errors.map(e => { + return `${e.line}:${e.charPositionInLine} ${e.msg}\n${src.split("\n")[e.line]}` + }).join("\n") + console.error(msg); + throw new Error(msg) +} \ No newline at end of file diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index df3b1fc7..f973a9e3 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,20 +1,58 @@ +import { ParserRuleContext } from "antlr4ts" +import { DuplicatedVariableException, JackCompilerError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { GenericSymbol } from "../src/listener/symbol.table.listener" import { ValidatorListener } from "../src/listener/validator.listener" -import { parseJackFile, parseJackText } from "./test.helper" +import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" +import { ProgramContext } from "../src/generated/JackParser" describe('ValidatorListener', () => { - test('Duplicate variable declaration', () => { - const src = ` - class Main { - static int a; - field int a; - }` - const errorListener = ErrorListener.getInstance(); - const tree = parseJackText(src, errorListener) - expect(errorListener.error).toBe(false) - const validator = new ValidatorListener({} as Record); + const duplicateVarClassBodies = [ + ["static", ' static int a, a;'], + ["field", ' field int a, a;'], + ["static and field", ' static int a; field boolean a;'], + ["function args", ' function void a(int a, int a){return;}'], + ["function var", ` function void a(){ + var boolean a, a; + return; + }`], + ["function var with different types", ` function void a(){ + var boolean a; + var int a; + return; + }`], + ] + test.concurrent.each(duplicateVarClassBodies)('duplicated %s', (testName, classBody) => { + testValidator(testName, ` + class Main { + ${classBody} + }`, DuplicatedVariableException) + }) + //TODO: print line when on exception + /* + * - variable declaration - validate duplicate variable declarations + * Let: + * - Undeclared variable + * - `Subroutine ${subroutine.name.value}: not all code paths return a value`, + * - `A non void subroutine must return a value`, + * - Unknown type for return type, class variable, or method local var + * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface + * - validate arg number + * - `Method ${className}.${subroutineName} was called as a function/constructor` + * - Subroutine was called as a method + * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` + * - `Class ${className} doesn't exist` + */ +}) - }) -}) \ No newline at end of file +function testValidator(testName: string, src: string, expectedError: T) { + console.info("Testing \n", src) + const errorListener = ErrorListener.getInstance(); + errorListener.filepath = testName; + const tree = parseJackText(src, errorListener) + + const validator = listenToTheTree(tree, new ValidatorListener({} as Record)) + expect(validator.errors.length).toBe(1) + expect(validator.errors[0]).toBeInstanceOf(expectedError) +} From d07a587d5bb6f335ab064b8f1e0c6061fffd3ff3 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 26 Sep 2024 18:49:56 +0200 Subject: [PATCH 09/87] Add more validations --- .vscode/numbered-bookmarks.json | 49 ++ compiler/parser-gen/JackParser.g4 | 15 +- compiler/src/error.ts | 11 + compiler/src/generated/JackParser.interp | 3 +- compiler/src/generated/JackParser.ts | 765 ++++++++++--------- compiler/src/generated/JackParserListener.ts | 12 + compiler/src/generated/JackParserVisitor.ts | 8 + compiler/src/listener/error.listener.ts | 7 - compiler/src/listener/validator.listener.ts | 19 +- compiler/test/local.symbol.table.test.ts | 22 +- compiler/test/parser.test.ts | 5 +- compiler/test/symbol.table.listener.test.ts | 9 + compiler/test/test.helper.ts | 5 +- compiler/test/validator.listener.test.ts | 72 +- simulator/.vscode/numbered-bookmarks.json | 3 + 15 files changed, 618 insertions(+), 387 deletions(-) create mode 100644 .vscode/numbered-bookmarks.json create mode 100644 simulator/.vscode/numbered-bookmarks.json diff --git a/.vscode/numbered-bookmarks.json b/.vscode/numbered-bookmarks.json new file mode 100644 index 00000000..5268caba --- /dev/null +++ b/.vscode/numbered-bookmarks.json @@ -0,0 +1,49 @@ +{ + "files": [ + { + "path": "simulator/src/jack/compiler.ts", + "bookmarks": [ + { + "line": -1, + "column": 0 + }, + { + "line": -1, + "column": 0 + }, + { + "line": -1, + "column": 0 + }, + { + "line": 160, + "column": 2 + }, + { + "line": -1, + "column": 0 + }, + { + "line": -1, + "column": 0 + }, + { + "line": -1, + "column": 0 + }, + { + "line": -1, + "column": 0 + }, + { + "line": -1, + "column": 0 + }, + { + "line": -1, + "column": 0 + } + ] + } + ] +} \ No newline at end of file diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/parser-gen/JackParser.g4 index 242c8066..4fd359a9 100644 --- a/compiler/parser-gen/JackParser.g4 +++ b/compiler/parser-gen/JackParser.g4 @@ -20,7 +20,7 @@ subroutineDeclaration: | FUNCTION subroutineDecWithoutType # function; subroutineDecWithoutType: subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; -subroutineName: IDENTIFIER; + subroutineName: IDENTIFIER; subroutineReturnType: varType | VOID; varType: INT | CHAR | BOOLEAN | IDENTIFIER; @@ -31,7 +31,8 @@ parameterName: IDENTIFIER; subroutineBody: LBRACE varDeclaration* statements RBRACE; -varDeclaration: VAR varType varName (COMMA varName)* SEMICOLON; +varDeclaration: VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; +varNameInDeclaration: IDENTIFIER; varName: IDENTIFIER; statements: statement*; statement: @@ -42,7 +43,7 @@ statement: | returnStatement; letStatement: - LET (IDENTIFIER | arrayAccess) EQUALS expression SEMICOLON; //TODO: check right assoc for this + LET (varName | arrayAccess) EQUALS expression SEMICOLON; //TODO: check right assoc for this ifStatement: IF LPAREN expression RPAREN LBRACE statements RBRACE ( @@ -55,8 +56,8 @@ whileStatement: doStatement: DO subroutineCall SEMICOLON; subroutineCall: - IDENTIFIER LPAREN expressionList RPAREN - | (IDENTIFIER | THIS_LITERAL) DOT IDENTIFIER LPAREN expressionList RPAREN; + subroutineName LPAREN expressionList RPAREN + | (className | THIS_LITERAL) DOT subroutineName LPAREN expressionList RPAREN; returnStatement: RETURN expression? SEMICOLON; @@ -65,7 +66,7 @@ expressionList: (expression (COMMA expression)*)?; expression: binaryOperation = expression binaryOperator expression | constant - | IDENTIFIER + | varName | subroutineCall | arrayAccess | unaryOp @@ -73,7 +74,7 @@ expression: groupedExpression: LPAREN expression RPAREN; unaryOp: unaryOperator expression; -arrayAccess: IDENTIFIER LBRACKET expression RBRACKET; +arrayAccess: varName LBRACKET expression RBRACKET; constant: INTEGER_LITERAL diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 9ee5bb52..8ca6a8f0 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -45,3 +45,14 @@ export class DuplicatedVariableException extends JackCompilerError { } } + + +export class UndeclaredVariableError extends JackCompilerError { + constructor(line: number, charPositionInLine: number, variableName: string) { + super(line, charPositionInLine, "Undeclared variable " + variableName); + + // Set the prototype explicitly. + Object.setPrototypeOf(this, UndeclaredVariableError.prototype); + } + +} diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp index 3b0a4aa4..cf7546af 100644 --- a/compiler/src/generated/JackParser.interp +++ b/compiler/src/generated/JackParser.interp @@ -113,6 +113,7 @@ parameter parameterName subroutineBody varDeclaration +varNameInDeclaration varName statements statement @@ -133,4 +134,4 @@ binaryOperator atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 288, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 76, 10, 3, 12, 3, 14, 3, 79, 11, 3, 3, 3, 7, 3, 82, 10, 3, 12, 3, 14, 3, 85, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 99, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 105, 10, 6, 12, 6, 14, 6, 108, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 118, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 131, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 138, 10, 13, 12, 13, 14, 13, 141, 11, 13, 5, 13, 143, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 152, 10, 16, 12, 16, 14, 16, 155, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 165, 10, 17, 12, 17, 14, 17, 168, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 7, 19, 175, 10, 19, 12, 19, 14, 19, 178, 11, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 5, 20, 185, 10, 20, 3, 21, 3, 21, 3, 21, 5, 21, 190, 10, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 208, 10, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 5, 25, 234, 10, 25, 3, 26, 3, 26, 5, 26, 238, 10, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 7, 27, 245, 10, 27, 12, 27, 14, 27, 248, 11, 27, 5, 27, 250, 10, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 259, 10, 28, 3, 28, 3, 28, 3, 28, 3, 28, 7, 28, 265, 10, 28, 12, 28, 14, 28, 268, 11, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 2, 2, 3, 54, 35, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 2, 7, 4, 2, 10, 12, 46, 46, 3, 2, 45, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 282, 2, 68, 3, 2, 2, 2, 4, 71, 3, 2, 2, 2, 6, 88, 3, 2, 2, 2, 8, 98, 3, 2, 2, 2, 10, 100, 3, 2, 2, 2, 12, 109, 3, 2, 2, 2, 14, 117, 3, 2, 2, 2, 16, 119, 3, 2, 2, 2, 18, 126, 3, 2, 2, 2, 20, 130, 3, 2, 2, 2, 22, 132, 3, 2, 2, 2, 24, 142, 3, 2, 2, 2, 26, 144, 3, 2, 2, 2, 28, 147, 3, 2, 2, 2, 30, 149, 3, 2, 2, 2, 32, 159, 3, 2, 2, 2, 34, 171, 3, 2, 2, 2, 36, 176, 3, 2, 2, 2, 38, 184, 3, 2, 2, 2, 40, 186, 3, 2, 2, 2, 42, 195, 3, 2, 2, 2, 44, 209, 3, 2, 2, 2, 46, 217, 3, 2, 2, 2, 48, 233, 3, 2, 2, 2, 50, 235, 3, 2, 2, 2, 52, 249, 3, 2, 2, 2, 54, 258, 3, 2, 2, 2, 56, 269, 3, 2, 2, 2, 58, 273, 3, 2, 2, 2, 60, 276, 3, 2, 2, 2, 62, 281, 3, 2, 2, 2, 64, 283, 3, 2, 2, 2, 66, 285, 3, 2, 2, 2, 68, 69, 5, 4, 3, 2, 69, 70, 7, 2, 2, 3, 70, 3, 3, 2, 2, 2, 71, 72, 7, 3, 2, 2, 72, 73, 5, 6, 4, 2, 73, 77, 7, 20, 2, 2, 74, 76, 5, 8, 5, 2, 75, 74, 3, 2, 2, 2, 76, 79, 3, 2, 2, 2, 77, 75, 3, 2, 2, 2, 77, 78, 3, 2, 2, 2, 78, 83, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 80, 82, 5, 14, 8, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 86, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 87, 7, 21, 2, 2, 87, 5, 3, 2, 2, 2, 88, 89, 7, 46, 2, 2, 89, 7, 3, 2, 2, 2, 90, 91, 7, 8, 2, 2, 91, 92, 5, 10, 6, 2, 92, 93, 7, 28, 2, 2, 93, 99, 3, 2, 2, 2, 94, 95, 7, 7, 2, 2, 95, 96, 5, 10, 6, 2, 96, 97, 7, 28, 2, 2, 97, 99, 3, 2, 2, 2, 98, 90, 3, 2, 2, 2, 98, 94, 3, 2, 2, 2, 99, 9, 3, 2, 2, 2, 100, 101, 5, 22, 12, 2, 101, 106, 5, 12, 7, 2, 102, 103, 7, 27, 2, 2, 103, 105, 5, 12, 7, 2, 104, 102, 3, 2, 2, 2, 105, 108, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 106, 107, 3, 2, 2, 2, 107, 11, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 109, 110, 7, 46, 2, 2, 110, 13, 3, 2, 2, 2, 111, 112, 7, 4, 2, 2, 112, 118, 5, 16, 9, 2, 113, 114, 7, 6, 2, 2, 114, 118, 5, 16, 9, 2, 115, 116, 7, 5, 2, 2, 116, 118, 5, 16, 9, 2, 117, 111, 3, 2, 2, 2, 117, 113, 3, 2, 2, 2, 117, 115, 3, 2, 2, 2, 118, 15, 3, 2, 2, 2, 119, 120, 5, 20, 11, 2, 120, 121, 5, 18, 10, 2, 121, 122, 7, 22, 2, 2, 122, 123, 5, 24, 13, 2, 123, 124, 7, 23, 2, 2, 124, 125, 5, 30, 16, 2, 125, 17, 3, 2, 2, 2, 126, 127, 7, 46, 2, 2, 127, 19, 3, 2, 2, 2, 128, 131, 5, 22, 12, 2, 129, 131, 7, 13, 2, 2, 130, 128, 3, 2, 2, 2, 130, 129, 3, 2, 2, 2, 131, 21, 3, 2, 2, 2, 132, 133, 9, 2, 2, 2, 133, 23, 3, 2, 2, 2, 134, 139, 5, 26, 14, 2, 135, 136, 7, 27, 2, 2, 136, 138, 5, 26, 14, 2, 137, 135, 3, 2, 2, 2, 138, 141, 3, 2, 2, 2, 139, 137, 3, 2, 2, 2, 139, 140, 3, 2, 2, 2, 140, 143, 3, 2, 2, 2, 141, 139, 3, 2, 2, 2, 142, 134, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 25, 3, 2, 2, 2, 144, 145, 5, 22, 12, 2, 145, 146, 5, 28, 15, 2, 146, 27, 3, 2, 2, 2, 147, 148, 7, 46, 2, 2, 148, 29, 3, 2, 2, 2, 149, 153, 7, 20, 2, 2, 150, 152, 5, 32, 17, 2, 151, 150, 3, 2, 2, 2, 152, 155, 3, 2, 2, 2, 153, 151, 3, 2, 2, 2, 153, 154, 3, 2, 2, 2, 154, 156, 3, 2, 2, 2, 155, 153, 3, 2, 2, 2, 156, 157, 5, 36, 19, 2, 157, 158, 7, 21, 2, 2, 158, 31, 3, 2, 2, 2, 159, 160, 7, 9, 2, 2, 160, 161, 5, 22, 12, 2, 161, 166, 5, 34, 18, 2, 162, 163, 7, 27, 2, 2, 163, 165, 5, 34, 18, 2, 164, 162, 3, 2, 2, 2, 165, 168, 3, 2, 2, 2, 166, 164, 3, 2, 2, 2, 166, 167, 3, 2, 2, 2, 167, 169, 3, 2, 2, 2, 168, 166, 3, 2, 2, 2, 169, 170, 7, 28, 2, 2, 170, 33, 3, 2, 2, 2, 171, 172, 7, 46, 2, 2, 172, 35, 3, 2, 2, 2, 173, 175, 5, 38, 20, 2, 174, 173, 3, 2, 2, 2, 175, 178, 3, 2, 2, 2, 176, 174, 3, 2, 2, 2, 176, 177, 3, 2, 2, 2, 177, 37, 3, 2, 2, 2, 178, 176, 3, 2, 2, 2, 179, 185, 5, 40, 21, 2, 180, 185, 5, 42, 22, 2, 181, 185, 5, 44, 23, 2, 182, 185, 5, 46, 24, 2, 183, 185, 5, 50, 26, 2, 184, 179, 3, 2, 2, 2, 184, 180, 3, 2, 2, 2, 184, 181, 3, 2, 2, 2, 184, 182, 3, 2, 2, 2, 184, 183, 3, 2, 2, 2, 185, 39, 3, 2, 2, 2, 186, 189, 7, 14, 2, 2, 187, 190, 7, 46, 2, 2, 188, 190, 5, 60, 31, 2, 189, 187, 3, 2, 2, 2, 189, 188, 3, 2, 2, 2, 190, 191, 3, 2, 2, 2, 191, 192, 7, 29, 2, 2, 192, 193, 5, 54, 28, 2, 193, 194, 7, 28, 2, 2, 194, 41, 3, 2, 2, 2, 195, 196, 7, 16, 2, 2, 196, 197, 7, 22, 2, 2, 197, 198, 5, 54, 28, 2, 198, 199, 7, 23, 2, 2, 199, 200, 7, 20, 2, 2, 200, 201, 5, 36, 19, 2, 201, 207, 7, 21, 2, 2, 202, 203, 7, 17, 2, 2, 203, 204, 7, 20, 2, 2, 204, 205, 5, 36, 19, 2, 205, 206, 7, 21, 2, 2, 206, 208, 3, 2, 2, 2, 207, 202, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 43, 3, 2, 2, 2, 209, 210, 7, 18, 2, 2, 210, 211, 7, 22, 2, 2, 211, 212, 5, 54, 28, 2, 212, 213, 7, 23, 2, 2, 213, 214, 7, 20, 2, 2, 214, 215, 5, 36, 19, 2, 215, 216, 7, 21, 2, 2, 216, 45, 3, 2, 2, 2, 217, 218, 7, 15, 2, 2, 218, 219, 5, 48, 25, 2, 219, 220, 7, 28, 2, 2, 220, 47, 3, 2, 2, 2, 221, 222, 7, 46, 2, 2, 222, 223, 7, 22, 2, 2, 223, 224, 5, 52, 27, 2, 224, 225, 7, 23, 2, 2, 225, 234, 3, 2, 2, 2, 226, 227, 9, 3, 2, 2, 227, 228, 7, 26, 2, 2, 228, 229, 7, 46, 2, 2, 229, 230, 7, 22, 2, 2, 230, 231, 5, 52, 27, 2, 231, 232, 7, 23, 2, 2, 232, 234, 3, 2, 2, 2, 233, 221, 3, 2, 2, 2, 233, 226, 3, 2, 2, 2, 234, 49, 3, 2, 2, 2, 235, 237, 7, 19, 2, 2, 236, 238, 5, 54, 28, 2, 237, 236, 3, 2, 2, 2, 237, 238, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 240, 7, 28, 2, 2, 240, 51, 3, 2, 2, 2, 241, 246, 5, 54, 28, 2, 242, 243, 7, 27, 2, 2, 243, 245, 5, 54, 28, 2, 244, 242, 3, 2, 2, 2, 245, 248, 3, 2, 2, 2, 246, 244, 3, 2, 2, 2, 246, 247, 3, 2, 2, 2, 247, 250, 3, 2, 2, 2, 248, 246, 3, 2, 2, 2, 249, 241, 3, 2, 2, 2, 249, 250, 3, 2, 2, 2, 250, 53, 3, 2, 2, 2, 251, 252, 8, 28, 1, 2, 252, 259, 5, 62, 32, 2, 253, 259, 7, 46, 2, 2, 254, 259, 5, 48, 25, 2, 255, 259, 5, 60, 31, 2, 256, 259, 5, 58, 30, 2, 257, 259, 5, 56, 29, 2, 258, 251, 3, 2, 2, 2, 258, 253, 3, 2, 2, 2, 258, 254, 3, 2, 2, 2, 258, 255, 3, 2, 2, 2, 258, 256, 3, 2, 2, 2, 258, 257, 3, 2, 2, 2, 259, 266, 3, 2, 2, 2, 260, 261, 12, 9, 2, 2, 261, 262, 5, 66, 34, 2, 262, 263, 5, 54, 28, 10, 263, 265, 3, 2, 2, 2, 264, 260, 3, 2, 2, 2, 265, 268, 3, 2, 2, 2, 266, 264, 3, 2, 2, 2, 266, 267, 3, 2, 2, 2, 267, 55, 3, 2, 2, 2, 268, 266, 3, 2, 2, 2, 269, 270, 7, 22, 2, 2, 270, 271, 5, 54, 28, 2, 271, 272, 7, 23, 2, 2, 272, 57, 3, 2, 2, 2, 273, 274, 5, 64, 33, 2, 274, 275, 5, 54, 28, 2, 275, 59, 3, 2, 2, 2, 276, 277, 7, 46, 2, 2, 277, 278, 7, 24, 2, 2, 278, 279, 5, 54, 28, 2, 279, 280, 7, 25, 2, 2, 280, 61, 3, 2, 2, 2, 281, 282, 9, 4, 2, 2, 282, 63, 3, 2, 2, 2, 283, 284, 9, 5, 2, 2, 284, 65, 3, 2, 2, 2, 285, 286, 9, 6, 2, 2, 286, 67, 3, 2, 2, 2, 22, 77, 83, 98, 106, 117, 130, 139, 142, 153, 166, 176, 184, 189, 207, 233, 237, 246, 249, 258, 266] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 295, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 78, 10, 3, 12, 3, 14, 3, 81, 11, 3, 3, 3, 7, 3, 84, 10, 3, 12, 3, 14, 3, 87, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 101, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 107, 10, 6, 12, 6, 14, 6, 110, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 120, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 133, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 140, 10, 13, 12, 13, 14, 13, 143, 11, 13, 5, 13, 145, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 154, 10, 16, 12, 16, 14, 16, 157, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 167, 10, 17, 12, 17, 14, 17, 170, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 7, 20, 179, 10, 20, 12, 20, 14, 20, 182, 11, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 189, 10, 21, 3, 22, 3, 22, 3, 22, 5, 22, 194, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 212, 10, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 233, 10, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 241, 10, 26, 3, 27, 3, 27, 5, 27, 245, 10, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 7, 28, 252, 10, 28, 12, 28, 14, 28, 255, 11, 28, 5, 28, 257, 10, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 5, 29, 266, 10, 29, 3, 29, 3, 29, 3, 29, 3, 29, 7, 29, 272, 10, 29, 12, 29, 14, 29, 275, 11, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 2, 2, 3, 56, 36, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 2, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 289, 2, 70, 3, 2, 2, 2, 4, 73, 3, 2, 2, 2, 6, 90, 3, 2, 2, 2, 8, 100, 3, 2, 2, 2, 10, 102, 3, 2, 2, 2, 12, 111, 3, 2, 2, 2, 14, 119, 3, 2, 2, 2, 16, 121, 3, 2, 2, 2, 18, 128, 3, 2, 2, 2, 20, 132, 3, 2, 2, 2, 22, 134, 3, 2, 2, 2, 24, 144, 3, 2, 2, 2, 26, 146, 3, 2, 2, 2, 28, 149, 3, 2, 2, 2, 30, 151, 3, 2, 2, 2, 32, 161, 3, 2, 2, 2, 34, 173, 3, 2, 2, 2, 36, 175, 3, 2, 2, 2, 38, 180, 3, 2, 2, 2, 40, 188, 3, 2, 2, 2, 42, 190, 3, 2, 2, 2, 44, 199, 3, 2, 2, 2, 46, 213, 3, 2, 2, 2, 48, 221, 3, 2, 2, 2, 50, 240, 3, 2, 2, 2, 52, 242, 3, 2, 2, 2, 54, 256, 3, 2, 2, 2, 56, 265, 3, 2, 2, 2, 58, 276, 3, 2, 2, 2, 60, 280, 3, 2, 2, 2, 62, 283, 3, 2, 2, 2, 64, 288, 3, 2, 2, 2, 66, 290, 3, 2, 2, 2, 68, 292, 3, 2, 2, 2, 70, 71, 5, 4, 3, 2, 71, 72, 7, 2, 2, 3, 72, 3, 3, 2, 2, 2, 73, 74, 7, 3, 2, 2, 74, 75, 5, 6, 4, 2, 75, 79, 7, 20, 2, 2, 76, 78, 5, 8, 5, 2, 77, 76, 3, 2, 2, 2, 78, 81, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 79, 80, 3, 2, 2, 2, 80, 85, 3, 2, 2, 2, 81, 79, 3, 2, 2, 2, 82, 84, 5, 14, 8, 2, 83, 82, 3, 2, 2, 2, 84, 87, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 88, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 88, 89, 7, 21, 2, 2, 89, 5, 3, 2, 2, 2, 90, 91, 7, 46, 2, 2, 91, 7, 3, 2, 2, 2, 92, 93, 7, 8, 2, 2, 93, 94, 5, 10, 6, 2, 94, 95, 7, 28, 2, 2, 95, 101, 3, 2, 2, 2, 96, 97, 7, 7, 2, 2, 97, 98, 5, 10, 6, 2, 98, 99, 7, 28, 2, 2, 99, 101, 3, 2, 2, 2, 100, 92, 3, 2, 2, 2, 100, 96, 3, 2, 2, 2, 101, 9, 3, 2, 2, 2, 102, 103, 5, 22, 12, 2, 103, 108, 5, 12, 7, 2, 104, 105, 7, 27, 2, 2, 105, 107, 5, 12, 7, 2, 106, 104, 3, 2, 2, 2, 107, 110, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 108, 109, 3, 2, 2, 2, 109, 11, 3, 2, 2, 2, 110, 108, 3, 2, 2, 2, 111, 112, 7, 46, 2, 2, 112, 13, 3, 2, 2, 2, 113, 114, 7, 4, 2, 2, 114, 120, 5, 16, 9, 2, 115, 116, 7, 6, 2, 2, 116, 120, 5, 16, 9, 2, 117, 118, 7, 5, 2, 2, 118, 120, 5, 16, 9, 2, 119, 113, 3, 2, 2, 2, 119, 115, 3, 2, 2, 2, 119, 117, 3, 2, 2, 2, 120, 15, 3, 2, 2, 2, 121, 122, 5, 20, 11, 2, 122, 123, 5, 18, 10, 2, 123, 124, 7, 22, 2, 2, 124, 125, 5, 24, 13, 2, 125, 126, 7, 23, 2, 2, 126, 127, 5, 30, 16, 2, 127, 17, 3, 2, 2, 2, 128, 129, 7, 46, 2, 2, 129, 19, 3, 2, 2, 2, 130, 133, 5, 22, 12, 2, 131, 133, 7, 13, 2, 2, 132, 130, 3, 2, 2, 2, 132, 131, 3, 2, 2, 2, 133, 21, 3, 2, 2, 2, 134, 135, 9, 2, 2, 2, 135, 23, 3, 2, 2, 2, 136, 141, 5, 26, 14, 2, 137, 138, 7, 27, 2, 2, 138, 140, 5, 26, 14, 2, 139, 137, 3, 2, 2, 2, 140, 143, 3, 2, 2, 2, 141, 139, 3, 2, 2, 2, 141, 142, 3, 2, 2, 2, 142, 145, 3, 2, 2, 2, 143, 141, 3, 2, 2, 2, 144, 136, 3, 2, 2, 2, 144, 145, 3, 2, 2, 2, 145, 25, 3, 2, 2, 2, 146, 147, 5, 22, 12, 2, 147, 148, 5, 28, 15, 2, 148, 27, 3, 2, 2, 2, 149, 150, 7, 46, 2, 2, 150, 29, 3, 2, 2, 2, 151, 155, 7, 20, 2, 2, 152, 154, 5, 32, 17, 2, 153, 152, 3, 2, 2, 2, 154, 157, 3, 2, 2, 2, 155, 153, 3, 2, 2, 2, 155, 156, 3, 2, 2, 2, 156, 158, 3, 2, 2, 2, 157, 155, 3, 2, 2, 2, 158, 159, 5, 38, 20, 2, 159, 160, 7, 21, 2, 2, 160, 31, 3, 2, 2, 2, 161, 162, 7, 9, 2, 2, 162, 163, 5, 22, 12, 2, 163, 168, 5, 34, 18, 2, 164, 165, 7, 27, 2, 2, 165, 167, 5, 34, 18, 2, 166, 164, 3, 2, 2, 2, 167, 170, 3, 2, 2, 2, 168, 166, 3, 2, 2, 2, 168, 169, 3, 2, 2, 2, 169, 171, 3, 2, 2, 2, 170, 168, 3, 2, 2, 2, 171, 172, 7, 28, 2, 2, 172, 33, 3, 2, 2, 2, 173, 174, 7, 46, 2, 2, 174, 35, 3, 2, 2, 2, 175, 176, 7, 46, 2, 2, 176, 37, 3, 2, 2, 2, 177, 179, 5, 40, 21, 2, 178, 177, 3, 2, 2, 2, 179, 182, 3, 2, 2, 2, 180, 178, 3, 2, 2, 2, 180, 181, 3, 2, 2, 2, 181, 39, 3, 2, 2, 2, 182, 180, 3, 2, 2, 2, 183, 189, 5, 42, 22, 2, 184, 189, 5, 44, 23, 2, 185, 189, 5, 46, 24, 2, 186, 189, 5, 48, 25, 2, 187, 189, 5, 52, 27, 2, 188, 183, 3, 2, 2, 2, 188, 184, 3, 2, 2, 2, 188, 185, 3, 2, 2, 2, 188, 186, 3, 2, 2, 2, 188, 187, 3, 2, 2, 2, 189, 41, 3, 2, 2, 2, 190, 193, 7, 14, 2, 2, 191, 194, 5, 36, 19, 2, 192, 194, 5, 62, 32, 2, 193, 191, 3, 2, 2, 2, 193, 192, 3, 2, 2, 2, 194, 195, 3, 2, 2, 2, 195, 196, 7, 29, 2, 2, 196, 197, 5, 56, 29, 2, 197, 198, 7, 28, 2, 2, 198, 43, 3, 2, 2, 2, 199, 200, 7, 16, 2, 2, 200, 201, 7, 22, 2, 2, 201, 202, 5, 56, 29, 2, 202, 203, 7, 23, 2, 2, 203, 204, 7, 20, 2, 2, 204, 205, 5, 38, 20, 2, 205, 211, 7, 21, 2, 2, 206, 207, 7, 17, 2, 2, 207, 208, 7, 20, 2, 2, 208, 209, 5, 38, 20, 2, 209, 210, 7, 21, 2, 2, 210, 212, 3, 2, 2, 2, 211, 206, 3, 2, 2, 2, 211, 212, 3, 2, 2, 2, 212, 45, 3, 2, 2, 2, 213, 214, 7, 18, 2, 2, 214, 215, 7, 22, 2, 2, 215, 216, 5, 56, 29, 2, 216, 217, 7, 23, 2, 2, 217, 218, 7, 20, 2, 2, 218, 219, 5, 38, 20, 2, 219, 220, 7, 21, 2, 2, 220, 47, 3, 2, 2, 2, 221, 222, 7, 15, 2, 2, 222, 223, 5, 50, 26, 2, 223, 224, 7, 28, 2, 2, 224, 49, 3, 2, 2, 2, 225, 226, 5, 18, 10, 2, 226, 227, 7, 22, 2, 2, 227, 228, 5, 54, 28, 2, 228, 229, 7, 23, 2, 2, 229, 241, 3, 2, 2, 2, 230, 233, 5, 6, 4, 2, 231, 233, 7, 45, 2, 2, 232, 230, 3, 2, 2, 2, 232, 231, 3, 2, 2, 2, 233, 234, 3, 2, 2, 2, 234, 235, 7, 26, 2, 2, 235, 236, 5, 18, 10, 2, 236, 237, 7, 22, 2, 2, 237, 238, 5, 54, 28, 2, 238, 239, 7, 23, 2, 2, 239, 241, 3, 2, 2, 2, 240, 225, 3, 2, 2, 2, 240, 232, 3, 2, 2, 2, 241, 51, 3, 2, 2, 2, 242, 244, 7, 19, 2, 2, 243, 245, 5, 56, 29, 2, 244, 243, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 246, 3, 2, 2, 2, 246, 247, 7, 28, 2, 2, 247, 53, 3, 2, 2, 2, 248, 253, 5, 56, 29, 2, 249, 250, 7, 27, 2, 2, 250, 252, 5, 56, 29, 2, 251, 249, 3, 2, 2, 2, 252, 255, 3, 2, 2, 2, 253, 251, 3, 2, 2, 2, 253, 254, 3, 2, 2, 2, 254, 257, 3, 2, 2, 2, 255, 253, 3, 2, 2, 2, 256, 248, 3, 2, 2, 2, 256, 257, 3, 2, 2, 2, 257, 55, 3, 2, 2, 2, 258, 259, 8, 29, 1, 2, 259, 266, 5, 64, 33, 2, 260, 266, 5, 36, 19, 2, 261, 266, 5, 50, 26, 2, 262, 266, 5, 62, 32, 2, 263, 266, 5, 60, 31, 2, 264, 266, 5, 58, 30, 2, 265, 258, 3, 2, 2, 2, 265, 260, 3, 2, 2, 2, 265, 261, 3, 2, 2, 2, 265, 262, 3, 2, 2, 2, 265, 263, 3, 2, 2, 2, 265, 264, 3, 2, 2, 2, 266, 273, 3, 2, 2, 2, 267, 268, 12, 9, 2, 2, 268, 269, 5, 68, 35, 2, 269, 270, 5, 56, 29, 10, 270, 272, 3, 2, 2, 2, 271, 267, 3, 2, 2, 2, 272, 275, 3, 2, 2, 2, 273, 271, 3, 2, 2, 2, 273, 274, 3, 2, 2, 2, 274, 57, 3, 2, 2, 2, 275, 273, 3, 2, 2, 2, 276, 277, 7, 22, 2, 2, 277, 278, 5, 56, 29, 2, 278, 279, 7, 23, 2, 2, 279, 59, 3, 2, 2, 2, 280, 281, 5, 66, 34, 2, 281, 282, 5, 56, 29, 2, 282, 61, 3, 2, 2, 2, 283, 284, 5, 36, 19, 2, 284, 285, 7, 24, 2, 2, 285, 286, 5, 56, 29, 2, 286, 287, 7, 25, 2, 2, 287, 63, 3, 2, 2, 2, 288, 289, 9, 3, 2, 2, 289, 65, 3, 2, 2, 2, 290, 291, 9, 4, 2, 2, 291, 67, 3, 2, 2, 2, 292, 293, 9, 5, 2, 2, 293, 69, 3, 2, 2, 2, 23, 79, 85, 100, 108, 119, 132, 141, 144, 155, 168, 180, 188, 193, 211, 232, 240, 244, 253, 256, 265, 273] \ No newline at end of file diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts index 487618d5..3c2fe50c 100644 --- a/compiler/src/generated/JackParser.ts +++ b/compiler/src/generated/JackParser.ts @@ -90,32 +90,34 @@ export class JackParser extends Parser { public static readonly RULE_parameterName = 13; public static readonly RULE_subroutineBody = 14; public static readonly RULE_varDeclaration = 15; - public static readonly RULE_varName = 16; - public static readonly RULE_statements = 17; - public static readonly RULE_statement = 18; - public static readonly RULE_letStatement = 19; - public static readonly RULE_ifStatement = 20; - public static readonly RULE_whileStatement = 21; - public static readonly RULE_doStatement = 22; - public static readonly RULE_subroutineCall = 23; - public static readonly RULE_returnStatement = 24; - public static readonly RULE_expressionList = 25; - public static readonly RULE_expression = 26; - public static readonly RULE_groupedExpression = 27; - public static readonly RULE_unaryOp = 28; - public static readonly RULE_arrayAccess = 29; - public static readonly RULE_constant = 30; - public static readonly RULE_unaryOperator = 31; - public static readonly RULE_binaryOperator = 32; + public static readonly RULE_varNameInDeclaration = 16; + public static readonly RULE_varName = 17; + public static readonly RULE_statements = 18; + public static readonly RULE_statement = 19; + public static readonly RULE_letStatement = 20; + public static readonly RULE_ifStatement = 21; + public static readonly RULE_whileStatement = 22; + public static readonly RULE_doStatement = 23; + public static readonly RULE_subroutineCall = 24; + public static readonly RULE_returnStatement = 25; + public static readonly RULE_expressionList = 26; + public static readonly RULE_expression = 27; + public static readonly RULE_groupedExpression = 28; + public static readonly RULE_unaryOp = 29; + public static readonly RULE_arrayAccess = 30; + public static readonly RULE_constant = 31; + public static readonly RULE_unaryOperator = 32; + public static readonly RULE_binaryOperator = 33; // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ "program", "classDeclaration", "className", "classVarDec", "fieldList", "fieldName", "subroutineDeclaration", "subroutineDecWithoutType", "subroutineName", "subroutineReturnType", "varType", "parameterList", "parameter", "parameterName", - "subroutineBody", "varDeclaration", "varName", "statements", "statement", - "letStatement", "ifStatement", "whileStatement", "doStatement", "subroutineCall", - "returnStatement", "expressionList", "expression", "groupedExpression", - "unaryOp", "arrayAccess", "constant", "unaryOperator", "binaryOperator", + "subroutineBody", "varDeclaration", "varNameInDeclaration", "varName", + "statements", "statement", "letStatement", "ifStatement", "whileStatement", + "doStatement", "subroutineCall", "returnStatement", "expressionList", + "expression", "groupedExpression", "unaryOp", "arrayAccess", "constant", + "unaryOperator", "binaryOperator", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -168,9 +170,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 66; + this.state = 68; this.classDeclaration(); - this.state = 67; + this.state = 69; this.match(JackParser.EOF); } } @@ -196,41 +198,41 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 69; + this.state = 71; this.match(JackParser.CLASS); - this.state = 70; + this.state = 72; this.className(); - this.state = 71; + this.state = 73; this.match(JackParser.LBRACE); - this.state = 75; + this.state = 77; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.FIELD || _la === JackParser.STATIC) { { { - this.state = 72; + this.state = 74; this.classVarDec(); } } - this.state = 77; + this.state = 79; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 81; + this.state = 83; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0)) { { { - this.state = 78; + this.state = 80; this.subroutineDeclaration(); } } - this.state = 83; + this.state = 85; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 84; + this.state = 86; this.match(JackParser.RBRACE); } } @@ -255,7 +257,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 86; + this.state = 88; this.match(JackParser.IDENTIFIER); } } @@ -278,18 +280,18 @@ export class JackParser extends Parser { let _localctx: ClassVarDecContext = new ClassVarDecContext(this._ctx, this.state); this.enterRule(_localctx, 6, JackParser.RULE_classVarDec); try { - this.state = 96; + this.state = 98; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.STATIC: _localctx = new StaticFieldDeclarationContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 88; + this.state = 90; this.match(JackParser.STATIC); - this.state = 89; + this.state = 91; this.fieldList(); - this.state = 90; + this.state = 92; this.match(JackParser.SEMICOLON); } break; @@ -297,11 +299,11 @@ export class JackParser extends Parser { _localctx = new FieldDeclarationContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 92; + this.state = 94; this.match(JackParser.FIELD); - this.state = 93; + this.state = 95; this.fieldList(); - this.state = 94; + this.state = 96; this.match(JackParser.SEMICOLON); } break; @@ -331,23 +333,23 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 98; + this.state = 100; this.varType(); - this.state = 99; + this.state = 101; this.fieldName(); - this.state = 104; + this.state = 106; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 100; + this.state = 102; this.match(JackParser.COMMA); - this.state = 101; + this.state = 103; this.fieldName(); } } - this.state = 106; + this.state = 108; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -374,7 +376,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 107; + this.state = 109; this.match(JackParser.IDENTIFIER); } } @@ -397,16 +399,16 @@ export class JackParser extends Parser { let _localctx: SubroutineDeclarationContext = new SubroutineDeclarationContext(this._ctx, this.state); this.enterRule(_localctx, 12, JackParser.RULE_subroutineDeclaration); try { - this.state = 115; + this.state = 117; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.CONSTRUCTOR: _localctx = new ConstructorContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 109; + this.state = 111; this.match(JackParser.CONSTRUCTOR); - this.state = 110; + this.state = 112; this.subroutineDecWithoutType(); } break; @@ -414,9 +416,9 @@ export class JackParser extends Parser { _localctx = new MethodContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 111; + this.state = 113; this.match(JackParser.METHOD); - this.state = 112; + this.state = 114; this.subroutineDecWithoutType(); } break; @@ -424,9 +426,9 @@ export class JackParser extends Parser { _localctx = new FunctionContext(_localctx); this.enterOuterAlt(_localctx, 3); { - this.state = 113; + this.state = 115; this.match(JackParser.FUNCTION); - this.state = 114; + this.state = 116; this.subroutineDecWithoutType(); } break; @@ -455,17 +457,17 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 117; + this.state = 119; this.subroutineReturnType(); - this.state = 118; + this.state = 120; this.subroutineName(); - this.state = 119; + this.state = 121; this.match(JackParser.LPAREN); - this.state = 120; + this.state = 122; this.parameterList(); - this.state = 121; + this.state = 123; this.match(JackParser.RPAREN); - this.state = 122; + this.state = 124; this.subroutineBody(); } } @@ -490,7 +492,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 124; + this.state = 126; this.match(JackParser.IDENTIFIER); } } @@ -513,7 +515,7 @@ export class JackParser extends Parser { let _localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this._ctx, this.state); this.enterRule(_localctx, 18, JackParser.RULE_subroutineReturnType); try { - this.state = 128; + this.state = 130; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.INT: @@ -522,14 +524,14 @@ export class JackParser extends Parser { case JackParser.IDENTIFIER: this.enterOuterAlt(_localctx, 1); { - this.state = 126; + this.state = 128; this.varType(); } break; case JackParser.VOID: this.enterOuterAlt(_localctx, 2); { - this.state = 127; + this.state = 129; this.match(JackParser.VOID); } break; @@ -559,7 +561,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 130; + this.state = 132; _la = this._input.LA(1); if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER)) { this._errHandler.recoverInline(this); @@ -595,26 +597,26 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 140; + this.state = 142; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER) { { - this.state = 132; + this.state = 134; this.parameter(); - this.state = 137; + this.state = 139; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 133; + this.state = 135; this.match(JackParser.COMMA); - this.state = 134; + this.state = 136; this.parameter(); } } - this.state = 139; + this.state = 141; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -644,9 +646,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 142; + this.state = 144; this.varType(); - this.state = 143; + this.state = 145; this.parameterName(); } } @@ -671,7 +673,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 145; + this.state = 147; this.match(JackParser.IDENTIFIER); } } @@ -697,25 +699,25 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 147; + this.state = 149; this.match(JackParser.LBRACE); - this.state = 151; + this.state = 153; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.VAR) { { { - this.state = 148; + this.state = 150; this.varDeclaration(); } } - this.state = 153; + this.state = 155; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 154; + this.state = 156; this.statements(); - this.state = 155; + this.state = 157; this.match(JackParser.RBRACE); } } @@ -741,29 +743,29 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 157; + this.state = 159; this.match(JackParser.VAR); - this.state = 158; + this.state = 160; this.varType(); - this.state = 159; - this.varName(); - this.state = 164; + this.state = 161; + this.varNameInDeclaration(); + this.state = 166; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 160; + this.state = 162; this.match(JackParser.COMMA); - this.state = 161; - this.varName(); + this.state = 163; + this.varNameInDeclaration(); } } - this.state = 166; + this.state = 168; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 167; + this.state = 169; this.match(JackParser.SEMICOLON); } } @@ -782,13 +784,38 @@ export class JackParser extends Parser { return _localctx; } // @RuleVersion(0) + public varNameInDeclaration(): VarNameInDeclarationContext { + let _localctx: VarNameInDeclarationContext = new VarNameInDeclarationContext(this._ctx, this.state); + this.enterRule(_localctx, 32, JackParser.RULE_varNameInDeclaration); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 171; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) public varName(): VarNameContext { let _localctx: VarNameContext = new VarNameContext(this._ctx, this.state); - this.enterRule(_localctx, 32, JackParser.RULE_varName); + this.enterRule(_localctx, 34, JackParser.RULE_varName); try { this.enterOuterAlt(_localctx, 1); { - this.state = 169; + this.state = 173; this.match(JackParser.IDENTIFIER); } } @@ -809,22 +836,22 @@ export class JackParser extends Parser { // @RuleVersion(0) public statements(): StatementsContext { let _localctx: StatementsContext = new StatementsContext(this._ctx, this.state); - this.enterRule(_localctx, 34, JackParser.RULE_statements); + this.enterRule(_localctx, 36, JackParser.RULE_statements); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 174; + this.state = 178; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.LET) | (1 << JackParser.DO) | (1 << JackParser.IF) | (1 << JackParser.WHILE) | (1 << JackParser.RETURN))) !== 0)) { { { - this.state = 171; + this.state = 175; this.statement(); } } - this.state = 176; + this.state = 180; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -847,43 +874,43 @@ export class JackParser extends Parser { // @RuleVersion(0) public statement(): StatementContext { let _localctx: StatementContext = new StatementContext(this._ctx, this.state); - this.enterRule(_localctx, 36, JackParser.RULE_statement); + this.enterRule(_localctx, 38, JackParser.RULE_statement); try { - this.state = 182; + this.state = 186; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.LET: this.enterOuterAlt(_localctx, 1); { - this.state = 177; + this.state = 181; this.letStatement(); } break; case JackParser.IF: this.enterOuterAlt(_localctx, 2); { - this.state = 178; + this.state = 182; this.ifStatement(); } break; case JackParser.WHILE: this.enterOuterAlt(_localctx, 3); { - this.state = 179; + this.state = 183; this.whileStatement(); } break; case JackParser.DO: this.enterOuterAlt(_localctx, 4); { - this.state = 180; + this.state = 184; this.doStatement(); } break; case JackParser.RETURN: this.enterOuterAlt(_localctx, 5); { - this.state = 181; + this.state = 185; this.returnStatement(); } break; @@ -908,34 +935,34 @@ export class JackParser extends Parser { // @RuleVersion(0) public letStatement(): LetStatementContext { let _localctx: LetStatementContext = new LetStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 38, JackParser.RULE_letStatement); + this.enterRule(_localctx, 40, JackParser.RULE_letStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 184; + this.state = 188; this.match(JackParser.LET); - this.state = 187; + this.state = 191; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 12, this._ctx) ) { case 1: { - this.state = 185; - this.match(JackParser.IDENTIFIER); + this.state = 189; + this.varName(); } break; case 2: { - this.state = 186; + this.state = 190; this.arrayAccess(); } break; } - this.state = 189; + this.state = 193; this.match(JackParser.EQUALS); - this.state = 190; + this.state = 194; this.expression(0); - this.state = 191; + this.state = 195; this.match(JackParser.SEMICOLON); } } @@ -956,37 +983,37 @@ export class JackParser extends Parser { // @RuleVersion(0) public ifStatement(): IfStatementContext { let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 40, JackParser.RULE_ifStatement); + this.enterRule(_localctx, 42, JackParser.RULE_ifStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 193; + this.state = 197; this.match(JackParser.IF); - this.state = 194; + this.state = 198; this.match(JackParser.LPAREN); - this.state = 195; + this.state = 199; this.expression(0); - this.state = 196; + this.state = 200; this.match(JackParser.RPAREN); - this.state = 197; + this.state = 201; this.match(JackParser.LBRACE); - this.state = 198; + this.state = 202; this.statements(); - this.state = 199; + this.state = 203; this.match(JackParser.RBRACE); - this.state = 205; + this.state = 209; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === JackParser.ELSE) { { - this.state = 200; + this.state = 204; this.match(JackParser.ELSE); - this.state = 201; + this.state = 205; this.match(JackParser.LBRACE); - this.state = 202; + this.state = 206; this.statements(); - this.state = 203; + this.state = 207; this.match(JackParser.RBRACE); } } @@ -1010,23 +1037,23 @@ export class JackParser extends Parser { // @RuleVersion(0) public whileStatement(): WhileStatementContext { let _localctx: WhileStatementContext = new WhileStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 42, JackParser.RULE_whileStatement); + this.enterRule(_localctx, 44, JackParser.RULE_whileStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 207; + this.state = 211; this.match(JackParser.WHILE); - this.state = 208; + this.state = 212; this.match(JackParser.LPAREN); - this.state = 209; + this.state = 213; this.expression(0); - this.state = 210; + this.state = 214; this.match(JackParser.RPAREN); - this.state = 211; + this.state = 215; this.match(JackParser.LBRACE); - this.state = 212; + this.state = 216; this.statements(); - this.state = 213; + this.state = 217; this.match(JackParser.RBRACE); } } @@ -1047,15 +1074,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public doStatement(): DoStatementContext { let _localctx: DoStatementContext = new DoStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 44, JackParser.RULE_doStatement); + this.enterRule(_localctx, 46, JackParser.RULE_doStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 215; + this.state = 219; this.match(JackParser.DO); - this.state = 216; + this.state = 220; this.subroutineCall(); - this.state = 217; + this.state = 221; this.match(JackParser.SEMICOLON); } } @@ -1076,22 +1103,21 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineCall(): SubroutineCallContext { let _localctx: SubroutineCallContext = new SubroutineCallContext(this._ctx, this.state); - this.enterRule(_localctx, 46, JackParser.RULE_subroutineCall); - let _la: number; + this.enterRule(_localctx, 48, JackParser.RULE_subroutineCall); try { - this.state = 231; + this.state = 238; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 14, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 15, this._ctx) ) { case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 219; - this.match(JackParser.IDENTIFIER); - this.state = 220; + this.state = 223; + this.subroutineName(); + this.state = 224; this.match(JackParser.LPAREN); - this.state = 221; + this.state = 225; this.expressionList(); - this.state = 222; + this.state = 226; this.match(JackParser.RPAREN); } break; @@ -1099,27 +1125,33 @@ export class JackParser extends Parser { case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 224; - _la = this._input.LA(1); - if (!(_la === JackParser.THIS_LITERAL || _la === JackParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; + this.state = 230; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case JackParser.IDENTIFIER: + { + this.state = 228; + this.className(); } - - this._errHandler.reportMatch(this); - this.consume(); + break; + case JackParser.THIS_LITERAL: + { + this.state = 229; + this.match(JackParser.THIS_LITERAL); + } + break; + default: + throw new NoViableAltException(this); } - this.state = 225; + this.state = 232; this.match(JackParser.DOT); - this.state = 226; - this.match(JackParser.IDENTIFIER); - this.state = 227; + this.state = 233; + this.subroutineName(); + this.state = 234; this.match(JackParser.LPAREN); - this.state = 228; + this.state = 235; this.expressionList(); - this.state = 229; + this.state = 236; this.match(JackParser.RPAREN); } break; @@ -1142,24 +1174,24 @@ export class JackParser extends Parser { // @RuleVersion(0) public returnStatement(): ReturnStatementContext { let _localctx: ReturnStatementContext = new ReturnStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 48, JackParser.RULE_returnStatement); + this.enterRule(_localctx, 50, JackParser.RULE_returnStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 233; + this.state = 240; this.match(JackParser.RETURN); - this.state = 235; + this.state = 242; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 234; + this.state = 241; this.expression(0); } } - this.state = 237; + this.state = 244; this.match(JackParser.SEMICOLON); } } @@ -1180,31 +1212,31 @@ export class JackParser extends Parser { // @RuleVersion(0) public expressionList(): ExpressionListContext { let _localctx: ExpressionListContext = new ExpressionListContext(this._ctx, this.state); - this.enterRule(_localctx, 50, JackParser.RULE_expressionList); + this.enterRule(_localctx, 52, JackParser.RULE_expressionList); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 247; + this.state = 254; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 239; + this.state = 246; this.expression(0); - this.state = 244; + this.state = 251; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 240; + this.state = 247; this.match(JackParser.COMMA); - this.state = 241; + this.state = 248; this.expression(0); } } - this.state = 246; + this.state = 253; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1240,61 +1272,61 @@ export class JackParser extends Parser { let _parentState: number = this.state; let _localctx: ExpressionContext = new ExpressionContext(this._ctx, _parentState); let _prevctx: ExpressionContext = _localctx; - let _startState: number = 52; - this.enterRecursionRule(_localctx, 52, JackParser.RULE_expression, _p); + let _startState: number = 54; + this.enterRecursionRule(_localctx, 54, JackParser.RULE_expression, _p); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 256; + this.state = 263; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 18, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 19, this._ctx) ) { case 1: { - this.state = 250; + this.state = 257; this.constant(); } break; case 2: { - this.state = 251; - this.match(JackParser.IDENTIFIER); + this.state = 258; + this.varName(); } break; case 3: { - this.state = 252; + this.state = 259; this.subroutineCall(); } break; case 4: { - this.state = 253; + this.state = 260; this.arrayAccess(); } break; case 5: { - this.state = 254; + this.state = 261; this.unaryOp(); } break; case 6: { - this.state = 255; + this.state = 262; this.groupedExpression(); } break; } this._ctx._stop = this._input.tryLT(-1); - this.state = 264; + this.state = 271; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -1306,20 +1338,20 @@ export class JackParser extends Parser { _localctx = new ExpressionContext(_parentctx, _parentState); _localctx._binaryOperation = _prevctx; this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); - this.state = 258; + this.state = 265; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 259; + this.state = 266; this.binaryOperator(); - this.state = 260; + this.state = 267; this.expression(8); } } } - this.state = 266; + this.state = 273; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 19, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); } } } @@ -1340,15 +1372,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public groupedExpression(): GroupedExpressionContext { let _localctx: GroupedExpressionContext = new GroupedExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 54, JackParser.RULE_groupedExpression); + this.enterRule(_localctx, 56, JackParser.RULE_groupedExpression); try { this.enterOuterAlt(_localctx, 1); { - this.state = 267; + this.state = 274; this.match(JackParser.LPAREN); - this.state = 268; + this.state = 275; this.expression(0); - this.state = 269; + this.state = 276; this.match(JackParser.RPAREN); } } @@ -1369,13 +1401,13 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOp(): UnaryOpContext { let _localctx: UnaryOpContext = new UnaryOpContext(this._ctx, this.state); - this.enterRule(_localctx, 56, JackParser.RULE_unaryOp); + this.enterRule(_localctx, 58, JackParser.RULE_unaryOp); try { this.enterOuterAlt(_localctx, 1); { - this.state = 271; + this.state = 278; this.unaryOperator(); - this.state = 272; + this.state = 279; this.expression(0); } } @@ -1396,17 +1428,17 @@ export class JackParser extends Parser { // @RuleVersion(0) public arrayAccess(): ArrayAccessContext { let _localctx: ArrayAccessContext = new ArrayAccessContext(this._ctx, this.state); - this.enterRule(_localctx, 58, JackParser.RULE_arrayAccess); + this.enterRule(_localctx, 60, JackParser.RULE_arrayAccess); try { this.enterOuterAlt(_localctx, 1); { - this.state = 274; - this.match(JackParser.IDENTIFIER); - this.state = 275; + this.state = 281; + this.varName(); + this.state = 282; this.match(JackParser.LBRACKET); - this.state = 276; + this.state = 283; this.expression(0); - this.state = 277; + this.state = 284; this.match(JackParser.RBRACKET); } } @@ -1427,12 +1459,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public constant(): ConstantContext { let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 60, JackParser.RULE_constant); + this.enterRule(_localctx, 62, JackParser.RULE_constant); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 279; + this.state = 286; _la = this._input.LA(1); if (!(((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & ((1 << (JackParser.INTEGER_LITERAL - 40)) | (1 << (JackParser.BOOLEAN_LITERAL - 40)) | (1 << (JackParser.NULL_LITERAL - 40)) | (1 << (JackParser.THIS_LITERAL - 40)) | (1 << (JackParser.STRING_LITERAL - 40)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1463,12 +1495,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOperator(): UnaryOperatorContext { let _localctx: UnaryOperatorContext = new UnaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 62, JackParser.RULE_unaryOperator); + this.enterRule(_localctx, 64, JackParser.RULE_unaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 281; + this.state = 288; _la = this._input.LA(1); if (!(_la === JackParser.MINUS || _la === JackParser.TILDE)) { this._errHandler.recoverInline(this); @@ -1499,12 +1531,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public binaryOperator(): BinaryOperatorContext { let _localctx: BinaryOperatorContext = new BinaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 64, JackParser.RULE_binaryOperator); + this.enterRule(_localctx, 66, JackParser.RULE_binaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 283; + this.state = 290; _la = this._input.LA(1); if (!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & ((1 << (JackParser.EQUALS - 27)) | (1 << (JackParser.PLUS - 27)) | (1 << (JackParser.MINUS - 27)) | (1 << (JackParser.MUL - 27)) | (1 << (JackParser.DIV - 27)) | (1 << (JackParser.AND - 27)) | (1 << (JackParser.OR - 27)) | (1 << (JackParser.LESS_THAN - 27)) | (1 << (JackParser.GREATER_THAN - 27)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1535,7 +1567,7 @@ export class JackParser extends Parser { public override sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 26: + case 27: return this.expression_sempred(_localctx as ExpressionContext, predIndex); } return true; @@ -1549,130 +1581,134 @@ export class JackParser extends Parser { } public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u0120\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u0127\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + - "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x03\x02" + - "\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x07\x03L\n\x03\f\x03" + - "\x0E\x03O\v\x03\x03\x03\x07\x03R\n\x03\f\x03\x0E\x03U\v\x03\x03\x03\x03" + - "\x03\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x05\x05c\n\x05\x03\x06\x03\x06\x03\x06\x03\x06\x07\x06i\n" + - "\x06\f\x06\x0E\x06l\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\b\x03" + - "\b\x03\b\x05\bv\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03\n\x03" + - "\n\x03\v\x03\v\x05\v\x83\n\v\x03\f\x03\f\x03\r\x03\r\x03\r\x07\r\x8A\n" + - "\r\f\r\x0E\r\x8D\v\r\x05\r\x8F\n\r\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03" + - "\x0F\x03\x10\x03\x10\x07\x10\x98\n\x10\f\x10\x0E\x10\x9B\v\x10\x03\x10" + - "\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x07\x11\xA5\n" + - "\x11\f\x11\x0E\x11\xA8\v\x11\x03\x11\x03\x11\x03\x12\x03\x12\x03\x13\x07" + - "\x13\xAF\n\x13\f\x13\x0E\x13\xB2\v\x13\x03\x14\x03\x14\x03\x14\x03\x14" + - "\x03\x14\x05\x14\xB9\n\x14\x03\x15\x03\x15\x03\x15\x05\x15\xBE\n\x15\x03" + - "\x15\x03\x15\x03\x15\x03\x15\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03" + - "\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x16\x05\x16\xD0\n\x16" + - "\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18" + - "\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19" + - "\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x05\x19\xEA\n\x19\x03" + - "\x1A\x03\x1A\x05\x1A\xEE\n\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03\x1B" + - "\x07\x1B\xF5\n\x1B\f\x1B\x0E\x1B\xF8\v\x1B\x05\x1B\xFA\n\x1B\x03\x1C\x03" + - "\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x05\x1C\u0103\n\x1C\x03\x1C" + - "\x03\x1C\x03\x1C\x03\x1C\x07\x1C\u0109\n\x1C\f\x1C\x0E\x1C\u010C\v\x1C" + - "\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F" + - "\x03\x1F\x03\x1F\x03\x1F\x03 \x03 \x03!\x03!\x03\"\x03\"\x03\"\x02\x02" + - "\x036#\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02" + - "\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02" + - "(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02" + - "\x02\x07\x04\x02\n\f..\x03\x02-.\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02" + - "\x1D#%&\x02\u011A\x02D\x03\x02\x02\x02\x04G\x03\x02\x02\x02\x06X\x03\x02" + - "\x02\x02\bb\x03\x02\x02\x02\nd\x03\x02\x02\x02\fm\x03\x02\x02\x02\x0E" + - "u\x03\x02\x02\x02\x10w\x03\x02\x02\x02\x12~\x03\x02\x02\x02\x14\x82\x03" + - "\x02\x02\x02\x16\x84\x03\x02\x02\x02\x18\x8E\x03\x02\x02\x02\x1A\x90\x03" + - "\x02\x02\x02\x1C\x93\x03\x02\x02\x02\x1E\x95\x03\x02\x02\x02 \x9F\x03" + - "\x02\x02\x02\"\xAB\x03\x02\x02\x02$\xB0\x03\x02\x02\x02&\xB8\x03\x02\x02" + - "\x02(\xBA\x03\x02\x02\x02*\xC3\x03\x02\x02\x02,\xD1\x03\x02\x02\x02.\xD9" + - "\x03\x02\x02\x020\xE9\x03\x02\x02\x022\xEB\x03\x02\x02\x024\xF9\x03\x02" + - "\x02\x026\u0102\x03\x02\x02\x028\u010D\x03\x02\x02\x02:\u0111\x03\x02" + - "\x02\x02<\u0114\x03\x02\x02\x02>\u0119\x03\x02\x02\x02@\u011B\x03\x02" + - "\x02\x02B\u011D\x03\x02\x02\x02DE\x05\x04\x03\x02EF\x07\x02\x02\x03F\x03" + - "\x03\x02\x02\x02GH\x07\x03\x02\x02HI\x05\x06\x04\x02IM\x07\x14\x02\x02" + - "JL\x05\b\x05\x02KJ\x03\x02\x02\x02LO\x03\x02\x02\x02MK\x03\x02\x02\x02" + - "MN\x03\x02\x02\x02NS\x03\x02\x02\x02OM\x03\x02\x02\x02PR\x05\x0E\b\x02" + - "QP\x03\x02\x02\x02RU\x03\x02\x02\x02SQ\x03\x02\x02\x02ST\x03\x02\x02\x02" + - "TV\x03\x02\x02\x02US\x03\x02\x02\x02VW\x07\x15\x02\x02W\x05\x03\x02\x02" + - "\x02XY\x07.\x02\x02Y\x07\x03\x02\x02\x02Z[\x07\b\x02\x02[\\\x05\n\x06" + - "\x02\\]\x07\x1C\x02\x02]c\x03\x02\x02\x02^_\x07\x07\x02\x02_`\x05\n\x06" + - "\x02`a\x07\x1C\x02\x02ac\x03\x02\x02\x02bZ\x03\x02\x02\x02b^\x03\x02\x02" + - "\x02c\t\x03\x02\x02\x02de\x05\x16\f\x02ej\x05\f\x07\x02fg\x07\x1B\x02" + - "\x02gi\x05\f\x07\x02hf\x03\x02\x02\x02il\x03\x02\x02\x02jh\x03\x02\x02" + - "\x02jk\x03\x02\x02\x02k\v\x03\x02\x02\x02lj\x03\x02\x02\x02mn\x07.\x02" + - "\x02n\r\x03\x02\x02\x02op\x07\x04\x02\x02pv\x05\x10\t\x02qr\x07\x06\x02" + - "\x02rv\x05\x10\t\x02st\x07\x05\x02\x02tv\x05\x10\t\x02uo\x03\x02\x02\x02" + - "uq\x03\x02\x02\x02us\x03\x02\x02\x02v\x0F\x03\x02\x02\x02wx\x05\x14\v" + - "\x02xy\x05\x12\n\x02yz\x07\x16\x02\x02z{\x05\x18\r\x02{|\x07\x17\x02\x02" + - "|}\x05\x1E\x10\x02}\x11\x03\x02\x02\x02~\x7F\x07.\x02\x02\x7F\x13\x03" + - "\x02\x02\x02\x80\x83\x05\x16\f\x02\x81\x83\x07\r\x02\x02\x82\x80\x03\x02" + - "\x02\x02\x82\x81\x03\x02\x02\x02\x83\x15\x03\x02\x02\x02\x84\x85\t\x02" + - "\x02\x02\x85\x17\x03\x02\x02\x02\x86\x8B\x05\x1A\x0E\x02\x87\x88\x07\x1B" + - "\x02\x02\x88\x8A\x05\x1A\x0E\x02\x89\x87\x03\x02\x02\x02\x8A\x8D\x03\x02" + - "\x02\x02\x8B\x89\x03\x02\x02\x02\x8B\x8C\x03\x02\x02\x02\x8C\x8F\x03\x02" + - "\x02\x02\x8D\x8B\x03\x02\x02\x02\x8E\x86\x03\x02\x02\x02\x8E\x8F\x03\x02" + - "\x02\x02\x8F\x19\x03\x02\x02\x02\x90\x91\x05\x16\f\x02\x91\x92\x05\x1C" + - "\x0F\x02\x92\x1B\x03\x02\x02\x02\x93\x94\x07.\x02\x02\x94\x1D\x03\x02" + - "\x02\x02\x95\x99\x07\x14\x02\x02\x96\x98\x05 \x11\x02\x97\x96\x03\x02" + - "\x02\x02\x98\x9B\x03\x02\x02\x02\x99\x97\x03\x02\x02\x02\x99\x9A\x03\x02" + - "\x02\x02\x9A\x9C\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9C\x9D\x05$" + - "\x13\x02\x9D\x9E\x07\x15\x02\x02\x9E\x1F\x03\x02\x02\x02\x9F\xA0\x07\t" + - "\x02\x02\xA0\xA1\x05\x16\f\x02\xA1\xA6\x05\"\x12\x02\xA2\xA3\x07\x1B\x02" + - "\x02\xA3\xA5\x05\"\x12\x02\xA4\xA2\x03\x02\x02\x02\xA5\xA8\x03\x02\x02" + - "\x02\xA6\xA4\x03\x02\x02\x02\xA6\xA7\x03\x02\x02\x02\xA7\xA9\x03\x02\x02" + - "\x02\xA8\xA6\x03\x02\x02\x02\xA9\xAA\x07\x1C\x02\x02\xAA!\x03\x02\x02" + - "\x02\xAB\xAC\x07.\x02\x02\xAC#\x03\x02\x02\x02\xAD\xAF\x05&\x14\x02\xAE" + - "\xAD\x03\x02\x02\x02\xAF\xB2\x03\x02\x02\x02\xB0\xAE\x03\x02\x02\x02\xB0" + - "\xB1\x03\x02\x02\x02\xB1%\x03\x02\x02\x02\xB2\xB0\x03\x02\x02\x02\xB3" + - "\xB9\x05(\x15\x02\xB4\xB9\x05*\x16\x02\xB5\xB9\x05,\x17\x02\xB6\xB9\x05" + - ".\x18\x02\xB7\xB9\x052\x1A\x02\xB8\xB3\x03\x02\x02\x02\xB8\xB4\x03\x02" + - "\x02\x02\xB8\xB5\x03\x02\x02\x02\xB8\xB6\x03\x02\x02\x02\xB8\xB7\x03\x02" + - "\x02\x02\xB9\'\x03\x02\x02\x02\xBA\xBD\x07\x0E\x02\x02\xBB\xBE\x07.\x02" + - "\x02\xBC\xBE\x05<\x1F\x02\xBD\xBB\x03\x02\x02\x02\xBD\xBC\x03\x02\x02" + - "\x02\xBE\xBF\x03\x02\x02\x02\xBF\xC0\x07\x1D\x02\x02\xC0\xC1\x056\x1C" + - "\x02\xC1\xC2\x07\x1C\x02\x02\xC2)\x03\x02\x02\x02\xC3\xC4\x07\x10\x02" + - "\x02\xC4\xC5\x07\x16\x02\x02\xC5\xC6\x056\x1C\x02\xC6\xC7\x07\x17\x02" + - "\x02\xC7\xC8\x07\x14\x02\x02\xC8\xC9\x05$\x13\x02\xC9\xCF\x07\x15\x02" + - "\x02\xCA\xCB\x07\x11\x02\x02\xCB\xCC\x07\x14\x02\x02\xCC\xCD\x05$\x13" + - "\x02\xCD\xCE\x07\x15\x02\x02\xCE\xD0\x03\x02\x02\x02\xCF\xCA\x03\x02\x02" + - "\x02\xCF\xD0\x03\x02\x02\x02\xD0+\x03\x02\x02\x02\xD1\xD2\x07\x12\x02" + - "\x02\xD2\xD3\x07\x16\x02\x02\xD3\xD4\x056\x1C\x02\xD4\xD5\x07\x17\x02" + - "\x02\xD5\xD6\x07\x14\x02\x02\xD6\xD7\x05$\x13\x02\xD7\xD8\x07\x15\x02" + - "\x02\xD8-\x03\x02\x02\x02\xD9\xDA\x07\x0F\x02\x02\xDA\xDB\x050\x19\x02" + - "\xDB\xDC\x07\x1C\x02\x02\xDC/\x03\x02\x02\x02\xDD\xDE\x07.\x02\x02\xDE" + - "\xDF\x07\x16\x02\x02\xDF\xE0\x054\x1B\x02\xE0\xE1\x07\x17\x02\x02\xE1" + - "\xEA\x03\x02\x02\x02\xE2\xE3\t\x03\x02\x02\xE3\xE4\x07\x1A\x02\x02\xE4" + - "\xE5\x07.\x02\x02\xE5\xE6\x07\x16\x02\x02\xE6\xE7\x054\x1B\x02\xE7\xE8" + - "\x07\x17\x02\x02\xE8\xEA\x03\x02\x02\x02\xE9\xDD\x03\x02\x02\x02\xE9\xE2" + - "\x03\x02\x02\x02\xEA1\x03\x02\x02\x02\xEB\xED\x07\x13\x02\x02\xEC\xEE" + - "\x056\x1C\x02\xED\xEC\x03\x02\x02\x02\xED\xEE\x03\x02\x02\x02\xEE\xEF" + - "\x03\x02\x02\x02\xEF\xF0\x07\x1C\x02\x02\xF03\x03\x02\x02\x02\xF1\xF6" + - "\x056\x1C\x02\xF2\xF3\x07\x1B\x02\x02\xF3\xF5\x056\x1C\x02\xF4\xF2\x03" + - "\x02\x02\x02\xF5\xF8\x03\x02\x02\x02\xF6\xF4\x03\x02\x02\x02\xF6\xF7\x03" + - "\x02\x02\x02\xF7\xFA\x03\x02\x02\x02\xF8\xF6\x03\x02\x02\x02\xF9\xF1\x03" + - "\x02\x02\x02\xF9\xFA\x03\x02\x02\x02\xFA5\x03\x02\x02\x02\xFB\xFC\b\x1C" + - "\x01\x02\xFC\u0103\x05> \x02\xFD\u0103\x07.\x02\x02\xFE\u0103\x050\x19" + - "\x02\xFF\u0103\x05<\x1F\x02\u0100\u0103\x05:\x1E\x02\u0101\u0103\x058" + - "\x1D\x02\u0102\xFB\x03\x02\x02\x02\u0102\xFD\x03\x02\x02\x02\u0102\xFE" + - "\x03\x02\x02\x02\u0102\xFF\x03\x02\x02\x02\u0102\u0100\x03\x02\x02\x02" + - "\u0102\u0101\x03\x02\x02\x02\u0103\u010A\x03\x02\x02\x02\u0104\u0105\f" + - "\t\x02\x02\u0105\u0106\x05B\"\x02\u0106\u0107\x056\x1C\n\u0107\u0109\x03" + - "\x02\x02\x02\u0108\u0104\x03\x02\x02\x02\u0109\u010C\x03\x02\x02\x02\u010A" + - "\u0108\x03\x02\x02\x02\u010A\u010B\x03\x02\x02\x02\u010B7\x03\x02\x02" + - "\x02\u010C\u010A\x03\x02\x02\x02\u010D\u010E\x07\x16\x02\x02\u010E\u010F" + - "\x056\x1C\x02\u010F\u0110\x07\x17\x02\x02\u01109\x03\x02\x02\x02\u0111" + - "\u0112\x05@!\x02\u0112\u0113\x056\x1C\x02\u0113;\x03\x02\x02\x02\u0114" + - "\u0115\x07.\x02\x02\u0115\u0116\x07\x18\x02\x02\u0116\u0117\x056\x1C\x02" + - "\u0117\u0118\x07\x19\x02\x02\u0118=\x03\x02\x02\x02\u0119\u011A\t\x04" + - "\x02\x02\u011A?\x03\x02\x02\x02\u011B\u011C\t\x05\x02\x02\u011CA\x03\x02" + - "\x02\x02\u011D\u011E\t\x06\x02\x02\u011EC\x03\x02\x02\x02\x16MSbju\x82" + - "\x8B\x8E\x99\xA6\xB0\xB8\xBD\xCF\xE9\xED\xF6\xF9\u0102\u010A"; + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + + "\t#\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x07\x03N\n" + + "\x03\f\x03\x0E\x03Q\v\x03\x03\x03\x07\x03T\n\x03\f\x03\x0E\x03W\v\x03" + + "\x03\x03\x03\x03\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05" + + "\x03\x05\x03\x05\x03\x05\x05\x05e\n\x05\x03\x06\x03\x06\x03\x06\x03\x06" + + "\x07\x06k\n\x06\f\x06\x0E\x06n\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b" + + "\x03\b\x03\b\x03\b\x05\bx\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03" + + "\t\x03\n\x03\n\x03\v\x03\v\x05\v\x85\n\v\x03\f\x03\f\x03\r\x03\r\x03\r" + + "\x07\r\x8C\n\r\f\r\x0E\r\x8F\v\r\x05\r\x91\n\r\x03\x0E\x03\x0E\x03\x0E" + + "\x03\x0F\x03\x0F\x03\x10\x03\x10\x07\x10\x9A\n\x10\f\x10\x0E\x10\x9D\v" + + "\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x07" + + "\x11\xA7\n\x11\f\x11\x0E\x11\xAA\v\x11\x03\x11\x03\x11\x03\x12\x03\x12" + + "\x03\x13\x03\x13\x03\x14\x07\x14\xB3\n\x14\f\x14\x0E\x14\xB6\v\x14\x03" + + "\x15\x03\x15\x03\x15\x03\x15\x03\x15\x05\x15\xBD\n\x15\x03\x16\x03\x16" + + "\x03\x16\x05\x16\xC2\n\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x17\x03" + + "\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03" + + "\x17\x03\x17\x05\x17\xD4\n\x17\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18" + + "\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x1A\x03\x1A" + + "\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x05\x1A\xE9\n\x1A\x03\x1A\x03" + + "\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x05\x1A\xF1\n\x1A\x03\x1B\x03\x1B" + + "\x05\x1B\xF5\n\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x07\x1C\xFC" + + "\n\x1C\f\x1C\x0E\x1C\xFF\v\x1C\x05\x1C\u0101\n\x1C\x03\x1D\x03\x1D\x03" + + "\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x05\x1D\u010A\n\x1D\x03\x1D\x03\x1D" + + "\x03\x1D\x03\x1D\x07\x1D\u0110\n\x1D\f\x1D\x0E\x1D\u0113\v\x1D\x03\x1E" + + "\x03\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03\x1F\x03 \x03 \x03 \x03 \x03" + + " \x03!\x03!\x03\"\x03\"\x03#\x03#\x03#\x02\x02\x038$\x02\x02\x04\x02\x06" + + "\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02" + + "\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x02" + + "2\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02D\x02\x02\x06\x04\x02\n\f" + + "..\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02\x1D#%&\x02\u0121\x02F\x03\x02" + + "\x02\x02\x04I\x03\x02\x02\x02\x06Z\x03\x02\x02\x02\bd\x03\x02\x02\x02" + + "\nf\x03\x02\x02\x02\fo\x03\x02\x02\x02\x0Ew\x03\x02\x02\x02\x10y\x03\x02" + + "\x02\x02\x12\x80\x03\x02\x02\x02\x14\x84\x03\x02\x02\x02\x16\x86\x03\x02" + + "\x02\x02\x18\x90\x03\x02\x02\x02\x1A\x92\x03\x02\x02\x02\x1C\x95\x03\x02" + + "\x02\x02\x1E\x97\x03\x02\x02\x02 \xA1\x03\x02\x02\x02\"\xAD\x03\x02\x02" + + "\x02$\xAF\x03\x02\x02\x02&\xB4\x03\x02\x02\x02(\xBC\x03\x02\x02\x02*\xBE" + + "\x03\x02\x02\x02,\xC7\x03\x02\x02\x02.\xD5\x03\x02\x02\x020\xDD\x03\x02" + + "\x02\x022\xF0\x03\x02\x02\x024\xF2\x03\x02\x02\x026\u0100\x03\x02\x02" + + "\x028\u0109\x03\x02\x02\x02:\u0114\x03\x02\x02\x02<\u0118\x03\x02\x02" + + "\x02>\u011B\x03\x02\x02\x02@\u0120\x03\x02\x02\x02B\u0122\x03\x02\x02" + + "\x02D\u0124\x03\x02\x02\x02FG\x05\x04\x03\x02GH\x07\x02\x02\x03H\x03\x03" + + "\x02\x02\x02IJ\x07\x03\x02\x02JK\x05\x06\x04\x02KO\x07\x14\x02\x02LN\x05" + + "\b\x05\x02ML\x03\x02\x02\x02NQ\x03\x02\x02\x02OM\x03\x02\x02\x02OP\x03" + + "\x02\x02\x02PU\x03\x02\x02\x02QO\x03\x02\x02\x02RT\x05\x0E\b\x02SR\x03" + + "\x02\x02\x02TW\x03\x02\x02\x02US\x03\x02\x02\x02UV\x03\x02\x02\x02VX\x03" + + "\x02\x02\x02WU\x03\x02\x02\x02XY\x07\x15\x02\x02Y\x05\x03\x02\x02\x02" + + "Z[\x07.\x02\x02[\x07\x03\x02\x02\x02\\]\x07\b\x02\x02]^\x05\n\x06\x02" + + "^_\x07\x1C\x02\x02_e\x03\x02\x02\x02`a\x07\x07\x02\x02ab\x05\n\x06\x02" + + "bc\x07\x1C\x02\x02ce\x03\x02\x02\x02d\\\x03\x02\x02\x02d`\x03\x02\x02" + + "\x02e\t\x03\x02\x02\x02fg\x05\x16\f\x02gl\x05\f\x07\x02hi\x07\x1B\x02" + + "\x02ik\x05\f\x07\x02jh\x03\x02\x02\x02kn\x03\x02\x02\x02lj\x03\x02\x02" + + "\x02lm\x03\x02\x02\x02m\v\x03\x02\x02\x02nl\x03\x02\x02\x02op\x07.\x02" + + "\x02p\r\x03\x02\x02\x02qr\x07\x04\x02\x02rx\x05\x10\t\x02st\x07\x06\x02" + + "\x02tx\x05\x10\t\x02uv\x07\x05\x02\x02vx\x05\x10\t\x02wq\x03\x02\x02\x02" + + "ws\x03\x02\x02\x02wu\x03\x02\x02\x02x\x0F\x03\x02\x02\x02yz\x05\x14\v" + + "\x02z{\x05\x12\n\x02{|\x07\x16\x02\x02|}\x05\x18\r\x02}~\x07\x17\x02\x02" + + "~\x7F\x05\x1E\x10\x02\x7F\x11\x03\x02\x02\x02\x80\x81\x07.\x02\x02\x81" + + "\x13\x03\x02\x02\x02\x82\x85\x05\x16\f\x02\x83\x85\x07\r\x02\x02\x84\x82" + + "\x03\x02\x02\x02\x84\x83\x03\x02\x02\x02\x85\x15\x03\x02\x02\x02\x86\x87" + + "\t\x02\x02\x02\x87\x17\x03\x02\x02\x02\x88\x8D\x05\x1A\x0E\x02\x89\x8A" + + "\x07\x1B\x02\x02\x8A\x8C\x05\x1A\x0E\x02\x8B\x89\x03\x02\x02\x02\x8C\x8F" + + "\x03\x02\x02\x02\x8D\x8B\x03\x02\x02\x02\x8D\x8E\x03\x02\x02\x02\x8E\x91" + + "\x03\x02\x02\x02\x8F\x8D\x03\x02\x02\x02\x90\x88\x03\x02\x02\x02\x90\x91" + + "\x03\x02\x02\x02\x91\x19\x03\x02\x02\x02\x92\x93\x05\x16\f\x02\x93\x94" + + "\x05\x1C\x0F\x02\x94\x1B\x03\x02\x02\x02\x95\x96\x07.\x02\x02\x96\x1D" + + "\x03\x02\x02\x02\x97\x9B\x07\x14\x02\x02\x98\x9A\x05 \x11\x02\x99\x98" + + "\x03\x02\x02\x02\x9A\x9D\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C" + + "\x03\x02\x02\x02\x9C\x9E\x03\x02\x02\x02\x9D\x9B\x03\x02\x02\x02\x9E\x9F" + + "\x05&\x14\x02\x9F\xA0\x07\x15\x02\x02\xA0\x1F\x03\x02\x02\x02\xA1\xA2" + + "\x07\t\x02\x02\xA2\xA3\x05\x16\f\x02\xA3\xA8\x05\"\x12\x02\xA4\xA5\x07" + + "\x1B\x02\x02\xA5\xA7\x05\"\x12\x02\xA6\xA4\x03\x02\x02\x02\xA7\xAA\x03" + + "\x02\x02\x02\xA8\xA6\x03\x02\x02\x02\xA8\xA9\x03\x02\x02\x02\xA9\xAB\x03" + + "\x02\x02\x02\xAA\xA8\x03\x02\x02\x02\xAB\xAC\x07\x1C\x02\x02\xAC!\x03" + + "\x02\x02\x02\xAD\xAE\x07.\x02\x02\xAE#\x03\x02\x02\x02\xAF\xB0\x07.\x02" + + "\x02\xB0%\x03\x02\x02\x02\xB1\xB3\x05(\x15\x02\xB2\xB1\x03\x02\x02\x02" + + "\xB3\xB6\x03\x02\x02\x02\xB4\xB2\x03\x02\x02\x02\xB4\xB5\x03\x02\x02\x02" + + "\xB5\'\x03\x02\x02\x02\xB6\xB4\x03\x02\x02\x02\xB7\xBD\x05*\x16\x02\xB8" + + "\xBD\x05,\x17\x02\xB9\xBD\x05.\x18\x02\xBA\xBD\x050\x19\x02\xBB\xBD\x05" + + "4\x1B\x02\xBC\xB7\x03\x02\x02\x02\xBC\xB8\x03\x02\x02\x02\xBC\xB9\x03" + + "\x02\x02\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD)\x03" + + "\x02\x02\x02\xBE\xC1\x07\x0E\x02\x02\xBF\xC2\x05$\x13\x02\xC0\xC2\x05" + + "> \x02\xC1\xBF\x03\x02\x02\x02\xC1\xC0\x03\x02\x02\x02\xC2\xC3\x03\x02" + + "\x02\x02\xC3\xC4\x07\x1D\x02\x02\xC4\xC5\x058\x1D\x02\xC5\xC6\x07\x1C" + + "\x02\x02\xC6+\x03\x02\x02\x02\xC7\xC8\x07\x10\x02\x02\xC8\xC9\x07\x16" + + "\x02\x02\xC9\xCA\x058\x1D\x02\xCA\xCB\x07\x17\x02\x02\xCB\xCC\x07\x14" + + "\x02\x02\xCC\xCD\x05&\x14\x02\xCD\xD3\x07\x15\x02\x02\xCE\xCF\x07\x11" + + "\x02\x02\xCF\xD0\x07\x14\x02\x02\xD0\xD1\x05&\x14\x02\xD1\xD2\x07\x15" + + "\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xCE\x03\x02\x02\x02\xD3\xD4\x03\x02" + + "\x02\x02\xD4-\x03\x02\x02\x02\xD5\xD6\x07\x12\x02\x02\xD6\xD7\x07\x16" + + "\x02\x02\xD7\xD8\x058\x1D\x02\xD8\xD9\x07\x17\x02\x02\xD9\xDA\x07\x14" + + "\x02\x02\xDA\xDB\x05&\x14\x02\xDB\xDC\x07\x15\x02\x02\xDC/\x03\x02\x02" + + "\x02\xDD\xDE\x07\x0F\x02\x02\xDE\xDF\x052\x1A\x02\xDF\xE0\x07\x1C\x02" + + "\x02\xE01\x03\x02\x02\x02\xE1\xE2\x05\x12\n\x02\xE2\xE3\x07\x16\x02\x02" + + "\xE3\xE4\x056\x1C\x02\xE4\xE5\x07\x17\x02\x02\xE5\xF1\x03\x02\x02\x02" + + "\xE6\xE9\x05\x06\x04\x02\xE7\xE9\x07-\x02\x02\xE8\xE6\x03\x02\x02\x02" + + "\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xEB\x07\x1A\x02\x02" + + "\xEB\xEC\x05\x12\n\x02\xEC\xED\x07\x16\x02\x02\xED\xEE\x056\x1C\x02\xEE" + + "\xEF\x07\x17\x02\x02\xEF\xF1\x03\x02\x02\x02\xF0\xE1\x03\x02\x02\x02\xF0" + + "\xE8\x03\x02\x02\x02\xF13\x03\x02\x02\x02\xF2\xF4\x07\x13\x02\x02\xF3" + + "\xF5\x058\x1D\x02\xF4\xF3\x03\x02\x02\x02\xF4\xF5\x03\x02\x02\x02\xF5" + + "\xF6\x03\x02\x02\x02\xF6\xF7\x07\x1C\x02\x02\xF75\x03\x02\x02\x02\xF8" + + "\xFD\x058\x1D\x02\xF9\xFA\x07\x1B\x02\x02\xFA\xFC\x058\x1D\x02\xFB\xF9" + + "\x03\x02\x02\x02\xFC\xFF\x03\x02\x02\x02\xFD\xFB\x03\x02\x02\x02\xFD\xFE" + + "\x03\x02\x02\x02\xFE\u0101\x03\x02\x02\x02\xFF\xFD\x03\x02\x02\x02\u0100" + + "\xF8\x03\x02\x02\x02\u0100\u0101\x03\x02\x02\x02\u01017\x03\x02\x02\x02" + + "\u0102\u0103\b\x1D\x01\x02\u0103\u010A\x05@!\x02\u0104\u010A\x05$\x13" + + "\x02\u0105\u010A\x052\x1A\x02\u0106\u010A\x05> \x02\u0107\u010A\x05<\x1F" + + "\x02\u0108\u010A\x05:\x1E\x02\u0109\u0102\x03\x02\x02\x02\u0109\u0104" + + "\x03\x02\x02\x02\u0109\u0105\x03\x02\x02\x02\u0109\u0106\x03\x02\x02\x02" + + "\u0109\u0107\x03\x02\x02\x02\u0109\u0108\x03\x02\x02\x02\u010A\u0111\x03" + + "\x02\x02\x02\u010B\u010C\f\t\x02\x02\u010C\u010D\x05D#\x02\u010D\u010E" + + "\x058\x1D\n\u010E\u0110\x03\x02\x02\x02\u010F\u010B\x03\x02\x02\x02\u0110" + + "\u0113\x03\x02\x02\x02\u0111\u010F\x03\x02\x02\x02\u0111\u0112\x03\x02" + + "\x02\x02\u01129\x03\x02\x02\x02\u0113\u0111\x03\x02\x02\x02\u0114\u0115" + + "\x07\x16\x02\x02\u0115\u0116\x058\x1D\x02\u0116\u0117\x07\x17\x02\x02" + + "\u0117;\x03\x02\x02\x02\u0118\u0119\x05B\"\x02\u0119\u011A\x058\x1D\x02" + + "\u011A=\x03\x02\x02\x02\u011B\u011C\x05$\x13\x02\u011C\u011D\x07\x18\x02" + + "\x02\u011D\u011E\x058\x1D\x02\u011E\u011F\x07\x19\x02\x02\u011F?\x03\x02" + + "\x02\x02\u0120\u0121\t\x03\x02\x02\u0121A\x03\x02\x02\x02\u0122\u0123" + + "\t\x04\x02\x02\u0123C\x03\x02\x02\x02\u0124\u0125\t\x05\x02\x02\u0125" + + "E\x03\x02\x02\x02\x17OUdlw\x84\x8D\x90\x9B\xA8\xB4\xBC\xC1\xD3\xE8\xF0" + + "\xF4\xFD\u0100\u0109\u0111"; public static __ATN: ATN; public static get _ATN(): ATN { if (!JackParser.__ATN) { @@ -2355,13 +2391,13 @@ export class VarDeclarationContext extends ParserRuleContext { public varType(): VarTypeContext { return this.getRuleContext(0, VarTypeContext); } - public varName(): VarNameContext[]; - public varName(i: number): VarNameContext; - public varName(i?: number): VarNameContext | VarNameContext[] { + public varNameInDeclaration(): VarNameInDeclarationContext[]; + public varNameInDeclaration(i: number): VarNameInDeclarationContext; + public varNameInDeclaration(i?: number): VarNameInDeclarationContext | VarNameInDeclarationContext[] { if (i === undefined) { - return this.getRuleContexts(VarNameContext); + return this.getRuleContexts(VarNameInDeclarationContext); } else { - return this.getRuleContext(i, VarNameContext); + return this.getRuleContext(i, VarNameInDeclarationContext); } } public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } @@ -2402,6 +2438,36 @@ export class VarDeclarationContext extends ParserRuleContext { } +export class VarNameInDeclarationContext extends ParserRuleContext { + public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_varNameInDeclaration; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterVarNameInDeclaration) { + listener.enterVarNameInDeclaration(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitVarNameInDeclaration) { + listener.exitVarNameInDeclaration(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitVarNameInDeclaration) { + return visitor.visitVarNameInDeclaration(this); + } else { + return visitor.visitChildren(this); + } + } +} + + export class VarNameContext extends ParserRuleContext { public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { @@ -2521,7 +2587,9 @@ export class LetStatementContext extends ParserRuleContext { return this.getRuleContext(0, ExpressionContext); } public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(JackParser.IDENTIFIER, 0); } + public varName(): VarNameContext | undefined { + return this.tryGetRuleContext(0, VarNameContext); + } public arrayAccess(): ArrayAccessContext | undefined { return this.tryGetRuleContext(0, ArrayAccessContext); } @@ -2691,14 +2759,8 @@ export class DoStatementContext extends ParserRuleContext { export class SubroutineCallContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode[]; - public IDENTIFIER(i: number): TerminalNode; - public IDENTIFIER(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.IDENTIFIER); - } else { - return this.getToken(JackParser.IDENTIFIER, i); - } + public subroutineName(): SubroutineNameContext { + return this.getRuleContext(0, SubroutineNameContext); } public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } public expressionList(): ExpressionListContext { @@ -2706,6 +2768,9 @@ export class SubroutineCallContext extends ParserRuleContext { } public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } public DOT(): TerminalNode | undefined { return this.tryGetToken(JackParser.DOT, 0); } + public className(): ClassNameContext | undefined { + return this.tryGetRuleContext(0, ClassNameContext); + } public THIS_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.THIS_LITERAL, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); @@ -2833,7 +2898,9 @@ export class ExpressionContext extends ParserRuleContext { public constant(): ConstantContext | undefined { return this.tryGetRuleContext(0, ConstantContext); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(JackParser.IDENTIFIER, 0); } + public varName(): VarNameContext | undefined { + return this.tryGetRuleContext(0, VarNameContext); + } public subroutineCall(): SubroutineCallContext | undefined { return this.tryGetRuleContext(0, SubroutineCallContext); } @@ -2944,7 +3011,9 @@ export class UnaryOpContext extends ParserRuleContext { export class ArrayAccessContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } + public varName(): VarNameContext { + return this.getRuleContext(0, VarNameContext); + } public LBRACKET(): TerminalNode { return this.getToken(JackParser.LBRACKET, 0); } public expression(): ExpressionContext { return this.getRuleContext(0, ExpressionContext); diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts index 160ac157..47d743c7 100644 --- a/compiler/src/generated/JackParserListener.ts +++ b/compiler/src/generated/JackParserListener.ts @@ -24,6 +24,7 @@ import { ParameterContext } from "./JackParser"; import { ParameterNameContext } from "./JackParser"; import { SubroutineBodyContext } from "./JackParser"; import { VarDeclarationContext } from "./JackParser"; +import { VarNameInDeclarationContext } from "./JackParser"; import { VarNameContext } from "./JackParser"; import { StatementsContext } from "./JackParser"; import { StatementContext } from "./JackParser"; @@ -289,6 +290,17 @@ export interface JackParserListener extends ParseTreeListener { */ exitVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** * Enter a parse tree produced by `JackParser.varName`. * @param ctx the parse tree diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts index 6910d487..5a9563f3 100644 --- a/compiler/src/generated/JackParserVisitor.ts +++ b/compiler/src/generated/JackParserVisitor.ts @@ -24,6 +24,7 @@ import { ParameterContext } from "./JackParser"; import { ParameterNameContext } from "./JackParser"; import { SubroutineBodyContext } from "./JackParser"; import { VarDeclarationContext } from "./JackParser"; +import { VarNameInDeclarationContext } from "./JackParser"; import { VarNameContext } from "./JackParser"; import { StatementsContext } from "./JackParser"; import { StatementContext } from "./JackParser"; @@ -203,6 +204,13 @@ export interface JackParserVisitor extends ParseTreeVisitor { */ visitVarDeclaration?: (ctx: VarDeclarationContext) => Result; + /** + * Visit a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + * @return the visitor result + */ + visitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => Result; + /** * Visit a parse tree produced by `JackParser.varName`. * @param ctx the parse tree diff --git a/compiler/src/listener/error.listener.ts b/compiler/src/listener/error.listener.ts index 17c9b60d..5fab50ea 100644 --- a/compiler/src/listener/error.listener.ts +++ b/compiler/src/listener/error.listener.ts @@ -4,13 +4,6 @@ export class ErrorListener implements ANTLRErrorListener { static instance: ErrorListener; public filepath: string = ""; public errors: JackCompilerError[] = []; - static getInstance(): ErrorListener { - if (this.instance == null) { - this.instance = new ErrorListener() - } - return this.instance; - } - // constructor(private filepath: string, ) { }; /** diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index eba86ae1..361b1244 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,7 +1,7 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { DuplicatedVariableException, JackCompilerError } from "../error"; -import { FieldDeclarationContext, FieldNameContext, ParameterContext, ParameterNameContext, SubroutineBodyContext, SubroutineDeclarationContext, VarDeclarationContext, VarNameContext } from "../generated/JackParser"; +import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError } from "../error"; +import { FieldDeclarationContext, FieldNameContext, LetStatementContext, ParameterContext, ParameterNameContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol } from "./symbol.table.listener"; @@ -32,8 +32,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterFieldName(ctx: FieldNameContext) { this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); }; - - enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { + enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { this.localSymbolTable.pushStack(); }; @@ -41,14 +40,20 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); } - enterVarName(ctx: VarNameContext) { + enterVarNameInDeclaration(ctx: VarNameInDeclarationContext) { this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); }; + + enterVarName(ctx: VarNameContext) { + if (!this.localSymbolTable.existsSymbol(ctx.text)) { + this.errors.push(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); + } + }; exitSubroutineBody(ctx: SubroutineBodyContext) { this.localSymbolTable.popStack(); }; localSymbolTableAdd(line: number, position: number, name: string) { - if (this.localSymbolTable.lookup(name)) { + if (this.localSymbolTable.existsSymbol(name)) { this.errors.push(new DuplicatedVariableException(line, position, name)); } else { this.localSymbolTable.add(name); @@ -62,7 +67,7 @@ export class LocalSymbolTable { constructor(private scopeVarDecs: string[][] = [[]]) { } - lookup(name: string): boolean { + existsSymbol(name: string): boolean { for (let i = this.scopeVarDecs.length - 1; i >= 0; i--) { if (this.scopeVarDecs[i].includes(name)) { return true; diff --git a/compiler/test/local.symbol.table.test.ts b/compiler/test/local.symbol.table.test.ts index cb604d00..62e7d776 100644 --- a/compiler/test/local.symbol.table.test.ts +++ b/compiler/test/local.symbol.table.test.ts @@ -1,14 +1,24 @@ import { LocalSymbolTable } from "../src/listener/validator.listener"; describe('LocalSymbolTable', () => { + const jestConsole = console; + + beforeEach(() => { + global.console = require('console'); + }); + + afterEach(() => { + global.console = jestConsole; + }); + test('add', () => { const localSymbolTable = new LocalSymbolTable(); const variableNames = ['testVariable1', 'testVariable2', 'testVariable3']; variableNames.forEach(variableName => { localSymbolTable.add(variableName) - expect(localSymbolTable.lookup(variableName)).toBe(true); - expect(localSymbolTable.lookup(variableName + "_")).toBe(false); + expect(localSymbolTable.existsSymbol(variableName)).toBe(true); + expect(localSymbolTable.existsSymbol(variableName + "_")).toBe(false); }); @@ -24,13 +34,13 @@ describe('LocalSymbolTable', () => { localSymbolTable.pushStack(); localSymbolTable.add(functionVar); - expect(localSymbolTable.lookup(classVar )).toBe(true); - expect(localSymbolTable.lookup(functionVar)).toBe(true); + expect(localSymbolTable.existsSymbol(classVar )).toBe(true); + expect(localSymbolTable.existsSymbol(functionVar)).toBe(true); localSymbolTable.popStack(); - expect(localSymbolTable.lookup(classVar)).toBe(true); - expect(localSymbolTable.lookup(functionVar)).toBe(false); + expect(localSymbolTable.existsSymbol(classVar)).toBe(true); + expect(localSymbolTable.existsSymbol(functionVar)).toBe(false); }) diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index cc6cea83..586f06b6 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -39,15 +39,14 @@ describe('Parser', () => { function testJackDir(testFolder: string): void { const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); for (const filePath of files) { - const errorListener = ErrorListener.getInstance() + const errorListener = new ErrorListener() errorListener.filepath = filePath; const tree = parseJackFile(filePath) const globalSymbolsListener = listenToTheTree(tree, new GlobalSymbolTableListener()); const symbolsErrors = globalSymbolsListener.errors.join("\n") try { expect(globalSymbolsListener.errors.length).toBe(0) - } - catch (e) { + } catch (e) { throw new Error(symbolsErrors); } globalSymbolsListener.resetErrors(); diff --git a/compiler/test/symbol.table.listener.test.ts b/compiler/test/symbol.table.listener.test.ts index eb729520..5db68289 100644 --- a/compiler/test/symbol.table.listener.test.ts +++ b/compiler/test/symbol.table.listener.test.ts @@ -8,6 +8,15 @@ import path from "path"; import { ProgramContext } from "../src/generated/JackParser"; describe('Global symbol table', () => { + const jestConsole = console; + + beforeEach(() => { + global.console = require('console'); + }); + + afterEach(() => { + global.console = jestConsole; + }); test("should fail on duplicated subroutine", () => { const filePath = getTestResourcePath("DuplicatedSubroutine.jack"); diff --git a/compiler/test/test.helper.ts b/compiler/test/test.helper.ts index 0bb90da2..065e5232 100644 --- a/compiler/test/test.helper.ts +++ b/compiler/test/test.helper.ts @@ -9,7 +9,7 @@ import { JackCompilerError } from "../src/error"; import { ErrorListener } from "../src/listener/error.listener"; export function parseJackFile(filePath: string, trace = false) { - const errorListener: ErrorListener = ErrorListener.getInstance() + const errorListener: ErrorListener = new ErrorListener() errorListener.filepath = filePath const f = fs.readFileSync(filePath, 'utf8'); return parseJackText(f, errorListener, trace); @@ -17,7 +17,7 @@ export function parseJackFile(filePath: string, trace = false) { export function parseJackText(src: string, errorListener?: ErrorListener, trace: boolean = false): ProgramContext { if (errorListener === undefined) { - errorListener = ErrorListener.getInstance(); + errorListener = new ErrorListener(); } const inputStream = CharStreams.fromString(src); const lexer = new JackLexer(inputStream); @@ -36,6 +36,7 @@ export function parseJackText(src: string, errorListener?: ErrorListener, trace: } const tree = parser.program() if (errorListener.errors.length > 0) { + console.error("Parser or lexer errors found"); handleErrors(src, errorListener.errors); } return tree; diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index f973a9e3..065c8d81 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,5 +1,5 @@ import { ParserRuleContext } from "antlr4ts" -import { DuplicatedVariableException, JackCompilerError } from "../src/error" +import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { GenericSymbol } from "../src/listener/symbol.table.listener" import { ValidatorListener } from "../src/listener/validator.listener" @@ -7,6 +7,16 @@ import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" import { ProgramContext } from "../src/generated/JackParser" describe('ValidatorListener', () => { + const jestConsole = console; + + beforeEach(() => { + global.console = require('console'); + }); + + afterEach(() => { + global.console = jestConsole; + }); + const duplicateVarClassBodies = [ ["static", ' static int a, a;'], ["field", ' field int a, a;'], @@ -28,9 +38,59 @@ describe('ValidatorListener', () => { ${classBody} }`, DuplicatedVariableException) }) + test('let - undeclared variable ', () => { + testValidator('let - undeclared variable', ` + class Main { + function void a(){ + let b=1; + } + }`, UndeclaredVariableError) + }) + + test('call function - undeclared variable ', () => { + testValidator('let - undeclared variable', + `class Main { + function void b(int a){ + return; + } + function void a(){ + do Main.b(a); + } + }`, UndeclaredVariableError) + }) + + test('if - undeclared variable ', () => { + testValidator('let - undeclared variable', + `class Main { + function void a(){ + if(a=0){ + }else { + } + return; + } + }`, UndeclaredVariableError) + }) + + test('call function - undeclared variable ', () => { + testValidator('let - undeclared variable', ` + class Main { + constructor Main new(){ + return this; + } + function void b(int a){ + return; + } + method void a(){ + var Main m; + let m = Main.new(); + do m.b(a); + } + }`, UndeclaredVariableError) + }) + + //TODO: print line when on exception /* - * - variable declaration - validate duplicate variable declarations * Let: * - Undeclared variable * - `Subroutine ${subroutine.name.value}: not all code paths return a value`, @@ -46,10 +106,10 @@ describe('ValidatorListener', () => { }) -function testValidator(testName: string, src: string, expectedError: T) { - console.info("Testing \n", src) - const errorListener = ErrorListener.getInstance(); - errorListener.filepath = testName; +function testValidator(name: string, src: string, expectedError: T) { + console.info(`Testing ${name}\n`, src) + const errorListener = new ErrorListener(); + errorListener.filepath = name; const tree = parseJackText(src, errorListener) const validator = listenToTheTree(tree, new ValidatorListener({} as Record)) diff --git a/simulator/.vscode/numbered-bookmarks.json b/simulator/.vscode/numbered-bookmarks.json new file mode 100644 index 00000000..5916671d --- /dev/null +++ b/simulator/.vscode/numbered-bookmarks.json @@ -0,0 +1,3 @@ +{ + "files": [] +} \ No newline at end of file From 3a690781997c9aa5cc35a04672bfbc66971d1671 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 27 Sep 2024 08:27:45 +0200 Subject: [PATCH 10/87] Add unknown subroutine return type error --- compiler/src/error.ts | 11 ++++ compiler/src/listener/validator.listener.ts | 14 ++++- compiler/test/validator.listener.test.ts | 70 ++++++++++++++------- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 8ca6a8f0..24e561e8 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -56,3 +56,14 @@ export class UndeclaredVariableError extends JackCompilerError { } } + + +export class UnknownSubroutineReturnType extends JackCompilerError { + constructor(line: number, charPositionInLine: number, type: string) { + super(line, charPositionInLine, "Unknown subroutine return type " + type); + + // Set the prototype explicitly. + Object.setPrototypeOf(this, UnknownSubroutineReturnType.prototype); + } + +} diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 361b1244..18b6e5ff 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,7 +1,7 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError } from "../error"; -import { FieldDeclarationContext, FieldNameContext, LetStatementContext, ParameterContext, ParameterNameContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext } from "../generated/JackParser"; +import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError, UnknownSubroutineReturnType } from "../error"; +import { FieldDeclarationContext, FieldNameContext, LetStatementContext, ParameterContext, ParameterNameContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol } from "./symbol.table.listener"; @@ -35,6 +35,14 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { this.localSymbolTable.pushStack(); }; + enterVarType(ctx: VarTypeContext) { + if (ctx.IDENTIFIER() != undefined) { + const type = ctx.IDENTIFIER()!.text + if (this.globalSymbolTable[type] === undefined) { + this.errors.push(new UnknownSubroutineReturnType(ctx.start.line, ctx.start.startIndex, type)); + } + } + }; enterParameterName(ctx: ParameterNameContext) { this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); @@ -43,7 +51,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterVarNameInDeclaration(ctx: VarNameInDeclarationContext) { this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); }; - + enterVarName(ctx: VarNameContext) { if (!this.localSymbolTable.existsSymbol(ctx.text)) { this.errors.push(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index 065c8d81..a2b6c874 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,10 +1,11 @@ import { ParserRuleContext } from "antlr4ts" -import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError } from "../src/error" +import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError, UnknownSubroutineReturnType } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { GenericSymbol } from "../src/listener/symbol.table.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" import { ProgramContext } from "../src/generated/JackParser" +import { assert } from "console" describe('ValidatorListener', () => { const jestConsole = console; @@ -33,13 +34,13 @@ describe('ValidatorListener', () => { }`], ] test.concurrent.each(duplicateVarClassBodies)('duplicated %s', (testName, classBody) => { - testValidator(testName, ` + testValidator(` class Main { ${classBody} }`, DuplicatedVariableException) }) test('let - undeclared variable ', () => { - testValidator('let - undeclared variable', ` + testValidator( ` class Main { function void a(){ let b=1; @@ -48,7 +49,7 @@ describe('ValidatorListener', () => { }) test('call function - undeclared variable ', () => { - testValidator('let - undeclared variable', + testValidator( `class Main { function void b(int a){ return; @@ -60,7 +61,7 @@ describe('ValidatorListener', () => { }) test('if - undeclared variable ', () => { - testValidator('let - undeclared variable', + testValidator( `class Main { function void a(){ if(a=0){ @@ -71,28 +72,48 @@ describe('ValidatorListener', () => { }`, UndeclaredVariableError) }) - test('call function - undeclared variable ', () => { - testValidator('let - undeclared variable', ` + test('Unknown type for subroutine return type ', () => { + testValidator( ` class Main { - constructor Main new(){ - return this; - } - function void b(int a){ + function D b(int a){ return; } - method void a(){ - var Main m; - let m = Main.new(); - do m.b(a); + }`, UnknownSubroutineReturnType) + }) + + test('Known type for subroutine return type ', () => { + testValidator(` + class Main { + function D b(int a){ + return; + } + }`, undefined, { "D": {} as GenericSymbol }) + }) + + + test('Arg unknown type ', () => { + testValidator(` + class Main { + function void b(D a){ + return; } - }`, UndeclaredVariableError) + }`, UnknownSubroutineReturnType) + }) + + test('Arg known type ', () => { + testValidator( ` + + class Main { + function void b(D a){ + return; + } + }`, undefined, { "D": {} as GenericSymbol }) }) //TODO: print line when on exception /* * Let: - * - Undeclared variable * - `Subroutine ${subroutine.name.value}: not all code paths return a value`, * - `A non void subroutine must return a value`, * - Unknown type for return type, class variable, or method local var @@ -105,14 +126,19 @@ describe('ValidatorListener', () => { */ }) - -function testValidator(name: string, src: string, expectedError: T) { +function testValidator(src: string, expectedError?: T, globalSymbolTable: Record = {}) { + const name = expect.getState().currentTestName! console.info(`Testing ${name}\n`, src) const errorListener = new ErrorListener(); errorListener.filepath = name; const tree = parseJackText(src, errorListener) - const validator = listenToTheTree(tree, new ValidatorListener({} as Record)) - expect(validator.errors.length).toBe(1) - expect(validator.errors[0]).toBeInstanceOf(expectedError) + const validator = listenToTheTree(tree, new ValidatorListener(globalSymbolTable)) + if (expectedError) { + expect(validator.errors.length).toBe(1) + expect(validator.errors[0]).toBeInstanceOf(expectedError) + } else { + if (validator.errors.length != 0) throw new Error("Didn't expect any errors but got " + validator.errors.join("\n")) + + } } From b541d2299e15eb716172326e47194dbc988083e4 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 27 Sep 2024 08:41:22 +0200 Subject: [PATCH 11/87] Add unknown type error --- compiler/src/error.ts | 6 +-- compiler/src/listener/validator.listener.ts | 7 ++- compiler/test/validator.listener.test.ts | 53 ++++++++++++++++++--- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 24e561e8..0bde2b92 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -58,12 +58,12 @@ export class UndeclaredVariableError extends JackCompilerError { } -export class UnknownSubroutineReturnType extends JackCompilerError { +export class UnknownTypeError extends JackCompilerError { constructor(line: number, charPositionInLine: number, type: string) { - super(line, charPositionInLine, "Unknown subroutine return type " + type); + super(line, charPositionInLine, "Unknown type " + type); // Set the prototype explicitly. - Object.setPrototypeOf(this, UnknownSubroutineReturnType.prototype); + Object.setPrototypeOf(this, UnknownTypeError.prototype); } } diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 18b6e5ff..8a8f0c42 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,6 +1,6 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError, UnknownSubroutineReturnType } from "../error"; +import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError, UnknownTypeError } from "../error"; import { FieldDeclarationContext, FieldNameContext, LetStatementContext, ParameterContext, ParameterNameContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol } from "./symbol.table.listener"; @@ -35,15 +35,18 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { this.localSymbolTable.pushStack(); }; + + enterVarType(ctx: VarTypeContext) { if (ctx.IDENTIFIER() != undefined) { const type = ctx.IDENTIFIER()!.text if (this.globalSymbolTable[type] === undefined) { - this.errors.push(new UnknownSubroutineReturnType(ctx.start.line, ctx.start.startIndex, type)); + this.errors.push(new UnknownTypeError(ctx.start.line, ctx.start.startIndex, type)); } } }; + enterParameterName(ctx: ParameterNameContext) { this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); } diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index a2b6c874..67cd2e74 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,11 +1,10 @@ import { ParserRuleContext } from "antlr4ts" -import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError, UnknownSubroutineReturnType } from "../src/error" +import { DuplicatedVariableException as DuplicatedVariableError, JackCompilerError, UndeclaredVariableError, UnknownTypeError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { GenericSymbol } from "../src/listener/symbol.table.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" import { ProgramContext } from "../src/generated/JackParser" -import { assert } from "console" describe('ValidatorListener', () => { const jestConsole = console; @@ -37,7 +36,7 @@ describe('ValidatorListener', () => { testValidator(` class Main { ${classBody} - }`, DuplicatedVariableException) + }`, DuplicatedVariableError) }) test('let - undeclared variable ', () => { testValidator( ` @@ -78,7 +77,7 @@ describe('ValidatorListener', () => { function D b(int a){ return; } - }`, UnknownSubroutineReturnType) + }`, UnknownTypeError) }) test('Known type for subroutine return type ', () => { @@ -89,15 +88,13 @@ describe('ValidatorListener', () => { } }`, undefined, { "D": {} as GenericSymbol }) }) - - test('Arg unknown type ', () => { testValidator(` class Main { function void b(D a){ return; } - }`, UnknownSubroutineReturnType) + }`, UnknownTypeError) }) test('Arg known type ', () => { @@ -109,6 +106,48 @@ describe('ValidatorListener', () => { } }`, undefined, { "D": {} as GenericSymbol }) }) + test('var unknown type', () => { + testValidator( ` + class Main { + function void b(){ + var D d; + return; + } + }`, UnknownTypeError) + }) + test('var known type', () => { + testValidator( ` + class Main { + function void b(){ + var D d; + return; + } + }`, undefined, { "D": {} as GenericSymbol }) + }) + test('field unknown type', () => { + testValidator( ` + class Main { + field T t; + }`, UnknownTypeError) + }) + test('field known type', () => { + testValidator( ` + class Main { + field T t; + }`, undefined, { "T": {} as GenericSymbol }) + }) + test('static field unknown type', () => { + testValidator( ` + class Main { + static T t; + }`, UnknownTypeError) + }) + test('static field known type', () => { + testValidator( ` + class Main { + static T t; + }`, undefined, { "T": {} as GenericSymbol }) + }) //TODO: print line when on exception From ab1e0c9c9cc8461e39d0b30b1ad4c9fb8d82e6a0 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 27 Sep 2024 22:44:37 +0200 Subject: [PATCH 12/87] Add CFG for simple cases --- compiler/parser-gen/JackParser.g4 | 16 +- compiler/src/error.ts | 51 +- compiler/src/generated/JackParser.interp | 4 +- compiler/src/generated/JackParser.ts | 799 ++++++++++-------- compiler/src/generated/JackParserListener.ts | 24 + compiler/src/generated/JackParserVisitor.ts | 16 + .../src/listener/symbol.table.listener.ts | 28 +- compiler/src/listener/validator.listener.ts | 94 ++- compiler/test/parser.test.ts | 2 - compiler/test/symbol.table.listener.test.ts | 1 + compiler/test/validator.listener.test.ts | 174 ++-- 11 files changed, 752 insertions(+), 457 deletions(-) diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/parser-gen/JackParser.g4 index 4fd359a9..7ac3db3e 100644 --- a/compiler/parser-gen/JackParser.g4 +++ b/compiler/parser-gen/JackParser.g4 @@ -20,7 +20,7 @@ subroutineDeclaration: | FUNCTION subroutineDecWithoutType # function; subroutineDecWithoutType: subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; - subroutineName: IDENTIFIER; +subroutineName: IDENTIFIER; subroutineReturnType: varType | VOID; varType: INT | CHAR | BOOLEAN | IDENTIFIER; @@ -28,16 +28,16 @@ varType: INT | CHAR | BOOLEAN | IDENTIFIER; parameterList: (parameter (COMMA parameter)*)?; parameter: varType parameterName; parameterName: IDENTIFIER; -subroutineBody: - LBRACE varDeclaration* statements RBRACE; +subroutineBody: LBRACE varDeclaration* statements RBRACE; -varDeclaration: VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; +varDeclaration: + VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; varNameInDeclaration: IDENTIFIER; varName: IDENTIFIER; statements: statement*; statement: letStatement - | ifStatement + | ifElseStatement | whileStatement | doStatement | returnStatement; @@ -45,10 +45,10 @@ statement: letStatement: LET (varName | arrayAccess) EQUALS expression SEMICOLON; //TODO: check right assoc for this +ifElseStatement: ifStatement elseStatement?; ifStatement: - IF LPAREN expression RPAREN LBRACE statements RBRACE ( - ELSE LBRACE statements RBRACE - )?; + IF LPAREN expression RPAREN LBRACE statements RBRACE; +elseStatement: ELSE LBRACE statements RBRACE; whileStatement: WHILE LPAREN expression RPAREN LBRACE statements RBRACE; diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 0bde2b92..98f9b812 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -1,4 +1,4 @@ -export class JackCompilerError extends Error { +export class JackCompilerError { /** * * @param line - line number @@ -6,10 +6,6 @@ export class JackCompilerError extends Error { * @param msg - error message */ constructor(public line: number, public charPositionInLine: number, public msg: string) { - super(msg); - - // Set the prototype explicitly. - Object.setPrototypeOf(this, JackCompilerError.prototype); } } export class LexerOrParserError extends Error { @@ -21,27 +17,17 @@ export class LexerOrParserError extends Error { */ constructor(public filepath: string, public line: number, public charPositionInLine: number, public msg: string) { super(msg); - - // Set the prototype explicitly. - Object.setPrototypeOf(this, LexerOrParserError.prototype); } } export class DuplicatedSubroutineError extends JackCompilerError { constructor(line: number, charPositionInLine: number, msg: string) { super(line, charPositionInLine, msg); - - // Set the prototype explicitly. - Object.setPrototypeOf(this, DuplicatedSubroutineError.prototype); } - } export class DuplicatedVariableException extends JackCompilerError { constructor(line: number, charPositionInLine: number, variableName: string) { super(line, charPositionInLine, "Duplicated variable " + variableName); - - // Set the prototype explicitly. - Object.setPrototypeOf(this, DuplicatedVariableException.prototype); } } @@ -50,20 +36,41 @@ export class DuplicatedVariableException extends JackCompilerError { export class UndeclaredVariableError extends JackCompilerError { constructor(line: number, charPositionInLine: number, variableName: string) { super(line, charPositionInLine, "Undeclared variable " + variableName); + } + +} - // Set the prototype explicitly. - Object.setPrototypeOf(this, UndeclaredVariableError.prototype); + +export class UnknownClassError extends JackCompilerError { + constructor(line: number, charPositionInLine: number, className: string) { + super(line, charPositionInLine, `Class ${className} doesn't exist` ); } } +export class NonVoidFunctionNoReturnError extends JackCompilerError { + + //TODO: should we add a subroutine name? + constructor(line: number, charPositionInLine: number) { + super(line, charPositionInLine, `A non void subroutine must return a value` ); + } + +} -export class UnknownTypeError extends JackCompilerError { - constructor(line: number, charPositionInLine: number, type: string) { - super(line, charPositionInLine, "Unknown type " + type); +export class VoidSubroutineReturnsValueError extends JackCompilerError { - // Set the prototype explicitly. - Object.setPrototypeOf(this, UnknownTypeError.prototype); + constructor(line: number, charPositionInLine: number) { + super(line, charPositionInLine, `Cannot return a value from a void subroutine` ); + Object.setPrototypeOf(this, VoidSubroutineReturnsValueError.prototype); } } + +export class SubroutineNotAllPathsReturn extends JackCompilerError { + + constructor(line: number, charPositionInLine: number, subroutineName: string) { + super(line, charPositionInLine, `Subroutine ${subroutineName}: not all code paths return a value` ); + Object.setPrototypeOf(this, SubroutineNotAllPathsReturn.prototype); + } + +} \ No newline at end of file diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp index cf7546af..f85f3f4d 100644 --- a/compiler/src/generated/JackParser.interp +++ b/compiler/src/generated/JackParser.interp @@ -118,6 +118,8 @@ varName statements statement letStatement +ifElseStatement +elseStatement ifStatement whileStatement doStatement @@ -134,4 +136,4 @@ binaryOperator atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 295, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 78, 10, 3, 12, 3, 14, 3, 81, 11, 3, 3, 3, 7, 3, 84, 10, 3, 12, 3, 14, 3, 87, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 101, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 107, 10, 6, 12, 6, 14, 6, 110, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 120, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 133, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 140, 10, 13, 12, 13, 14, 13, 143, 11, 13, 5, 13, 145, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 154, 10, 16, 12, 16, 14, 16, 157, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 167, 10, 17, 12, 17, 14, 17, 170, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 7, 20, 179, 10, 20, 12, 20, 14, 20, 182, 11, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 189, 10, 21, 3, 22, 3, 22, 3, 22, 5, 22, 194, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 212, 10, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 233, 10, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 5, 26, 241, 10, 26, 3, 27, 3, 27, 5, 27, 245, 10, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 7, 28, 252, 10, 28, 12, 28, 14, 28, 255, 11, 28, 5, 28, 257, 10, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 5, 29, 266, 10, 29, 3, 29, 3, 29, 3, 29, 3, 29, 7, 29, 272, 10, 29, 12, 29, 14, 29, 275, 11, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 2, 2, 3, 56, 36, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 2, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 289, 2, 70, 3, 2, 2, 2, 4, 73, 3, 2, 2, 2, 6, 90, 3, 2, 2, 2, 8, 100, 3, 2, 2, 2, 10, 102, 3, 2, 2, 2, 12, 111, 3, 2, 2, 2, 14, 119, 3, 2, 2, 2, 16, 121, 3, 2, 2, 2, 18, 128, 3, 2, 2, 2, 20, 132, 3, 2, 2, 2, 22, 134, 3, 2, 2, 2, 24, 144, 3, 2, 2, 2, 26, 146, 3, 2, 2, 2, 28, 149, 3, 2, 2, 2, 30, 151, 3, 2, 2, 2, 32, 161, 3, 2, 2, 2, 34, 173, 3, 2, 2, 2, 36, 175, 3, 2, 2, 2, 38, 180, 3, 2, 2, 2, 40, 188, 3, 2, 2, 2, 42, 190, 3, 2, 2, 2, 44, 199, 3, 2, 2, 2, 46, 213, 3, 2, 2, 2, 48, 221, 3, 2, 2, 2, 50, 240, 3, 2, 2, 2, 52, 242, 3, 2, 2, 2, 54, 256, 3, 2, 2, 2, 56, 265, 3, 2, 2, 2, 58, 276, 3, 2, 2, 2, 60, 280, 3, 2, 2, 2, 62, 283, 3, 2, 2, 2, 64, 288, 3, 2, 2, 2, 66, 290, 3, 2, 2, 2, 68, 292, 3, 2, 2, 2, 70, 71, 5, 4, 3, 2, 71, 72, 7, 2, 2, 3, 72, 3, 3, 2, 2, 2, 73, 74, 7, 3, 2, 2, 74, 75, 5, 6, 4, 2, 75, 79, 7, 20, 2, 2, 76, 78, 5, 8, 5, 2, 77, 76, 3, 2, 2, 2, 78, 81, 3, 2, 2, 2, 79, 77, 3, 2, 2, 2, 79, 80, 3, 2, 2, 2, 80, 85, 3, 2, 2, 2, 81, 79, 3, 2, 2, 2, 82, 84, 5, 14, 8, 2, 83, 82, 3, 2, 2, 2, 84, 87, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 88, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 88, 89, 7, 21, 2, 2, 89, 5, 3, 2, 2, 2, 90, 91, 7, 46, 2, 2, 91, 7, 3, 2, 2, 2, 92, 93, 7, 8, 2, 2, 93, 94, 5, 10, 6, 2, 94, 95, 7, 28, 2, 2, 95, 101, 3, 2, 2, 2, 96, 97, 7, 7, 2, 2, 97, 98, 5, 10, 6, 2, 98, 99, 7, 28, 2, 2, 99, 101, 3, 2, 2, 2, 100, 92, 3, 2, 2, 2, 100, 96, 3, 2, 2, 2, 101, 9, 3, 2, 2, 2, 102, 103, 5, 22, 12, 2, 103, 108, 5, 12, 7, 2, 104, 105, 7, 27, 2, 2, 105, 107, 5, 12, 7, 2, 106, 104, 3, 2, 2, 2, 107, 110, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 108, 109, 3, 2, 2, 2, 109, 11, 3, 2, 2, 2, 110, 108, 3, 2, 2, 2, 111, 112, 7, 46, 2, 2, 112, 13, 3, 2, 2, 2, 113, 114, 7, 4, 2, 2, 114, 120, 5, 16, 9, 2, 115, 116, 7, 6, 2, 2, 116, 120, 5, 16, 9, 2, 117, 118, 7, 5, 2, 2, 118, 120, 5, 16, 9, 2, 119, 113, 3, 2, 2, 2, 119, 115, 3, 2, 2, 2, 119, 117, 3, 2, 2, 2, 120, 15, 3, 2, 2, 2, 121, 122, 5, 20, 11, 2, 122, 123, 5, 18, 10, 2, 123, 124, 7, 22, 2, 2, 124, 125, 5, 24, 13, 2, 125, 126, 7, 23, 2, 2, 126, 127, 5, 30, 16, 2, 127, 17, 3, 2, 2, 2, 128, 129, 7, 46, 2, 2, 129, 19, 3, 2, 2, 2, 130, 133, 5, 22, 12, 2, 131, 133, 7, 13, 2, 2, 132, 130, 3, 2, 2, 2, 132, 131, 3, 2, 2, 2, 133, 21, 3, 2, 2, 2, 134, 135, 9, 2, 2, 2, 135, 23, 3, 2, 2, 2, 136, 141, 5, 26, 14, 2, 137, 138, 7, 27, 2, 2, 138, 140, 5, 26, 14, 2, 139, 137, 3, 2, 2, 2, 140, 143, 3, 2, 2, 2, 141, 139, 3, 2, 2, 2, 141, 142, 3, 2, 2, 2, 142, 145, 3, 2, 2, 2, 143, 141, 3, 2, 2, 2, 144, 136, 3, 2, 2, 2, 144, 145, 3, 2, 2, 2, 145, 25, 3, 2, 2, 2, 146, 147, 5, 22, 12, 2, 147, 148, 5, 28, 15, 2, 148, 27, 3, 2, 2, 2, 149, 150, 7, 46, 2, 2, 150, 29, 3, 2, 2, 2, 151, 155, 7, 20, 2, 2, 152, 154, 5, 32, 17, 2, 153, 152, 3, 2, 2, 2, 154, 157, 3, 2, 2, 2, 155, 153, 3, 2, 2, 2, 155, 156, 3, 2, 2, 2, 156, 158, 3, 2, 2, 2, 157, 155, 3, 2, 2, 2, 158, 159, 5, 38, 20, 2, 159, 160, 7, 21, 2, 2, 160, 31, 3, 2, 2, 2, 161, 162, 7, 9, 2, 2, 162, 163, 5, 22, 12, 2, 163, 168, 5, 34, 18, 2, 164, 165, 7, 27, 2, 2, 165, 167, 5, 34, 18, 2, 166, 164, 3, 2, 2, 2, 167, 170, 3, 2, 2, 2, 168, 166, 3, 2, 2, 2, 168, 169, 3, 2, 2, 2, 169, 171, 3, 2, 2, 2, 170, 168, 3, 2, 2, 2, 171, 172, 7, 28, 2, 2, 172, 33, 3, 2, 2, 2, 173, 174, 7, 46, 2, 2, 174, 35, 3, 2, 2, 2, 175, 176, 7, 46, 2, 2, 176, 37, 3, 2, 2, 2, 177, 179, 5, 40, 21, 2, 178, 177, 3, 2, 2, 2, 179, 182, 3, 2, 2, 2, 180, 178, 3, 2, 2, 2, 180, 181, 3, 2, 2, 2, 181, 39, 3, 2, 2, 2, 182, 180, 3, 2, 2, 2, 183, 189, 5, 42, 22, 2, 184, 189, 5, 44, 23, 2, 185, 189, 5, 46, 24, 2, 186, 189, 5, 48, 25, 2, 187, 189, 5, 52, 27, 2, 188, 183, 3, 2, 2, 2, 188, 184, 3, 2, 2, 2, 188, 185, 3, 2, 2, 2, 188, 186, 3, 2, 2, 2, 188, 187, 3, 2, 2, 2, 189, 41, 3, 2, 2, 2, 190, 193, 7, 14, 2, 2, 191, 194, 5, 36, 19, 2, 192, 194, 5, 62, 32, 2, 193, 191, 3, 2, 2, 2, 193, 192, 3, 2, 2, 2, 194, 195, 3, 2, 2, 2, 195, 196, 7, 29, 2, 2, 196, 197, 5, 56, 29, 2, 197, 198, 7, 28, 2, 2, 198, 43, 3, 2, 2, 2, 199, 200, 7, 16, 2, 2, 200, 201, 7, 22, 2, 2, 201, 202, 5, 56, 29, 2, 202, 203, 7, 23, 2, 2, 203, 204, 7, 20, 2, 2, 204, 205, 5, 38, 20, 2, 205, 211, 7, 21, 2, 2, 206, 207, 7, 17, 2, 2, 207, 208, 7, 20, 2, 2, 208, 209, 5, 38, 20, 2, 209, 210, 7, 21, 2, 2, 210, 212, 3, 2, 2, 2, 211, 206, 3, 2, 2, 2, 211, 212, 3, 2, 2, 2, 212, 45, 3, 2, 2, 2, 213, 214, 7, 18, 2, 2, 214, 215, 7, 22, 2, 2, 215, 216, 5, 56, 29, 2, 216, 217, 7, 23, 2, 2, 217, 218, 7, 20, 2, 2, 218, 219, 5, 38, 20, 2, 219, 220, 7, 21, 2, 2, 220, 47, 3, 2, 2, 2, 221, 222, 7, 15, 2, 2, 222, 223, 5, 50, 26, 2, 223, 224, 7, 28, 2, 2, 224, 49, 3, 2, 2, 2, 225, 226, 5, 18, 10, 2, 226, 227, 7, 22, 2, 2, 227, 228, 5, 54, 28, 2, 228, 229, 7, 23, 2, 2, 229, 241, 3, 2, 2, 2, 230, 233, 5, 6, 4, 2, 231, 233, 7, 45, 2, 2, 232, 230, 3, 2, 2, 2, 232, 231, 3, 2, 2, 2, 233, 234, 3, 2, 2, 2, 234, 235, 7, 26, 2, 2, 235, 236, 5, 18, 10, 2, 236, 237, 7, 22, 2, 2, 237, 238, 5, 54, 28, 2, 238, 239, 7, 23, 2, 2, 239, 241, 3, 2, 2, 2, 240, 225, 3, 2, 2, 2, 240, 232, 3, 2, 2, 2, 241, 51, 3, 2, 2, 2, 242, 244, 7, 19, 2, 2, 243, 245, 5, 56, 29, 2, 244, 243, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 246, 3, 2, 2, 2, 246, 247, 7, 28, 2, 2, 247, 53, 3, 2, 2, 2, 248, 253, 5, 56, 29, 2, 249, 250, 7, 27, 2, 2, 250, 252, 5, 56, 29, 2, 251, 249, 3, 2, 2, 2, 252, 255, 3, 2, 2, 2, 253, 251, 3, 2, 2, 2, 253, 254, 3, 2, 2, 2, 254, 257, 3, 2, 2, 2, 255, 253, 3, 2, 2, 2, 256, 248, 3, 2, 2, 2, 256, 257, 3, 2, 2, 2, 257, 55, 3, 2, 2, 2, 258, 259, 8, 29, 1, 2, 259, 266, 5, 64, 33, 2, 260, 266, 5, 36, 19, 2, 261, 266, 5, 50, 26, 2, 262, 266, 5, 62, 32, 2, 263, 266, 5, 60, 31, 2, 264, 266, 5, 58, 30, 2, 265, 258, 3, 2, 2, 2, 265, 260, 3, 2, 2, 2, 265, 261, 3, 2, 2, 2, 265, 262, 3, 2, 2, 2, 265, 263, 3, 2, 2, 2, 265, 264, 3, 2, 2, 2, 266, 273, 3, 2, 2, 2, 267, 268, 12, 9, 2, 2, 268, 269, 5, 68, 35, 2, 269, 270, 5, 56, 29, 10, 270, 272, 3, 2, 2, 2, 271, 267, 3, 2, 2, 2, 272, 275, 3, 2, 2, 2, 273, 271, 3, 2, 2, 2, 273, 274, 3, 2, 2, 2, 274, 57, 3, 2, 2, 2, 275, 273, 3, 2, 2, 2, 276, 277, 7, 22, 2, 2, 277, 278, 5, 56, 29, 2, 278, 279, 7, 23, 2, 2, 279, 59, 3, 2, 2, 2, 280, 281, 5, 66, 34, 2, 281, 282, 5, 56, 29, 2, 282, 61, 3, 2, 2, 2, 283, 284, 5, 36, 19, 2, 284, 285, 7, 24, 2, 2, 285, 286, 5, 56, 29, 2, 286, 287, 7, 25, 2, 2, 287, 63, 3, 2, 2, 2, 288, 289, 9, 3, 2, 2, 289, 65, 3, 2, 2, 2, 290, 291, 9, 4, 2, 2, 291, 67, 3, 2, 2, 2, 292, 293, 9, 5, 2, 2, 293, 69, 3, 2, 2, 2, 23, 79, 85, 100, 108, 119, 132, 141, 144, 155, 168, 180, 188, 193, 211, 232, 240, 244, 253, 256, 265, 273] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 302, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 82, 10, 3, 12, 3, 14, 3, 85, 11, 3, 3, 3, 7, 3, 88, 10, 3, 12, 3, 14, 3, 91, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 105, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 111, 10, 6, 12, 6, 14, 6, 114, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 124, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 137, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 144, 10, 13, 12, 13, 14, 13, 147, 11, 13, 5, 13, 149, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 158, 10, 16, 12, 16, 14, 16, 161, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 171, 10, 17, 12, 17, 14, 17, 174, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 7, 20, 183, 10, 20, 12, 20, 14, 20, 186, 11, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 193, 10, 21, 3, 22, 3, 22, 3, 22, 5, 22, 198, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 5, 23, 206, 10, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 240, 10, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 248, 10, 28, 3, 29, 3, 29, 5, 29, 252, 10, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 7, 30, 259, 10, 30, 12, 30, 14, 30, 262, 11, 30, 5, 30, 264, 10, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 5, 31, 273, 10, 31, 3, 31, 3, 31, 3, 31, 3, 31, 7, 31, 279, 10, 31, 12, 31, 14, 31, 282, 11, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 2, 2, 3, 60, 38, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 2, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 294, 2, 74, 3, 2, 2, 2, 4, 77, 3, 2, 2, 2, 6, 94, 3, 2, 2, 2, 8, 104, 3, 2, 2, 2, 10, 106, 3, 2, 2, 2, 12, 115, 3, 2, 2, 2, 14, 123, 3, 2, 2, 2, 16, 125, 3, 2, 2, 2, 18, 132, 3, 2, 2, 2, 20, 136, 3, 2, 2, 2, 22, 138, 3, 2, 2, 2, 24, 148, 3, 2, 2, 2, 26, 150, 3, 2, 2, 2, 28, 153, 3, 2, 2, 2, 30, 155, 3, 2, 2, 2, 32, 165, 3, 2, 2, 2, 34, 177, 3, 2, 2, 2, 36, 179, 3, 2, 2, 2, 38, 184, 3, 2, 2, 2, 40, 192, 3, 2, 2, 2, 42, 194, 3, 2, 2, 2, 44, 203, 3, 2, 2, 2, 46, 207, 3, 2, 2, 2, 48, 212, 3, 2, 2, 2, 50, 220, 3, 2, 2, 2, 52, 228, 3, 2, 2, 2, 54, 247, 3, 2, 2, 2, 56, 249, 3, 2, 2, 2, 58, 263, 3, 2, 2, 2, 60, 272, 3, 2, 2, 2, 62, 283, 3, 2, 2, 2, 64, 287, 3, 2, 2, 2, 66, 290, 3, 2, 2, 2, 68, 295, 3, 2, 2, 2, 70, 297, 3, 2, 2, 2, 72, 299, 3, 2, 2, 2, 74, 75, 5, 4, 3, 2, 75, 76, 7, 2, 2, 3, 76, 3, 3, 2, 2, 2, 77, 78, 7, 3, 2, 2, 78, 79, 5, 6, 4, 2, 79, 83, 7, 20, 2, 2, 80, 82, 5, 8, 5, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 89, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 88, 5, 14, 8, 2, 87, 86, 3, 2, 2, 2, 88, 91, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 92, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 92, 93, 7, 21, 2, 2, 93, 5, 3, 2, 2, 2, 94, 95, 7, 46, 2, 2, 95, 7, 3, 2, 2, 2, 96, 97, 7, 8, 2, 2, 97, 98, 5, 10, 6, 2, 98, 99, 7, 28, 2, 2, 99, 105, 3, 2, 2, 2, 100, 101, 7, 7, 2, 2, 101, 102, 5, 10, 6, 2, 102, 103, 7, 28, 2, 2, 103, 105, 3, 2, 2, 2, 104, 96, 3, 2, 2, 2, 104, 100, 3, 2, 2, 2, 105, 9, 3, 2, 2, 2, 106, 107, 5, 22, 12, 2, 107, 112, 5, 12, 7, 2, 108, 109, 7, 27, 2, 2, 109, 111, 5, 12, 7, 2, 110, 108, 3, 2, 2, 2, 111, 114, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 112, 113, 3, 2, 2, 2, 113, 11, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 115, 116, 7, 46, 2, 2, 116, 13, 3, 2, 2, 2, 117, 118, 7, 4, 2, 2, 118, 124, 5, 16, 9, 2, 119, 120, 7, 6, 2, 2, 120, 124, 5, 16, 9, 2, 121, 122, 7, 5, 2, 2, 122, 124, 5, 16, 9, 2, 123, 117, 3, 2, 2, 2, 123, 119, 3, 2, 2, 2, 123, 121, 3, 2, 2, 2, 124, 15, 3, 2, 2, 2, 125, 126, 5, 20, 11, 2, 126, 127, 5, 18, 10, 2, 127, 128, 7, 22, 2, 2, 128, 129, 5, 24, 13, 2, 129, 130, 7, 23, 2, 2, 130, 131, 5, 30, 16, 2, 131, 17, 3, 2, 2, 2, 132, 133, 7, 46, 2, 2, 133, 19, 3, 2, 2, 2, 134, 137, 5, 22, 12, 2, 135, 137, 7, 13, 2, 2, 136, 134, 3, 2, 2, 2, 136, 135, 3, 2, 2, 2, 137, 21, 3, 2, 2, 2, 138, 139, 9, 2, 2, 2, 139, 23, 3, 2, 2, 2, 140, 145, 5, 26, 14, 2, 141, 142, 7, 27, 2, 2, 142, 144, 5, 26, 14, 2, 143, 141, 3, 2, 2, 2, 144, 147, 3, 2, 2, 2, 145, 143, 3, 2, 2, 2, 145, 146, 3, 2, 2, 2, 146, 149, 3, 2, 2, 2, 147, 145, 3, 2, 2, 2, 148, 140, 3, 2, 2, 2, 148, 149, 3, 2, 2, 2, 149, 25, 3, 2, 2, 2, 150, 151, 5, 22, 12, 2, 151, 152, 5, 28, 15, 2, 152, 27, 3, 2, 2, 2, 153, 154, 7, 46, 2, 2, 154, 29, 3, 2, 2, 2, 155, 159, 7, 20, 2, 2, 156, 158, 5, 32, 17, 2, 157, 156, 3, 2, 2, 2, 158, 161, 3, 2, 2, 2, 159, 157, 3, 2, 2, 2, 159, 160, 3, 2, 2, 2, 160, 162, 3, 2, 2, 2, 161, 159, 3, 2, 2, 2, 162, 163, 5, 38, 20, 2, 163, 164, 7, 21, 2, 2, 164, 31, 3, 2, 2, 2, 165, 166, 7, 9, 2, 2, 166, 167, 5, 22, 12, 2, 167, 172, 5, 34, 18, 2, 168, 169, 7, 27, 2, 2, 169, 171, 5, 34, 18, 2, 170, 168, 3, 2, 2, 2, 171, 174, 3, 2, 2, 2, 172, 170, 3, 2, 2, 2, 172, 173, 3, 2, 2, 2, 173, 175, 3, 2, 2, 2, 174, 172, 3, 2, 2, 2, 175, 176, 7, 28, 2, 2, 176, 33, 3, 2, 2, 2, 177, 178, 7, 46, 2, 2, 178, 35, 3, 2, 2, 2, 179, 180, 7, 46, 2, 2, 180, 37, 3, 2, 2, 2, 181, 183, 5, 40, 21, 2, 182, 181, 3, 2, 2, 2, 183, 186, 3, 2, 2, 2, 184, 182, 3, 2, 2, 2, 184, 185, 3, 2, 2, 2, 185, 39, 3, 2, 2, 2, 186, 184, 3, 2, 2, 2, 187, 193, 5, 42, 22, 2, 188, 193, 5, 44, 23, 2, 189, 193, 5, 50, 26, 2, 190, 193, 5, 52, 27, 2, 191, 193, 5, 56, 29, 2, 192, 187, 3, 2, 2, 2, 192, 188, 3, 2, 2, 2, 192, 189, 3, 2, 2, 2, 192, 190, 3, 2, 2, 2, 192, 191, 3, 2, 2, 2, 193, 41, 3, 2, 2, 2, 194, 197, 7, 14, 2, 2, 195, 198, 5, 36, 19, 2, 196, 198, 5, 66, 34, 2, 197, 195, 3, 2, 2, 2, 197, 196, 3, 2, 2, 2, 198, 199, 3, 2, 2, 2, 199, 200, 7, 29, 2, 2, 200, 201, 5, 60, 31, 2, 201, 202, 7, 28, 2, 2, 202, 43, 3, 2, 2, 2, 203, 205, 5, 48, 25, 2, 204, 206, 5, 46, 24, 2, 205, 204, 3, 2, 2, 2, 205, 206, 3, 2, 2, 2, 206, 45, 3, 2, 2, 2, 207, 208, 7, 17, 2, 2, 208, 209, 7, 20, 2, 2, 209, 210, 5, 38, 20, 2, 210, 211, 7, 21, 2, 2, 211, 47, 3, 2, 2, 2, 212, 213, 7, 16, 2, 2, 213, 214, 7, 22, 2, 2, 214, 215, 5, 60, 31, 2, 215, 216, 7, 23, 2, 2, 216, 217, 7, 20, 2, 2, 217, 218, 5, 38, 20, 2, 218, 219, 7, 21, 2, 2, 219, 49, 3, 2, 2, 2, 220, 221, 7, 18, 2, 2, 221, 222, 7, 22, 2, 2, 222, 223, 5, 60, 31, 2, 223, 224, 7, 23, 2, 2, 224, 225, 7, 20, 2, 2, 225, 226, 5, 38, 20, 2, 226, 227, 7, 21, 2, 2, 227, 51, 3, 2, 2, 2, 228, 229, 7, 15, 2, 2, 229, 230, 5, 54, 28, 2, 230, 231, 7, 28, 2, 2, 231, 53, 3, 2, 2, 2, 232, 233, 5, 18, 10, 2, 233, 234, 7, 22, 2, 2, 234, 235, 5, 58, 30, 2, 235, 236, 7, 23, 2, 2, 236, 248, 3, 2, 2, 2, 237, 240, 5, 6, 4, 2, 238, 240, 7, 45, 2, 2, 239, 237, 3, 2, 2, 2, 239, 238, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 242, 7, 26, 2, 2, 242, 243, 5, 18, 10, 2, 243, 244, 7, 22, 2, 2, 244, 245, 5, 58, 30, 2, 245, 246, 7, 23, 2, 2, 246, 248, 3, 2, 2, 2, 247, 232, 3, 2, 2, 2, 247, 239, 3, 2, 2, 2, 248, 55, 3, 2, 2, 2, 249, 251, 7, 19, 2, 2, 250, 252, 5, 60, 31, 2, 251, 250, 3, 2, 2, 2, 251, 252, 3, 2, 2, 2, 252, 253, 3, 2, 2, 2, 253, 254, 7, 28, 2, 2, 254, 57, 3, 2, 2, 2, 255, 260, 5, 60, 31, 2, 256, 257, 7, 27, 2, 2, 257, 259, 5, 60, 31, 2, 258, 256, 3, 2, 2, 2, 259, 262, 3, 2, 2, 2, 260, 258, 3, 2, 2, 2, 260, 261, 3, 2, 2, 2, 261, 264, 3, 2, 2, 2, 262, 260, 3, 2, 2, 2, 263, 255, 3, 2, 2, 2, 263, 264, 3, 2, 2, 2, 264, 59, 3, 2, 2, 2, 265, 266, 8, 31, 1, 2, 266, 273, 5, 68, 35, 2, 267, 273, 5, 36, 19, 2, 268, 273, 5, 54, 28, 2, 269, 273, 5, 66, 34, 2, 270, 273, 5, 64, 33, 2, 271, 273, 5, 62, 32, 2, 272, 265, 3, 2, 2, 2, 272, 267, 3, 2, 2, 2, 272, 268, 3, 2, 2, 2, 272, 269, 3, 2, 2, 2, 272, 270, 3, 2, 2, 2, 272, 271, 3, 2, 2, 2, 273, 280, 3, 2, 2, 2, 274, 275, 12, 9, 2, 2, 275, 276, 5, 72, 37, 2, 276, 277, 5, 60, 31, 10, 277, 279, 3, 2, 2, 2, 278, 274, 3, 2, 2, 2, 279, 282, 3, 2, 2, 2, 280, 278, 3, 2, 2, 2, 280, 281, 3, 2, 2, 2, 281, 61, 3, 2, 2, 2, 282, 280, 3, 2, 2, 2, 283, 284, 7, 22, 2, 2, 284, 285, 5, 60, 31, 2, 285, 286, 7, 23, 2, 2, 286, 63, 3, 2, 2, 2, 287, 288, 5, 70, 36, 2, 288, 289, 5, 60, 31, 2, 289, 65, 3, 2, 2, 2, 290, 291, 5, 36, 19, 2, 291, 292, 7, 24, 2, 2, 292, 293, 5, 60, 31, 2, 293, 294, 7, 25, 2, 2, 294, 67, 3, 2, 2, 2, 295, 296, 9, 3, 2, 2, 296, 69, 3, 2, 2, 2, 297, 298, 9, 4, 2, 2, 298, 71, 3, 2, 2, 2, 299, 300, 9, 5, 2, 2, 300, 73, 3, 2, 2, 2, 23, 83, 89, 104, 112, 123, 136, 145, 148, 159, 172, 184, 192, 197, 205, 239, 247, 251, 260, 263, 272, 280] \ No newline at end of file diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts index 3c2fe50c..af837dee 100644 --- a/compiler/src/generated/JackParser.ts +++ b/compiler/src/generated/JackParser.ts @@ -95,29 +95,31 @@ export class JackParser extends Parser { public static readonly RULE_statements = 18; public static readonly RULE_statement = 19; public static readonly RULE_letStatement = 20; - public static readonly RULE_ifStatement = 21; - public static readonly RULE_whileStatement = 22; - public static readonly RULE_doStatement = 23; - public static readonly RULE_subroutineCall = 24; - public static readonly RULE_returnStatement = 25; - public static readonly RULE_expressionList = 26; - public static readonly RULE_expression = 27; - public static readonly RULE_groupedExpression = 28; - public static readonly RULE_unaryOp = 29; - public static readonly RULE_arrayAccess = 30; - public static readonly RULE_constant = 31; - public static readonly RULE_unaryOperator = 32; - public static readonly RULE_binaryOperator = 33; + public static readonly RULE_ifElseStatement = 21; + public static readonly RULE_elseStatement = 22; + public static readonly RULE_ifStatement = 23; + public static readonly RULE_whileStatement = 24; + public static readonly RULE_doStatement = 25; + public static readonly RULE_subroutineCall = 26; + public static readonly RULE_returnStatement = 27; + public static readonly RULE_expressionList = 28; + public static readonly RULE_expression = 29; + public static readonly RULE_groupedExpression = 30; + public static readonly RULE_unaryOp = 31; + public static readonly RULE_arrayAccess = 32; + public static readonly RULE_constant = 33; + public static readonly RULE_unaryOperator = 34; + public static readonly RULE_binaryOperator = 35; // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ "program", "classDeclaration", "className", "classVarDec", "fieldList", "fieldName", "subroutineDeclaration", "subroutineDecWithoutType", "subroutineName", "subroutineReturnType", "varType", "parameterList", "parameter", "parameterName", "subroutineBody", "varDeclaration", "varNameInDeclaration", "varName", - "statements", "statement", "letStatement", "ifStatement", "whileStatement", - "doStatement", "subroutineCall", "returnStatement", "expressionList", - "expression", "groupedExpression", "unaryOp", "arrayAccess", "constant", - "unaryOperator", "binaryOperator", + "statements", "statement", "letStatement", "ifElseStatement", "elseStatement", + "ifStatement", "whileStatement", "doStatement", "subroutineCall", "returnStatement", + "expressionList", "expression", "groupedExpression", "unaryOp", "arrayAccess", + "constant", "unaryOperator", "binaryOperator", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -170,9 +172,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 68; + this.state = 72; this.classDeclaration(); - this.state = 69; + this.state = 73; this.match(JackParser.EOF); } } @@ -198,41 +200,41 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 71; + this.state = 75; this.match(JackParser.CLASS); - this.state = 72; + this.state = 76; this.className(); - this.state = 73; - this.match(JackParser.LBRACE); this.state = 77; + this.match(JackParser.LBRACE); + this.state = 81; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.FIELD || _la === JackParser.STATIC) { { { - this.state = 74; + this.state = 78; this.classVarDec(); } } - this.state = 79; + this.state = 83; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 83; + this.state = 87; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0)) { { { - this.state = 80; + this.state = 84; this.subroutineDeclaration(); } } - this.state = 85; + this.state = 89; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 86; + this.state = 90; this.match(JackParser.RBRACE); } } @@ -257,7 +259,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 88; + this.state = 92; this.match(JackParser.IDENTIFIER); } } @@ -280,18 +282,18 @@ export class JackParser extends Parser { let _localctx: ClassVarDecContext = new ClassVarDecContext(this._ctx, this.state); this.enterRule(_localctx, 6, JackParser.RULE_classVarDec); try { - this.state = 98; + this.state = 102; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.STATIC: _localctx = new StaticFieldDeclarationContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 90; + this.state = 94; this.match(JackParser.STATIC); - this.state = 91; + this.state = 95; this.fieldList(); - this.state = 92; + this.state = 96; this.match(JackParser.SEMICOLON); } break; @@ -299,11 +301,11 @@ export class JackParser extends Parser { _localctx = new FieldDeclarationContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 94; + this.state = 98; this.match(JackParser.FIELD); - this.state = 95; + this.state = 99; this.fieldList(); - this.state = 96; + this.state = 100; this.match(JackParser.SEMICOLON); } break; @@ -333,23 +335,23 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 100; + this.state = 104; this.varType(); - this.state = 101; + this.state = 105; this.fieldName(); - this.state = 106; + this.state = 110; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 102; + this.state = 106; this.match(JackParser.COMMA); - this.state = 103; + this.state = 107; this.fieldName(); } } - this.state = 108; + this.state = 112; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -376,7 +378,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 109; + this.state = 113; this.match(JackParser.IDENTIFIER); } } @@ -399,16 +401,16 @@ export class JackParser extends Parser { let _localctx: SubroutineDeclarationContext = new SubroutineDeclarationContext(this._ctx, this.state); this.enterRule(_localctx, 12, JackParser.RULE_subroutineDeclaration); try { - this.state = 117; + this.state = 121; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.CONSTRUCTOR: _localctx = new ConstructorContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 111; + this.state = 115; this.match(JackParser.CONSTRUCTOR); - this.state = 112; + this.state = 116; this.subroutineDecWithoutType(); } break; @@ -416,9 +418,9 @@ export class JackParser extends Parser { _localctx = new MethodContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 113; + this.state = 117; this.match(JackParser.METHOD); - this.state = 114; + this.state = 118; this.subroutineDecWithoutType(); } break; @@ -426,9 +428,9 @@ export class JackParser extends Parser { _localctx = new FunctionContext(_localctx); this.enterOuterAlt(_localctx, 3); { - this.state = 115; + this.state = 119; this.match(JackParser.FUNCTION); - this.state = 116; + this.state = 120; this.subroutineDecWithoutType(); } break; @@ -457,17 +459,17 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 119; + this.state = 123; this.subroutineReturnType(); - this.state = 120; + this.state = 124; this.subroutineName(); - this.state = 121; + this.state = 125; this.match(JackParser.LPAREN); - this.state = 122; + this.state = 126; this.parameterList(); - this.state = 123; + this.state = 127; this.match(JackParser.RPAREN); - this.state = 124; + this.state = 128; this.subroutineBody(); } } @@ -492,7 +494,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 126; + this.state = 130; this.match(JackParser.IDENTIFIER); } } @@ -515,7 +517,7 @@ export class JackParser extends Parser { let _localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this._ctx, this.state); this.enterRule(_localctx, 18, JackParser.RULE_subroutineReturnType); try { - this.state = 130; + this.state = 134; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.INT: @@ -524,14 +526,14 @@ export class JackParser extends Parser { case JackParser.IDENTIFIER: this.enterOuterAlt(_localctx, 1); { - this.state = 128; + this.state = 132; this.varType(); } break; case JackParser.VOID: this.enterOuterAlt(_localctx, 2); { - this.state = 129; + this.state = 133; this.match(JackParser.VOID); } break; @@ -561,7 +563,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 132; + this.state = 136; _la = this._input.LA(1); if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER)) { this._errHandler.recoverInline(this); @@ -597,26 +599,26 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 142; + this.state = 146; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER) { { - this.state = 134; + this.state = 138; this.parameter(); - this.state = 139; + this.state = 143; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 135; + this.state = 139; this.match(JackParser.COMMA); - this.state = 136; + this.state = 140; this.parameter(); } } - this.state = 141; + this.state = 145; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -646,9 +648,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 144; + this.state = 148; this.varType(); - this.state = 145; + this.state = 149; this.parameterName(); } } @@ -673,7 +675,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 147; + this.state = 151; this.match(JackParser.IDENTIFIER); } } @@ -699,25 +701,25 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 149; - this.match(JackParser.LBRACE); this.state = 153; + this.match(JackParser.LBRACE); + this.state = 157; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.VAR) { { { - this.state = 150; + this.state = 154; this.varDeclaration(); } } - this.state = 155; + this.state = 159; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 156; + this.state = 160; this.statements(); - this.state = 157; + this.state = 161; this.match(JackParser.RBRACE); } } @@ -743,29 +745,29 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 159; + this.state = 163; this.match(JackParser.VAR); - this.state = 160; + this.state = 164; this.varType(); - this.state = 161; + this.state = 165; this.varNameInDeclaration(); - this.state = 166; + this.state = 170; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 162; + this.state = 166; this.match(JackParser.COMMA); - this.state = 163; + this.state = 167; this.varNameInDeclaration(); } } - this.state = 168; + this.state = 172; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 169; + this.state = 173; this.match(JackParser.SEMICOLON); } } @@ -790,7 +792,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 171; + this.state = 175; this.match(JackParser.IDENTIFIER); } } @@ -815,7 +817,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 173; + this.state = 177; this.match(JackParser.IDENTIFIER); } } @@ -841,17 +843,17 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 178; + this.state = 182; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.LET) | (1 << JackParser.DO) | (1 << JackParser.IF) | (1 << JackParser.WHILE) | (1 << JackParser.RETURN))) !== 0)) { { { - this.state = 175; + this.state = 179; this.statement(); } } - this.state = 180; + this.state = 184; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -876,41 +878,41 @@ export class JackParser extends Parser { let _localctx: StatementContext = new StatementContext(this._ctx, this.state); this.enterRule(_localctx, 38, JackParser.RULE_statement); try { - this.state = 186; + this.state = 190; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.LET: this.enterOuterAlt(_localctx, 1); { - this.state = 181; + this.state = 185; this.letStatement(); } break; case JackParser.IF: this.enterOuterAlt(_localctx, 2); { - this.state = 182; - this.ifStatement(); + this.state = 186; + this.ifElseStatement(); } break; case JackParser.WHILE: this.enterOuterAlt(_localctx, 3); { - this.state = 183; + this.state = 187; this.whileStatement(); } break; case JackParser.DO: this.enterOuterAlt(_localctx, 4); { - this.state = 184; + this.state = 188; this.doStatement(); } break; case JackParser.RETURN: this.enterOuterAlt(_localctx, 5); { - this.state = 185; + this.state = 189; this.returnStatement(); } break; @@ -939,30 +941,30 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 188; + this.state = 192; this.match(JackParser.LET); - this.state = 191; + this.state = 195; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 12, this._ctx) ) { case 1: { - this.state = 189; + this.state = 193; this.varName(); } break; case 2: { - this.state = 190; + this.state = 194; this.arrayAccess(); } break; } - this.state = 193; + this.state = 197; this.match(JackParser.EQUALS); - this.state = 194; + this.state = 198; this.expression(0); - this.state = 195; + this.state = 199; this.match(JackParser.SEMICOLON); } } @@ -981,40 +983,22 @@ export class JackParser extends Parser { return _localctx; } // @RuleVersion(0) - public ifStatement(): IfStatementContext { - let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 42, JackParser.RULE_ifStatement); + public ifElseStatement(): IfElseStatementContext { + let _localctx: IfElseStatementContext = new IfElseStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 42, JackParser.RULE_ifElseStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 197; - this.match(JackParser.IF); - this.state = 198; - this.match(JackParser.LPAREN); - this.state = 199; - this.expression(0); - this.state = 200; - this.match(JackParser.RPAREN); this.state = 201; - this.match(JackParser.LBRACE); - this.state = 202; - this.statements(); + this.ifStatement(); this.state = 203; - this.match(JackParser.RBRACE); - this.state = 209; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === JackParser.ELSE) { { - this.state = 204; - this.match(JackParser.ELSE); - this.state = 205; - this.match(JackParser.LBRACE); - this.state = 206; - this.statements(); - this.state = 207; - this.match(JackParser.RBRACE); + this.state = 202; + this.elseStatement(); } } @@ -1035,25 +1019,93 @@ export class JackParser extends Parser { return _localctx; } // @RuleVersion(0) + public elseStatement(): ElseStatementContext { + let _localctx: ElseStatementContext = new ElseStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 44, JackParser.RULE_elseStatement); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 205; + this.match(JackParser.ELSE); + this.state = 206; + this.match(JackParser.LBRACE); + this.state = 207; + this.statements(); + this.state = 208; + this.match(JackParser.RBRACE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public ifStatement(): IfStatementContext { + let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 46, JackParser.RULE_ifStatement); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 210; + this.match(JackParser.IF); + this.state = 211; + this.match(JackParser.LPAREN); + this.state = 212; + this.expression(0); + this.state = 213; + this.match(JackParser.RPAREN); + this.state = 214; + this.match(JackParser.LBRACE); + this.state = 215; + this.statements(); + this.state = 216; + this.match(JackParser.RBRACE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) public whileStatement(): WhileStatementContext { let _localctx: WhileStatementContext = new WhileStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 44, JackParser.RULE_whileStatement); + this.enterRule(_localctx, 48, JackParser.RULE_whileStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 211; + this.state = 218; this.match(JackParser.WHILE); - this.state = 212; + this.state = 219; this.match(JackParser.LPAREN); - this.state = 213; + this.state = 220; this.expression(0); - this.state = 214; + this.state = 221; this.match(JackParser.RPAREN); - this.state = 215; + this.state = 222; this.match(JackParser.LBRACE); - this.state = 216; + this.state = 223; this.statements(); - this.state = 217; + this.state = 224; this.match(JackParser.RBRACE); } } @@ -1074,15 +1126,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public doStatement(): DoStatementContext { let _localctx: DoStatementContext = new DoStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 46, JackParser.RULE_doStatement); + this.enterRule(_localctx, 50, JackParser.RULE_doStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 219; + this.state = 226; this.match(JackParser.DO); - this.state = 220; + this.state = 227; this.subroutineCall(); - this.state = 221; + this.state = 228; this.match(JackParser.SEMICOLON); } } @@ -1103,21 +1155,21 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineCall(): SubroutineCallContext { let _localctx: SubroutineCallContext = new SubroutineCallContext(this._ctx, this.state); - this.enterRule(_localctx, 48, JackParser.RULE_subroutineCall); + this.enterRule(_localctx, 52, JackParser.RULE_subroutineCall); try { - this.state = 238; + this.state = 245; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 15, this._ctx) ) { case 1: this.enterOuterAlt(_localctx, 1); { - this.state = 223; + this.state = 230; this.subroutineName(); - this.state = 224; + this.state = 231; this.match(JackParser.LPAREN); - this.state = 225; + this.state = 232; this.expressionList(); - this.state = 226; + this.state = 233; this.match(JackParser.RPAREN); } break; @@ -1125,33 +1177,33 @@ export class JackParser extends Parser { case 2: this.enterOuterAlt(_localctx, 2); { - this.state = 230; + this.state = 237; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.IDENTIFIER: { - this.state = 228; + this.state = 235; this.className(); } break; case JackParser.THIS_LITERAL: { - this.state = 229; + this.state = 236; this.match(JackParser.THIS_LITERAL); } break; default: throw new NoViableAltException(this); } - this.state = 232; + this.state = 239; this.match(JackParser.DOT); - this.state = 233; + this.state = 240; this.subroutineName(); - this.state = 234; + this.state = 241; this.match(JackParser.LPAREN); - this.state = 235; + this.state = 242; this.expressionList(); - this.state = 236; + this.state = 243; this.match(JackParser.RPAREN); } break; @@ -1174,24 +1226,24 @@ export class JackParser extends Parser { // @RuleVersion(0) public returnStatement(): ReturnStatementContext { let _localctx: ReturnStatementContext = new ReturnStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 50, JackParser.RULE_returnStatement); + this.enterRule(_localctx, 54, JackParser.RULE_returnStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 240; + this.state = 247; this.match(JackParser.RETURN); - this.state = 242; + this.state = 249; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 241; + this.state = 248; this.expression(0); } } - this.state = 244; + this.state = 251; this.match(JackParser.SEMICOLON); } } @@ -1212,31 +1264,31 @@ export class JackParser extends Parser { // @RuleVersion(0) public expressionList(): ExpressionListContext { let _localctx: ExpressionListContext = new ExpressionListContext(this._ctx, this.state); - this.enterRule(_localctx, 52, JackParser.RULE_expressionList); + this.enterRule(_localctx, 56, JackParser.RULE_expressionList); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 254; + this.state = 261; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 246; + this.state = 253; this.expression(0); - this.state = 251; + this.state = 258; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 247; + this.state = 254; this.match(JackParser.COMMA); - this.state = 248; + this.state = 255; this.expression(0); } } - this.state = 253; + this.state = 260; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1272,59 +1324,59 @@ export class JackParser extends Parser { let _parentState: number = this.state; let _localctx: ExpressionContext = new ExpressionContext(this._ctx, _parentState); let _prevctx: ExpressionContext = _localctx; - let _startState: number = 54; - this.enterRecursionRule(_localctx, 54, JackParser.RULE_expression, _p); + let _startState: number = 58; + this.enterRecursionRule(_localctx, 58, JackParser.RULE_expression, _p); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 263; + this.state = 270; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 19, this._ctx) ) { case 1: { - this.state = 257; + this.state = 264; this.constant(); } break; case 2: { - this.state = 258; + this.state = 265; this.varName(); } break; case 3: { - this.state = 259; + this.state = 266; this.subroutineCall(); } break; case 4: { - this.state = 260; + this.state = 267; this.arrayAccess(); } break; case 5: { - this.state = 261; + this.state = 268; this.unaryOp(); } break; case 6: { - this.state = 262; + this.state = 269; this.groupedExpression(); } break; } this._ctx._stop = this._input.tryLT(-1); - this.state = 271; + this.state = 278; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -1338,18 +1390,18 @@ export class JackParser extends Parser { _localctx = new ExpressionContext(_parentctx, _parentState); _localctx._binaryOperation = _prevctx; this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); - this.state = 265; + this.state = 272; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 266; + this.state = 273; this.binaryOperator(); - this.state = 267; + this.state = 274; this.expression(8); } } } - this.state = 273; + this.state = 280; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); } @@ -1372,15 +1424,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public groupedExpression(): GroupedExpressionContext { let _localctx: GroupedExpressionContext = new GroupedExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 56, JackParser.RULE_groupedExpression); + this.enterRule(_localctx, 60, JackParser.RULE_groupedExpression); try { this.enterOuterAlt(_localctx, 1); { - this.state = 274; + this.state = 281; this.match(JackParser.LPAREN); - this.state = 275; + this.state = 282; this.expression(0); - this.state = 276; + this.state = 283; this.match(JackParser.RPAREN); } } @@ -1401,13 +1453,13 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOp(): UnaryOpContext { let _localctx: UnaryOpContext = new UnaryOpContext(this._ctx, this.state); - this.enterRule(_localctx, 58, JackParser.RULE_unaryOp); + this.enterRule(_localctx, 62, JackParser.RULE_unaryOp); try { this.enterOuterAlt(_localctx, 1); { - this.state = 278; + this.state = 285; this.unaryOperator(); - this.state = 279; + this.state = 286; this.expression(0); } } @@ -1428,17 +1480,17 @@ export class JackParser extends Parser { // @RuleVersion(0) public arrayAccess(): ArrayAccessContext { let _localctx: ArrayAccessContext = new ArrayAccessContext(this._ctx, this.state); - this.enterRule(_localctx, 60, JackParser.RULE_arrayAccess); + this.enterRule(_localctx, 64, JackParser.RULE_arrayAccess); try { this.enterOuterAlt(_localctx, 1); { - this.state = 281; + this.state = 288; this.varName(); - this.state = 282; + this.state = 289; this.match(JackParser.LBRACKET); - this.state = 283; + this.state = 290; this.expression(0); - this.state = 284; + this.state = 291; this.match(JackParser.RBRACKET); } } @@ -1459,12 +1511,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public constant(): ConstantContext { let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 62, JackParser.RULE_constant); + this.enterRule(_localctx, 66, JackParser.RULE_constant); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 286; + this.state = 293; _la = this._input.LA(1); if (!(((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & ((1 << (JackParser.INTEGER_LITERAL - 40)) | (1 << (JackParser.BOOLEAN_LITERAL - 40)) | (1 << (JackParser.NULL_LITERAL - 40)) | (1 << (JackParser.THIS_LITERAL - 40)) | (1 << (JackParser.STRING_LITERAL - 40)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1495,12 +1547,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOperator(): UnaryOperatorContext { let _localctx: UnaryOperatorContext = new UnaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 64, JackParser.RULE_unaryOperator); + this.enterRule(_localctx, 68, JackParser.RULE_unaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 288; + this.state = 295; _la = this._input.LA(1); if (!(_la === JackParser.MINUS || _la === JackParser.TILDE)) { this._errHandler.recoverInline(this); @@ -1531,12 +1583,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public binaryOperator(): BinaryOperatorContext { let _localctx: BinaryOperatorContext = new BinaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 66, JackParser.RULE_binaryOperator); + this.enterRule(_localctx, 70, JackParser.RULE_binaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 290; + this.state = 297; _la = this._input.LA(1); if (!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & ((1 << (JackParser.EQUALS - 27)) | (1 << (JackParser.PLUS - 27)) | (1 << (JackParser.MINUS - 27)) | (1 << (JackParser.MUL - 27)) | (1 << (JackParser.DIV - 27)) | (1 << (JackParser.AND - 27)) | (1 << (JackParser.OR - 27)) | (1 << (JackParser.LESS_THAN - 27)) | (1 << (JackParser.GREATER_THAN - 27)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1567,7 +1619,7 @@ export class JackParser extends Parser { public override sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 27: + case 29: return this.expression_sempred(_localctx as ExpressionContext, predIndex); } return true; @@ -1581,134 +1633,136 @@ export class JackParser extends Parser { } public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u0127\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u012E\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + - "\t#\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x07\x03N\n" + - "\x03\f\x03\x0E\x03Q\v\x03\x03\x03\x07\x03T\n\x03\f\x03\x0E\x03W\v\x03" + - "\x03\x03\x03\x03\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05" + - "\x03\x05\x03\x05\x03\x05\x05\x05e\n\x05\x03\x06\x03\x06\x03\x06\x03\x06" + - "\x07\x06k\n\x06\f\x06\x0E\x06n\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b" + - "\x03\b\x03\b\x03\b\x05\bx\n\b\x03\t\x03\t\x03\t\x03\t\x03\t\x03\t\x03" + - "\t\x03\n\x03\n\x03\v\x03\v\x05\v\x85\n\v\x03\f\x03\f\x03\r\x03\r\x03\r" + - "\x07\r\x8C\n\r\f\r\x0E\r\x8F\v\r\x05\r\x91\n\r\x03\x0E\x03\x0E\x03\x0E" + - "\x03\x0F\x03\x0F\x03\x10\x03\x10\x07\x10\x9A\n\x10\f\x10\x0E\x10\x9D\v" + - "\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03\x11\x07" + - "\x11\xA7\n\x11\f\x11\x0E\x11\xAA\v\x11\x03\x11\x03\x11\x03\x12\x03\x12" + - "\x03\x13\x03\x13\x03\x14\x07\x14\xB3\n\x14\f\x14\x0E\x14\xB6\v\x14\x03" + - "\x15\x03\x15\x03\x15\x03\x15\x03\x15\x05\x15\xBD\n\x15\x03\x16\x03\x16" + - "\x03\x16\x05\x16\xC2\n\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03\x17\x03" + - "\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03" + - "\x17\x03\x17\x05\x17\xD4\n\x17\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18" + - "\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x1A\x03\x1A" + - "\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x05\x1A\xE9\n\x1A\x03\x1A\x03" + - "\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x05\x1A\xF1\n\x1A\x03\x1B\x03\x1B" + - "\x05\x1B\xF5\n\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x07\x1C\xFC" + - "\n\x1C\f\x1C\x0E\x1C\xFF\v\x1C\x05\x1C\u0101\n\x1C\x03\x1D\x03\x1D\x03" + - "\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x05\x1D\u010A\n\x1D\x03\x1D\x03\x1D" + - "\x03\x1D\x03\x1D\x07\x1D\u0110\n\x1D\f\x1D\x0E\x1D\u0113\v\x1D\x03\x1E" + - "\x03\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03\x1F\x03 \x03 \x03 \x03 \x03" + - " \x03!\x03!\x03\"\x03\"\x03#\x03#\x03#\x02\x02\x038$\x02\x02\x04\x02\x06" + - "\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02" + - "\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x02" + - "2\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02D\x02\x02\x06\x04\x02\n\f" + - "..\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02\x1D#%&\x02\u0121\x02F\x03\x02" + - "\x02\x02\x04I\x03\x02\x02\x02\x06Z\x03\x02\x02\x02\bd\x03\x02\x02\x02" + - "\nf\x03\x02\x02\x02\fo\x03\x02\x02\x02\x0Ew\x03\x02\x02\x02\x10y\x03\x02" + - "\x02\x02\x12\x80\x03\x02\x02\x02\x14\x84\x03\x02\x02\x02\x16\x86\x03\x02" + - "\x02\x02\x18\x90\x03\x02\x02\x02\x1A\x92\x03\x02\x02\x02\x1C\x95\x03\x02" + - "\x02\x02\x1E\x97\x03\x02\x02\x02 \xA1\x03\x02\x02\x02\"\xAD\x03\x02\x02" + - "\x02$\xAF\x03\x02\x02\x02&\xB4\x03\x02\x02\x02(\xBC\x03\x02\x02\x02*\xBE" + - "\x03\x02\x02\x02,\xC7\x03\x02\x02\x02.\xD5\x03\x02\x02\x020\xDD\x03\x02" + - "\x02\x022\xF0\x03\x02\x02\x024\xF2\x03\x02\x02\x026\u0100\x03\x02\x02" + - "\x028\u0109\x03\x02\x02\x02:\u0114\x03\x02\x02\x02<\u0118\x03\x02\x02" + - "\x02>\u011B\x03\x02\x02\x02@\u0120\x03\x02\x02\x02B\u0122\x03\x02\x02" + - "\x02D\u0124\x03\x02\x02\x02FG\x05\x04\x03\x02GH\x07\x02\x02\x03H\x03\x03" + - "\x02\x02\x02IJ\x07\x03\x02\x02JK\x05\x06\x04\x02KO\x07\x14\x02\x02LN\x05" + - "\b\x05\x02ML\x03\x02\x02\x02NQ\x03\x02\x02\x02OM\x03\x02\x02\x02OP\x03" + - "\x02\x02\x02PU\x03\x02\x02\x02QO\x03\x02\x02\x02RT\x05\x0E\b\x02SR\x03" + - "\x02\x02\x02TW\x03\x02\x02\x02US\x03\x02\x02\x02UV\x03\x02\x02\x02VX\x03" + - "\x02\x02\x02WU\x03\x02\x02\x02XY\x07\x15\x02\x02Y\x05\x03\x02\x02\x02" + - "Z[\x07.\x02\x02[\x07\x03\x02\x02\x02\\]\x07\b\x02\x02]^\x05\n\x06\x02" + - "^_\x07\x1C\x02\x02_e\x03\x02\x02\x02`a\x07\x07\x02\x02ab\x05\n\x06\x02" + - "bc\x07\x1C\x02\x02ce\x03\x02\x02\x02d\\\x03\x02\x02\x02d`\x03\x02\x02" + - "\x02e\t\x03\x02\x02\x02fg\x05\x16\f\x02gl\x05\f\x07\x02hi\x07\x1B\x02" + - "\x02ik\x05\f\x07\x02jh\x03\x02\x02\x02kn\x03\x02\x02\x02lj\x03\x02\x02" + - "\x02lm\x03\x02\x02\x02m\v\x03\x02\x02\x02nl\x03\x02\x02\x02op\x07.\x02" + - "\x02p\r\x03\x02\x02\x02qr\x07\x04\x02\x02rx\x05\x10\t\x02st\x07\x06\x02" + - "\x02tx\x05\x10\t\x02uv\x07\x05\x02\x02vx\x05\x10\t\x02wq\x03\x02\x02\x02" + - "ws\x03\x02\x02\x02wu\x03\x02\x02\x02x\x0F\x03\x02\x02\x02yz\x05\x14\v" + - "\x02z{\x05\x12\n\x02{|\x07\x16\x02\x02|}\x05\x18\r\x02}~\x07\x17\x02\x02" + - "~\x7F\x05\x1E\x10\x02\x7F\x11\x03\x02\x02\x02\x80\x81\x07.\x02\x02\x81" + - "\x13\x03\x02\x02\x02\x82\x85\x05\x16\f\x02\x83\x85\x07\r\x02\x02\x84\x82" + - "\x03\x02\x02\x02\x84\x83\x03\x02\x02\x02\x85\x15\x03\x02\x02\x02\x86\x87" + - "\t\x02\x02\x02\x87\x17\x03\x02\x02\x02\x88\x8D\x05\x1A\x0E\x02\x89\x8A" + - "\x07\x1B\x02\x02\x8A\x8C\x05\x1A\x0E\x02\x8B\x89\x03\x02\x02\x02\x8C\x8F" + - "\x03\x02\x02\x02\x8D\x8B\x03\x02\x02\x02\x8D\x8E\x03\x02\x02\x02\x8E\x91" + - "\x03\x02\x02\x02\x8F\x8D\x03\x02\x02\x02\x90\x88\x03\x02\x02\x02\x90\x91" + - "\x03\x02\x02\x02\x91\x19\x03\x02\x02\x02\x92\x93\x05\x16\f\x02\x93\x94" + - "\x05\x1C\x0F\x02\x94\x1B\x03\x02\x02\x02\x95\x96\x07.\x02\x02\x96\x1D" + - "\x03\x02\x02\x02\x97\x9B\x07\x14\x02\x02\x98\x9A\x05 \x11\x02\x99\x98" + - "\x03\x02\x02\x02\x9A\x9D\x03\x02\x02\x02\x9B\x99\x03\x02\x02\x02\x9B\x9C" + - "\x03\x02\x02\x02\x9C\x9E\x03\x02\x02\x02\x9D\x9B\x03\x02\x02\x02\x9E\x9F" + - "\x05&\x14\x02\x9F\xA0\x07\x15\x02\x02\xA0\x1F\x03\x02\x02\x02\xA1\xA2" + - "\x07\t\x02\x02\xA2\xA3\x05\x16\f\x02\xA3\xA8\x05\"\x12\x02\xA4\xA5\x07" + - "\x1B\x02\x02\xA5\xA7\x05\"\x12\x02\xA6\xA4\x03\x02\x02\x02\xA7\xAA\x03" + - "\x02\x02\x02\xA8\xA6\x03\x02\x02\x02\xA8\xA9\x03\x02\x02\x02\xA9\xAB\x03" + - "\x02\x02\x02\xAA\xA8\x03\x02\x02\x02\xAB\xAC\x07\x1C\x02\x02\xAC!\x03" + - "\x02\x02\x02\xAD\xAE\x07.\x02\x02\xAE#\x03\x02\x02\x02\xAF\xB0\x07.\x02" + - "\x02\xB0%\x03\x02\x02\x02\xB1\xB3\x05(\x15\x02\xB2\xB1\x03\x02\x02\x02" + - "\xB3\xB6\x03\x02\x02\x02\xB4\xB2\x03\x02\x02\x02\xB4\xB5\x03\x02\x02\x02" + - "\xB5\'\x03\x02\x02\x02\xB6\xB4\x03\x02\x02\x02\xB7\xBD\x05*\x16\x02\xB8" + - "\xBD\x05,\x17\x02\xB9\xBD\x05.\x18\x02\xBA\xBD\x050\x19\x02\xBB\xBD\x05" + - "4\x1B\x02\xBC\xB7\x03\x02\x02\x02\xBC\xB8\x03\x02\x02\x02\xBC\xB9\x03" + - "\x02\x02\x02\xBC\xBA\x03\x02\x02\x02\xBC\xBB\x03\x02\x02\x02\xBD)\x03" + - "\x02\x02\x02\xBE\xC1\x07\x0E\x02\x02\xBF\xC2\x05$\x13\x02\xC0\xC2\x05" + - "> \x02\xC1\xBF\x03\x02\x02\x02\xC1\xC0\x03\x02\x02\x02\xC2\xC3\x03\x02" + - "\x02\x02\xC3\xC4\x07\x1D\x02\x02\xC4\xC5\x058\x1D\x02\xC5\xC6\x07\x1C" + - "\x02\x02\xC6+\x03\x02\x02\x02\xC7\xC8\x07\x10\x02\x02\xC8\xC9\x07\x16" + - "\x02\x02\xC9\xCA\x058\x1D\x02\xCA\xCB\x07\x17\x02\x02\xCB\xCC\x07\x14" + - "\x02\x02\xCC\xCD\x05&\x14\x02\xCD\xD3\x07\x15\x02\x02\xCE\xCF\x07\x11" + - "\x02\x02\xCF\xD0\x07\x14\x02\x02\xD0\xD1\x05&\x14\x02\xD1\xD2\x07\x15" + - "\x02\x02\xD2\xD4\x03\x02\x02\x02\xD3\xCE\x03\x02\x02\x02\xD3\xD4\x03\x02" + - "\x02\x02\xD4-\x03\x02\x02\x02\xD5\xD6\x07\x12\x02\x02\xD6\xD7\x07\x16" + - "\x02\x02\xD7\xD8\x058\x1D\x02\xD8\xD9\x07\x17\x02\x02\xD9\xDA\x07\x14" + - "\x02\x02\xDA\xDB\x05&\x14\x02\xDB\xDC\x07\x15\x02\x02\xDC/\x03\x02\x02" + - "\x02\xDD\xDE\x07\x0F\x02\x02\xDE\xDF\x052\x1A\x02\xDF\xE0\x07\x1C\x02" + - "\x02\xE01\x03\x02\x02\x02\xE1\xE2\x05\x12\n\x02\xE2\xE3\x07\x16\x02\x02" + - "\xE3\xE4\x056\x1C\x02\xE4\xE5\x07\x17\x02\x02\xE5\xF1\x03\x02\x02\x02" + - "\xE6\xE9\x05\x06\x04\x02\xE7\xE9\x07-\x02\x02\xE8\xE6\x03\x02\x02\x02" + - "\xE8\xE7\x03\x02\x02\x02\xE9\xEA\x03\x02\x02\x02\xEA\xEB\x07\x1A\x02\x02" + - "\xEB\xEC\x05\x12\n\x02\xEC\xED\x07\x16\x02\x02\xED\xEE\x056\x1C\x02\xEE" + - "\xEF\x07\x17\x02\x02\xEF\xF1\x03\x02\x02\x02\xF0\xE1\x03\x02\x02\x02\xF0" + - "\xE8\x03\x02\x02\x02\xF13\x03\x02\x02\x02\xF2\xF4\x07\x13\x02\x02\xF3" + - "\xF5\x058\x1D\x02\xF4\xF3\x03\x02\x02\x02\xF4\xF5\x03\x02\x02\x02\xF5" + - "\xF6\x03\x02\x02\x02\xF6\xF7\x07\x1C\x02\x02\xF75\x03\x02\x02\x02\xF8" + - "\xFD\x058\x1D\x02\xF9\xFA\x07\x1B\x02\x02\xFA\xFC\x058\x1D\x02\xFB\xF9" + - "\x03\x02\x02\x02\xFC\xFF\x03\x02\x02\x02\xFD\xFB\x03\x02\x02\x02\xFD\xFE" + - "\x03\x02\x02\x02\xFE\u0101\x03\x02\x02\x02\xFF\xFD\x03\x02\x02\x02\u0100" + - "\xF8\x03\x02\x02\x02\u0100\u0101\x03\x02\x02\x02\u01017\x03\x02\x02\x02" + - "\u0102\u0103\b\x1D\x01\x02\u0103\u010A\x05@!\x02\u0104\u010A\x05$\x13" + - "\x02\u0105\u010A\x052\x1A\x02\u0106\u010A\x05> \x02\u0107\u010A\x05<\x1F" + - "\x02\u0108\u010A\x05:\x1E\x02\u0109\u0102\x03\x02\x02\x02\u0109\u0104" + - "\x03\x02\x02\x02\u0109\u0105\x03\x02\x02\x02\u0109\u0106\x03\x02\x02\x02" + - "\u0109\u0107\x03\x02\x02\x02\u0109\u0108\x03\x02\x02\x02\u010A\u0111\x03" + - "\x02\x02\x02\u010B\u010C\f\t\x02\x02\u010C\u010D\x05D#\x02\u010D\u010E" + - "\x058\x1D\n\u010E\u0110\x03\x02\x02\x02\u010F\u010B\x03\x02\x02\x02\u0110" + - "\u0113\x03\x02\x02\x02\u0111\u010F\x03\x02\x02\x02\u0111\u0112\x03\x02" + - "\x02\x02\u01129\x03\x02\x02\x02\u0113\u0111\x03\x02\x02\x02\u0114\u0115" + - "\x07\x16\x02\x02\u0115\u0116\x058\x1D\x02\u0116\u0117\x07\x17\x02\x02" + - "\u0117;\x03\x02\x02\x02\u0118\u0119\x05B\"\x02\u0119\u011A\x058\x1D\x02" + - "\u011A=\x03\x02\x02\x02\u011B\u011C\x05$\x13\x02\u011C\u011D\x07\x18\x02" + - "\x02\u011D\u011E\x058\x1D\x02\u011E\u011F\x07\x19\x02\x02\u011F?\x03\x02" + - "\x02\x02\u0120\u0121\t\x03\x02\x02\u0121A\x03\x02\x02\x02\u0122\u0123" + - "\t\x04\x02\x02\u0123C\x03\x02\x02\x02\u0124\u0125\t\x05\x02\x02\u0125" + - "E\x03\x02\x02\x02\x17OUdlw\x84\x8D\x90\x9B\xA8\xB4\xBC\xC1\xD3\xE8\xF0" + - "\xF4\xFD\u0100\u0109\u0111"; + "\t#\x04$\t$\x04%\t%\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03" + + "\x03\x07\x03R\n\x03\f\x03\x0E\x03U\v\x03\x03\x03\x07\x03X\n\x03\f\x03" + + "\x0E\x03[\v\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05" + + "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05i\n\x05\x03\x06\x03\x06" + + "\x03\x06\x03\x06\x07\x06o\n\x06\f\x06\x0E\x06r\v\x06\x03\x07\x03\x07\x03" + + "\b\x03\b\x03\b\x03\b\x03\b\x03\b\x05\b|\n\b\x03\t\x03\t\x03\t\x03\t\x03" + + "\t\x03\t\x03\t\x03\n\x03\n\x03\v\x03\v\x05\v\x89\n\v\x03\f\x03\f\x03\r" + + "\x03\r\x03\r\x07\r\x90\n\r\f\r\x0E\r\x93\v\r\x05\r\x95\n\r\x03\x0E\x03" + + "\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x10\x03\x10\x07\x10\x9E\n\x10\f\x10\x0E" + + "\x10\xA1\v\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11" + + "\x03\x11\x07\x11\xAB\n\x11\f\x11\x0E\x11\xAE\v\x11\x03\x11\x03\x11\x03" + + "\x12\x03\x12\x03\x13\x03\x13\x03\x14\x07\x14\xB7\n\x14\f\x14\x0E\x14\xBA" + + "\v\x14\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x05\x15\xC1\n\x15\x03\x16" + + "\x03\x16\x03\x16\x05\x16\xC6\n\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03" + + "\x17\x03\x17\x05\x17\xCE\n\x17\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18" + + "\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x1A" + + "\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B" + + "\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C" + + "\x05\x1C\xF0\n\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x05" + + "\x1C\xF8\n\x1C\x03\x1D\x03\x1D\x05\x1D\xFC\n\x1D\x03\x1D\x03\x1D\x03\x1E" + + "\x03\x1E\x03\x1E\x07\x1E\u0103\n\x1E\f\x1E\x0E\x1E\u0106\v\x1E\x05\x1E" + + "\u0108\n\x1E\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x05" + + "\x1F\u0111\n\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x07\x1F\u0117\n\x1F\f" + + "\x1F\x0E\x1F\u011A\v\x1F\x03 \x03 \x03 \x03 \x03!\x03!\x03!\x03\"\x03" + + "\"\x03\"\x03\"\x03\"\x03#\x03#\x03$\x03$\x03%\x03%\x03%\x02\x02\x03<&" + + "\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14" + + "\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02(\x02" + + "*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02D\x02" + + "F\x02H\x02\x02\x06\x04\x02\n\f..\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02" + + "\x1D#%&\x02\u0126\x02J\x03\x02\x02\x02\x04M\x03\x02\x02\x02\x06^\x03\x02" + + "\x02\x02\bh\x03\x02\x02\x02\nj\x03\x02\x02\x02\fs\x03\x02\x02\x02\x0E" + + "{\x03\x02\x02\x02\x10}\x03\x02\x02\x02\x12\x84\x03\x02\x02\x02\x14\x88" + + "\x03\x02\x02\x02\x16\x8A\x03\x02\x02\x02\x18\x94\x03\x02\x02\x02\x1A\x96" + + "\x03\x02\x02\x02\x1C\x99\x03\x02\x02\x02\x1E\x9B\x03\x02\x02\x02 \xA5" + + "\x03\x02\x02\x02\"\xB1\x03\x02\x02\x02$\xB3\x03\x02\x02\x02&\xB8\x03\x02" + + "\x02\x02(\xC0\x03\x02\x02\x02*\xC2\x03\x02\x02\x02,\xCB\x03\x02\x02\x02" + + ".\xCF\x03\x02\x02\x020\xD4\x03\x02\x02\x022\xDC\x03\x02\x02\x024\xE4\x03" + + "\x02\x02\x026\xF7\x03\x02\x02\x028\xF9\x03\x02\x02\x02:\u0107\x03\x02" + + "\x02\x02<\u0110\x03\x02\x02\x02>\u011B\x03\x02\x02\x02@\u011F\x03\x02" + + "\x02\x02B\u0122\x03\x02\x02\x02D\u0127\x03\x02\x02\x02F\u0129\x03\x02" + + "\x02\x02H\u012B\x03\x02\x02\x02JK\x05\x04\x03\x02KL\x07\x02\x02\x03L\x03" + + "\x03\x02\x02\x02MN\x07\x03\x02\x02NO\x05\x06\x04\x02OS\x07\x14\x02\x02" + + "PR\x05\b\x05\x02QP\x03\x02\x02\x02RU\x03\x02\x02\x02SQ\x03\x02\x02\x02" + + "ST\x03\x02\x02\x02TY\x03\x02\x02\x02US\x03\x02\x02\x02VX\x05\x0E\b\x02" + + "WV\x03\x02\x02\x02X[\x03\x02\x02\x02YW\x03\x02\x02\x02YZ\x03\x02\x02\x02" + + "Z\\\x03\x02\x02\x02[Y\x03\x02\x02\x02\\]\x07\x15\x02\x02]\x05\x03\x02" + + "\x02\x02^_\x07.\x02\x02_\x07\x03\x02\x02\x02`a\x07\b\x02\x02ab\x05\n\x06" + + "\x02bc\x07\x1C\x02\x02ci\x03\x02\x02\x02de\x07\x07\x02\x02ef\x05\n\x06" + + "\x02fg\x07\x1C\x02\x02gi\x03\x02\x02\x02h`\x03\x02\x02\x02hd\x03\x02\x02" + + "\x02i\t\x03\x02\x02\x02jk\x05\x16\f\x02kp\x05\f\x07\x02lm\x07\x1B\x02" + + "\x02mo\x05\f\x07\x02nl\x03\x02\x02\x02or\x03\x02\x02\x02pn\x03\x02\x02" + + "\x02pq\x03\x02\x02\x02q\v\x03\x02\x02\x02rp\x03\x02\x02\x02st\x07.\x02" + + "\x02t\r\x03\x02\x02\x02uv\x07\x04\x02\x02v|\x05\x10\t\x02wx\x07\x06\x02" + + "\x02x|\x05\x10\t\x02yz\x07\x05\x02\x02z|\x05\x10\t\x02{u\x03\x02\x02\x02" + + "{w\x03\x02\x02\x02{y\x03\x02\x02\x02|\x0F\x03\x02\x02\x02}~\x05\x14\v" + + "\x02~\x7F\x05\x12\n\x02\x7F\x80\x07\x16\x02\x02\x80\x81\x05\x18\r\x02" + + "\x81\x82\x07\x17\x02\x02\x82\x83\x05\x1E\x10\x02\x83\x11\x03\x02\x02\x02" + + "\x84\x85\x07.\x02\x02\x85\x13\x03\x02\x02\x02\x86\x89\x05\x16\f\x02\x87" + + "\x89\x07\r\x02\x02\x88\x86\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89" + + "\x15\x03\x02\x02\x02\x8A\x8B\t\x02\x02\x02\x8B\x17\x03\x02\x02\x02\x8C" + + "\x91\x05\x1A\x0E\x02\x8D\x8E\x07\x1B\x02\x02\x8E\x90\x05\x1A\x0E\x02\x8F" + + "\x8D\x03\x02\x02\x02\x90\x93\x03\x02\x02\x02\x91\x8F\x03\x02\x02\x02\x91" + + "\x92\x03\x02\x02\x02\x92\x95\x03\x02\x02\x02\x93\x91\x03\x02\x02\x02\x94" + + "\x8C\x03\x02\x02\x02\x94\x95\x03\x02\x02\x02\x95\x19\x03\x02\x02\x02\x96" + + "\x97\x05\x16\f\x02\x97\x98\x05\x1C\x0F\x02\x98\x1B\x03\x02\x02\x02\x99" + + "\x9A\x07.\x02\x02\x9A\x1D\x03\x02\x02\x02\x9B\x9F\x07\x14\x02\x02\x9C" + + "\x9E\x05 \x11\x02\x9D\x9C\x03\x02\x02\x02\x9E\xA1\x03\x02\x02\x02\x9F" + + "\x9D\x03\x02\x02\x02\x9F\xA0\x03\x02\x02\x02\xA0\xA2\x03\x02\x02\x02\xA1" + + "\x9F\x03\x02\x02\x02\xA2\xA3\x05&\x14\x02\xA3\xA4\x07\x15\x02\x02\xA4" + + "\x1F\x03\x02\x02\x02\xA5\xA6\x07\t\x02\x02\xA6\xA7\x05\x16\f\x02\xA7\xAC" + + "\x05\"\x12\x02\xA8\xA9\x07\x1B\x02\x02\xA9\xAB\x05\"\x12\x02\xAA\xA8\x03" + + "\x02\x02\x02\xAB\xAE\x03\x02\x02\x02\xAC\xAA\x03\x02\x02\x02\xAC\xAD\x03" + + "\x02\x02\x02\xAD\xAF\x03\x02\x02\x02\xAE\xAC\x03\x02\x02\x02\xAF\xB0\x07" + + "\x1C\x02\x02\xB0!\x03\x02\x02\x02\xB1\xB2\x07.\x02\x02\xB2#\x03\x02\x02" + + "\x02\xB3\xB4\x07.\x02\x02\xB4%\x03\x02\x02\x02\xB5\xB7\x05(\x15\x02\xB6" + + "\xB5\x03\x02\x02\x02\xB7\xBA\x03\x02\x02\x02\xB8\xB6\x03\x02\x02\x02\xB8" + + "\xB9\x03\x02\x02\x02\xB9\'\x03\x02\x02\x02\xBA\xB8\x03\x02\x02\x02\xBB" + + "\xC1\x05*\x16\x02\xBC\xC1\x05,\x17\x02\xBD\xC1\x052\x1A\x02\xBE\xC1\x05" + + "4\x1B\x02\xBF\xC1\x058\x1D\x02\xC0\xBB\x03\x02\x02\x02\xC0\xBC\x03\x02" + + "\x02\x02\xC0\xBD\x03\x02\x02\x02\xC0\xBE\x03\x02\x02\x02\xC0\xBF\x03\x02" + + "\x02\x02\xC1)\x03\x02\x02\x02\xC2\xC5\x07\x0E\x02\x02\xC3\xC6\x05$\x13" + + "\x02\xC4\xC6\x05B\"\x02\xC5\xC3\x03\x02\x02\x02\xC5\xC4\x03\x02\x02\x02" + + "\xC6\xC7\x03\x02\x02\x02\xC7\xC8\x07\x1D\x02\x02\xC8\xC9\x05<\x1F\x02" + + "\xC9\xCA\x07\x1C\x02\x02\xCA+\x03\x02\x02\x02\xCB\xCD\x050\x19\x02\xCC" + + "\xCE\x05.\x18\x02\xCD\xCC\x03\x02\x02\x02\xCD\xCE\x03\x02\x02\x02\xCE" + + "-\x03\x02\x02\x02\xCF\xD0\x07\x11\x02\x02\xD0\xD1\x07\x14\x02\x02\xD1" + + "\xD2\x05&\x14\x02\xD2\xD3\x07\x15\x02\x02\xD3/\x03\x02\x02\x02\xD4\xD5" + + "\x07\x10\x02\x02\xD5\xD6\x07\x16\x02\x02\xD6\xD7\x05<\x1F\x02\xD7\xD8" + + "\x07\x17\x02\x02\xD8\xD9\x07\x14\x02\x02\xD9\xDA\x05&\x14\x02\xDA\xDB" + + "\x07\x15\x02\x02\xDB1\x03\x02\x02\x02\xDC\xDD\x07\x12\x02\x02\xDD\xDE" + + "\x07\x16\x02\x02\xDE\xDF\x05<\x1F\x02\xDF\xE0\x07\x17\x02\x02\xE0\xE1" + + "\x07\x14\x02\x02\xE1\xE2\x05&\x14\x02\xE2\xE3\x07\x15\x02\x02\xE33\x03" + + "\x02\x02\x02\xE4\xE5\x07\x0F\x02\x02\xE5\xE6\x056\x1C\x02\xE6\xE7\x07" + + "\x1C\x02\x02\xE75\x03\x02\x02\x02\xE8\xE9\x05\x12\n\x02\xE9\xEA\x07\x16" + + "\x02\x02\xEA\xEB\x05:\x1E\x02\xEB\xEC\x07\x17\x02\x02\xEC\xF8\x03\x02" + + "\x02\x02\xED\xF0\x05\x06\x04\x02\xEE\xF0\x07-\x02\x02\xEF\xED\x03\x02" + + "\x02\x02\xEF\xEE\x03\x02\x02\x02\xF0\xF1\x03\x02\x02\x02\xF1\xF2\x07\x1A" + + "\x02\x02\xF2\xF3\x05\x12\n\x02\xF3\xF4\x07\x16\x02\x02\xF4\xF5\x05:\x1E" + + "\x02\xF5\xF6\x07\x17\x02\x02\xF6\xF8\x03\x02\x02\x02\xF7\xE8\x03\x02\x02" + + "\x02\xF7\xEF\x03\x02\x02\x02\xF87\x03\x02\x02\x02\xF9\xFB\x07\x13\x02" + + "\x02\xFA\xFC\x05<\x1F\x02\xFB\xFA\x03\x02\x02\x02\xFB\xFC\x03\x02\x02" + + "\x02\xFC\xFD\x03\x02\x02\x02\xFD\xFE\x07\x1C\x02\x02\xFE9\x03\x02\x02" + + "\x02\xFF\u0104\x05<\x1F\x02\u0100\u0101\x07\x1B\x02\x02\u0101\u0103\x05" + + "<\x1F\x02\u0102\u0100\x03\x02\x02\x02\u0103\u0106\x03\x02\x02\x02\u0104" + + "\u0102\x03\x02\x02\x02\u0104\u0105\x03\x02\x02\x02\u0105\u0108\x03\x02" + + "\x02\x02\u0106\u0104\x03\x02\x02\x02\u0107\xFF\x03\x02\x02\x02\u0107\u0108" + + "\x03\x02\x02\x02\u0108;\x03\x02\x02\x02\u0109\u010A\b\x1F\x01\x02\u010A" + + "\u0111\x05D#\x02\u010B\u0111\x05$\x13\x02\u010C\u0111\x056\x1C\x02\u010D" + + "\u0111\x05B\"\x02\u010E\u0111\x05@!\x02\u010F\u0111\x05> \x02\u0110\u0109" + + "\x03\x02\x02\x02\u0110\u010B\x03\x02\x02\x02\u0110\u010C\x03\x02\x02\x02" + + "\u0110\u010D\x03\x02\x02\x02\u0110\u010E\x03\x02\x02\x02\u0110\u010F\x03" + + "\x02\x02\x02\u0111\u0118\x03\x02\x02\x02\u0112\u0113\f\t\x02\x02\u0113" + + "\u0114\x05H%\x02\u0114\u0115\x05<\x1F\n\u0115\u0117\x03\x02\x02\x02\u0116" + + "\u0112\x03\x02\x02\x02\u0117\u011A\x03\x02\x02\x02\u0118\u0116\x03\x02" + + "\x02\x02\u0118\u0119\x03\x02\x02\x02\u0119=\x03\x02\x02\x02\u011A\u0118" + + "\x03\x02\x02\x02\u011B\u011C\x07\x16\x02\x02\u011C\u011D\x05<\x1F\x02" + + "\u011D\u011E\x07\x17\x02\x02\u011E?\x03\x02\x02\x02\u011F\u0120\x05F$" + + "\x02\u0120\u0121\x05<\x1F\x02\u0121A\x03\x02\x02\x02\u0122\u0123\x05$" + + "\x13\x02\u0123\u0124\x07\x18\x02\x02\u0124\u0125\x05<\x1F\x02\u0125\u0126" + + "\x07\x19\x02\x02\u0126C\x03\x02\x02\x02\u0127\u0128\t\x03\x02\x02\u0128" + + "E\x03\x02\x02\x02\u0129\u012A\t\x04\x02\x02\u012AG\x03\x02\x02\x02\u012B" + + "\u012C\t\x05\x02\x02\u012CI\x03\x02\x02\x02\x17SYhp{\x88\x91\x94\x9F\xAC" + + "\xB8\xC0\xC5\xCD\xEF\xF7\xFB\u0104\u0107\u0110\u0118"; public static __ATN: ATN; public static get _ATN(): ATN { if (!JackParser.__ATN) { @@ -2540,8 +2594,8 @@ export class StatementContext extends ParserRuleContext { public letStatement(): LetStatementContext | undefined { return this.tryGetRuleContext(0, LetStatementContext); } - public ifStatement(): IfStatementContext | undefined { - return this.tryGetRuleContext(0, IfStatementContext); + public ifElseStatement(): IfElseStatementContext | undefined { + return this.tryGetRuleContext(0, IfElseStatementContext); } public whileStatement(): WhileStatementContext | undefined { return this.tryGetRuleContext(0, WhileStatementContext); @@ -2621,41 +2675,88 @@ export class LetStatementContext extends ParserRuleContext { } -export class IfStatementContext extends ParserRuleContext { - public IF(): TerminalNode { return this.getToken(JackParser.IF, 0); } - public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext); +export class IfElseStatementContext extends ParserRuleContext { + public ifStatement(): IfStatementContext { + return this.getRuleContext(0, IfStatementContext); } - public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } - public LBRACE(): TerminalNode[]; - public LBRACE(i: number): TerminalNode; - public LBRACE(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.LBRACE); - } else { - return this.getToken(JackParser.LBRACE, i); + public elseStatement(): ElseStatementContext | undefined { + return this.tryGetRuleContext(0, ElseStatementContext); + } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_ifElseStatement; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterIfElseStatement) { + listener.enterIfElseStatement(this); } } - public statements(): StatementsContext[]; - public statements(i: number): StatementsContext; - public statements(i?: number): StatementsContext | StatementsContext[] { - if (i === undefined) { - return this.getRuleContexts(StatementsContext); + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitIfElseStatement) { + listener.exitIfElseStatement(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitIfElseStatement) { + return visitor.visitIfElseStatement(this); } else { - return this.getRuleContext(i, StatementsContext); + return visitor.visitChildren(this); } } - public RBRACE(): TerminalNode[]; - public RBRACE(i: number): TerminalNode; - public RBRACE(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.RBRACE); +} + + +export class ElseStatementContext extends ParserRuleContext { + public ELSE(): TerminalNode { return this.getToken(JackParser.ELSE, 0); } + public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext); + } + public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_elseStatement; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterElseStatement) { + listener.enterElseStatement(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitElseStatement) { + listener.exitElseStatement(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitElseStatement) { + return visitor.visitElseStatement(this); } else { - return this.getToken(JackParser.RBRACE, i); + return visitor.visitChildren(this); } } - public ELSE(): TerminalNode | undefined { return this.tryGetToken(JackParser.ELSE, 0); } +} + + +export class IfStatementContext extends ParserRuleContext { + public IF(): TerminalNode { return this.getToken(JackParser.IF, 0); } + public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext); + } + public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } + public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext); + } + public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts index 47d743c7..d1dee688 100644 --- a/compiler/src/generated/JackParserListener.ts +++ b/compiler/src/generated/JackParserListener.ts @@ -29,6 +29,8 @@ import { VarNameContext } from "./JackParser"; import { StatementsContext } from "./JackParser"; import { StatementContext } from "./JackParser"; import { LetStatementContext } from "./JackParser"; +import { IfElseStatementContext } from "./JackParser"; +import { ElseStatementContext } from "./JackParser"; import { IfStatementContext } from "./JackParser"; import { WhileStatementContext } from "./JackParser"; import { DoStatementContext } from "./JackParser"; @@ -345,6 +347,28 @@ export interface JackParserListener extends ParseTreeListener { */ exitLetStatement?: (ctx: LetStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + enterIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + exitIfElseStatement?: (ctx: IfElseStatementContext) => void; + + /** + * Enter a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + enterElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + exitElseStatement?: (ctx: ElseStatementContext) => void; + /** * Enter a parse tree produced by `JackParser.ifStatement`. * @param ctx the parse tree diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts index 5a9563f3..a8274208 100644 --- a/compiler/src/generated/JackParserVisitor.ts +++ b/compiler/src/generated/JackParserVisitor.ts @@ -29,6 +29,8 @@ import { VarNameContext } from "./JackParser"; import { StatementsContext } from "./JackParser"; import { StatementContext } from "./JackParser"; import { LetStatementContext } from "./JackParser"; +import { IfElseStatementContext } from "./JackParser"; +import { ElseStatementContext } from "./JackParser"; import { IfStatementContext } from "./JackParser"; import { WhileStatementContext } from "./JackParser"; import { DoStatementContext } from "./JackParser"; @@ -239,6 +241,20 @@ export interface JackParserVisitor extends ParseTreeVisitor { */ visitLetStatement?: (ctx: LetStatementContext) => Result; + /** + * Visit a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitIfElseStatement?: (ctx: IfElseStatementContext) => Result; + + /** + * Visit a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitElseStatement?: (ctx: ElseStatementContext) => Result; + /** * Visit a parse tree produced by `JackParser.ifStatement`. * @param ctx the parse tree diff --git a/compiler/src/listener/symbol.table.listener.ts b/compiler/src/listener/symbol.table.listener.ts index 911a35eb..4564614c 100644 --- a/compiler/src/listener/symbol.table.listener.ts +++ b/compiler/src/listener/symbol.table.listener.ts @@ -33,29 +33,19 @@ export class GlobalSymbolTableListener implements JackParserListener, ParseTreeL this.className = ctx.className()?.text; }; - enterConstructor(ctx: ConstructorContext) { - this.#addSymbol(ctx.subroutineDecWithoutType()) - }; - enterMethod(ctx: MethodContext) { - this.#addSymbol(ctx.subroutineDecWithoutType()) - }; - enterFunction(ctx: FunctionContext) { - this.#addSymbol(ctx.subroutineDecWithoutType()) - }; - - resetErrors() { - this.errors = []; - } - - #addSymbol(c: SubroutineDecWithoutTypeContext) { - const ctx = c.subroutineName() - const subroutineName = ctx.text + enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { + const nameCtx = ctx.subroutineName() + const subroutineName = nameCtx.text const id = this.className + "." + subroutineName if (this.globalSymbolTable[id] != undefined) { - this.errors.push(new DuplicatedSubroutineError(ctx.start.line, ctx.start.startIndex, `Subroutine "${subroutineName}" is already defined.`)); + this.errors.push(new DuplicatedSubroutineError(nameCtx.start.line, nameCtx.start.startIndex, `Subroutine "${subroutineName}" is already defined.`)); } this.globalSymbolTable[id] = { - subroutineParameterCount: c.parameterList().parameter().length + subroutineParameterCount: ctx.parameterList().parameter().length, } as GenericSymbol; } + + resetErrors() { + this.errors = []; + } } diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 8a8f0c42..0526c85b 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,10 +1,28 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { DuplicatedVariableException, JackCompilerError, UndeclaredVariableError, UnknownTypeError } from "../error"; -import { FieldDeclarationContext, FieldNameContext, LetStatementContext, ParameterContext, ParameterNameContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext } from "../generated/JackParser"; +import { DuplicatedVariableException, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, VoidSubroutineReturnsValueError } from "../error"; +import { FieldDeclarationContext, FieldNameContext, IfStatementContext, LetStatementContext, ParameterContext, ParameterNameContext, ReturnStatementContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol } from "./symbol.table.listener"; +class BinaryTreeNode { + + constructor( + public parent: BinaryTreeNode | undefined, + public left: BinaryTreeNode | LeafNode, + public right: BinaryTreeNode | LeafNode) { } + + get returns(): boolean { + return this.left.returns && this.right.returns; + } +} +enum CFGSide { + LEFT, + RIGHT +} +class LeafNode { + returns: boolean = false; +} export class ValidatorListener implements JackParserListener, ParseTreeListener { @@ -27,6 +45,10 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener //why do we need local symbol table? this vars, arguments, local vars. What about types? localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); + subroutineShouldReturnVoidType: boolean = false; + cfgNode: BinaryTreeNode | undefined + cfgSide: CFGSide = CFGSide.LEFT; + subroutineName: string = "" constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } enterFieldName(ctx: FieldNameContext) { @@ -34,19 +56,54 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { this.localSymbolTable.pushStack(); + const returnType = ctx.subroutineReturnType() + this.subroutineShouldReturnVoidType = returnType.VOID() != undefined + this.cfgNode = undefined + this.cfgSide = CFGSide.LEFT; + this.subroutineName = ctx.subroutineName().text + }; + + addCFGNode() { + if (this.cfgNode == undefined) { + this.cfgNode = new BinaryTreeNode(undefined, new LeafNode(), new LeafNode()); + this.cfgSide = CFGSide.LEFT; + } else { + switch (this.cfgSide) { + case CFGSide.LEFT: + this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode, new LeafNode(), new LeafNode()); + break; + case CFGSide.RIGHT: + this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode, new LeafNode(), new LeafNode()); + this.cfgSide = CFGSide.LEFT; + break; + } + } + } + //while + enterWhileStatement(ctx: WhileStatementContext) { + this.addCFGNode() + }; + + exitWhileStatement(ctx: WhileStatementContext) { + this.cfgSide = CFGSide.RIGHT; + }; + enterIfStatement(ctx: IfStatementContext) { + this.addCFGNode() + }; + exitIfStatement(ctx: IfStatementContext) { + this.cfgSide = CFGSide.RIGHT; }; - enterVarType(ctx: VarTypeContext) { if (ctx.IDENTIFIER() != undefined) { const type = ctx.IDENTIFIER()!.text if (this.globalSymbolTable[type] === undefined) { - this.errors.push(new UnknownTypeError(ctx.start.line, ctx.start.startIndex, type)); + this.errors.push(new UnknownClassError(ctx.start.line, ctx.start.startIndex, type)); } } }; - + enterParameterName(ctx: ParameterNameContext) { this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); } @@ -60,7 +117,34 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener this.errors.push(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); } }; + enterReturnStatement(ctx: ReturnStatementContext) { + const returnsVoid = ctx.expression() == undefined + if (returnsVoid && !this.subroutineShouldReturnVoidType) { + this.errors.push(new NonVoidFunctionNoReturnError(ctx.start.line, ctx.start.startIndex)); + } + if (!returnsVoid && this.subroutineShouldReturnVoidType) { + this.errors.push(new VoidSubroutineReturnsValueError(ctx.start.line, ctx.start.startIndex,)); + } + if (this.cfgNode !== undefined) { + switch (this.cfgSide) { + case CFGSide.LEFT: + if (!(this.cfgNode.left instanceof LeafNode)) { + throw new Error("Expected left node in CFG") + } + this.cfgNode.left.returns = true; + break + case CFGSide.RIGHT: + if (!(this.cfgNode.right instanceof LeafNode)) { + throw new Error("Expected left node in CFG") + } + this.cfgNode.right.returns = true; + } + } + }; exitSubroutineBody(ctx: SubroutineBodyContext) { + if (this.cfgNode != undefined && !this.cfgNode.returns) { + this.errors.push(new SubroutineNotAllPathsReturn(ctx.start.line, ctx.start.startIndex, this.subroutineName)); + } this.localSymbolTable.popStack(); }; localSymbolTableAdd(line: number, position: number, name: string) { diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index 586f06b6..f20996ab 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -8,10 +8,8 @@ import { getTestResourcePath, listenToTheTree, parseJackText, handleErrors, pars import { ProgramContext } from '../src/generated/JackParser'; import { JackCompilerError } from '../src/error'; - describe('Parser', () => { const jestConsole = console; - beforeEach(() => { global.console = require('console'); }); diff --git a/compiler/test/symbol.table.listener.test.ts b/compiler/test/symbol.table.listener.test.ts index 5db68289..3c6f7c20 100644 --- a/compiler/test/symbol.table.listener.test.ts +++ b/compiler/test/symbol.table.listener.test.ts @@ -56,3 +56,4 @@ describe('Global symbol table', () => { }) }) + diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index 67cd2e74..a8f81729 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,21 +1,26 @@ import { ParserRuleContext } from "antlr4ts" -import { DuplicatedVariableException as DuplicatedVariableError, JackCompilerError, UndeclaredVariableError, UnknownTypeError } from "../src/error" +import { DuplicatedVariableException as DuplicatedVariableError, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, VoidSubroutineReturnsValueError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { GenericSymbol } from "../src/listener/symbol.table.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" import { ProgramContext } from "../src/generated/JackParser" +import { Logger, ILogObj } from "tslog"; +const log: Logger = new Logger(); describe('ValidatorListener', () => { - const jestConsole = console; + // const jestConsole = console; + // beforeEach(() => { - beforeEach(() => { - global.console = require('console'); - }); + // global.console = require('console'); + // }); - afterEach(() => { - global.console = jestConsole; - }); + // afterEach(() => { + // global.console = jestConsole; + // }); + + + const genericSymbol = {} as GenericSymbol const duplicateVarClassBodies = [ ["static", ' static int a, a;'], @@ -38,8 +43,12 @@ describe('ValidatorListener', () => { ${classBody} }`, DuplicatedVariableError) }) + + /** + * Undeclared var + */ test('let - undeclared variable ', () => { - testValidator( ` + testValidator(` class Main { function void a(){ let b=1; @@ -64,120 +73,183 @@ describe('ValidatorListener', () => { `class Main { function void a(){ if(a=0){ + return; }else { + return; } - return; } }`, UndeclaredVariableError) }) - test('Unknown type for subroutine return type ', () => { - testValidator( ` + /** + * Unknown class + */ + test('Unknown class for subroutine return type ', () => { + testValidator(` class Main { function D b(int a){ - return; + return D.new(); } - }`, UnknownTypeError) + }`, UnknownClassError) }) test('Known type for subroutine return type ', () => { testValidator(` class Main { function D b(int a){ - return; + return D.new(); } - }`, undefined, { "D": {} as GenericSymbol }) + }`, undefined, { "D": genericSymbol, "D.new": genericSymbol }) }) - test('Arg unknown type ', () => { + test('Arg Unknown class ', () => { testValidator(` class Main { function void b(D a){ return; } - }`, UnknownTypeError) + }`, UnknownClassError) }) test('Arg known type ', () => { - testValidator( ` + testValidator(` class Main { function void b(D a){ return; } - }`, undefined, { "D": {} as GenericSymbol }) + }`, undefined, { "D": genericSymbol }) }) - test('var unknown type', () => { - testValidator( ` + test('var Unknown class', () => { + testValidator(` class Main { function void b(){ var D d; return; } - }`, UnknownTypeError) + }`, UnknownClassError) }) test('var known type', () => { - testValidator( ` + testValidator(` class Main { function void b(){ var D d; return; } - }`, undefined, { "D": {} as GenericSymbol }) + }`, undefined, { "D": genericSymbol }) }) - test('field unknown type', () => { - testValidator( ` + test('field Unknown class', () => { + testValidator(` class Main { field T t; - }`, UnknownTypeError) + }`, UnknownClassError) }) test('field known type', () => { - testValidator( ` + testValidator(` class Main { field T t; - }`, undefined, { "T": {} as GenericSymbol }) + }`, undefined, { "T": genericSymbol }) }) - test('static field unknown type', () => { - testValidator( ` + test('static field Unknown class', () => { + testValidator(` class Main { static T t; - }`, UnknownTypeError) + }`, UnknownClassError) }) test('static field known type', () => { - testValidator( ` + testValidator(` class Main { static T t; - }`, undefined, { "T": {} as GenericSymbol }) + }`, undefined, { "T": genericSymbol }) + }) + + /** + * Incorrect return type + */ + + test('non void subroutine must return a value', () => { + testValidator(` + class Main { + function int a(){ + return; + } + }`, NonVoidFunctionNoReturnError) }) - //TODO: print line when on exception - /* - * Let: - * - `Subroutine ${subroutine.name.value}: not all code paths return a value`, - * - `A non void subroutine must return a value`, - * - Unknown type for return type, class variable, or method local var - * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface - * - validate arg number - * - `Method ${className}.${subroutineName} was called as a function/constructor` - * - Subroutine was called as a method - * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` - * - `Class ${className} doesn't exist` - */ + test('void subroutine must return not return a value', () => { + testValidator(` + class Main { + function void a(){ + return 1; + } + }`, VoidSubroutineReturnsValueError) + }) + /** + * `Subroutine ${subroutine.name.value}: not all code paths return a value` + */ + + test('if else missing return', () => { + testValidator(` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + + }else{ + return; + } + } + }`, SubroutineNotAllPathsReturn) + }) + + test('while missing return', () => { + testValidator(` + class Main { + function int a(){ + var int a; + let a=0; + while(a<10){ + return 0; + } + } + }`, SubroutineNotAllPathsReturn) + }) + + /** + * List of validations rules: + * - , + * - ``, + * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface + * - validate arg number + * - `Method ${className}.${subroutineName} was called as a function/constructor` + * - Subroutine was called as a method + * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` + */ }) -function testValidator(src: string, expectedError?: T, globalSymbolTable: Record = {}) { +function testValidator(src: string, expectedError?: T, globalSymbolTable: Record = {}) { const name = expect.getState().currentTestName! - console.info(`Testing ${name}\n`, src) const errorListener = new ErrorListener(); errorListener.filepath = name; const tree = parseJackText(src, errorListener) const validator = listenToTheTree(tree, new ValidatorListener(globalSymbolTable)) if (expectedError) { + if (validator.errors.length > 1) { + console.error("Errors", validator.errors) + } expect(validator.errors.length).toBe(1) - expect(validator.errors[0]).toBeInstanceOf(expectedError) + try { + expect(validator.errors[0]).toBeInstanceOf(expectedError) + } catch (e) { + throw new Error(`Expected error ${expectedError.name} but got ` + JSON.stringify(validator.errors[0])) + } } else { if (validator.errors.length != 0) throw new Error("Didn't expect any errors but got " + validator.errors.join("\n")) } } + + + From 59f750771e84037d5bf3310f9e31f9548afdbb73 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:21:03 +0200 Subject: [PATCH 13/87] Add not all pahts retun validation --- compiler/src/listener/validator.listener.ts | 109 +++++++++---------- compiler/test/validator.listener.test.ts | 114 ++++++++++++++++++-- 2 files changed, 156 insertions(+), 67 deletions(-) diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 0526c85b..79e01a82 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,28 +1,31 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; import { DuplicatedVariableException, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, VoidSubroutineReturnsValueError } from "../error"; -import { FieldDeclarationContext, FieldNameContext, IfStatementContext, LetStatementContext, ParameterContext, ParameterNameContext, ReturnStatementContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; +import { ClassDeclarationContext, ElseStatementContext, FieldDeclarationContext, FieldNameContext, IfElseStatementContext, IfStatementContext, LetStatementContext, ParameterContext, ParameterNameContext, ReturnStatementContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol } from "./symbol.table.listener"; class BinaryTreeNode { - + _returns?: boolean; constructor( public parent: BinaryTreeNode | undefined, - public left: BinaryTreeNode | LeafNode, - public right: BinaryTreeNode | LeafNode) { } + public left?: BinaryTreeNode, + public right?: BinaryTreeNode) { } get returns(): boolean { - return this.left.returns && this.right.returns; + if (this._returns) { + return this._returns; + } else if (this.right == undefined && this.left == undefined) { + return false; + } else if (this.right != undefined && this.left != undefined) { + return this.left.returns && this.right.returns; + } else if (this.left != undefined) { + return false; + } else { + throw new Error("Something went wrong - CFG has only right subtree") + } } } -enum CFGSide { - LEFT, - RIGHT -} -class LeafNode { - returns: boolean = false; -} export class ValidatorListener implements JackParserListener, ParseTreeListener { @@ -32,22 +35,21 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener * - variable declaration - validate duplicate variable declarations * Let: * - Undeclared variable - * - `Subroutine ${subroutine.name.value}: not all code paths return a value`, + * - `Subroutine ${ subroutine.name.value }: not all code paths return a value`, * - `A non void subroutine must return a value`, * - Unknown type for return type, class variable, or method local var * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface * - validate arg number - * - `Method ${className}.${subroutineName} was called as a function/constructor` - * - Subroutine was called as a method - * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` - * - `Class ${className} doesn't exist` - */ + * - `Method ${ className }.${ subroutineName } was called as a function/constructor` + * - Subroutine was called as a method + * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` + * - `Class ${className} doesn't exist` + */ //why do we need local symbol table? this vars, arguments, local vars. What about types? localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); subroutineShouldReturnVoidType: boolean = false; - cfgNode: BinaryTreeNode | undefined - cfgSide: CFGSide = CFGSide.LEFT; + cfgNode: BinaryTreeNode = new BinaryTreeNode(undefined); subroutineName: string = "" constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } @@ -58,40 +60,35 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener this.localSymbolTable.pushStack(); const returnType = ctx.subroutineReturnType() this.subroutineShouldReturnVoidType = returnType.VOID() != undefined - this.cfgNode = undefined - this.cfgSide = CFGSide.LEFT; + this.cfgNode = new BinaryTreeNode(undefined); this.subroutineName = ctx.subroutineName().text }; - addCFGNode() { - if (this.cfgNode == undefined) { - this.cfgNode = new BinaryTreeNode(undefined, new LeafNode(), new LeafNode()); - this.cfgSide = CFGSide.LEFT; - } else { - switch (this.cfgSide) { - case CFGSide.LEFT: - this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode, new LeafNode(), new LeafNode()); - break; - case CFGSide.RIGHT: - this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode, new LeafNode(), new LeafNode()); - this.cfgSide = CFGSide.LEFT; - break; - } - } - } - //while + enterWhileStatement(ctx: WhileStatementContext) { - this.addCFGNode() + this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode); }; exitWhileStatement(ctx: WhileStatementContext) { - this.cfgSide = CFGSide.RIGHT; + if (this.cfgNode?.parent != null) { + this.cfgNode = this.cfgNode.parent + } }; enterIfStatement(ctx: IfStatementContext) { - this.addCFGNode() + this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode); }; exitIfStatement(ctx: IfStatementContext) { - this.cfgSide = CFGSide.RIGHT; + if (this.cfgNode?.parent != null) { + this.cfgNode = this.cfgNode.parent + } + }; + enterElseStatement(ctx: ElseStatementContext) { + this.cfgNode = this.cfgNode.right = new BinaryTreeNode(this.cfgNode); + }; + exitElseStatement(ctx: ElseStatementContext) { + if (this.cfgNode?.parent != null) { + this.cfgNode = this.cfgNode.parent + } }; enterVarType(ctx: VarTypeContext) { @@ -125,24 +122,11 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener if (!returnsVoid && this.subroutineShouldReturnVoidType) { this.errors.push(new VoidSubroutineReturnsValueError(ctx.start.line, ctx.start.startIndex,)); } - if (this.cfgNode !== undefined) { - switch (this.cfgSide) { - case CFGSide.LEFT: - if (!(this.cfgNode.left instanceof LeafNode)) { - throw new Error("Expected left node in CFG") - } - this.cfgNode.left.returns = true; - break - case CFGSide.RIGHT: - if (!(this.cfgNode.right instanceof LeafNode)) { - throw new Error("Expected left node in CFG") - } - this.cfgNode.right.returns = true; - } - } + this.cfgNode._returns = true; }; + exitSubroutineBody(ctx: SubroutineBodyContext) { - if (this.cfgNode != undefined && !this.cfgNode.returns) { + if (!this.cfgNode.returns) { this.errors.push(new SubroutineNotAllPathsReturn(ctx.start.line, ctx.start.startIndex, this.subroutineName)); } this.localSymbolTable.popStack(); @@ -156,6 +140,12 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener } //to fix compiler error visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; + + exitClassDeclaration(ctx: ClassDeclarationContext) { + while (this.cfgNode?.parent != undefined) { + this.cfgNode = this.cfgNode.parent + } + }; } export class LocalSymbolTable { @@ -179,4 +169,5 @@ export class LocalSymbolTable { popStack() { this.scopeVarDecs.pop(); } + } \ No newline at end of file diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index a8f81729..c47ef31a 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -9,15 +9,15 @@ import { Logger, ILogObj } from "tslog"; const log: Logger = new Logger(); describe('ValidatorListener', () => { - // const jestConsole = console; - // beforeEach(() => { + const jestConsole = console; + beforeEach(() => { - // global.console = require('console'); - // }); + global.console = require('console'); + }); - // afterEach(() => { - // global.console = jestConsole; - // }); + afterEach(() => { + global.console = jestConsole; + }); const genericSymbol = {} as GenericSymbol @@ -52,6 +52,7 @@ describe('ValidatorListener', () => { class Main { function void a(){ let b=1; + return; } }`, UndeclaredVariableError) }) @@ -64,6 +65,7 @@ describe('ValidatorListener', () => { } function void a(){ do Main.b(a); + return; } }`, UndeclaredVariableError) }) @@ -188,7 +190,7 @@ describe('ValidatorListener', () => { * `Subroutine ${subroutine.name.value}: not all code paths return a value` */ - test('if else missing return', () => { + test('if missing return', () => { testValidator(` class Main { function void a(){ @@ -202,8 +204,35 @@ describe('ValidatorListener', () => { } }`, SubroutineNotAllPathsReturn) }) + test('else missing return ', () => { + testValidator(` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + return; + }else{ + + } + } + }`, SubroutineNotAllPathsReturn) + }) test('while missing return', () => { + testValidator(` + class Main { + function int a(){ + var int a; + let a=0; + while(a<10){ + + } + } + }`, SubroutineNotAllPathsReturn) + }) + + test(' missing return after while', () => { testValidator(` class Main { function int a(){ @@ -216,6 +245,75 @@ describe('ValidatorListener', () => { }`, SubroutineNotAllPathsReturn) }) + test('nested if missing return', () => { + testValidator(` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + return; + }else { + + } + }else{ + return; + } + } + }`, SubroutineNotAllPathsReturn) + }) + test('nested if missing return 2', () => { + testValidator(` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + + }else { + return; + } + }else{ + return; + } + } + }`, SubroutineNotAllPathsReturn) + }) + test('nested if missing return 2', () => { + testValidator(` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + + return; + }else { + return; + } + }else{ + } + } + }`, SubroutineNotAllPathsReturn) + }) + test('should be valid', () => { + testValidator(` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + }else { + } + } + return; + } + }`) + }) /** * List of validations rules: * - , From 730f72e74c67879d1bc312d497d09a960a8a6ac4 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sat, 28 Sep 2024 10:20:48 +0200 Subject: [PATCH 14/87] Add print binary tree function --- compiler/src/listener/validator.listener.ts | 37 +++++++++++++++++++++ compiler/test/validator.listener.test.ts | 12 ++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 79e01a82..2f950665 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -25,6 +25,43 @@ class BinaryTreeNode { throw new Error("Something went wrong - CFG has only right subtree") } } + print() { + console.log("Branch returns value") + console.log(".") + console.log(this.printBT()); + } + + printBT(prefix: string = "", side: Side = Side.LEFT) { + let res: string = "" + if (this._returns) { + res += this.#pad(prefix, side) + res += " " + this._returns + "\n"; + return res; + } else { + if (this.right == undefined && this.left == undefined) { + res += this.#pad(prefix, side) + res += " " + false + "\n"; + } else { + res += this.left?.printBT((side == Side.LEFT ? "| " : " "), Side.LEFT); + if (this.right) { + res += prefix + res += this.right?.printBT((side == Side.LEFT ? "|\t" : "\t"), Side.RIGHT); + } else { + res += "\n"; + } + + } + } + return res; + } + #pad(prefix: string, side: Side): string { + return side == Side.LEFT ? "├──" : "└──"; + } + +} +enum Side { + LEFT, + RIGHT } export class ValidatorListener implements JackParserListener, ParseTreeListener { diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index c47ef31a..b46ad0f4 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -281,7 +281,8 @@ describe('ValidatorListener', () => { } }`, SubroutineNotAllPathsReturn) }) - test('nested if missing return 2', () => { + + test('nested if missing return 3', () => { testValidator(` class Main { function void a(){ @@ -289,12 +290,12 @@ describe('ValidatorListener', () => { let a=0; if(a=0){ if(a=1){ - - return; + return; }else { - return; + return; } }else{ + } } }`, SubroutineNotAllPathsReturn) @@ -334,6 +335,9 @@ function testValidator(src: string, expected const validator = listenToTheTree(tree, new ValidatorListener(globalSymbolTable)) if (expectedError) { + if (validator.cfgNode) { + validator.cfgNode.print() + } if (validator.errors.length > 1) { console.error("Errors", validator.errors) } From d61c6ca258b49626718a87cbe408163716db4dcd Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sat, 28 Sep 2024 11:20:56 +0200 Subject: [PATCH 15/87] Add validations for subroutine call --- compiler/parser-gen/JackParser.g4 | 6 +- compiler/src/error.ts | 36 +- compiler/src/generated/JackParser.interp | 5 +- compiler/src/generated/JackParser.ts | 766 ++++++++++--------- compiler/src/generated/JackParserListener.ts | 30 +- compiler/src/generated/JackParserVisitor.ts | 18 +- compiler/src/listener/validator.listener.ts | 92 +-- compiler/test/validator.listener.test.ts | 74 +- 8 files changed, 579 insertions(+), 448 deletions(-) diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/parser-gen/JackParser.g4 index 7ac3db3e..3a0d0c1c 100644 --- a/compiler/parser-gen/JackParser.g4 +++ b/compiler/parser-gen/JackParser.g4 @@ -55,10 +55,8 @@ whileStatement: doStatement: DO subroutineCall SEMICOLON; -subroutineCall: - subroutineName LPAREN expressionList RPAREN - | (className | THIS_LITERAL) DOT subroutineName LPAREN expressionList RPAREN; - +subroutineCall: subroutineId LPAREN expressionList RPAREN; +subroutineId: ((className | THIS_LITERAL) DOT)? subroutineName; returnStatement: RETURN expression? SEMICOLON; expressionList: (expression (COMMA expression)*)?; diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 98f9b812..8b291618 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -7,7 +7,11 @@ export class JackCompilerError { */ constructor(public line: number, public charPositionInLine: number, public msg: string) { } + public toString = (): string => { + return this.constructor.name + `(${this.line}:${this.charPositionInLine} ${this.msg})`; + } } + export class LexerOrParserError extends Error { /** * @@ -43,7 +47,7 @@ export class UndeclaredVariableError extends JackCompilerError { export class UnknownClassError extends JackCompilerError { constructor(line: number, charPositionInLine: number, className: string) { - super(line, charPositionInLine, `Class ${className} doesn't exist` ); + super(line, charPositionInLine, `Class ${className} doesn't exist`); } } @@ -52,7 +56,7 @@ export class NonVoidFunctionNoReturnError extends JackCompilerError { //TODO: should we add a subroutine name? constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `A non void subroutine must return a value` ); + super(line, charPositionInLine, `A non void subroutine must return a value`); } } @@ -60,7 +64,7 @@ export class NonVoidFunctionNoReturnError extends JackCompilerError { export class VoidSubroutineReturnsValueError extends JackCompilerError { constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `Cannot return a value from a void subroutine` ); + super(line, charPositionInLine, `Cannot return a value from a void subroutine`); Object.setPrototypeOf(this, VoidSubroutineReturnsValueError.prototype); } @@ -69,8 +73,32 @@ export class VoidSubroutineReturnsValueError extends JackCompilerError { export class SubroutineNotAllPathsReturn extends JackCompilerError { constructor(line: number, charPositionInLine: number, subroutineName: string) { - super(line, charPositionInLine, `Subroutine ${subroutineName}: not all code paths return a value` ); + super(line, charPositionInLine, `Subroutine ${subroutineName}: not all code paths return a value`); Object.setPrototypeOf(this, SubroutineNotAllPathsReturn.prototype); } +} + +export class IncorrectParamsNumberInSubroutineCall extends JackCompilerError { + + constructor(line: number, + charPositionInLine: number, + subroutineName: string, + expectedParamsCount: number, + actualParamsCount: number) { + super(line, charPositionInLine, + `Subroutine ${subroutineName} expects ${expectedParamsCount} arguments while ${actualParamsCount} was provided`); + Object.setPrototypeOf(this, IncorrectParamsNumberInSubroutineCall.prototype); + } + +} +export class UnknownSubroutineCall extends JackCompilerError { + + constructor(line: number, + charPositionInLine: number, + subroutineId: string) { + super(line, charPositionInLine, `Subroutine ${subroutineId} not found`); + Object.setPrototypeOf(this, UnknownSubroutineCall.prototype); + } + } \ No newline at end of file diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp index f85f3f4d..419c18a9 100644 --- a/compiler/src/generated/JackParser.interp +++ b/compiler/src/generated/JackParser.interp @@ -119,11 +119,12 @@ statements statement letStatement ifElseStatement -elseStatement ifStatement +elseStatement whileStatement doStatement subroutineCall +subroutineId returnStatement expressionList expression @@ -136,4 +137,4 @@ binaryOperator atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 302, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 82, 10, 3, 12, 3, 14, 3, 85, 11, 3, 3, 3, 7, 3, 88, 10, 3, 12, 3, 14, 3, 91, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 105, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 111, 10, 6, 12, 6, 14, 6, 114, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 124, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 137, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 144, 10, 13, 12, 13, 14, 13, 147, 11, 13, 5, 13, 149, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 158, 10, 16, 12, 16, 14, 16, 161, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 171, 10, 17, 12, 17, 14, 17, 174, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 7, 20, 183, 10, 20, 12, 20, 14, 20, 186, 11, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 193, 10, 21, 3, 22, 3, 22, 3, 22, 5, 22, 198, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 5, 23, 206, 10, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 240, 10, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 5, 28, 248, 10, 28, 3, 29, 3, 29, 5, 29, 252, 10, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 7, 30, 259, 10, 30, 12, 30, 14, 30, 262, 11, 30, 5, 30, 264, 10, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 5, 31, 273, 10, 31, 3, 31, 3, 31, 3, 31, 3, 31, 7, 31, 279, 10, 31, 12, 31, 14, 31, 282, 11, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 2, 2, 3, 60, 38, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 2, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 294, 2, 74, 3, 2, 2, 2, 4, 77, 3, 2, 2, 2, 6, 94, 3, 2, 2, 2, 8, 104, 3, 2, 2, 2, 10, 106, 3, 2, 2, 2, 12, 115, 3, 2, 2, 2, 14, 123, 3, 2, 2, 2, 16, 125, 3, 2, 2, 2, 18, 132, 3, 2, 2, 2, 20, 136, 3, 2, 2, 2, 22, 138, 3, 2, 2, 2, 24, 148, 3, 2, 2, 2, 26, 150, 3, 2, 2, 2, 28, 153, 3, 2, 2, 2, 30, 155, 3, 2, 2, 2, 32, 165, 3, 2, 2, 2, 34, 177, 3, 2, 2, 2, 36, 179, 3, 2, 2, 2, 38, 184, 3, 2, 2, 2, 40, 192, 3, 2, 2, 2, 42, 194, 3, 2, 2, 2, 44, 203, 3, 2, 2, 2, 46, 207, 3, 2, 2, 2, 48, 212, 3, 2, 2, 2, 50, 220, 3, 2, 2, 2, 52, 228, 3, 2, 2, 2, 54, 247, 3, 2, 2, 2, 56, 249, 3, 2, 2, 2, 58, 263, 3, 2, 2, 2, 60, 272, 3, 2, 2, 2, 62, 283, 3, 2, 2, 2, 64, 287, 3, 2, 2, 2, 66, 290, 3, 2, 2, 2, 68, 295, 3, 2, 2, 2, 70, 297, 3, 2, 2, 2, 72, 299, 3, 2, 2, 2, 74, 75, 5, 4, 3, 2, 75, 76, 7, 2, 2, 3, 76, 3, 3, 2, 2, 2, 77, 78, 7, 3, 2, 2, 78, 79, 5, 6, 4, 2, 79, 83, 7, 20, 2, 2, 80, 82, 5, 8, 5, 2, 81, 80, 3, 2, 2, 2, 82, 85, 3, 2, 2, 2, 83, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 89, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 86, 88, 5, 14, 8, 2, 87, 86, 3, 2, 2, 2, 88, 91, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 92, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 92, 93, 7, 21, 2, 2, 93, 5, 3, 2, 2, 2, 94, 95, 7, 46, 2, 2, 95, 7, 3, 2, 2, 2, 96, 97, 7, 8, 2, 2, 97, 98, 5, 10, 6, 2, 98, 99, 7, 28, 2, 2, 99, 105, 3, 2, 2, 2, 100, 101, 7, 7, 2, 2, 101, 102, 5, 10, 6, 2, 102, 103, 7, 28, 2, 2, 103, 105, 3, 2, 2, 2, 104, 96, 3, 2, 2, 2, 104, 100, 3, 2, 2, 2, 105, 9, 3, 2, 2, 2, 106, 107, 5, 22, 12, 2, 107, 112, 5, 12, 7, 2, 108, 109, 7, 27, 2, 2, 109, 111, 5, 12, 7, 2, 110, 108, 3, 2, 2, 2, 111, 114, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 112, 113, 3, 2, 2, 2, 113, 11, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 115, 116, 7, 46, 2, 2, 116, 13, 3, 2, 2, 2, 117, 118, 7, 4, 2, 2, 118, 124, 5, 16, 9, 2, 119, 120, 7, 6, 2, 2, 120, 124, 5, 16, 9, 2, 121, 122, 7, 5, 2, 2, 122, 124, 5, 16, 9, 2, 123, 117, 3, 2, 2, 2, 123, 119, 3, 2, 2, 2, 123, 121, 3, 2, 2, 2, 124, 15, 3, 2, 2, 2, 125, 126, 5, 20, 11, 2, 126, 127, 5, 18, 10, 2, 127, 128, 7, 22, 2, 2, 128, 129, 5, 24, 13, 2, 129, 130, 7, 23, 2, 2, 130, 131, 5, 30, 16, 2, 131, 17, 3, 2, 2, 2, 132, 133, 7, 46, 2, 2, 133, 19, 3, 2, 2, 2, 134, 137, 5, 22, 12, 2, 135, 137, 7, 13, 2, 2, 136, 134, 3, 2, 2, 2, 136, 135, 3, 2, 2, 2, 137, 21, 3, 2, 2, 2, 138, 139, 9, 2, 2, 2, 139, 23, 3, 2, 2, 2, 140, 145, 5, 26, 14, 2, 141, 142, 7, 27, 2, 2, 142, 144, 5, 26, 14, 2, 143, 141, 3, 2, 2, 2, 144, 147, 3, 2, 2, 2, 145, 143, 3, 2, 2, 2, 145, 146, 3, 2, 2, 2, 146, 149, 3, 2, 2, 2, 147, 145, 3, 2, 2, 2, 148, 140, 3, 2, 2, 2, 148, 149, 3, 2, 2, 2, 149, 25, 3, 2, 2, 2, 150, 151, 5, 22, 12, 2, 151, 152, 5, 28, 15, 2, 152, 27, 3, 2, 2, 2, 153, 154, 7, 46, 2, 2, 154, 29, 3, 2, 2, 2, 155, 159, 7, 20, 2, 2, 156, 158, 5, 32, 17, 2, 157, 156, 3, 2, 2, 2, 158, 161, 3, 2, 2, 2, 159, 157, 3, 2, 2, 2, 159, 160, 3, 2, 2, 2, 160, 162, 3, 2, 2, 2, 161, 159, 3, 2, 2, 2, 162, 163, 5, 38, 20, 2, 163, 164, 7, 21, 2, 2, 164, 31, 3, 2, 2, 2, 165, 166, 7, 9, 2, 2, 166, 167, 5, 22, 12, 2, 167, 172, 5, 34, 18, 2, 168, 169, 7, 27, 2, 2, 169, 171, 5, 34, 18, 2, 170, 168, 3, 2, 2, 2, 171, 174, 3, 2, 2, 2, 172, 170, 3, 2, 2, 2, 172, 173, 3, 2, 2, 2, 173, 175, 3, 2, 2, 2, 174, 172, 3, 2, 2, 2, 175, 176, 7, 28, 2, 2, 176, 33, 3, 2, 2, 2, 177, 178, 7, 46, 2, 2, 178, 35, 3, 2, 2, 2, 179, 180, 7, 46, 2, 2, 180, 37, 3, 2, 2, 2, 181, 183, 5, 40, 21, 2, 182, 181, 3, 2, 2, 2, 183, 186, 3, 2, 2, 2, 184, 182, 3, 2, 2, 2, 184, 185, 3, 2, 2, 2, 185, 39, 3, 2, 2, 2, 186, 184, 3, 2, 2, 2, 187, 193, 5, 42, 22, 2, 188, 193, 5, 44, 23, 2, 189, 193, 5, 50, 26, 2, 190, 193, 5, 52, 27, 2, 191, 193, 5, 56, 29, 2, 192, 187, 3, 2, 2, 2, 192, 188, 3, 2, 2, 2, 192, 189, 3, 2, 2, 2, 192, 190, 3, 2, 2, 2, 192, 191, 3, 2, 2, 2, 193, 41, 3, 2, 2, 2, 194, 197, 7, 14, 2, 2, 195, 198, 5, 36, 19, 2, 196, 198, 5, 66, 34, 2, 197, 195, 3, 2, 2, 2, 197, 196, 3, 2, 2, 2, 198, 199, 3, 2, 2, 2, 199, 200, 7, 29, 2, 2, 200, 201, 5, 60, 31, 2, 201, 202, 7, 28, 2, 2, 202, 43, 3, 2, 2, 2, 203, 205, 5, 48, 25, 2, 204, 206, 5, 46, 24, 2, 205, 204, 3, 2, 2, 2, 205, 206, 3, 2, 2, 2, 206, 45, 3, 2, 2, 2, 207, 208, 7, 17, 2, 2, 208, 209, 7, 20, 2, 2, 209, 210, 5, 38, 20, 2, 210, 211, 7, 21, 2, 2, 211, 47, 3, 2, 2, 2, 212, 213, 7, 16, 2, 2, 213, 214, 7, 22, 2, 2, 214, 215, 5, 60, 31, 2, 215, 216, 7, 23, 2, 2, 216, 217, 7, 20, 2, 2, 217, 218, 5, 38, 20, 2, 218, 219, 7, 21, 2, 2, 219, 49, 3, 2, 2, 2, 220, 221, 7, 18, 2, 2, 221, 222, 7, 22, 2, 2, 222, 223, 5, 60, 31, 2, 223, 224, 7, 23, 2, 2, 224, 225, 7, 20, 2, 2, 225, 226, 5, 38, 20, 2, 226, 227, 7, 21, 2, 2, 227, 51, 3, 2, 2, 2, 228, 229, 7, 15, 2, 2, 229, 230, 5, 54, 28, 2, 230, 231, 7, 28, 2, 2, 231, 53, 3, 2, 2, 2, 232, 233, 5, 18, 10, 2, 233, 234, 7, 22, 2, 2, 234, 235, 5, 58, 30, 2, 235, 236, 7, 23, 2, 2, 236, 248, 3, 2, 2, 2, 237, 240, 5, 6, 4, 2, 238, 240, 7, 45, 2, 2, 239, 237, 3, 2, 2, 2, 239, 238, 3, 2, 2, 2, 240, 241, 3, 2, 2, 2, 241, 242, 7, 26, 2, 2, 242, 243, 5, 18, 10, 2, 243, 244, 7, 22, 2, 2, 244, 245, 5, 58, 30, 2, 245, 246, 7, 23, 2, 2, 246, 248, 3, 2, 2, 2, 247, 232, 3, 2, 2, 2, 247, 239, 3, 2, 2, 2, 248, 55, 3, 2, 2, 2, 249, 251, 7, 19, 2, 2, 250, 252, 5, 60, 31, 2, 251, 250, 3, 2, 2, 2, 251, 252, 3, 2, 2, 2, 252, 253, 3, 2, 2, 2, 253, 254, 7, 28, 2, 2, 254, 57, 3, 2, 2, 2, 255, 260, 5, 60, 31, 2, 256, 257, 7, 27, 2, 2, 257, 259, 5, 60, 31, 2, 258, 256, 3, 2, 2, 2, 259, 262, 3, 2, 2, 2, 260, 258, 3, 2, 2, 2, 260, 261, 3, 2, 2, 2, 261, 264, 3, 2, 2, 2, 262, 260, 3, 2, 2, 2, 263, 255, 3, 2, 2, 2, 263, 264, 3, 2, 2, 2, 264, 59, 3, 2, 2, 2, 265, 266, 8, 31, 1, 2, 266, 273, 5, 68, 35, 2, 267, 273, 5, 36, 19, 2, 268, 273, 5, 54, 28, 2, 269, 273, 5, 66, 34, 2, 270, 273, 5, 64, 33, 2, 271, 273, 5, 62, 32, 2, 272, 265, 3, 2, 2, 2, 272, 267, 3, 2, 2, 2, 272, 268, 3, 2, 2, 2, 272, 269, 3, 2, 2, 2, 272, 270, 3, 2, 2, 2, 272, 271, 3, 2, 2, 2, 273, 280, 3, 2, 2, 2, 274, 275, 12, 9, 2, 2, 275, 276, 5, 72, 37, 2, 276, 277, 5, 60, 31, 10, 277, 279, 3, 2, 2, 2, 278, 274, 3, 2, 2, 2, 279, 282, 3, 2, 2, 2, 280, 278, 3, 2, 2, 2, 280, 281, 3, 2, 2, 2, 281, 61, 3, 2, 2, 2, 282, 280, 3, 2, 2, 2, 283, 284, 7, 22, 2, 2, 284, 285, 5, 60, 31, 2, 285, 286, 7, 23, 2, 2, 286, 63, 3, 2, 2, 2, 287, 288, 5, 70, 36, 2, 288, 289, 5, 60, 31, 2, 289, 65, 3, 2, 2, 2, 290, 291, 5, 36, 19, 2, 291, 292, 7, 24, 2, 2, 292, 293, 5, 60, 31, 2, 293, 294, 7, 25, 2, 2, 294, 67, 3, 2, 2, 2, 295, 296, 9, 3, 2, 2, 296, 69, 3, 2, 2, 2, 297, 298, 9, 4, 2, 2, 298, 71, 3, 2, 2, 2, 299, 300, 9, 5, 2, 2, 300, 73, 3, 2, 2, 2, 23, 83, 89, 104, 112, 123, 136, 145, 148, 159, 172, 184, 192, 197, 205, 239, 247, 251, 260, 263, 272, 280] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 301, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 84, 10, 3, 12, 3, 14, 3, 87, 11, 3, 3, 3, 7, 3, 90, 10, 3, 12, 3, 14, 3, 93, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 107, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 113, 10, 6, 12, 6, 14, 6, 116, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 126, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 139, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 146, 10, 13, 12, 13, 14, 13, 149, 11, 13, 5, 13, 151, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 160, 10, 16, 12, 16, 14, 16, 163, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 173, 10, 17, 12, 17, 14, 17, 176, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 7, 20, 185, 10, 20, 12, 20, 14, 20, 188, 11, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 195, 10, 21, 3, 22, 3, 22, 3, 22, 5, 22, 200, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 5, 23, 208, 10, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 5, 29, 242, 10, 29, 3, 29, 5, 29, 245, 10, 29, 3, 29, 3, 29, 3, 30, 3, 30, 5, 30, 251, 10, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 7, 31, 258, 10, 31, 12, 31, 14, 31, 261, 11, 31, 5, 31, 263, 10, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 5, 32, 272, 10, 32, 3, 32, 3, 32, 3, 32, 3, 32, 7, 32, 278, 10, 32, 12, 32, 14, 32, 281, 11, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 2, 2, 3, 62, 39, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 2, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 292, 2, 76, 3, 2, 2, 2, 4, 79, 3, 2, 2, 2, 6, 96, 3, 2, 2, 2, 8, 106, 3, 2, 2, 2, 10, 108, 3, 2, 2, 2, 12, 117, 3, 2, 2, 2, 14, 125, 3, 2, 2, 2, 16, 127, 3, 2, 2, 2, 18, 134, 3, 2, 2, 2, 20, 138, 3, 2, 2, 2, 22, 140, 3, 2, 2, 2, 24, 150, 3, 2, 2, 2, 26, 152, 3, 2, 2, 2, 28, 155, 3, 2, 2, 2, 30, 157, 3, 2, 2, 2, 32, 167, 3, 2, 2, 2, 34, 179, 3, 2, 2, 2, 36, 181, 3, 2, 2, 2, 38, 186, 3, 2, 2, 2, 40, 194, 3, 2, 2, 2, 42, 196, 3, 2, 2, 2, 44, 205, 3, 2, 2, 2, 46, 209, 3, 2, 2, 2, 48, 217, 3, 2, 2, 2, 50, 222, 3, 2, 2, 2, 52, 230, 3, 2, 2, 2, 54, 234, 3, 2, 2, 2, 56, 244, 3, 2, 2, 2, 58, 248, 3, 2, 2, 2, 60, 262, 3, 2, 2, 2, 62, 271, 3, 2, 2, 2, 64, 282, 3, 2, 2, 2, 66, 286, 3, 2, 2, 2, 68, 289, 3, 2, 2, 2, 70, 294, 3, 2, 2, 2, 72, 296, 3, 2, 2, 2, 74, 298, 3, 2, 2, 2, 76, 77, 5, 4, 3, 2, 77, 78, 7, 2, 2, 3, 78, 3, 3, 2, 2, 2, 79, 80, 7, 3, 2, 2, 80, 81, 5, 6, 4, 2, 81, 85, 7, 20, 2, 2, 82, 84, 5, 8, 5, 2, 83, 82, 3, 2, 2, 2, 84, 87, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 91, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 88, 90, 5, 14, 8, 2, 89, 88, 3, 2, 2, 2, 90, 93, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 91, 92, 3, 2, 2, 2, 92, 94, 3, 2, 2, 2, 93, 91, 3, 2, 2, 2, 94, 95, 7, 21, 2, 2, 95, 5, 3, 2, 2, 2, 96, 97, 7, 46, 2, 2, 97, 7, 3, 2, 2, 2, 98, 99, 7, 8, 2, 2, 99, 100, 5, 10, 6, 2, 100, 101, 7, 28, 2, 2, 101, 107, 3, 2, 2, 2, 102, 103, 7, 7, 2, 2, 103, 104, 5, 10, 6, 2, 104, 105, 7, 28, 2, 2, 105, 107, 3, 2, 2, 2, 106, 98, 3, 2, 2, 2, 106, 102, 3, 2, 2, 2, 107, 9, 3, 2, 2, 2, 108, 109, 5, 22, 12, 2, 109, 114, 5, 12, 7, 2, 110, 111, 7, 27, 2, 2, 111, 113, 5, 12, 7, 2, 112, 110, 3, 2, 2, 2, 113, 116, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 114, 115, 3, 2, 2, 2, 115, 11, 3, 2, 2, 2, 116, 114, 3, 2, 2, 2, 117, 118, 7, 46, 2, 2, 118, 13, 3, 2, 2, 2, 119, 120, 7, 4, 2, 2, 120, 126, 5, 16, 9, 2, 121, 122, 7, 6, 2, 2, 122, 126, 5, 16, 9, 2, 123, 124, 7, 5, 2, 2, 124, 126, 5, 16, 9, 2, 125, 119, 3, 2, 2, 2, 125, 121, 3, 2, 2, 2, 125, 123, 3, 2, 2, 2, 126, 15, 3, 2, 2, 2, 127, 128, 5, 20, 11, 2, 128, 129, 5, 18, 10, 2, 129, 130, 7, 22, 2, 2, 130, 131, 5, 24, 13, 2, 131, 132, 7, 23, 2, 2, 132, 133, 5, 30, 16, 2, 133, 17, 3, 2, 2, 2, 134, 135, 7, 46, 2, 2, 135, 19, 3, 2, 2, 2, 136, 139, 5, 22, 12, 2, 137, 139, 7, 13, 2, 2, 138, 136, 3, 2, 2, 2, 138, 137, 3, 2, 2, 2, 139, 21, 3, 2, 2, 2, 140, 141, 9, 2, 2, 2, 141, 23, 3, 2, 2, 2, 142, 147, 5, 26, 14, 2, 143, 144, 7, 27, 2, 2, 144, 146, 5, 26, 14, 2, 145, 143, 3, 2, 2, 2, 146, 149, 3, 2, 2, 2, 147, 145, 3, 2, 2, 2, 147, 148, 3, 2, 2, 2, 148, 151, 3, 2, 2, 2, 149, 147, 3, 2, 2, 2, 150, 142, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 25, 3, 2, 2, 2, 152, 153, 5, 22, 12, 2, 153, 154, 5, 28, 15, 2, 154, 27, 3, 2, 2, 2, 155, 156, 7, 46, 2, 2, 156, 29, 3, 2, 2, 2, 157, 161, 7, 20, 2, 2, 158, 160, 5, 32, 17, 2, 159, 158, 3, 2, 2, 2, 160, 163, 3, 2, 2, 2, 161, 159, 3, 2, 2, 2, 161, 162, 3, 2, 2, 2, 162, 164, 3, 2, 2, 2, 163, 161, 3, 2, 2, 2, 164, 165, 5, 38, 20, 2, 165, 166, 7, 21, 2, 2, 166, 31, 3, 2, 2, 2, 167, 168, 7, 9, 2, 2, 168, 169, 5, 22, 12, 2, 169, 174, 5, 34, 18, 2, 170, 171, 7, 27, 2, 2, 171, 173, 5, 34, 18, 2, 172, 170, 3, 2, 2, 2, 173, 176, 3, 2, 2, 2, 174, 172, 3, 2, 2, 2, 174, 175, 3, 2, 2, 2, 175, 177, 3, 2, 2, 2, 176, 174, 3, 2, 2, 2, 177, 178, 7, 28, 2, 2, 178, 33, 3, 2, 2, 2, 179, 180, 7, 46, 2, 2, 180, 35, 3, 2, 2, 2, 181, 182, 7, 46, 2, 2, 182, 37, 3, 2, 2, 2, 183, 185, 5, 40, 21, 2, 184, 183, 3, 2, 2, 2, 185, 188, 3, 2, 2, 2, 186, 184, 3, 2, 2, 2, 186, 187, 3, 2, 2, 2, 187, 39, 3, 2, 2, 2, 188, 186, 3, 2, 2, 2, 189, 195, 5, 42, 22, 2, 190, 195, 5, 44, 23, 2, 191, 195, 5, 50, 26, 2, 192, 195, 5, 52, 27, 2, 193, 195, 5, 58, 30, 2, 194, 189, 3, 2, 2, 2, 194, 190, 3, 2, 2, 2, 194, 191, 3, 2, 2, 2, 194, 192, 3, 2, 2, 2, 194, 193, 3, 2, 2, 2, 195, 41, 3, 2, 2, 2, 196, 199, 7, 14, 2, 2, 197, 200, 5, 36, 19, 2, 198, 200, 5, 68, 35, 2, 199, 197, 3, 2, 2, 2, 199, 198, 3, 2, 2, 2, 200, 201, 3, 2, 2, 2, 201, 202, 7, 29, 2, 2, 202, 203, 5, 62, 32, 2, 203, 204, 7, 28, 2, 2, 204, 43, 3, 2, 2, 2, 205, 207, 5, 46, 24, 2, 206, 208, 5, 48, 25, 2, 207, 206, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 45, 3, 2, 2, 2, 209, 210, 7, 16, 2, 2, 210, 211, 7, 22, 2, 2, 211, 212, 5, 62, 32, 2, 212, 213, 7, 23, 2, 2, 213, 214, 7, 20, 2, 2, 214, 215, 5, 38, 20, 2, 215, 216, 7, 21, 2, 2, 216, 47, 3, 2, 2, 2, 217, 218, 7, 17, 2, 2, 218, 219, 7, 20, 2, 2, 219, 220, 5, 38, 20, 2, 220, 221, 7, 21, 2, 2, 221, 49, 3, 2, 2, 2, 222, 223, 7, 18, 2, 2, 223, 224, 7, 22, 2, 2, 224, 225, 5, 62, 32, 2, 225, 226, 7, 23, 2, 2, 226, 227, 7, 20, 2, 2, 227, 228, 5, 38, 20, 2, 228, 229, 7, 21, 2, 2, 229, 51, 3, 2, 2, 2, 230, 231, 7, 15, 2, 2, 231, 232, 5, 54, 28, 2, 232, 233, 7, 28, 2, 2, 233, 53, 3, 2, 2, 2, 234, 235, 5, 56, 29, 2, 235, 236, 7, 22, 2, 2, 236, 237, 5, 60, 31, 2, 237, 238, 7, 23, 2, 2, 238, 55, 3, 2, 2, 2, 239, 242, 5, 6, 4, 2, 240, 242, 7, 45, 2, 2, 241, 239, 3, 2, 2, 2, 241, 240, 3, 2, 2, 2, 242, 243, 3, 2, 2, 2, 243, 245, 7, 26, 2, 2, 244, 241, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 246, 3, 2, 2, 2, 246, 247, 5, 18, 10, 2, 247, 57, 3, 2, 2, 2, 248, 250, 7, 19, 2, 2, 249, 251, 5, 62, 32, 2, 250, 249, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 252, 3, 2, 2, 2, 252, 253, 7, 28, 2, 2, 253, 59, 3, 2, 2, 2, 254, 259, 5, 62, 32, 2, 255, 256, 7, 27, 2, 2, 256, 258, 5, 62, 32, 2, 257, 255, 3, 2, 2, 2, 258, 261, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 263, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 262, 254, 3, 2, 2, 2, 262, 263, 3, 2, 2, 2, 263, 61, 3, 2, 2, 2, 264, 265, 8, 32, 1, 2, 265, 272, 5, 70, 36, 2, 266, 272, 5, 36, 19, 2, 267, 272, 5, 54, 28, 2, 268, 272, 5, 68, 35, 2, 269, 272, 5, 66, 34, 2, 270, 272, 5, 64, 33, 2, 271, 264, 3, 2, 2, 2, 271, 266, 3, 2, 2, 2, 271, 267, 3, 2, 2, 2, 271, 268, 3, 2, 2, 2, 271, 269, 3, 2, 2, 2, 271, 270, 3, 2, 2, 2, 272, 279, 3, 2, 2, 2, 273, 274, 12, 9, 2, 2, 274, 275, 5, 74, 38, 2, 275, 276, 5, 62, 32, 10, 276, 278, 3, 2, 2, 2, 277, 273, 3, 2, 2, 2, 278, 281, 3, 2, 2, 2, 279, 277, 3, 2, 2, 2, 279, 280, 3, 2, 2, 2, 280, 63, 3, 2, 2, 2, 281, 279, 3, 2, 2, 2, 282, 283, 7, 22, 2, 2, 283, 284, 5, 62, 32, 2, 284, 285, 7, 23, 2, 2, 285, 65, 3, 2, 2, 2, 286, 287, 5, 72, 37, 2, 287, 288, 5, 62, 32, 2, 288, 67, 3, 2, 2, 2, 289, 290, 5, 36, 19, 2, 290, 291, 7, 24, 2, 2, 291, 292, 5, 62, 32, 2, 292, 293, 7, 25, 2, 2, 293, 69, 3, 2, 2, 2, 294, 295, 9, 3, 2, 2, 295, 71, 3, 2, 2, 2, 296, 297, 9, 4, 2, 2, 297, 73, 3, 2, 2, 2, 298, 299, 9, 5, 2, 2, 299, 75, 3, 2, 2, 2, 23, 85, 91, 106, 114, 125, 138, 147, 150, 161, 174, 186, 194, 199, 207, 241, 244, 250, 259, 262, 271, 279] \ No newline at end of file diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts index af837dee..0df5c0f5 100644 --- a/compiler/src/generated/JackParser.ts +++ b/compiler/src/generated/JackParser.ts @@ -96,30 +96,31 @@ export class JackParser extends Parser { public static readonly RULE_statement = 19; public static readonly RULE_letStatement = 20; public static readonly RULE_ifElseStatement = 21; - public static readonly RULE_elseStatement = 22; - public static readonly RULE_ifStatement = 23; + public static readonly RULE_ifStatement = 22; + public static readonly RULE_elseStatement = 23; public static readonly RULE_whileStatement = 24; public static readonly RULE_doStatement = 25; public static readonly RULE_subroutineCall = 26; - public static readonly RULE_returnStatement = 27; - public static readonly RULE_expressionList = 28; - public static readonly RULE_expression = 29; - public static readonly RULE_groupedExpression = 30; - public static readonly RULE_unaryOp = 31; - public static readonly RULE_arrayAccess = 32; - public static readonly RULE_constant = 33; - public static readonly RULE_unaryOperator = 34; - public static readonly RULE_binaryOperator = 35; + public static readonly RULE_subroutineId = 27; + public static readonly RULE_returnStatement = 28; + public static readonly RULE_expressionList = 29; + public static readonly RULE_expression = 30; + public static readonly RULE_groupedExpression = 31; + public static readonly RULE_unaryOp = 32; + public static readonly RULE_arrayAccess = 33; + public static readonly RULE_constant = 34; + public static readonly RULE_unaryOperator = 35; + public static readonly RULE_binaryOperator = 36; // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ "program", "classDeclaration", "className", "classVarDec", "fieldList", "fieldName", "subroutineDeclaration", "subroutineDecWithoutType", "subroutineName", "subroutineReturnType", "varType", "parameterList", "parameter", "parameterName", "subroutineBody", "varDeclaration", "varNameInDeclaration", "varName", - "statements", "statement", "letStatement", "ifElseStatement", "elseStatement", - "ifStatement", "whileStatement", "doStatement", "subroutineCall", "returnStatement", - "expressionList", "expression", "groupedExpression", "unaryOp", "arrayAccess", - "constant", "unaryOperator", "binaryOperator", + "statements", "statement", "letStatement", "ifElseStatement", "ifStatement", + "elseStatement", "whileStatement", "doStatement", "subroutineCall", "subroutineId", + "returnStatement", "expressionList", "expression", "groupedExpression", + "unaryOp", "arrayAccess", "constant", "unaryOperator", "binaryOperator", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -172,9 +173,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 72; + this.state = 74; this.classDeclaration(); - this.state = 73; + this.state = 75; this.match(JackParser.EOF); } } @@ -200,41 +201,41 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 75; + this.state = 77; this.match(JackParser.CLASS); - this.state = 76; + this.state = 78; this.className(); - this.state = 77; + this.state = 79; this.match(JackParser.LBRACE); - this.state = 81; + this.state = 83; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.FIELD || _la === JackParser.STATIC) { { { - this.state = 78; + this.state = 80; this.classVarDec(); } } - this.state = 83; + this.state = 85; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 87; + this.state = 89; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0)) { { { - this.state = 84; + this.state = 86; this.subroutineDeclaration(); } } - this.state = 89; + this.state = 91; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 90; + this.state = 92; this.match(JackParser.RBRACE); } } @@ -259,7 +260,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 92; + this.state = 94; this.match(JackParser.IDENTIFIER); } } @@ -282,18 +283,18 @@ export class JackParser extends Parser { let _localctx: ClassVarDecContext = new ClassVarDecContext(this._ctx, this.state); this.enterRule(_localctx, 6, JackParser.RULE_classVarDec); try { - this.state = 102; + this.state = 104; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.STATIC: _localctx = new StaticFieldDeclarationContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 94; + this.state = 96; this.match(JackParser.STATIC); - this.state = 95; + this.state = 97; this.fieldList(); - this.state = 96; + this.state = 98; this.match(JackParser.SEMICOLON); } break; @@ -301,11 +302,11 @@ export class JackParser extends Parser { _localctx = new FieldDeclarationContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 98; + this.state = 100; this.match(JackParser.FIELD); - this.state = 99; + this.state = 101; this.fieldList(); - this.state = 100; + this.state = 102; this.match(JackParser.SEMICOLON); } break; @@ -335,23 +336,23 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 104; + this.state = 106; this.varType(); - this.state = 105; + this.state = 107; this.fieldName(); - this.state = 110; + this.state = 112; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 106; + this.state = 108; this.match(JackParser.COMMA); - this.state = 107; + this.state = 109; this.fieldName(); } } - this.state = 112; + this.state = 114; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -378,7 +379,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 113; + this.state = 115; this.match(JackParser.IDENTIFIER); } } @@ -401,16 +402,16 @@ export class JackParser extends Parser { let _localctx: SubroutineDeclarationContext = new SubroutineDeclarationContext(this._ctx, this.state); this.enterRule(_localctx, 12, JackParser.RULE_subroutineDeclaration); try { - this.state = 121; + this.state = 123; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.CONSTRUCTOR: _localctx = new ConstructorContext(_localctx); this.enterOuterAlt(_localctx, 1); { - this.state = 115; + this.state = 117; this.match(JackParser.CONSTRUCTOR); - this.state = 116; + this.state = 118; this.subroutineDecWithoutType(); } break; @@ -418,9 +419,9 @@ export class JackParser extends Parser { _localctx = new MethodContext(_localctx); this.enterOuterAlt(_localctx, 2); { - this.state = 117; + this.state = 119; this.match(JackParser.METHOD); - this.state = 118; + this.state = 120; this.subroutineDecWithoutType(); } break; @@ -428,9 +429,9 @@ export class JackParser extends Parser { _localctx = new FunctionContext(_localctx); this.enterOuterAlt(_localctx, 3); { - this.state = 119; + this.state = 121; this.match(JackParser.FUNCTION); - this.state = 120; + this.state = 122; this.subroutineDecWithoutType(); } break; @@ -459,17 +460,17 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 123; + this.state = 125; this.subroutineReturnType(); - this.state = 124; + this.state = 126; this.subroutineName(); - this.state = 125; + this.state = 127; this.match(JackParser.LPAREN); - this.state = 126; + this.state = 128; this.parameterList(); - this.state = 127; + this.state = 129; this.match(JackParser.RPAREN); - this.state = 128; + this.state = 130; this.subroutineBody(); } } @@ -494,7 +495,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 130; + this.state = 132; this.match(JackParser.IDENTIFIER); } } @@ -517,7 +518,7 @@ export class JackParser extends Parser { let _localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this._ctx, this.state); this.enterRule(_localctx, 18, JackParser.RULE_subroutineReturnType); try { - this.state = 134; + this.state = 136; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.INT: @@ -526,14 +527,14 @@ export class JackParser extends Parser { case JackParser.IDENTIFIER: this.enterOuterAlt(_localctx, 1); { - this.state = 132; + this.state = 134; this.varType(); } break; case JackParser.VOID: this.enterOuterAlt(_localctx, 2); { - this.state = 133; + this.state = 135; this.match(JackParser.VOID); } break; @@ -563,7 +564,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 136; + this.state = 138; _la = this._input.LA(1); if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER)) { this._errHandler.recoverInline(this); @@ -599,26 +600,26 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 146; + this.state = 148; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER) { { - this.state = 138; + this.state = 140; this.parameter(); - this.state = 143; + this.state = 145; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 139; + this.state = 141; this.match(JackParser.COMMA); - this.state = 140; + this.state = 142; this.parameter(); } } - this.state = 145; + this.state = 147; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -648,9 +649,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 148; + this.state = 150; this.varType(); - this.state = 149; + this.state = 151; this.parameterName(); } } @@ -675,7 +676,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 151; + this.state = 153; this.match(JackParser.IDENTIFIER); } } @@ -701,25 +702,25 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 153; + this.state = 155; this.match(JackParser.LBRACE); - this.state = 157; + this.state = 159; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.VAR) { { { - this.state = 154; + this.state = 156; this.varDeclaration(); } } - this.state = 159; + this.state = 161; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 160; + this.state = 162; this.statements(); - this.state = 161; + this.state = 163; this.match(JackParser.RBRACE); } } @@ -745,29 +746,29 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 163; + this.state = 165; this.match(JackParser.VAR); - this.state = 164; + this.state = 166; this.varType(); - this.state = 165; + this.state = 167; this.varNameInDeclaration(); - this.state = 170; + this.state = 172; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 166; + this.state = 168; this.match(JackParser.COMMA); - this.state = 167; + this.state = 169; this.varNameInDeclaration(); } } - this.state = 172; + this.state = 174; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 173; + this.state = 175; this.match(JackParser.SEMICOLON); } } @@ -792,7 +793,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 175; + this.state = 177; this.match(JackParser.IDENTIFIER); } } @@ -817,7 +818,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 177; + this.state = 179; this.match(JackParser.IDENTIFIER); } } @@ -843,17 +844,17 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 182; + this.state = 184; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.LET) | (1 << JackParser.DO) | (1 << JackParser.IF) | (1 << JackParser.WHILE) | (1 << JackParser.RETURN))) !== 0)) { { { - this.state = 179; + this.state = 181; this.statement(); } } - this.state = 184; + this.state = 186; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -878,41 +879,41 @@ export class JackParser extends Parser { let _localctx: StatementContext = new StatementContext(this._ctx, this.state); this.enterRule(_localctx, 38, JackParser.RULE_statement); try { - this.state = 190; + this.state = 192; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.LET: this.enterOuterAlt(_localctx, 1); { - this.state = 185; + this.state = 187; this.letStatement(); } break; case JackParser.IF: this.enterOuterAlt(_localctx, 2); { - this.state = 186; + this.state = 188; this.ifElseStatement(); } break; case JackParser.WHILE: this.enterOuterAlt(_localctx, 3); { - this.state = 187; + this.state = 189; this.whileStatement(); } break; case JackParser.DO: this.enterOuterAlt(_localctx, 4); { - this.state = 188; + this.state = 190; this.doStatement(); } break; case JackParser.RETURN: this.enterOuterAlt(_localctx, 5); { - this.state = 189; + this.state = 191; this.returnStatement(); } break; @@ -941,30 +942,30 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 192; + this.state = 194; this.match(JackParser.LET); - this.state = 195; + this.state = 197; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 12, this._ctx) ) { case 1: { - this.state = 193; + this.state = 195; this.varName(); } break; case 2: { - this.state = 194; + this.state = 196; this.arrayAccess(); } break; } - this.state = 197; + this.state = 199; this.match(JackParser.EQUALS); - this.state = 198; + this.state = 200; this.expression(0); - this.state = 199; + this.state = 201; this.match(JackParser.SEMICOLON); } } @@ -990,14 +991,14 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 201; - this.ifStatement(); this.state = 203; + this.ifStatement(); + this.state = 205; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === JackParser.ELSE) { { - this.state = 202; + this.state = 204; this.elseStatement(); } } @@ -1019,19 +1020,25 @@ export class JackParser extends Parser { return _localctx; } // @RuleVersion(0) - public elseStatement(): ElseStatementContext { - let _localctx: ElseStatementContext = new ElseStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 44, JackParser.RULE_elseStatement); + public ifStatement(): IfStatementContext { + let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 44, JackParser.RULE_ifStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 205; - this.match(JackParser.ELSE); - this.state = 206; - this.match(JackParser.LBRACE); this.state = 207; - this.statements(); + this.match(JackParser.IF); this.state = 208; + this.match(JackParser.LPAREN); + this.state = 209; + this.expression(0); + this.state = 210; + this.match(JackParser.RPAREN); + this.state = 211; + this.match(JackParser.LBRACE); + this.state = 212; + this.statements(); + this.state = 213; this.match(JackParser.RBRACE); } } @@ -1050,25 +1057,19 @@ export class JackParser extends Parser { return _localctx; } // @RuleVersion(0) - public ifStatement(): IfStatementContext { - let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 46, JackParser.RULE_ifStatement); + public elseStatement(): ElseStatementContext { + let _localctx: ElseStatementContext = new ElseStatementContext(this._ctx, this.state); + this.enterRule(_localctx, 46, JackParser.RULE_elseStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 210; - this.match(JackParser.IF); - this.state = 211; - this.match(JackParser.LPAREN); - this.state = 212; - this.expression(0); - this.state = 213; - this.match(JackParser.RPAREN); - this.state = 214; - this.match(JackParser.LBRACE); this.state = 215; - this.statements(); + this.match(JackParser.ELSE); this.state = 216; + this.match(JackParser.LBRACE); + this.state = 217; + this.statements(); + this.state = 218; this.match(JackParser.RBRACE); } } @@ -1093,19 +1094,19 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 218; + this.state = 220; this.match(JackParser.WHILE); - this.state = 219; + this.state = 221; this.match(JackParser.LPAREN); - this.state = 220; + this.state = 222; this.expression(0); - this.state = 221; + this.state = 223; this.match(JackParser.RPAREN); - this.state = 222; + this.state = 224; this.match(JackParser.LBRACE); - this.state = 223; + this.state = 225; this.statements(); - this.state = 224; + this.state = 226; this.match(JackParser.RBRACE); } } @@ -1130,11 +1131,11 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 226; + this.state = 228; this.match(JackParser.DO); - this.state = 227; + this.state = 229; this.subroutineCall(); - this.state = 228; + this.state = 230; this.match(JackParser.SEMICOLON); } } @@ -1157,57 +1158,70 @@ export class JackParser extends Parser { let _localctx: SubroutineCallContext = new SubroutineCallContext(this._ctx, this.state); this.enterRule(_localctx, 52, JackParser.RULE_subroutineCall); try { - this.state = 245; + this.enterOuterAlt(_localctx, 1); + { + this.state = 232; + this.subroutineId(); + this.state = 233; + this.match(JackParser.LPAREN); + this.state = 234; + this.expressionList(); + this.state = 235; + this.match(JackParser.RPAREN); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subroutineId(): SubroutineIdContext { + let _localctx: SubroutineIdContext = new SubroutineIdContext(this._ctx, this.state); + this.enterRule(_localctx, 54, JackParser.RULE_subroutineId); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 242; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 15, this._ctx) ) { case 1: - this.enterOuterAlt(_localctx, 1); - { - this.state = 230; - this.subroutineName(); - this.state = 231; - this.match(JackParser.LPAREN); - this.state = 232; - this.expressionList(); - this.state = 233; - this.match(JackParser.RPAREN); - } - break; - - case 2: - this.enterOuterAlt(_localctx, 2); { - this.state = 237; + this.state = 239; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.IDENTIFIER: { - this.state = 235; + this.state = 237; this.className(); } break; case JackParser.THIS_LITERAL: { - this.state = 236; + this.state = 238; this.match(JackParser.THIS_LITERAL); } break; default: throw new NoViableAltException(this); } - this.state = 239; - this.match(JackParser.DOT); - this.state = 240; - this.subroutineName(); this.state = 241; - this.match(JackParser.LPAREN); - this.state = 242; - this.expressionList(); - this.state = 243; - this.match(JackParser.RPAREN); + this.match(JackParser.DOT); } break; } + this.state = 244; + this.subroutineName(); + } } catch (re) { if (re instanceof RecognitionException) { @@ -1226,24 +1240,24 @@ export class JackParser extends Parser { // @RuleVersion(0) public returnStatement(): ReturnStatementContext { let _localctx: ReturnStatementContext = new ReturnStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 54, JackParser.RULE_returnStatement); + this.enterRule(_localctx, 56, JackParser.RULE_returnStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 247; + this.state = 246; this.match(JackParser.RETURN); - this.state = 249; + this.state = 248; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 248; + this.state = 247; this.expression(0); } } - this.state = 251; + this.state = 250; this.match(JackParser.SEMICOLON); } } @@ -1264,31 +1278,31 @@ export class JackParser extends Parser { // @RuleVersion(0) public expressionList(): ExpressionListContext { let _localctx: ExpressionListContext = new ExpressionListContext(this._ctx, this.state); - this.enterRule(_localctx, 56, JackParser.RULE_expressionList); + this.enterRule(_localctx, 58, JackParser.RULE_expressionList); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 261; + this.state = 260; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 253; + this.state = 252; this.expression(0); - this.state = 258; + this.state = 257; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 254; + this.state = 253; this.match(JackParser.COMMA); - this.state = 255; + this.state = 254; this.expression(0); } } - this.state = 260; + this.state = 259; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1324,59 +1338,59 @@ export class JackParser extends Parser { let _parentState: number = this.state; let _localctx: ExpressionContext = new ExpressionContext(this._ctx, _parentState); let _prevctx: ExpressionContext = _localctx; - let _startState: number = 58; - this.enterRecursionRule(_localctx, 58, JackParser.RULE_expression, _p); + let _startState: number = 60; + this.enterRecursionRule(_localctx, 60, JackParser.RULE_expression, _p); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 270; + this.state = 269; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 19, this._ctx) ) { case 1: { - this.state = 264; + this.state = 263; this.constant(); } break; case 2: { - this.state = 265; + this.state = 264; this.varName(); } break; case 3: { - this.state = 266; + this.state = 265; this.subroutineCall(); } break; case 4: { - this.state = 267; + this.state = 266; this.arrayAccess(); } break; case 5: { - this.state = 268; + this.state = 267; this.unaryOp(); } break; case 6: { - this.state = 269; + this.state = 268; this.groupedExpression(); } break; } this._ctx._stop = this._input.tryLT(-1); - this.state = 278; + this.state = 277; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -1390,18 +1404,18 @@ export class JackParser extends Parser { _localctx = new ExpressionContext(_parentctx, _parentState); _localctx._binaryOperation = _prevctx; this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); - this.state = 272; + this.state = 271; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 273; + this.state = 272; this.binaryOperator(); - this.state = 274; + this.state = 273; this.expression(8); } } } - this.state = 280; + this.state = 279; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); } @@ -1424,15 +1438,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public groupedExpression(): GroupedExpressionContext { let _localctx: GroupedExpressionContext = new GroupedExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 60, JackParser.RULE_groupedExpression); + this.enterRule(_localctx, 62, JackParser.RULE_groupedExpression); try { this.enterOuterAlt(_localctx, 1); { - this.state = 281; + this.state = 280; this.match(JackParser.LPAREN); - this.state = 282; + this.state = 281; this.expression(0); - this.state = 283; + this.state = 282; this.match(JackParser.RPAREN); } } @@ -1453,13 +1467,13 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOp(): UnaryOpContext { let _localctx: UnaryOpContext = new UnaryOpContext(this._ctx, this.state); - this.enterRule(_localctx, 62, JackParser.RULE_unaryOp); + this.enterRule(_localctx, 64, JackParser.RULE_unaryOp); try { this.enterOuterAlt(_localctx, 1); { - this.state = 285; + this.state = 284; this.unaryOperator(); - this.state = 286; + this.state = 285; this.expression(0); } } @@ -1480,17 +1494,17 @@ export class JackParser extends Parser { // @RuleVersion(0) public arrayAccess(): ArrayAccessContext { let _localctx: ArrayAccessContext = new ArrayAccessContext(this._ctx, this.state); - this.enterRule(_localctx, 64, JackParser.RULE_arrayAccess); + this.enterRule(_localctx, 66, JackParser.RULE_arrayAccess); try { this.enterOuterAlt(_localctx, 1); { - this.state = 288; + this.state = 287; this.varName(); - this.state = 289; + this.state = 288; this.match(JackParser.LBRACKET); - this.state = 290; + this.state = 289; this.expression(0); - this.state = 291; + this.state = 290; this.match(JackParser.RBRACKET); } } @@ -1511,12 +1525,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public constant(): ConstantContext { let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 66, JackParser.RULE_constant); + this.enterRule(_localctx, 68, JackParser.RULE_constant); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 293; + this.state = 292; _la = this._input.LA(1); if (!(((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & ((1 << (JackParser.INTEGER_LITERAL - 40)) | (1 << (JackParser.BOOLEAN_LITERAL - 40)) | (1 << (JackParser.NULL_LITERAL - 40)) | (1 << (JackParser.THIS_LITERAL - 40)) | (1 << (JackParser.STRING_LITERAL - 40)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1547,12 +1561,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOperator(): UnaryOperatorContext { let _localctx: UnaryOperatorContext = new UnaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 68, JackParser.RULE_unaryOperator); + this.enterRule(_localctx, 70, JackParser.RULE_unaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 295; + this.state = 294; _la = this._input.LA(1); if (!(_la === JackParser.MINUS || _la === JackParser.TILDE)) { this._errHandler.recoverInline(this); @@ -1583,12 +1597,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public binaryOperator(): BinaryOperatorContext { let _localctx: BinaryOperatorContext = new BinaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 70, JackParser.RULE_binaryOperator); + this.enterRule(_localctx, 72, JackParser.RULE_binaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 297; + this.state = 296; _la = this._input.LA(1); if (!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & ((1 << (JackParser.EQUALS - 27)) | (1 << (JackParser.PLUS - 27)) | (1 << (JackParser.MINUS - 27)) | (1 << (JackParser.MUL - 27)) | (1 << (JackParser.DIV - 27)) | (1 << (JackParser.AND - 27)) | (1 << (JackParser.OR - 27)) | (1 << (JackParser.LESS_THAN - 27)) | (1 << (JackParser.GREATER_THAN - 27)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1619,7 +1633,7 @@ export class JackParser extends Parser { public override sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 29: + case 30: return this.expression_sempred(_localctx as ExpressionContext, predIndex); } return true; @@ -1633,136 +1647,134 @@ export class JackParser extends Parser { } public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u012E\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u012D\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + - "\t#\x04$\t$\x04%\t%\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03" + - "\x03\x07\x03R\n\x03\f\x03\x0E\x03U\v\x03\x03\x03\x07\x03X\n\x03\f\x03" + - "\x0E\x03[\v\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05" + - "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05i\n\x05\x03\x06\x03\x06" + - "\x03\x06\x03\x06\x07\x06o\n\x06\f\x06\x0E\x06r\v\x06\x03\x07\x03\x07\x03" + - "\b\x03\b\x03\b\x03\b\x03\b\x03\b\x05\b|\n\b\x03\t\x03\t\x03\t\x03\t\x03" + - "\t\x03\t\x03\t\x03\n\x03\n\x03\v\x03\v\x05\v\x89\n\v\x03\f\x03\f\x03\r" + - "\x03\r\x03\r\x07\r\x90\n\r\f\r\x0E\r\x93\v\r\x05\r\x95\n\r\x03\x0E\x03" + - "\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x10\x03\x10\x07\x10\x9E\n\x10\f\x10\x0E" + - "\x10\xA1\v\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11" + - "\x03\x11\x07\x11\xAB\n\x11\f\x11\x0E\x11\xAE\v\x11\x03\x11\x03\x11\x03" + - "\x12\x03\x12\x03\x13\x03\x13\x03\x14\x07\x14\xB7\n\x14\f\x14\x0E\x14\xBA" + - "\v\x14\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x05\x15\xC1\n\x15\x03\x16" + - "\x03\x16\x03\x16\x05\x16\xC6\n\x16\x03\x16\x03\x16\x03\x16\x03\x16\x03" + - "\x17\x03\x17\x05\x17\xCE\n\x17\x03\x18\x03\x18\x03\x18\x03\x18\x03\x18" + - "\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x1A" + - "\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B" + - "\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C" + - "\x05\x1C\xF0\n\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x05" + - "\x1C\xF8\n\x1C\x03\x1D\x03\x1D\x05\x1D\xFC\n\x1D\x03\x1D\x03\x1D\x03\x1E" + - "\x03\x1E\x03\x1E\x07\x1E\u0103\n\x1E\f\x1E\x0E\x1E\u0106\v\x1E\x05\x1E" + - "\u0108\n\x1E\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x05" + - "\x1F\u0111\n\x1F\x03\x1F\x03\x1F\x03\x1F\x03\x1F\x07\x1F\u0117\n\x1F\f" + - "\x1F\x0E\x1F\u011A\v\x1F\x03 \x03 \x03 \x03 \x03!\x03!\x03!\x03\"\x03" + - "\"\x03\"\x03\"\x03\"\x03#\x03#\x03$\x03$\x03%\x03%\x03%\x02\x02\x03<&" + - "\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14" + + "\t#\x04$\t$\x04%\t%\x04&\t&\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03" + + "\x03\x03\x03\x07\x03T\n\x03\f\x03\x0E\x03W\v\x03\x03\x03\x07\x03Z\n\x03" + + "\f\x03\x0E\x03]\v\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x05\x03\x05" + + "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05k\n\x05\x03\x06" + + "\x03\x06\x03\x06\x03\x06\x07\x06q\n\x06\f\x06\x0E\x06t\v\x06\x03\x07\x03" + + "\x07\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x05\b~\n\b\x03\t\x03\t\x03\t" + + "\x03\t\x03\t\x03\t\x03\t\x03\n\x03\n\x03\v\x03\v\x05\v\x8B\n\v\x03\f\x03" + + "\f\x03\r\x03\r\x03\r\x07\r\x92\n\r\f\r\x0E\r\x95\v\r\x05\r\x97\n\r\x03" + + "\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x10\x03\x10\x07\x10\xA0\n\x10" + + "\f\x10\x0E\x10\xA3\v\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11" + + "\x03\x11\x03\x11\x07\x11\xAD\n\x11\f\x11\x0E\x11\xB0\v\x11\x03\x11\x03" + + "\x11\x03\x12\x03\x12\x03\x13\x03\x13\x03\x14\x07\x14\xB9\n\x14\f\x14\x0E" + + "\x14\xBC\v\x14\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x05\x15\xC3\n\x15" + + "\x03\x16\x03\x16\x03\x16\x05\x16\xC8\n\x16\x03\x16\x03\x16\x03\x16\x03" + + "\x16\x03\x17\x03\x17\x05\x17\xD0\n\x17\x03\x18\x03\x18\x03\x18\x03\x18" + + "\x03\x18\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19" + + "\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B" + + "\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1D" + + "\x03\x1D\x05\x1D\xF2\n\x1D\x03\x1D\x05\x1D\xF5\n\x1D\x03\x1D\x03\x1D\x03" + + "\x1E\x03\x1E\x05\x1E\xFB\n\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03\x1F" + + "\x07\x1F\u0102\n\x1F\f\x1F\x0E\x1F\u0105\v\x1F\x05\x1F\u0107\n\x1F\x03" + + " \x03 \x03 \x03 \x03 \x03 \x03 \x05 \u0110\n \x03 \x03 \x03 \x03 \x07" + + " \u0116\n \f \x0E \u0119\v \x03!\x03!\x03!\x03!\x03\"\x03\"\x03\"\x03" + + "#\x03#\x03#\x03#\x03#\x03$\x03$\x03%\x03%\x03&\x03&\x03&\x02\x02\x03>" + + "\'\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14" + "\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02(\x02" + "*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02D\x02" + - "F\x02H\x02\x02\x06\x04\x02\n\f..\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02" + - "\x1D#%&\x02\u0126\x02J\x03\x02\x02\x02\x04M\x03\x02\x02\x02\x06^\x03\x02" + - "\x02\x02\bh\x03\x02\x02\x02\nj\x03\x02\x02\x02\fs\x03\x02\x02\x02\x0E" + - "{\x03\x02\x02\x02\x10}\x03\x02\x02\x02\x12\x84\x03\x02\x02\x02\x14\x88" + - "\x03\x02\x02\x02\x16\x8A\x03\x02\x02\x02\x18\x94\x03\x02\x02\x02\x1A\x96" + - "\x03\x02\x02\x02\x1C\x99\x03\x02\x02\x02\x1E\x9B\x03\x02\x02\x02 \xA5" + - "\x03\x02\x02\x02\"\xB1\x03\x02\x02\x02$\xB3\x03\x02\x02\x02&\xB8\x03\x02" + - "\x02\x02(\xC0\x03\x02\x02\x02*\xC2\x03\x02\x02\x02,\xCB\x03\x02\x02\x02" + - ".\xCF\x03\x02\x02\x020\xD4\x03\x02\x02\x022\xDC\x03\x02\x02\x024\xE4\x03" + - "\x02\x02\x026\xF7\x03\x02\x02\x028\xF9\x03\x02\x02\x02:\u0107\x03\x02" + - "\x02\x02<\u0110\x03\x02\x02\x02>\u011B\x03\x02\x02\x02@\u011F\x03\x02" + - "\x02\x02B\u0122\x03\x02\x02\x02D\u0127\x03\x02\x02\x02F\u0129\x03\x02" + - "\x02\x02H\u012B\x03\x02\x02\x02JK\x05\x04\x03\x02KL\x07\x02\x02\x03L\x03" + - "\x03\x02\x02\x02MN\x07\x03\x02\x02NO\x05\x06\x04\x02OS\x07\x14\x02\x02" + - "PR\x05\b\x05\x02QP\x03\x02\x02\x02RU\x03\x02\x02\x02SQ\x03\x02\x02\x02" + - "ST\x03\x02\x02\x02TY\x03\x02\x02\x02US\x03\x02\x02\x02VX\x05\x0E\b\x02" + - "WV\x03\x02\x02\x02X[\x03\x02\x02\x02YW\x03\x02\x02\x02YZ\x03\x02\x02\x02" + - "Z\\\x03\x02\x02\x02[Y\x03\x02\x02\x02\\]\x07\x15\x02\x02]\x05\x03\x02" + - "\x02\x02^_\x07.\x02\x02_\x07\x03\x02\x02\x02`a\x07\b\x02\x02ab\x05\n\x06" + - "\x02bc\x07\x1C\x02\x02ci\x03\x02\x02\x02de\x07\x07\x02\x02ef\x05\n\x06" + - "\x02fg\x07\x1C\x02\x02gi\x03\x02\x02\x02h`\x03\x02\x02\x02hd\x03\x02\x02" + - "\x02i\t\x03\x02\x02\x02jk\x05\x16\f\x02kp\x05\f\x07\x02lm\x07\x1B\x02" + - "\x02mo\x05\f\x07\x02nl\x03\x02\x02\x02or\x03\x02\x02\x02pn\x03\x02\x02" + - "\x02pq\x03\x02\x02\x02q\v\x03\x02\x02\x02rp\x03\x02\x02\x02st\x07.\x02" + - "\x02t\r\x03\x02\x02\x02uv\x07\x04\x02\x02v|\x05\x10\t\x02wx\x07\x06\x02" + - "\x02x|\x05\x10\t\x02yz\x07\x05\x02\x02z|\x05\x10\t\x02{u\x03\x02\x02\x02" + - "{w\x03\x02\x02\x02{y\x03\x02\x02\x02|\x0F\x03\x02\x02\x02}~\x05\x14\v" + - "\x02~\x7F\x05\x12\n\x02\x7F\x80\x07\x16\x02\x02\x80\x81\x05\x18\r\x02" + - "\x81\x82\x07\x17\x02\x02\x82\x83\x05\x1E\x10\x02\x83\x11\x03\x02\x02\x02" + - "\x84\x85\x07.\x02\x02\x85\x13\x03\x02\x02\x02\x86\x89\x05\x16\f\x02\x87" + - "\x89\x07\r\x02\x02\x88\x86\x03\x02\x02\x02\x88\x87\x03\x02\x02\x02\x89" + - "\x15\x03\x02\x02\x02\x8A\x8B\t\x02\x02\x02\x8B\x17\x03\x02\x02\x02\x8C" + - "\x91\x05\x1A\x0E\x02\x8D\x8E\x07\x1B\x02\x02\x8E\x90\x05\x1A\x0E\x02\x8F" + - "\x8D\x03\x02\x02\x02\x90\x93\x03\x02\x02\x02\x91\x8F\x03\x02\x02\x02\x91" + - "\x92\x03\x02\x02\x02\x92\x95\x03\x02\x02\x02\x93\x91\x03\x02\x02\x02\x94" + - "\x8C\x03\x02\x02\x02\x94\x95\x03\x02\x02\x02\x95\x19\x03\x02\x02\x02\x96" + - "\x97\x05\x16\f\x02\x97\x98\x05\x1C\x0F\x02\x98\x1B\x03\x02\x02\x02\x99" + - "\x9A\x07.\x02\x02\x9A\x1D\x03\x02\x02\x02\x9B\x9F\x07\x14\x02\x02\x9C" + - "\x9E\x05 \x11\x02\x9D\x9C\x03\x02\x02\x02\x9E\xA1\x03\x02\x02\x02\x9F" + - "\x9D\x03\x02\x02\x02\x9F\xA0\x03\x02\x02\x02\xA0\xA2\x03\x02\x02\x02\xA1" + - "\x9F\x03\x02\x02\x02\xA2\xA3\x05&\x14\x02\xA3\xA4\x07\x15\x02\x02\xA4" + - "\x1F\x03\x02\x02\x02\xA5\xA6\x07\t\x02\x02\xA6\xA7\x05\x16\f\x02\xA7\xAC" + - "\x05\"\x12\x02\xA8\xA9\x07\x1B\x02\x02\xA9\xAB\x05\"\x12\x02\xAA\xA8\x03" + - "\x02\x02\x02\xAB\xAE\x03\x02\x02\x02\xAC\xAA\x03\x02\x02\x02\xAC\xAD\x03" + - "\x02\x02\x02\xAD\xAF\x03\x02\x02\x02\xAE\xAC\x03\x02\x02\x02\xAF\xB0\x07" + - "\x1C\x02\x02\xB0!\x03\x02\x02\x02\xB1\xB2\x07.\x02\x02\xB2#\x03\x02\x02" + - "\x02\xB3\xB4\x07.\x02\x02\xB4%\x03\x02\x02\x02\xB5\xB7\x05(\x15\x02\xB6" + - "\xB5\x03\x02\x02\x02\xB7\xBA\x03\x02\x02\x02\xB8\xB6\x03\x02\x02\x02\xB8" + - "\xB9\x03\x02\x02\x02\xB9\'\x03\x02\x02\x02\xBA\xB8\x03\x02\x02\x02\xBB" + - "\xC1\x05*\x16\x02\xBC\xC1\x05,\x17\x02\xBD\xC1\x052\x1A\x02\xBE\xC1\x05" + - "4\x1B\x02\xBF\xC1\x058\x1D\x02\xC0\xBB\x03\x02\x02\x02\xC0\xBC\x03\x02" + - "\x02\x02\xC0\xBD\x03\x02\x02\x02\xC0\xBE\x03\x02\x02\x02\xC0\xBF\x03\x02" + - "\x02\x02\xC1)\x03\x02\x02\x02\xC2\xC5\x07\x0E\x02\x02\xC3\xC6\x05$\x13" + - "\x02\xC4\xC6\x05B\"\x02\xC5\xC3\x03\x02\x02\x02\xC5\xC4\x03\x02\x02\x02" + - "\xC6\xC7\x03\x02\x02\x02\xC7\xC8\x07\x1D\x02\x02\xC8\xC9\x05<\x1F\x02" + - "\xC9\xCA\x07\x1C\x02\x02\xCA+\x03\x02\x02\x02\xCB\xCD\x050\x19\x02\xCC" + - "\xCE\x05.\x18\x02\xCD\xCC\x03\x02\x02\x02\xCD\xCE\x03\x02\x02\x02\xCE" + - "-\x03\x02\x02\x02\xCF\xD0\x07\x11\x02\x02\xD0\xD1\x07\x14\x02\x02\xD1" + - "\xD2\x05&\x14\x02\xD2\xD3\x07\x15\x02\x02\xD3/\x03\x02\x02\x02\xD4\xD5" + - "\x07\x10\x02\x02\xD5\xD6\x07\x16\x02\x02\xD6\xD7\x05<\x1F\x02\xD7\xD8" + - "\x07\x17\x02\x02\xD8\xD9\x07\x14\x02\x02\xD9\xDA\x05&\x14\x02\xDA\xDB" + - "\x07\x15\x02\x02\xDB1\x03\x02\x02\x02\xDC\xDD\x07\x12\x02\x02\xDD\xDE" + - "\x07\x16\x02\x02\xDE\xDF\x05<\x1F\x02\xDF\xE0\x07\x17\x02\x02\xE0\xE1" + - "\x07\x14\x02\x02\xE1\xE2\x05&\x14\x02\xE2\xE3\x07\x15\x02\x02\xE33\x03" + - "\x02\x02\x02\xE4\xE5\x07\x0F\x02\x02\xE5\xE6\x056\x1C\x02\xE6\xE7\x07" + - "\x1C\x02\x02\xE75\x03\x02\x02\x02\xE8\xE9\x05\x12\n\x02\xE9\xEA\x07\x16" + - "\x02\x02\xEA\xEB\x05:\x1E\x02\xEB\xEC\x07\x17\x02\x02\xEC\xF8\x03\x02" + - "\x02\x02\xED\xF0\x05\x06\x04\x02\xEE\xF0\x07-\x02\x02\xEF\xED\x03\x02" + - "\x02\x02\xEF\xEE\x03\x02\x02\x02\xF0\xF1\x03\x02\x02\x02\xF1\xF2\x07\x1A" + - "\x02\x02\xF2\xF3\x05\x12\n\x02\xF3\xF4\x07\x16\x02\x02\xF4\xF5\x05:\x1E" + - "\x02\xF5\xF6\x07\x17\x02\x02\xF6\xF8\x03\x02\x02\x02\xF7\xE8\x03\x02\x02" + - "\x02\xF7\xEF\x03\x02\x02\x02\xF87\x03\x02\x02\x02\xF9\xFB\x07\x13\x02" + - "\x02\xFA\xFC\x05<\x1F\x02\xFB\xFA\x03\x02\x02\x02\xFB\xFC\x03\x02\x02" + - "\x02\xFC\xFD\x03\x02\x02\x02\xFD\xFE\x07\x1C\x02\x02\xFE9\x03\x02\x02" + - "\x02\xFF\u0104\x05<\x1F\x02\u0100\u0101\x07\x1B\x02\x02\u0101\u0103\x05" + - "<\x1F\x02\u0102\u0100\x03\x02\x02\x02\u0103\u0106\x03\x02\x02\x02\u0104" + - "\u0102\x03\x02\x02\x02\u0104\u0105\x03\x02\x02\x02\u0105\u0108\x03\x02" + - "\x02\x02\u0106\u0104\x03\x02\x02\x02\u0107\xFF\x03\x02\x02\x02\u0107\u0108" + - "\x03\x02\x02\x02\u0108;\x03\x02\x02\x02\u0109\u010A\b\x1F\x01\x02\u010A" + - "\u0111\x05D#\x02\u010B\u0111\x05$\x13\x02\u010C\u0111\x056\x1C\x02\u010D" + - "\u0111\x05B\"\x02\u010E\u0111\x05@!\x02\u010F\u0111\x05> \x02\u0110\u0109" + - "\x03\x02\x02\x02\u0110\u010B\x03\x02\x02\x02\u0110\u010C\x03\x02\x02\x02" + - "\u0110\u010D\x03\x02\x02\x02\u0110\u010E\x03\x02\x02\x02\u0110\u010F\x03" + - "\x02\x02\x02\u0111\u0118\x03\x02\x02\x02\u0112\u0113\f\t\x02\x02\u0113" + - "\u0114\x05H%\x02\u0114\u0115\x05<\x1F\n\u0115\u0117\x03\x02\x02\x02\u0116" + - "\u0112\x03\x02\x02\x02\u0117\u011A\x03\x02\x02\x02\u0118\u0116\x03\x02" + - "\x02\x02\u0118\u0119\x03\x02\x02\x02\u0119=\x03\x02\x02\x02\u011A\u0118" + - "\x03\x02\x02\x02\u011B\u011C\x07\x16\x02\x02\u011C\u011D\x05<\x1F\x02" + - "\u011D\u011E\x07\x17\x02\x02\u011E?\x03\x02\x02\x02\u011F\u0120\x05F$" + - "\x02\u0120\u0121\x05<\x1F\x02\u0121A\x03\x02\x02\x02\u0122\u0123\x05$" + - "\x13\x02\u0123\u0124\x07\x18\x02\x02\u0124\u0125\x05<\x1F\x02\u0125\u0126" + - "\x07\x19\x02\x02\u0126C\x03\x02\x02\x02\u0127\u0128\t\x03\x02\x02\u0128" + - "E\x03\x02\x02\x02\u0129\u012A\t\x04\x02\x02\u012AG\x03\x02\x02\x02\u012B" + - "\u012C\t\x05\x02\x02\u012CI\x03\x02\x02\x02\x17SYhp{\x88\x91\x94\x9F\xAC" + - "\xB8\xC0\xC5\xCD\xEF\xF7\xFB\u0104\u0107\u0110\u0118"; + "F\x02H\x02J\x02\x02\x06\x04\x02\n\f..\x04\x02*-//\x04\x02\x1F\x1F$$\x04" + + "\x02\x1D#%&\x02\u0124\x02L\x03\x02\x02\x02\x04O\x03\x02\x02\x02\x06`\x03" + + "\x02\x02\x02\bj\x03\x02\x02\x02\nl\x03\x02\x02\x02\fu\x03\x02\x02\x02" + + "\x0E}\x03\x02\x02\x02\x10\x7F\x03\x02\x02\x02\x12\x86\x03\x02\x02\x02" + + "\x14\x8A\x03\x02\x02\x02\x16\x8C\x03\x02\x02\x02\x18\x96\x03\x02\x02\x02" + + "\x1A\x98\x03\x02\x02\x02\x1C\x9B\x03\x02\x02\x02\x1E\x9D\x03\x02\x02\x02" + + " \xA7\x03\x02\x02\x02\"\xB3\x03\x02\x02\x02$\xB5\x03\x02\x02\x02&\xBA" + + "\x03\x02\x02\x02(\xC2\x03\x02\x02\x02*\xC4\x03\x02\x02\x02,\xCD\x03\x02" + + "\x02\x02.\xD1\x03\x02\x02\x020\xD9\x03\x02\x02\x022\xDE\x03\x02\x02\x02" + + "4\xE6\x03\x02\x02\x026\xEA\x03\x02\x02\x028\xF4\x03\x02\x02\x02:\xF8\x03" + + "\x02\x02\x02<\u0106\x03\x02\x02\x02>\u010F\x03\x02\x02\x02@\u011A\x03" + + "\x02\x02\x02B\u011E\x03\x02\x02\x02D\u0121\x03\x02\x02\x02F\u0126\x03" + + "\x02\x02\x02H\u0128\x03\x02\x02\x02J\u012A\x03\x02\x02\x02LM\x05\x04\x03" + + "\x02MN\x07\x02\x02\x03N\x03\x03\x02\x02\x02OP\x07\x03\x02\x02PQ\x05\x06" + + "\x04\x02QU\x07\x14\x02\x02RT\x05\b\x05\x02SR\x03\x02\x02\x02TW\x03\x02" + + "\x02\x02US\x03\x02\x02\x02UV\x03\x02\x02\x02V[\x03\x02\x02\x02WU\x03\x02" + + "\x02\x02XZ\x05\x0E\b\x02YX\x03\x02\x02\x02Z]\x03\x02\x02\x02[Y\x03\x02" + + "\x02\x02[\\\x03\x02\x02\x02\\^\x03\x02\x02\x02][\x03\x02\x02\x02^_\x07" + + "\x15\x02\x02_\x05\x03\x02\x02\x02`a\x07.\x02\x02a\x07\x03\x02\x02\x02" + + "bc\x07\b\x02\x02cd\x05\n\x06\x02de\x07\x1C\x02\x02ek\x03\x02\x02\x02f" + + "g\x07\x07\x02\x02gh\x05\n\x06\x02hi\x07\x1C\x02\x02ik\x03\x02\x02\x02" + + "jb\x03\x02\x02\x02jf\x03\x02\x02\x02k\t\x03\x02\x02\x02lm\x05\x16\f\x02" + + "mr\x05\f\x07\x02no\x07\x1B\x02\x02oq\x05\f\x07\x02pn\x03\x02\x02\x02q" + + "t\x03\x02\x02\x02rp\x03\x02\x02\x02rs\x03\x02\x02\x02s\v\x03\x02\x02\x02" + + "tr\x03\x02\x02\x02uv\x07.\x02\x02v\r\x03\x02\x02\x02wx\x07\x04\x02\x02" + + "x~\x05\x10\t\x02yz\x07\x06\x02\x02z~\x05\x10\t\x02{|\x07\x05\x02\x02|" + + "~\x05\x10\t\x02}w\x03\x02\x02\x02}y\x03\x02\x02\x02}{\x03\x02\x02\x02" + + "~\x0F\x03\x02\x02\x02\x7F\x80\x05\x14\v\x02\x80\x81\x05\x12\n\x02\x81" + + "\x82\x07\x16\x02\x02\x82\x83\x05\x18\r\x02\x83\x84\x07\x17\x02\x02\x84" + + "\x85\x05\x1E\x10\x02\x85\x11\x03\x02\x02\x02\x86\x87\x07.\x02\x02\x87" + + "\x13\x03\x02\x02\x02\x88\x8B\x05\x16\f\x02\x89\x8B\x07\r\x02\x02\x8A\x88" + + "\x03\x02\x02\x02\x8A\x89\x03\x02\x02\x02\x8B\x15\x03\x02\x02\x02\x8C\x8D" + + "\t\x02\x02\x02\x8D\x17\x03\x02\x02\x02\x8E\x93\x05\x1A\x0E\x02\x8F\x90" + + "\x07\x1B\x02\x02\x90\x92\x05\x1A\x0E\x02\x91\x8F\x03\x02\x02\x02\x92\x95" + + "\x03\x02\x02\x02\x93\x91\x03\x02\x02\x02\x93\x94\x03\x02\x02\x02\x94\x97" + + "\x03\x02\x02\x02\x95\x93\x03\x02\x02\x02\x96\x8E\x03\x02\x02\x02\x96\x97" + + "\x03\x02\x02\x02\x97\x19\x03\x02\x02\x02\x98\x99\x05\x16\f\x02\x99\x9A" + + "\x05\x1C\x0F\x02\x9A\x1B\x03\x02\x02\x02\x9B\x9C\x07.\x02\x02\x9C\x1D" + + "\x03\x02\x02\x02\x9D\xA1\x07\x14\x02\x02\x9E\xA0\x05 \x11\x02\x9F\x9E" + + "\x03\x02\x02\x02\xA0\xA3\x03\x02\x02\x02\xA1\x9F\x03\x02\x02\x02\xA1\xA2" + + "\x03\x02\x02\x02\xA2\xA4\x03\x02\x02\x02\xA3\xA1\x03\x02\x02\x02\xA4\xA5" + + "\x05&\x14\x02\xA5\xA6\x07\x15\x02\x02\xA6\x1F\x03\x02\x02\x02\xA7\xA8" + + "\x07\t\x02\x02\xA8\xA9\x05\x16\f\x02\xA9\xAE\x05\"\x12\x02\xAA\xAB\x07" + + "\x1B\x02\x02\xAB\xAD\x05\"\x12\x02\xAC\xAA\x03\x02\x02\x02\xAD\xB0\x03" + + "\x02\x02\x02\xAE\xAC\x03\x02\x02\x02\xAE\xAF\x03\x02\x02\x02\xAF\xB1\x03" + + "\x02\x02\x02\xB0\xAE\x03\x02\x02\x02\xB1\xB2\x07\x1C\x02\x02\xB2!\x03" + + "\x02\x02\x02\xB3\xB4\x07.\x02\x02\xB4#\x03\x02\x02\x02\xB5\xB6\x07.\x02" + + "\x02\xB6%\x03\x02\x02\x02\xB7\xB9\x05(\x15\x02\xB8\xB7\x03\x02\x02\x02" + + "\xB9\xBC\x03\x02\x02\x02\xBA\xB8\x03\x02\x02\x02\xBA\xBB\x03\x02\x02\x02" + + "\xBB\'\x03\x02\x02\x02\xBC\xBA\x03\x02\x02\x02\xBD\xC3\x05*\x16\x02\xBE" + + "\xC3\x05,\x17\x02\xBF\xC3\x052\x1A\x02\xC0\xC3\x054\x1B\x02\xC1\xC3\x05" + + ":\x1E\x02\xC2\xBD\x03\x02\x02\x02\xC2\xBE\x03\x02\x02\x02\xC2\xBF\x03" + + "\x02\x02\x02\xC2\xC0\x03\x02\x02\x02\xC2\xC1\x03\x02\x02\x02\xC3)\x03" + + "\x02\x02\x02\xC4\xC7\x07\x0E\x02\x02\xC5\xC8\x05$\x13\x02\xC6\xC8\x05" + + "D#\x02\xC7\xC5\x03\x02\x02\x02\xC7\xC6\x03\x02\x02\x02\xC8\xC9\x03\x02" + + "\x02\x02\xC9\xCA\x07\x1D\x02\x02\xCA\xCB\x05> \x02\xCB\xCC\x07\x1C\x02" + + "\x02\xCC+\x03\x02\x02\x02\xCD\xCF\x05.\x18\x02\xCE\xD0\x050\x19\x02\xCF" + + "\xCE\x03\x02\x02\x02\xCF\xD0\x03\x02\x02\x02\xD0-\x03\x02\x02\x02\xD1" + + "\xD2\x07\x10\x02\x02\xD2\xD3\x07\x16\x02\x02\xD3\xD4\x05> \x02\xD4\xD5" + + "\x07\x17\x02\x02\xD5\xD6\x07\x14\x02\x02\xD6\xD7\x05&\x14\x02\xD7\xD8" + + "\x07\x15\x02\x02\xD8/\x03\x02\x02\x02\xD9\xDA\x07\x11\x02\x02\xDA\xDB" + + "\x07\x14\x02\x02\xDB\xDC\x05&\x14\x02\xDC\xDD\x07\x15\x02\x02\xDD1\x03" + + "\x02\x02\x02\xDE\xDF\x07\x12\x02\x02\xDF\xE0\x07\x16\x02\x02\xE0\xE1\x05" + + "> \x02\xE1\xE2\x07\x17\x02\x02\xE2\xE3\x07\x14\x02\x02\xE3\xE4\x05&\x14" + + "\x02\xE4\xE5\x07\x15\x02\x02\xE53\x03\x02\x02\x02\xE6\xE7\x07\x0F\x02" + + "\x02\xE7\xE8\x056\x1C\x02\xE8\xE9\x07\x1C\x02\x02\xE95\x03\x02\x02\x02" + + "\xEA\xEB\x058\x1D\x02\xEB\xEC\x07\x16\x02\x02\xEC\xED\x05<\x1F\x02\xED" + + "\xEE\x07\x17\x02\x02\xEE7\x03\x02\x02\x02\xEF\xF2\x05\x06\x04\x02\xF0" + + "\xF2\x07-\x02\x02\xF1\xEF\x03\x02\x02\x02\xF1\xF0\x03\x02\x02\x02\xF2" + + "\xF3\x03\x02\x02\x02\xF3\xF5\x07\x1A\x02\x02\xF4\xF1\x03\x02\x02\x02\xF4" + + "\xF5\x03\x02\x02\x02\xF5\xF6\x03\x02\x02\x02\xF6\xF7\x05\x12\n\x02\xF7" + + "9\x03\x02\x02\x02\xF8\xFA\x07\x13\x02\x02\xF9\xFB\x05> \x02\xFA\xF9\x03" + + "\x02\x02\x02\xFA\xFB\x03\x02\x02\x02\xFB\xFC\x03\x02\x02\x02\xFC\xFD\x07" + + "\x1C\x02\x02\xFD;\x03\x02\x02\x02\xFE\u0103\x05> \x02\xFF\u0100\x07\x1B" + + "\x02\x02\u0100\u0102\x05> \x02\u0101\xFF\x03\x02\x02\x02\u0102\u0105\x03" + + "\x02\x02\x02\u0103\u0101\x03\x02\x02\x02\u0103\u0104\x03\x02\x02\x02\u0104" + + "\u0107\x03\x02\x02\x02\u0105\u0103\x03\x02\x02\x02\u0106\xFE\x03\x02\x02" + + "\x02\u0106\u0107\x03\x02\x02\x02\u0107=\x03\x02\x02\x02\u0108\u0109\b" + + " \x01\x02\u0109\u0110\x05F$\x02\u010A\u0110\x05$\x13\x02\u010B\u0110\x05" + + "6\x1C\x02\u010C\u0110\x05D#\x02\u010D\u0110\x05B\"\x02\u010E\u0110\x05" + + "@!\x02\u010F\u0108\x03\x02\x02\x02\u010F\u010A\x03\x02\x02\x02\u010F\u010B" + + "\x03\x02\x02\x02\u010F\u010C\x03\x02\x02\x02\u010F\u010D\x03\x02\x02\x02" + + "\u010F\u010E\x03\x02\x02\x02\u0110\u0117\x03\x02\x02\x02\u0111\u0112\f" + + "\t\x02\x02\u0112\u0113\x05J&\x02\u0113\u0114\x05> \n\u0114\u0116\x03\x02" + + "\x02\x02\u0115\u0111\x03\x02\x02\x02\u0116\u0119\x03\x02\x02\x02\u0117" + + "\u0115\x03\x02\x02\x02\u0117\u0118\x03\x02\x02\x02\u0118?\x03\x02\x02" + + "\x02\u0119\u0117\x03\x02\x02\x02\u011A\u011B\x07\x16\x02\x02\u011B\u011C" + + "\x05> \x02\u011C\u011D\x07\x17\x02\x02\u011DA\x03\x02\x02\x02\u011E\u011F" + + "\x05H%\x02\u011F\u0120\x05> \x02\u0120C\x03\x02\x02\x02\u0121\u0122\x05" + + "$\x13\x02\u0122\u0123\x07\x18\x02\x02\u0123\u0124\x05> \x02\u0124\u0125" + + "\x07\x19\x02\x02\u0125E\x03\x02\x02\x02\u0126\u0127\t\x03\x02\x02\u0127" + + "G\x03\x02\x02\x02\u0128\u0129\t\x04\x02\x02\u0129I\x03\x02\x02\x02\u012A" + + "\u012B\t\x05\x02\x02\u012BK\x03\x02\x02\x02\x17U[jr}\x8A\x93\x96\xA1\xAE" + + "\xBA\xC2\xC7\xCF\xF1\xF4\xFA\u0103\u0106\u010F\u0117"; public static __ATN: ATN; public static get _ATN(): ATN { if (!JackParser.__ATN) { @@ -2710,8 +2722,13 @@ export class IfElseStatementContext extends ParserRuleContext { } -export class ElseStatementContext extends ParserRuleContext { - public ELSE(): TerminalNode { return this.getToken(JackParser.ELSE, 0); } +export class IfStatementContext extends ParserRuleContext { + public IF(): TerminalNode { return this.getToken(JackParser.IF, 0); } + public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext); + } + public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } public statements(): StatementsContext { return this.getRuleContext(0, StatementsContext); @@ -2721,23 +2738,23 @@ export class ElseStatementContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public override get ruleIndex(): number { return JackParser.RULE_elseStatement; } + public override get ruleIndex(): number { return JackParser.RULE_ifStatement; } // @Override public override enterRule(listener: JackParserListener): void { - if (listener.enterElseStatement) { - listener.enterElseStatement(this); + if (listener.enterIfStatement) { + listener.enterIfStatement(this); } } // @Override public override exitRule(listener: JackParserListener): void { - if (listener.exitElseStatement) { - listener.exitElseStatement(this); + if (listener.exitIfStatement) { + listener.exitIfStatement(this); } } // @Override public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitElseStatement) { - return visitor.visitElseStatement(this); + if (visitor.visitIfStatement) { + return visitor.visitIfStatement(this); } else { return visitor.visitChildren(this); } @@ -2745,13 +2762,8 @@ export class ElseStatementContext extends ParserRuleContext { } -export class IfStatementContext extends ParserRuleContext { - public IF(): TerminalNode { return this.getToken(JackParser.IF, 0); } - public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext); - } - public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } +export class ElseStatementContext extends ParserRuleContext { + public ELSE(): TerminalNode { return this.getToken(JackParser.ELSE, 0); } public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } public statements(): StatementsContext { return this.getRuleContext(0, StatementsContext); @@ -2761,23 +2773,23 @@ export class IfStatementContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public override get ruleIndex(): number { return JackParser.RULE_ifStatement; } + public override get ruleIndex(): number { return JackParser.RULE_elseStatement; } // @Override public override enterRule(listener: JackParserListener): void { - if (listener.enterIfStatement) { - listener.enterIfStatement(this); + if (listener.enterElseStatement) { + listener.enterElseStatement(this); } } // @Override public override exitRule(listener: JackParserListener): void { - if (listener.exitIfStatement) { - listener.exitIfStatement(this); + if (listener.exitElseStatement) { + listener.exitElseStatement(this); } } // @Override public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitIfStatement) { - return visitor.visitIfStatement(this); + if (visitor.visitElseStatement) { + return visitor.visitElseStatement(this); } else { return visitor.visitChildren(this); } @@ -2860,19 +2872,14 @@ export class DoStatementContext extends ParserRuleContext { export class SubroutineCallContext extends ParserRuleContext { - public subroutineName(): SubroutineNameContext { - return this.getRuleContext(0, SubroutineNameContext); + public subroutineId(): SubroutineIdContext { + return this.getRuleContext(0, SubroutineIdContext); } public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } public expressionList(): ExpressionListContext { return this.getRuleContext(0, ExpressionListContext); } public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } - public DOT(): TerminalNode | undefined { return this.tryGetToken(JackParser.DOT, 0); } - public className(): ClassNameContext | undefined { - return this.tryGetRuleContext(0, ClassNameContext); - } - public THIS_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.THIS_LITERAL, 0); } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -2901,6 +2908,43 @@ export class SubroutineCallContext extends ParserRuleContext { } +export class SubroutineIdContext extends ParserRuleContext { + public subroutineName(): SubroutineNameContext { + return this.getRuleContext(0, SubroutineNameContext); + } + public DOT(): TerminalNode | undefined { return this.tryGetToken(JackParser.DOT, 0); } + public className(): ClassNameContext | undefined { + return this.tryGetRuleContext(0, ClassNameContext); + } + public THIS_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.THIS_LITERAL, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_subroutineId; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineId) { + listener.enterSubroutineId(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineId) { + listener.exitSubroutineId(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitSubroutineId) { + return visitor.visitSubroutineId(this); + } else { + return visitor.visitChildren(this); + } + } +} + + export class ReturnStatementContext extends ParserRuleContext { public RETURN(): TerminalNode { return this.getToken(JackParser.RETURN, 0); } public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts index d1dee688..18feef11 100644 --- a/compiler/src/generated/JackParserListener.ts +++ b/compiler/src/generated/JackParserListener.ts @@ -30,11 +30,12 @@ import { StatementsContext } from "./JackParser"; import { StatementContext } from "./JackParser"; import { LetStatementContext } from "./JackParser"; import { IfElseStatementContext } from "./JackParser"; -import { ElseStatementContext } from "./JackParser"; import { IfStatementContext } from "./JackParser"; +import { ElseStatementContext } from "./JackParser"; import { WhileStatementContext } from "./JackParser"; import { DoStatementContext } from "./JackParser"; import { SubroutineCallContext } from "./JackParser"; +import { SubroutineIdContext } from "./JackParser"; import { ReturnStatementContext } from "./JackParser"; import { ExpressionListContext } from "./JackParser"; import { ExpressionContext } from "./JackParser"; @@ -359,26 +360,26 @@ export interface JackParserListener extends ParseTreeListener { exitIfElseStatement?: (ctx: IfElseStatementContext) => void; /** - * Enter a parse tree produced by `JackParser.elseStatement`. + * Enter a parse tree produced by `JackParser.ifStatement`. * @param ctx the parse tree */ - enterElseStatement?: (ctx: ElseStatementContext) => void; + enterIfStatement?: (ctx: IfStatementContext) => void; /** - * Exit a parse tree produced by `JackParser.elseStatement`. + * Exit a parse tree produced by `JackParser.ifStatement`. * @param ctx the parse tree */ - exitElseStatement?: (ctx: ElseStatementContext) => void; + exitIfStatement?: (ctx: IfStatementContext) => void; /** - * Enter a parse tree produced by `JackParser.ifStatement`. + * Enter a parse tree produced by `JackParser.elseStatement`. * @param ctx the parse tree */ - enterIfStatement?: (ctx: IfStatementContext) => void; + enterElseStatement?: (ctx: ElseStatementContext) => void; /** - * Exit a parse tree produced by `JackParser.ifStatement`. + * Exit a parse tree produced by `JackParser.elseStatement`. * @param ctx the parse tree */ - exitIfStatement?: (ctx: IfStatementContext) => void; + exitElseStatement?: (ctx: ElseStatementContext) => void; /** * Enter a parse tree produced by `JackParser.whileStatement`. @@ -413,6 +414,17 @@ export interface JackParserListener extends ParseTreeListener { */ exitSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + enterSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + exitSubroutineId?: (ctx: SubroutineIdContext) => void; + /** * Enter a parse tree produced by `JackParser.returnStatement`. * @param ctx the parse tree diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts index a8274208..db2a78a0 100644 --- a/compiler/src/generated/JackParserVisitor.ts +++ b/compiler/src/generated/JackParserVisitor.ts @@ -30,11 +30,12 @@ import { StatementsContext } from "./JackParser"; import { StatementContext } from "./JackParser"; import { LetStatementContext } from "./JackParser"; import { IfElseStatementContext } from "./JackParser"; -import { ElseStatementContext } from "./JackParser"; import { IfStatementContext } from "./JackParser"; +import { ElseStatementContext } from "./JackParser"; import { WhileStatementContext } from "./JackParser"; import { DoStatementContext } from "./JackParser"; import { SubroutineCallContext } from "./JackParser"; +import { SubroutineIdContext } from "./JackParser"; import { ReturnStatementContext } from "./JackParser"; import { ExpressionListContext } from "./JackParser"; import { ExpressionContext } from "./JackParser"; @@ -249,18 +250,18 @@ export interface JackParserVisitor extends ParseTreeVisitor { visitIfElseStatement?: (ctx: IfElseStatementContext) => Result; /** - * Visit a parse tree produced by `JackParser.elseStatement`. + * Visit a parse tree produced by `JackParser.ifStatement`. * @param ctx the parse tree * @return the visitor result */ - visitElseStatement?: (ctx: ElseStatementContext) => Result; + visitIfStatement?: (ctx: IfStatementContext) => Result; /** - * Visit a parse tree produced by `JackParser.ifStatement`. + * Visit a parse tree produced by `JackParser.elseStatement`. * @param ctx the parse tree * @return the visitor result */ - visitIfStatement?: (ctx: IfStatementContext) => Result; + visitElseStatement?: (ctx: ElseStatementContext) => Result; /** * Visit a parse tree produced by `JackParser.whileStatement`. @@ -283,6 +284,13 @@ export interface JackParserVisitor extends ParseTreeVisitor { */ visitSubroutineCall?: (ctx: SubroutineCallContext) => Result; + /** + * Visit a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSubroutineId?: (ctx: SubroutineIdContext) => Result; + /** * Visit a parse tree produced by `JackParser.returnStatement`. * @param ctx the parse tree diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 2f950665..1eb65f54 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,7 +1,7 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { DuplicatedVariableException, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, VoidSubroutineReturnsValueError } from "../error"; -import { ClassDeclarationContext, ElseStatementContext, FieldDeclarationContext, FieldNameContext, IfElseStatementContext, IfStatementContext, LetStatementContext, ParameterContext, ParameterNameContext, ReturnStatementContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; +import { DuplicatedVariableException, IncorrectParamsNumberInSubroutineCall, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCall, VoidSubroutineReturnsValueError } from "../error"; +import { ClassDeclarationContext, ElseStatementContext, FieldDeclarationContext, FieldNameContext, IfElseStatementContext, IfStatementContext, LetStatementContext, ParameterContext, ParameterNameContext, ReturnStatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol } from "./symbol.table.listener"; @@ -66,23 +66,6 @@ enum Side { export class ValidatorListener implements JackParserListener, ParseTreeListener { - - /** - * List of validations rules: - * - variable declaration - validate duplicate variable declarations - * Let: - * - Undeclared variable - * - `Subroutine ${ subroutine.name.value }: not all code paths return a value`, - * - `A non void subroutine must return a value`, - * - Unknown type for return type, class variable, or method local var - * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface - * - validate arg number - * - `Method ${ className }.${ subroutineName } was called as a function/constructor` - * - Subroutine was called as a method - * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` - * - `Class ${className} doesn't exist` - */ - //why do we need local symbol table? this vars, arguments, local vars. What about types? localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); subroutineShouldReturnVoidType: boolean = false; @@ -101,6 +84,33 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener this.subroutineName = ctx.subroutineName().text }; + enterParameterName(ctx: ParameterNameContext) { + this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); + } + + //Var + enterVarType(ctx: VarTypeContext) { + if (ctx.IDENTIFIER() != undefined) { + const type = ctx.IDENTIFIER()!.text + if (this.globalSymbolTable[type] === undefined) { + this.errors.push(new UnknownClassError(ctx.start.line, ctx.start.startIndex, type)); + } + } + }; + + enterVarNameInDeclaration(ctx: VarNameInDeclarationContext) { + this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); + }; + + enterVarName(ctx: VarNameContext) { + if (!this.localSymbolTable.existsSymbol(ctx.text)) { + this.errors.push(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); + } + }; + + /** + * Control flow + */ enterWhileStatement(ctx: WhileStatementContext) { this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode); @@ -127,30 +137,19 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener this.cfgNode = this.cfgNode.parent } }; - - enterVarType(ctx: VarTypeContext) { - if (ctx.IDENTIFIER() != undefined) { - const type = ctx.IDENTIFIER()!.text - if (this.globalSymbolTable[type] === undefined) { - this.errors.push(new UnknownClassError(ctx.start.line, ctx.start.startIndex, type)); + enterSubroutineCall(ctx: SubroutineCallContext) { + const subroutineId = ctx.subroutineId().text + const f = this.globalSymbolTable[subroutineId] + if (f == undefined) { + this.errors.push(new UnknownSubroutineCall(ctx.start.line, ctx.start.startIndex, ctx.subroutineId().text)); + } else { + const l = ctx.expressionList().expression().length + if (f.subroutineParameterCount != l) { + this.errors.push(new IncorrectParamsNumberInSubroutineCall(ctx.start.line, ctx.start.startIndex, subroutineId, + f.subroutineParameterCount!, l)); } } }; - - - enterParameterName(ctx: ParameterNameContext) { - this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); - } - - enterVarNameInDeclaration(ctx: VarNameInDeclarationContext) { - this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); - }; - - enterVarName(ctx: VarNameContext) { - if (!this.localSymbolTable.existsSymbol(ctx.text)) { - this.errors.push(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); - } - }; enterReturnStatement(ctx: ReturnStatementContext) { const returnsVoid = ctx.expression() == undefined if (returnsVoid && !this.subroutineShouldReturnVoidType) { @@ -168,6 +167,14 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener } this.localSymbolTable.popStack(); }; + + exitClassDeclaration(ctx: ClassDeclarationContext) { + while (this.cfgNode?.parent != undefined) { + this.cfgNode = this.cfgNode.parent + } + }; + + //Utils localSymbolTableAdd(line: number, position: number, name: string) { if (this.localSymbolTable.existsSymbol(name)) { this.errors.push(new DuplicatedVariableException(line, position, name)); @@ -178,11 +185,6 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener //to fix compiler error visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; - exitClassDeclaration(ctx: ClassDeclarationContext) { - while (this.cfgNode?.parent != undefined) { - this.cfgNode = this.cfgNode.parent - } - }; } export class LocalSymbolTable { diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index b46ad0f4..28268007 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,5 +1,5 @@ import { ParserRuleContext } from "antlr4ts" -import { DuplicatedVariableException as DuplicatedVariableError, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, VoidSubroutineReturnsValueError } from "../src/error" +import { DuplicatedVariableException as DuplicatedVariableError, IncorrectParamsNumberInSubroutineCall, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCall, VoidSubroutineReturnsValueError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { GenericSymbol } from "../src/listener/symbol.table.listener" import { ValidatorListener } from "../src/listener/validator.listener" @@ -20,7 +20,10 @@ describe('ValidatorListener', () => { }); - const genericSymbol = {} as GenericSymbol + function genericSymbol(paramsCount?: number) { + return paramsCount != undefined ? { subroutineParameterCount: paramsCount } as GenericSymbol : + {} as GenericSymbol + } const duplicateVarClassBodies = [ ["static", ' static int a, a;'], @@ -67,7 +70,12 @@ describe('ValidatorListener', () => { do Main.b(a); return; } - }`, UndeclaredVariableError) + }`, UndeclaredVariableError, + { + "Main": genericSymbol(), + "Main.b": genericSymbol(1), + "Main.a": genericSymbol() + }) }) test('if - undeclared variable ', () => { @@ -89,8 +97,9 @@ describe('ValidatorListener', () => { test('Unknown class for subroutine return type ', () => { testValidator(` class Main { - function D b(int a){ - return D.new(); + function void b(int a){ + var D d; + return; } }`, UnknownClassError) }) @@ -101,7 +110,7 @@ describe('ValidatorListener', () => { function D b(int a){ return D.new(); } - }`, undefined, { "D": genericSymbol, "D.new": genericSymbol }) + }`, undefined, { "D": genericSymbol(), "D.new": genericSymbol(0) }) }) test('Arg Unknown class ', () => { testValidator(` @@ -119,7 +128,7 @@ describe('ValidatorListener', () => { function void b(D a){ return; } - }`, undefined, { "D": genericSymbol }) + }`, undefined, { "D": genericSymbol() }) }) test('var Unknown class', () => { testValidator(` @@ -137,7 +146,7 @@ describe('ValidatorListener', () => { var D d; return; } - }`, undefined, { "D": genericSymbol }) + }`, undefined, { "D": genericSymbol() }) }) test('field Unknown class', () => { testValidator(` @@ -149,7 +158,7 @@ describe('ValidatorListener', () => { testValidator(` class Main { field T t; - }`, undefined, { "T": genericSymbol }) + }`, undefined, { "T": genericSymbol() }) }) test('static field Unknown class', () => { testValidator(` @@ -161,7 +170,7 @@ describe('ValidatorListener', () => { testValidator(` class Main { static T t; - }`, undefined, { "T": genericSymbol }) + }`, undefined, { "T": genericSymbol() }) }) /** @@ -315,10 +324,38 @@ describe('ValidatorListener', () => { } }`) }) + /** + * Validate function call + */ + test('calling undefined subroutine', () => { + testValidator(` + class Main { + function void b(){ + do Main.c(); + return; + } + }`, UnknownSubroutineCall) + }) + test('incorrect number of parameters when calling a function', () => { + testValidator(` + class Main { + function void a(int a, int b){ + return; + } + function void b(){ + do Main.a(1); + return; + } + }`, IncorrectParamsNumberInSubroutineCall, { + "Main": genericSymbol(), + "Main.a": genericSymbol(2), + "Main.b": genericSymbol(2) + }) + }) + + /** * List of validations rules: - * - , - * - ``, * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface * - validate arg number * - `Method ${className}.${subroutineName} was called as a function/constructor` @@ -327,7 +364,7 @@ describe('ValidatorListener', () => { */ }) -function testValidator(src: string, expectedError?: T, globalSymbolTable: Record = {}) { +function testValidator(src: string, expectedError?: T, globalSymbolTable: Record = {}) { const name = expect.getState().currentTestName! const errorListener = new ErrorListener(); errorListener.filepath = name; @@ -335,17 +372,18 @@ function testValidator(src: string, expected const validator = listenToTheTree(tree, new ValidatorListener(globalSymbolTable)) if (expectedError) { - if (validator.cfgNode) { - validator.cfgNode.print() - } + // if (validator.cfgNode) { + // validator.cfgNode.print() + // } if (validator.errors.length > 1) { console.error("Errors", validator.errors) } - expect(validator.errors.length).toBe(1) + try { + expect(validator.errors.length).toBe(1) expect(validator.errors[0]).toBeInstanceOf(expectedError) } catch (e) { - throw new Error(`Expected error ${expectedError.name} but got ` + JSON.stringify(validator.errors[0])) + throw new Error(`Expected error ${expectedError.name} but got ` + validator.errors[0]) } } else { if (validator.errors.length != 0) throw new Error("Didn't expect any errors but got " + validator.errors.join("\n")) From 2fb01ebe75021734f3f8903f7e42a4cead29d577 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sat, 28 Sep 2024 12:07:14 +0200 Subject: [PATCH 16/87] Add builtin functions --- compiler/src/builtins.ts | 63 +++++++++++++++++++ .../src/listener/symbol.table.listener.ts | 13 ++-- compiler/src/listener/validator.listener.ts | 2 +- compiler/src/symbol.table.istener.ts | 0 compiler/src/symbol.ts | 6 ++ compiler/test/parser.test.ts | 1 + compiler/test/symbol.table.listener.test.ts | 50 ++++++++++++++- compiler/test/validator.listener.test.ts | 2 +- 8 files changed, 124 insertions(+), 13 deletions(-) create mode 100644 compiler/src/builtins.ts create mode 100644 compiler/src/symbol.table.istener.ts create mode 100644 compiler/src/symbol.ts diff --git a/compiler/src/builtins.ts b/compiler/src/builtins.ts new file mode 100644 index 00000000..0db53693 --- /dev/null +++ b/compiler/src/builtins.ts @@ -0,0 +1,63 @@ +import { GenericSymbol } from "./symbol"; + +//TODO: should we convert this to symbols? +const builtInFunctionsToArgCount: Record = { + + "Array.dispose": 0, + //TODO: what is this? + // "Array.init": 0, + "Array.new": 1, + "Keyboard.init": 0, + "Keyboard.keyPressed": 0, + "Keyboard.readChar": 0, + "Keyboard.readInt": 1, + "Keyboard.readLine": 1, + "Math.abs": 1, + "Math.divide": 2, + //TODO: what is this ? + // "Math.init": 0, + "Math.max": 2, + "Math.min": 2, + "Math.multiply": 2, + "Math.sqrt": 1, + "Memory.alloc": 1, + "Memory.deAlloc": 1, + // "Memory.init": 0, + "Memory.peek": 1, + "Memory.poke": 2, + "Output.backSpace": 0, + // "Output.init": 0, + "Output.moveCursor": 2, + "Output.printChar": 1, + "Output.printInt": 1, + "Output.println": 0, + "Output.printString": 1, + "Screen.clearScreen": 0, + "Screen.drawCircle": 3, + "Screen.drawLine": 4, + "Screen.drawPixel": 2, + "Screen.drawRectangle": 4, + // "Screen.init": 0, + "Screen.setColor": 1, + "String.appendChar": 1, + "String.backSpace": 0, + "String.charAt": 2, + "String.dispose": 0, + "String.doubleQuote": 0, + "String.eraseLastChar": 0, + // "String.init": 0, + "String.intValue": 0, + "String.length": 0, + "String.new": 1, + "String.newLine": 0, + "String.setCharAt": 1, + "String.setInt": 1, + "Sys.error": 1, + "Sys.halt": 0, + "Sys.wait": 1, +}; + +export const builtInSymbols = Object.keys(builtInFunctionsToArgCount).reduce((acc, elem) => ({ + ...acc, + [elem]: { subroutineParameterCount: builtInFunctionsToArgCount[elem] } as GenericSymbol +}), {} as Record) \ No newline at end of file diff --git a/compiler/src/listener/symbol.table.listener.ts b/compiler/src/listener/symbol.table.listener.ts index 4564614c..b2c27ae3 100644 --- a/compiler/src/listener/symbol.table.listener.ts +++ b/compiler/src/listener/symbol.table.listener.ts @@ -3,20 +3,17 @@ import { TerminalNode } from "antlr4ts/tree/TerminalNode"; import { ClassDeclarationContext, ConstructorContext, FunctionContext, MethodContext, SubroutineDecWithoutTypeContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { DuplicatedSubroutineError } from '../error' +import { builtInSymbols } from "../builtins"; +import { GenericSymbol } from "../symbol"; + const primitives = new Set(["int", "boolean", "char"] as const); export type Primitive = typeof primitives extends Set ? S : never; -/** - * Generic symbol. Can be used for both class and function symbols - */ -export interface GenericSymbol extends Symbol { - subroutineParameterCount?: number; -} -export class GlobalSymbolTableListener implements JackParserListener, ParseTreeListener { +export class GlobalSymbolTableListener implements JackParserListener, ParseTreeListener { // key can be class or . - public globalSymbolTable: Record = {}; + public globalSymbolTable: Record = structuredClone(builtInSymbols); //track class variables, local vars, function args public className = ""; public errors: DuplicatedSubroutineError[] = [] diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 1eb65f54..39ce32a8 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -3,7 +3,7 @@ import { TerminalNode } from "antlr4ts/tree/TerminalNode"; import { DuplicatedVariableException, IncorrectParamsNumberInSubroutineCall, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCall, VoidSubroutineReturnsValueError } from "../error"; import { ClassDeclarationContext, ElseStatementContext, FieldDeclarationContext, FieldNameContext, IfElseStatementContext, IfStatementContext, LetStatementContext, ParameterContext, ParameterNameContext, ReturnStatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; -import { GenericSymbol } from "./symbol.table.listener"; +import { GenericSymbol } from "../symbol"; class BinaryTreeNode { _returns?: boolean; diff --git a/compiler/src/symbol.table.istener.ts b/compiler/src/symbol.table.istener.ts new file mode 100644 index 00000000..e69de29b diff --git a/compiler/src/symbol.ts b/compiler/src/symbol.ts new file mode 100644 index 00000000..da3d6013 --- /dev/null +++ b/compiler/src/symbol.ts @@ -0,0 +1,6 @@ +/** + * Generic symbol. Can be used for both class and function symbols + */ +export interface GenericSymbol { + subroutineParameterCount?: number; +} \ No newline at end of file diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index f20996ab..3ddb83bb 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -29,6 +29,7 @@ describe('Parser', () => { "ComplexArrays" ] test.each(dirs)('%s', (dir: string) => { + console.log("Testing " + dir) testJackDir(path.join(__dirname, "resources", dir)); }); diff --git a/compiler/test/symbol.table.listener.test.ts b/compiler/test/symbol.table.listener.test.ts index 3c6f7c20..2bd2cb05 100644 --- a/compiler/test/symbol.table.listener.test.ts +++ b/compiler/test/symbol.table.listener.test.ts @@ -1,6 +1,6 @@ import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; import { ErrorListener } from "../src/listener/error.listener"; -import { GenericSymbol, GlobalSymbolTableListener } from "../src/listener/symbol.table.listener"; +import { GlobalSymbolTableListener } from "../src/listener/symbol.table.listener"; import { DuplicatedSubroutineError, JackCompilerError } from "../src/error"; import { getTestResourcePath, listenToTheTree, handleErrors, parseJackText, parseJackFile } from "./test.helper"; import fs from 'fs'; @@ -40,7 +40,52 @@ describe('Global symbol table', () => { 'Fraction.print': { subroutineParameterCount: 0 }, 'Fraction.gcd': { subroutineParameterCount: 2 }, 'Main': {}, - 'Main.main': { subroutineParameterCount: 0 } + 'Main.main': { subroutineParameterCount: 0 }, + //builtins + 'Array.dispose': { subroutineParameterCount: 0 }, + 'Array.new': { subroutineParameterCount: 1 }, + 'Keyboard.init': { subroutineParameterCount: 0 }, + 'Keyboard.keyPressed': { subroutineParameterCount: 0 }, + 'Keyboard.readChar': { subroutineParameterCount: 0 }, + 'Keyboard.readInt': { subroutineParameterCount: 1 }, + 'Keyboard.readLine': { subroutineParameterCount: 1 }, + 'Math.abs': { subroutineParameterCount: 1 }, + 'Math.divide': { subroutineParameterCount: 2 }, + 'Math.max': { subroutineParameterCount: 2 }, + 'Math.min': { subroutineParameterCount: 2 }, + 'Math.multiply': { subroutineParameterCount: 2 }, + 'Math.sqrt': { subroutineParameterCount: 1 }, + 'Memory.alloc': { subroutineParameterCount: 1 }, + 'Memory.deAlloc': { subroutineParameterCount: 1 }, + 'Memory.peek': { subroutineParameterCount: 1 }, + 'Memory.poke': { subroutineParameterCount: 2 }, + 'Output.backSpace': { subroutineParameterCount: 0 }, + 'Output.moveCursor': { subroutineParameterCount: 2 }, + 'Output.printChar': { subroutineParameterCount: 1 }, + 'Output.printInt': { subroutineParameterCount: 1 }, + 'Output.println': { subroutineParameterCount: 0 }, + 'Output.printString': { subroutineParameterCount: 1 }, + 'Screen.clearScreen': { subroutineParameterCount: 0 }, + 'Screen.drawCircle': { subroutineParameterCount: 3 }, + 'Screen.drawLine': { subroutineParameterCount: 4 }, + 'Screen.drawPixel': { subroutineParameterCount: 2 }, + 'Screen.drawRectangle': { subroutineParameterCount: 4 }, + 'Screen.setColor': { subroutineParameterCount: 1 }, + 'String.appendChar': { subroutineParameterCount: 1 }, + 'String.backSpace': { subroutineParameterCount: 0 }, + 'String.charAt': { subroutineParameterCount: 2 }, + 'String.dispose': { subroutineParameterCount: 0 }, + 'String.doubleQuote': { subroutineParameterCount: 0 }, + 'String.eraseLastChar': { subroutineParameterCount: 0 }, + 'String.intValue': { subroutineParameterCount: 0 }, + 'String.length': { subroutineParameterCount: 0 }, + 'String.new': { subroutineParameterCount: 1 }, + 'String.newLine': { subroutineParameterCount: 0 }, + 'String.setCharAt': { subroutineParameterCount: 1 }, + 'String.setInt': { subroutineParameterCount: 1 }, + 'Sys.error': { subroutineParameterCount: 1 }, + 'Sys.halt': { subroutineParameterCount: 0 }, + 'Sys.wait': { subroutineParameterCount: 1 } } let globalSymbolsListener = new GlobalSymbolTableListener() @@ -52,7 +97,6 @@ describe('Global symbol table', () => { console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) } expect(globalSymbolsListener.globalSymbolTable).toEqual(expected) - }) }) diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index 28268007..d24654b4 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,11 +1,11 @@ import { ParserRuleContext } from "antlr4ts" import { DuplicatedVariableException as DuplicatedVariableError, IncorrectParamsNumberInSubroutineCall, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCall, VoidSubroutineReturnsValueError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" -import { GenericSymbol } from "../src/listener/symbol.table.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" import { ProgramContext } from "../src/generated/JackParser" import { Logger, ILogObj } from "tslog"; +import { GenericSymbol } from "../src/symbol" const log: Logger = new Logger(); describe('ValidatorListener', () => { From 81193e262f562238914c087b8535cfbc385f9835 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sat, 28 Sep 2024 14:54:38 +0200 Subject: [PATCH 17/87] Add function/method called as function/method --- compiler/parser-gen/JackParser.g4 | 10 +- compiler/src/builtins.ts | 10 +- compiler/src/compiler.ts | 2 +- compiler/src/error.ts | 33 +- compiler/src/generated/JackParser.interp | 3 +- compiler/src/generated/JackParser.ts | 938 ++++++++---------- compiler/src/generated/JackParserListener.ts | 82 +- compiler/src/generated/JackParserVisitor.ts | 53 +- ...ner.ts => global.symbol.table.listener.ts} | 31 +- compiler/src/listener/validator.listener.ts | 121 ++- compiler/src/symbol.ts | 48 +- .../test/global.symbol.table.listener.test.ts | 104 ++ compiler/test/local.symbol.table.test.ts | 13 +- compiler/test/parser.test.ts | 2 +- compiler/test/symbol.table.listener.test.ts | 103 -- compiler/test/validator.listener.test.ts | 125 ++- 16 files changed, 845 insertions(+), 833 deletions(-) rename compiler/src/listener/{symbol.table.listener.ts => global.symbol.table.listener.ts} (58%) create mode 100644 compiler/test/global.symbol.table.listener.test.ts delete mode 100644 compiler/test/symbol.table.listener.test.ts diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/parser-gen/JackParser.g4 index 3a0d0c1c..39fad1d9 100644 --- a/compiler/parser-gen/JackParser.g4 +++ b/compiler/parser-gen/JackParser.g4 @@ -9,15 +9,11 @@ program: classDeclaration EOF; classDeclaration: CLASS className LBRACE classVarDec* subroutineDeclaration* RBRACE; className: IDENTIFIER; -classVarDec: - STATIC fieldList SEMICOLON # staticFieldDeclaration - | FIELD fieldList SEMICOLON # fieldDeclaration; +classVarDec: (STATIC | FIELD) fieldList SEMICOLON; fieldList: varType fieldName ( COMMA fieldName)*; fieldName: IDENTIFIER; -subroutineDeclaration: - CONSTRUCTOR subroutineDecWithoutType # constructor - | METHOD subroutineDecWithoutType # method - | FUNCTION subroutineDecWithoutType # function; +subroutineDeclaration: subroutineType subroutineDecWithoutType; +subroutineType: CONSTRUCTOR | METHOD | FUNCTION; subroutineDecWithoutType: subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; subroutineName: IDENTIFIER; diff --git a/compiler/src/builtins.ts b/compiler/src/builtins.ts index 0db53693..1c364919 100644 --- a/compiler/src/builtins.ts +++ b/compiler/src/builtins.ts @@ -1,5 +1,6 @@ -import { GenericSymbol } from "./symbol"; +import { GenericSymbol, SubroutineType } from "./symbol"; +export const builtInTypes = ["int", "boolean", "char"] //TODO: should we convert this to symbols? const builtInFunctionsToArgCount: Record = { @@ -59,5 +60,10 @@ const builtInFunctionsToArgCount: Record = { export const builtInSymbols = Object.keys(builtInFunctionsToArgCount).reduce((acc, elem) => ({ ...acc, - [elem]: { subroutineParameterCount: builtInFunctionsToArgCount[elem] } as GenericSymbol + [elem]: { + subroutineInfo: { + paramsCount: builtInFunctionsToArgCount[elem], + type: SubroutineType.Function + } + } as GenericSymbol }), {} as Record) \ No newline at end of file diff --git a/compiler/src/compiler.ts b/compiler/src/compiler.ts index 8d73ad0f..38558fb3 100644 --- a/compiler/src/compiler.ts +++ b/compiler/src/compiler.ts @@ -1,5 +1,5 @@ import path from "path"; -import { GlobalSymbolTableListener } from "./listener/symbol.table.listener"; +import { GlobalSymbolTableListener } from "./listener/global.symbol.table.listener"; import fs from "fs"; import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; import { JackParser } from "./generated/JackParser"; diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 8b291618..1bd9f6fd 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -70,16 +70,16 @@ export class VoidSubroutineReturnsValueError extends JackCompilerError { } -export class SubroutineNotAllPathsReturn extends JackCompilerError { +export class SubroutineNotAllPathsReturnError extends JackCompilerError { constructor(line: number, charPositionInLine: number, subroutineName: string) { super(line, charPositionInLine, `Subroutine ${subroutineName}: not all code paths return a value`); - Object.setPrototypeOf(this, SubroutineNotAllPathsReturn.prototype); + Object.setPrototypeOf(this, SubroutineNotAllPathsReturnError.prototype); } } -export class IncorrectParamsNumberInSubroutineCall extends JackCompilerError { +export class IncorrectParamsNumberInSubroutineCallError extends JackCompilerError { constructor(line: number, charPositionInLine: number, @@ -88,17 +88,32 @@ export class IncorrectParamsNumberInSubroutineCall extends JackCompilerError { actualParamsCount: number) { super(line, charPositionInLine, `Subroutine ${subroutineName} expects ${expectedParamsCount} arguments while ${actualParamsCount} was provided`); - Object.setPrototypeOf(this, IncorrectParamsNumberInSubroutineCall.prototype); + Object.setPrototypeOf(this, IncorrectParamsNumberInSubroutineCallError.prototype); } } -export class UnknownSubroutineCall extends JackCompilerError { - +export class UnknownSubroutineCallError extends JackCompilerError { + constructor(line: number, + charPositionInLine: number, + subroutineName: string, + className?: string) { + super(line, charPositionInLine, `Can't find subroutine '${subroutineName}' ${className ? `in ${className}` : ""} `); + Object.setPrototypeOf(this, UnknownSubroutineCallError.prototype); + } +} +export class MethodCalledAsFunctionError extends JackCompilerError { constructor(line: number, charPositionInLine: number, subroutineId: string) { - super(line, charPositionInLine, `Subroutine ${subroutineId} not found`); - Object.setPrototypeOf(this, UnknownSubroutineCall.prototype); + super(line, charPositionInLine, `Method ${subroutineId} was called as a function/constructor`); + Object.setPrototypeOf(this, MethodCalledAsFunctionError.prototype); + } +} +export class FunctionCalledAsMethodError extends JackCompilerError { + constructor(line: number, + charPositionInLine: number, + subroutineId: string) { + super(line, charPositionInLine, `Function or constructor ${subroutineId} was called as a method`); + Object.setPrototypeOf(this, FunctionCalledAsMethodError.prototype); } - } \ No newline at end of file diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp index 419c18a9..91b826ff 100644 --- a/compiler/src/generated/JackParser.interp +++ b/compiler/src/generated/JackParser.interp @@ -104,6 +104,7 @@ classVarDec fieldList fieldName subroutineDeclaration +subroutineType subroutineDecWithoutType subroutineName subroutineReturnType @@ -137,4 +138,4 @@ binaryOperator atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 301, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 84, 10, 3, 12, 3, 14, 3, 87, 11, 3, 3, 3, 7, 3, 90, 10, 3, 12, 3, 14, 3, 93, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 5, 5, 107, 10, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 113, 10, 6, 12, 6, 14, 6, 116, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 5, 8, 126, 10, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 5, 11, 139, 10, 11, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 7, 13, 146, 10, 13, 12, 13, 14, 13, 149, 11, 13, 5, 13, 151, 10, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 7, 16, 160, 10, 16, 12, 16, 14, 16, 163, 11, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 7, 17, 173, 10, 17, 12, 17, 14, 17, 176, 11, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 7, 20, 185, 10, 20, 12, 20, 14, 20, 188, 11, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 5, 21, 195, 10, 21, 3, 22, 3, 22, 3, 22, 5, 22, 200, 10, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 5, 23, 208, 10, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 5, 29, 242, 10, 29, 3, 29, 5, 29, 245, 10, 29, 3, 29, 3, 29, 3, 30, 3, 30, 5, 30, 251, 10, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 7, 31, 258, 10, 31, 12, 31, 14, 31, 261, 11, 31, 5, 31, 263, 10, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 5, 32, 272, 10, 32, 3, 32, 3, 32, 3, 32, 3, 32, 7, 32, 278, 10, 32, 12, 32, 14, 32, 281, 11, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 2, 2, 3, 62, 39, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 2, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 292, 2, 76, 3, 2, 2, 2, 4, 79, 3, 2, 2, 2, 6, 96, 3, 2, 2, 2, 8, 106, 3, 2, 2, 2, 10, 108, 3, 2, 2, 2, 12, 117, 3, 2, 2, 2, 14, 125, 3, 2, 2, 2, 16, 127, 3, 2, 2, 2, 18, 134, 3, 2, 2, 2, 20, 138, 3, 2, 2, 2, 22, 140, 3, 2, 2, 2, 24, 150, 3, 2, 2, 2, 26, 152, 3, 2, 2, 2, 28, 155, 3, 2, 2, 2, 30, 157, 3, 2, 2, 2, 32, 167, 3, 2, 2, 2, 34, 179, 3, 2, 2, 2, 36, 181, 3, 2, 2, 2, 38, 186, 3, 2, 2, 2, 40, 194, 3, 2, 2, 2, 42, 196, 3, 2, 2, 2, 44, 205, 3, 2, 2, 2, 46, 209, 3, 2, 2, 2, 48, 217, 3, 2, 2, 2, 50, 222, 3, 2, 2, 2, 52, 230, 3, 2, 2, 2, 54, 234, 3, 2, 2, 2, 56, 244, 3, 2, 2, 2, 58, 248, 3, 2, 2, 2, 60, 262, 3, 2, 2, 2, 62, 271, 3, 2, 2, 2, 64, 282, 3, 2, 2, 2, 66, 286, 3, 2, 2, 2, 68, 289, 3, 2, 2, 2, 70, 294, 3, 2, 2, 2, 72, 296, 3, 2, 2, 2, 74, 298, 3, 2, 2, 2, 76, 77, 5, 4, 3, 2, 77, 78, 7, 2, 2, 3, 78, 3, 3, 2, 2, 2, 79, 80, 7, 3, 2, 2, 80, 81, 5, 6, 4, 2, 81, 85, 7, 20, 2, 2, 82, 84, 5, 8, 5, 2, 83, 82, 3, 2, 2, 2, 84, 87, 3, 2, 2, 2, 85, 83, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 91, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 88, 90, 5, 14, 8, 2, 89, 88, 3, 2, 2, 2, 90, 93, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 91, 92, 3, 2, 2, 2, 92, 94, 3, 2, 2, 2, 93, 91, 3, 2, 2, 2, 94, 95, 7, 21, 2, 2, 95, 5, 3, 2, 2, 2, 96, 97, 7, 46, 2, 2, 97, 7, 3, 2, 2, 2, 98, 99, 7, 8, 2, 2, 99, 100, 5, 10, 6, 2, 100, 101, 7, 28, 2, 2, 101, 107, 3, 2, 2, 2, 102, 103, 7, 7, 2, 2, 103, 104, 5, 10, 6, 2, 104, 105, 7, 28, 2, 2, 105, 107, 3, 2, 2, 2, 106, 98, 3, 2, 2, 2, 106, 102, 3, 2, 2, 2, 107, 9, 3, 2, 2, 2, 108, 109, 5, 22, 12, 2, 109, 114, 5, 12, 7, 2, 110, 111, 7, 27, 2, 2, 111, 113, 5, 12, 7, 2, 112, 110, 3, 2, 2, 2, 113, 116, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 114, 115, 3, 2, 2, 2, 115, 11, 3, 2, 2, 2, 116, 114, 3, 2, 2, 2, 117, 118, 7, 46, 2, 2, 118, 13, 3, 2, 2, 2, 119, 120, 7, 4, 2, 2, 120, 126, 5, 16, 9, 2, 121, 122, 7, 6, 2, 2, 122, 126, 5, 16, 9, 2, 123, 124, 7, 5, 2, 2, 124, 126, 5, 16, 9, 2, 125, 119, 3, 2, 2, 2, 125, 121, 3, 2, 2, 2, 125, 123, 3, 2, 2, 2, 126, 15, 3, 2, 2, 2, 127, 128, 5, 20, 11, 2, 128, 129, 5, 18, 10, 2, 129, 130, 7, 22, 2, 2, 130, 131, 5, 24, 13, 2, 131, 132, 7, 23, 2, 2, 132, 133, 5, 30, 16, 2, 133, 17, 3, 2, 2, 2, 134, 135, 7, 46, 2, 2, 135, 19, 3, 2, 2, 2, 136, 139, 5, 22, 12, 2, 137, 139, 7, 13, 2, 2, 138, 136, 3, 2, 2, 2, 138, 137, 3, 2, 2, 2, 139, 21, 3, 2, 2, 2, 140, 141, 9, 2, 2, 2, 141, 23, 3, 2, 2, 2, 142, 147, 5, 26, 14, 2, 143, 144, 7, 27, 2, 2, 144, 146, 5, 26, 14, 2, 145, 143, 3, 2, 2, 2, 146, 149, 3, 2, 2, 2, 147, 145, 3, 2, 2, 2, 147, 148, 3, 2, 2, 2, 148, 151, 3, 2, 2, 2, 149, 147, 3, 2, 2, 2, 150, 142, 3, 2, 2, 2, 150, 151, 3, 2, 2, 2, 151, 25, 3, 2, 2, 2, 152, 153, 5, 22, 12, 2, 153, 154, 5, 28, 15, 2, 154, 27, 3, 2, 2, 2, 155, 156, 7, 46, 2, 2, 156, 29, 3, 2, 2, 2, 157, 161, 7, 20, 2, 2, 158, 160, 5, 32, 17, 2, 159, 158, 3, 2, 2, 2, 160, 163, 3, 2, 2, 2, 161, 159, 3, 2, 2, 2, 161, 162, 3, 2, 2, 2, 162, 164, 3, 2, 2, 2, 163, 161, 3, 2, 2, 2, 164, 165, 5, 38, 20, 2, 165, 166, 7, 21, 2, 2, 166, 31, 3, 2, 2, 2, 167, 168, 7, 9, 2, 2, 168, 169, 5, 22, 12, 2, 169, 174, 5, 34, 18, 2, 170, 171, 7, 27, 2, 2, 171, 173, 5, 34, 18, 2, 172, 170, 3, 2, 2, 2, 173, 176, 3, 2, 2, 2, 174, 172, 3, 2, 2, 2, 174, 175, 3, 2, 2, 2, 175, 177, 3, 2, 2, 2, 176, 174, 3, 2, 2, 2, 177, 178, 7, 28, 2, 2, 178, 33, 3, 2, 2, 2, 179, 180, 7, 46, 2, 2, 180, 35, 3, 2, 2, 2, 181, 182, 7, 46, 2, 2, 182, 37, 3, 2, 2, 2, 183, 185, 5, 40, 21, 2, 184, 183, 3, 2, 2, 2, 185, 188, 3, 2, 2, 2, 186, 184, 3, 2, 2, 2, 186, 187, 3, 2, 2, 2, 187, 39, 3, 2, 2, 2, 188, 186, 3, 2, 2, 2, 189, 195, 5, 42, 22, 2, 190, 195, 5, 44, 23, 2, 191, 195, 5, 50, 26, 2, 192, 195, 5, 52, 27, 2, 193, 195, 5, 58, 30, 2, 194, 189, 3, 2, 2, 2, 194, 190, 3, 2, 2, 2, 194, 191, 3, 2, 2, 2, 194, 192, 3, 2, 2, 2, 194, 193, 3, 2, 2, 2, 195, 41, 3, 2, 2, 2, 196, 199, 7, 14, 2, 2, 197, 200, 5, 36, 19, 2, 198, 200, 5, 68, 35, 2, 199, 197, 3, 2, 2, 2, 199, 198, 3, 2, 2, 2, 200, 201, 3, 2, 2, 2, 201, 202, 7, 29, 2, 2, 202, 203, 5, 62, 32, 2, 203, 204, 7, 28, 2, 2, 204, 43, 3, 2, 2, 2, 205, 207, 5, 46, 24, 2, 206, 208, 5, 48, 25, 2, 207, 206, 3, 2, 2, 2, 207, 208, 3, 2, 2, 2, 208, 45, 3, 2, 2, 2, 209, 210, 7, 16, 2, 2, 210, 211, 7, 22, 2, 2, 211, 212, 5, 62, 32, 2, 212, 213, 7, 23, 2, 2, 213, 214, 7, 20, 2, 2, 214, 215, 5, 38, 20, 2, 215, 216, 7, 21, 2, 2, 216, 47, 3, 2, 2, 2, 217, 218, 7, 17, 2, 2, 218, 219, 7, 20, 2, 2, 219, 220, 5, 38, 20, 2, 220, 221, 7, 21, 2, 2, 221, 49, 3, 2, 2, 2, 222, 223, 7, 18, 2, 2, 223, 224, 7, 22, 2, 2, 224, 225, 5, 62, 32, 2, 225, 226, 7, 23, 2, 2, 226, 227, 7, 20, 2, 2, 227, 228, 5, 38, 20, 2, 228, 229, 7, 21, 2, 2, 229, 51, 3, 2, 2, 2, 230, 231, 7, 15, 2, 2, 231, 232, 5, 54, 28, 2, 232, 233, 7, 28, 2, 2, 233, 53, 3, 2, 2, 2, 234, 235, 5, 56, 29, 2, 235, 236, 7, 22, 2, 2, 236, 237, 5, 60, 31, 2, 237, 238, 7, 23, 2, 2, 238, 55, 3, 2, 2, 2, 239, 242, 5, 6, 4, 2, 240, 242, 7, 45, 2, 2, 241, 239, 3, 2, 2, 2, 241, 240, 3, 2, 2, 2, 242, 243, 3, 2, 2, 2, 243, 245, 7, 26, 2, 2, 244, 241, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 246, 3, 2, 2, 2, 246, 247, 5, 18, 10, 2, 247, 57, 3, 2, 2, 2, 248, 250, 7, 19, 2, 2, 249, 251, 5, 62, 32, 2, 250, 249, 3, 2, 2, 2, 250, 251, 3, 2, 2, 2, 251, 252, 3, 2, 2, 2, 252, 253, 7, 28, 2, 2, 253, 59, 3, 2, 2, 2, 254, 259, 5, 62, 32, 2, 255, 256, 7, 27, 2, 2, 256, 258, 5, 62, 32, 2, 257, 255, 3, 2, 2, 2, 258, 261, 3, 2, 2, 2, 259, 257, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 263, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 262, 254, 3, 2, 2, 2, 262, 263, 3, 2, 2, 2, 263, 61, 3, 2, 2, 2, 264, 265, 8, 32, 1, 2, 265, 272, 5, 70, 36, 2, 266, 272, 5, 36, 19, 2, 267, 272, 5, 54, 28, 2, 268, 272, 5, 68, 35, 2, 269, 272, 5, 66, 34, 2, 270, 272, 5, 64, 33, 2, 271, 264, 3, 2, 2, 2, 271, 266, 3, 2, 2, 2, 271, 267, 3, 2, 2, 2, 271, 268, 3, 2, 2, 2, 271, 269, 3, 2, 2, 2, 271, 270, 3, 2, 2, 2, 272, 279, 3, 2, 2, 2, 273, 274, 12, 9, 2, 2, 274, 275, 5, 74, 38, 2, 275, 276, 5, 62, 32, 10, 276, 278, 3, 2, 2, 2, 277, 273, 3, 2, 2, 2, 278, 281, 3, 2, 2, 2, 279, 277, 3, 2, 2, 2, 279, 280, 3, 2, 2, 2, 280, 63, 3, 2, 2, 2, 281, 279, 3, 2, 2, 2, 282, 283, 7, 22, 2, 2, 283, 284, 5, 62, 32, 2, 284, 285, 7, 23, 2, 2, 285, 65, 3, 2, 2, 2, 286, 287, 5, 72, 37, 2, 287, 288, 5, 62, 32, 2, 288, 67, 3, 2, 2, 2, 289, 290, 5, 36, 19, 2, 290, 291, 7, 24, 2, 2, 291, 292, 5, 62, 32, 2, 292, 293, 7, 25, 2, 2, 293, 69, 3, 2, 2, 2, 294, 295, 9, 3, 2, 2, 295, 71, 3, 2, 2, 2, 296, 297, 9, 4, 2, 2, 297, 73, 3, 2, 2, 2, 298, 299, 9, 5, 2, 2, 299, 75, 3, 2, 2, 2, 23, 85, 91, 106, 114, 125, 138, 147, 150, 161, 174, 186, 194, 199, 207, 241, 244, 250, 259, 262, 271, 279] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 294, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 86, 10, 3, 12, 3, 14, 3, 89, 11, 3, 3, 3, 7, 3, 92, 10, 3, 12, 3, 14, 3, 95, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 109, 10, 6, 12, 6, 14, 6, 112, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 5, 12, 132, 10, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 7, 14, 139, 10, 14, 12, 14, 14, 14, 142, 11, 14, 5, 14, 144, 10, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 7, 17, 153, 10, 17, 12, 17, 14, 17, 156, 11, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 166, 10, 18, 12, 18, 14, 18, 169, 11, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 7, 21, 178, 10, 21, 12, 21, 14, 21, 181, 11, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 188, 10, 22, 3, 23, 3, 23, 3, 23, 5, 23, 193, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 5, 24, 201, 10, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 5, 30, 235, 10, 30, 3, 30, 5, 30, 238, 10, 30, 3, 30, 3, 30, 3, 31, 3, 31, 5, 31, 244, 10, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 7, 32, 251, 10, 32, 12, 32, 14, 32, 254, 11, 32, 5, 32, 256, 10, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 5, 33, 265, 10, 33, 3, 33, 3, 33, 3, 33, 3, 33, 7, 33, 271, 10, 33, 12, 33, 14, 33, 274, 11, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 2, 2, 3, 64, 40, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 2, 8, 3, 2, 7, 8, 3, 2, 4, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 281, 2, 78, 3, 2, 2, 2, 4, 81, 3, 2, 2, 2, 6, 98, 3, 2, 2, 2, 8, 100, 3, 2, 2, 2, 10, 104, 3, 2, 2, 2, 12, 113, 3, 2, 2, 2, 14, 115, 3, 2, 2, 2, 16, 118, 3, 2, 2, 2, 18, 120, 3, 2, 2, 2, 20, 127, 3, 2, 2, 2, 22, 131, 3, 2, 2, 2, 24, 133, 3, 2, 2, 2, 26, 143, 3, 2, 2, 2, 28, 145, 3, 2, 2, 2, 30, 148, 3, 2, 2, 2, 32, 150, 3, 2, 2, 2, 34, 160, 3, 2, 2, 2, 36, 172, 3, 2, 2, 2, 38, 174, 3, 2, 2, 2, 40, 179, 3, 2, 2, 2, 42, 187, 3, 2, 2, 2, 44, 189, 3, 2, 2, 2, 46, 198, 3, 2, 2, 2, 48, 202, 3, 2, 2, 2, 50, 210, 3, 2, 2, 2, 52, 215, 3, 2, 2, 2, 54, 223, 3, 2, 2, 2, 56, 227, 3, 2, 2, 2, 58, 237, 3, 2, 2, 2, 60, 241, 3, 2, 2, 2, 62, 255, 3, 2, 2, 2, 64, 264, 3, 2, 2, 2, 66, 275, 3, 2, 2, 2, 68, 279, 3, 2, 2, 2, 70, 282, 3, 2, 2, 2, 72, 287, 3, 2, 2, 2, 74, 289, 3, 2, 2, 2, 76, 291, 3, 2, 2, 2, 78, 79, 5, 4, 3, 2, 79, 80, 7, 2, 2, 3, 80, 3, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 6, 4, 2, 83, 87, 7, 20, 2, 2, 84, 86, 5, 8, 5, 2, 85, 84, 3, 2, 2, 2, 86, 89, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 87, 88, 3, 2, 2, 2, 88, 93, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 90, 92, 5, 14, 8, 2, 91, 90, 3, 2, 2, 2, 92, 95, 3, 2, 2, 2, 93, 91, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 96, 3, 2, 2, 2, 95, 93, 3, 2, 2, 2, 96, 97, 7, 21, 2, 2, 97, 5, 3, 2, 2, 2, 98, 99, 7, 46, 2, 2, 99, 7, 3, 2, 2, 2, 100, 101, 9, 2, 2, 2, 101, 102, 5, 10, 6, 2, 102, 103, 7, 28, 2, 2, 103, 9, 3, 2, 2, 2, 104, 105, 5, 24, 13, 2, 105, 110, 5, 12, 7, 2, 106, 107, 7, 27, 2, 2, 107, 109, 5, 12, 7, 2, 108, 106, 3, 2, 2, 2, 109, 112, 3, 2, 2, 2, 110, 108, 3, 2, 2, 2, 110, 111, 3, 2, 2, 2, 111, 11, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 113, 114, 7, 46, 2, 2, 114, 13, 3, 2, 2, 2, 115, 116, 5, 16, 9, 2, 116, 117, 5, 18, 10, 2, 117, 15, 3, 2, 2, 2, 118, 119, 9, 3, 2, 2, 119, 17, 3, 2, 2, 2, 120, 121, 5, 22, 12, 2, 121, 122, 5, 20, 11, 2, 122, 123, 7, 22, 2, 2, 123, 124, 5, 26, 14, 2, 124, 125, 7, 23, 2, 2, 125, 126, 5, 32, 17, 2, 126, 19, 3, 2, 2, 2, 127, 128, 7, 46, 2, 2, 128, 21, 3, 2, 2, 2, 129, 132, 5, 24, 13, 2, 130, 132, 7, 13, 2, 2, 131, 129, 3, 2, 2, 2, 131, 130, 3, 2, 2, 2, 132, 23, 3, 2, 2, 2, 133, 134, 9, 4, 2, 2, 134, 25, 3, 2, 2, 2, 135, 140, 5, 28, 15, 2, 136, 137, 7, 27, 2, 2, 137, 139, 5, 28, 15, 2, 138, 136, 3, 2, 2, 2, 139, 142, 3, 2, 2, 2, 140, 138, 3, 2, 2, 2, 140, 141, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 143, 135, 3, 2, 2, 2, 143, 144, 3, 2, 2, 2, 144, 27, 3, 2, 2, 2, 145, 146, 5, 24, 13, 2, 146, 147, 5, 30, 16, 2, 147, 29, 3, 2, 2, 2, 148, 149, 7, 46, 2, 2, 149, 31, 3, 2, 2, 2, 150, 154, 7, 20, 2, 2, 151, 153, 5, 34, 18, 2, 152, 151, 3, 2, 2, 2, 153, 156, 3, 2, 2, 2, 154, 152, 3, 2, 2, 2, 154, 155, 3, 2, 2, 2, 155, 157, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 157, 158, 5, 40, 21, 2, 158, 159, 7, 21, 2, 2, 159, 33, 3, 2, 2, 2, 160, 161, 7, 9, 2, 2, 161, 162, 5, 24, 13, 2, 162, 167, 5, 36, 19, 2, 163, 164, 7, 27, 2, 2, 164, 166, 5, 36, 19, 2, 165, 163, 3, 2, 2, 2, 166, 169, 3, 2, 2, 2, 167, 165, 3, 2, 2, 2, 167, 168, 3, 2, 2, 2, 168, 170, 3, 2, 2, 2, 169, 167, 3, 2, 2, 2, 170, 171, 7, 28, 2, 2, 171, 35, 3, 2, 2, 2, 172, 173, 7, 46, 2, 2, 173, 37, 3, 2, 2, 2, 174, 175, 7, 46, 2, 2, 175, 39, 3, 2, 2, 2, 176, 178, 5, 42, 22, 2, 177, 176, 3, 2, 2, 2, 178, 181, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 179, 180, 3, 2, 2, 2, 180, 41, 3, 2, 2, 2, 181, 179, 3, 2, 2, 2, 182, 188, 5, 44, 23, 2, 183, 188, 5, 46, 24, 2, 184, 188, 5, 52, 27, 2, 185, 188, 5, 54, 28, 2, 186, 188, 5, 60, 31, 2, 187, 182, 3, 2, 2, 2, 187, 183, 3, 2, 2, 2, 187, 184, 3, 2, 2, 2, 187, 185, 3, 2, 2, 2, 187, 186, 3, 2, 2, 2, 188, 43, 3, 2, 2, 2, 189, 192, 7, 14, 2, 2, 190, 193, 5, 38, 20, 2, 191, 193, 5, 70, 36, 2, 192, 190, 3, 2, 2, 2, 192, 191, 3, 2, 2, 2, 193, 194, 3, 2, 2, 2, 194, 195, 7, 29, 2, 2, 195, 196, 5, 64, 33, 2, 196, 197, 7, 28, 2, 2, 197, 45, 3, 2, 2, 2, 198, 200, 5, 48, 25, 2, 199, 201, 5, 50, 26, 2, 200, 199, 3, 2, 2, 2, 200, 201, 3, 2, 2, 2, 201, 47, 3, 2, 2, 2, 202, 203, 7, 16, 2, 2, 203, 204, 7, 22, 2, 2, 204, 205, 5, 64, 33, 2, 205, 206, 7, 23, 2, 2, 206, 207, 7, 20, 2, 2, 207, 208, 5, 40, 21, 2, 208, 209, 7, 21, 2, 2, 209, 49, 3, 2, 2, 2, 210, 211, 7, 17, 2, 2, 211, 212, 7, 20, 2, 2, 212, 213, 5, 40, 21, 2, 213, 214, 7, 21, 2, 2, 214, 51, 3, 2, 2, 2, 215, 216, 7, 18, 2, 2, 216, 217, 7, 22, 2, 2, 217, 218, 5, 64, 33, 2, 218, 219, 7, 23, 2, 2, 219, 220, 7, 20, 2, 2, 220, 221, 5, 40, 21, 2, 221, 222, 7, 21, 2, 2, 222, 53, 3, 2, 2, 2, 223, 224, 7, 15, 2, 2, 224, 225, 5, 56, 29, 2, 225, 226, 7, 28, 2, 2, 226, 55, 3, 2, 2, 2, 227, 228, 5, 58, 30, 2, 228, 229, 7, 22, 2, 2, 229, 230, 5, 62, 32, 2, 230, 231, 7, 23, 2, 2, 231, 57, 3, 2, 2, 2, 232, 235, 5, 6, 4, 2, 233, 235, 7, 45, 2, 2, 234, 232, 3, 2, 2, 2, 234, 233, 3, 2, 2, 2, 235, 236, 3, 2, 2, 2, 236, 238, 7, 26, 2, 2, 237, 234, 3, 2, 2, 2, 237, 238, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 240, 5, 20, 11, 2, 240, 59, 3, 2, 2, 2, 241, 243, 7, 19, 2, 2, 242, 244, 5, 64, 33, 2, 243, 242, 3, 2, 2, 2, 243, 244, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 246, 7, 28, 2, 2, 246, 61, 3, 2, 2, 2, 247, 252, 5, 64, 33, 2, 248, 249, 7, 27, 2, 2, 249, 251, 5, 64, 33, 2, 250, 248, 3, 2, 2, 2, 251, 254, 3, 2, 2, 2, 252, 250, 3, 2, 2, 2, 252, 253, 3, 2, 2, 2, 253, 256, 3, 2, 2, 2, 254, 252, 3, 2, 2, 2, 255, 247, 3, 2, 2, 2, 255, 256, 3, 2, 2, 2, 256, 63, 3, 2, 2, 2, 257, 258, 8, 33, 1, 2, 258, 265, 5, 72, 37, 2, 259, 265, 5, 38, 20, 2, 260, 265, 5, 56, 29, 2, 261, 265, 5, 70, 36, 2, 262, 265, 5, 68, 35, 2, 263, 265, 5, 66, 34, 2, 264, 257, 3, 2, 2, 2, 264, 259, 3, 2, 2, 2, 264, 260, 3, 2, 2, 2, 264, 261, 3, 2, 2, 2, 264, 262, 3, 2, 2, 2, 264, 263, 3, 2, 2, 2, 265, 272, 3, 2, 2, 2, 266, 267, 12, 9, 2, 2, 267, 268, 5, 76, 39, 2, 268, 269, 5, 64, 33, 10, 269, 271, 3, 2, 2, 2, 270, 266, 3, 2, 2, 2, 271, 274, 3, 2, 2, 2, 272, 270, 3, 2, 2, 2, 272, 273, 3, 2, 2, 2, 273, 65, 3, 2, 2, 2, 274, 272, 3, 2, 2, 2, 275, 276, 7, 22, 2, 2, 276, 277, 5, 64, 33, 2, 277, 278, 7, 23, 2, 2, 278, 67, 3, 2, 2, 2, 279, 280, 5, 74, 38, 2, 280, 281, 5, 64, 33, 2, 281, 69, 3, 2, 2, 2, 282, 283, 5, 38, 20, 2, 283, 284, 7, 24, 2, 2, 284, 285, 5, 64, 33, 2, 285, 286, 7, 25, 2, 2, 286, 71, 3, 2, 2, 2, 287, 288, 9, 5, 2, 2, 288, 73, 3, 2, 2, 2, 289, 290, 9, 6, 2, 2, 290, 75, 3, 2, 2, 2, 291, 292, 9, 7, 2, 2, 292, 77, 3, 2, 2, 2, 21, 87, 93, 110, 131, 140, 143, 154, 167, 179, 187, 192, 200, 234, 237, 243, 252, 255, 264, 272] \ No newline at end of file diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts index 0df5c0f5..2199555f 100644 --- a/compiler/src/generated/JackParser.ts +++ b/compiler/src/generated/JackParser.ts @@ -81,45 +81,46 @@ export class JackParser extends Parser { public static readonly RULE_fieldList = 4; public static readonly RULE_fieldName = 5; public static readonly RULE_subroutineDeclaration = 6; - public static readonly RULE_subroutineDecWithoutType = 7; - public static readonly RULE_subroutineName = 8; - public static readonly RULE_subroutineReturnType = 9; - public static readonly RULE_varType = 10; - public static readonly RULE_parameterList = 11; - public static readonly RULE_parameter = 12; - public static readonly RULE_parameterName = 13; - public static readonly RULE_subroutineBody = 14; - public static readonly RULE_varDeclaration = 15; - public static readonly RULE_varNameInDeclaration = 16; - public static readonly RULE_varName = 17; - public static readonly RULE_statements = 18; - public static readonly RULE_statement = 19; - public static readonly RULE_letStatement = 20; - public static readonly RULE_ifElseStatement = 21; - public static readonly RULE_ifStatement = 22; - public static readonly RULE_elseStatement = 23; - public static readonly RULE_whileStatement = 24; - public static readonly RULE_doStatement = 25; - public static readonly RULE_subroutineCall = 26; - public static readonly RULE_subroutineId = 27; - public static readonly RULE_returnStatement = 28; - public static readonly RULE_expressionList = 29; - public static readonly RULE_expression = 30; - public static readonly RULE_groupedExpression = 31; - public static readonly RULE_unaryOp = 32; - public static readonly RULE_arrayAccess = 33; - public static readonly RULE_constant = 34; - public static readonly RULE_unaryOperator = 35; - public static readonly RULE_binaryOperator = 36; + public static readonly RULE_subroutineType = 7; + public static readonly RULE_subroutineDecWithoutType = 8; + public static readonly RULE_subroutineName = 9; + public static readonly RULE_subroutineReturnType = 10; + public static readonly RULE_varType = 11; + public static readonly RULE_parameterList = 12; + public static readonly RULE_parameter = 13; + public static readonly RULE_parameterName = 14; + public static readonly RULE_subroutineBody = 15; + public static readonly RULE_varDeclaration = 16; + public static readonly RULE_varNameInDeclaration = 17; + public static readonly RULE_varName = 18; + public static readonly RULE_statements = 19; + public static readonly RULE_statement = 20; + public static readonly RULE_letStatement = 21; + public static readonly RULE_ifElseStatement = 22; + public static readonly RULE_ifStatement = 23; + public static readonly RULE_elseStatement = 24; + public static readonly RULE_whileStatement = 25; + public static readonly RULE_doStatement = 26; + public static readonly RULE_subroutineCall = 27; + public static readonly RULE_subroutineId = 28; + public static readonly RULE_returnStatement = 29; + public static readonly RULE_expressionList = 30; + public static readonly RULE_expression = 31; + public static readonly RULE_groupedExpression = 32; + public static readonly RULE_unaryOp = 33; + public static readonly RULE_arrayAccess = 34; + public static readonly RULE_constant = 35; + public static readonly RULE_unaryOperator = 36; + public static readonly RULE_binaryOperator = 37; // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ "program", "classDeclaration", "className", "classVarDec", "fieldList", - "fieldName", "subroutineDeclaration", "subroutineDecWithoutType", "subroutineName", - "subroutineReturnType", "varType", "parameterList", "parameter", "parameterName", - "subroutineBody", "varDeclaration", "varNameInDeclaration", "varName", - "statements", "statement", "letStatement", "ifElseStatement", "ifStatement", - "elseStatement", "whileStatement", "doStatement", "subroutineCall", "subroutineId", - "returnStatement", "expressionList", "expression", "groupedExpression", + "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", + "subroutineName", "subroutineReturnType", "varType", "parameterList", + "parameter", "parameterName", "subroutineBody", "varDeclaration", "varNameInDeclaration", + "varName", "statements", "statement", "letStatement", "ifElseStatement", + "ifStatement", "elseStatement", "whileStatement", "doStatement", "subroutineCall", + "subroutineId", "returnStatement", "expressionList", "expression", "groupedExpression", "unaryOp", "arrayAccess", "constant", "unaryOperator", "binaryOperator", ]; @@ -173,9 +174,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 74; + this.state = 76; this.classDeclaration(); - this.state = 75; + this.state = 77; this.match(JackParser.EOF); } } @@ -201,41 +202,41 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 77; + this.state = 79; this.match(JackParser.CLASS); - this.state = 78; + this.state = 80; this.className(); - this.state = 79; + this.state = 81; this.match(JackParser.LBRACE); - this.state = 83; + this.state = 85; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.FIELD || _la === JackParser.STATIC) { { { - this.state = 80; + this.state = 82; this.classVarDec(); } } - this.state = 85; + this.state = 87; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 89; + this.state = 91; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0)) { { { - this.state = 86; + this.state = 88; this.subroutineDeclaration(); } } - this.state = 91; + this.state = 93; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 92; + this.state = 94; this.match(JackParser.RBRACE); } } @@ -260,7 +261,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 94; + this.state = 96; this.match(JackParser.IDENTIFIER); } } @@ -282,36 +283,26 @@ export class JackParser extends Parser { public classVarDec(): ClassVarDecContext { let _localctx: ClassVarDecContext = new ClassVarDecContext(this._ctx, this.state); this.enterRule(_localctx, 6, JackParser.RULE_classVarDec); + let _la: number; try { - this.state = 104; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case JackParser.STATIC: - _localctx = new StaticFieldDeclarationContext(_localctx); - this.enterOuterAlt(_localctx, 1); - { - this.state = 96; - this.match(JackParser.STATIC); - this.state = 97; - this.fieldList(); - this.state = 98; - this.match(JackParser.SEMICOLON); - } - break; - case JackParser.FIELD: - _localctx = new FieldDeclarationContext(_localctx); - this.enterOuterAlt(_localctx, 2); - { - this.state = 100; - this.match(JackParser.FIELD); - this.state = 101; - this.fieldList(); - this.state = 102; - this.match(JackParser.SEMICOLON); + this.enterOuterAlt(_localctx, 1); + { + this.state = 98; + _la = this._input.LA(1); + if (!(_la === JackParser.FIELD || _la === JackParser.STATIC)) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; } - break; - default: - throw new NoViableAltException(this); + + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 99; + this.fieldList(); + this.state = 100; + this.match(JackParser.SEMICOLON); } } catch (re) { @@ -336,23 +327,23 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 106; + this.state = 102; this.varType(); - this.state = 107; + this.state = 103; this.fieldName(); - this.state = 112; + this.state = 108; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 108; + this.state = 104; this.match(JackParser.COMMA); - this.state = 109; + this.state = 105; this.fieldName(); } } - this.state = 114; + this.state = 110; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -379,7 +370,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 115; + this.state = 111; this.match(JackParser.IDENTIFIER); } } @@ -402,41 +393,48 @@ export class JackParser extends Parser { let _localctx: SubroutineDeclarationContext = new SubroutineDeclarationContext(this._ctx, this.state); this.enterRule(_localctx, 12, JackParser.RULE_subroutineDeclaration); try { - this.state = 123; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case JackParser.CONSTRUCTOR: - _localctx = new ConstructorContext(_localctx); - this.enterOuterAlt(_localctx, 1); - { - this.state = 117; - this.match(JackParser.CONSTRUCTOR); - this.state = 118; - this.subroutineDecWithoutType(); - } - break; - case JackParser.METHOD: - _localctx = new MethodContext(_localctx); - this.enterOuterAlt(_localctx, 2); - { - this.state = 119; - this.match(JackParser.METHOD); - this.state = 120; - this.subroutineDecWithoutType(); - } - break; - case JackParser.FUNCTION: - _localctx = new FunctionContext(_localctx); - this.enterOuterAlt(_localctx, 3); - { - this.state = 121; - this.match(JackParser.FUNCTION); - this.state = 122; - this.subroutineDecWithoutType(); + this.enterOuterAlt(_localctx, 1); + { + this.state = 113; + this.subroutineType(); + this.state = 114; + this.subroutineDecWithoutType(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public subroutineType(): SubroutineTypeContext { + let _localctx: SubroutineTypeContext = new SubroutineTypeContext(this._ctx, this.state); + this.enterRule(_localctx, 14, JackParser.RULE_subroutineType); + let _la: number; + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 116; + _la = this._input.LA(1); + if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0))) { + this._errHandler.recoverInline(this); + } else { + if (this._input.LA(1) === Token.EOF) { + this.matchedEOF = true; } - break; - default: - throw new NoViableAltException(this); + + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -456,21 +454,21 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { let _localctx: SubroutineDecWithoutTypeContext = new SubroutineDecWithoutTypeContext(this._ctx, this.state); - this.enterRule(_localctx, 14, JackParser.RULE_subroutineDecWithoutType); + this.enterRule(_localctx, 16, JackParser.RULE_subroutineDecWithoutType); try { this.enterOuterAlt(_localctx, 1); { - this.state = 125; + this.state = 118; this.subroutineReturnType(); - this.state = 126; + this.state = 119; this.subroutineName(); - this.state = 127; + this.state = 120; this.match(JackParser.LPAREN); - this.state = 128; + this.state = 121; this.parameterList(); - this.state = 129; + this.state = 122; this.match(JackParser.RPAREN); - this.state = 130; + this.state = 123; this.subroutineBody(); } } @@ -491,11 +489,11 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineName(): SubroutineNameContext { let _localctx: SubroutineNameContext = new SubroutineNameContext(this._ctx, this.state); - this.enterRule(_localctx, 16, JackParser.RULE_subroutineName); + this.enterRule(_localctx, 18, JackParser.RULE_subroutineName); try { this.enterOuterAlt(_localctx, 1); { - this.state = 132; + this.state = 125; this.match(JackParser.IDENTIFIER); } } @@ -516,9 +514,9 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineReturnType(): SubroutineReturnTypeContext { let _localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this._ctx, this.state); - this.enterRule(_localctx, 18, JackParser.RULE_subroutineReturnType); + this.enterRule(_localctx, 20, JackParser.RULE_subroutineReturnType); try { - this.state = 136; + this.state = 129; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.INT: @@ -527,14 +525,14 @@ export class JackParser extends Parser { case JackParser.IDENTIFIER: this.enterOuterAlt(_localctx, 1); { - this.state = 134; + this.state = 127; this.varType(); } break; case JackParser.VOID: this.enterOuterAlt(_localctx, 2); { - this.state = 135; + this.state = 128; this.match(JackParser.VOID); } break; @@ -559,12 +557,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public varType(): VarTypeContext { let _localctx: VarTypeContext = new VarTypeContext(this._ctx, this.state); - this.enterRule(_localctx, 20, JackParser.RULE_varType); + this.enterRule(_localctx, 22, JackParser.RULE_varType); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 138; + this.state = 131; _la = this._input.LA(1); if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER)) { this._errHandler.recoverInline(this); @@ -595,31 +593,31 @@ export class JackParser extends Parser { // @RuleVersion(0) public parameterList(): ParameterListContext { let _localctx: ParameterListContext = new ParameterListContext(this._ctx, this.state); - this.enterRule(_localctx, 22, JackParser.RULE_parameterList); + this.enterRule(_localctx, 24, JackParser.RULE_parameterList); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 148; + this.state = 141; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER) { { - this.state = 140; + this.state = 133; this.parameter(); - this.state = 145; + this.state = 138; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 141; + this.state = 134; this.match(JackParser.COMMA); - this.state = 142; + this.state = 135; this.parameter(); } } - this.state = 147; + this.state = 140; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -645,13 +643,13 @@ export class JackParser extends Parser { // @RuleVersion(0) public parameter(): ParameterContext { let _localctx: ParameterContext = new ParameterContext(this._ctx, this.state); - this.enterRule(_localctx, 24, JackParser.RULE_parameter); + this.enterRule(_localctx, 26, JackParser.RULE_parameter); try { this.enterOuterAlt(_localctx, 1); { - this.state = 150; + this.state = 143; this.varType(); - this.state = 151; + this.state = 144; this.parameterName(); } } @@ -672,11 +670,11 @@ export class JackParser extends Parser { // @RuleVersion(0) public parameterName(): ParameterNameContext { let _localctx: ParameterNameContext = new ParameterNameContext(this._ctx, this.state); - this.enterRule(_localctx, 26, JackParser.RULE_parameterName); + this.enterRule(_localctx, 28, JackParser.RULE_parameterName); try { this.enterOuterAlt(_localctx, 1); { - this.state = 153; + this.state = 146; this.match(JackParser.IDENTIFIER); } } @@ -697,30 +695,30 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineBody(): SubroutineBodyContext { let _localctx: SubroutineBodyContext = new SubroutineBodyContext(this._ctx, this.state); - this.enterRule(_localctx, 28, JackParser.RULE_subroutineBody); + this.enterRule(_localctx, 30, JackParser.RULE_subroutineBody); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 155; + this.state = 148; this.match(JackParser.LBRACE); - this.state = 159; + this.state = 152; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.VAR) { { { - this.state = 156; + this.state = 149; this.varDeclaration(); } } - this.state = 161; + this.state = 154; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 162; + this.state = 155; this.statements(); - this.state = 163; + this.state = 156; this.match(JackParser.RBRACE); } } @@ -741,34 +739,34 @@ export class JackParser extends Parser { // @RuleVersion(0) public varDeclaration(): VarDeclarationContext { let _localctx: VarDeclarationContext = new VarDeclarationContext(this._ctx, this.state); - this.enterRule(_localctx, 30, JackParser.RULE_varDeclaration); + this.enterRule(_localctx, 32, JackParser.RULE_varDeclaration); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 165; + this.state = 158; this.match(JackParser.VAR); - this.state = 166; + this.state = 159; this.varType(); - this.state = 167; + this.state = 160; this.varNameInDeclaration(); - this.state = 172; + this.state = 165; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 168; + this.state = 161; this.match(JackParser.COMMA); - this.state = 169; + this.state = 162; this.varNameInDeclaration(); } } - this.state = 174; + this.state = 167; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 175; + this.state = 168; this.match(JackParser.SEMICOLON); } } @@ -789,11 +787,11 @@ export class JackParser extends Parser { // @RuleVersion(0) public varNameInDeclaration(): VarNameInDeclarationContext { let _localctx: VarNameInDeclarationContext = new VarNameInDeclarationContext(this._ctx, this.state); - this.enterRule(_localctx, 32, JackParser.RULE_varNameInDeclaration); + this.enterRule(_localctx, 34, JackParser.RULE_varNameInDeclaration); try { this.enterOuterAlt(_localctx, 1); { - this.state = 177; + this.state = 170; this.match(JackParser.IDENTIFIER); } } @@ -814,11 +812,11 @@ export class JackParser extends Parser { // @RuleVersion(0) public varName(): VarNameContext { let _localctx: VarNameContext = new VarNameContext(this._ctx, this.state); - this.enterRule(_localctx, 34, JackParser.RULE_varName); + this.enterRule(_localctx, 36, JackParser.RULE_varName); try { this.enterOuterAlt(_localctx, 1); { - this.state = 179; + this.state = 172; this.match(JackParser.IDENTIFIER); } } @@ -839,22 +837,22 @@ export class JackParser extends Parser { // @RuleVersion(0) public statements(): StatementsContext { let _localctx: StatementsContext = new StatementsContext(this._ctx, this.state); - this.enterRule(_localctx, 36, JackParser.RULE_statements); + this.enterRule(_localctx, 38, JackParser.RULE_statements); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 184; + this.state = 177; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.LET) | (1 << JackParser.DO) | (1 << JackParser.IF) | (1 << JackParser.WHILE) | (1 << JackParser.RETURN))) !== 0)) { { { - this.state = 181; + this.state = 174; this.statement(); } } - this.state = 186; + this.state = 179; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -877,43 +875,43 @@ export class JackParser extends Parser { // @RuleVersion(0) public statement(): StatementContext { let _localctx: StatementContext = new StatementContext(this._ctx, this.state); - this.enterRule(_localctx, 38, JackParser.RULE_statement); + this.enterRule(_localctx, 40, JackParser.RULE_statement); try { - this.state = 192; + this.state = 185; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.LET: this.enterOuterAlt(_localctx, 1); { - this.state = 187; + this.state = 180; this.letStatement(); } break; case JackParser.IF: this.enterOuterAlt(_localctx, 2); { - this.state = 188; + this.state = 181; this.ifElseStatement(); } break; case JackParser.WHILE: this.enterOuterAlt(_localctx, 3); { - this.state = 189; + this.state = 182; this.whileStatement(); } break; case JackParser.DO: this.enterOuterAlt(_localctx, 4); { - this.state = 190; + this.state = 183; this.doStatement(); } break; case JackParser.RETURN: this.enterOuterAlt(_localctx, 5); { - this.state = 191; + this.state = 184; this.returnStatement(); } break; @@ -938,34 +936,34 @@ export class JackParser extends Parser { // @RuleVersion(0) public letStatement(): LetStatementContext { let _localctx: LetStatementContext = new LetStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 40, JackParser.RULE_letStatement); + this.enterRule(_localctx, 42, JackParser.RULE_letStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 194; + this.state = 187; this.match(JackParser.LET); - this.state = 197; + this.state = 190; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 12, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 10, this._ctx) ) { case 1: { - this.state = 195; + this.state = 188; this.varName(); } break; case 2: { - this.state = 196; + this.state = 189; this.arrayAccess(); } break; } - this.state = 199; + this.state = 192; this.match(JackParser.EQUALS); - this.state = 200; + this.state = 193; this.expression(0); - this.state = 201; + this.state = 194; this.match(JackParser.SEMICOLON); } } @@ -986,19 +984,19 @@ export class JackParser extends Parser { // @RuleVersion(0) public ifElseStatement(): IfElseStatementContext { let _localctx: IfElseStatementContext = new IfElseStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 42, JackParser.RULE_ifElseStatement); + this.enterRule(_localctx, 44, JackParser.RULE_ifElseStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 203; + this.state = 196; this.ifStatement(); - this.state = 205; + this.state = 198; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === JackParser.ELSE) { { - this.state = 204; + this.state = 197; this.elseStatement(); } } @@ -1022,23 +1020,23 @@ export class JackParser extends Parser { // @RuleVersion(0) public ifStatement(): IfStatementContext { let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 44, JackParser.RULE_ifStatement); + this.enterRule(_localctx, 46, JackParser.RULE_ifStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 207; + this.state = 200; this.match(JackParser.IF); - this.state = 208; + this.state = 201; this.match(JackParser.LPAREN); - this.state = 209; + this.state = 202; this.expression(0); - this.state = 210; + this.state = 203; this.match(JackParser.RPAREN); - this.state = 211; + this.state = 204; this.match(JackParser.LBRACE); - this.state = 212; + this.state = 205; this.statements(); - this.state = 213; + this.state = 206; this.match(JackParser.RBRACE); } } @@ -1059,17 +1057,17 @@ export class JackParser extends Parser { // @RuleVersion(0) public elseStatement(): ElseStatementContext { let _localctx: ElseStatementContext = new ElseStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 46, JackParser.RULE_elseStatement); + this.enterRule(_localctx, 48, JackParser.RULE_elseStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 215; + this.state = 208; this.match(JackParser.ELSE); - this.state = 216; + this.state = 209; this.match(JackParser.LBRACE); - this.state = 217; + this.state = 210; this.statements(); - this.state = 218; + this.state = 211; this.match(JackParser.RBRACE); } } @@ -1090,23 +1088,23 @@ export class JackParser extends Parser { // @RuleVersion(0) public whileStatement(): WhileStatementContext { let _localctx: WhileStatementContext = new WhileStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 48, JackParser.RULE_whileStatement); + this.enterRule(_localctx, 50, JackParser.RULE_whileStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 220; + this.state = 213; this.match(JackParser.WHILE); - this.state = 221; + this.state = 214; this.match(JackParser.LPAREN); - this.state = 222; + this.state = 215; this.expression(0); - this.state = 223; + this.state = 216; this.match(JackParser.RPAREN); - this.state = 224; + this.state = 217; this.match(JackParser.LBRACE); - this.state = 225; + this.state = 218; this.statements(); - this.state = 226; + this.state = 219; this.match(JackParser.RBRACE); } } @@ -1127,15 +1125,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public doStatement(): DoStatementContext { let _localctx: DoStatementContext = new DoStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 50, JackParser.RULE_doStatement); + this.enterRule(_localctx, 52, JackParser.RULE_doStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 228; + this.state = 221; this.match(JackParser.DO); - this.state = 229; + this.state = 222; this.subroutineCall(); - this.state = 230; + this.state = 223; this.match(JackParser.SEMICOLON); } } @@ -1156,17 +1154,17 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineCall(): SubroutineCallContext { let _localctx: SubroutineCallContext = new SubroutineCallContext(this._ctx, this.state); - this.enterRule(_localctx, 52, JackParser.RULE_subroutineCall); + this.enterRule(_localctx, 54, JackParser.RULE_subroutineCall); try { this.enterOuterAlt(_localctx, 1); { - this.state = 232; + this.state = 225; this.subroutineId(); - this.state = 233; + this.state = 226; this.match(JackParser.LPAREN); - this.state = 234; + this.state = 227; this.expressionList(); - this.state = 235; + this.state = 228; this.match(JackParser.RPAREN); } } @@ -1187,39 +1185,39 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineId(): SubroutineIdContext { let _localctx: SubroutineIdContext = new SubroutineIdContext(this._ctx, this.state); - this.enterRule(_localctx, 54, JackParser.RULE_subroutineId); + this.enterRule(_localctx, 56, JackParser.RULE_subroutineId); try { this.enterOuterAlt(_localctx, 1); { - this.state = 242; + this.state = 235; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 15, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 13, this._ctx) ) { case 1: { - this.state = 239; + this.state = 232; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.IDENTIFIER: { - this.state = 237; + this.state = 230; this.className(); } break; case JackParser.THIS_LITERAL: { - this.state = 238; + this.state = 231; this.match(JackParser.THIS_LITERAL); } break; default: throw new NoViableAltException(this); } - this.state = 241; + this.state = 234; this.match(JackParser.DOT); } break; } - this.state = 244; + this.state = 237; this.subroutineName(); } } @@ -1240,24 +1238,24 @@ export class JackParser extends Parser { // @RuleVersion(0) public returnStatement(): ReturnStatementContext { let _localctx: ReturnStatementContext = new ReturnStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 56, JackParser.RULE_returnStatement); + this.enterRule(_localctx, 58, JackParser.RULE_returnStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 246; + this.state = 239; this.match(JackParser.RETURN); - this.state = 248; + this.state = 241; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 247; + this.state = 240; this.expression(0); } } - this.state = 250; + this.state = 243; this.match(JackParser.SEMICOLON); } } @@ -1278,31 +1276,31 @@ export class JackParser extends Parser { // @RuleVersion(0) public expressionList(): ExpressionListContext { let _localctx: ExpressionListContext = new ExpressionListContext(this._ctx, this.state); - this.enterRule(_localctx, 58, JackParser.RULE_expressionList); + this.enterRule(_localctx, 60, JackParser.RULE_expressionList); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 260; + this.state = 253; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 252; + this.state = 245; this.expression(0); - this.state = 257; + this.state = 250; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 253; + this.state = 246; this.match(JackParser.COMMA); - this.state = 254; + this.state = 247; this.expression(0); } } - this.state = 259; + this.state = 252; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1338,61 +1336,61 @@ export class JackParser extends Parser { let _parentState: number = this.state; let _localctx: ExpressionContext = new ExpressionContext(this._ctx, _parentState); let _prevctx: ExpressionContext = _localctx; - let _startState: number = 60; - this.enterRecursionRule(_localctx, 60, JackParser.RULE_expression, _p); + let _startState: number = 62; + this.enterRecursionRule(_localctx, 62, JackParser.RULE_expression, _p); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 269; + this.state = 262; this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 19, this._ctx) ) { + switch ( this.interpreter.adaptivePredict(this._input, 17, this._ctx) ) { case 1: { - this.state = 263; + this.state = 256; this.constant(); } break; case 2: { - this.state = 264; + this.state = 257; this.varName(); } break; case 3: { - this.state = 265; + this.state = 258; this.subroutineCall(); } break; case 4: { - this.state = 266; + this.state = 259; this.arrayAccess(); } break; case 5: { - this.state = 267; + this.state = 260; this.unaryOp(); } break; case 6: { - this.state = 268; + this.state = 261; this.groupedExpression(); } break; } this._ctx._stop = this._input.tryLT(-1); - this.state = 277; + this.state = 270; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -1404,20 +1402,20 @@ export class JackParser extends Parser { _localctx = new ExpressionContext(_parentctx, _parentState); _localctx._binaryOperation = _prevctx; this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); - this.state = 271; + this.state = 264; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 272; + this.state = 265; this.binaryOperator(); - this.state = 273; + this.state = 266; this.expression(8); } } } - this.state = 279; + this.state = 272; this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 20, this._ctx); + _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); } } } @@ -1438,15 +1436,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public groupedExpression(): GroupedExpressionContext { let _localctx: GroupedExpressionContext = new GroupedExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 62, JackParser.RULE_groupedExpression); + this.enterRule(_localctx, 64, JackParser.RULE_groupedExpression); try { this.enterOuterAlt(_localctx, 1); { - this.state = 280; + this.state = 273; this.match(JackParser.LPAREN); - this.state = 281; + this.state = 274; this.expression(0); - this.state = 282; + this.state = 275; this.match(JackParser.RPAREN); } } @@ -1467,13 +1465,13 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOp(): UnaryOpContext { let _localctx: UnaryOpContext = new UnaryOpContext(this._ctx, this.state); - this.enterRule(_localctx, 64, JackParser.RULE_unaryOp); + this.enterRule(_localctx, 66, JackParser.RULE_unaryOp); try { this.enterOuterAlt(_localctx, 1); { - this.state = 284; + this.state = 277; this.unaryOperator(); - this.state = 285; + this.state = 278; this.expression(0); } } @@ -1494,17 +1492,17 @@ export class JackParser extends Parser { // @RuleVersion(0) public arrayAccess(): ArrayAccessContext { let _localctx: ArrayAccessContext = new ArrayAccessContext(this._ctx, this.state); - this.enterRule(_localctx, 66, JackParser.RULE_arrayAccess); + this.enterRule(_localctx, 68, JackParser.RULE_arrayAccess); try { this.enterOuterAlt(_localctx, 1); { - this.state = 287; + this.state = 280; this.varName(); - this.state = 288; + this.state = 281; this.match(JackParser.LBRACKET); - this.state = 289; + this.state = 282; this.expression(0); - this.state = 290; + this.state = 283; this.match(JackParser.RBRACKET); } } @@ -1525,12 +1523,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public constant(): ConstantContext { let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 68, JackParser.RULE_constant); + this.enterRule(_localctx, 70, JackParser.RULE_constant); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 292; + this.state = 285; _la = this._input.LA(1); if (!(((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & ((1 << (JackParser.INTEGER_LITERAL - 40)) | (1 << (JackParser.BOOLEAN_LITERAL - 40)) | (1 << (JackParser.NULL_LITERAL - 40)) | (1 << (JackParser.THIS_LITERAL - 40)) | (1 << (JackParser.STRING_LITERAL - 40)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1561,12 +1559,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOperator(): UnaryOperatorContext { let _localctx: UnaryOperatorContext = new UnaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 70, JackParser.RULE_unaryOperator); + this.enterRule(_localctx, 72, JackParser.RULE_unaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 294; + this.state = 287; _la = this._input.LA(1); if (!(_la === JackParser.MINUS || _la === JackParser.TILDE)) { this._errHandler.recoverInline(this); @@ -1597,12 +1595,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public binaryOperator(): BinaryOperatorContext { let _localctx: BinaryOperatorContext = new BinaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 72, JackParser.RULE_binaryOperator); + this.enterRule(_localctx, 74, JackParser.RULE_binaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 296; + this.state = 289; _la = this._input.LA(1); if (!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & ((1 << (JackParser.EQUALS - 27)) | (1 << (JackParser.PLUS - 27)) | (1 << (JackParser.MINUS - 27)) | (1 << (JackParser.MUL - 27)) | (1 << (JackParser.DIV - 27)) | (1 << (JackParser.AND - 27)) | (1 << (JackParser.OR - 27)) | (1 << (JackParser.LESS_THAN - 27)) | (1 << (JackParser.GREATER_THAN - 27)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1633,7 +1631,7 @@ export class JackParser extends Parser { public override sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 30: + case 31: return this.expression_sempred(_localctx as ExpressionContext, predIndex); } return true; @@ -1647,134 +1645,130 @@ export class JackParser extends Parser { } public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u012D\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u0126\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + - "\t#\x04$\t$\x04%\t%\x04&\t&\x03\x02\x03\x02\x03\x02\x03\x03\x03\x03\x03" + - "\x03\x03\x03\x07\x03T\n\x03\f\x03\x0E\x03W\v\x03\x03\x03\x07\x03Z\n\x03" + - "\f\x03\x0E\x03]\v\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x05\x03\x05" + - "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x03\x05\x05\x05k\n\x05\x03\x06" + - "\x03\x06\x03\x06\x03\x06\x07\x06q\n\x06\f\x06\x0E\x06t\v\x06\x03\x07\x03" + - "\x07\x03\b\x03\b\x03\b\x03\b\x03\b\x03\b\x05\b~\n\b\x03\t\x03\t\x03\t" + - "\x03\t\x03\t\x03\t\x03\t\x03\n\x03\n\x03\v\x03\v\x05\v\x8B\n\v\x03\f\x03" + - "\f\x03\r\x03\r\x03\r\x07\r\x92\n\r\f\r\x0E\r\x95\v\r\x05\r\x97\n\r\x03" + - "\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x10\x03\x10\x07\x10\xA0\n\x10" + - "\f\x10\x0E\x10\xA3\v\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11" + - "\x03\x11\x03\x11\x07\x11\xAD\n\x11\f\x11\x0E\x11\xB0\v\x11\x03\x11\x03" + - "\x11\x03\x12\x03\x12\x03\x13\x03\x13\x03\x14\x07\x14\xB9\n\x14\f\x14\x0E" + - "\x14\xBC\v\x14\x03\x15\x03\x15\x03\x15\x03\x15\x03\x15\x05\x15\xC3\n\x15" + - "\x03\x16\x03\x16\x03\x16\x05\x16\xC8\n\x16\x03\x16\x03\x16\x03\x16\x03" + - "\x16\x03\x17\x03\x17\x05\x17\xD0\n\x17\x03\x18\x03\x18\x03\x18\x03\x18" + - "\x03\x18\x03\x18\x03\x18\x03\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19" + - "\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B" + - "\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1D" + - "\x03\x1D\x05\x1D\xF2\n\x1D\x03\x1D\x05\x1D\xF5\n\x1D\x03\x1D\x03\x1D\x03" + - "\x1E\x03\x1E\x05\x1E\xFB\n\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03\x1F" + - "\x07\x1F\u0102\n\x1F\f\x1F\x0E\x1F\u0105\v\x1F\x05\x1F\u0107\n\x1F\x03" + - " \x03 \x03 \x03 \x03 \x03 \x03 \x05 \u0110\n \x03 \x03 \x03 \x03 \x07" + - " \u0116\n \f \x0E \u0119\v \x03!\x03!\x03!\x03!\x03\"\x03\"\x03\"\x03" + - "#\x03#\x03#\x03#\x03#\x03$\x03$\x03%\x03%\x03&\x03&\x03&\x02\x02\x03>" + - "\'\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02\x12\x02\x14" + - "\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02&\x02(\x02" + - "*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02B\x02D\x02" + - "F\x02H\x02J\x02\x02\x06\x04\x02\n\f..\x04\x02*-//\x04\x02\x1F\x1F$$\x04" + - "\x02\x1D#%&\x02\u0124\x02L\x03\x02\x02\x02\x04O\x03\x02\x02\x02\x06`\x03" + - "\x02\x02\x02\bj\x03\x02\x02\x02\nl\x03\x02\x02\x02\fu\x03\x02\x02\x02" + - "\x0E}\x03\x02\x02\x02\x10\x7F\x03\x02\x02\x02\x12\x86\x03\x02\x02\x02" + - "\x14\x8A\x03\x02\x02\x02\x16\x8C\x03\x02\x02\x02\x18\x96\x03\x02\x02\x02" + - "\x1A\x98\x03\x02\x02\x02\x1C\x9B\x03\x02\x02\x02\x1E\x9D\x03\x02\x02\x02" + - " \xA7\x03\x02\x02\x02\"\xB3\x03\x02\x02\x02$\xB5\x03\x02\x02\x02&\xBA" + - "\x03\x02\x02\x02(\xC2\x03\x02\x02\x02*\xC4\x03\x02\x02\x02,\xCD\x03\x02" + - "\x02\x02.\xD1\x03\x02\x02\x020\xD9\x03\x02\x02\x022\xDE\x03\x02\x02\x02" + - "4\xE6\x03\x02\x02\x026\xEA\x03\x02\x02\x028\xF4\x03\x02\x02\x02:\xF8\x03" + - "\x02\x02\x02<\u0106\x03\x02\x02\x02>\u010F\x03\x02\x02\x02@\u011A\x03" + - "\x02\x02\x02B\u011E\x03\x02\x02\x02D\u0121\x03\x02\x02\x02F\u0126\x03" + - "\x02\x02\x02H\u0128\x03\x02\x02\x02J\u012A\x03\x02\x02\x02LM\x05\x04\x03" + - "\x02MN\x07\x02\x02\x03N\x03\x03\x02\x02\x02OP\x07\x03\x02\x02PQ\x05\x06" + - "\x04\x02QU\x07\x14\x02\x02RT\x05\b\x05\x02SR\x03\x02\x02\x02TW\x03\x02" + - "\x02\x02US\x03\x02\x02\x02UV\x03\x02\x02\x02V[\x03\x02\x02\x02WU\x03\x02" + - "\x02\x02XZ\x05\x0E\b\x02YX\x03\x02\x02\x02Z]\x03\x02\x02\x02[Y\x03\x02" + - "\x02\x02[\\\x03\x02\x02\x02\\^\x03\x02\x02\x02][\x03\x02\x02\x02^_\x07" + - "\x15\x02\x02_\x05\x03\x02\x02\x02`a\x07.\x02\x02a\x07\x03\x02\x02\x02" + - "bc\x07\b\x02\x02cd\x05\n\x06\x02de\x07\x1C\x02\x02ek\x03\x02\x02\x02f" + - "g\x07\x07\x02\x02gh\x05\n\x06\x02hi\x07\x1C\x02\x02ik\x03\x02\x02\x02" + - "jb\x03\x02\x02\x02jf\x03\x02\x02\x02k\t\x03\x02\x02\x02lm\x05\x16\f\x02" + - "mr\x05\f\x07\x02no\x07\x1B\x02\x02oq\x05\f\x07\x02pn\x03\x02\x02\x02q" + - "t\x03\x02\x02\x02rp\x03\x02\x02\x02rs\x03\x02\x02\x02s\v\x03\x02\x02\x02" + - "tr\x03\x02\x02\x02uv\x07.\x02\x02v\r\x03\x02\x02\x02wx\x07\x04\x02\x02" + - "x~\x05\x10\t\x02yz\x07\x06\x02\x02z~\x05\x10\t\x02{|\x07\x05\x02\x02|" + - "~\x05\x10\t\x02}w\x03\x02\x02\x02}y\x03\x02\x02\x02}{\x03\x02\x02\x02" + - "~\x0F\x03\x02\x02\x02\x7F\x80\x05\x14\v\x02\x80\x81\x05\x12\n\x02\x81" + - "\x82\x07\x16\x02\x02\x82\x83\x05\x18\r\x02\x83\x84\x07\x17\x02\x02\x84" + - "\x85\x05\x1E\x10\x02\x85\x11\x03\x02\x02\x02\x86\x87\x07.\x02\x02\x87" + - "\x13\x03\x02\x02\x02\x88\x8B\x05\x16\f\x02\x89\x8B\x07\r\x02\x02\x8A\x88" + - "\x03\x02\x02\x02\x8A\x89\x03\x02\x02\x02\x8B\x15\x03\x02\x02\x02\x8C\x8D" + - "\t\x02\x02\x02\x8D\x17\x03\x02\x02\x02\x8E\x93\x05\x1A\x0E\x02\x8F\x90" + - "\x07\x1B\x02\x02\x90\x92\x05\x1A\x0E\x02\x91\x8F\x03\x02\x02\x02\x92\x95" + - "\x03\x02\x02\x02\x93\x91\x03\x02\x02\x02\x93\x94\x03\x02\x02\x02\x94\x97" + - "\x03\x02\x02\x02\x95\x93\x03\x02\x02\x02\x96\x8E\x03\x02\x02\x02\x96\x97" + - "\x03\x02\x02\x02\x97\x19\x03\x02\x02\x02\x98\x99\x05\x16\f\x02\x99\x9A" + - "\x05\x1C\x0F\x02\x9A\x1B\x03\x02\x02\x02\x9B\x9C\x07.\x02\x02\x9C\x1D" + - "\x03\x02\x02\x02\x9D\xA1\x07\x14\x02\x02\x9E\xA0\x05 \x11\x02\x9F\x9E" + - "\x03\x02\x02\x02\xA0\xA3\x03\x02\x02\x02\xA1\x9F\x03\x02\x02\x02\xA1\xA2" + - "\x03\x02\x02\x02\xA2\xA4\x03\x02\x02\x02\xA3\xA1\x03\x02\x02\x02\xA4\xA5" + - "\x05&\x14\x02\xA5\xA6\x07\x15\x02\x02\xA6\x1F\x03\x02\x02\x02\xA7\xA8" + - "\x07\t\x02\x02\xA8\xA9\x05\x16\f\x02\xA9\xAE\x05\"\x12\x02\xAA\xAB\x07" + - "\x1B\x02\x02\xAB\xAD\x05\"\x12\x02\xAC\xAA\x03\x02\x02\x02\xAD\xB0\x03" + - "\x02\x02\x02\xAE\xAC\x03\x02\x02\x02\xAE\xAF\x03\x02\x02\x02\xAF\xB1\x03" + - "\x02\x02\x02\xB0\xAE\x03\x02\x02\x02\xB1\xB2\x07\x1C\x02\x02\xB2!\x03" + - "\x02\x02\x02\xB3\xB4\x07.\x02\x02\xB4#\x03\x02\x02\x02\xB5\xB6\x07.\x02" + - "\x02\xB6%\x03\x02\x02\x02\xB7\xB9\x05(\x15\x02\xB8\xB7\x03\x02\x02\x02" + - "\xB9\xBC\x03\x02\x02\x02\xBA\xB8\x03\x02\x02\x02\xBA\xBB\x03\x02\x02\x02" + - "\xBB\'\x03\x02\x02\x02\xBC\xBA\x03\x02\x02\x02\xBD\xC3\x05*\x16\x02\xBE" + - "\xC3\x05,\x17\x02\xBF\xC3\x052\x1A\x02\xC0\xC3\x054\x1B\x02\xC1\xC3\x05" + - ":\x1E\x02\xC2\xBD\x03\x02\x02\x02\xC2\xBE\x03\x02\x02\x02\xC2\xBF\x03" + - "\x02\x02\x02\xC2\xC0\x03\x02\x02\x02\xC2\xC1\x03\x02\x02\x02\xC3)\x03" + - "\x02\x02\x02\xC4\xC7\x07\x0E\x02\x02\xC5\xC8\x05$\x13\x02\xC6\xC8\x05" + - "D#\x02\xC7\xC5\x03\x02\x02\x02\xC7\xC6\x03\x02\x02\x02\xC8\xC9\x03\x02" + - "\x02\x02\xC9\xCA\x07\x1D\x02\x02\xCA\xCB\x05> \x02\xCB\xCC\x07\x1C\x02" + - "\x02\xCC+\x03\x02\x02\x02\xCD\xCF\x05.\x18\x02\xCE\xD0\x050\x19\x02\xCF" + - "\xCE\x03\x02\x02\x02\xCF\xD0\x03\x02\x02\x02\xD0-\x03\x02\x02\x02\xD1" + - "\xD2\x07\x10\x02\x02\xD2\xD3\x07\x16\x02\x02\xD3\xD4\x05> \x02\xD4\xD5" + - "\x07\x17\x02\x02\xD5\xD6\x07\x14\x02\x02\xD6\xD7\x05&\x14\x02\xD7\xD8" + - "\x07\x15\x02\x02\xD8/\x03\x02\x02\x02\xD9\xDA\x07\x11\x02\x02\xDA\xDB" + - "\x07\x14\x02\x02\xDB\xDC\x05&\x14\x02\xDC\xDD\x07\x15\x02\x02\xDD1\x03" + - "\x02\x02\x02\xDE\xDF\x07\x12\x02\x02\xDF\xE0\x07\x16\x02\x02\xE0\xE1\x05" + - "> \x02\xE1\xE2\x07\x17\x02\x02\xE2\xE3\x07\x14\x02\x02\xE3\xE4\x05&\x14" + - "\x02\xE4\xE5\x07\x15\x02\x02\xE53\x03\x02\x02\x02\xE6\xE7\x07\x0F\x02" + - "\x02\xE7\xE8\x056\x1C\x02\xE8\xE9\x07\x1C\x02\x02\xE95\x03\x02\x02\x02" + - "\xEA\xEB\x058\x1D\x02\xEB\xEC\x07\x16\x02\x02\xEC\xED\x05<\x1F\x02\xED" + - "\xEE\x07\x17\x02\x02\xEE7\x03\x02\x02\x02\xEF\xF2\x05\x06\x04\x02\xF0" + - "\xF2\x07-\x02\x02\xF1\xEF\x03\x02\x02\x02\xF1\xF0\x03\x02\x02\x02\xF2" + - "\xF3\x03\x02\x02\x02\xF3\xF5\x07\x1A\x02\x02\xF4\xF1\x03\x02\x02\x02\xF4" + - "\xF5\x03\x02\x02\x02\xF5\xF6\x03\x02\x02\x02\xF6\xF7\x05\x12\n\x02\xF7" + - "9\x03\x02\x02\x02\xF8\xFA\x07\x13\x02\x02\xF9\xFB\x05> \x02\xFA\xF9\x03" + - "\x02\x02\x02\xFA\xFB\x03\x02\x02\x02\xFB\xFC\x03\x02\x02\x02\xFC\xFD\x07" + - "\x1C\x02\x02\xFD;\x03\x02\x02\x02\xFE\u0103\x05> \x02\xFF\u0100\x07\x1B" + - "\x02\x02\u0100\u0102\x05> \x02\u0101\xFF\x03\x02\x02\x02\u0102\u0105\x03" + - "\x02\x02\x02\u0103\u0101\x03\x02\x02\x02\u0103\u0104\x03\x02\x02\x02\u0104" + - "\u0107\x03\x02\x02\x02\u0105\u0103\x03\x02\x02\x02\u0106\xFE\x03\x02\x02" + - "\x02\u0106\u0107\x03\x02\x02\x02\u0107=\x03\x02\x02\x02\u0108\u0109\b" + - " \x01\x02\u0109\u0110\x05F$\x02\u010A\u0110\x05$\x13\x02\u010B\u0110\x05" + - "6\x1C\x02\u010C\u0110\x05D#\x02\u010D\u0110\x05B\"\x02\u010E\u0110\x05" + - "@!\x02\u010F\u0108\x03\x02\x02\x02\u010F\u010A\x03\x02\x02\x02\u010F\u010B" + - "\x03\x02\x02\x02\u010F\u010C\x03\x02\x02\x02\u010F\u010D\x03\x02\x02\x02" + - "\u010F\u010E\x03\x02\x02\x02\u0110\u0117\x03\x02\x02\x02\u0111\u0112\f" + - "\t\x02\x02\u0112\u0113\x05J&\x02\u0113\u0114\x05> \n\u0114\u0116\x03\x02" + - "\x02\x02\u0115\u0111\x03\x02\x02\x02\u0116\u0119\x03\x02\x02\x02\u0117" + - "\u0115\x03\x02\x02\x02\u0117\u0118\x03\x02\x02\x02\u0118?\x03\x02\x02" + - "\x02\u0119\u0117\x03\x02\x02\x02\u011A\u011B\x07\x16\x02\x02\u011B\u011C" + - "\x05> \x02\u011C\u011D\x07\x17\x02\x02\u011DA\x03\x02\x02\x02\u011E\u011F" + - "\x05H%\x02\u011F\u0120\x05> \x02\u0120C\x03\x02\x02\x02\u0121\u0122\x05" + - "$\x13\x02\u0122\u0123\x07\x18\x02\x02\u0123\u0124\x05> \x02\u0124\u0125" + - "\x07\x19\x02\x02\u0125E\x03\x02\x02\x02\u0126\u0127\t\x03\x02\x02\u0127" + - "G\x03\x02\x02\x02\u0128\u0129\t\x04\x02\x02\u0129I\x03\x02\x02\x02\u012A" + - "\u012B\t\x05\x02\x02\u012BK\x03\x02\x02\x02\x17U[jr}\x8A\x93\x96\xA1\xAE" + - "\xBA\xC2\xC7\xCF\xF1\xF4\xFA\u0103\u0106\u010F\u0117"; + "\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x03\x02\x03\x02\x03\x02\x03\x03" + + "\x03\x03\x03\x03\x03\x03\x07\x03V\n\x03\f\x03\x0E\x03Y\v\x03\x03\x03\x07" + + "\x03\\\n\x03\f\x03\x0E\x03_\v\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03" + + "\x05\x03\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x07\x06m" + + "\n\x06\f\x06\x0E\x06p\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\t\x03" + + "\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03\f\x03\f\x05" + + "\f\x84\n\f\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x07\x0E\x8B\n\x0E\f\x0E" + + "\x0E\x0E\x8E\v\x0E\x05\x0E\x90\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x10\x03" + + "\x10\x03\x11\x03\x11\x07\x11\x99\n\x11\f\x11\x0E\x11\x9C\v\x11\x03\x11" + + "\x03\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x07\x12\xA6\n" + + "\x12\f\x12\x0E\x12\xA9\v\x12\x03\x12\x03\x12\x03\x13\x03\x13\x03\x14\x03" + + "\x14\x03\x15\x07\x15\xB2\n\x15\f\x15\x0E\x15\xB5\v\x15\x03\x16\x03\x16" + + "\x03\x16\x03\x16\x03\x16\x05\x16\xBC\n\x16\x03\x17\x03\x17\x03\x17\x05" + + "\x17\xC1\n\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18\x03\x18\x05\x18" + + "\xC9\n\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03" + + "\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03\x1B\x03" + + "\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03" + + "\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x05\x1E\xEB\n\x1E" + + "\x03\x1E\x05\x1E\xEE\n\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x05\x1F\xF4" + + "\n\x1F\x03\x1F\x03\x1F\x03 \x03 \x03 \x07 \xFB\n \f \x0E \xFE\v \x05 " + + "\u0100\n \x03!\x03!\x03!\x03!\x03!\x03!\x03!\x05!\u0109\n!\x03!\x03!\x03" + + "!\x03!\x07!\u010F\n!\f!\x0E!\u0112\v!\x03\"\x03\"\x03\"\x03\"\x03#\x03" + + "#\x03#\x03$\x03$\x03$\x03$\x03$\x03%\x03%\x03&\x03&\x03\'\x03\'\x03\'" + + "\x02\x02\x03@(\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02" + + "\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02" + + "&\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02" + + "B\x02D\x02F\x02H\x02J\x02L\x02\x02\b\x03\x02\x07\b\x03\x02\x04\x06\x04" + + "\x02\n\f..\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02\x1D#%&\x02\u0119\x02" + + "N\x03\x02\x02\x02\x04Q\x03\x02\x02\x02\x06b\x03\x02\x02\x02\bd\x03\x02" + + "\x02\x02\nh\x03\x02\x02\x02\fq\x03\x02\x02\x02\x0Es\x03\x02\x02\x02\x10" + + "v\x03\x02\x02\x02\x12x\x03\x02\x02\x02\x14\x7F\x03\x02\x02\x02\x16\x83" + + "\x03\x02\x02\x02\x18\x85\x03\x02\x02\x02\x1A\x8F\x03\x02\x02\x02\x1C\x91" + + "\x03\x02\x02\x02\x1E\x94\x03\x02\x02\x02 \x96\x03\x02\x02\x02\"\xA0\x03" + + "\x02\x02\x02$\xAC\x03\x02\x02\x02&\xAE\x03\x02\x02\x02(\xB3\x03\x02\x02" + + "\x02*\xBB\x03\x02\x02\x02,\xBD\x03\x02\x02\x02.\xC6\x03\x02\x02\x020\xCA" + + "\x03\x02\x02\x022\xD2\x03\x02\x02\x024\xD7\x03\x02\x02\x026\xDF\x03\x02" + + "\x02\x028\xE3\x03\x02\x02\x02:\xED\x03\x02\x02\x02<\xF1\x03\x02\x02\x02" + + ">\xFF\x03\x02\x02\x02@\u0108\x03\x02\x02\x02B\u0113\x03\x02\x02\x02D\u0117" + + "\x03\x02\x02\x02F\u011A\x03\x02\x02\x02H\u011F\x03\x02\x02\x02J\u0121" + + "\x03\x02\x02\x02L\u0123\x03\x02\x02\x02NO\x05\x04\x03\x02OP\x07\x02\x02" + + "\x03P\x03\x03\x02\x02\x02QR\x07\x03\x02\x02RS\x05\x06\x04\x02SW\x07\x14" + + "\x02\x02TV\x05\b\x05\x02UT\x03\x02\x02\x02VY\x03\x02\x02\x02WU\x03\x02" + + "\x02\x02WX\x03\x02\x02\x02X]\x03\x02\x02\x02YW\x03\x02\x02\x02Z\\\x05" + + "\x0E\b\x02[Z\x03\x02\x02\x02\\_\x03\x02\x02\x02][\x03\x02\x02\x02]^\x03" + + "\x02\x02\x02^`\x03\x02\x02\x02_]\x03\x02\x02\x02`a\x07\x15\x02\x02a\x05" + + "\x03\x02\x02\x02bc\x07.\x02\x02c\x07\x03\x02\x02\x02de\t\x02\x02\x02e" + + "f\x05\n\x06\x02fg\x07\x1C\x02\x02g\t\x03\x02\x02\x02hi\x05\x18\r\x02i" + + "n\x05\f\x07\x02jk\x07\x1B\x02\x02km\x05\f\x07\x02lj\x03\x02\x02\x02mp" + + "\x03\x02\x02\x02nl\x03\x02\x02\x02no\x03\x02\x02\x02o\v\x03\x02\x02\x02" + + "pn\x03\x02\x02\x02qr\x07.\x02\x02r\r\x03\x02\x02\x02st\x05\x10\t\x02t" + + "u\x05\x12\n\x02u\x0F\x03\x02\x02\x02vw\t\x03\x02\x02w\x11\x03\x02\x02" + + "\x02xy\x05\x16\f\x02yz\x05\x14\v\x02z{\x07\x16\x02\x02{|\x05\x1A\x0E\x02" + + "|}\x07\x17\x02\x02}~\x05 \x11\x02~\x13\x03\x02\x02\x02\x7F\x80\x07.\x02" + + "\x02\x80\x15\x03\x02\x02\x02\x81\x84\x05\x18\r\x02\x82\x84\x07\r\x02\x02" + + "\x83\x81\x03\x02\x02\x02\x83\x82\x03\x02\x02\x02\x84\x17\x03\x02\x02\x02" + + "\x85\x86\t\x04\x02\x02\x86\x19\x03\x02\x02\x02\x87\x8C\x05\x1C\x0F\x02" + + "\x88\x89\x07\x1B\x02\x02\x89\x8B\x05\x1C\x0F\x02\x8A\x88\x03\x02\x02\x02" + + "\x8B\x8E\x03\x02\x02\x02\x8C\x8A\x03\x02\x02\x02\x8C\x8D\x03\x02\x02\x02" + + "\x8D\x90\x03\x02\x02\x02\x8E\x8C\x03\x02\x02\x02\x8F\x87\x03\x02\x02\x02" + + "\x8F\x90\x03\x02\x02\x02\x90\x1B\x03\x02\x02\x02\x91\x92\x05\x18\r\x02" + + "\x92\x93\x05\x1E\x10\x02\x93\x1D\x03\x02\x02\x02\x94\x95\x07.\x02\x02" + + "\x95\x1F\x03\x02\x02\x02\x96\x9A\x07\x14\x02\x02\x97\x99\x05\"\x12\x02" + + "\x98\x97\x03\x02\x02\x02\x99\x9C\x03\x02\x02\x02\x9A\x98\x03\x02\x02\x02" + + "\x9A\x9B\x03\x02\x02\x02\x9B\x9D\x03\x02\x02\x02\x9C\x9A\x03\x02\x02\x02" + + "\x9D\x9E\x05(\x15\x02\x9E\x9F\x07\x15\x02\x02\x9F!\x03\x02\x02\x02\xA0" + + "\xA1\x07\t\x02\x02\xA1\xA2\x05\x18\r\x02\xA2\xA7\x05$\x13\x02\xA3\xA4" + + "\x07\x1B\x02\x02\xA4\xA6\x05$\x13\x02\xA5\xA3\x03\x02\x02\x02\xA6\xA9" + + "\x03\x02\x02\x02\xA7\xA5\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02\xA8\xAA" + + "\x03\x02\x02\x02\xA9\xA7\x03\x02\x02\x02\xAA\xAB\x07\x1C\x02\x02\xAB#" + + "\x03\x02\x02\x02\xAC\xAD\x07.\x02\x02\xAD%\x03\x02\x02\x02\xAE\xAF\x07" + + ".\x02\x02\xAF\'\x03\x02\x02\x02\xB0\xB2\x05*\x16\x02\xB1\xB0\x03\x02\x02" + + "\x02\xB2\xB5\x03\x02\x02\x02\xB3\xB1\x03\x02\x02\x02\xB3\xB4\x03\x02\x02" + + "\x02\xB4)\x03\x02\x02\x02\xB5\xB3\x03\x02\x02\x02\xB6\xBC\x05,\x17\x02" + + "\xB7\xBC\x05.\x18\x02\xB8\xBC\x054\x1B\x02\xB9\xBC\x056\x1C\x02\xBA\xBC" + + "\x05<\x1F\x02\xBB\xB6\x03\x02\x02\x02\xBB\xB7\x03\x02\x02\x02\xBB\xB8" + + "\x03\x02\x02\x02\xBB\xB9\x03\x02\x02\x02\xBB\xBA\x03\x02\x02\x02\xBC+" + + "\x03\x02\x02\x02\xBD\xC0\x07\x0E\x02\x02\xBE\xC1\x05&\x14\x02\xBF\xC1" + + "\x05F$\x02\xC0\xBE\x03\x02\x02\x02\xC0\xBF\x03\x02\x02\x02\xC1\xC2\x03" + + "\x02\x02\x02\xC2\xC3\x07\x1D\x02\x02\xC3\xC4\x05@!\x02\xC4\xC5\x07\x1C" + + "\x02\x02\xC5-\x03\x02\x02\x02\xC6\xC8\x050\x19\x02\xC7\xC9\x052\x1A\x02" + + "\xC8\xC7\x03\x02\x02\x02\xC8\xC9\x03\x02\x02\x02\xC9/\x03\x02\x02\x02" + + "\xCA\xCB\x07\x10\x02\x02\xCB\xCC\x07\x16\x02\x02\xCC\xCD\x05@!\x02\xCD" + + "\xCE\x07\x17\x02\x02\xCE\xCF\x07\x14\x02\x02\xCF\xD0\x05(\x15\x02\xD0" + + "\xD1\x07\x15\x02\x02\xD11\x03\x02\x02\x02\xD2\xD3\x07\x11\x02\x02\xD3" + + "\xD4\x07\x14\x02\x02\xD4\xD5\x05(\x15\x02\xD5\xD6\x07\x15\x02\x02\xD6" + + "3\x03\x02\x02\x02\xD7\xD8\x07\x12\x02\x02\xD8\xD9\x07\x16\x02\x02\xD9" + + "\xDA\x05@!\x02\xDA\xDB\x07\x17\x02\x02\xDB\xDC\x07\x14\x02\x02\xDC\xDD" + + "\x05(\x15\x02\xDD\xDE\x07\x15\x02\x02\xDE5\x03\x02\x02\x02\xDF\xE0\x07" + + "\x0F\x02\x02\xE0\xE1\x058\x1D\x02\xE1\xE2\x07\x1C\x02\x02\xE27\x03\x02" + + "\x02\x02\xE3\xE4\x05:\x1E\x02\xE4\xE5\x07\x16\x02\x02\xE5\xE6\x05> \x02" + + "\xE6\xE7\x07\x17\x02\x02\xE79\x03\x02\x02\x02\xE8\xEB\x05\x06\x04\x02" + + "\xE9\xEB\x07-\x02\x02\xEA\xE8\x03\x02\x02\x02\xEA\xE9\x03\x02\x02\x02" + + "\xEB\xEC\x03\x02\x02\x02\xEC\xEE\x07\x1A\x02\x02\xED\xEA\x03\x02\x02\x02" + + "\xED\xEE\x03\x02\x02\x02\xEE\xEF\x03\x02\x02\x02\xEF\xF0\x05\x14\v\x02" + + "\xF0;\x03\x02\x02\x02\xF1\xF3\x07\x13\x02\x02\xF2\xF4\x05@!\x02\xF3\xF2" + + "\x03\x02\x02\x02\xF3\xF4\x03\x02\x02\x02\xF4\xF5\x03\x02\x02\x02\xF5\xF6" + + "\x07\x1C\x02\x02\xF6=\x03\x02\x02\x02\xF7\xFC\x05@!\x02\xF8\xF9\x07\x1B" + + "\x02\x02\xF9\xFB\x05@!\x02\xFA\xF8\x03\x02\x02\x02\xFB\xFE\x03\x02\x02" + + "\x02\xFC\xFA\x03\x02\x02\x02\xFC\xFD\x03\x02\x02\x02\xFD\u0100\x03\x02" + + "\x02\x02\xFE\xFC\x03\x02\x02\x02\xFF\xF7\x03\x02\x02\x02\xFF\u0100\x03" + + "\x02\x02\x02\u0100?\x03\x02\x02\x02\u0101\u0102\b!\x01\x02\u0102\u0109" + + "\x05H%\x02\u0103\u0109\x05&\x14\x02\u0104\u0109\x058\x1D\x02\u0105\u0109" + + "\x05F$\x02\u0106\u0109\x05D#\x02\u0107\u0109\x05B\"\x02\u0108\u0101\x03" + + "\x02\x02\x02\u0108\u0103\x03\x02\x02\x02\u0108\u0104\x03\x02\x02\x02\u0108" + + "\u0105\x03\x02\x02\x02\u0108\u0106\x03\x02\x02\x02\u0108\u0107\x03\x02" + + "\x02\x02\u0109\u0110\x03\x02\x02\x02\u010A\u010B\f\t\x02\x02\u010B\u010C" + + "\x05L\'\x02\u010C\u010D\x05@!\n\u010D\u010F\x03\x02\x02\x02\u010E\u010A" + + "\x03\x02\x02\x02\u010F\u0112\x03\x02\x02\x02\u0110\u010E\x03\x02\x02\x02" + + "\u0110\u0111\x03\x02\x02\x02\u0111A\x03\x02\x02\x02\u0112\u0110\x03\x02" + + "\x02\x02\u0113\u0114\x07\x16\x02\x02\u0114\u0115\x05@!\x02\u0115\u0116" + + "\x07\x17\x02\x02\u0116C\x03\x02\x02\x02\u0117\u0118\x05J&\x02\u0118\u0119" + + "\x05@!\x02\u0119E\x03\x02\x02\x02\u011A\u011B\x05&\x14\x02\u011B\u011C" + + "\x07\x18\x02\x02\u011C\u011D\x05@!\x02\u011D\u011E\x07\x19\x02\x02\u011E" + + "G\x03\x02\x02\x02\u011F\u0120\t\x05\x02\x02\u0120I\x03\x02\x02\x02\u0121" + + "\u0122\t\x06\x02\x02\u0122K\x03\x02\x02\x02\u0123\u0124\t\x07\x02\x02" + + "\u0124M\x03\x02\x02\x02\x15W]n\x83\x8C\x8F\x9A\xA7\xB3\xBB\xC0\xC8\xEA" + + "\xED\xF3\xFC\xFF\u0108\u0110"; public static __ATN: ATN; public static get _ATN(): ATN { if (!JackParser.__ATN) { @@ -1903,72 +1897,33 @@ export class ClassNameContext extends ParserRuleContext { export class ClassVarDecContext extends ParserRuleContext { - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_classVarDec; } - public override copyFrom(ctx: ClassVarDecContext): void { - super.copyFrom(ctx); - } -} -export class StaticFieldDeclarationContext extends ClassVarDecContext { - public STATIC(): TerminalNode { return this.getToken(JackParser.STATIC, 0); } public fieldList(): FieldListContext { return this.getRuleContext(0, FieldListContext); } public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } - constructor(ctx: ClassVarDecContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); - } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterStaticFieldDeclaration) { - listener.enterStaticFieldDeclaration(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitStaticFieldDeclaration) { - listener.exitStaticFieldDeclaration(this); - } + public STATIC(): TerminalNode | undefined { return this.tryGetToken(JackParser.STATIC, 0); } + public FIELD(): TerminalNode | undefined { return this.tryGetToken(JackParser.FIELD, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); } // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitStaticFieldDeclaration) { - return visitor.visitStaticFieldDeclaration(this); - } else { - return visitor.visitChildren(this); - } - } -} -export class FieldDeclarationContext extends ClassVarDecContext { - public FIELD(): TerminalNode { return this.getToken(JackParser.FIELD, 0); } - public fieldList(): FieldListContext { - return this.getRuleContext(0, FieldListContext); - } - public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } - constructor(ctx: ClassVarDecContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); - } + public override get ruleIndex(): number { return JackParser.RULE_classVarDec; } // @Override public override enterRule(listener: JackParserListener): void { - if (listener.enterFieldDeclaration) { - listener.enterFieldDeclaration(this); + if (listener.enterClassVarDec) { + listener.enterClassVarDec(this); } } // @Override public override exitRule(listener: JackParserListener): void { - if (listener.exitFieldDeclaration) { - listener.exitFieldDeclaration(this); + if (listener.exitClassVarDec) { + listener.exitClassVarDec(this); } } // @Override public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitFieldDeclaration) { - return visitor.visitFieldDeclaration(this); + if (visitor.visitClassVarDec) { + return visitor.visitClassVarDec(this); } else { return visitor.visitChildren(this); } @@ -2057,100 +2012,65 @@ export class FieldNameContext extends ParserRuleContext { export class SubroutineDeclarationContext extends ParserRuleContext { - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); + public subroutineType(): SubroutineTypeContext { + return this.getRuleContext(0, SubroutineTypeContext); } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineDeclaration; } - public override copyFrom(ctx: SubroutineDeclarationContext): void { - super.copyFrom(ctx); - } -} -export class ConstructorContext extends SubroutineDeclarationContext { - public CONSTRUCTOR(): TerminalNode { return this.getToken(JackParser.CONSTRUCTOR, 0); } public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { return this.getRuleContext(0, SubroutineDecWithoutTypeContext); } - constructor(ctx: SubroutineDeclarationContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); - } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterConstructor) { - listener.enterConstructor(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitConstructor) { - listener.exitConstructor(this); - } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); } // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitConstructor) { - return visitor.visitConstructor(this); - } else { - return visitor.visitChildren(this); - } - } -} -export class MethodContext extends SubroutineDeclarationContext { - public METHOD(): TerminalNode { return this.getToken(JackParser.METHOD, 0); } - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - return this.getRuleContext(0, SubroutineDecWithoutTypeContext); - } - constructor(ctx: SubroutineDeclarationContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); - } + public override get ruleIndex(): number { return JackParser.RULE_subroutineDeclaration; } // @Override public override enterRule(listener: JackParserListener): void { - if (listener.enterMethod) { - listener.enterMethod(this); + if (listener.enterSubroutineDeclaration) { + listener.enterSubroutineDeclaration(this); } } // @Override public override exitRule(listener: JackParserListener): void { - if (listener.exitMethod) { - listener.exitMethod(this); + if (listener.exitSubroutineDeclaration) { + listener.exitSubroutineDeclaration(this); } } // @Override public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitMethod) { - return visitor.visitMethod(this); + if (visitor.visitSubroutineDeclaration) { + return visitor.visitSubroutineDeclaration(this); } else { return visitor.visitChildren(this); } } } -export class FunctionContext extends SubroutineDeclarationContext { - public FUNCTION(): TerminalNode { return this.getToken(JackParser.FUNCTION, 0); } - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - return this.getRuleContext(0, SubroutineDecWithoutTypeContext); - } - constructor(ctx: SubroutineDeclarationContext) { - super(ctx.parent, ctx.invokingState); - this.copyFrom(ctx); + + +export class SubroutineTypeContext extends ParserRuleContext { + public CONSTRUCTOR(): TerminalNode | undefined { return this.tryGetToken(JackParser.CONSTRUCTOR, 0); } + public METHOD(): TerminalNode | undefined { return this.tryGetToken(JackParser.METHOD, 0); } + public FUNCTION(): TerminalNode | undefined { return this.tryGetToken(JackParser.FUNCTION, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); } // @Override + public override get ruleIndex(): number { return JackParser.RULE_subroutineType; } + // @Override public override enterRule(listener: JackParserListener): void { - if (listener.enterFunction) { - listener.enterFunction(this); + if (listener.enterSubroutineType) { + listener.enterSubroutineType(this); } } // @Override public override exitRule(listener: JackParserListener): void { - if (listener.exitFunction) { - listener.exitFunction(this); + if (listener.exitSubroutineType) { + listener.exitSubroutineType(this); } } // @Override public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitFunction) { - return visitor.visitFunction(this); + if (visitor.visitSubroutineType) { + return visitor.visitSubroutineType(this); } else { return visitor.visitChildren(this); } diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts index 18feef11..6cd2e47d 100644 --- a/compiler/src/generated/JackParserListener.ts +++ b/compiler/src/generated/JackParserListener.ts @@ -3,11 +3,6 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; -import { StaticFieldDeclarationContext } from "./JackParser"; -import { FieldDeclarationContext } from "./JackParser"; -import { ConstructorContext } from "./JackParser"; -import { MethodContext } from "./JackParser"; -import { FunctionContext } from "./JackParser"; import { ProgramContext } from "./JackParser"; import { ClassDeclarationContext } from "./JackParser"; import { ClassNameContext } from "./JackParser"; @@ -15,6 +10,7 @@ import { ClassVarDecContext } from "./JackParser"; import { FieldListContext } from "./JackParser"; import { FieldNameContext } from "./JackParser"; import { SubroutineDeclarationContext } from "./JackParser"; +import { SubroutineTypeContext } from "./JackParser"; import { SubroutineDecWithoutTypeContext } from "./JackParser"; import { SubroutineNameContext } from "./JackParser"; import { SubroutineReturnTypeContext } from "./JackParser"; @@ -52,71 +48,6 @@ import { BinaryOperatorContext } from "./JackParser"; * `JackParser`. */ export interface JackParserListener extends ParseTreeListener { - /** - * Enter a parse tree produced by the `staticFieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. - * @param ctx the parse tree - */ - enterStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => void; - /** - * Exit a parse tree produced by the `staticFieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. - * @param ctx the parse tree - */ - exitStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => void; - - /** - * Enter a parse tree produced by the `fieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. - * @param ctx the parse tree - */ - enterFieldDeclaration?: (ctx: FieldDeclarationContext) => void; - /** - * Exit a parse tree produced by the `fieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. - * @param ctx the parse tree - */ - exitFieldDeclaration?: (ctx: FieldDeclarationContext) => void; - - /** - * Enter a parse tree produced by the `constructor` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - enterConstructor?: (ctx: ConstructorContext) => void; - /** - * Exit a parse tree produced by the `constructor` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - exitConstructor?: (ctx: ConstructorContext) => void; - - /** - * Enter a parse tree produced by the `method` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - enterMethod?: (ctx: MethodContext) => void; - /** - * Exit a parse tree produced by the `method` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - exitMethod?: (ctx: MethodContext) => void; - - /** - * Enter a parse tree produced by the `function` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - enterFunction?: (ctx: FunctionContext) => void; - /** - * Exit a parse tree produced by the `function` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - exitFunction?: (ctx: FunctionContext) => void; - /** * Enter a parse tree produced by `JackParser.program`. * @param ctx the parse tree @@ -194,6 +125,17 @@ export interface JackParserListener extends ParseTreeListener { */ exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + enterSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + exitSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. * @param ctx the parse tree diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts index db2a78a0..2711d29e 100644 --- a/compiler/src/generated/JackParserVisitor.ts +++ b/compiler/src/generated/JackParserVisitor.ts @@ -3,11 +3,6 @@ import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; -import { StaticFieldDeclarationContext } from "./JackParser"; -import { FieldDeclarationContext } from "./JackParser"; -import { ConstructorContext } from "./JackParser"; -import { MethodContext } from "./JackParser"; -import { FunctionContext } from "./JackParser"; import { ProgramContext } from "./JackParser"; import { ClassDeclarationContext } from "./JackParser"; import { ClassNameContext } from "./JackParser"; @@ -15,6 +10,7 @@ import { ClassVarDecContext } from "./JackParser"; import { FieldListContext } from "./JackParser"; import { FieldNameContext } from "./JackParser"; import { SubroutineDeclarationContext } from "./JackParser"; +import { SubroutineTypeContext } from "./JackParser"; import { SubroutineDecWithoutTypeContext } from "./JackParser"; import { SubroutineNameContext } from "./JackParser"; import { SubroutineReturnTypeContext } from "./JackParser"; @@ -55,46 +51,6 @@ import { BinaryOperatorContext } from "./JackParser"; * operations with no return type. */ export interface JackParserVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by the `staticFieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. - * @param ctx the parse tree - * @return the visitor result - */ - visitStaticFieldDeclaration?: (ctx: StaticFieldDeclarationContext) => Result; - - /** - * Visit a parse tree produced by the `fieldDeclaration` - * labeled alternative in `JackParser.classVarDec`. - * @param ctx the parse tree - * @return the visitor result - */ - visitFieldDeclaration?: (ctx: FieldDeclarationContext) => Result; - - /** - * Visit a parse tree produced by the `constructor` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - * @return the visitor result - */ - visitConstructor?: (ctx: ConstructorContext) => Result; - - /** - * Visit a parse tree produced by the `method` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - * @return the visitor result - */ - visitMethod?: (ctx: MethodContext) => Result; - - /** - * Visit a parse tree produced by the `function` - * labeled alternative in `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - * @return the visitor result - */ - visitFunction?: (ctx: FunctionContext) => Result; - /** * Visit a parse tree produced by `JackParser.program`. * @param ctx the parse tree @@ -144,6 +100,13 @@ export interface JackParserVisitor extends ParseTreeVisitor { */ visitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => Result; + /** + * Visit a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + * @return the visitor result + */ + visitSubroutineType?: (ctx: SubroutineTypeContext) => Result; + /** * Visit a parse tree produced by `JackParser.subroutineDecWithoutType`. * @param ctx the parse tree diff --git a/compiler/src/listener/symbol.table.listener.ts b/compiler/src/listener/global.symbol.table.listener.ts similarity index 58% rename from compiler/src/listener/symbol.table.listener.ts rename to compiler/src/listener/global.symbol.table.listener.ts index b2c27ae3..f684e1fb 100644 --- a/compiler/src/listener/symbol.table.listener.ts +++ b/compiler/src/listener/global.symbol.table.listener.ts @@ -1,16 +1,14 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ClassDeclarationContext, ConstructorContext, FunctionContext, MethodContext, SubroutineDecWithoutTypeContext } from "../generated/JackParser"; +import { ClassDeclarationContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { DuplicatedSubroutineError } from '../error' -import { builtInSymbols } from "../builtins"; -import { GenericSymbol } from "../symbol"; +import { builtInSymbols, builtInTypes } from "../builtins"; +import { GenericSymbol, SubroutineType } from "../symbol"; -const primitives = new Set(["int", "boolean", "char"] as const); +const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; - - export class GlobalSymbolTableListener implements JackParserListener, ParseTreeListener { // key can be class or . public globalSymbolTable: Record = structuredClone(builtInSymbols); @@ -30,15 +28,30 @@ export class GlobalSymbolTableListener implements JackParserListener, ParseTreeL this.className = ctx.className()?.text; }; - enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { - const nameCtx = ctx.subroutineName() + enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { + let subroutineType: SubroutineType; + if (ctx.subroutineType().CONSTRUCTOR() != undefined) { + subroutineType = SubroutineType.Constructor; + } else if (ctx.subroutineType().METHOD() != undefined) { + subroutineType = SubroutineType.Method; + } else if (ctx.subroutineType().FUNCTION() != undefined) { + subroutineType = SubroutineType.Function; + } else { + throw new Error("Invalid subroutine type") + } + const subroutineWithoutTypeCtx = ctx.subroutineDecWithoutType() + const nameCtx = subroutineWithoutTypeCtx.subroutineName() const subroutineName = nameCtx.text const id = this.className + "." + subroutineName if (this.globalSymbolTable[id] != undefined) { this.errors.push(new DuplicatedSubroutineError(nameCtx.start.line, nameCtx.start.startIndex, `Subroutine "${subroutineName}" is already defined.`)); } + const paramsCount = subroutineWithoutTypeCtx.parameterList().parameter().length this.globalSymbolTable[id] = { - subroutineParameterCount: ctx.parameterList().parameter().length, + subroutineInfo: { + type: subroutineType, + paramsCount: paramsCount, + } } as GenericSymbol; } diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 39ce32a8..e069f330 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,9 +1,9 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { DuplicatedVariableException, IncorrectParamsNumberInSubroutineCall, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCall, VoidSubroutineReturnsValueError } from "../error"; -import { ClassDeclarationContext, ElseStatementContext, FieldDeclarationContext, FieldNameContext, IfElseStatementContext, IfStatementContext, LetStatementContext, ParameterContext, ParameterNameContext, ReturnStatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, SubroutineReturnTypeContext, VarDeclarationContext, VarNameContext, VarNameInDeclarationContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; +import { DuplicatedVariableException, FunctionCalledAsMethodError, IncorrectParamsNumberInSubroutineCallError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, VoidSubroutineReturnsValueError } from "../error"; +import { ClassDeclarationContext, ClassNameContext, ElseStatementContext, FieldListContext, IfStatementContext, ParameterContext, ReturnStatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; -import { GenericSymbol } from "../symbol"; +import { GenericSymbol, LocalSymbolTable, SubroutineType } from "../symbol"; class BinaryTreeNode { _returns?: boolean; @@ -71,10 +71,17 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener subroutineShouldReturnVoidType: boolean = false; cfgNode: BinaryTreeNode = new BinaryTreeNode(undefined); subroutineName: string = "" + className = "" constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } - enterFieldName(ctx: FieldNameContext) { - this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); + enterClassName(ctx: ClassNameContext) { + this.className = ctx.IDENTIFIER().text + }; + enterFieldList(ctx: FieldListContext) { + const type = ctx.varType().text + ctx.fieldName().forEach(field => { + this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, field.text, type); + }); }; enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { this.localSymbolTable.pushStack(); @@ -84,10 +91,9 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener this.subroutineName = ctx.subroutineName().text }; - enterParameterName(ctx: ParameterNameContext) { - this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); - } - + enterParameter(ctx: ParameterContext) { + this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.parameterName().text, ctx.varType().text); + }; //Var enterVarType(ctx: VarTypeContext) { if (ctx.IDENTIFIER() != undefined) { @@ -98,8 +104,11 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener } }; - enterVarNameInDeclaration(ctx: VarNameInDeclarationContext) { - this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.text); + enterVarDeclaration(ctx: VarDeclarationContext) { + const type = ctx.varType().text + ctx.varNameInDeclaration().forEach(name => { + this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, name.text, type); + }) }; enterVarName(ctx: VarNameContext) { @@ -111,7 +120,6 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener /** * Control flow */ - enterWhileStatement(ctx: WhileStatementContext) { this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode); }; @@ -138,17 +146,59 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener } }; enterSubroutineCall(ctx: SubroutineCallContext) { - const subroutineId = ctx.subroutineId().text - const f = this.globalSymbolTable[subroutineId] - if (f == undefined) { - this.errors.push(new UnknownSubroutineCall(ctx.start.line, ctx.start.startIndex, ctx.subroutineId().text)); + //check if variable exists with the name before dot + + const subroutineId = ctx.subroutineId() + let callType: CallType; + + let subroutineIdText: string; + if (subroutineId.text.indexOf('.') == -1) { + //local method + callType = CallType.LocalMethod + subroutineIdText = this.className + "." + subroutineId.subroutineName().text } else { - const l = ctx.expressionList().expression().length - if (f.subroutineParameterCount != l) { - this.errors.push(new IncorrectParamsNumberInSubroutineCall(ctx.start.line, ctx.start.startIndex, subroutineId, - f.subroutineParameterCount!, l)); + // var method + const [varName, methodName] = subroutineId.text.split('.') + if (this.localSymbolTable.existsSymbol(varName)) { + const varType = this.localSymbolTable.getType(varName) + subroutineIdText = varType + "." + methodName + callType = CallType.VarMethod; + } else { + // class function/ctor + subroutineIdText = subroutineId.text + callType = CallType.ClassFunctionOrConstructor; } } + + const symbol = this.globalSymbolTable[subroutineIdText] + if (symbol == undefined) { + this.errors.push(new UnknownSubroutineCallError(ctx.start.line, ctx.start.startIndex, + subroutineId.subroutineName().text, + subroutineId.className()?.text + )); + } else { + //method called as a function + if (symbol.subroutineInfo?.type == SubroutineType.Method + && callType == CallType.ClassFunctionOrConstructor) { + this.errors.push(new MethodCalledAsFunctionError(ctx.start.line, ctx.start.startIndex, + subroutineId.subroutineName().text)); + } + // function called as a method + else if (symbol.subroutineInfo?.type == SubroutineType.Function + && callType == CallType.LocalMethod) { + this.errors.push(new FunctionCalledAsMethodError(ctx.start.line, ctx.start.startIndex, + subroutineId.subroutineName().text)); + + } else { + //check parameter count + const l = ctx.expressionList().expression().length + if (symbol.subroutineInfo!.paramsCount != l) { + this.errors.push(new IncorrectParamsNumberInSubroutineCallError(ctx.start.line, ctx.start.startIndex, subroutineId.text, + symbol.subroutineInfo!.paramsCount, l)); + } + } + } + }; enterReturnStatement(ctx: ReturnStatementContext) { const returnsVoid = ctx.expression() == undefined @@ -163,7 +213,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener exitSubroutineBody(ctx: SubroutineBodyContext) { if (!this.cfgNode.returns) { - this.errors.push(new SubroutineNotAllPathsReturn(ctx.start.line, ctx.start.startIndex, this.subroutineName)); + this.errors.push(new SubroutineNotAllPathsReturnError(ctx.start.line, ctx.start.startIndex, this.subroutineName)); } this.localSymbolTable.popStack(); }; @@ -175,11 +225,11 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; //Utils - localSymbolTableAdd(line: number, position: number, name: string) { + localSymbolTableAdd(line: number, position: number, name: string, type: string) { if (this.localSymbolTable.existsSymbol(name)) { this.errors.push(new DuplicatedVariableException(line, position, name)); } else { - this.localSymbolTable.add(name); + this.localSymbolTable.add(name, type); } } //to fix compiler error @@ -187,26 +237,9 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener } -export class LocalSymbolTable { - constructor(private scopeVarDecs: string[][] = [[]]) { - - } - existsSymbol(name: string): boolean { - for (let i = this.scopeVarDecs.length - 1; i >= 0; i--) { - if (this.scopeVarDecs[i].includes(name)) { - return true; - } - } - return false; - } - add(varName: string) { - this.scopeVarDecs[this.scopeVarDecs.length - 1].push(varName); - } - pushStack() { - this.scopeVarDecs.push([]); - } - popStack() { - this.scopeVarDecs.pop(); - } +enum CallType { + VarMethod, + LocalMethod, + ClassFunctionOrConstructor } \ No newline at end of file diff --git a/compiler/src/symbol.ts b/compiler/src/symbol.ts index da3d6013..cb80f095 100644 --- a/compiler/src/symbol.ts +++ b/compiler/src/symbol.ts @@ -1,6 +1,52 @@ /** * Generic symbol. Can be used for both class and function symbols */ +export enum SubroutineType { + Constructor = "ctor", + Function = "function", + Method = "method", +} +export interface SubroutineInfo { + paramsCount: number; + type: SubroutineType +} export interface GenericSymbol { - subroutineParameterCount?: number; + subroutineInfo?: SubroutineInfo; +} +export function createSubroutineSymbol(paramsCount: number, type: SubroutineType) { + return { subroutineInfo: { paramsCount, type } } as GenericSymbol +} + +type VariableType = string + +export class LocalSymbolTable { + constructor(private scopeVarDecs: Record[] = [{}]) { + + } + existsSymbol(name: string): boolean { + for (let i = this.scopeVarDecs.length - 1; i >= 0; i--) { + if (this.scopeVarDecs[i][name] != undefined) { + return true; + } + } + return false; + } + getType(name: string) { + for (let i = this.scopeVarDecs.length - 1; i >= 0; i--) { + if (this.scopeVarDecs[i][name] != undefined) { + return this.scopeVarDecs[i][name]; + } + } + return undefined; + } + add(varName: string, type: VariableType) { + this.scopeVarDecs[this.scopeVarDecs.length - 1][varName] = type; + } + pushStack() { + this.scopeVarDecs.push({}); + } + popStack() { + this.scopeVarDecs.pop(); + } + } \ No newline at end of file diff --git a/compiler/test/global.symbol.table.listener.test.ts b/compiler/test/global.symbol.table.listener.test.ts new file mode 100644 index 00000000..590264d8 --- /dev/null +++ b/compiler/test/global.symbol.table.listener.test.ts @@ -0,0 +1,104 @@ +import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; +import { ErrorListener } from "../src/listener/error.listener"; +import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.listener"; +import { DuplicatedSubroutineError, JackCompilerError } from "../src/error"; +import { getTestResourcePath, listenToTheTree, handleErrors, parseJackText, parseJackFile } from "./test.helper"; +import fs from 'fs'; +import path from "path"; +import { ProgramContext } from "../src/generated/JackParser"; +import { createSubroutineSymbol, SubroutineType } from "../src/symbol"; + +describe('Global symbol table', () => { + const jestConsole = console; + + beforeEach(() => { + global.console = require('console'); + }); + + afterEach(() => { + global.console = jestConsole; + }); + + test("should fail on duplicated subroutine", () => { + const filePath = getTestResourcePath("DuplicatedSubroutine.jack"); + const tree = parseJackFile(filePath) + const globalSymbolsListener = new GlobalSymbolTableListener() + listenToTheTree(tree, globalSymbolsListener) + const symbolsErrors = globalSymbolsListener.errors + expect(globalSymbolsListener.errors.length).toBe(1) + expect(symbolsErrors[0]).toBeInstanceOf(DuplicatedSubroutineError) + }) + + test("basic", () => { + + const expected = { + 'Array.dispose': createSubroutineSymbol(0, SubroutineType.Function), + 'Array.new': createSubroutineSymbol(1, SubroutineType.Function), + 'Keyboard.init': createSubroutineSymbol(0, SubroutineType.Function), + 'Keyboard.keyPressed': createSubroutineSymbol(0, SubroutineType.Function), + 'Keyboard.readChar': createSubroutineSymbol(0, SubroutineType.Function), + 'Keyboard.readInt': createSubroutineSymbol(1, SubroutineType.Function), + 'Keyboard.readLine': createSubroutineSymbol(1, SubroutineType.Function), + 'Math.abs': createSubroutineSymbol(1, SubroutineType.Function), + 'Math.divide': createSubroutineSymbol(2, SubroutineType.Function), + 'Math.max': createSubroutineSymbol(2, SubroutineType.Function), + 'Math.min': createSubroutineSymbol(2, SubroutineType.Function), + 'Math.multiply': createSubroutineSymbol(2, SubroutineType.Function), + 'Math.sqrt': createSubroutineSymbol(1, SubroutineType.Function), + 'Memory.alloc': createSubroutineSymbol(1, SubroutineType.Function), + 'Memory.deAlloc': createSubroutineSymbol(1, SubroutineType.Function), + 'Memory.peek': createSubroutineSymbol(1, SubroutineType.Function), + 'Memory.poke': createSubroutineSymbol(2, SubroutineType.Function), + 'Output.backSpace': createSubroutineSymbol(0, SubroutineType.Function), + 'Output.moveCursor': createSubroutineSymbol(2, SubroutineType.Function), + 'Output.printChar': createSubroutineSymbol(1, SubroutineType.Function), + 'Output.printInt': createSubroutineSymbol(1, SubroutineType.Function), + 'Output.println': createSubroutineSymbol(0, SubroutineType.Function), + 'Output.printString': createSubroutineSymbol(1, SubroutineType.Function), + 'Screen.clearScreen': createSubroutineSymbol(0, SubroutineType.Function), + 'Screen.drawCircle': createSubroutineSymbol(3, SubroutineType.Function), + 'Screen.drawLine': createSubroutineSymbol(4, SubroutineType.Function), + 'Screen.drawPixel': createSubroutineSymbol(2, SubroutineType.Function), + 'Screen.drawRectangle': createSubroutineSymbol(4, SubroutineType.Function), + 'Screen.setColor': createSubroutineSymbol(1, SubroutineType.Function), + 'String.appendChar': createSubroutineSymbol(1, SubroutineType.Function), + 'String.backSpace': createSubroutineSymbol(0, SubroutineType.Function), + 'String.charAt': createSubroutineSymbol(2, SubroutineType.Function), + 'String.dispose': createSubroutineSymbol(0, SubroutineType.Function), + 'String.doubleQuote': createSubroutineSymbol(0, SubroutineType.Function), + 'String.eraseLastChar': createSubroutineSymbol(0, SubroutineType.Function), + 'String.intValue': createSubroutineSymbol(0, SubroutineType.Function), + 'String.length': createSubroutineSymbol(0, SubroutineType.Function), + 'String.new': createSubroutineSymbol(1, SubroutineType.Function), + 'String.newLine': createSubroutineSymbol(0, SubroutineType.Function), + 'String.setCharAt': createSubroutineSymbol(1, SubroutineType.Function), + 'String.setInt': createSubroutineSymbol(1, SubroutineType.Function), + 'Sys.error': createSubroutineSymbol(1, SubroutineType.Function), + 'Sys.halt': createSubroutineSymbol(0, SubroutineType.Function), + 'Sys.wait': createSubroutineSymbol(1, SubroutineType.Function), + 'Fraction': {}, + 'Fraction.new': createSubroutineSymbol(2, SubroutineType.Constructor), + 'Fraction.reduce': createSubroutineSymbol(0, SubroutineType.Method), + 'Fraction.getNumerator': createSubroutineSymbol(0, SubroutineType.Method), + 'Fraction.getDenominator': createSubroutineSymbol(0, SubroutineType.Method), + 'Fraction.plus': createSubroutineSymbol(1, SubroutineType.Method), + 'Fraction.dispose': createSubroutineSymbol(0, SubroutineType.Method), + 'Fraction.print': createSubroutineSymbol(0, SubroutineType.Method), + 'Fraction.gcd': createSubroutineSymbol(2, SubroutineType.Function), + 'Main': {}, + 'Main.main': createSubroutineSymbol(0, SubroutineType.Function), + } + let globalSymbolsListener = new GlobalSymbolTableListener() + + const testFolder = getTestResourcePath("Fraction"); + const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); + for (const filePath of files) { + const tree = parseJackFile(filePath) + globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); + // console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) + } + expect(globalSymbolsListener.globalSymbolTable).toEqual(expected) + }) +}) + + diff --git a/compiler/test/local.symbol.table.test.ts b/compiler/test/local.symbol.table.test.ts index 62e7d776..b9ec250e 100644 --- a/compiler/test/local.symbol.table.test.ts +++ b/compiler/test/local.symbol.table.test.ts @@ -1,4 +1,4 @@ -import { LocalSymbolTable } from "../src/listener/validator.listener"; +import { LocalSymbolTable } from "../src/symbol"; describe('LocalSymbolTable', () => { const jestConsole = console; @@ -11,12 +11,13 @@ describe('LocalSymbolTable', () => { global.console = jestConsole; }); + test('add', () => { const localSymbolTable = new LocalSymbolTable(); const variableNames = ['testVariable1', 'testVariable2', 'testVariable3']; variableNames.forEach(variableName => { - localSymbolTable.add(variableName) + localSymbolTable.add(variableName, "int") expect(localSymbolTable.existsSymbol(variableName)).toBe(true); expect(localSymbolTable.existsSymbol(variableName + "_")).toBe(false); @@ -28,20 +29,20 @@ describe('LocalSymbolTable', () => { const classVar = 'a'; const functionVar = 'b'; - localSymbolTable.add(classVar); + localSymbolTable.add(classVar, "boolean"); localSymbolTable.pushStack(); - localSymbolTable.add(functionVar); + localSymbolTable.add(functionVar, "boolean"); - expect(localSymbolTable.existsSymbol(classVar )).toBe(true); + expect(localSymbolTable.existsSymbol(classVar)).toBe(true); expect(localSymbolTable.existsSymbol(functionVar)).toBe(true); localSymbolTable.popStack(); expect(localSymbolTable.existsSymbol(classVar)).toBe(true); expect(localSymbolTable.existsSymbol(functionVar)).toBe(false); - + }) }); \ No newline at end of file diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index 3ddb83bb..467fa8fd 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -1,6 +1,6 @@ import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker'; import fs from 'fs'; -import { GlobalSymbolTableListener } from "../src/listener/symbol.table.listener"; +import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.listener"; import path from "path"; import { ErrorListener } from "../src/listener/error.listener"; diff --git a/compiler/test/symbol.table.listener.test.ts b/compiler/test/symbol.table.listener.test.ts deleted file mode 100644 index 2bd2cb05..00000000 --- a/compiler/test/symbol.table.listener.test.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; -import { ErrorListener } from "../src/listener/error.listener"; -import { GlobalSymbolTableListener } from "../src/listener/symbol.table.listener"; -import { DuplicatedSubroutineError, JackCompilerError } from "../src/error"; -import { getTestResourcePath, listenToTheTree, handleErrors, parseJackText, parseJackFile } from "./test.helper"; -import fs from 'fs'; -import path from "path"; -import { ProgramContext } from "../src/generated/JackParser"; - -describe('Global symbol table', () => { - const jestConsole = console; - - beforeEach(() => { - global.console = require('console'); - }); - - afterEach(() => { - global.console = jestConsole; - }); - - test("should fail on duplicated subroutine", () => { - const filePath = getTestResourcePath("DuplicatedSubroutine.jack"); - const tree = parseJackFile(filePath) - const globalSymbolsListener = new GlobalSymbolTableListener() - listenToTheTree(tree, globalSymbolsListener) - const symbolsErrors = globalSymbolsListener.errors - expect(globalSymbolsListener.errors.length).toBe(1) - expect(symbolsErrors[0]).toBeInstanceOf(DuplicatedSubroutineError) - }) - - test("basic", () => { - const expected = { - 'Fraction': {}, - 'Fraction.new': { subroutineParameterCount: 2 }, - 'Fraction.reduce': { subroutineParameterCount: 0 }, - 'Fraction.getNumerator': { subroutineParameterCount: 0 }, - 'Fraction.getDenominator': { subroutineParameterCount: 0 }, - 'Fraction.plus': { subroutineParameterCount: 1 }, - 'Fraction.dispose': { subroutineParameterCount: 0 }, - 'Fraction.print': { subroutineParameterCount: 0 }, - 'Fraction.gcd': { subroutineParameterCount: 2 }, - 'Main': {}, - 'Main.main': { subroutineParameterCount: 0 }, - //builtins - 'Array.dispose': { subroutineParameterCount: 0 }, - 'Array.new': { subroutineParameterCount: 1 }, - 'Keyboard.init': { subroutineParameterCount: 0 }, - 'Keyboard.keyPressed': { subroutineParameterCount: 0 }, - 'Keyboard.readChar': { subroutineParameterCount: 0 }, - 'Keyboard.readInt': { subroutineParameterCount: 1 }, - 'Keyboard.readLine': { subroutineParameterCount: 1 }, - 'Math.abs': { subroutineParameterCount: 1 }, - 'Math.divide': { subroutineParameterCount: 2 }, - 'Math.max': { subroutineParameterCount: 2 }, - 'Math.min': { subroutineParameterCount: 2 }, - 'Math.multiply': { subroutineParameterCount: 2 }, - 'Math.sqrt': { subroutineParameterCount: 1 }, - 'Memory.alloc': { subroutineParameterCount: 1 }, - 'Memory.deAlloc': { subroutineParameterCount: 1 }, - 'Memory.peek': { subroutineParameterCount: 1 }, - 'Memory.poke': { subroutineParameterCount: 2 }, - 'Output.backSpace': { subroutineParameterCount: 0 }, - 'Output.moveCursor': { subroutineParameterCount: 2 }, - 'Output.printChar': { subroutineParameterCount: 1 }, - 'Output.printInt': { subroutineParameterCount: 1 }, - 'Output.println': { subroutineParameterCount: 0 }, - 'Output.printString': { subroutineParameterCount: 1 }, - 'Screen.clearScreen': { subroutineParameterCount: 0 }, - 'Screen.drawCircle': { subroutineParameterCount: 3 }, - 'Screen.drawLine': { subroutineParameterCount: 4 }, - 'Screen.drawPixel': { subroutineParameterCount: 2 }, - 'Screen.drawRectangle': { subroutineParameterCount: 4 }, - 'Screen.setColor': { subroutineParameterCount: 1 }, - 'String.appendChar': { subroutineParameterCount: 1 }, - 'String.backSpace': { subroutineParameterCount: 0 }, - 'String.charAt': { subroutineParameterCount: 2 }, - 'String.dispose': { subroutineParameterCount: 0 }, - 'String.doubleQuote': { subroutineParameterCount: 0 }, - 'String.eraseLastChar': { subroutineParameterCount: 0 }, - 'String.intValue': { subroutineParameterCount: 0 }, - 'String.length': { subroutineParameterCount: 0 }, - 'String.new': { subroutineParameterCount: 1 }, - 'String.newLine': { subroutineParameterCount: 0 }, - 'String.setCharAt': { subroutineParameterCount: 1 }, - 'String.setInt': { subroutineParameterCount: 1 }, - 'Sys.error': { subroutineParameterCount: 1 }, - 'Sys.halt': { subroutineParameterCount: 0 }, - 'Sys.wait': { subroutineParameterCount: 1 } - } - let globalSymbolsListener = new GlobalSymbolTableListener() - - const testFolder = getTestResourcePath("Fraction"); - const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); - for (const filePath of files) { - const tree = parseJackFile(filePath) - globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); - console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) - } - expect(globalSymbolsListener.globalSymbolTable).toEqual(expected) - }) -}) - - diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index d24654b4..45ce59df 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,11 +1,11 @@ import { ParserRuleContext } from "antlr4ts" -import { DuplicatedVariableException as DuplicatedVariableError, IncorrectParamsNumberInSubroutineCall, JackCompilerError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturn, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCall, VoidSubroutineReturnsValueError } from "../src/error" +import { DuplicatedVariableException as DuplicatedVariableError, FunctionCalledAsMethodError, IncorrectParamsNumberInSubroutineCallError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, VoidSubroutineReturnsValueError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" import { ProgramContext } from "../src/generated/JackParser" import { Logger, ILogObj } from "tslog"; -import { GenericSymbol } from "../src/symbol" +import { GenericSymbol, SubroutineInfo, SubroutineType } from "../src/symbol" const log: Logger = new Logger(); describe('ValidatorListener', () => { @@ -19,10 +19,13 @@ describe('ValidatorListener', () => { global.console = jestConsole; }); - - function genericSymbol(paramsCount?: number) { - return paramsCount != undefined ? { subroutineParameterCount: paramsCount } as GenericSymbol : - {} as GenericSymbol + //TODO: refactor to use createFunctionSymbol + function genericSymbol(type?: SubroutineType, paramsCount?: number): GenericSymbol { + if (type != undefined && paramsCount != undefined) { + return { subroutineInfo: { type, paramsCount } } as GenericSymbol + } else { + return {} as GenericSymbol + } } const duplicateVarClassBodies = [ @@ -73,8 +76,8 @@ describe('ValidatorListener', () => { }`, UndeclaredVariableError, { "Main": genericSymbol(), - "Main.b": genericSymbol(1), - "Main.a": genericSymbol() + "Main.b": genericSymbol(SubroutineType.Function, 1), + "Main.a": genericSymbol(SubroutineType.Function, 1) }) }) @@ -110,7 +113,7 @@ describe('ValidatorListener', () => { function D b(int a){ return D.new(); } - }`, undefined, { "D": genericSymbol(), "D.new": genericSymbol(0) }) + }`, undefined, { "D": genericSymbol(), "D.new": genericSymbol(SubroutineType.Constructor, 0) }) }) test('Arg Unknown class ', () => { testValidator(` @@ -211,7 +214,7 @@ describe('ValidatorListener', () => { return; } } - }`, SubroutineNotAllPathsReturn) + }`, SubroutineNotAllPathsReturnError) }) test('else missing return ', () => { testValidator(` @@ -225,7 +228,7 @@ describe('ValidatorListener', () => { } } - }`, SubroutineNotAllPathsReturn) + }`, SubroutineNotAllPathsReturnError) }) test('while missing return', () => { @@ -238,7 +241,7 @@ describe('ValidatorListener', () => { } } - }`, SubroutineNotAllPathsReturn) + }`, SubroutineNotAllPathsReturnError) }) test(' missing return after while', () => { @@ -251,7 +254,7 @@ describe('ValidatorListener', () => { return 0; } } - }`, SubroutineNotAllPathsReturn) + }`, SubroutineNotAllPathsReturnError) }) test('nested if missing return', () => { @@ -270,7 +273,7 @@ describe('ValidatorListener', () => { return; } } - }`, SubroutineNotAllPathsReturn) + }`, SubroutineNotAllPathsReturnError) }) test('nested if missing return 2', () => { testValidator(` @@ -288,7 +291,7 @@ describe('ValidatorListener', () => { return; } } - }`, SubroutineNotAllPathsReturn) + }`, SubroutineNotAllPathsReturnError) }) test('nested if missing return 3', () => { @@ -307,7 +310,7 @@ describe('ValidatorListener', () => { } } - }`, SubroutineNotAllPathsReturn) + }`, SubroutineNotAllPathsReturnError) }) test('should be valid', () => { testValidator(` @@ -334,7 +337,7 @@ describe('ValidatorListener', () => { do Main.c(); return; } - }`, UnknownSubroutineCall) + }`, UnknownSubroutineCallError) }) test('incorrect number of parameters when calling a function', () => { testValidator(` @@ -346,18 +349,92 @@ describe('ValidatorListener', () => { do Main.a(1); return; } - }`, IncorrectParamsNumberInSubroutineCall, { + }`, IncorrectParamsNumberInSubroutineCallError, { "Main": genericSymbol(), - "Main.a": genericSymbol(2), - "Main.b": genericSymbol(2) + "Main.a": genericSymbol(SubroutineType.Function, 2), + "Main.b": genericSymbol(SubroutineType.Function, 2) }) }) + test('call var method ', () => { + testValidator(` + class Main { + constructor Main new(){ + return this; + } + function void a(){ + var Main m; + let m = Main.new(); + do m.b(); + return; + } + method void b(){ + return; + } + }`, undefined, { + "Main": genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + "Main.a": genericSymbol(SubroutineType.Function, 0), + "Main.b": genericSymbol(SubroutineType.Method, 0) + }) + }) + test('call local method ', () => { + testValidator(` + class Main { + method void a(){ + do b(); + return; + } + method void b(){ + return; + } + }`, undefined, { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Method, 0), + "Main.b": genericSymbol(SubroutineType.Method, 0) + }) + }) + + /** + * - `Method ${className}.${subroutineName} was called as a function/constructor` + */ + test('method called as a function/constructor', () => { + testValidator(` + class Main { + function void b(){ + do Main.c(); + return; + } + method void c(){ + return; + } + }`, MethodCalledAsFunctionError, + { + "Main": genericSymbol(), + "Main.b": genericSymbol(SubroutineType.Function, 0), + "Main.c": genericSymbol(SubroutineType.Method, 0) + }) + }) + test('function/ctor called as a method', () => { + testValidator(` + class Main { + function void b(){ + do c(); + return; + } + function void c(){ + return; + } + }`, FunctionCalledAsMethodError, + { + "Main": genericSymbol(), + "Main.b": genericSymbol(SubroutineType.Function, 0), + "Main.c": genericSymbol(SubroutineType.Function, 0) + }) + }) /** * List of validations rules: - * - OS subroutine ${this.className}.${subroutine.name.value} must follow the interface - * - validate arg number * - `Method ${className}.${subroutineName} was called as a function/constructor` * - Subroutine was called as a method * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` @@ -378,16 +455,14 @@ function testValidator(src: string, expectedError?: if (validator.errors.length > 1) { console.error("Errors", validator.errors) } - try { expect(validator.errors.length).toBe(1) expect(validator.errors[0]).toBeInstanceOf(expectedError) } catch (e) { - throw new Error(`Expected error ${expectedError.name} but got ` + validator.errors[0]) + throw new Error(`Expected error ${expectedError.name} but got '` + validator.errors.join(",") + "'") } } else { if (validator.errors.length != 0) throw new Error("Didn't expect any errors but got " + validator.errors.join("\n")) - } } From 04d720f732047ebd04fb017d900ac2ec5779eea0 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sat, 28 Sep 2024 16:31:19 +0200 Subject: [PATCH 18/87] Add more validations --- compiler/parser-gen/JackParser.g4 | 14 +- compiler/src/error.ts | 31 +- compiler/src/generated/JackParser.interp | 3 +- compiler/src/generated/JackParser.ts | 714 ++++++++++-------- compiler/src/generated/JackParserListener.ts | 12 + compiler/src/generated/JackParserVisitor.ts | 8 + .../listener/global.symbol.table.listener.ts | 2 +- compiler/src/listener/validator.listener.ts | 66 +- compiler/test/parser.test.ts | 23 +- compiler/test/validator.listener.test.ts | 63 +- 10 files changed, 568 insertions(+), 368 deletions(-) diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/parser-gen/JackParser.g4 index 39fad1d9..cc70c142 100644 --- a/compiler/parser-gen/JackParser.g4 +++ b/compiler/parser-gen/JackParser.g4 @@ -7,7 +7,7 @@ options { program: classDeclaration EOF; classDeclaration: - CLASS className LBRACE classVarDec* subroutineDeclaration* RBRACE; + CLASS className LBRACE classVarDec* subroutineDeclaration* rBrace; className: IDENTIFIER; classVarDec: (STATIC | FIELD) fieldList SEMICOLON; fieldList: varType fieldName ( COMMA fieldName)*; @@ -24,8 +24,8 @@ varType: INT | CHAR | BOOLEAN | IDENTIFIER; parameterList: (parameter (COMMA parameter)*)?; parameter: varType parameterName; parameterName: IDENTIFIER; -subroutineBody: LBRACE varDeclaration* statements RBRACE; - +subroutineBody: LBRACE varDeclaration* statements rBrace; +rBrace: RBRACE; varDeclaration: VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; varNameInDeclaration: IDENTIFIER; @@ -43,11 +43,11 @@ letStatement: ifElseStatement: ifStatement elseStatement?; ifStatement: - IF LPAREN expression RPAREN LBRACE statements RBRACE; -elseStatement: ELSE LBRACE statements RBRACE; + IF LPAREN expression RPAREN LBRACE statements rBrace; +elseStatement: ELSE LBRACE statements rBrace; whileStatement: - WHILE LPAREN expression RPAREN LBRACE statements RBRACE; + WHILE LPAREN expression RPAREN LBRACE statements rBrace; doStatement: DO subroutineCall SEMICOLON; @@ -59,7 +59,7 @@ expressionList: (expression (COMMA expression)*)?; expression: binaryOperation = expression binaryOperator expression - | constant + | constant | varName | subroutineCall | arrayAccess diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 1bd9f6fd..019c52ae 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -24,8 +24,8 @@ export class LexerOrParserError extends Error { } } export class DuplicatedSubroutineError extends JackCompilerError { - constructor(line: number, charPositionInLine: number, msg: string) { - super(line, charPositionInLine, msg); + constructor(line: number, charPositionInLine: number, subroutineName: string) { + super(line, charPositionInLine, `Subroutine ${subroutineName} redeclared.`); } } @@ -33,7 +33,6 @@ export class DuplicatedVariableException extends JackCompilerError { constructor(line: number, charPositionInLine: number, variableName: string) { super(line, charPositionInLine, "Duplicated variable " + variableName); } - } @@ -86,8 +85,9 @@ export class IncorrectParamsNumberInSubroutineCallError extends JackCompilerErro subroutineName: string, expectedParamsCount: number, actualParamsCount: number) { + super(line, charPositionInLine, - `Subroutine ${subroutineName} expects ${expectedParamsCount} arguments while ${actualParamsCount} was provided`); + `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)`); Object.setPrototypeOf(this, IncorrectParamsNumberInSubroutineCallError.prototype); } @@ -116,4 +116,25 @@ export class FunctionCalledAsMethodError extends JackCompilerError { super(line, charPositionInLine, `Function or constructor ${subroutineId} was called as a method`); Object.setPrototypeOf(this, FunctionCalledAsMethodError.prototype); } -} \ No newline at end of file +} + +export class IncorrectConstructorReturnType extends JackCompilerError { + constructor(line: number, charPositionInLine: number) { + super(line, charPositionInLine, `The return type of a constructor must be of the class type`); + Object.setPrototypeOf(this, IncorrectConstructorReturnType.prototype); + } +} + +export class UnreachableCodeError extends JackCompilerError { + constructor(line: number, charPositionInLine: number) { + super(line, charPositionInLine, `Unreachable code`); + Object.setPrototypeOf(this, UnreachableCodeError.prototype); + } +} + +export class ConstructorMushReturnThis extends JackCompilerError { + constructor(line: number, charPositionInLine: number) { + super(line, charPositionInLine, `A constructor must return 'this'`); + Object.setPrototypeOf(this, ConstructorMushReturnThis.prototype); + } +} diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp index 91b826ff..13be77e9 100644 --- a/compiler/src/generated/JackParser.interp +++ b/compiler/src/generated/JackParser.interp @@ -113,6 +113,7 @@ parameterList parameter parameterName subroutineBody +rBrace varDeclaration varNameInDeclaration varName @@ -138,4 +139,4 @@ binaryOperator atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 294, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 86, 10, 3, 12, 3, 14, 3, 89, 11, 3, 3, 3, 7, 3, 92, 10, 3, 12, 3, 14, 3, 95, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 109, 10, 6, 12, 6, 14, 6, 112, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 5, 12, 132, 10, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 7, 14, 139, 10, 14, 12, 14, 14, 14, 142, 11, 14, 5, 14, 144, 10, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 7, 17, 153, 10, 17, 12, 17, 14, 17, 156, 11, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 7, 18, 166, 10, 18, 12, 18, 14, 18, 169, 11, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 7, 21, 178, 10, 21, 12, 21, 14, 21, 181, 11, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 5, 22, 188, 10, 22, 3, 23, 3, 23, 3, 23, 5, 23, 193, 10, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 5, 24, 201, 10, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 5, 30, 235, 10, 30, 3, 30, 5, 30, 238, 10, 30, 3, 30, 3, 30, 3, 31, 3, 31, 5, 31, 244, 10, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 7, 32, 251, 10, 32, 12, 32, 14, 32, 254, 11, 32, 5, 32, 256, 10, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 5, 33, 265, 10, 33, 3, 33, 3, 33, 3, 33, 3, 33, 7, 33, 271, 10, 33, 12, 33, 14, 33, 274, 11, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 2, 2, 3, 64, 40, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 2, 8, 3, 2, 7, 8, 3, 2, 4, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 281, 2, 78, 3, 2, 2, 2, 4, 81, 3, 2, 2, 2, 6, 98, 3, 2, 2, 2, 8, 100, 3, 2, 2, 2, 10, 104, 3, 2, 2, 2, 12, 113, 3, 2, 2, 2, 14, 115, 3, 2, 2, 2, 16, 118, 3, 2, 2, 2, 18, 120, 3, 2, 2, 2, 20, 127, 3, 2, 2, 2, 22, 131, 3, 2, 2, 2, 24, 133, 3, 2, 2, 2, 26, 143, 3, 2, 2, 2, 28, 145, 3, 2, 2, 2, 30, 148, 3, 2, 2, 2, 32, 150, 3, 2, 2, 2, 34, 160, 3, 2, 2, 2, 36, 172, 3, 2, 2, 2, 38, 174, 3, 2, 2, 2, 40, 179, 3, 2, 2, 2, 42, 187, 3, 2, 2, 2, 44, 189, 3, 2, 2, 2, 46, 198, 3, 2, 2, 2, 48, 202, 3, 2, 2, 2, 50, 210, 3, 2, 2, 2, 52, 215, 3, 2, 2, 2, 54, 223, 3, 2, 2, 2, 56, 227, 3, 2, 2, 2, 58, 237, 3, 2, 2, 2, 60, 241, 3, 2, 2, 2, 62, 255, 3, 2, 2, 2, 64, 264, 3, 2, 2, 2, 66, 275, 3, 2, 2, 2, 68, 279, 3, 2, 2, 2, 70, 282, 3, 2, 2, 2, 72, 287, 3, 2, 2, 2, 74, 289, 3, 2, 2, 2, 76, 291, 3, 2, 2, 2, 78, 79, 5, 4, 3, 2, 79, 80, 7, 2, 2, 3, 80, 3, 3, 2, 2, 2, 81, 82, 7, 3, 2, 2, 82, 83, 5, 6, 4, 2, 83, 87, 7, 20, 2, 2, 84, 86, 5, 8, 5, 2, 85, 84, 3, 2, 2, 2, 86, 89, 3, 2, 2, 2, 87, 85, 3, 2, 2, 2, 87, 88, 3, 2, 2, 2, 88, 93, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 90, 92, 5, 14, 8, 2, 91, 90, 3, 2, 2, 2, 92, 95, 3, 2, 2, 2, 93, 91, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 96, 3, 2, 2, 2, 95, 93, 3, 2, 2, 2, 96, 97, 7, 21, 2, 2, 97, 5, 3, 2, 2, 2, 98, 99, 7, 46, 2, 2, 99, 7, 3, 2, 2, 2, 100, 101, 9, 2, 2, 2, 101, 102, 5, 10, 6, 2, 102, 103, 7, 28, 2, 2, 103, 9, 3, 2, 2, 2, 104, 105, 5, 24, 13, 2, 105, 110, 5, 12, 7, 2, 106, 107, 7, 27, 2, 2, 107, 109, 5, 12, 7, 2, 108, 106, 3, 2, 2, 2, 109, 112, 3, 2, 2, 2, 110, 108, 3, 2, 2, 2, 110, 111, 3, 2, 2, 2, 111, 11, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 113, 114, 7, 46, 2, 2, 114, 13, 3, 2, 2, 2, 115, 116, 5, 16, 9, 2, 116, 117, 5, 18, 10, 2, 117, 15, 3, 2, 2, 2, 118, 119, 9, 3, 2, 2, 119, 17, 3, 2, 2, 2, 120, 121, 5, 22, 12, 2, 121, 122, 5, 20, 11, 2, 122, 123, 7, 22, 2, 2, 123, 124, 5, 26, 14, 2, 124, 125, 7, 23, 2, 2, 125, 126, 5, 32, 17, 2, 126, 19, 3, 2, 2, 2, 127, 128, 7, 46, 2, 2, 128, 21, 3, 2, 2, 2, 129, 132, 5, 24, 13, 2, 130, 132, 7, 13, 2, 2, 131, 129, 3, 2, 2, 2, 131, 130, 3, 2, 2, 2, 132, 23, 3, 2, 2, 2, 133, 134, 9, 4, 2, 2, 134, 25, 3, 2, 2, 2, 135, 140, 5, 28, 15, 2, 136, 137, 7, 27, 2, 2, 137, 139, 5, 28, 15, 2, 138, 136, 3, 2, 2, 2, 139, 142, 3, 2, 2, 2, 140, 138, 3, 2, 2, 2, 140, 141, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 143, 135, 3, 2, 2, 2, 143, 144, 3, 2, 2, 2, 144, 27, 3, 2, 2, 2, 145, 146, 5, 24, 13, 2, 146, 147, 5, 30, 16, 2, 147, 29, 3, 2, 2, 2, 148, 149, 7, 46, 2, 2, 149, 31, 3, 2, 2, 2, 150, 154, 7, 20, 2, 2, 151, 153, 5, 34, 18, 2, 152, 151, 3, 2, 2, 2, 153, 156, 3, 2, 2, 2, 154, 152, 3, 2, 2, 2, 154, 155, 3, 2, 2, 2, 155, 157, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 157, 158, 5, 40, 21, 2, 158, 159, 7, 21, 2, 2, 159, 33, 3, 2, 2, 2, 160, 161, 7, 9, 2, 2, 161, 162, 5, 24, 13, 2, 162, 167, 5, 36, 19, 2, 163, 164, 7, 27, 2, 2, 164, 166, 5, 36, 19, 2, 165, 163, 3, 2, 2, 2, 166, 169, 3, 2, 2, 2, 167, 165, 3, 2, 2, 2, 167, 168, 3, 2, 2, 2, 168, 170, 3, 2, 2, 2, 169, 167, 3, 2, 2, 2, 170, 171, 7, 28, 2, 2, 171, 35, 3, 2, 2, 2, 172, 173, 7, 46, 2, 2, 173, 37, 3, 2, 2, 2, 174, 175, 7, 46, 2, 2, 175, 39, 3, 2, 2, 2, 176, 178, 5, 42, 22, 2, 177, 176, 3, 2, 2, 2, 178, 181, 3, 2, 2, 2, 179, 177, 3, 2, 2, 2, 179, 180, 3, 2, 2, 2, 180, 41, 3, 2, 2, 2, 181, 179, 3, 2, 2, 2, 182, 188, 5, 44, 23, 2, 183, 188, 5, 46, 24, 2, 184, 188, 5, 52, 27, 2, 185, 188, 5, 54, 28, 2, 186, 188, 5, 60, 31, 2, 187, 182, 3, 2, 2, 2, 187, 183, 3, 2, 2, 2, 187, 184, 3, 2, 2, 2, 187, 185, 3, 2, 2, 2, 187, 186, 3, 2, 2, 2, 188, 43, 3, 2, 2, 2, 189, 192, 7, 14, 2, 2, 190, 193, 5, 38, 20, 2, 191, 193, 5, 70, 36, 2, 192, 190, 3, 2, 2, 2, 192, 191, 3, 2, 2, 2, 193, 194, 3, 2, 2, 2, 194, 195, 7, 29, 2, 2, 195, 196, 5, 64, 33, 2, 196, 197, 7, 28, 2, 2, 197, 45, 3, 2, 2, 2, 198, 200, 5, 48, 25, 2, 199, 201, 5, 50, 26, 2, 200, 199, 3, 2, 2, 2, 200, 201, 3, 2, 2, 2, 201, 47, 3, 2, 2, 2, 202, 203, 7, 16, 2, 2, 203, 204, 7, 22, 2, 2, 204, 205, 5, 64, 33, 2, 205, 206, 7, 23, 2, 2, 206, 207, 7, 20, 2, 2, 207, 208, 5, 40, 21, 2, 208, 209, 7, 21, 2, 2, 209, 49, 3, 2, 2, 2, 210, 211, 7, 17, 2, 2, 211, 212, 7, 20, 2, 2, 212, 213, 5, 40, 21, 2, 213, 214, 7, 21, 2, 2, 214, 51, 3, 2, 2, 2, 215, 216, 7, 18, 2, 2, 216, 217, 7, 22, 2, 2, 217, 218, 5, 64, 33, 2, 218, 219, 7, 23, 2, 2, 219, 220, 7, 20, 2, 2, 220, 221, 5, 40, 21, 2, 221, 222, 7, 21, 2, 2, 222, 53, 3, 2, 2, 2, 223, 224, 7, 15, 2, 2, 224, 225, 5, 56, 29, 2, 225, 226, 7, 28, 2, 2, 226, 55, 3, 2, 2, 2, 227, 228, 5, 58, 30, 2, 228, 229, 7, 22, 2, 2, 229, 230, 5, 62, 32, 2, 230, 231, 7, 23, 2, 2, 231, 57, 3, 2, 2, 2, 232, 235, 5, 6, 4, 2, 233, 235, 7, 45, 2, 2, 234, 232, 3, 2, 2, 2, 234, 233, 3, 2, 2, 2, 235, 236, 3, 2, 2, 2, 236, 238, 7, 26, 2, 2, 237, 234, 3, 2, 2, 2, 237, 238, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 240, 5, 20, 11, 2, 240, 59, 3, 2, 2, 2, 241, 243, 7, 19, 2, 2, 242, 244, 5, 64, 33, 2, 243, 242, 3, 2, 2, 2, 243, 244, 3, 2, 2, 2, 244, 245, 3, 2, 2, 2, 245, 246, 7, 28, 2, 2, 246, 61, 3, 2, 2, 2, 247, 252, 5, 64, 33, 2, 248, 249, 7, 27, 2, 2, 249, 251, 5, 64, 33, 2, 250, 248, 3, 2, 2, 2, 251, 254, 3, 2, 2, 2, 252, 250, 3, 2, 2, 2, 252, 253, 3, 2, 2, 2, 253, 256, 3, 2, 2, 2, 254, 252, 3, 2, 2, 2, 255, 247, 3, 2, 2, 2, 255, 256, 3, 2, 2, 2, 256, 63, 3, 2, 2, 2, 257, 258, 8, 33, 1, 2, 258, 265, 5, 72, 37, 2, 259, 265, 5, 38, 20, 2, 260, 265, 5, 56, 29, 2, 261, 265, 5, 70, 36, 2, 262, 265, 5, 68, 35, 2, 263, 265, 5, 66, 34, 2, 264, 257, 3, 2, 2, 2, 264, 259, 3, 2, 2, 2, 264, 260, 3, 2, 2, 2, 264, 261, 3, 2, 2, 2, 264, 262, 3, 2, 2, 2, 264, 263, 3, 2, 2, 2, 265, 272, 3, 2, 2, 2, 266, 267, 12, 9, 2, 2, 267, 268, 5, 76, 39, 2, 268, 269, 5, 64, 33, 10, 269, 271, 3, 2, 2, 2, 270, 266, 3, 2, 2, 2, 271, 274, 3, 2, 2, 2, 272, 270, 3, 2, 2, 2, 272, 273, 3, 2, 2, 2, 273, 65, 3, 2, 2, 2, 274, 272, 3, 2, 2, 2, 275, 276, 7, 22, 2, 2, 276, 277, 5, 64, 33, 2, 277, 278, 7, 23, 2, 2, 278, 67, 3, 2, 2, 2, 279, 280, 5, 74, 38, 2, 280, 281, 5, 64, 33, 2, 281, 69, 3, 2, 2, 2, 282, 283, 5, 38, 20, 2, 283, 284, 7, 24, 2, 2, 284, 285, 5, 64, 33, 2, 285, 286, 7, 25, 2, 2, 286, 71, 3, 2, 2, 2, 287, 288, 9, 5, 2, 2, 288, 73, 3, 2, 2, 2, 289, 290, 9, 6, 2, 2, 290, 75, 3, 2, 2, 2, 291, 292, 9, 7, 2, 2, 292, 77, 3, 2, 2, 2, 21, 87, 93, 110, 131, 140, 143, 154, 167, 179, 187, 192, 200, 234, 237, 243, 252, 255, 264, 272] \ No newline at end of file +[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 298, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 88, 10, 3, 12, 3, 14, 3, 91, 11, 3, 3, 3, 7, 3, 94, 10, 3, 12, 3, 14, 3, 97, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 111, 10, 6, 12, 6, 14, 6, 114, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 5, 12, 134, 10, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 7, 14, 141, 10, 14, 12, 14, 14, 14, 144, 11, 14, 5, 14, 146, 10, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 7, 17, 155, 10, 17, 12, 17, 14, 17, 158, 11, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 170, 10, 19, 12, 19, 14, 19, 173, 11, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 7, 22, 182, 10, 22, 12, 22, 14, 22, 185, 11, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 192, 10, 23, 3, 24, 3, 24, 3, 24, 5, 24, 197, 10, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 5, 25, 205, 10, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 5, 31, 239, 10, 31, 3, 31, 5, 31, 242, 10, 31, 3, 31, 3, 31, 3, 32, 3, 32, 5, 32, 248, 10, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 7, 33, 255, 10, 33, 12, 33, 14, 33, 258, 11, 33, 5, 33, 260, 10, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 5, 34, 269, 10, 34, 3, 34, 3, 34, 3, 34, 3, 34, 7, 34, 275, 10, 34, 12, 34, 14, 34, 278, 11, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 2, 2, 3, 66, 41, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 2, 8, 3, 2, 7, 8, 3, 2, 4, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 284, 2, 80, 3, 2, 2, 2, 4, 83, 3, 2, 2, 2, 6, 100, 3, 2, 2, 2, 8, 102, 3, 2, 2, 2, 10, 106, 3, 2, 2, 2, 12, 115, 3, 2, 2, 2, 14, 117, 3, 2, 2, 2, 16, 120, 3, 2, 2, 2, 18, 122, 3, 2, 2, 2, 20, 129, 3, 2, 2, 2, 22, 133, 3, 2, 2, 2, 24, 135, 3, 2, 2, 2, 26, 145, 3, 2, 2, 2, 28, 147, 3, 2, 2, 2, 30, 150, 3, 2, 2, 2, 32, 152, 3, 2, 2, 2, 34, 162, 3, 2, 2, 2, 36, 164, 3, 2, 2, 2, 38, 176, 3, 2, 2, 2, 40, 178, 3, 2, 2, 2, 42, 183, 3, 2, 2, 2, 44, 191, 3, 2, 2, 2, 46, 193, 3, 2, 2, 2, 48, 202, 3, 2, 2, 2, 50, 206, 3, 2, 2, 2, 52, 214, 3, 2, 2, 2, 54, 219, 3, 2, 2, 2, 56, 227, 3, 2, 2, 2, 58, 231, 3, 2, 2, 2, 60, 241, 3, 2, 2, 2, 62, 245, 3, 2, 2, 2, 64, 259, 3, 2, 2, 2, 66, 268, 3, 2, 2, 2, 68, 279, 3, 2, 2, 2, 70, 283, 3, 2, 2, 2, 72, 286, 3, 2, 2, 2, 74, 291, 3, 2, 2, 2, 76, 293, 3, 2, 2, 2, 78, 295, 3, 2, 2, 2, 80, 81, 5, 4, 3, 2, 81, 82, 7, 2, 2, 3, 82, 3, 3, 2, 2, 2, 83, 84, 7, 3, 2, 2, 84, 85, 5, 6, 4, 2, 85, 89, 7, 20, 2, 2, 86, 88, 5, 8, 5, 2, 87, 86, 3, 2, 2, 2, 88, 91, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 95, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 92, 94, 5, 14, 8, 2, 93, 92, 3, 2, 2, 2, 94, 97, 3, 2, 2, 2, 95, 93, 3, 2, 2, 2, 95, 96, 3, 2, 2, 2, 96, 98, 3, 2, 2, 2, 97, 95, 3, 2, 2, 2, 98, 99, 5, 34, 18, 2, 99, 5, 3, 2, 2, 2, 100, 101, 7, 46, 2, 2, 101, 7, 3, 2, 2, 2, 102, 103, 9, 2, 2, 2, 103, 104, 5, 10, 6, 2, 104, 105, 7, 28, 2, 2, 105, 9, 3, 2, 2, 2, 106, 107, 5, 24, 13, 2, 107, 112, 5, 12, 7, 2, 108, 109, 7, 27, 2, 2, 109, 111, 5, 12, 7, 2, 110, 108, 3, 2, 2, 2, 111, 114, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 112, 113, 3, 2, 2, 2, 113, 11, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 115, 116, 7, 46, 2, 2, 116, 13, 3, 2, 2, 2, 117, 118, 5, 16, 9, 2, 118, 119, 5, 18, 10, 2, 119, 15, 3, 2, 2, 2, 120, 121, 9, 3, 2, 2, 121, 17, 3, 2, 2, 2, 122, 123, 5, 22, 12, 2, 123, 124, 5, 20, 11, 2, 124, 125, 7, 22, 2, 2, 125, 126, 5, 26, 14, 2, 126, 127, 7, 23, 2, 2, 127, 128, 5, 32, 17, 2, 128, 19, 3, 2, 2, 2, 129, 130, 7, 46, 2, 2, 130, 21, 3, 2, 2, 2, 131, 134, 5, 24, 13, 2, 132, 134, 7, 13, 2, 2, 133, 131, 3, 2, 2, 2, 133, 132, 3, 2, 2, 2, 134, 23, 3, 2, 2, 2, 135, 136, 9, 4, 2, 2, 136, 25, 3, 2, 2, 2, 137, 142, 5, 28, 15, 2, 138, 139, 7, 27, 2, 2, 139, 141, 5, 28, 15, 2, 140, 138, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 146, 3, 2, 2, 2, 144, 142, 3, 2, 2, 2, 145, 137, 3, 2, 2, 2, 145, 146, 3, 2, 2, 2, 146, 27, 3, 2, 2, 2, 147, 148, 5, 24, 13, 2, 148, 149, 5, 30, 16, 2, 149, 29, 3, 2, 2, 2, 150, 151, 7, 46, 2, 2, 151, 31, 3, 2, 2, 2, 152, 156, 7, 20, 2, 2, 153, 155, 5, 36, 19, 2, 154, 153, 3, 2, 2, 2, 155, 158, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 156, 157, 3, 2, 2, 2, 157, 159, 3, 2, 2, 2, 158, 156, 3, 2, 2, 2, 159, 160, 5, 42, 22, 2, 160, 161, 5, 34, 18, 2, 161, 33, 3, 2, 2, 2, 162, 163, 7, 21, 2, 2, 163, 35, 3, 2, 2, 2, 164, 165, 7, 9, 2, 2, 165, 166, 5, 24, 13, 2, 166, 171, 5, 38, 20, 2, 167, 168, 7, 27, 2, 2, 168, 170, 5, 38, 20, 2, 169, 167, 3, 2, 2, 2, 170, 173, 3, 2, 2, 2, 171, 169, 3, 2, 2, 2, 171, 172, 3, 2, 2, 2, 172, 174, 3, 2, 2, 2, 173, 171, 3, 2, 2, 2, 174, 175, 7, 28, 2, 2, 175, 37, 3, 2, 2, 2, 176, 177, 7, 46, 2, 2, 177, 39, 3, 2, 2, 2, 178, 179, 7, 46, 2, 2, 179, 41, 3, 2, 2, 2, 180, 182, 5, 44, 23, 2, 181, 180, 3, 2, 2, 2, 182, 185, 3, 2, 2, 2, 183, 181, 3, 2, 2, 2, 183, 184, 3, 2, 2, 2, 184, 43, 3, 2, 2, 2, 185, 183, 3, 2, 2, 2, 186, 192, 5, 46, 24, 2, 187, 192, 5, 48, 25, 2, 188, 192, 5, 54, 28, 2, 189, 192, 5, 56, 29, 2, 190, 192, 5, 62, 32, 2, 191, 186, 3, 2, 2, 2, 191, 187, 3, 2, 2, 2, 191, 188, 3, 2, 2, 2, 191, 189, 3, 2, 2, 2, 191, 190, 3, 2, 2, 2, 192, 45, 3, 2, 2, 2, 193, 196, 7, 14, 2, 2, 194, 197, 5, 40, 21, 2, 195, 197, 5, 72, 37, 2, 196, 194, 3, 2, 2, 2, 196, 195, 3, 2, 2, 2, 197, 198, 3, 2, 2, 2, 198, 199, 7, 29, 2, 2, 199, 200, 5, 66, 34, 2, 200, 201, 7, 28, 2, 2, 201, 47, 3, 2, 2, 2, 202, 204, 5, 50, 26, 2, 203, 205, 5, 52, 27, 2, 204, 203, 3, 2, 2, 2, 204, 205, 3, 2, 2, 2, 205, 49, 3, 2, 2, 2, 206, 207, 7, 16, 2, 2, 207, 208, 7, 22, 2, 2, 208, 209, 5, 66, 34, 2, 209, 210, 7, 23, 2, 2, 210, 211, 7, 20, 2, 2, 211, 212, 5, 42, 22, 2, 212, 213, 5, 34, 18, 2, 213, 51, 3, 2, 2, 2, 214, 215, 7, 17, 2, 2, 215, 216, 7, 20, 2, 2, 216, 217, 5, 42, 22, 2, 217, 218, 5, 34, 18, 2, 218, 53, 3, 2, 2, 2, 219, 220, 7, 18, 2, 2, 220, 221, 7, 22, 2, 2, 221, 222, 5, 66, 34, 2, 222, 223, 7, 23, 2, 2, 223, 224, 7, 20, 2, 2, 224, 225, 5, 42, 22, 2, 225, 226, 5, 34, 18, 2, 226, 55, 3, 2, 2, 2, 227, 228, 7, 15, 2, 2, 228, 229, 5, 58, 30, 2, 229, 230, 7, 28, 2, 2, 230, 57, 3, 2, 2, 2, 231, 232, 5, 60, 31, 2, 232, 233, 7, 22, 2, 2, 233, 234, 5, 64, 33, 2, 234, 235, 7, 23, 2, 2, 235, 59, 3, 2, 2, 2, 236, 239, 5, 6, 4, 2, 237, 239, 7, 45, 2, 2, 238, 236, 3, 2, 2, 2, 238, 237, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 242, 7, 26, 2, 2, 241, 238, 3, 2, 2, 2, 241, 242, 3, 2, 2, 2, 242, 243, 3, 2, 2, 2, 243, 244, 5, 20, 11, 2, 244, 61, 3, 2, 2, 2, 245, 247, 7, 19, 2, 2, 246, 248, 5, 66, 34, 2, 247, 246, 3, 2, 2, 2, 247, 248, 3, 2, 2, 2, 248, 249, 3, 2, 2, 2, 249, 250, 7, 28, 2, 2, 250, 63, 3, 2, 2, 2, 251, 256, 5, 66, 34, 2, 252, 253, 7, 27, 2, 2, 253, 255, 5, 66, 34, 2, 254, 252, 3, 2, 2, 2, 255, 258, 3, 2, 2, 2, 256, 254, 3, 2, 2, 2, 256, 257, 3, 2, 2, 2, 257, 260, 3, 2, 2, 2, 258, 256, 3, 2, 2, 2, 259, 251, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 65, 3, 2, 2, 2, 261, 262, 8, 34, 1, 2, 262, 269, 5, 74, 38, 2, 263, 269, 5, 40, 21, 2, 264, 269, 5, 58, 30, 2, 265, 269, 5, 72, 37, 2, 266, 269, 5, 70, 36, 2, 267, 269, 5, 68, 35, 2, 268, 261, 3, 2, 2, 2, 268, 263, 3, 2, 2, 2, 268, 264, 3, 2, 2, 2, 268, 265, 3, 2, 2, 2, 268, 266, 3, 2, 2, 2, 268, 267, 3, 2, 2, 2, 269, 276, 3, 2, 2, 2, 270, 271, 12, 9, 2, 2, 271, 272, 5, 78, 40, 2, 272, 273, 5, 66, 34, 10, 273, 275, 3, 2, 2, 2, 274, 270, 3, 2, 2, 2, 275, 278, 3, 2, 2, 2, 276, 274, 3, 2, 2, 2, 276, 277, 3, 2, 2, 2, 277, 67, 3, 2, 2, 2, 278, 276, 3, 2, 2, 2, 279, 280, 7, 22, 2, 2, 280, 281, 5, 66, 34, 2, 281, 282, 7, 23, 2, 2, 282, 69, 3, 2, 2, 2, 283, 284, 5, 76, 39, 2, 284, 285, 5, 66, 34, 2, 285, 71, 3, 2, 2, 2, 286, 287, 5, 40, 21, 2, 287, 288, 7, 24, 2, 2, 288, 289, 5, 66, 34, 2, 289, 290, 7, 25, 2, 2, 290, 73, 3, 2, 2, 2, 291, 292, 9, 5, 2, 2, 292, 75, 3, 2, 2, 2, 293, 294, 9, 6, 2, 2, 294, 77, 3, 2, 2, 2, 295, 296, 9, 7, 2, 2, 296, 79, 3, 2, 2, 2, 21, 89, 95, 112, 133, 142, 145, 156, 171, 183, 191, 196, 204, 238, 241, 247, 256, 259, 268, 276] \ No newline at end of file diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts index 2199555f..53fbc204 100644 --- a/compiler/src/generated/JackParser.ts +++ b/compiler/src/generated/JackParser.ts @@ -90,38 +90,40 @@ export class JackParser extends Parser { public static readonly RULE_parameter = 13; public static readonly RULE_parameterName = 14; public static readonly RULE_subroutineBody = 15; - public static readonly RULE_varDeclaration = 16; - public static readonly RULE_varNameInDeclaration = 17; - public static readonly RULE_varName = 18; - public static readonly RULE_statements = 19; - public static readonly RULE_statement = 20; - public static readonly RULE_letStatement = 21; - public static readonly RULE_ifElseStatement = 22; - public static readonly RULE_ifStatement = 23; - public static readonly RULE_elseStatement = 24; - public static readonly RULE_whileStatement = 25; - public static readonly RULE_doStatement = 26; - public static readonly RULE_subroutineCall = 27; - public static readonly RULE_subroutineId = 28; - public static readonly RULE_returnStatement = 29; - public static readonly RULE_expressionList = 30; - public static readonly RULE_expression = 31; - public static readonly RULE_groupedExpression = 32; - public static readonly RULE_unaryOp = 33; - public static readonly RULE_arrayAccess = 34; - public static readonly RULE_constant = 35; - public static readonly RULE_unaryOperator = 36; - public static readonly RULE_binaryOperator = 37; + public static readonly RULE_rBrace = 16; + public static readonly RULE_varDeclaration = 17; + public static readonly RULE_varNameInDeclaration = 18; + public static readonly RULE_varName = 19; + public static readonly RULE_statements = 20; + public static readonly RULE_statement = 21; + public static readonly RULE_letStatement = 22; + public static readonly RULE_ifElseStatement = 23; + public static readonly RULE_ifStatement = 24; + public static readonly RULE_elseStatement = 25; + public static readonly RULE_whileStatement = 26; + public static readonly RULE_doStatement = 27; + public static readonly RULE_subroutineCall = 28; + public static readonly RULE_subroutineId = 29; + public static readonly RULE_returnStatement = 30; + public static readonly RULE_expressionList = 31; + public static readonly RULE_expression = 32; + public static readonly RULE_groupedExpression = 33; + public static readonly RULE_unaryOp = 34; + public static readonly RULE_arrayAccess = 35; + public static readonly RULE_constant = 36; + public static readonly RULE_unaryOperator = 37; + public static readonly RULE_binaryOperator = 38; // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ "program", "classDeclaration", "className", "classVarDec", "fieldList", "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", "subroutineName", "subroutineReturnType", "varType", "parameterList", - "parameter", "parameterName", "subroutineBody", "varDeclaration", "varNameInDeclaration", - "varName", "statements", "statement", "letStatement", "ifElseStatement", - "ifStatement", "elseStatement", "whileStatement", "doStatement", "subroutineCall", - "subroutineId", "returnStatement", "expressionList", "expression", "groupedExpression", - "unaryOp", "arrayAccess", "constant", "unaryOperator", "binaryOperator", + "parameter", "parameterName", "subroutineBody", "rBrace", "varDeclaration", + "varNameInDeclaration", "varName", "statements", "statement", "letStatement", + "ifElseStatement", "ifStatement", "elseStatement", "whileStatement", "doStatement", + "subroutineCall", "subroutineId", "returnStatement", "expressionList", + "expression", "groupedExpression", "unaryOp", "arrayAccess", "constant", + "unaryOperator", "binaryOperator", ]; private static readonly _LITERAL_NAMES: Array = [ @@ -174,9 +176,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 76; + this.state = 78; this.classDeclaration(); - this.state = 77; + this.state = 79; this.match(JackParser.EOF); } } @@ -202,42 +204,42 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 79; + this.state = 81; this.match(JackParser.CLASS); - this.state = 80; + this.state = 82; this.className(); - this.state = 81; + this.state = 83; this.match(JackParser.LBRACE); - this.state = 85; + this.state = 87; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.FIELD || _la === JackParser.STATIC) { { { - this.state = 82; + this.state = 84; this.classVarDec(); } } - this.state = 87; + this.state = 89; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 91; + this.state = 93; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0)) { { { - this.state = 88; + this.state = 90; this.subroutineDeclaration(); } } - this.state = 93; + this.state = 95; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 94; - this.match(JackParser.RBRACE); + this.state = 96; + this.rBrace(); } } catch (re) { @@ -261,7 +263,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 96; + this.state = 98; this.match(JackParser.IDENTIFIER); } } @@ -287,7 +289,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 98; + this.state = 100; _la = this._input.LA(1); if (!(_la === JackParser.FIELD || _la === JackParser.STATIC)) { this._errHandler.recoverInline(this); @@ -299,9 +301,9 @@ export class JackParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 99; + this.state = 101; this.fieldList(); - this.state = 100; + this.state = 102; this.match(JackParser.SEMICOLON); } } @@ -327,23 +329,23 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 102; + this.state = 104; this.varType(); - this.state = 103; + this.state = 105; this.fieldName(); - this.state = 108; + this.state = 110; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 104; + this.state = 106; this.match(JackParser.COMMA); - this.state = 105; + this.state = 107; this.fieldName(); } } - this.state = 110; + this.state = 112; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -370,7 +372,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 111; + this.state = 113; this.match(JackParser.IDENTIFIER); } } @@ -395,9 +397,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 113; + this.state = 115; this.subroutineType(); - this.state = 114; + this.state = 116; this.subroutineDecWithoutType(); } } @@ -423,7 +425,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 116; + this.state = 118; _la = this._input.LA(1); if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0))) { this._errHandler.recoverInline(this); @@ -458,17 +460,17 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 118; + this.state = 120; this.subroutineReturnType(); - this.state = 119; + this.state = 121; this.subroutineName(); - this.state = 120; + this.state = 122; this.match(JackParser.LPAREN); - this.state = 121; + this.state = 123; this.parameterList(); - this.state = 122; + this.state = 124; this.match(JackParser.RPAREN); - this.state = 123; + this.state = 125; this.subroutineBody(); } } @@ -493,7 +495,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 125; + this.state = 127; this.match(JackParser.IDENTIFIER); } } @@ -516,7 +518,7 @@ export class JackParser extends Parser { let _localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this._ctx, this.state); this.enterRule(_localctx, 20, JackParser.RULE_subroutineReturnType); try { - this.state = 129; + this.state = 131; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.INT: @@ -525,14 +527,14 @@ export class JackParser extends Parser { case JackParser.IDENTIFIER: this.enterOuterAlt(_localctx, 1); { - this.state = 127; + this.state = 129; this.varType(); } break; case JackParser.VOID: this.enterOuterAlt(_localctx, 2); { - this.state = 128; + this.state = 130; this.match(JackParser.VOID); } break; @@ -562,7 +564,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 131; + this.state = 133; _la = this._input.LA(1); if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER)) { this._errHandler.recoverInline(this); @@ -598,26 +600,26 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 141; + this.state = 143; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER) { { - this.state = 133; + this.state = 135; this.parameter(); - this.state = 138; + this.state = 140; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 134; + this.state = 136; this.match(JackParser.COMMA); - this.state = 135; + this.state = 137; this.parameter(); } } - this.state = 140; + this.state = 142; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -647,9 +649,9 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 143; + this.state = 145; this.varType(); - this.state = 144; + this.state = 146; this.parameterName(); } } @@ -674,7 +676,7 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 146; + this.state = 148; this.match(JackParser.IDENTIFIER); } } @@ -700,25 +702,50 @@ export class JackParser extends Parser { try { this.enterOuterAlt(_localctx, 1); { - this.state = 148; + this.state = 150; this.match(JackParser.LBRACE); - this.state = 152; + this.state = 154; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.VAR) { { { - this.state = 149; + this.state = 151; this.varDeclaration(); } } - this.state = 154; + this.state = 156; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 155; + this.state = 157; this.statements(); - this.state = 156; + this.state = 158; + this.rBrace(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + _localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return _localctx; + } + // @RuleVersion(0) + public rBrace(): RBraceContext { + let _localctx: RBraceContext = new RBraceContext(this._ctx, this.state); + this.enterRule(_localctx, 32, JackParser.RULE_rBrace); + try { + this.enterOuterAlt(_localctx, 1); + { + this.state = 160; this.match(JackParser.RBRACE); } } @@ -739,34 +766,34 @@ export class JackParser extends Parser { // @RuleVersion(0) public varDeclaration(): VarDeclarationContext { let _localctx: VarDeclarationContext = new VarDeclarationContext(this._ctx, this.state); - this.enterRule(_localctx, 32, JackParser.RULE_varDeclaration); + this.enterRule(_localctx, 34, JackParser.RULE_varDeclaration); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 158; + this.state = 162; this.match(JackParser.VAR); - this.state = 159; + this.state = 163; this.varType(); - this.state = 160; + this.state = 164; this.varNameInDeclaration(); - this.state = 165; + this.state = 169; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 161; + this.state = 165; this.match(JackParser.COMMA); - this.state = 162; + this.state = 166; this.varNameInDeclaration(); } } - this.state = 167; + this.state = 171; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 168; + this.state = 172; this.match(JackParser.SEMICOLON); } } @@ -787,11 +814,11 @@ export class JackParser extends Parser { // @RuleVersion(0) public varNameInDeclaration(): VarNameInDeclarationContext { let _localctx: VarNameInDeclarationContext = new VarNameInDeclarationContext(this._ctx, this.state); - this.enterRule(_localctx, 34, JackParser.RULE_varNameInDeclaration); + this.enterRule(_localctx, 36, JackParser.RULE_varNameInDeclaration); try { this.enterOuterAlt(_localctx, 1); { - this.state = 170; + this.state = 174; this.match(JackParser.IDENTIFIER); } } @@ -812,11 +839,11 @@ export class JackParser extends Parser { // @RuleVersion(0) public varName(): VarNameContext { let _localctx: VarNameContext = new VarNameContext(this._ctx, this.state); - this.enterRule(_localctx, 36, JackParser.RULE_varName); + this.enterRule(_localctx, 38, JackParser.RULE_varName); try { this.enterOuterAlt(_localctx, 1); { - this.state = 172; + this.state = 176; this.match(JackParser.IDENTIFIER); } } @@ -837,22 +864,22 @@ export class JackParser extends Parser { // @RuleVersion(0) public statements(): StatementsContext { let _localctx: StatementsContext = new StatementsContext(this._ctx, this.state); - this.enterRule(_localctx, 38, JackParser.RULE_statements); + this.enterRule(_localctx, 40, JackParser.RULE_statements); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 177; + this.state = 181; this._errHandler.sync(this); _la = this._input.LA(1); while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.LET) | (1 << JackParser.DO) | (1 << JackParser.IF) | (1 << JackParser.WHILE) | (1 << JackParser.RETURN))) !== 0)) { { { - this.state = 174; + this.state = 178; this.statement(); } } - this.state = 179; + this.state = 183; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -875,43 +902,43 @@ export class JackParser extends Parser { // @RuleVersion(0) public statement(): StatementContext { let _localctx: StatementContext = new StatementContext(this._ctx, this.state); - this.enterRule(_localctx, 40, JackParser.RULE_statement); + this.enterRule(_localctx, 42, JackParser.RULE_statement); try { - this.state = 185; + this.state = 189; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.LET: this.enterOuterAlt(_localctx, 1); { - this.state = 180; + this.state = 184; this.letStatement(); } break; case JackParser.IF: this.enterOuterAlt(_localctx, 2); { - this.state = 181; + this.state = 185; this.ifElseStatement(); } break; case JackParser.WHILE: this.enterOuterAlt(_localctx, 3); { - this.state = 182; + this.state = 186; this.whileStatement(); } break; case JackParser.DO: this.enterOuterAlt(_localctx, 4); { - this.state = 183; + this.state = 187; this.doStatement(); } break; case JackParser.RETURN: this.enterOuterAlt(_localctx, 5); { - this.state = 184; + this.state = 188; this.returnStatement(); } break; @@ -936,34 +963,34 @@ export class JackParser extends Parser { // @RuleVersion(0) public letStatement(): LetStatementContext { let _localctx: LetStatementContext = new LetStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 42, JackParser.RULE_letStatement); + this.enterRule(_localctx, 44, JackParser.RULE_letStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 187; + this.state = 191; this.match(JackParser.LET); - this.state = 190; + this.state = 194; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 10, this._ctx) ) { case 1: { - this.state = 188; + this.state = 192; this.varName(); } break; case 2: { - this.state = 189; + this.state = 193; this.arrayAccess(); } break; } - this.state = 192; + this.state = 196; this.match(JackParser.EQUALS); - this.state = 193; + this.state = 197; this.expression(0); - this.state = 194; + this.state = 198; this.match(JackParser.SEMICOLON); } } @@ -984,19 +1011,19 @@ export class JackParser extends Parser { // @RuleVersion(0) public ifElseStatement(): IfElseStatementContext { let _localctx: IfElseStatementContext = new IfElseStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 44, JackParser.RULE_ifElseStatement); + this.enterRule(_localctx, 46, JackParser.RULE_ifElseStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 196; + this.state = 200; this.ifStatement(); - this.state = 198; + this.state = 202; this._errHandler.sync(this); _la = this._input.LA(1); if (_la === JackParser.ELSE) { { - this.state = 197; + this.state = 201; this.elseStatement(); } } @@ -1020,24 +1047,24 @@ export class JackParser extends Parser { // @RuleVersion(0) public ifStatement(): IfStatementContext { let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 46, JackParser.RULE_ifStatement); + this.enterRule(_localctx, 48, JackParser.RULE_ifStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 200; + this.state = 204; this.match(JackParser.IF); - this.state = 201; + this.state = 205; this.match(JackParser.LPAREN); - this.state = 202; + this.state = 206; this.expression(0); - this.state = 203; + this.state = 207; this.match(JackParser.RPAREN); - this.state = 204; + this.state = 208; this.match(JackParser.LBRACE); - this.state = 205; + this.state = 209; this.statements(); - this.state = 206; - this.match(JackParser.RBRACE); + this.state = 210; + this.rBrace(); } } catch (re) { @@ -1057,18 +1084,18 @@ export class JackParser extends Parser { // @RuleVersion(0) public elseStatement(): ElseStatementContext { let _localctx: ElseStatementContext = new ElseStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 48, JackParser.RULE_elseStatement); + this.enterRule(_localctx, 50, JackParser.RULE_elseStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 208; + this.state = 212; this.match(JackParser.ELSE); - this.state = 209; + this.state = 213; this.match(JackParser.LBRACE); - this.state = 210; + this.state = 214; this.statements(); - this.state = 211; - this.match(JackParser.RBRACE); + this.state = 215; + this.rBrace(); } } catch (re) { @@ -1088,24 +1115,24 @@ export class JackParser extends Parser { // @RuleVersion(0) public whileStatement(): WhileStatementContext { let _localctx: WhileStatementContext = new WhileStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 50, JackParser.RULE_whileStatement); + this.enterRule(_localctx, 52, JackParser.RULE_whileStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 213; + this.state = 217; this.match(JackParser.WHILE); - this.state = 214; + this.state = 218; this.match(JackParser.LPAREN); - this.state = 215; + this.state = 219; this.expression(0); - this.state = 216; + this.state = 220; this.match(JackParser.RPAREN); - this.state = 217; + this.state = 221; this.match(JackParser.LBRACE); - this.state = 218; + this.state = 222; this.statements(); - this.state = 219; - this.match(JackParser.RBRACE); + this.state = 223; + this.rBrace(); } } catch (re) { @@ -1125,15 +1152,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public doStatement(): DoStatementContext { let _localctx: DoStatementContext = new DoStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 52, JackParser.RULE_doStatement); + this.enterRule(_localctx, 54, JackParser.RULE_doStatement); try { this.enterOuterAlt(_localctx, 1); { - this.state = 221; + this.state = 225; this.match(JackParser.DO); - this.state = 222; + this.state = 226; this.subroutineCall(); - this.state = 223; + this.state = 227; this.match(JackParser.SEMICOLON); } } @@ -1154,17 +1181,17 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineCall(): SubroutineCallContext { let _localctx: SubroutineCallContext = new SubroutineCallContext(this._ctx, this.state); - this.enterRule(_localctx, 54, JackParser.RULE_subroutineCall); + this.enterRule(_localctx, 56, JackParser.RULE_subroutineCall); try { this.enterOuterAlt(_localctx, 1); { - this.state = 225; + this.state = 229; this.subroutineId(); - this.state = 226; + this.state = 230; this.match(JackParser.LPAREN); - this.state = 227; + this.state = 231; this.expressionList(); - this.state = 228; + this.state = 232; this.match(JackParser.RPAREN); } } @@ -1185,39 +1212,39 @@ export class JackParser extends Parser { // @RuleVersion(0) public subroutineId(): SubroutineIdContext { let _localctx: SubroutineIdContext = new SubroutineIdContext(this._ctx, this.state); - this.enterRule(_localctx, 56, JackParser.RULE_subroutineId); + this.enterRule(_localctx, 58, JackParser.RULE_subroutineId); try { this.enterOuterAlt(_localctx, 1); { - this.state = 235; + this.state = 239; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 13, this._ctx) ) { case 1: { - this.state = 232; + this.state = 236; this._errHandler.sync(this); switch (this._input.LA(1)) { case JackParser.IDENTIFIER: { - this.state = 230; + this.state = 234; this.className(); } break; case JackParser.THIS_LITERAL: { - this.state = 231; + this.state = 235; this.match(JackParser.THIS_LITERAL); } break; default: throw new NoViableAltException(this); } - this.state = 234; + this.state = 238; this.match(JackParser.DOT); } break; } - this.state = 237; + this.state = 241; this.subroutineName(); } } @@ -1238,24 +1265,24 @@ export class JackParser extends Parser { // @RuleVersion(0) public returnStatement(): ReturnStatementContext { let _localctx: ReturnStatementContext = new ReturnStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 58, JackParser.RULE_returnStatement); + this.enterRule(_localctx, 60, JackParser.RULE_returnStatement); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 239; + this.state = 243; this.match(JackParser.RETURN); - this.state = 241; + this.state = 245; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 240; + this.state = 244; this.expression(0); } } - this.state = 243; + this.state = 247; this.match(JackParser.SEMICOLON); } } @@ -1276,31 +1303,31 @@ export class JackParser extends Parser { // @RuleVersion(0) public expressionList(): ExpressionListContext { let _localctx: ExpressionListContext = new ExpressionListContext(this._ctx, this.state); - this.enterRule(_localctx, 60, JackParser.RULE_expressionList); + this.enterRule(_localctx, 62, JackParser.RULE_expressionList); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 253; + this.state = 257; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { { - this.state = 245; + this.state = 249; this.expression(0); - this.state = 250; + this.state = 254; this._errHandler.sync(this); _la = this._input.LA(1); while (_la === JackParser.COMMA) { { { - this.state = 246; + this.state = 250; this.match(JackParser.COMMA); - this.state = 247; + this.state = 251; this.expression(0); } } - this.state = 252; + this.state = 256; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1336,59 +1363,59 @@ export class JackParser extends Parser { let _parentState: number = this.state; let _localctx: ExpressionContext = new ExpressionContext(this._ctx, _parentState); let _prevctx: ExpressionContext = _localctx; - let _startState: number = 62; - this.enterRecursionRule(_localctx, 62, JackParser.RULE_expression, _p); + let _startState: number = 64; + this.enterRecursionRule(_localctx, 64, JackParser.RULE_expression, _p); try { let _alt: number; this.enterOuterAlt(_localctx, 1); { - this.state = 262; + this.state = 266; this._errHandler.sync(this); switch ( this.interpreter.adaptivePredict(this._input, 17, this._ctx) ) { case 1: { - this.state = 256; + this.state = 260; this.constant(); } break; case 2: { - this.state = 257; + this.state = 261; this.varName(); } break; case 3: { - this.state = 258; + this.state = 262; this.subroutineCall(); } break; case 4: { - this.state = 259; + this.state = 263; this.arrayAccess(); } break; case 5: { - this.state = 260; + this.state = 264; this.unaryOp(); } break; case 6: { - this.state = 261; + this.state = 265; this.groupedExpression(); } break; } this._ctx._stop = this._input.tryLT(-1); - this.state = 270; + this.state = 274; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -1402,18 +1429,18 @@ export class JackParser extends Parser { _localctx = new ExpressionContext(_parentctx, _parentState); _localctx._binaryOperation = _prevctx; this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); - this.state = 264; + this.state = 268; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 265; + this.state = 269; this.binaryOperator(); - this.state = 266; + this.state = 270; this.expression(8); } } } - this.state = 272; + this.state = 276; this._errHandler.sync(this); _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); } @@ -1436,15 +1463,15 @@ export class JackParser extends Parser { // @RuleVersion(0) public groupedExpression(): GroupedExpressionContext { let _localctx: GroupedExpressionContext = new GroupedExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 64, JackParser.RULE_groupedExpression); + this.enterRule(_localctx, 66, JackParser.RULE_groupedExpression); try { this.enterOuterAlt(_localctx, 1); { - this.state = 273; + this.state = 277; this.match(JackParser.LPAREN); - this.state = 274; + this.state = 278; this.expression(0); - this.state = 275; + this.state = 279; this.match(JackParser.RPAREN); } } @@ -1465,13 +1492,13 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOp(): UnaryOpContext { let _localctx: UnaryOpContext = new UnaryOpContext(this._ctx, this.state); - this.enterRule(_localctx, 66, JackParser.RULE_unaryOp); + this.enterRule(_localctx, 68, JackParser.RULE_unaryOp); try { this.enterOuterAlt(_localctx, 1); { - this.state = 277; + this.state = 281; this.unaryOperator(); - this.state = 278; + this.state = 282; this.expression(0); } } @@ -1492,17 +1519,17 @@ export class JackParser extends Parser { // @RuleVersion(0) public arrayAccess(): ArrayAccessContext { let _localctx: ArrayAccessContext = new ArrayAccessContext(this._ctx, this.state); - this.enterRule(_localctx, 68, JackParser.RULE_arrayAccess); + this.enterRule(_localctx, 70, JackParser.RULE_arrayAccess); try { this.enterOuterAlt(_localctx, 1); { - this.state = 280; + this.state = 284; this.varName(); - this.state = 281; + this.state = 285; this.match(JackParser.LBRACKET); - this.state = 282; + this.state = 286; this.expression(0); - this.state = 283; + this.state = 287; this.match(JackParser.RBRACKET); } } @@ -1523,12 +1550,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public constant(): ConstantContext { let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 70, JackParser.RULE_constant); + this.enterRule(_localctx, 72, JackParser.RULE_constant); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 285; + this.state = 289; _la = this._input.LA(1); if (!(((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & ((1 << (JackParser.INTEGER_LITERAL - 40)) | (1 << (JackParser.BOOLEAN_LITERAL - 40)) | (1 << (JackParser.NULL_LITERAL - 40)) | (1 << (JackParser.THIS_LITERAL - 40)) | (1 << (JackParser.STRING_LITERAL - 40)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1559,12 +1586,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public unaryOperator(): UnaryOperatorContext { let _localctx: UnaryOperatorContext = new UnaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 72, JackParser.RULE_unaryOperator); + this.enterRule(_localctx, 74, JackParser.RULE_unaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 287; + this.state = 291; _la = this._input.LA(1); if (!(_la === JackParser.MINUS || _la === JackParser.TILDE)) { this._errHandler.recoverInline(this); @@ -1595,12 +1622,12 @@ export class JackParser extends Parser { // @RuleVersion(0) public binaryOperator(): BinaryOperatorContext { let _localctx: BinaryOperatorContext = new BinaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 74, JackParser.RULE_binaryOperator); + this.enterRule(_localctx, 76, JackParser.RULE_binaryOperator); let _la: number; try { this.enterOuterAlt(_localctx, 1); { - this.state = 289; + this.state = 293; _la = this._input.LA(1); if (!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & ((1 << (JackParser.EQUALS - 27)) | (1 << (JackParser.PLUS - 27)) | (1 << (JackParser.MINUS - 27)) | (1 << (JackParser.MUL - 27)) | (1 << (JackParser.DIV - 27)) | (1 << (JackParser.AND - 27)) | (1 << (JackParser.OR - 27)) | (1 << (JackParser.LESS_THAN - 27)) | (1 << (JackParser.GREATER_THAN - 27)))) !== 0))) { this._errHandler.recoverInline(this); @@ -1631,7 +1658,7 @@ export class JackParser extends Parser { public override sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 31: + case 32: return this.expression_sempred(_localctx as ExpressionContext, predIndex); } return true; @@ -1645,130 +1672,131 @@ export class JackParser extends Parser { } public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u0126\x04\x02" + + "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u012A\x04\x02" + "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + - "\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x03\x02\x03\x02\x03\x02\x03\x03" + - "\x03\x03\x03\x03\x03\x03\x07\x03V\n\x03\f\x03\x0E\x03Y\v\x03\x03\x03\x07" + - "\x03\\\n\x03\f\x03\x0E\x03_\v\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03" + - "\x05\x03\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x07\x06m" + - "\n\x06\f\x06\x0E\x06p\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\t\x03" + + "\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x03\x02\x03\x02\x03\x02" + + "\x03\x03\x03\x03\x03\x03\x03\x03\x07\x03X\n\x03\f\x03\x0E\x03[\v\x03\x03" + + "\x03\x07\x03^\n\x03\f\x03\x0E\x03a\v\x03\x03\x03\x03\x03\x03\x04\x03\x04" + + "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x07\x06" + + "o\n\x06\f\x06\x0E\x06r\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\t\x03" + "\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03\f\x03\f\x05" + - "\f\x84\n\f\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x07\x0E\x8B\n\x0E\f\x0E" + - "\x0E\x0E\x8E\v\x0E\x05\x0E\x90\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x10\x03" + - "\x10\x03\x11\x03\x11\x07\x11\x99\n\x11\f\x11\x0E\x11\x9C\v\x11\x03\x11" + - "\x03\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x07\x12\xA6\n" + - "\x12\f\x12\x0E\x12\xA9\v\x12\x03\x12\x03\x12\x03\x13\x03\x13\x03\x14\x03" + - "\x14\x03\x15\x07\x15\xB2\n\x15\f\x15\x0E\x15\xB5\v\x15\x03\x16\x03\x16" + - "\x03\x16\x03\x16\x03\x16\x05\x16\xBC\n\x16\x03\x17\x03\x17\x03\x17\x05" + - "\x17\xC1\n\x17\x03\x17\x03\x17\x03\x17\x03\x17\x03\x18\x03\x18\x05\x18" + - "\xC9\n\x18\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03\x19\x03" + - "\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03\x1B\x03" + - "\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03" + - "\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x05\x1E\xEB\n\x1E" + - "\x03\x1E\x05\x1E\xEE\n\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x05\x1F\xF4" + - "\n\x1F\x03\x1F\x03\x1F\x03 \x03 \x03 \x07 \xFB\n \f \x0E \xFE\v \x05 " + - "\u0100\n \x03!\x03!\x03!\x03!\x03!\x03!\x03!\x05!\u0109\n!\x03!\x03!\x03" + - "!\x03!\x07!\u010F\n!\f!\x0E!\u0112\v!\x03\"\x03\"\x03\"\x03\"\x03#\x03" + - "#\x03#\x03$\x03$\x03$\x03$\x03$\x03%\x03%\x03&\x03&\x03\'\x03\'\x03\'" + - "\x02\x02\x03@(\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02\x10\x02" + - "\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02\"\x02$\x02" + - "&\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02>\x02@\x02" + - "B\x02D\x02F\x02H\x02J\x02L\x02\x02\b\x03\x02\x07\b\x03\x02\x04\x06\x04" + - "\x02\n\f..\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02\x1D#%&\x02\u0119\x02" + - "N\x03\x02\x02\x02\x04Q\x03\x02\x02\x02\x06b\x03\x02\x02\x02\bd\x03\x02" + - "\x02\x02\nh\x03\x02\x02\x02\fq\x03\x02\x02\x02\x0Es\x03\x02\x02\x02\x10" + - "v\x03\x02\x02\x02\x12x\x03\x02\x02\x02\x14\x7F\x03\x02\x02\x02\x16\x83" + - "\x03\x02\x02\x02\x18\x85\x03\x02\x02\x02\x1A\x8F\x03\x02\x02\x02\x1C\x91" + - "\x03\x02\x02\x02\x1E\x94\x03\x02\x02\x02 \x96\x03\x02\x02\x02\"\xA0\x03" + - "\x02\x02\x02$\xAC\x03\x02\x02\x02&\xAE\x03\x02\x02\x02(\xB3\x03\x02\x02" + - "\x02*\xBB\x03\x02\x02\x02,\xBD\x03\x02\x02\x02.\xC6\x03\x02\x02\x020\xCA" + - "\x03\x02\x02\x022\xD2\x03\x02\x02\x024\xD7\x03\x02\x02\x026\xDF\x03\x02" + - "\x02\x028\xE3\x03\x02\x02\x02:\xED\x03\x02\x02\x02<\xF1\x03\x02\x02\x02" + - ">\xFF\x03\x02\x02\x02@\u0108\x03\x02\x02\x02B\u0113\x03\x02\x02\x02D\u0117" + - "\x03\x02\x02\x02F\u011A\x03\x02\x02\x02H\u011F\x03\x02\x02\x02J\u0121" + - "\x03\x02\x02\x02L\u0123\x03\x02\x02\x02NO\x05\x04\x03\x02OP\x07\x02\x02" + - "\x03P\x03\x03\x02\x02\x02QR\x07\x03\x02\x02RS\x05\x06\x04\x02SW\x07\x14" + - "\x02\x02TV\x05\b\x05\x02UT\x03\x02\x02\x02VY\x03\x02\x02\x02WU\x03\x02" + - "\x02\x02WX\x03\x02\x02\x02X]\x03\x02\x02\x02YW\x03\x02\x02\x02Z\\\x05" + - "\x0E\b\x02[Z\x03\x02\x02\x02\\_\x03\x02\x02\x02][\x03\x02\x02\x02]^\x03" + - "\x02\x02\x02^`\x03\x02\x02\x02_]\x03\x02\x02\x02`a\x07\x15\x02\x02a\x05" + - "\x03\x02\x02\x02bc\x07.\x02\x02c\x07\x03\x02\x02\x02de\t\x02\x02\x02e" + - "f\x05\n\x06\x02fg\x07\x1C\x02\x02g\t\x03\x02\x02\x02hi\x05\x18\r\x02i" + - "n\x05\f\x07\x02jk\x07\x1B\x02\x02km\x05\f\x07\x02lj\x03\x02\x02\x02mp" + - "\x03\x02\x02\x02nl\x03\x02\x02\x02no\x03\x02\x02\x02o\v\x03\x02\x02\x02" + - "pn\x03\x02\x02\x02qr\x07.\x02\x02r\r\x03\x02\x02\x02st\x05\x10\t\x02t" + - "u\x05\x12\n\x02u\x0F\x03\x02\x02\x02vw\t\x03\x02\x02w\x11\x03\x02\x02" + - "\x02xy\x05\x16\f\x02yz\x05\x14\v\x02z{\x07\x16\x02\x02{|\x05\x1A\x0E\x02" + - "|}\x07\x17\x02\x02}~\x05 \x11\x02~\x13\x03\x02\x02\x02\x7F\x80\x07.\x02" + - "\x02\x80\x15\x03\x02\x02\x02\x81\x84\x05\x18\r\x02\x82\x84\x07\r\x02\x02" + - "\x83\x81\x03\x02\x02\x02\x83\x82\x03\x02\x02\x02\x84\x17\x03\x02\x02\x02" + - "\x85\x86\t\x04\x02\x02\x86\x19\x03\x02\x02\x02\x87\x8C\x05\x1C\x0F\x02" + - "\x88\x89\x07\x1B\x02\x02\x89\x8B\x05\x1C\x0F\x02\x8A\x88\x03\x02\x02\x02" + - "\x8B\x8E\x03\x02\x02\x02\x8C\x8A\x03\x02\x02\x02\x8C\x8D\x03\x02\x02\x02" + - "\x8D\x90\x03\x02\x02\x02\x8E\x8C\x03\x02\x02\x02\x8F\x87\x03\x02\x02\x02" + - "\x8F\x90\x03\x02\x02\x02\x90\x1B\x03\x02\x02\x02\x91\x92\x05\x18\r\x02" + - "\x92\x93\x05\x1E\x10\x02\x93\x1D\x03\x02\x02\x02\x94\x95\x07.\x02\x02" + - "\x95\x1F\x03\x02\x02\x02\x96\x9A\x07\x14\x02\x02\x97\x99\x05\"\x12\x02" + - "\x98\x97\x03\x02\x02\x02\x99\x9C\x03\x02\x02\x02\x9A\x98\x03\x02\x02\x02" + - "\x9A\x9B\x03\x02\x02\x02\x9B\x9D\x03\x02\x02\x02\x9C\x9A\x03\x02\x02\x02" + - "\x9D\x9E\x05(\x15\x02\x9E\x9F\x07\x15\x02\x02\x9F!\x03\x02\x02\x02\xA0" + - "\xA1\x07\t\x02\x02\xA1\xA2\x05\x18\r\x02\xA2\xA7\x05$\x13\x02\xA3\xA4" + - "\x07\x1B\x02\x02\xA4\xA6\x05$\x13\x02\xA5\xA3\x03\x02\x02\x02\xA6\xA9" + - "\x03\x02\x02\x02\xA7\xA5\x03\x02\x02\x02\xA7\xA8\x03\x02\x02\x02\xA8\xAA" + - "\x03\x02\x02\x02\xA9\xA7\x03\x02\x02\x02\xAA\xAB\x07\x1C\x02\x02\xAB#" + - "\x03\x02\x02\x02\xAC\xAD\x07.\x02\x02\xAD%\x03\x02\x02\x02\xAE\xAF\x07" + - ".\x02\x02\xAF\'\x03\x02\x02\x02\xB0\xB2\x05*\x16\x02\xB1\xB0\x03\x02\x02" + - "\x02\xB2\xB5\x03\x02\x02\x02\xB3\xB1\x03\x02\x02\x02\xB3\xB4\x03\x02\x02" + - "\x02\xB4)\x03\x02\x02\x02\xB5\xB3\x03\x02\x02\x02\xB6\xBC\x05,\x17\x02" + - "\xB7\xBC\x05.\x18\x02\xB8\xBC\x054\x1B\x02\xB9\xBC\x056\x1C\x02\xBA\xBC" + - "\x05<\x1F\x02\xBB\xB6\x03\x02\x02\x02\xBB\xB7\x03\x02\x02\x02\xBB\xB8" + - "\x03\x02\x02\x02\xBB\xB9\x03\x02\x02\x02\xBB\xBA\x03\x02\x02\x02\xBC+" + - "\x03\x02\x02\x02\xBD\xC0\x07\x0E\x02\x02\xBE\xC1\x05&\x14\x02\xBF\xC1" + - "\x05F$\x02\xC0\xBE\x03\x02\x02\x02\xC0\xBF\x03\x02\x02\x02\xC1\xC2\x03" + - "\x02\x02\x02\xC2\xC3\x07\x1D\x02\x02\xC3\xC4\x05@!\x02\xC4\xC5\x07\x1C" + - "\x02\x02\xC5-\x03\x02\x02\x02\xC6\xC8\x050\x19\x02\xC7\xC9\x052\x1A\x02" + - "\xC8\xC7\x03\x02\x02\x02\xC8\xC9\x03\x02\x02\x02\xC9/\x03\x02\x02\x02" + - "\xCA\xCB\x07\x10\x02\x02\xCB\xCC\x07\x16\x02\x02\xCC\xCD\x05@!\x02\xCD" + - "\xCE\x07\x17\x02\x02\xCE\xCF\x07\x14\x02\x02\xCF\xD0\x05(\x15\x02\xD0" + - "\xD1\x07\x15\x02\x02\xD11\x03\x02\x02\x02\xD2\xD3\x07\x11\x02\x02\xD3" + - "\xD4\x07\x14\x02\x02\xD4\xD5\x05(\x15\x02\xD5\xD6\x07\x15\x02\x02\xD6" + - "3\x03\x02\x02\x02\xD7\xD8\x07\x12\x02\x02\xD8\xD9\x07\x16\x02\x02\xD9" + - "\xDA\x05@!\x02\xDA\xDB\x07\x17\x02\x02\xDB\xDC\x07\x14\x02\x02\xDC\xDD" + - "\x05(\x15\x02\xDD\xDE\x07\x15\x02\x02\xDE5\x03\x02\x02\x02\xDF\xE0\x07" + - "\x0F\x02\x02\xE0\xE1\x058\x1D\x02\xE1\xE2\x07\x1C\x02\x02\xE27\x03\x02" + - "\x02\x02\xE3\xE4\x05:\x1E\x02\xE4\xE5\x07\x16\x02\x02\xE5\xE6\x05> \x02" + - "\xE6\xE7\x07\x17\x02\x02\xE79\x03\x02\x02\x02\xE8\xEB\x05\x06\x04\x02" + - "\xE9\xEB\x07-\x02\x02\xEA\xE8\x03\x02\x02\x02\xEA\xE9\x03\x02\x02\x02" + - "\xEB\xEC\x03\x02\x02\x02\xEC\xEE\x07\x1A\x02\x02\xED\xEA\x03\x02\x02\x02" + - "\xED\xEE\x03\x02\x02\x02\xEE\xEF\x03\x02\x02\x02\xEF\xF0\x05\x14\v\x02" + - "\xF0;\x03\x02\x02\x02\xF1\xF3\x07\x13\x02\x02\xF2\xF4\x05@!\x02\xF3\xF2" + - "\x03\x02\x02\x02\xF3\xF4\x03\x02\x02\x02\xF4\xF5\x03\x02\x02\x02\xF5\xF6" + - "\x07\x1C\x02\x02\xF6=\x03\x02\x02\x02\xF7\xFC\x05@!\x02\xF8\xF9\x07\x1B" + - "\x02\x02\xF9\xFB\x05@!\x02\xFA\xF8\x03\x02\x02\x02\xFB\xFE\x03\x02\x02" + - "\x02\xFC\xFA\x03\x02\x02\x02\xFC\xFD\x03\x02\x02\x02\xFD\u0100\x03\x02" + - "\x02\x02\xFE\xFC\x03\x02\x02\x02\xFF\xF7\x03\x02\x02\x02\xFF\u0100\x03" + - "\x02\x02\x02\u0100?\x03\x02\x02\x02\u0101\u0102\b!\x01\x02\u0102\u0109" + - "\x05H%\x02\u0103\u0109\x05&\x14\x02\u0104\u0109\x058\x1D\x02\u0105\u0109" + - "\x05F$\x02\u0106\u0109\x05D#\x02\u0107\u0109\x05B\"\x02\u0108\u0101\x03" + - "\x02\x02\x02\u0108\u0103\x03\x02\x02\x02\u0108\u0104\x03\x02\x02\x02\u0108" + - "\u0105\x03\x02\x02\x02\u0108\u0106\x03\x02\x02\x02\u0108\u0107\x03\x02" + - "\x02\x02\u0109\u0110\x03\x02\x02\x02\u010A\u010B\f\t\x02\x02\u010B\u010C" + - "\x05L\'\x02\u010C\u010D\x05@!\n\u010D\u010F\x03\x02\x02\x02\u010E\u010A" + - "\x03\x02\x02\x02\u010F\u0112\x03\x02\x02\x02\u0110\u010E\x03\x02\x02\x02" + - "\u0110\u0111\x03\x02\x02\x02\u0111A\x03\x02\x02\x02\u0112\u0110\x03\x02" + - "\x02\x02\u0113\u0114\x07\x16\x02\x02\u0114\u0115\x05@!\x02\u0115\u0116" + - "\x07\x17\x02\x02\u0116C\x03\x02\x02\x02\u0117\u0118\x05J&\x02\u0118\u0119" + - "\x05@!\x02\u0119E\x03\x02\x02\x02\u011A\u011B\x05&\x14\x02\u011B\u011C" + - "\x07\x18\x02\x02\u011C\u011D\x05@!\x02\u011D\u011E\x07\x19\x02\x02\u011E" + - "G\x03\x02\x02\x02\u011F\u0120\t\x05\x02\x02\u0120I\x03\x02\x02\x02\u0121" + - "\u0122\t\x06\x02\x02\u0122K\x03\x02\x02\x02\u0123\u0124\t\x07\x02\x02" + - "\u0124M\x03\x02\x02\x02\x15W]n\x83\x8C\x8F\x9A\xA7\xB3\xBB\xC0\xC8\xEA" + - "\xED\xF3\xFC\xFF\u0108\u0110"; + "\f\x86\n\f\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x07\x0E\x8D\n\x0E\f\x0E" + + "\x0E\x0E\x90\v\x0E\x05\x0E\x92\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x10\x03" + + "\x10\x03\x11\x03\x11\x07\x11\x9B\n\x11\f\x11\x0E\x11\x9E\v\x11\x03\x11" + + "\x03\x11\x03\x11\x03\x12\x03\x12\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13" + + "\x07\x13\xAA\n\x13\f\x13\x0E\x13\xAD\v\x13\x03\x13\x03\x13\x03\x14\x03" + + "\x14\x03\x15\x03\x15\x03\x16\x07\x16\xB6\n\x16\f\x16\x0E\x16\xB9\v\x16" + + "\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x05\x17\xC0\n\x17\x03\x18\x03" + + "\x18\x03\x18\x05\x18\xC5\n\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x19" + + "\x03\x19\x05\x19\xCD\n\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03" + + "\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03" + + "\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1D\x03\x1D\x03" + + "\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x05" + + "\x1F\xEF\n\x1F\x03\x1F\x05\x1F\xF2\n\x1F\x03\x1F\x03\x1F\x03 \x03 \x05" + + " \xF8\n \x03 \x03 \x03!\x03!\x03!\x07!\xFF\n!\f!\x0E!\u0102\v!\x05!\u0104" + + "\n!\x03\"\x03\"\x03\"\x03\"\x03\"\x03\"\x03\"\x05\"\u010D\n\"\x03\"\x03" + + "\"\x03\"\x03\"\x07\"\u0113\n\"\f\"\x0E\"\u0116\v\"\x03#\x03#\x03#\x03" + + "#\x03$\x03$\x03$\x03%\x03%\x03%\x03%\x03%\x03&\x03&\x03\'\x03\'\x03(\x03" + + "(\x03(\x02\x02\x03B)\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02" + + "\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02" + + "\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02" + + ">\x02@\x02B\x02D\x02F\x02H\x02J\x02L\x02N\x02\x02\b\x03\x02\x07\b\x03" + + "\x02\x04\x06\x04\x02\n\f..\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02\x1D#" + + "%&\x02\u011C\x02P\x03\x02\x02\x02\x04S\x03\x02\x02\x02\x06d\x03\x02\x02" + + "\x02\bf\x03\x02\x02\x02\nj\x03\x02\x02\x02\fs\x03\x02\x02\x02\x0Eu\x03" + + "\x02\x02\x02\x10x\x03\x02\x02\x02\x12z\x03\x02\x02\x02\x14\x81\x03\x02" + + "\x02\x02\x16\x85\x03\x02\x02\x02\x18\x87\x03\x02\x02\x02\x1A\x91\x03\x02" + + "\x02\x02\x1C\x93\x03\x02\x02\x02\x1E\x96\x03\x02\x02\x02 \x98\x03\x02" + + "\x02\x02\"\xA2\x03\x02\x02\x02$\xA4\x03\x02\x02\x02&\xB0\x03\x02\x02\x02" + + "(\xB2\x03\x02\x02\x02*\xB7\x03\x02\x02\x02,\xBF\x03\x02\x02\x02.\xC1\x03" + + "\x02\x02\x020\xCA\x03\x02\x02\x022\xCE\x03\x02\x02\x024\xD6\x03\x02\x02" + + "\x026\xDB\x03\x02\x02\x028\xE3\x03\x02\x02\x02:\xE7\x03\x02\x02\x02<\xF1" + + "\x03\x02\x02\x02>\xF5\x03\x02\x02\x02@\u0103\x03\x02\x02\x02B\u010C\x03" + + "\x02\x02\x02D\u0117\x03\x02\x02\x02F\u011B\x03\x02\x02\x02H\u011E\x03" + + "\x02\x02\x02J\u0123\x03\x02\x02\x02L\u0125\x03\x02\x02\x02N\u0127\x03" + + "\x02\x02\x02PQ\x05\x04\x03\x02QR\x07\x02\x02\x03R\x03\x03\x02\x02\x02" + + "ST\x07\x03\x02\x02TU\x05\x06\x04\x02UY\x07\x14\x02\x02VX\x05\b\x05\x02" + + "WV\x03\x02\x02\x02X[\x03\x02\x02\x02YW\x03\x02\x02\x02YZ\x03\x02\x02\x02" + + "Z_\x03\x02\x02\x02[Y\x03\x02\x02\x02\\^\x05\x0E\b\x02]\\\x03\x02\x02\x02" + + "^a\x03\x02\x02\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`b\x03\x02\x02\x02" + + "a_\x03\x02\x02\x02bc\x05\"\x12\x02c\x05\x03\x02\x02\x02de\x07.\x02\x02" + + "e\x07\x03\x02\x02\x02fg\t\x02\x02\x02gh\x05\n\x06\x02hi\x07\x1C\x02\x02" + + "i\t\x03\x02\x02\x02jk\x05\x18\r\x02kp\x05\f\x07\x02lm\x07\x1B\x02\x02" + + "mo\x05\f\x07\x02nl\x03\x02\x02\x02or\x03\x02\x02\x02pn\x03\x02\x02\x02" + + "pq\x03\x02\x02\x02q\v\x03\x02\x02\x02rp\x03\x02\x02\x02st\x07.\x02\x02" + + "t\r\x03\x02\x02\x02uv\x05\x10\t\x02vw\x05\x12\n\x02w\x0F\x03\x02\x02\x02" + + "xy\t\x03\x02\x02y\x11\x03\x02\x02\x02z{\x05\x16\f\x02{|\x05\x14\v\x02" + + "|}\x07\x16\x02\x02}~\x05\x1A\x0E\x02~\x7F\x07\x17\x02\x02\x7F\x80\x05" + + " \x11\x02\x80\x13\x03\x02\x02\x02\x81\x82\x07.\x02\x02\x82\x15\x03\x02" + + "\x02\x02\x83\x86\x05\x18\r\x02\x84\x86\x07\r\x02\x02\x85\x83\x03\x02\x02" + + "\x02\x85\x84\x03\x02\x02\x02\x86\x17\x03\x02\x02\x02\x87\x88\t\x04\x02" + + "\x02\x88\x19\x03\x02\x02\x02\x89\x8E\x05\x1C\x0F\x02\x8A\x8B\x07\x1B\x02" + + "\x02\x8B\x8D\x05\x1C\x0F\x02\x8C\x8A\x03\x02\x02\x02\x8D\x90\x03\x02\x02" + + "\x02\x8E\x8C\x03\x02\x02\x02\x8E\x8F\x03\x02\x02\x02\x8F\x92\x03\x02\x02" + + "\x02\x90\x8E\x03\x02\x02\x02\x91\x89\x03\x02\x02\x02\x91\x92\x03\x02\x02" + + "\x02\x92\x1B\x03\x02\x02\x02\x93\x94\x05\x18\r\x02\x94\x95\x05\x1E\x10" + + "\x02\x95\x1D\x03\x02\x02\x02\x96\x97\x07.\x02\x02\x97\x1F\x03\x02\x02" + + "\x02\x98\x9C\x07\x14\x02\x02\x99\x9B\x05$\x13\x02\x9A\x99\x03\x02\x02" + + "\x02\x9B\x9E\x03\x02\x02\x02\x9C\x9A\x03\x02\x02\x02\x9C\x9D\x03\x02\x02" + + "\x02\x9D\x9F\x03\x02\x02\x02\x9E\x9C\x03\x02\x02\x02\x9F\xA0\x05*\x16" + + "\x02\xA0\xA1\x05\"\x12\x02\xA1!\x03\x02\x02\x02\xA2\xA3\x07\x15\x02\x02" + + "\xA3#\x03\x02\x02\x02\xA4\xA5\x07\t\x02\x02\xA5\xA6\x05\x18\r\x02\xA6" + + "\xAB\x05&\x14\x02\xA7\xA8\x07\x1B\x02\x02\xA8\xAA\x05&\x14\x02\xA9\xA7" + + "\x03\x02\x02\x02\xAA\xAD\x03\x02\x02\x02\xAB\xA9\x03\x02\x02\x02\xAB\xAC" + + "\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD\xAB\x03\x02\x02\x02\xAE\xAF" + + "\x07\x1C\x02\x02\xAF%\x03\x02\x02\x02\xB0\xB1\x07.\x02\x02\xB1\'\x03\x02" + + "\x02\x02\xB2\xB3\x07.\x02\x02\xB3)\x03\x02\x02\x02\xB4\xB6\x05,\x17\x02" + + "\xB5\xB4\x03\x02\x02\x02\xB6\xB9\x03\x02\x02\x02\xB7\xB5\x03\x02\x02\x02" + + "\xB7\xB8\x03\x02\x02\x02\xB8+\x03\x02\x02\x02\xB9\xB7\x03\x02\x02\x02" + + "\xBA\xC0\x05.\x18\x02\xBB\xC0\x050\x19\x02\xBC\xC0\x056\x1C\x02\xBD\xC0" + + "\x058\x1D\x02\xBE\xC0\x05> \x02\xBF\xBA\x03\x02\x02\x02\xBF\xBB\x03\x02" + + "\x02\x02\xBF\xBC\x03\x02\x02\x02\xBF\xBD\x03\x02\x02\x02\xBF\xBE\x03\x02" + + "\x02\x02\xC0-\x03\x02\x02\x02\xC1\xC4\x07\x0E\x02\x02\xC2\xC5\x05(\x15" + + "\x02\xC3\xC5\x05H%\x02\xC4\xC2\x03\x02\x02\x02\xC4\xC3\x03\x02\x02\x02" + + "\xC5\xC6\x03\x02\x02\x02\xC6\xC7\x07\x1D\x02\x02\xC7\xC8\x05B\"\x02\xC8" + + "\xC9\x07\x1C\x02\x02\xC9/\x03\x02\x02\x02\xCA\xCC\x052\x1A\x02\xCB\xCD" + + "\x054\x1B\x02\xCC\xCB\x03\x02\x02\x02\xCC\xCD\x03\x02\x02\x02\xCD1\x03" + + "\x02\x02\x02\xCE\xCF\x07\x10\x02\x02\xCF\xD0\x07\x16\x02\x02\xD0\xD1\x05" + + "B\"\x02\xD1\xD2\x07\x17\x02\x02\xD2\xD3\x07\x14\x02\x02\xD3\xD4\x05*\x16" + + "\x02\xD4\xD5\x05\"\x12\x02\xD53\x03\x02\x02\x02\xD6\xD7\x07\x11\x02\x02" + + "\xD7\xD8\x07\x14\x02\x02\xD8\xD9\x05*\x16\x02\xD9\xDA\x05\"\x12\x02\xDA" + + "5\x03\x02\x02\x02\xDB\xDC\x07\x12\x02\x02\xDC\xDD\x07\x16\x02\x02\xDD" + + "\xDE\x05B\"\x02\xDE\xDF\x07\x17\x02\x02\xDF\xE0\x07\x14\x02\x02\xE0\xE1" + + "\x05*\x16\x02\xE1\xE2\x05\"\x12\x02\xE27\x03\x02\x02\x02\xE3\xE4\x07\x0F" + + "\x02\x02\xE4\xE5\x05:\x1E\x02\xE5\xE6\x07\x1C\x02\x02\xE69\x03\x02\x02" + + "\x02\xE7\xE8\x05<\x1F\x02\xE8\xE9\x07\x16\x02\x02\xE9\xEA\x05@!\x02\xEA" + + "\xEB\x07\x17\x02\x02\xEB;\x03\x02\x02\x02\xEC\xEF\x05\x06\x04\x02\xED" + + "\xEF\x07-\x02\x02\xEE\xEC\x03\x02\x02\x02\xEE\xED\x03\x02\x02\x02\xEF" + + "\xF0\x03\x02\x02\x02\xF0\xF2\x07\x1A\x02\x02\xF1\xEE\x03\x02\x02\x02\xF1" + + "\xF2\x03\x02\x02\x02\xF2\xF3\x03\x02\x02\x02\xF3\xF4\x05\x14\v\x02\xF4" + + "=\x03\x02\x02\x02\xF5\xF7\x07\x13\x02\x02\xF6\xF8\x05B\"\x02\xF7\xF6\x03" + + "\x02\x02\x02\xF7\xF8\x03\x02\x02\x02\xF8\xF9\x03\x02\x02\x02\xF9\xFA\x07" + + "\x1C\x02\x02\xFA?\x03\x02\x02\x02\xFB\u0100\x05B\"\x02\xFC\xFD\x07\x1B" + + "\x02\x02\xFD\xFF\x05B\"\x02\xFE\xFC\x03\x02\x02\x02\xFF\u0102\x03\x02" + + "\x02\x02\u0100\xFE\x03\x02\x02\x02\u0100\u0101\x03\x02\x02\x02\u0101\u0104" + + "\x03\x02\x02\x02\u0102\u0100\x03\x02\x02\x02\u0103\xFB\x03\x02\x02\x02" + + "\u0103\u0104\x03\x02\x02\x02\u0104A\x03\x02\x02\x02\u0105\u0106\b\"\x01" + + "\x02\u0106\u010D\x05J&\x02\u0107\u010D\x05(\x15\x02\u0108\u010D\x05:\x1E" + + "\x02\u0109\u010D\x05H%\x02\u010A\u010D\x05F$\x02\u010B\u010D\x05D#\x02" + + "\u010C\u0105\x03\x02\x02\x02\u010C\u0107\x03\x02\x02\x02\u010C\u0108\x03" + + "\x02\x02\x02\u010C\u0109\x03\x02\x02\x02\u010C\u010A\x03\x02\x02\x02\u010C" + + "\u010B\x03\x02\x02\x02\u010D\u0114\x03\x02\x02\x02\u010E\u010F\f\t\x02" + + "\x02\u010F\u0110\x05N(\x02\u0110\u0111\x05B\"\n\u0111\u0113\x03\x02\x02" + + "\x02\u0112\u010E\x03\x02\x02\x02\u0113\u0116\x03\x02\x02\x02\u0114\u0112" + + "\x03\x02\x02\x02\u0114\u0115\x03\x02\x02\x02\u0115C\x03\x02\x02\x02\u0116" + + "\u0114\x03\x02\x02\x02\u0117\u0118\x07\x16\x02\x02\u0118\u0119\x05B\"" + + "\x02\u0119\u011A\x07\x17\x02\x02\u011AE\x03\x02\x02\x02\u011B\u011C\x05" + + "L\'\x02\u011C\u011D\x05B\"\x02\u011DG\x03\x02\x02\x02\u011E\u011F\x05" + + "(\x15\x02\u011F\u0120\x07\x18\x02\x02\u0120\u0121\x05B\"\x02\u0121\u0122" + + "\x07\x19\x02\x02\u0122I\x03\x02\x02\x02\u0123\u0124\t\x05\x02\x02\u0124" + + "K\x03\x02\x02\x02\u0125\u0126\t\x06\x02\x02\u0126M\x03\x02\x02\x02\u0127" + + "\u0128\t\x07\x02\x02\u0128O\x03\x02\x02\x02\x15Y_p\x85\x8E\x91\x9C\xAB" + + "\xB7\xBF\xC4\xCC\xEE\xF1\xF7\u0100\u0103\u010C\u0114"; public static __ATN: ATN; public static get _ATN(): ATN { if (!JackParser.__ATN) { @@ -1819,7 +1847,9 @@ export class ClassDeclarationContext extends ParserRuleContext { return this.getRuleContext(0, ClassNameContext); } public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } - public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext); + } public classVarDec(): ClassVarDecContext[]; public classVarDec(i: number): ClassVarDecContext; public classVarDec(i?: number): ClassVarDecContext | ClassVarDecContext[] { @@ -2334,7 +2364,9 @@ export class SubroutineBodyContext extends ParserRuleContext { public statements(): StatementsContext { return this.getRuleContext(0, StatementsContext); } - public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext); + } public varDeclaration(): VarDeclarationContext[]; public varDeclaration(i: number): VarDeclarationContext; public varDeclaration(i?: number): VarDeclarationContext | VarDeclarationContext[] { @@ -2372,6 +2404,36 @@ export class SubroutineBodyContext extends ParserRuleContext { } +export class RBraceContext extends ParserRuleContext { + public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + constructor(parent: ParserRuleContext | undefined, invokingState: number) { + super(parent, invokingState); + } + // @Override + public override get ruleIndex(): number { return JackParser.RULE_rBrace; } + // @Override + public override enterRule(listener: JackParserListener): void { + if (listener.enterRBrace) { + listener.enterRBrace(this); + } + } + // @Override + public override exitRule(listener: JackParserListener): void { + if (listener.exitRBrace) { + listener.exitRBrace(this); + } + } + // @Override + public override accept(visitor: JackParserVisitor): Result { + if (visitor.visitRBrace) { + return visitor.visitRBrace(this); + } else { + return visitor.visitChildren(this); + } + } +} + + export class VarDeclarationContext extends ParserRuleContext { public VAR(): TerminalNode { return this.getToken(JackParser.VAR, 0); } public varType(): VarTypeContext { @@ -2653,7 +2715,9 @@ export class IfStatementContext extends ParserRuleContext { public statements(): StatementsContext { return this.getRuleContext(0, StatementsContext); } - public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -2688,7 +2752,9 @@ export class ElseStatementContext extends ParserRuleContext { public statements(): StatementsContext { return this.getRuleContext(0, StatementsContext); } - public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } @@ -2728,7 +2794,9 @@ export class WhileStatementContext extends ParserRuleContext { public statements(): StatementsContext { return this.getRuleContext(0, StatementsContext); } - public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext); + } constructor(parent: ParserRuleContext | undefined, invokingState: number) { super(parent, invokingState); } diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts index 6cd2e47d..50b45295 100644 --- a/compiler/src/generated/JackParserListener.ts +++ b/compiler/src/generated/JackParserListener.ts @@ -19,6 +19,7 @@ import { ParameterListContext } from "./JackParser"; import { ParameterContext } from "./JackParser"; import { ParameterNameContext } from "./JackParser"; import { SubroutineBodyContext } from "./JackParser"; +import { RBraceContext } from "./JackParser"; import { VarDeclarationContext } from "./JackParser"; import { VarNameInDeclarationContext } from "./JackParser"; import { VarNameContext } from "./JackParser"; @@ -224,6 +225,17 @@ export interface JackParserListener extends ParseTreeListener { */ exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Enter a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + enterRBrace?: (ctx: RBraceContext) => void; + /** + * Exit a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + exitRBrace?: (ctx: RBraceContext) => void; + /** * Enter a parse tree produced by `JackParser.varDeclaration`. * @param ctx the parse tree diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts index 2711d29e..0dc85abc 100644 --- a/compiler/src/generated/JackParserVisitor.ts +++ b/compiler/src/generated/JackParserVisitor.ts @@ -19,6 +19,7 @@ import { ParameterListContext } from "./JackParser"; import { ParameterContext } from "./JackParser"; import { ParameterNameContext } from "./JackParser"; import { SubroutineBodyContext } from "./JackParser"; +import { RBraceContext } from "./JackParser"; import { VarDeclarationContext } from "./JackParser"; import { VarNameInDeclarationContext } from "./JackParser"; import { VarNameContext } from "./JackParser"; @@ -163,6 +164,13 @@ export interface JackParserVisitor extends ParseTreeVisitor { */ visitSubroutineBody?: (ctx: SubroutineBodyContext) => Result; + /** + * Visit a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + * @return the visitor result + */ + visitRBrace?: (ctx: RBraceContext) => Result; + /** * Visit a parse tree produced by `JackParser.varDeclaration`. * @param ctx the parse tree diff --git a/compiler/src/listener/global.symbol.table.listener.ts b/compiler/src/listener/global.symbol.table.listener.ts index f684e1fb..0eeaf6a7 100644 --- a/compiler/src/listener/global.symbol.table.listener.ts +++ b/compiler/src/listener/global.symbol.table.listener.ts @@ -44,7 +44,7 @@ export class GlobalSymbolTableListener implements JackParserListener, ParseTreeL const subroutineName = nameCtx.text const id = this.className + "." + subroutineName if (this.globalSymbolTable[id] != undefined) { - this.errors.push(new DuplicatedSubroutineError(nameCtx.start.line, nameCtx.start.startIndex, `Subroutine "${subroutineName}" is already defined.`)); + this.errors.push(new DuplicatedSubroutineError(nameCtx.start.line, nameCtx.start.startIndex, subroutineName)); } const paramsCount = subroutineWithoutTypeCtx.parameterList().parameter().length this.globalSymbolTable[id] = { diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index e069f330..9ef2fef0 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,7 +1,7 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { DuplicatedVariableException, FunctionCalledAsMethodError, IncorrectParamsNumberInSubroutineCallError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, VoidSubroutineReturnsValueError } from "../error"; -import { ClassDeclarationContext, ClassNameContext, ElseStatementContext, FieldListContext, IfStatementContext, ParameterContext, ReturnStatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; +import { ConstructorMushReturnThis, DuplicatedVariableException, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError } from "../error"; +import { ClassDeclarationContext, ClassNameContext, ElseStatementContext, FieldListContext, IfStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol, LocalSymbolTable, SubroutineType } from "../symbol"; @@ -72,6 +72,8 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener cfgNode: BinaryTreeNode = new BinaryTreeNode(undefined); subroutineName: string = "" className = "" + inConstructor: boolean = false + stopProcessingErrorsInThisScope = false; constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } enterClassName(ctx: ClassNameContext) { @@ -80,9 +82,18 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterFieldList(ctx: FieldListContext) { const type = ctx.varType().text ctx.fieldName().forEach(field => { - this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, field.text, type); + this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, field.text, type); }); }; + enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { + let subroutineType: SubroutineType; + if (ctx.subroutineType().CONSTRUCTOR() != undefined) { + this.inConstructor = true; + if (ctx.subroutineDecWithoutType().subroutineReturnType().text !== this.className) { + this.#addError(new IncorrectConstructorReturnType(ctx.start.line, ctx.start.startIndex)); + } + } + } enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { this.localSymbolTable.pushStack(); const returnType = ctx.subroutineReturnType() @@ -92,14 +103,14 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; enterParameter(ctx: ParameterContext) { - this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.parameterName().text, ctx.varType().text); + this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.parameterName().text, ctx.varType().text); }; //Var enterVarType(ctx: VarTypeContext) { if (ctx.IDENTIFIER() != undefined) { const type = ctx.IDENTIFIER()!.text if (this.globalSymbolTable[type] === undefined) { - this.errors.push(new UnknownClassError(ctx.start.line, ctx.start.startIndex, type)); + this.#addError(new UnknownClassError(ctx.start.line, ctx.start.startIndex, type)); } } }; @@ -107,16 +118,25 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterVarDeclaration(ctx: VarDeclarationContext) { const type = ctx.varType().text ctx.varNameInDeclaration().forEach(name => { - this.localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, name.text, type); + this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, name.text, type); }) }; enterVarName(ctx: VarNameContext) { if (!this.localSymbolTable.existsSymbol(ctx.text)) { - this.errors.push(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); + this.#addError(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); } }; + enterStatement(ctx: StatementContext) { + if (this.cfgNode._returns == true) { + this.#addError(new UnreachableCodeError(ctx.start.line, ctx.start.startIndex)); + this.stopProcessingErrorsInThisScope = true; + } + }; + enterRBrace(ctx: RBraceContext) { + this.stopProcessingErrorsInThisScope = false; + }; /** * Control flow */ @@ -144,10 +164,10 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener if (this.cfgNode?.parent != null) { this.cfgNode = this.cfgNode.parent } + }; enterSubroutineCall(ctx: SubroutineCallContext) { //check if variable exists with the name before dot - const subroutineId = ctx.subroutineId() let callType: CallType; @@ -172,7 +192,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener const symbol = this.globalSymbolTable[subroutineIdText] if (symbol == undefined) { - this.errors.push(new UnknownSubroutineCallError(ctx.start.line, ctx.start.startIndex, + this.#addError(new UnknownSubroutineCallError(ctx.start.line, ctx.start.startIndex, subroutineId.subroutineName().text, subroutineId.className()?.text )); @@ -180,20 +200,19 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener //method called as a function if (symbol.subroutineInfo?.type == SubroutineType.Method && callType == CallType.ClassFunctionOrConstructor) { - this.errors.push(new MethodCalledAsFunctionError(ctx.start.line, ctx.start.startIndex, + this.#addError(new MethodCalledAsFunctionError(ctx.start.line, ctx.start.startIndex, subroutineId.subroutineName().text)); } // function called as a method else if (symbol.subroutineInfo?.type == SubroutineType.Function && callType == CallType.LocalMethod) { - this.errors.push(new FunctionCalledAsMethodError(ctx.start.line, ctx.start.startIndex, + this.#addError(new FunctionCalledAsMethodError(ctx.start.line, ctx.start.startIndex, subroutineId.subroutineName().text)); - } else { //check parameter count const l = ctx.expressionList().expression().length if (symbol.subroutineInfo!.paramsCount != l) { - this.errors.push(new IncorrectParamsNumberInSubroutineCallError(ctx.start.line, ctx.start.startIndex, subroutineId.text, + this.#addError(new IncorrectParamsNumberInSubroutineCallError(ctx.start.line, ctx.start.startIndex, subroutineId.text, symbol.subroutineInfo!.paramsCount, l)); } } @@ -203,18 +222,25 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterReturnStatement(ctx: ReturnStatementContext) { const returnsVoid = ctx.expression() == undefined if (returnsVoid && !this.subroutineShouldReturnVoidType) { - this.errors.push(new NonVoidFunctionNoReturnError(ctx.start.line, ctx.start.startIndex)); + this.#addError(new NonVoidFunctionNoReturnError(ctx.start.line, ctx.start.startIndex)); } if (!returnsVoid && this.subroutineShouldReturnVoidType) { - this.errors.push(new VoidSubroutineReturnsValueError(ctx.start.line, ctx.start.startIndex,)); + this.#addError(new VoidSubroutineReturnsValueError(ctx.start.line, ctx.start.startIndex)); } this.cfgNode._returns = true; + if (this.inConstructor) { + if (returnsVoid || ctx.expression()!.expression().length > 1 || + ctx.expression()!.constant() == undefined || ctx.expression()!.constant()!.THIS_LITERAL() == undefined) { + this.#addError(new ConstructorMushReturnThis(ctx.start.line, ctx.start.startIndex)) + } + } }; exitSubroutineBody(ctx: SubroutineBodyContext) { if (!this.cfgNode.returns) { - this.errors.push(new SubroutineNotAllPathsReturnError(ctx.start.line, ctx.start.startIndex, this.subroutineName)); + this.#addError(new SubroutineNotAllPathsReturnError(ctx.start.line, ctx.start.startIndex, this.subroutineName)); } + this.inConstructor = false; this.localSymbolTable.popStack(); }; @@ -225,13 +251,17 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; //Utils - localSymbolTableAdd(line: number, position: number, name: string, type: string) { + #localSymbolTableAdd(line: number, position: number, name: string, type: string) { if (this.localSymbolTable.existsSymbol(name)) { - this.errors.push(new DuplicatedVariableException(line, position, name)); + this.#addError(new DuplicatedVariableException(line, position, name)); } else { this.localSymbolTable.add(name, type); } } + #addError(error: T) { + if (!this.stopProcessingErrorsInThisScope) + this.errors.push(error); + } //to fix compiler error visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index 467fa8fd..b3e6e514 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -1,12 +1,9 @@ -import { ParseTreeWalker } from 'antlr4ts/tree/ParseTreeWalker'; import fs from 'fs'; import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.listener"; import path from "path"; import { ErrorListener } from "../src/listener/error.listener"; -import { getTestResourcePath, listenToTheTree, parseJackText, handleErrors, parseJackFile } from "./test.helper"; -import { ProgramContext } from '../src/generated/JackParser'; -import { JackCompilerError } from '../src/error'; +import { listenToTheTree, parseJackFile, parseJackText } from "./test.helper"; describe('Parser', () => { const jestConsole = console; @@ -33,6 +30,24 @@ describe('Parser', () => { console.log("Testing " + dir) testJackDir(path.join(__dirname, "resources", dir)); }); + test('expected EOF', () => { + try { + parseJackText(` + class A{ + } + var a; + `) + } catch (e) { + if (e instanceof Error) { + expect(e.message).toContain("expecting ") + return; + } else { + fail("Expected Error"); + } + } + fail('Expected Error'); + }) + }); function testJackDir(testFolder: string): void { diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index 45ce59df..aa2b62b0 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,11 +1,11 @@ import { ParserRuleContext } from "antlr4ts" -import { DuplicatedVariableException as DuplicatedVariableError, FunctionCalledAsMethodError, IncorrectParamsNumberInSubroutineCallError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, VoidSubroutineReturnsValueError } from "../src/error" +import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" import { ProgramContext } from "../src/generated/JackParser" import { Logger, ILogObj } from "tslog"; -import { GenericSymbol, SubroutineInfo, SubroutineType } from "../src/symbol" +import { createSubroutineSymbol, GenericSymbol, SubroutineInfo, SubroutineType } from "../src/symbol" const log: Logger = new Logger(); describe('ValidatorListener', () => { @@ -19,10 +19,9 @@ describe('ValidatorListener', () => { global.console = jestConsole; }); - //TODO: refactor to use createFunctionSymbol function genericSymbol(type?: SubroutineType, paramsCount?: number): GenericSymbol { if (type != undefined && paramsCount != undefined) { - return { subroutineInfo: { type, paramsCount } } as GenericSymbol + return createSubroutineSymbol(paramsCount, type) } else { return {} as GenericSymbol } @@ -432,12 +431,58 @@ describe('ValidatorListener', () => { "Main.c": genericSymbol(SubroutineType.Function, 0) }) }) - + test('incorrect return type in constructor', () => { + testValidator(` + class Main { + constructor D new(){ + return this; + } + }`, IncorrectConstructorReturnType, + { + "Main": genericSymbol(), + "D": genericSymbol(), + }) + }); + test('unreachable code', () => { + testValidator(` + class Main { + constructor Main new(){ + return this; + let a=0; + let a=0; + let a=0; + } + }`, UnreachableCodeError, + { + "Main": genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + }) + }); + test("A constructor must return 'this'", () => { + testValidator(` + class Main { + constructor Main new(){ + return 1; + } + }`, ConstructorMushReturnThis, + { + "Main": genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + }) + }) /** - * List of validations rules: - * - `Method ${className}.${subroutineName} was called as a function/constructor` - * - Subroutine was called as a method - * - `Class ${className} doesn't contain a function/constructor ${subroutineName}` + * - An empty statement is not allowed - what is this? + * + * - Expected class name, subroutine name, field, parameter or local or static variable name (currently expected IDENTIFIER) + * - Expected subroutine name in call + * - A constructor must return 'this' + * - Let statement - expected literal based on var type - boolean, char, int (String?) + * - Integer constant too big >32767 + * - a numeric value is illegal here + * - this' can't be referenced in a function + * - Illegal casting into String constant + * - A field may not be referenced in a function + * - Expected primitive type or class name */ }) From 1511c9470354fc651b0dba5c81eda02e786d630a Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sat, 28 Sep 2024 21:44:49 +0200 Subject: [PATCH 19/87] Add int out of range validation --- compiler/src/builtins.ts | 5 ++ compiler/src/error.ts | 16 +++++ compiler/src/listener/validator.listener.ts | 60 +++++++++++++++- compiler/test/validator.listener.test.ts | 77 +++++++++++++++++++-- 4 files changed, 152 insertions(+), 6 deletions(-) diff --git a/compiler/src/builtins.ts b/compiler/src/builtins.ts index 1c364919..02fe137c 100644 --- a/compiler/src/builtins.ts +++ b/compiler/src/builtins.ts @@ -1,6 +1,11 @@ import { GenericSymbol, SubroutineType } from "./symbol"; export const builtInTypes = ["int", "boolean", "char"] +interface Range { + min: number; + max: number; +} +export const intRange = { min: -32768, max: 32767 } as Range; //TODO: should we convert this to symbols? const builtInFunctionsToArgCount: Record = { diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 019c52ae..67142ede 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -138,3 +138,19 @@ export class ConstructorMushReturnThis extends JackCompilerError { Object.setPrototypeOf(this, ConstructorMushReturnThis.prototype); } } + +const vowels = "aeiou" +export class WrongLiteralTypeError extends JackCompilerError { + constructor(line: number, charPositionInLine: number, typeName: string) { + const article = vowels.indexOf(typeName.substring(0, 1)) != -1 ? "an" : "a"; + super(line, charPositionInLine, `${article} ${typeName} value is expected`); + Object.setPrototypeOf(this, WrongLiteralTypeError.prototype); + } +} + +export class IntLiteralIsOutOfRange extends JackCompilerError { + constructor(line: number, charPositionInLine: number, value: number, min: number, max: number) { + super(line, charPositionInLine, `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}`); + Object.setPrototypeOf(this, IntLiteralIsOutOfRange.prototype); + } +} diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 9ef2fef0..f6f4d230 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,9 +1,10 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ConstructorMushReturnThis, DuplicatedVariableException, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError } from "../error"; -import { ClassDeclarationContext, ClassNameContext, ElseStatementContext, FieldListContext, IfStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; +import { ConstructorMushReturnThis, DuplicatedVariableException, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error"; +import { ClassDeclarationContext, ClassNameContext, ElseStatementContext, FieldListContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol, LocalSymbolTable, SubroutineType } from "../symbol"; +import { builtInTypes, intRange } from "../builtins"; class BinaryTreeNode { _returns?: boolean; @@ -64,6 +65,11 @@ enum Side { RIGHT } +const literalTypes = [ + ...builtInTypes, + "String" +] + export class ValidatorListener implements JackParserListener, ParseTreeListener { //why do we need local symbol table? this vars, arguments, local vars. What about types? @@ -166,6 +172,56 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener } }; + enterLetStatement(ctx: LetStatementContext) { + const varName = ctx.varName() + const constCtx = ctx.expression().constant() + //corresponding literal type check + if (varName != undefined && constCtx != undefined && + this.localSymbolTable.existsSymbol(ctx.varName()!.text) && + ctx.expression().constant()!.NULL_LITERAL() == undefined) { + const type = this.localSymbolTable.getType(ctx.varName()!.text)! + if (literalTypes.indexOf(type) != -1) { + const constantCtx = ctx.expression().constant()! + switch (type) { + case "int": + if (constantCtx.INTEGER_LITERAL() === undefined) { + this.#addError(new WrongLiteralTypeError(ctx.start.line, ctx.start.startIndex, type)); + } else { + const value = parseInt(constantCtx.INTEGER_LITERAL()!.text) + if (value > intRange.max) { + this.#addError(new IntLiteralIsOutOfRange(ctx.start.line, ctx.start.startIndex, value, intRange.min, intRange.max)) + } + } + break; + case "boolean": + if (constantCtx.BOOLEAN_LITERAL() === undefined) { + this.#addError(new WrongLiteralTypeError(ctx.start.line, ctx.start.startIndex, type)); + } + break; + case "char": + //TODO: add. Is char literal same as int literal? + break; + case "String": + if (constantCtx.STRING_LITERAL() === undefined) { + this.#addError(new WrongLiteralTypeError(ctx.start.line, ctx.start.startIndex, type.toLowerCase())); + } + break; + default: + throw new Error(`Unknown literal type ${type}`) + } + } + } + //int min value check + const unaryOp = ctx.expression().unaryOp() + if (varName && unaryOp != undefined && unaryOp.unaryOperator().MINUS() !== undefined && + unaryOp!.expression().constant() != undefined && unaryOp!.expression().constant()?.INTEGER_LITERAL() !== undefined) { + const value = parseInt(unaryOp!.expression().constant()!.INTEGER_LITERAL()!.text) + if (-value < intRange.min) { + this.#addError(new IntLiteralIsOutOfRange(ctx.start.line, ctx.start.startIndex, value, intRange.min, intRange.max)); + } + } + }; + enterSubroutineCall(ctx: SubroutineCallContext) { //check if variable exists with the name before dot const subroutineId = ctx.subroutineId() diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index aa2b62b0..235f20e8 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,5 +1,5 @@ import { ParserRuleContext } from "antlr4ts" -import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError } from "../src/error" +import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange as IntLiteralOverflow, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" @@ -470,14 +470,83 @@ describe('ValidatorListener', () => { "Main.new": genericSymbol(SubroutineType.Constructor, 0), }) }) + test("Let statement - expected string literal ", () => { + testValidator(` + class Main { + function void a(){ + var String foo; + let foo = 1; + return; + } + }`, WrongLiteralTypeError, + { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + "String": genericSymbol(), + }) + }) + test("Let statement - expected boolean literal ", () => { + testValidator(` + class Main { + function void a(){ + var boolean foo; + let foo = 1; + return; + } + }`, WrongLiteralTypeError, + { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }) + }) + + test("Let statement - expected int literal ", () => { + testValidator(` + class Main { + function void a(){ + var int foo; + let foo = "asb"; + return; + } + }`, WrongLiteralTypeError, + { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }) + }) + test("integer constant value is too big", () => { + testValidator(` + class Main { + function void a(){ + var int foo; + let foo = 33000; + return; + } + }`, IntLiteralOverflow, + { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }) + }) + test("integer constant value is too small", () => { + testValidator(` + class Main { + function void a(){ + var int foo; + let foo = -33000; + return; + } + }`, IntLiteralOverflow, + { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }) + }) /** * - An empty statement is not allowed - what is this? * * - Expected class name, subroutine name, field, parameter or local or static variable name (currently expected IDENTIFIER) * - Expected subroutine name in call - * - A constructor must return 'this' - * - Let statement - expected literal based on var type - boolean, char, int (String?) - * - Integer constant too big >32767 * - a numeric value is illegal here * - this' can't be referenced in a function * - Illegal casting into String constant From c40bfdd161b1708efe0182c232b6ddbca528965d Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sat, 28 Sep 2024 23:42:18 +0200 Subject: [PATCH 20/87] Add field cant be referenced in a function validation --- compiler/src/error.ts | 8 ++++ compiler/src/listener/validator.listener.ts | 44 ++++++++++++++------- compiler/src/symbol.ts | 43 +++++++++++--------- compiler/test/local.symbol.table.test.ts | 11 +++--- compiler/test/validator.listener.test.ts | 31 ++++++++++++++- 5 files changed, 97 insertions(+), 40 deletions(-) diff --git a/compiler/src/error.ts b/compiler/src/error.ts index 67142ede..eb5fcf71 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -154,3 +154,11 @@ export class IntLiteralIsOutOfRange extends JackCompilerError { Object.setPrototypeOf(this, IntLiteralIsOutOfRange.prototype); } } + + +export class FieldCantBeReferencedInFunction extends JackCompilerError { + constructor(line: number, charPositionInLine: number) { + super(line, charPositionInLine, `Field can't be referenced in a function`); + Object.setPrototypeOf(this, FieldCantBeReferencedInFunction.prototype); + } +} diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index f6f4d230..f0457d8b 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,9 +1,9 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ConstructorMushReturnThis, DuplicatedVariableException, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error"; -import { ClassDeclarationContext, ClassNameContext, ElseStatementContext, FieldListContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; +import { ConstructorMushReturnThis, DuplicatedVariableException, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error"; +import { ClassDeclarationContext, ClassNameContext, ClassVarDecContext, ElseStatementContext, FieldListContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; -import { GenericSymbol, LocalSymbolTable, SubroutineType } from "../symbol"; +import { GenericSymbol, LocalSymbolTable, ScopeType, SubroutineType } from "../symbol"; import { builtInTypes, intRange } from "../builtins"; class BinaryTreeNode { @@ -79,16 +79,25 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener subroutineName: string = "" className = "" inConstructor: boolean = false + inFunction: boolean = false stopProcessingErrorsInThisScope = false; constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } enterClassName(ctx: ClassNameContext) { this.className = ctx.IDENTIFIER().text }; - enterFieldList(ctx: FieldListContext) { - const type = ctx.varType().text - ctx.fieldName().forEach(field => { - this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, field.text, type); + enterClassVarDec(ctx: ClassVarDecContext) { + let scope: ScopeType; + if (ctx.STATIC() != undefined) { + scope = ScopeType.StaticField; + } else if (ctx.FIELD() != undefined) { + scope = ScopeType.Field; + } else { + throw new Error("Unknown field modifier ") + } + const type = ctx.fieldList().varType().text + ctx.fieldList().fieldName().forEach(field => { + this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, scope, field.text, type); }); }; enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { @@ -98,10 +107,11 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener if (ctx.subroutineDecWithoutType().subroutineReturnType().text !== this.className) { this.#addError(new IncorrectConstructorReturnType(ctx.start.line, ctx.start.startIndex)); } + } else if (ctx.subroutineType().FUNCTION() != undefined) { + this.inFunction = true; } } enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { - this.localSymbolTable.pushStack(); const returnType = ctx.subroutineReturnType() this.subroutineShouldReturnVoidType = returnType.VOID() != undefined this.cfgNode = new BinaryTreeNode(undefined); @@ -109,7 +119,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; enterParameter(ctx: ParameterContext) { - this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ctx.parameterName().text, ctx.varType().text); + this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ScopeType.Argument, ctx.parameterName().text, ctx.varType().text); }; //Var enterVarType(ctx: VarTypeContext) { @@ -124,12 +134,17 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterVarDeclaration(ctx: VarDeclarationContext) { const type = ctx.varType().text ctx.varNameInDeclaration().forEach(name => { - this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, name.text, type); + this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ScopeType.Local, name.text, type); }) }; + /** + * Var name when using it - do Statement, let ... as oposed to varNameInDeclaration + */ enterVarName(ctx: VarNameContext) { - if (!this.localSymbolTable.existsSymbol(ctx.text)) { + if (this.inFunction && this.localSymbolTable.existsSymbol(ctx.text) && !this.localSymbolTable.existsSymbol(ctx.text, LocalSymbolTable.functionScopes)) { + this.#addError(new FieldCantBeReferencedInFunction(ctx.start.line, ctx.start.startIndex)); + } else if (!this.localSymbolTable.existsSymbol(ctx.text)) { this.#addError(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); } }; @@ -297,7 +312,8 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener this.#addError(new SubroutineNotAllPathsReturnError(ctx.start.line, ctx.start.startIndex, this.subroutineName)); } this.inConstructor = false; - this.localSymbolTable.popStack(); + this.inFunction = false; + this.localSymbolTable.clearSubroutineVars(); }; exitClassDeclaration(ctx: ClassDeclarationContext) { @@ -307,11 +323,11 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; //Utils - #localSymbolTableAdd(line: number, position: number, name: string, type: string) { + #localSymbolTableAdd(line: number, position: number, scope: ScopeType, name: string, type: string) { if (this.localSymbolTable.existsSymbol(name)) { this.#addError(new DuplicatedVariableException(line, position, name)); } else { - this.localSymbolTable.add(name, type); + this.localSymbolTable.add(scope, name, type); } } #addError(error: T) { diff --git a/compiler/src/symbol.ts b/compiler/src/symbol.ts index cb80f095..6d0a2652 100644 --- a/compiler/src/symbol.ts +++ b/compiler/src/symbol.ts @@ -18,35 +18,42 @@ export function createSubroutineSymbol(paramsCount: number, type: SubroutineType } type VariableType = string - +export enum ScopeType { + StaticField, + Field, + Argument, + Local, +} export class LocalSymbolTable { - constructor(private scopeVarDecs: Record[] = [{}]) { + private vars: Record> = { + [ScopeType.StaticField]: {}, + [ScopeType.Field]: {}, + [ScopeType.Argument]: {}, + [ScopeType.Local]: {}, + }; + static readonly functionScopes = [ScopeType.Local, ScopeType.Argument, ScopeType.StaticField]; - } - existsSymbol(name: string): boolean { - for (let i = this.scopeVarDecs.length - 1; i >= 0; i--) { - if (this.scopeVarDecs[i][name] != undefined) { + existsSymbol(name: string, scopesToSearch = [ScopeType.Local, ScopeType.Argument, ScopeType.Field, ScopeType.StaticField]): boolean { + for (const scope of scopesToSearch) { + if (this.vars[scope][name] != undefined) { return true; } } return false; } - getType(name: string) { - for (let i = this.scopeVarDecs.length - 1; i >= 0; i--) { - if (this.scopeVarDecs[i][name] != undefined) { - return this.scopeVarDecs[i][name]; + getType(name: string, scopesToSearch = [ScopeType.Local, ScopeType.Argument, ScopeType.Field, ScopeType.StaticField]) { + for (const scope of scopesToSearch) { + if (this.vars[scope][name] != undefined) { + return this.vars[scope][name]; } } return undefined; } - add(varName: string, type: VariableType) { - this.scopeVarDecs[this.scopeVarDecs.length - 1][varName] = type; + add(scope: ScopeType, varName: string, type: VariableType) { + this.vars[scope][varName] = type; } - pushStack() { - this.scopeVarDecs.push({}); + clearSubroutineVars() { + this.vars[ScopeType.Argument] = {}; + this.vars[ScopeType.Local] = {}; } - popStack() { - this.scopeVarDecs.pop(); - } - } \ No newline at end of file diff --git a/compiler/test/local.symbol.table.test.ts b/compiler/test/local.symbol.table.test.ts index b9ec250e..b939e0b1 100644 --- a/compiler/test/local.symbol.table.test.ts +++ b/compiler/test/local.symbol.table.test.ts @@ -1,4 +1,4 @@ -import { LocalSymbolTable } from "../src/symbol"; +import { LocalSymbolTable, ScopeType } from "../src/symbol"; describe('LocalSymbolTable', () => { const jestConsole = console; @@ -17,7 +17,7 @@ describe('LocalSymbolTable', () => { const variableNames = ['testVariable1', 'testVariable2', 'testVariable3']; variableNames.forEach(variableName => { - localSymbolTable.add(variableName, "int") + localSymbolTable.add(ScopeType.Local, variableName, "int") expect(localSymbolTable.existsSymbol(variableName)).toBe(true); expect(localSymbolTable.existsSymbol(variableName + "_")).toBe(false); @@ -29,16 +29,15 @@ describe('LocalSymbolTable', () => { const classVar = 'a'; const functionVar = 'b'; - localSymbolTable.add(classVar, "boolean"); + localSymbolTable.add(ScopeType.Field, classVar, "boolean"); - localSymbolTable.pushStack(); - localSymbolTable.add(functionVar, "boolean"); + localSymbolTable.add(ScopeType.Local, functionVar, "boolean"); expect(localSymbolTable.existsSymbol(classVar)).toBe(true); expect(localSymbolTable.existsSymbol(functionVar)).toBe(true); - localSymbolTable.popStack(); + localSymbolTable.clearSubroutineVars(); expect(localSymbolTable.existsSymbol(classVar)).toBe(true); expect(localSymbolTable.existsSymbol(functionVar)).toBe(false); diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index 235f20e8..df0c827c 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,5 +1,5 @@ import { ParserRuleContext } from "antlr4ts" -import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange as IntLiteralOverflow, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../src/error" +import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange as IntLiteralOverflow, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" @@ -542,6 +542,34 @@ describe('ValidatorListener', () => { "Main.a": genericSymbol(SubroutineType.Function, 0), }) }) + test("A field can not be referenced in a function", () => { + testValidator(` + class Main { + field int a; + function void a(){ + let a = 1; + return; + } + }`, FieldCantBeReferencedInFunction, + { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }) + }) + test("A static field can be referenced in a function", () => { + testValidator(` + class Main { + static int a; + function void a(){ + let a = 1; + return; + } + }`, undefined, + { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }) + }) /** * - An empty statement is not allowed - what is this? * @@ -551,7 +579,6 @@ describe('ValidatorListener', () => { * - this' can't be referenced in a function * - Illegal casting into String constant * - A field may not be referenced in a function - * - Expected primitive type or class name */ }) From 32b91f7e1cf259eaca13c76b56e79569d676b0ad Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 29 Sep 2024 00:14:42 +0200 Subject: [PATCH 21/87] this can't be referenced in a function validation --- compiler/parser-gen/JackParser.g4 | 2 +- compiler/src/error.ts | 7 ++++++ compiler/src/listener/validator.listener.ts | 9 +++++-- compiler/test/validator.listener.test.ts | 27 +++++++++++++++------ 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/parser-gen/JackParser.g4 index cc70c142..c3d3bcd1 100644 --- a/compiler/parser-gen/JackParser.g4 +++ b/compiler/parser-gen/JackParser.g4 @@ -39,7 +39,7 @@ statement: | returnStatement; letStatement: - LET (varName | arrayAccess) EQUALS expression SEMICOLON; //TODO: check right assoc for this + LET (varName | arrayAccess) EQUALS expression SEMICOLON; //TODO: check if we need right assoc for this ifElseStatement: ifStatement elseStatement?; ifStatement: diff --git a/compiler/src/error.ts b/compiler/src/error.ts index eb5fcf71..bc71eff0 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -162,3 +162,10 @@ export class FieldCantBeReferencedInFunction extends JackCompilerError { Object.setPrototypeOf(this, FieldCantBeReferencedInFunction.prototype); } } + +export class ThisCantBeReferencedInFunction extends JackCompilerError { + constructor(line: number, charPositionInLine: number) { + super(line, charPositionInLine, `this can't be referenced in a function`); + Object.setPrototypeOf(this, ThisCantBeReferencedInFunction.prototype); + } +} diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index f0457d8b..736951e5 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,7 +1,7 @@ import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ConstructorMushReturnThis, DuplicatedVariableException, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error"; -import { ClassDeclarationContext, ClassNameContext, ClassVarDecContext, ElseStatementContext, FieldListContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; +import { ConstructorMushReturnThis, DuplicatedVariableException, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunction, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error"; +import { ClassDeclarationContext, ClassNameContext, ClassVarDecContext, ConstantContext, ElseStatementContext, FieldListContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol, LocalSymbolTable, ScopeType, SubroutineType } from "../symbol"; import { builtInTypes, intRange } from "../builtins"; @@ -148,6 +148,11 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener this.#addError(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); } }; + enterConstant(ctx: ConstantContext) { + if (ctx.THIS_LITERAL() != undefined && this.inFunction) { + this.#addError(new ThisCantBeReferencedInFunction(ctx.start.line, ctx.start.startIndex)); + } + }; enterStatement(ctx: StatementContext) { if (this.cfgNode._returns == true) { diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index df0c827c..efc60159 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,11 +1,9 @@ -import { ParserRuleContext } from "antlr4ts" -import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange as IntLiteralOverflow, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../src/error" +import { ILogObj, Logger } from "tslog" +import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange as IntLiteralOverflow, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunction, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { ValidatorListener } from "../src/listener/validator.listener" -import { handleErrors, listenToTheTree, parseJackText } from "./test.helper" -import { ProgramContext } from "../src/generated/JackParser" -import { Logger, ILogObj } from "tslog"; -import { createSubroutineSymbol, GenericSymbol, SubroutineInfo, SubroutineType } from "../src/symbol" +import { createSubroutineSymbol, GenericSymbol, SubroutineType } from "../src/symbol" +import { listenToTheTree, parseJackText } from "./test.helper" const log: Logger = new Logger(); describe('ValidatorListener', () => { @@ -570,9 +568,22 @@ describe('ValidatorListener', () => { "Main.a": genericSymbol(SubroutineType.Function, 0), }) }) + test("this can't be referenced in a function", () => { + testValidator(` + class Main { + function void a(){ + var Main m; + let m = this; + return; + } + }`, ThisCantBeReferencedInFunction, + { + "Main": genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }) + }) /** - * - An empty statement is not allowed - what is this? - * + * Errors from old java compiler - * - Expected class name, subroutine name, field, parameter or local or static variable name (currently expected IDENTIFIER) * - Expected subroutine name in call * - a numeric value is illegal here From d6128160b75f8fdcaaefed7ab43653a20612fd91 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 29 Sep 2024 10:13:00 +0200 Subject: [PATCH 22/87] Fix bug in validation --- compiler/TODO.md | 3 + compiler/gen.sh | 2 +- compiler/grammar/.antlr/JackLexer.interp | 155 ++ compiler/grammar/.antlr/JackLexer.java | 321 +++ compiler/grammar/.antlr/JackLexer.tokens | 84 + compiler/grammar/.antlr/JackParser.interp | 142 ++ compiler/grammar/.antlr/JackParser.java | 2239 +++++++++++++++++ compiler/grammar/.antlr/JackParser.tokens | 84 + compiler/{parser-gen => grammar}/JackLexer.g4 | 0 .../{parser-gen => grammar}/JackParser.g4 | 0 compiler/package.json | 2 +- compiler/parser-gen/Main.jack | 78 - compiler/parser-gen/Makefile | 10 - compiler/parser-gen/jack.ohm | 78 - compiler/src/VIsitor.ts | 55 - compiler/src/builtins.ts | 8 +- compiler/src/compiler.ts | 8 +- compiler/src/error.ts | 3 +- compiler/src/listener/error.listener.ts | 1 - .../listener/global.symbol.table.listener.ts | 11 +- compiler/src/listener/validator.listener.ts | 189 +- compiler/src/symbol.table.istener.ts | 0 compiler/src/symbol.ts | 26 +- .../test/global.symbol.table.listener.test.ts | 8 + compiler/test/local.symbol.table.test.ts | 4 +- compiler/test/parser.test.ts | 16 +- compiler/test/test.helper.ts | 13 +- compiler/test/validator.listener.test.ts | 58 +- 28 files changed, 3228 insertions(+), 370 deletions(-) create mode 100644 compiler/TODO.md create mode 100644 compiler/grammar/.antlr/JackLexer.interp create mode 100644 compiler/grammar/.antlr/JackLexer.java create mode 100644 compiler/grammar/.antlr/JackLexer.tokens create mode 100644 compiler/grammar/.antlr/JackParser.interp create mode 100644 compiler/grammar/.antlr/JackParser.java create mode 100644 compiler/grammar/.antlr/JackParser.tokens rename compiler/{parser-gen => grammar}/JackLexer.g4 (100%) rename compiler/{parser-gen => grammar}/JackParser.g4 (100%) delete mode 100644 compiler/parser-gen/Main.jack delete mode 100644 compiler/parser-gen/Makefile delete mode 100644 compiler/parser-gen/jack.ohm delete mode 100644 compiler/src/VIsitor.ts delete mode 100644 compiler/src/symbol.table.istener.ts diff --git a/compiler/TODO.md b/compiler/TODO.md new file mode 100644 index 00000000..35b962d7 --- /dev/null +++ b/compiler/TODO.md @@ -0,0 +1,3 @@ +TODO: +- add error when expecting class/ function name instead of IDENTIFIER +- The class name doesn't match the file name diff --git a/compiler/gen.sh b/compiler/gen.sh index 07de373a..e5784cab 100644 --- a/compiler/gen.sh +++ b/compiler/gen.sh @@ -1,6 +1,6 @@ #!/bin/bash echo "Generating" -cd parser-gen +cd grammar antlr4ts -Werror -visitor JackLexer.g4 JackParser.g4 -o ../src/generated cd ../src/generated sed -i -e 's/public get serializedATN(/public override get serializedATN\(/g' JackLexer.ts diff --git a/compiler/grammar/.antlr/JackLexer.interp b/compiler/grammar/.antlr/JackLexer.interp new file mode 100644 index 00000000..722e32c5 --- /dev/null +++ b/compiler/grammar/.antlr/JackLexer.interp @@ -0,0 +1,155 @@ +token literal names: +null +'class' +'constructor' +'function' +'method' +'field' +'static' +'var' +'int' +'char' +'boolean' +'void' +'let' +'do' +'if' +'else' +'while' +'return' +'{' +'}' +'(' +')' +'[' +']' +'.' +',' +';' +'=' +'+' +'-' +'*' +'/' +'&' +'|' +'~' +'<' +'>' +null +null +null +null +null +'null' +'this' +null +null +null + +token symbolic names: +null +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +BOOLEAN_LITERAL +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +rule names: +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +BOOLEAN_LITERAL +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 46, 307, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 4, 36, 234, 8, 36, 11, 36, 12, 36, 235, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 244, 8, 37, 10, 37, 12, 37, 247, 9, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 258, 8, 38, 10, 38, 12, 38, 261, 9, 38, 1, 38, 1, 38, 1, 39, 4, 39, 266, 8, 39, 11, 39, 12, 39, 267, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 279, 8, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 5, 43, 293, 8, 43, 10, 43, 12, 43, 296, 9, 43, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 5, 45, 303, 8, 45, 10, 45, 12, 45, 306, 9, 45, 1, 245, 0, 46, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 1, 0, 6, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 313, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 1, 93, 1, 0, 0, 0, 3, 99, 1, 0, 0, 0, 5, 111, 1, 0, 0, 0, 7, 120, 1, 0, 0, 0, 9, 127, 1, 0, 0, 0, 11, 133, 1, 0, 0, 0, 13, 140, 1, 0, 0, 0, 15, 144, 1, 0, 0, 0, 17, 148, 1, 0, 0, 0, 19, 153, 1, 0, 0, 0, 21, 161, 1, 0, 0, 0, 23, 166, 1, 0, 0, 0, 25, 170, 1, 0, 0, 0, 27, 173, 1, 0, 0, 0, 29, 176, 1, 0, 0, 0, 31, 181, 1, 0, 0, 0, 33, 187, 1, 0, 0, 0, 35, 194, 1, 0, 0, 0, 37, 196, 1, 0, 0, 0, 39, 198, 1, 0, 0, 0, 41, 200, 1, 0, 0, 0, 43, 202, 1, 0, 0, 0, 45, 204, 1, 0, 0, 0, 47, 206, 1, 0, 0, 0, 49, 208, 1, 0, 0, 0, 51, 210, 1, 0, 0, 0, 53, 212, 1, 0, 0, 0, 55, 214, 1, 0, 0, 0, 57, 216, 1, 0, 0, 0, 59, 218, 1, 0, 0, 0, 61, 220, 1, 0, 0, 0, 63, 222, 1, 0, 0, 0, 65, 224, 1, 0, 0, 0, 67, 226, 1, 0, 0, 0, 69, 228, 1, 0, 0, 0, 71, 230, 1, 0, 0, 0, 73, 233, 1, 0, 0, 0, 75, 239, 1, 0, 0, 0, 77, 253, 1, 0, 0, 0, 79, 265, 1, 0, 0, 0, 81, 278, 1, 0, 0, 0, 83, 280, 1, 0, 0, 0, 85, 285, 1, 0, 0, 0, 87, 290, 1, 0, 0, 0, 89, 297, 1, 0, 0, 0, 91, 300, 1, 0, 0, 0, 93, 94, 5, 99, 0, 0, 94, 95, 5, 108, 0, 0, 95, 96, 5, 97, 0, 0, 96, 97, 5, 115, 0, 0, 97, 98, 5, 115, 0, 0, 98, 2, 1, 0, 0, 0, 99, 100, 5, 99, 0, 0, 100, 101, 5, 111, 0, 0, 101, 102, 5, 110, 0, 0, 102, 103, 5, 115, 0, 0, 103, 104, 5, 116, 0, 0, 104, 105, 5, 114, 0, 0, 105, 106, 5, 117, 0, 0, 106, 107, 5, 99, 0, 0, 107, 108, 5, 116, 0, 0, 108, 109, 5, 111, 0, 0, 109, 110, 5, 114, 0, 0, 110, 4, 1, 0, 0, 0, 111, 112, 5, 102, 0, 0, 112, 113, 5, 117, 0, 0, 113, 114, 5, 110, 0, 0, 114, 115, 5, 99, 0, 0, 115, 116, 5, 116, 0, 0, 116, 117, 5, 105, 0, 0, 117, 118, 5, 111, 0, 0, 118, 119, 5, 110, 0, 0, 119, 6, 1, 0, 0, 0, 120, 121, 5, 109, 0, 0, 121, 122, 5, 101, 0, 0, 122, 123, 5, 116, 0, 0, 123, 124, 5, 104, 0, 0, 124, 125, 5, 111, 0, 0, 125, 126, 5, 100, 0, 0, 126, 8, 1, 0, 0, 0, 127, 128, 5, 102, 0, 0, 128, 129, 5, 105, 0, 0, 129, 130, 5, 101, 0, 0, 130, 131, 5, 108, 0, 0, 131, 132, 5, 100, 0, 0, 132, 10, 1, 0, 0, 0, 133, 134, 5, 115, 0, 0, 134, 135, 5, 116, 0, 0, 135, 136, 5, 97, 0, 0, 136, 137, 5, 116, 0, 0, 137, 138, 5, 105, 0, 0, 138, 139, 5, 99, 0, 0, 139, 12, 1, 0, 0, 0, 140, 141, 5, 118, 0, 0, 141, 142, 5, 97, 0, 0, 142, 143, 5, 114, 0, 0, 143, 14, 1, 0, 0, 0, 144, 145, 5, 105, 0, 0, 145, 146, 5, 110, 0, 0, 146, 147, 5, 116, 0, 0, 147, 16, 1, 0, 0, 0, 148, 149, 5, 99, 0, 0, 149, 150, 5, 104, 0, 0, 150, 151, 5, 97, 0, 0, 151, 152, 5, 114, 0, 0, 152, 18, 1, 0, 0, 0, 153, 154, 5, 98, 0, 0, 154, 155, 5, 111, 0, 0, 155, 156, 5, 111, 0, 0, 156, 157, 5, 108, 0, 0, 157, 158, 5, 101, 0, 0, 158, 159, 5, 97, 0, 0, 159, 160, 5, 110, 0, 0, 160, 20, 1, 0, 0, 0, 161, 162, 5, 118, 0, 0, 162, 163, 5, 111, 0, 0, 163, 164, 5, 105, 0, 0, 164, 165, 5, 100, 0, 0, 165, 22, 1, 0, 0, 0, 166, 167, 5, 108, 0, 0, 167, 168, 5, 101, 0, 0, 168, 169, 5, 116, 0, 0, 169, 24, 1, 0, 0, 0, 170, 171, 5, 100, 0, 0, 171, 172, 5, 111, 0, 0, 172, 26, 1, 0, 0, 0, 173, 174, 5, 105, 0, 0, 174, 175, 5, 102, 0, 0, 175, 28, 1, 0, 0, 0, 176, 177, 5, 101, 0, 0, 177, 178, 5, 108, 0, 0, 178, 179, 5, 115, 0, 0, 179, 180, 5, 101, 0, 0, 180, 30, 1, 0, 0, 0, 181, 182, 5, 119, 0, 0, 182, 183, 5, 104, 0, 0, 183, 184, 5, 105, 0, 0, 184, 185, 5, 108, 0, 0, 185, 186, 5, 101, 0, 0, 186, 32, 1, 0, 0, 0, 187, 188, 5, 114, 0, 0, 188, 189, 5, 101, 0, 0, 189, 190, 5, 116, 0, 0, 190, 191, 5, 117, 0, 0, 191, 192, 5, 114, 0, 0, 192, 193, 5, 110, 0, 0, 193, 34, 1, 0, 0, 0, 194, 195, 5, 123, 0, 0, 195, 36, 1, 0, 0, 0, 196, 197, 5, 125, 0, 0, 197, 38, 1, 0, 0, 0, 198, 199, 5, 40, 0, 0, 199, 40, 1, 0, 0, 0, 200, 201, 5, 41, 0, 0, 201, 42, 1, 0, 0, 0, 202, 203, 5, 91, 0, 0, 203, 44, 1, 0, 0, 0, 204, 205, 5, 93, 0, 0, 205, 46, 1, 0, 0, 0, 206, 207, 5, 46, 0, 0, 207, 48, 1, 0, 0, 0, 208, 209, 5, 44, 0, 0, 209, 50, 1, 0, 0, 0, 210, 211, 5, 59, 0, 0, 211, 52, 1, 0, 0, 0, 212, 213, 5, 61, 0, 0, 213, 54, 1, 0, 0, 0, 214, 215, 5, 43, 0, 0, 215, 56, 1, 0, 0, 0, 216, 217, 5, 45, 0, 0, 217, 58, 1, 0, 0, 0, 218, 219, 5, 42, 0, 0, 219, 60, 1, 0, 0, 0, 220, 221, 5, 47, 0, 0, 221, 62, 1, 0, 0, 0, 222, 223, 5, 38, 0, 0, 223, 64, 1, 0, 0, 0, 224, 225, 5, 124, 0, 0, 225, 66, 1, 0, 0, 0, 226, 227, 5, 126, 0, 0, 227, 68, 1, 0, 0, 0, 228, 229, 5, 60, 0, 0, 229, 70, 1, 0, 0, 0, 230, 231, 5, 62, 0, 0, 231, 72, 1, 0, 0, 0, 232, 234, 7, 0, 0, 0, 233, 232, 1, 0, 0, 0, 234, 235, 1, 0, 0, 0, 235, 233, 1, 0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, 6, 36, 0, 0, 238, 74, 1, 0, 0, 0, 239, 240, 5, 47, 0, 0, 240, 241, 5, 42, 0, 0, 241, 245, 1, 0, 0, 0, 242, 244, 9, 0, 0, 0, 243, 242, 1, 0, 0, 0, 244, 247, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 246, 248, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 249, 5, 42, 0, 0, 249, 250, 5, 47, 0, 0, 250, 251, 1, 0, 0, 0, 251, 252, 6, 37, 0, 0, 252, 76, 1, 0, 0, 0, 253, 254, 5, 47, 0, 0, 254, 255, 5, 47, 0, 0, 255, 259, 1, 0, 0, 0, 256, 258, 8, 1, 0, 0, 257, 256, 1, 0, 0, 0, 258, 261, 1, 0, 0, 0, 259, 257, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 262, 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 262, 263, 6, 38, 0, 0, 263, 78, 1, 0, 0, 0, 264, 266, 7, 2, 0, 0, 265, 264, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 267, 268, 1, 0, 0, 0, 268, 80, 1, 0, 0, 0, 269, 270, 5, 116, 0, 0, 270, 271, 5, 114, 0, 0, 271, 272, 5, 117, 0, 0, 272, 279, 5, 101, 0, 0, 273, 274, 5, 102, 0, 0, 274, 275, 5, 97, 0, 0, 275, 276, 5, 108, 0, 0, 276, 277, 5, 115, 0, 0, 277, 279, 5, 101, 0, 0, 278, 269, 1, 0, 0, 0, 278, 273, 1, 0, 0, 0, 279, 82, 1, 0, 0, 0, 280, 281, 5, 110, 0, 0, 281, 282, 5, 117, 0, 0, 282, 283, 5, 108, 0, 0, 283, 284, 5, 108, 0, 0, 284, 84, 1, 0, 0, 0, 285, 286, 5, 116, 0, 0, 286, 287, 5, 104, 0, 0, 287, 288, 5, 105, 0, 0, 288, 289, 5, 115, 0, 0, 289, 86, 1, 0, 0, 0, 290, 294, 7, 3, 0, 0, 291, 293, 7, 4, 0, 0, 292, 291, 1, 0, 0, 0, 293, 296, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, 294, 295, 1, 0, 0, 0, 295, 88, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 297, 298, 3, 91, 45, 0, 298, 299, 5, 34, 0, 0, 299, 90, 1, 0, 0, 0, 300, 304, 5, 34, 0, 0, 301, 303, 8, 5, 0, 0, 302, 301, 1, 0, 0, 0, 303, 306, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 92, 1, 0, 0, 0, 306, 304, 1, 0, 0, 0, 8, 0, 235, 245, 259, 267, 278, 294, 304, 1, 6, 0, 0] \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackLexer.java b/compiler/grammar/.antlr/JackLexer.java new file mode 100644 index 00000000..6a4699be --- /dev/null +++ b/compiler/grammar/.antlr/JackLexer.java @@ -0,0 +1,321 @@ +// Generated from /home/babkamen/git/nand2tetris/tools/web-ide/compiler/grammar/JackLexer.g4 by ANTLR 4.13.1 +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"}) +public class JackLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + CLASS=1, CONSTRUCTOR=2, FUNCTION=3, METHOD=4, FIELD=5, STATIC=6, VAR=7, + INT=8, CHAR=9, BOOLEAN=10, VOID=11, LET=12, DO=13, IF=14, ELSE=15, WHILE=16, + RETURN=17, LBRACE=18, RBRACE=19, LPAREN=20, RPAREN=21, LBRACKET=22, RBRACKET=23, + DOT=24, COMMA=25, SEMICOLON=26, EQUALS=27, PLUS=28, MINUS=29, MUL=30, + DIV=31, AND=32, OR=33, TILDE=34, LESS_THAN=35, GREATER_THAN=36, WS=37, + COMMENT=38, LINE_COMMENT=39, INTEGER_LITERAL=40, BOOLEAN_LITERAL=41, NULL_LITERAL=42, + THIS_LITERAL=43, IDENTIFIER=44, STRING_LITERAL=45, UnterminatedStringLiteral=46; + public static String[] channelNames = { + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + }; + + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + private static String[] makeRuleNames() { + return new String[] { + "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", "VAR", + "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", + "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", + "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", + "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", + "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", + "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral" + }; + } + public static final String[] ruleNames = makeRuleNames(); + + private static String[] makeLiteralNames() { + return new String[] { + null, "'class'", "'constructor'", "'function'", "'method'", "'field'", + "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", + "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", + "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", + "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", null, null, null, null, null, + "'null'", "'this'" + }; + } + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + private static String[] makeSymbolicNames() { + return new String[] { + null, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", + "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", + "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", + "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", + "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", + "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", + "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral" + }; + } + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public JackLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "JackLexer.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getChannelNames() { return channelNames; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\u0004\u0000.\u0133\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001"+ + "\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004"+ + "\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007"+ + "\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b"+ + "\u0007\u000b\u0002\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e\u0002"+ + "\u000f\u0007\u000f\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011\u0002"+ + "\u0012\u0007\u0012\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014\u0002"+ + "\u0015\u0007\u0015\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017\u0002"+ + "\u0018\u0007\u0018\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a\u0002"+ + "\u001b\u0007\u001b\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d\u0002"+ + "\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007"+ + "!\u0002\"\u0007\"\u0002#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007"+ + "&\u0002\'\u0007\'\u0002(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002+\u0007"+ + "+\u0002,\u0007,\u0002-\u0007-\u0001\u0000\u0001\u0000\u0001\u0000\u0001"+ + "\u0000\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ + "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ + "\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001"+ + "\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001"+ + "\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001"+ + "\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001"+ + "\u0004\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001"+ + "\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001"+ + "\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001"+ + "\b\u0001\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ + "\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001"+ + "\u000b\u0001\u000b\u0001\f\u0001\f\u0001\f\u0001\r\u0001\r\u0001\r\u0001"+ + "\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000f\u0001"+ + "\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001"+ + "\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001"+ + "\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001"+ + "\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001"+ + "\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001"+ + "\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001"+ + "\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001"+ + " \u0001 \u0001!\u0001!\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0004$\u00ea"+ + "\b$\u000b$\f$\u00eb\u0001$\u0001$\u0001%\u0001%\u0001%\u0001%\u0005%\u00f4"+ + "\b%\n%\f%\u00f7\t%\u0001%\u0001%\u0001%\u0001%\u0001%\u0001&\u0001&\u0001"+ + "&\u0001&\u0005&\u0102\b&\n&\f&\u0105\t&\u0001&\u0001&\u0001\'\u0004\'"+ + "\u010a\b\'\u000b\'\f\'\u010b\u0001(\u0001(\u0001(\u0001(\u0001(\u0001"+ + "(\u0001(\u0001(\u0001(\u0003(\u0117\b(\u0001)\u0001)\u0001)\u0001)\u0001"+ + ")\u0001*\u0001*\u0001*\u0001*\u0001*\u0001+\u0001+\u0005+\u0125\b+\n+"+ + "\f+\u0128\t+\u0001,\u0001,\u0001,\u0001-\u0001-\u0005-\u012f\b-\n-\f-"+ + "\u0132\t-\u0001\u00f5\u0000.\u0001\u0001\u0003\u0002\u0005\u0003\u0007"+ + "\u0004\t\u0005\u000b\u0006\r\u0007\u000f\b\u0011\t\u0013\n\u0015\u000b"+ + "\u0017\f\u0019\r\u001b\u000e\u001d\u000f\u001f\u0010!\u0011#\u0012%\u0013"+ + "\'\u0014)\u0015+\u0016-\u0017/\u00181\u00193\u001a5\u001b7\u001c9\u001d"+ + ";\u001e=\u001f? A!C\"E#G$I%K&M\'O(Q)S*U+W,Y-[.\u0001\u0000\u0006\u0003"+ + "\u0000\t\n\r\r \u0002\u0000\n\n\r\r\u0001\u000009\u0003\u0000AZ__az\u0004"+ + "\u000009AZ__az\u0004\u0000\n\n\r\r\"\"\\\\\u0139\u0000\u0001\u0001\u0000"+ + "\u0000\u0000\u0000\u0003\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000"+ + "\u0000\u0000\u0000\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000"+ + "\u0000\u0000\u000b\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000"+ + "\u0000\u000f\u0001\u0000\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000"+ + "\u0000\u0013\u0001\u0000\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000"+ + "\u0000\u0017\u0001\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000"+ + "\u0000\u001b\u0001\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000"+ + "\u0000\u001f\u0001\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000"+ + "#\u0001\u0000\u0000\u0000\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001"+ + "\u0000\u0000\u0000\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000"+ + "\u0000\u0000-\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u0000"+ + "1\u0001\u0000\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001"+ + "\u0000\u0000\u0000\u00007\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000"+ + "\u0000\u0000;\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000"+ + "?\u0001\u0000\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C\u0001"+ + "\u0000\u0000\u0000\u0000E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000\u0000"+ + "\u0000\u0000I\u0001\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000\u0000"+ + "M\u0001\u0000\u0000\u0000\u0000O\u0001\u0000\u0000\u0000\u0000Q\u0001"+ + "\u0000\u0000\u0000\u0000S\u0001\u0000\u0000\u0000\u0000U\u0001\u0000\u0000"+ + "\u0000\u0000W\u0001\u0000\u0000\u0000\u0000Y\u0001\u0000\u0000\u0000\u0000"+ + "[\u0001\u0000\u0000\u0000\u0001]\u0001\u0000\u0000\u0000\u0003c\u0001"+ + "\u0000\u0000\u0000\u0005o\u0001\u0000\u0000\u0000\u0007x\u0001\u0000\u0000"+ + "\u0000\t\u007f\u0001\u0000\u0000\u0000\u000b\u0085\u0001\u0000\u0000\u0000"+ + "\r\u008c\u0001\u0000\u0000\u0000\u000f\u0090\u0001\u0000\u0000\u0000\u0011"+ + "\u0094\u0001\u0000\u0000\u0000\u0013\u0099\u0001\u0000\u0000\u0000\u0015"+ + "\u00a1\u0001\u0000\u0000\u0000\u0017\u00a6\u0001\u0000\u0000\u0000\u0019"+ + "\u00aa\u0001\u0000\u0000\u0000\u001b\u00ad\u0001\u0000\u0000\u0000\u001d"+ + "\u00b0\u0001\u0000\u0000\u0000\u001f\u00b5\u0001\u0000\u0000\u0000!\u00bb"+ + "\u0001\u0000\u0000\u0000#\u00c2\u0001\u0000\u0000\u0000%\u00c4\u0001\u0000"+ + "\u0000\u0000\'\u00c6\u0001\u0000\u0000\u0000)\u00c8\u0001\u0000\u0000"+ + "\u0000+\u00ca\u0001\u0000\u0000\u0000-\u00cc\u0001\u0000\u0000\u0000/"+ + "\u00ce\u0001\u0000\u0000\u00001\u00d0\u0001\u0000\u0000\u00003\u00d2\u0001"+ + "\u0000\u0000\u00005\u00d4\u0001\u0000\u0000\u00007\u00d6\u0001\u0000\u0000"+ + "\u00009\u00d8\u0001\u0000\u0000\u0000;\u00da\u0001\u0000\u0000\u0000="+ + "\u00dc\u0001\u0000\u0000\u0000?\u00de\u0001\u0000\u0000\u0000A\u00e0\u0001"+ + "\u0000\u0000\u0000C\u00e2\u0001\u0000\u0000\u0000E\u00e4\u0001\u0000\u0000"+ + "\u0000G\u00e6\u0001\u0000\u0000\u0000I\u00e9\u0001\u0000\u0000\u0000K"+ + "\u00ef\u0001\u0000\u0000\u0000M\u00fd\u0001\u0000\u0000\u0000O\u0109\u0001"+ + "\u0000\u0000\u0000Q\u0116\u0001\u0000\u0000\u0000S\u0118\u0001\u0000\u0000"+ + "\u0000U\u011d\u0001\u0000\u0000\u0000W\u0122\u0001\u0000\u0000\u0000Y"+ + "\u0129\u0001\u0000\u0000\u0000[\u012c\u0001\u0000\u0000\u0000]^\u0005"+ + "c\u0000\u0000^_\u0005l\u0000\u0000_`\u0005a\u0000\u0000`a\u0005s\u0000"+ + "\u0000ab\u0005s\u0000\u0000b\u0002\u0001\u0000\u0000\u0000cd\u0005c\u0000"+ + "\u0000de\u0005o\u0000\u0000ef\u0005n\u0000\u0000fg\u0005s\u0000\u0000"+ + "gh\u0005t\u0000\u0000hi\u0005r\u0000\u0000ij\u0005u\u0000\u0000jk\u0005"+ + "c\u0000\u0000kl\u0005t\u0000\u0000lm\u0005o\u0000\u0000mn\u0005r\u0000"+ + "\u0000n\u0004\u0001\u0000\u0000\u0000op\u0005f\u0000\u0000pq\u0005u\u0000"+ + "\u0000qr\u0005n\u0000\u0000rs\u0005c\u0000\u0000st\u0005t\u0000\u0000"+ + "tu\u0005i\u0000\u0000uv\u0005o\u0000\u0000vw\u0005n\u0000\u0000w\u0006"+ + "\u0001\u0000\u0000\u0000xy\u0005m\u0000\u0000yz\u0005e\u0000\u0000z{\u0005"+ + "t\u0000\u0000{|\u0005h\u0000\u0000|}\u0005o\u0000\u0000}~\u0005d\u0000"+ + "\u0000~\b\u0001\u0000\u0000\u0000\u007f\u0080\u0005f\u0000\u0000\u0080"+ + "\u0081\u0005i\u0000\u0000\u0081\u0082\u0005e\u0000\u0000\u0082\u0083\u0005"+ + "l\u0000\u0000\u0083\u0084\u0005d\u0000\u0000\u0084\n\u0001\u0000\u0000"+ + "\u0000\u0085\u0086\u0005s\u0000\u0000\u0086\u0087\u0005t\u0000\u0000\u0087"+ + "\u0088\u0005a\u0000\u0000\u0088\u0089\u0005t\u0000\u0000\u0089\u008a\u0005"+ + "i\u0000\u0000\u008a\u008b\u0005c\u0000\u0000\u008b\f\u0001\u0000\u0000"+ + "\u0000\u008c\u008d\u0005v\u0000\u0000\u008d\u008e\u0005a\u0000\u0000\u008e"+ + "\u008f\u0005r\u0000\u0000\u008f\u000e\u0001\u0000\u0000\u0000\u0090\u0091"+ + "\u0005i\u0000\u0000\u0091\u0092\u0005n\u0000\u0000\u0092\u0093\u0005t"+ + "\u0000\u0000\u0093\u0010\u0001\u0000\u0000\u0000\u0094\u0095\u0005c\u0000"+ + "\u0000\u0095\u0096\u0005h\u0000\u0000\u0096\u0097\u0005a\u0000\u0000\u0097"+ + "\u0098\u0005r\u0000\u0000\u0098\u0012\u0001\u0000\u0000\u0000\u0099\u009a"+ + "\u0005b\u0000\u0000\u009a\u009b\u0005o\u0000\u0000\u009b\u009c\u0005o"+ + "\u0000\u0000\u009c\u009d\u0005l\u0000\u0000\u009d\u009e\u0005e\u0000\u0000"+ + "\u009e\u009f\u0005a\u0000\u0000\u009f\u00a0\u0005n\u0000\u0000\u00a0\u0014"+ + "\u0001\u0000\u0000\u0000\u00a1\u00a2\u0005v\u0000\u0000\u00a2\u00a3\u0005"+ + "o\u0000\u0000\u00a3\u00a4\u0005i\u0000\u0000\u00a4\u00a5\u0005d\u0000"+ + "\u0000\u00a5\u0016\u0001\u0000\u0000\u0000\u00a6\u00a7\u0005l\u0000\u0000"+ + "\u00a7\u00a8\u0005e\u0000\u0000\u00a8\u00a9\u0005t\u0000\u0000\u00a9\u0018"+ + "\u0001\u0000\u0000\u0000\u00aa\u00ab\u0005d\u0000\u0000\u00ab\u00ac\u0005"+ + "o\u0000\u0000\u00ac\u001a\u0001\u0000\u0000\u0000\u00ad\u00ae\u0005i\u0000"+ + "\u0000\u00ae\u00af\u0005f\u0000\u0000\u00af\u001c\u0001\u0000\u0000\u0000"+ + "\u00b0\u00b1\u0005e\u0000\u0000\u00b1\u00b2\u0005l\u0000\u0000\u00b2\u00b3"+ + "\u0005s\u0000\u0000\u00b3\u00b4\u0005e\u0000\u0000\u00b4\u001e\u0001\u0000"+ + "\u0000\u0000\u00b5\u00b6\u0005w\u0000\u0000\u00b6\u00b7\u0005h\u0000\u0000"+ + "\u00b7\u00b8\u0005i\u0000\u0000\u00b8\u00b9\u0005l\u0000\u0000\u00b9\u00ba"+ + "\u0005e\u0000\u0000\u00ba \u0001\u0000\u0000\u0000\u00bb\u00bc\u0005r"+ + "\u0000\u0000\u00bc\u00bd\u0005e\u0000\u0000\u00bd\u00be\u0005t\u0000\u0000"+ + "\u00be\u00bf\u0005u\u0000\u0000\u00bf\u00c0\u0005r\u0000\u0000\u00c0\u00c1"+ + "\u0005n\u0000\u0000\u00c1\"\u0001\u0000\u0000\u0000\u00c2\u00c3\u0005"+ + "{\u0000\u0000\u00c3$\u0001\u0000\u0000\u0000\u00c4\u00c5\u0005}\u0000"+ + "\u0000\u00c5&\u0001\u0000\u0000\u0000\u00c6\u00c7\u0005(\u0000\u0000\u00c7"+ + "(\u0001\u0000\u0000\u0000\u00c8\u00c9\u0005)\u0000\u0000\u00c9*\u0001"+ + "\u0000\u0000\u0000\u00ca\u00cb\u0005[\u0000\u0000\u00cb,\u0001\u0000\u0000"+ + "\u0000\u00cc\u00cd\u0005]\u0000\u0000\u00cd.\u0001\u0000\u0000\u0000\u00ce"+ + "\u00cf\u0005.\u0000\u0000\u00cf0\u0001\u0000\u0000\u0000\u00d0\u00d1\u0005"+ + ",\u0000\u0000\u00d12\u0001\u0000\u0000\u0000\u00d2\u00d3\u0005;\u0000"+ + "\u0000\u00d34\u0001\u0000\u0000\u0000\u00d4\u00d5\u0005=\u0000\u0000\u00d5"+ + "6\u0001\u0000\u0000\u0000\u00d6\u00d7\u0005+\u0000\u0000\u00d78\u0001"+ + "\u0000\u0000\u0000\u00d8\u00d9\u0005-\u0000\u0000\u00d9:\u0001\u0000\u0000"+ + "\u0000\u00da\u00db\u0005*\u0000\u0000\u00db<\u0001\u0000\u0000\u0000\u00dc"+ + "\u00dd\u0005/\u0000\u0000\u00dd>\u0001\u0000\u0000\u0000\u00de\u00df\u0005"+ + "&\u0000\u0000\u00df@\u0001\u0000\u0000\u0000\u00e0\u00e1\u0005|\u0000"+ + "\u0000\u00e1B\u0001\u0000\u0000\u0000\u00e2\u00e3\u0005~\u0000\u0000\u00e3"+ + "D\u0001\u0000\u0000\u0000\u00e4\u00e5\u0005<\u0000\u0000\u00e5F\u0001"+ + "\u0000\u0000\u0000\u00e6\u00e7\u0005>\u0000\u0000\u00e7H\u0001\u0000\u0000"+ + "\u0000\u00e8\u00ea\u0007\u0000\u0000\u0000\u00e9\u00e8\u0001\u0000\u0000"+ + "\u0000\u00ea\u00eb\u0001\u0000\u0000\u0000\u00eb\u00e9\u0001\u0000\u0000"+ + "\u0000\u00eb\u00ec\u0001\u0000\u0000\u0000\u00ec\u00ed\u0001\u0000\u0000"+ + "\u0000\u00ed\u00ee\u0006$\u0000\u0000\u00eeJ\u0001\u0000\u0000\u0000\u00ef"+ + "\u00f0\u0005/\u0000\u0000\u00f0\u00f1\u0005*\u0000\u0000\u00f1\u00f5\u0001"+ + "\u0000\u0000\u0000\u00f2\u00f4\t\u0000\u0000\u0000\u00f3\u00f2\u0001\u0000"+ + "\u0000\u0000\u00f4\u00f7\u0001\u0000\u0000\u0000\u00f5\u00f6\u0001\u0000"+ + "\u0000\u0000\u00f5\u00f3\u0001\u0000\u0000\u0000\u00f6\u00f8\u0001\u0000"+ + "\u0000\u0000\u00f7\u00f5\u0001\u0000\u0000\u0000\u00f8\u00f9\u0005*\u0000"+ + "\u0000\u00f9\u00fa\u0005/\u0000\u0000\u00fa\u00fb\u0001\u0000\u0000\u0000"+ + "\u00fb\u00fc\u0006%\u0000\u0000\u00fcL\u0001\u0000\u0000\u0000\u00fd\u00fe"+ + "\u0005/\u0000\u0000\u00fe\u00ff\u0005/\u0000\u0000\u00ff\u0103\u0001\u0000"+ + "\u0000\u0000\u0100\u0102\b\u0001\u0000\u0000\u0101\u0100\u0001\u0000\u0000"+ + "\u0000\u0102\u0105\u0001\u0000\u0000\u0000\u0103\u0101\u0001\u0000\u0000"+ + "\u0000\u0103\u0104\u0001\u0000\u0000\u0000\u0104\u0106\u0001\u0000\u0000"+ + "\u0000\u0105\u0103\u0001\u0000\u0000\u0000\u0106\u0107\u0006&\u0000\u0000"+ + "\u0107N\u0001\u0000\u0000\u0000\u0108\u010a\u0007\u0002\u0000\u0000\u0109"+ + "\u0108\u0001\u0000\u0000\u0000\u010a\u010b\u0001\u0000\u0000\u0000\u010b"+ + "\u0109\u0001\u0000\u0000\u0000\u010b\u010c\u0001\u0000\u0000\u0000\u010c"+ + "P\u0001\u0000\u0000\u0000\u010d\u010e\u0005t\u0000\u0000\u010e\u010f\u0005"+ + "r\u0000\u0000\u010f\u0110\u0005u\u0000\u0000\u0110\u0117\u0005e\u0000"+ + "\u0000\u0111\u0112\u0005f\u0000\u0000\u0112\u0113\u0005a\u0000\u0000\u0113"+ + "\u0114\u0005l\u0000\u0000\u0114\u0115\u0005s\u0000\u0000\u0115\u0117\u0005"+ + "e\u0000\u0000\u0116\u010d\u0001\u0000\u0000\u0000\u0116\u0111\u0001\u0000"+ + "\u0000\u0000\u0117R\u0001\u0000\u0000\u0000\u0118\u0119\u0005n\u0000\u0000"+ + "\u0119\u011a\u0005u\u0000\u0000\u011a\u011b\u0005l\u0000\u0000\u011b\u011c"+ + "\u0005l\u0000\u0000\u011cT\u0001\u0000\u0000\u0000\u011d\u011e\u0005t"+ + "\u0000\u0000\u011e\u011f\u0005h\u0000\u0000\u011f\u0120\u0005i\u0000\u0000"+ + "\u0120\u0121\u0005s\u0000\u0000\u0121V\u0001\u0000\u0000\u0000\u0122\u0126"+ + "\u0007\u0003\u0000\u0000\u0123\u0125\u0007\u0004\u0000\u0000\u0124\u0123"+ + "\u0001\u0000\u0000\u0000\u0125\u0128\u0001\u0000\u0000\u0000\u0126\u0124"+ + "\u0001\u0000\u0000\u0000\u0126\u0127\u0001\u0000\u0000\u0000\u0127X\u0001"+ + "\u0000\u0000\u0000\u0128\u0126\u0001\u0000\u0000\u0000\u0129\u012a\u0003"+ + "[-\u0000\u012a\u012b\u0005\"\u0000\u0000\u012bZ\u0001\u0000\u0000\u0000"+ + "\u012c\u0130\u0005\"\u0000\u0000\u012d\u012f\b\u0005\u0000\u0000\u012e"+ + "\u012d\u0001\u0000\u0000\u0000\u012f\u0132\u0001\u0000\u0000\u0000\u0130"+ + "\u012e\u0001\u0000\u0000\u0000\u0130\u0131\u0001\u0000\u0000\u0000\u0131"+ + "\\\u0001\u0000\u0000\u0000\u0132\u0130\u0001\u0000\u0000\u0000\b\u0000"+ + "\u00eb\u00f5\u0103\u010b\u0116\u0126\u0130\u0001\u0006\u0000\u0000"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackLexer.tokens b/compiler/grammar/.antlr/JackLexer.tokens new file mode 100644 index 00000000..8292b05c --- /dev/null +++ b/compiler/grammar/.antlr/JackLexer.tokens @@ -0,0 +1,84 @@ +CLASS=1 +CONSTRUCTOR=2 +FUNCTION=3 +METHOD=4 +FIELD=5 +STATIC=6 +VAR=7 +INT=8 +CHAR=9 +BOOLEAN=10 +VOID=11 +LET=12 +DO=13 +IF=14 +ELSE=15 +WHILE=16 +RETURN=17 +LBRACE=18 +RBRACE=19 +LPAREN=20 +RPAREN=21 +LBRACKET=22 +RBRACKET=23 +DOT=24 +COMMA=25 +SEMICOLON=26 +EQUALS=27 +PLUS=28 +MINUS=29 +MUL=30 +DIV=31 +AND=32 +OR=33 +TILDE=34 +LESS_THAN=35 +GREATER_THAN=36 +WS=37 +COMMENT=38 +LINE_COMMENT=39 +INTEGER_LITERAL=40 +BOOLEAN_LITERAL=41 +NULL_LITERAL=42 +THIS_LITERAL=43 +IDENTIFIER=44 +STRING_LITERAL=45 +UnterminatedStringLiteral=46 +'class'=1 +'constructor'=2 +'function'=3 +'method'=4 +'field'=5 +'static'=6 +'var'=7 +'int'=8 +'char'=9 +'boolean'=10 +'void'=11 +'let'=12 +'do'=13 +'if'=14 +'else'=15 +'while'=16 +'return'=17 +'{'=18 +'}'=19 +'('=20 +')'=21 +'['=22 +']'=23 +'.'=24 +','=25 +';'=26 +'='=27 +'+'=28 +'-'=29 +'*'=30 +'/'=31 +'&'=32 +'|'=33 +'~'=34 +'<'=35 +'>'=36 +'null'=42 +'this'=43 diff --git a/compiler/grammar/.antlr/JackParser.interp b/compiler/grammar/.antlr/JackParser.interp new file mode 100644 index 00000000..f2fd9610 --- /dev/null +++ b/compiler/grammar/.antlr/JackParser.interp @@ -0,0 +1,142 @@ +token literal names: +null +'class' +'constructor' +'function' +'method' +'field' +'static' +'var' +'int' +'char' +'boolean' +'void' +'let' +'do' +'if' +'else' +'while' +'return' +'{' +'}' +'(' +')' +'[' +']' +'.' +',' +';' +'=' +'+' +'-' +'*' +'/' +'&' +'|' +'~' +'<' +'>' +null +null +null +null +null +'null' +'this' +null +null +null + +token symbolic names: +null +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +BOOLEAN_LITERAL +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +rule names: +program +classDeclaration +className +classVarDec +fieldList +fieldName +subroutineDeclaration +subroutineType +subroutineDecWithoutType +subroutineName +subroutineReturnType +varType +parameterList +parameter +parameterName +subroutineBody +rBrace +varDeclaration +varNameInDeclaration +varName +statements +statement +letStatement +ifElseStatement +ifStatement +elseStatement +whileStatement +doStatement +subroutineCall +subroutineId +returnStatement +expressionList +expression +groupedExpression +unaryOp +arrayAccess +constant +unaryOperator +binaryOperator + + +atn: +[4, 1, 46, 296, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 86, 8, 1, 10, 1, 12, 1, 89, 9, 1, 1, 1, 5, 1, 92, 8, 1, 10, 1, 12, 1, 95, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 109, 8, 4, 10, 4, 12, 4, 112, 9, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 132, 8, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 5, 12, 139, 8, 12, 10, 12, 12, 12, 142, 9, 12, 3, 12, 144, 8, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 153, 8, 15, 10, 15, 12, 15, 156, 9, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 168, 8, 17, 10, 17, 12, 17, 171, 9, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 5, 20, 180, 8, 20, 10, 20, 12, 20, 183, 9, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 190, 8, 21, 1, 22, 1, 22, 1, 22, 3, 22, 195, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 3, 23, 203, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 3, 29, 237, 8, 29, 1, 29, 3, 29, 240, 8, 29, 1, 29, 1, 29, 1, 30, 1, 30, 3, 30, 246, 8, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 5, 31, 253, 8, 31, 10, 31, 12, 31, 256, 9, 31, 3, 31, 258, 8, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 267, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 273, 8, 32, 10, 32, 12, 32, 276, 9, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 0, 1, 64, 39, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 0, 6, 1, 0, 5, 6, 1, 0, 2, 4, 2, 0, 8, 10, 44, 44, 2, 0, 40, 43, 45, 45, 2, 0, 29, 29, 34, 34, 2, 0, 27, 33, 35, 36, 282, 0, 78, 1, 0, 0, 0, 2, 81, 1, 0, 0, 0, 4, 98, 1, 0, 0, 0, 6, 100, 1, 0, 0, 0, 8, 104, 1, 0, 0, 0, 10, 113, 1, 0, 0, 0, 12, 115, 1, 0, 0, 0, 14, 118, 1, 0, 0, 0, 16, 120, 1, 0, 0, 0, 18, 127, 1, 0, 0, 0, 20, 131, 1, 0, 0, 0, 22, 133, 1, 0, 0, 0, 24, 143, 1, 0, 0, 0, 26, 145, 1, 0, 0, 0, 28, 148, 1, 0, 0, 0, 30, 150, 1, 0, 0, 0, 32, 160, 1, 0, 0, 0, 34, 162, 1, 0, 0, 0, 36, 174, 1, 0, 0, 0, 38, 176, 1, 0, 0, 0, 40, 181, 1, 0, 0, 0, 42, 189, 1, 0, 0, 0, 44, 191, 1, 0, 0, 0, 46, 200, 1, 0, 0, 0, 48, 204, 1, 0, 0, 0, 50, 212, 1, 0, 0, 0, 52, 217, 1, 0, 0, 0, 54, 225, 1, 0, 0, 0, 56, 229, 1, 0, 0, 0, 58, 239, 1, 0, 0, 0, 60, 243, 1, 0, 0, 0, 62, 257, 1, 0, 0, 0, 64, 266, 1, 0, 0, 0, 66, 277, 1, 0, 0, 0, 68, 281, 1, 0, 0, 0, 70, 284, 1, 0, 0, 0, 72, 289, 1, 0, 0, 0, 74, 291, 1, 0, 0, 0, 76, 293, 1, 0, 0, 0, 78, 79, 3, 2, 1, 0, 79, 80, 5, 0, 0, 1, 80, 1, 1, 0, 0, 0, 81, 82, 5, 1, 0, 0, 82, 83, 3, 4, 2, 0, 83, 87, 5, 18, 0, 0, 84, 86, 3, 6, 3, 0, 85, 84, 1, 0, 0, 0, 86, 89, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 93, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 90, 92, 3, 12, 6, 0, 91, 90, 1, 0, 0, 0, 92, 95, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 96, 1, 0, 0, 0, 95, 93, 1, 0, 0, 0, 96, 97, 3, 32, 16, 0, 97, 3, 1, 0, 0, 0, 98, 99, 5, 44, 0, 0, 99, 5, 1, 0, 0, 0, 100, 101, 7, 0, 0, 0, 101, 102, 3, 8, 4, 0, 102, 103, 5, 26, 0, 0, 103, 7, 1, 0, 0, 0, 104, 105, 3, 22, 11, 0, 105, 110, 3, 10, 5, 0, 106, 107, 5, 25, 0, 0, 107, 109, 3, 10, 5, 0, 108, 106, 1, 0, 0, 0, 109, 112, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 110, 111, 1, 0, 0, 0, 111, 9, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 113, 114, 5, 44, 0, 0, 114, 11, 1, 0, 0, 0, 115, 116, 3, 14, 7, 0, 116, 117, 3, 16, 8, 0, 117, 13, 1, 0, 0, 0, 118, 119, 7, 1, 0, 0, 119, 15, 1, 0, 0, 0, 120, 121, 3, 20, 10, 0, 121, 122, 3, 18, 9, 0, 122, 123, 5, 20, 0, 0, 123, 124, 3, 24, 12, 0, 124, 125, 5, 21, 0, 0, 125, 126, 3, 30, 15, 0, 126, 17, 1, 0, 0, 0, 127, 128, 5, 44, 0, 0, 128, 19, 1, 0, 0, 0, 129, 132, 3, 22, 11, 0, 130, 132, 5, 11, 0, 0, 131, 129, 1, 0, 0, 0, 131, 130, 1, 0, 0, 0, 132, 21, 1, 0, 0, 0, 133, 134, 7, 2, 0, 0, 134, 23, 1, 0, 0, 0, 135, 140, 3, 26, 13, 0, 136, 137, 5, 25, 0, 0, 137, 139, 3, 26, 13, 0, 138, 136, 1, 0, 0, 0, 139, 142, 1, 0, 0, 0, 140, 138, 1, 0, 0, 0, 140, 141, 1, 0, 0, 0, 141, 144, 1, 0, 0, 0, 142, 140, 1, 0, 0, 0, 143, 135, 1, 0, 0, 0, 143, 144, 1, 0, 0, 0, 144, 25, 1, 0, 0, 0, 145, 146, 3, 22, 11, 0, 146, 147, 3, 28, 14, 0, 147, 27, 1, 0, 0, 0, 148, 149, 5, 44, 0, 0, 149, 29, 1, 0, 0, 0, 150, 154, 5, 18, 0, 0, 151, 153, 3, 34, 17, 0, 152, 151, 1, 0, 0, 0, 153, 156, 1, 0, 0, 0, 154, 152, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 157, 1, 0, 0, 0, 156, 154, 1, 0, 0, 0, 157, 158, 3, 40, 20, 0, 158, 159, 3, 32, 16, 0, 159, 31, 1, 0, 0, 0, 160, 161, 5, 19, 0, 0, 161, 33, 1, 0, 0, 0, 162, 163, 5, 7, 0, 0, 163, 164, 3, 22, 11, 0, 164, 169, 3, 36, 18, 0, 165, 166, 5, 25, 0, 0, 166, 168, 3, 36, 18, 0, 167, 165, 1, 0, 0, 0, 168, 171, 1, 0, 0, 0, 169, 167, 1, 0, 0, 0, 169, 170, 1, 0, 0, 0, 170, 172, 1, 0, 0, 0, 171, 169, 1, 0, 0, 0, 172, 173, 5, 26, 0, 0, 173, 35, 1, 0, 0, 0, 174, 175, 5, 44, 0, 0, 175, 37, 1, 0, 0, 0, 176, 177, 5, 44, 0, 0, 177, 39, 1, 0, 0, 0, 178, 180, 3, 42, 21, 0, 179, 178, 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 41, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 190, 3, 44, 22, 0, 185, 190, 3, 46, 23, 0, 186, 190, 3, 52, 26, 0, 187, 190, 3, 54, 27, 0, 188, 190, 3, 60, 30, 0, 189, 184, 1, 0, 0, 0, 189, 185, 1, 0, 0, 0, 189, 186, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 188, 1, 0, 0, 0, 190, 43, 1, 0, 0, 0, 191, 194, 5, 12, 0, 0, 192, 195, 3, 38, 19, 0, 193, 195, 3, 70, 35, 0, 194, 192, 1, 0, 0, 0, 194, 193, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 197, 5, 27, 0, 0, 197, 198, 3, 64, 32, 0, 198, 199, 5, 26, 0, 0, 199, 45, 1, 0, 0, 0, 200, 202, 3, 48, 24, 0, 201, 203, 3, 50, 25, 0, 202, 201, 1, 0, 0, 0, 202, 203, 1, 0, 0, 0, 203, 47, 1, 0, 0, 0, 204, 205, 5, 14, 0, 0, 205, 206, 5, 20, 0, 0, 206, 207, 3, 64, 32, 0, 207, 208, 5, 21, 0, 0, 208, 209, 5, 18, 0, 0, 209, 210, 3, 40, 20, 0, 210, 211, 3, 32, 16, 0, 211, 49, 1, 0, 0, 0, 212, 213, 5, 15, 0, 0, 213, 214, 5, 18, 0, 0, 214, 215, 3, 40, 20, 0, 215, 216, 3, 32, 16, 0, 216, 51, 1, 0, 0, 0, 217, 218, 5, 16, 0, 0, 218, 219, 5, 20, 0, 0, 219, 220, 3, 64, 32, 0, 220, 221, 5, 21, 0, 0, 221, 222, 5, 18, 0, 0, 222, 223, 3, 40, 20, 0, 223, 224, 3, 32, 16, 0, 224, 53, 1, 0, 0, 0, 225, 226, 5, 13, 0, 0, 226, 227, 3, 56, 28, 0, 227, 228, 5, 26, 0, 0, 228, 55, 1, 0, 0, 0, 229, 230, 3, 58, 29, 0, 230, 231, 5, 20, 0, 0, 231, 232, 3, 62, 31, 0, 232, 233, 5, 21, 0, 0, 233, 57, 1, 0, 0, 0, 234, 237, 3, 4, 2, 0, 235, 237, 5, 43, 0, 0, 236, 234, 1, 0, 0, 0, 236, 235, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 240, 5, 24, 0, 0, 239, 236, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 242, 3, 18, 9, 0, 242, 59, 1, 0, 0, 0, 243, 245, 5, 17, 0, 0, 244, 246, 3, 64, 32, 0, 245, 244, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 248, 5, 26, 0, 0, 248, 61, 1, 0, 0, 0, 249, 254, 3, 64, 32, 0, 250, 251, 5, 25, 0, 0, 251, 253, 3, 64, 32, 0, 252, 250, 1, 0, 0, 0, 253, 256, 1, 0, 0, 0, 254, 252, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 258, 1, 0, 0, 0, 256, 254, 1, 0, 0, 0, 257, 249, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 63, 1, 0, 0, 0, 259, 260, 6, 32, -1, 0, 260, 267, 3, 72, 36, 0, 261, 267, 3, 38, 19, 0, 262, 267, 3, 56, 28, 0, 263, 267, 3, 70, 35, 0, 264, 267, 3, 68, 34, 0, 265, 267, 3, 66, 33, 0, 266, 259, 1, 0, 0, 0, 266, 261, 1, 0, 0, 0, 266, 262, 1, 0, 0, 0, 266, 263, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 266, 265, 1, 0, 0, 0, 267, 274, 1, 0, 0, 0, 268, 269, 10, 7, 0, 0, 269, 270, 3, 76, 38, 0, 270, 271, 3, 64, 32, 8, 271, 273, 1, 0, 0, 0, 272, 268, 1, 0, 0, 0, 273, 276, 1, 0, 0, 0, 274, 272, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 65, 1, 0, 0, 0, 276, 274, 1, 0, 0, 0, 277, 278, 5, 20, 0, 0, 278, 279, 3, 64, 32, 0, 279, 280, 5, 21, 0, 0, 280, 67, 1, 0, 0, 0, 281, 282, 3, 74, 37, 0, 282, 283, 3, 64, 32, 0, 283, 69, 1, 0, 0, 0, 284, 285, 3, 38, 19, 0, 285, 286, 5, 22, 0, 0, 286, 287, 3, 64, 32, 0, 287, 288, 5, 23, 0, 0, 288, 71, 1, 0, 0, 0, 289, 290, 7, 3, 0, 0, 290, 73, 1, 0, 0, 0, 291, 292, 7, 4, 0, 0, 292, 75, 1, 0, 0, 0, 293, 294, 7, 5, 0, 0, 294, 77, 1, 0, 0, 0, 19, 87, 93, 110, 131, 140, 143, 154, 169, 181, 189, 194, 202, 236, 239, 245, 254, 257, 266, 274] \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackParser.java b/compiler/grammar/.antlr/JackParser.java new file mode 100644 index 00000000..9b114a26 --- /dev/null +++ b/compiler/grammar/.antlr/JackParser.java @@ -0,0 +1,2239 @@ +// Generated from /home/babkamen/git/nand2tetris/tools/web-ide/compiler/grammar/JackParser.g4 by ANTLR 4.13.1 +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"}) +public class JackParser extends Parser { + static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + CLASS=1, CONSTRUCTOR=2, FUNCTION=3, METHOD=4, FIELD=5, STATIC=6, VAR=7, + INT=8, CHAR=9, BOOLEAN=10, VOID=11, LET=12, DO=13, IF=14, ELSE=15, WHILE=16, + RETURN=17, LBRACE=18, RBRACE=19, LPAREN=20, RPAREN=21, LBRACKET=22, RBRACKET=23, + DOT=24, COMMA=25, SEMICOLON=26, EQUALS=27, PLUS=28, MINUS=29, MUL=30, + DIV=31, AND=32, OR=33, TILDE=34, LESS_THAN=35, GREATER_THAN=36, WS=37, + COMMENT=38, LINE_COMMENT=39, INTEGER_LITERAL=40, BOOLEAN_LITERAL=41, NULL_LITERAL=42, + THIS_LITERAL=43, IDENTIFIER=44, STRING_LITERAL=45, UnterminatedStringLiteral=46; + public static final int + RULE_program = 0, RULE_classDeclaration = 1, RULE_className = 2, RULE_classVarDec = 3, + RULE_fieldList = 4, RULE_fieldName = 5, RULE_subroutineDeclaration = 6, + RULE_subroutineType = 7, RULE_subroutineDecWithoutType = 8, RULE_subroutineName = 9, + RULE_subroutineReturnType = 10, RULE_varType = 11, RULE_parameterList = 12, + RULE_parameter = 13, RULE_parameterName = 14, RULE_subroutineBody = 15, + RULE_rBrace = 16, RULE_varDeclaration = 17, RULE_varNameInDeclaration = 18, + RULE_varName = 19, RULE_statements = 20, RULE_statement = 21, RULE_letStatement = 22, + RULE_ifElseStatement = 23, RULE_ifStatement = 24, RULE_elseStatement = 25, + RULE_whileStatement = 26, RULE_doStatement = 27, RULE_subroutineCall = 28, + RULE_subroutineId = 29, RULE_returnStatement = 30, RULE_expressionList = 31, + RULE_expression = 32, RULE_groupedExpression = 33, RULE_unaryOp = 34, + RULE_arrayAccess = 35, RULE_constant = 36, RULE_unaryOperator = 37, RULE_binaryOperator = 38; + private static String[] makeRuleNames() { + return new String[] { + "program", "classDeclaration", "className", "classVarDec", "fieldList", + "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", + "subroutineName", "subroutineReturnType", "varType", "parameterList", + "parameter", "parameterName", "subroutineBody", "rBrace", "varDeclaration", + "varNameInDeclaration", "varName", "statements", "statement", "letStatement", + "ifElseStatement", "ifStatement", "elseStatement", "whileStatement", + "doStatement", "subroutineCall", "subroutineId", "returnStatement", "expressionList", + "expression", "groupedExpression", "unaryOp", "arrayAccess", "constant", + "unaryOperator", "binaryOperator" + }; + } + public static final String[] ruleNames = makeRuleNames(); + + private static String[] makeLiteralNames() { + return new String[] { + null, "'class'", "'constructor'", "'function'", "'method'", "'field'", + "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", + "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", + "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", + "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", null, null, null, null, null, + "'null'", "'this'" + }; + } + private static final String[] _LITERAL_NAMES = makeLiteralNames(); + private static String[] makeSymbolicNames() { + return new String[] { + null, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", + "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", + "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", + "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", + "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", + "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", + "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral" + }; + } + private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "JackParser.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + public JackParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @SuppressWarnings("CheckReturnValue") + public static class ProgramContext extends ParserRuleContext { + public ClassDeclarationContext classDeclaration() { + return getRuleContext(ClassDeclarationContext.class,0); + } + public TerminalNode EOF() { return getToken(JackParser.EOF, 0); } + public ProgramContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_program; } + } + + public final ProgramContext program() throws RecognitionException { + ProgramContext _localctx = new ProgramContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_program); + try { + enterOuterAlt(_localctx, 1); + { + setState(78); + classDeclaration(); + setState(79); + match(EOF); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassDeclarationContext extends ParserRuleContext { + public TerminalNode CLASS() { return getToken(JackParser.CLASS, 0); } + public ClassNameContext className() { + return getRuleContext(ClassNameContext.class,0); + } + public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } + public RBraceContext rBrace() { + return getRuleContext(RBraceContext.class,0); + } + public List classVarDec() { + return getRuleContexts(ClassVarDecContext.class); + } + public ClassVarDecContext classVarDec(int i) { + return getRuleContext(ClassVarDecContext.class,i); + } + public List subroutineDeclaration() { + return getRuleContexts(SubroutineDeclarationContext.class); + } + public SubroutineDeclarationContext subroutineDeclaration(int i) { + return getRuleContext(SubroutineDeclarationContext.class,i); + } + public ClassDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_classDeclaration; } + } + + public final ClassDeclarationContext classDeclaration() throws RecognitionException { + ClassDeclarationContext _localctx = new ClassDeclarationContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_classDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(81); + match(CLASS); + setState(82); + className(); + setState(83); + match(LBRACE); + setState(87); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==FIELD || _la==STATIC) { + { + { + setState(84); + classVarDec(); + } + } + setState(89); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(93); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 28L) != 0)) { + { + { + setState(90); + subroutineDeclaration(); + } + } + setState(95); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(96); + rBrace(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassNameContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } + public ClassNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_className; } + } + + public final ClassNameContext className() throws RecognitionException { + ClassNameContext _localctx = new ClassNameContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_className); + try { + enterOuterAlt(_localctx, 1); + { + setState(98); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ClassVarDecContext extends ParserRuleContext { + public FieldListContext fieldList() { + return getRuleContext(FieldListContext.class,0); + } + public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } + public TerminalNode STATIC() { return getToken(JackParser.STATIC, 0); } + public TerminalNode FIELD() { return getToken(JackParser.FIELD, 0); } + public ClassVarDecContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_classVarDec; } + } + + public final ClassVarDecContext classVarDec() throws RecognitionException { + ClassVarDecContext _localctx = new ClassVarDecContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_classVarDec); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(100); + _la = _input.LA(1); + if ( !(_la==FIELD || _la==STATIC) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(101); + fieldList(); + setState(102); + match(SEMICOLON); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class FieldListContext extends ParserRuleContext { + public VarTypeContext varType() { + return getRuleContext(VarTypeContext.class,0); + } + public List fieldName() { + return getRuleContexts(FieldNameContext.class); + } + public FieldNameContext fieldName(int i) { + return getRuleContext(FieldNameContext.class,i); + } + public List COMMA() { return getTokens(JackParser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(JackParser.COMMA, i); + } + public FieldListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_fieldList; } + } + + public final FieldListContext fieldList() throws RecognitionException { + FieldListContext _localctx = new FieldListContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_fieldList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(104); + varType(); + setState(105); + fieldName(); + setState(110); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==COMMA) { + { + { + setState(106); + match(COMMA); + setState(107); + fieldName(); + } + } + setState(112); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class FieldNameContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } + public FieldNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_fieldName; } + } + + public final FieldNameContext fieldName() throws RecognitionException { + FieldNameContext _localctx = new FieldNameContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_fieldName); + try { + enterOuterAlt(_localctx, 1); + { + setState(113); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SubroutineDeclarationContext extends ParserRuleContext { + public SubroutineTypeContext subroutineType() { + return getRuleContext(SubroutineTypeContext.class,0); + } + public SubroutineDecWithoutTypeContext subroutineDecWithoutType() { + return getRuleContext(SubroutineDecWithoutTypeContext.class,0); + } + public SubroutineDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_subroutineDeclaration; } + } + + public final SubroutineDeclarationContext subroutineDeclaration() throws RecognitionException { + SubroutineDeclarationContext _localctx = new SubroutineDeclarationContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_subroutineDeclaration); + try { + enterOuterAlt(_localctx, 1); + { + setState(115); + subroutineType(); + setState(116); + subroutineDecWithoutType(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SubroutineTypeContext extends ParserRuleContext { + public TerminalNode CONSTRUCTOR() { return getToken(JackParser.CONSTRUCTOR, 0); } + public TerminalNode METHOD() { return getToken(JackParser.METHOD, 0); } + public TerminalNode FUNCTION() { return getToken(JackParser.FUNCTION, 0); } + public SubroutineTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_subroutineType; } + } + + public final SubroutineTypeContext subroutineType() throws RecognitionException { + SubroutineTypeContext _localctx = new SubroutineTypeContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_subroutineType); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(118); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 28L) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SubroutineDecWithoutTypeContext extends ParserRuleContext { + public SubroutineReturnTypeContext subroutineReturnType() { + return getRuleContext(SubroutineReturnTypeContext.class,0); + } + public SubroutineNameContext subroutineName() { + return getRuleContext(SubroutineNameContext.class,0); + } + public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } + public ParameterListContext parameterList() { + return getRuleContext(ParameterListContext.class,0); + } + public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } + public SubroutineBodyContext subroutineBody() { + return getRuleContext(SubroutineBodyContext.class,0); + } + public SubroutineDecWithoutTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_subroutineDecWithoutType; } + } + + public final SubroutineDecWithoutTypeContext subroutineDecWithoutType() throws RecognitionException { + SubroutineDecWithoutTypeContext _localctx = new SubroutineDecWithoutTypeContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_subroutineDecWithoutType); + try { + enterOuterAlt(_localctx, 1); + { + setState(120); + subroutineReturnType(); + setState(121); + subroutineName(); + setState(122); + match(LPAREN); + setState(123); + parameterList(); + setState(124); + match(RPAREN); + setState(125); + subroutineBody(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SubroutineNameContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } + public SubroutineNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_subroutineName; } + } + + public final SubroutineNameContext subroutineName() throws RecognitionException { + SubroutineNameContext _localctx = new SubroutineNameContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_subroutineName); + try { + enterOuterAlt(_localctx, 1); + { + setState(127); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SubroutineReturnTypeContext extends ParserRuleContext { + public VarTypeContext varType() { + return getRuleContext(VarTypeContext.class,0); + } + public TerminalNode VOID() { return getToken(JackParser.VOID, 0); } + public SubroutineReturnTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_subroutineReturnType; } + } + + public final SubroutineReturnTypeContext subroutineReturnType() throws RecognitionException { + SubroutineReturnTypeContext _localctx = new SubroutineReturnTypeContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_subroutineReturnType); + try { + setState(131); + _errHandler.sync(this); + switch (_input.LA(1)) { + case INT: + case CHAR: + case BOOLEAN: + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(129); + varType(); + } + break; + case VOID: + enterOuterAlt(_localctx, 2); + { + setState(130); + match(VOID); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VarTypeContext extends ParserRuleContext { + public TerminalNode INT() { return getToken(JackParser.INT, 0); } + public TerminalNode CHAR() { return getToken(JackParser.CHAR, 0); } + public TerminalNode BOOLEAN() { return getToken(JackParser.BOOLEAN, 0); } + public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } + public VarTypeContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_varType; } + } + + public final VarTypeContext varType() throws RecognitionException { + VarTypeContext _localctx = new VarTypeContext(_ctx, getState()); + enterRule(_localctx, 22, RULE_varType); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(133); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 17592186046208L) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ParameterListContext extends ParserRuleContext { + public List parameter() { + return getRuleContexts(ParameterContext.class); + } + public ParameterContext parameter(int i) { + return getRuleContext(ParameterContext.class,i); + } + public List COMMA() { return getTokens(JackParser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(JackParser.COMMA, i); + } + public ParameterListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_parameterList; } + } + + public final ParameterListContext parameterList() throws RecognitionException { + ParameterListContext _localctx = new ParameterListContext(_ctx, getState()); + enterRule(_localctx, 24, RULE_parameterList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(143); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & 17592186046208L) != 0)) { + { + setState(135); + parameter(); + setState(140); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==COMMA) { + { + { + setState(136); + match(COMMA); + setState(137); + parameter(); + } + } + setState(142); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ParameterContext extends ParserRuleContext { + public VarTypeContext varType() { + return getRuleContext(VarTypeContext.class,0); + } + public ParameterNameContext parameterName() { + return getRuleContext(ParameterNameContext.class,0); + } + public ParameterContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_parameter; } + } + + public final ParameterContext parameter() throws RecognitionException { + ParameterContext _localctx = new ParameterContext(_ctx, getState()); + enterRule(_localctx, 26, RULE_parameter); + try { + enterOuterAlt(_localctx, 1); + { + setState(145); + varType(); + setState(146); + parameterName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ParameterNameContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } + public ParameterNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_parameterName; } + } + + public final ParameterNameContext parameterName() throws RecognitionException { + ParameterNameContext _localctx = new ParameterNameContext(_ctx, getState()); + enterRule(_localctx, 28, RULE_parameterName); + try { + enterOuterAlt(_localctx, 1); + { + setState(148); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SubroutineBodyContext extends ParserRuleContext { + public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } + public StatementsContext statements() { + return getRuleContext(StatementsContext.class,0); + } + public RBraceContext rBrace() { + return getRuleContext(RBraceContext.class,0); + } + public List varDeclaration() { + return getRuleContexts(VarDeclarationContext.class); + } + public VarDeclarationContext varDeclaration(int i) { + return getRuleContext(VarDeclarationContext.class,i); + } + public SubroutineBodyContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_subroutineBody; } + } + + public final SubroutineBodyContext subroutineBody() throws RecognitionException { + SubroutineBodyContext _localctx = new SubroutineBodyContext(_ctx, getState()); + enterRule(_localctx, 30, RULE_subroutineBody); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(150); + match(LBRACE); + setState(154); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==VAR) { + { + { + setState(151); + varDeclaration(); + } + } + setState(156); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(157); + statements(); + setState(158); + rBrace(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class RBraceContext extends ParserRuleContext { + public TerminalNode RBRACE() { return getToken(JackParser.RBRACE, 0); } + public RBraceContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_rBrace; } + } + + public final RBraceContext rBrace() throws RecognitionException { + RBraceContext _localctx = new RBraceContext(_ctx, getState()); + enterRule(_localctx, 32, RULE_rBrace); + try { + enterOuterAlt(_localctx, 1); + { + setState(160); + match(RBRACE); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VarDeclarationContext extends ParserRuleContext { + public TerminalNode VAR() { return getToken(JackParser.VAR, 0); } + public VarTypeContext varType() { + return getRuleContext(VarTypeContext.class,0); + } + public List varNameInDeclaration() { + return getRuleContexts(VarNameInDeclarationContext.class); + } + public VarNameInDeclarationContext varNameInDeclaration(int i) { + return getRuleContext(VarNameInDeclarationContext.class,i); + } + public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } + public List COMMA() { return getTokens(JackParser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(JackParser.COMMA, i); + } + public VarDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_varDeclaration; } + } + + public final VarDeclarationContext varDeclaration() throws RecognitionException { + VarDeclarationContext _localctx = new VarDeclarationContext(_ctx, getState()); + enterRule(_localctx, 34, RULE_varDeclaration); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(162); + match(VAR); + setState(163); + varType(); + setState(164); + varNameInDeclaration(); + setState(169); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==COMMA) { + { + { + setState(165); + match(COMMA); + setState(166); + varNameInDeclaration(); + } + } + setState(171); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(172); + match(SEMICOLON); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VarNameInDeclarationContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } + public VarNameInDeclarationContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_varNameInDeclaration; } + } + + public final VarNameInDeclarationContext varNameInDeclaration() throws RecognitionException { + VarNameInDeclarationContext _localctx = new VarNameInDeclarationContext(_ctx, getState()); + enterRule(_localctx, 36, RULE_varNameInDeclaration); + try { + enterOuterAlt(_localctx, 1); + { + setState(174); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class VarNameContext extends ParserRuleContext { + public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } + public VarNameContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_varName; } + } + + public final VarNameContext varName() throws RecognitionException { + VarNameContext _localctx = new VarNameContext(_ctx, getState()); + enterRule(_localctx, 38, RULE_varName); + try { + enterOuterAlt(_localctx, 1); + { + setState(176); + match(IDENTIFIER); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class StatementsContext extends ParserRuleContext { + public List statement() { + return getRuleContexts(StatementContext.class); + } + public StatementContext statement(int i) { + return getRuleContext(StatementContext.class,i); + } + public StatementsContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_statements; } + } + + public final StatementsContext statements() throws RecognitionException { + StatementsContext _localctx = new StatementsContext(_ctx, getState()); + enterRule(_localctx, 40, RULE_statements); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(181); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 225280L) != 0)) { + { + { + setState(178); + statement(); + } + } + setState(183); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class StatementContext extends ParserRuleContext { + public LetStatementContext letStatement() { + return getRuleContext(LetStatementContext.class,0); + } + public IfElseStatementContext ifElseStatement() { + return getRuleContext(IfElseStatementContext.class,0); + } + public WhileStatementContext whileStatement() { + return getRuleContext(WhileStatementContext.class,0); + } + public DoStatementContext doStatement() { + return getRuleContext(DoStatementContext.class,0); + } + public ReturnStatementContext returnStatement() { + return getRuleContext(ReturnStatementContext.class,0); + } + public StatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_statement; } + } + + public final StatementContext statement() throws RecognitionException { + StatementContext _localctx = new StatementContext(_ctx, getState()); + enterRule(_localctx, 42, RULE_statement); + try { + setState(189); + _errHandler.sync(this); + switch (_input.LA(1)) { + case LET: + enterOuterAlt(_localctx, 1); + { + setState(184); + letStatement(); + } + break; + case IF: + enterOuterAlt(_localctx, 2); + { + setState(185); + ifElseStatement(); + } + break; + case WHILE: + enterOuterAlt(_localctx, 3); + { + setState(186); + whileStatement(); + } + break; + case DO: + enterOuterAlt(_localctx, 4); + { + setState(187); + doStatement(); + } + break; + case RETURN: + enterOuterAlt(_localctx, 5); + { + setState(188); + returnStatement(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class LetStatementContext extends ParserRuleContext { + public TerminalNode LET() { return getToken(JackParser.LET, 0); } + public TerminalNode EQUALS() { return getToken(JackParser.EQUALS, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } + public VarNameContext varName() { + return getRuleContext(VarNameContext.class,0); + } + public ArrayAccessContext arrayAccess() { + return getRuleContext(ArrayAccessContext.class,0); + } + public LetStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_letStatement; } + } + + public final LetStatementContext letStatement() throws RecognitionException { + LetStatementContext _localctx = new LetStatementContext(_ctx, getState()); + enterRule(_localctx, 44, RULE_letStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(191); + match(LET); + setState(194); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { + case 1: + { + setState(192); + varName(); + } + break; + case 2: + { + setState(193); + arrayAccess(); + } + break; + } + setState(196); + match(EQUALS); + setState(197); + expression(0); + setState(198); + match(SEMICOLON); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class IfElseStatementContext extends ParserRuleContext { + public IfStatementContext ifStatement() { + return getRuleContext(IfStatementContext.class,0); + } + public ElseStatementContext elseStatement() { + return getRuleContext(ElseStatementContext.class,0); + } + public IfElseStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_ifElseStatement; } + } + + public final IfElseStatementContext ifElseStatement() throws RecognitionException { + IfElseStatementContext _localctx = new IfElseStatementContext(_ctx, getState()); + enterRule(_localctx, 46, RULE_ifElseStatement); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(200); + ifStatement(); + setState(202); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==ELSE) { + { + setState(201); + elseStatement(); + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class IfStatementContext extends ParserRuleContext { + public TerminalNode IF() { return getToken(JackParser.IF, 0); } + public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } + public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } + public StatementsContext statements() { + return getRuleContext(StatementsContext.class,0); + } + public RBraceContext rBrace() { + return getRuleContext(RBraceContext.class,0); + } + public IfStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_ifStatement; } + } + + public final IfStatementContext ifStatement() throws RecognitionException { + IfStatementContext _localctx = new IfStatementContext(_ctx, getState()); + enterRule(_localctx, 48, RULE_ifStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(204); + match(IF); + setState(205); + match(LPAREN); + setState(206); + expression(0); + setState(207); + match(RPAREN); + setState(208); + match(LBRACE); + setState(209); + statements(); + setState(210); + rBrace(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ElseStatementContext extends ParserRuleContext { + public TerminalNode ELSE() { return getToken(JackParser.ELSE, 0); } + public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } + public StatementsContext statements() { + return getRuleContext(StatementsContext.class,0); + } + public RBraceContext rBrace() { + return getRuleContext(RBraceContext.class,0); + } + public ElseStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_elseStatement; } + } + + public final ElseStatementContext elseStatement() throws RecognitionException { + ElseStatementContext _localctx = new ElseStatementContext(_ctx, getState()); + enterRule(_localctx, 50, RULE_elseStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(212); + match(ELSE); + setState(213); + match(LBRACE); + setState(214); + statements(); + setState(215); + rBrace(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class WhileStatementContext extends ParserRuleContext { + public TerminalNode WHILE() { return getToken(JackParser.WHILE, 0); } + public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } + public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } + public StatementsContext statements() { + return getRuleContext(StatementsContext.class,0); + } + public RBraceContext rBrace() { + return getRuleContext(RBraceContext.class,0); + } + public WhileStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_whileStatement; } + } + + public final WhileStatementContext whileStatement() throws RecognitionException { + WhileStatementContext _localctx = new WhileStatementContext(_ctx, getState()); + enterRule(_localctx, 52, RULE_whileStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(217); + match(WHILE); + setState(218); + match(LPAREN); + setState(219); + expression(0); + setState(220); + match(RPAREN); + setState(221); + match(LBRACE); + setState(222); + statements(); + setState(223); + rBrace(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class DoStatementContext extends ParserRuleContext { + public TerminalNode DO() { return getToken(JackParser.DO, 0); } + public SubroutineCallContext subroutineCall() { + return getRuleContext(SubroutineCallContext.class,0); + } + public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } + public DoStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_doStatement; } + } + + public final DoStatementContext doStatement() throws RecognitionException { + DoStatementContext _localctx = new DoStatementContext(_ctx, getState()); + enterRule(_localctx, 54, RULE_doStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(225); + match(DO); + setState(226); + subroutineCall(); + setState(227); + match(SEMICOLON); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SubroutineCallContext extends ParserRuleContext { + public SubroutineIdContext subroutineId() { + return getRuleContext(SubroutineIdContext.class,0); + } + public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } + public ExpressionListContext expressionList() { + return getRuleContext(ExpressionListContext.class,0); + } + public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } + public SubroutineCallContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_subroutineCall; } + } + + public final SubroutineCallContext subroutineCall() throws RecognitionException { + SubroutineCallContext _localctx = new SubroutineCallContext(_ctx, getState()); + enterRule(_localctx, 56, RULE_subroutineCall); + try { + enterOuterAlt(_localctx, 1); + { + setState(229); + subroutineId(); + setState(230); + match(LPAREN); + setState(231); + expressionList(); + setState(232); + match(RPAREN); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class SubroutineIdContext extends ParserRuleContext { + public SubroutineNameContext subroutineName() { + return getRuleContext(SubroutineNameContext.class,0); + } + public TerminalNode DOT() { return getToken(JackParser.DOT, 0); } + public ClassNameContext className() { + return getRuleContext(ClassNameContext.class,0); + } + public TerminalNode THIS_LITERAL() { return getToken(JackParser.THIS_LITERAL, 0); } + public SubroutineIdContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_subroutineId; } + } + + public final SubroutineIdContext subroutineId() throws RecognitionException { + SubroutineIdContext _localctx = new SubroutineIdContext(_ctx, getState()); + enterRule(_localctx, 58, RULE_subroutineId); + try { + enterOuterAlt(_localctx, 1); + { + setState(239); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { + case 1: + { + setState(236); + _errHandler.sync(this); + switch (_input.LA(1)) { + case IDENTIFIER: + { + setState(234); + className(); + } + break; + case THIS_LITERAL: + { + setState(235); + match(THIS_LITERAL); + } + break; + default: + throw new NoViableAltException(this); + } + setState(238); + match(DOT); + } + break; + } + setState(241); + subroutineName(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ReturnStatementContext extends ParserRuleContext { + public TerminalNode RETURN() { return getToken(JackParser.RETURN, 0); } + public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public ReturnStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_returnStatement; } + } + + public final ReturnStatementContext returnStatement() throws RecognitionException { + ReturnStatementContext _localctx = new ReturnStatementContext(_ctx, getState()); + enterRule(_localctx, 60, RULE_returnStatement); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(243); + match(RETURN); + setState(245); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & 69286950338560L) != 0)) { + { + setState(244); + expression(0); + } + } + + setState(247); + match(SEMICOLON); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ExpressionListContext extends ParserRuleContext { + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public List COMMA() { return getTokens(JackParser.COMMA); } + public TerminalNode COMMA(int i) { + return getToken(JackParser.COMMA, i); + } + public ExpressionListContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_expressionList; } + } + + public final ExpressionListContext expressionList() throws RecognitionException { + ExpressionListContext _localctx = new ExpressionListContext(_ctx, getState()); + enterRule(_localctx, 62, RULE_expressionList); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(257); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & 69286950338560L) != 0)) { + { + setState(249); + expression(0); + setState(254); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==COMMA) { + { + { + setState(250); + match(COMMA); + setState(251); + expression(0); + } + } + setState(256); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ExpressionContext extends ParserRuleContext { + public ExpressionContext binaryOperation; + public ConstantContext constant() { + return getRuleContext(ConstantContext.class,0); + } + public VarNameContext varName() { + return getRuleContext(VarNameContext.class,0); + } + public SubroutineCallContext subroutineCall() { + return getRuleContext(SubroutineCallContext.class,0); + } + public ArrayAccessContext arrayAccess() { + return getRuleContext(ArrayAccessContext.class,0); + } + public UnaryOpContext unaryOp() { + return getRuleContext(UnaryOpContext.class,0); + } + public GroupedExpressionContext groupedExpression() { + return getRuleContext(GroupedExpressionContext.class,0); + } + public BinaryOperatorContext binaryOperator() { + return getRuleContext(BinaryOperatorContext.class,0); + } + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public ExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_expression; } + } + + public final ExpressionContext expression() throws RecognitionException { + return expression(0); + } + + private ExpressionContext expression(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState); + ExpressionContext _prevctx = _localctx; + int _startState = 64; + enterRecursionRule(_localctx, 64, RULE_expression, _p); + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(266); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) { + case 1: + { + setState(260); + constant(); + } + break; + case 2: + { + setState(261); + varName(); + } + break; + case 3: + { + setState(262); + subroutineCall(); + } + break; + case 4: + { + setState(263); + arrayAccess(); + } + break; + case 5: + { + setState(264); + unaryOp(); + } + break; + case 6: + { + setState(265); + groupedExpression(); + } + break; + } + _ctx.stop = _input.LT(-1); + setState(274); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,18,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + { + _localctx = new ExpressionContext(_parentctx, _parentState); + _localctx.binaryOperation = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(268); + if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); + setState(269); + binaryOperator(); + setState(270); + expression(8); + } + } + } + setState(276); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,18,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class GroupedExpressionContext extends ParserRuleContext { + public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } + public GroupedExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_groupedExpression; } + } + + public final GroupedExpressionContext groupedExpression() throws RecognitionException { + GroupedExpressionContext _localctx = new GroupedExpressionContext(_ctx, getState()); + enterRule(_localctx, 66, RULE_groupedExpression); + try { + enterOuterAlt(_localctx, 1); + { + setState(277); + match(LPAREN); + setState(278); + expression(0); + setState(279); + match(RPAREN); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class UnaryOpContext extends ParserRuleContext { + public UnaryOperatorContext unaryOperator() { + return getRuleContext(UnaryOperatorContext.class,0); + } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public UnaryOpContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_unaryOp; } + } + + public final UnaryOpContext unaryOp() throws RecognitionException { + UnaryOpContext _localctx = new UnaryOpContext(_ctx, getState()); + enterRule(_localctx, 68, RULE_unaryOp); + try { + enterOuterAlt(_localctx, 1); + { + setState(281); + unaryOperator(); + setState(282); + expression(0); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ArrayAccessContext extends ParserRuleContext { + public VarNameContext varName() { + return getRuleContext(VarNameContext.class,0); + } + public TerminalNode LBRACKET() { return getToken(JackParser.LBRACKET, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TerminalNode RBRACKET() { return getToken(JackParser.RBRACKET, 0); } + public ArrayAccessContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_arrayAccess; } + } + + public final ArrayAccessContext arrayAccess() throws RecognitionException { + ArrayAccessContext _localctx = new ArrayAccessContext(_ctx, getState()); + enterRule(_localctx, 70, RULE_arrayAccess); + try { + enterOuterAlt(_localctx, 1); + { + setState(284); + varName(); + setState(285); + match(LBRACKET); + setState(286); + expression(0); + setState(287); + match(RBRACKET); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class ConstantContext extends ParserRuleContext { + public TerminalNode INTEGER_LITERAL() { return getToken(JackParser.INTEGER_LITERAL, 0); } + public TerminalNode STRING_LITERAL() { return getToken(JackParser.STRING_LITERAL, 0); } + public TerminalNode BOOLEAN_LITERAL() { return getToken(JackParser.BOOLEAN_LITERAL, 0); } + public TerminalNode NULL_LITERAL() { return getToken(JackParser.NULL_LITERAL, 0); } + public TerminalNode THIS_LITERAL() { return getToken(JackParser.THIS_LITERAL, 0); } + public ConstantContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_constant; } + } + + public final ConstantContext constant() throws RecognitionException { + ConstantContext _localctx = new ConstantContext(_ctx, getState()); + enterRule(_localctx, 72, RULE_constant); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(289); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 51677046505472L) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class UnaryOperatorContext extends ParserRuleContext { + public TerminalNode TILDE() { return getToken(JackParser.TILDE, 0); } + public TerminalNode MINUS() { return getToken(JackParser.MINUS, 0); } + public UnaryOperatorContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_unaryOperator; } + } + + public final UnaryOperatorContext unaryOperator() throws RecognitionException { + UnaryOperatorContext _localctx = new UnaryOperatorContext(_ctx, getState()); + enterRule(_localctx, 74, RULE_unaryOperator); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(291); + _la = _input.LA(1); + if ( !(_la==MINUS || _la==TILDE) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + @SuppressWarnings("CheckReturnValue") + public static class BinaryOperatorContext extends ParserRuleContext { + public TerminalNode PLUS() { return getToken(JackParser.PLUS, 0); } + public TerminalNode MINUS() { return getToken(JackParser.MINUS, 0); } + public TerminalNode MUL() { return getToken(JackParser.MUL, 0); } + public TerminalNode DIV() { return getToken(JackParser.DIV, 0); } + public TerminalNode AND() { return getToken(JackParser.AND, 0); } + public TerminalNode OR() { return getToken(JackParser.OR, 0); } + public TerminalNode LESS_THAN() { return getToken(JackParser.LESS_THAN, 0); } + public TerminalNode GREATER_THAN() { return getToken(JackParser.GREATER_THAN, 0); } + public TerminalNode EQUALS() { return getToken(JackParser.EQUALS, 0); } + public BinaryOperatorContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_binaryOperator; } + } + + public final BinaryOperatorContext binaryOperator() throws RecognitionException { + BinaryOperatorContext _localctx = new BinaryOperatorContext(_ctx, getState()); + enterRule(_localctx, 76, RULE_binaryOperator); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(293); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 120124866560L) != 0)) ) { + _errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 32: + return expression_sempred((ExpressionContext)_localctx, predIndex); + } + return true; + } + private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return precpred(_ctx, 7); + } + return true; + } + + public static final String _serializedATN = + "\u0004\u0001.\u0128\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ + "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002"+ + "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002"+ + "\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b\u0002"+ + "\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e\u0002\u000f\u0007\u000f"+ + "\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011\u0002\u0012\u0007\u0012"+ + "\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014\u0002\u0015\u0007\u0015"+ + "\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017\u0002\u0018\u0007\u0018"+ + "\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a\u0002\u001b\u0007\u001b"+ + "\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d\u0002\u001e\u0007\u001e"+ + "\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007!\u0002\"\u0007\"\u0002"+ + "#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007&\u0001\u0000\u0001\u0000"+ + "\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0001"+ + "V\b\u0001\n\u0001\f\u0001Y\t\u0001\u0001\u0001\u0005\u0001\\\b\u0001\n"+ + "\u0001\f\u0001_\t\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002"+ + "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0004\u0001\u0004"+ + "\u0001\u0004\u0001\u0004\u0005\u0004m\b\u0004\n\u0004\f\u0004p\t\u0004"+ + "\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007"+ + "\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001"+ + "\t\u0001\t\u0001\n\u0001\n\u0003\n\u0084\b\n\u0001\u000b\u0001\u000b\u0001"+ + "\f\u0001\f\u0001\f\u0005\f\u008b\b\f\n\f\f\f\u008e\t\f\u0003\f\u0090\b"+ + "\f\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f"+ + "\u0005\u000f\u0099\b\u000f\n\u000f\f\u000f\u009c\t\u000f\u0001\u000f\u0001"+ + "\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001"+ + "\u0011\u0001\u0011\u0001\u0011\u0005\u0011\u00a8\b\u0011\n\u0011\f\u0011"+ + "\u00ab\t\u0011\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013"+ + "\u0001\u0013\u0001\u0014\u0005\u0014\u00b4\b\u0014\n\u0014\f\u0014\u00b7"+ + "\t\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0003"+ + "\u0015\u00be\b\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0003\u0016\u00c3"+ + "\b\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0001"+ + "\u0017\u0003\u0017\u00cb\b\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001"+ + "\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019\u0001"+ + "\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001"+ + "\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001"+ + "\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001"+ + "\u001c\u0001\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0003\u001d\u00ed"+ + "\b\u001d\u0001\u001d\u0003\u001d\u00f0\b\u001d\u0001\u001d\u0001\u001d"+ + "\u0001\u001e\u0001\u001e\u0003\u001e\u00f6\b\u001e\u0001\u001e\u0001\u001e"+ + "\u0001\u001f\u0001\u001f\u0001\u001f\u0005\u001f\u00fd\b\u001f\n\u001f"+ + "\f\u001f\u0100\t\u001f\u0003\u001f\u0102\b\u001f\u0001 \u0001 \u0001 "+ + "\u0001 \u0001 \u0001 \u0001 \u0003 \u010b\b \u0001 \u0001 \u0001 \u0001"+ + " \u0005 \u0111\b \n \f \u0114\t \u0001!\u0001!\u0001!\u0001!\u0001\"\u0001"+ + "\"\u0001\"\u0001#\u0001#\u0001#\u0001#\u0001#\u0001$\u0001$\u0001%\u0001"+ + "%\u0001&\u0001&\u0001&\u0000\u0001@\'\u0000\u0002\u0004\u0006\b\n\f\u000e"+ + "\u0010\u0012\u0014\u0016\u0018\u001a\u001c\u001e \"$&(*,.02468:<>@BDF"+ + "HJL\u0000\u0006\u0001\u0000\u0005\u0006\u0001\u0000\u0002\u0004\u0002"+ + "\u0000\b\n,,\u0002\u0000(+--\u0002\u0000\u001d\u001d\"\"\u0002\u0000\u001b"+ + "!#$\u011a\u0000N\u0001\u0000\u0000\u0000\u0002Q\u0001\u0000\u0000\u0000"+ + "\u0004b\u0001\u0000\u0000\u0000\u0006d\u0001\u0000\u0000\u0000\bh\u0001"+ + "\u0000\u0000\u0000\nq\u0001\u0000\u0000\u0000\fs\u0001\u0000\u0000\u0000"+ + "\u000ev\u0001\u0000\u0000\u0000\u0010x\u0001\u0000\u0000\u0000\u0012\u007f"+ + "\u0001\u0000\u0000\u0000\u0014\u0083\u0001\u0000\u0000\u0000\u0016\u0085"+ + "\u0001\u0000\u0000\u0000\u0018\u008f\u0001\u0000\u0000\u0000\u001a\u0091"+ + "\u0001\u0000\u0000\u0000\u001c\u0094\u0001\u0000\u0000\u0000\u001e\u0096"+ + "\u0001\u0000\u0000\u0000 \u00a0\u0001\u0000\u0000\u0000\"\u00a2\u0001"+ + "\u0000\u0000\u0000$\u00ae\u0001\u0000\u0000\u0000&\u00b0\u0001\u0000\u0000"+ + "\u0000(\u00b5\u0001\u0000\u0000\u0000*\u00bd\u0001\u0000\u0000\u0000,"+ + "\u00bf\u0001\u0000\u0000\u0000.\u00c8\u0001\u0000\u0000\u00000\u00cc\u0001"+ + "\u0000\u0000\u00002\u00d4\u0001\u0000\u0000\u00004\u00d9\u0001\u0000\u0000"+ + "\u00006\u00e1\u0001\u0000\u0000\u00008\u00e5\u0001\u0000\u0000\u0000:"+ + "\u00ef\u0001\u0000\u0000\u0000<\u00f3\u0001\u0000\u0000\u0000>\u0101\u0001"+ + "\u0000\u0000\u0000@\u010a\u0001\u0000\u0000\u0000B\u0115\u0001\u0000\u0000"+ + "\u0000D\u0119\u0001\u0000\u0000\u0000F\u011c\u0001\u0000\u0000\u0000H"+ + "\u0121\u0001\u0000\u0000\u0000J\u0123\u0001\u0000\u0000\u0000L\u0125\u0001"+ + "\u0000\u0000\u0000NO\u0003\u0002\u0001\u0000OP\u0005\u0000\u0000\u0001"+ + "P\u0001\u0001\u0000\u0000\u0000QR\u0005\u0001\u0000\u0000RS\u0003\u0004"+ + "\u0002\u0000SW\u0005\u0012\u0000\u0000TV\u0003\u0006\u0003\u0000UT\u0001"+ + "\u0000\u0000\u0000VY\u0001\u0000\u0000\u0000WU\u0001\u0000\u0000\u0000"+ + "WX\u0001\u0000\u0000\u0000X]\u0001\u0000\u0000\u0000YW\u0001\u0000\u0000"+ + "\u0000Z\\\u0003\f\u0006\u0000[Z\u0001\u0000\u0000\u0000\\_\u0001\u0000"+ + "\u0000\u0000][\u0001\u0000\u0000\u0000]^\u0001\u0000\u0000\u0000^`\u0001"+ + "\u0000\u0000\u0000_]\u0001\u0000\u0000\u0000`a\u0003 \u0010\u0000a\u0003"+ + "\u0001\u0000\u0000\u0000bc\u0005,\u0000\u0000c\u0005\u0001\u0000\u0000"+ + "\u0000de\u0007\u0000\u0000\u0000ef\u0003\b\u0004\u0000fg\u0005\u001a\u0000"+ + "\u0000g\u0007\u0001\u0000\u0000\u0000hi\u0003\u0016\u000b\u0000in\u0003"+ + "\n\u0005\u0000jk\u0005\u0019\u0000\u0000km\u0003\n\u0005\u0000lj\u0001"+ + "\u0000\u0000\u0000mp\u0001\u0000\u0000\u0000nl\u0001\u0000\u0000\u0000"+ + "no\u0001\u0000\u0000\u0000o\t\u0001\u0000\u0000\u0000pn\u0001\u0000\u0000"+ + "\u0000qr\u0005,\u0000\u0000r\u000b\u0001\u0000\u0000\u0000st\u0003\u000e"+ + "\u0007\u0000tu\u0003\u0010\b\u0000u\r\u0001\u0000\u0000\u0000vw\u0007"+ + "\u0001\u0000\u0000w\u000f\u0001\u0000\u0000\u0000xy\u0003\u0014\n\u0000"+ + "yz\u0003\u0012\t\u0000z{\u0005\u0014\u0000\u0000{|\u0003\u0018\f\u0000"+ + "|}\u0005\u0015\u0000\u0000}~\u0003\u001e\u000f\u0000~\u0011\u0001\u0000"+ + "\u0000\u0000\u007f\u0080\u0005,\u0000\u0000\u0080\u0013\u0001\u0000\u0000"+ + "\u0000\u0081\u0084\u0003\u0016\u000b\u0000\u0082\u0084\u0005\u000b\u0000"+ + "\u0000\u0083\u0081\u0001\u0000\u0000\u0000\u0083\u0082\u0001\u0000\u0000"+ + "\u0000\u0084\u0015\u0001\u0000\u0000\u0000\u0085\u0086\u0007\u0002\u0000"+ + "\u0000\u0086\u0017\u0001\u0000\u0000\u0000\u0087\u008c\u0003\u001a\r\u0000"+ + "\u0088\u0089\u0005\u0019\u0000\u0000\u0089\u008b\u0003\u001a\r\u0000\u008a"+ + "\u0088\u0001\u0000\u0000\u0000\u008b\u008e\u0001\u0000\u0000\u0000\u008c"+ + "\u008a\u0001\u0000\u0000\u0000\u008c\u008d\u0001\u0000\u0000\u0000\u008d"+ + "\u0090\u0001\u0000\u0000\u0000\u008e\u008c\u0001\u0000\u0000\u0000\u008f"+ + "\u0087\u0001\u0000\u0000\u0000\u008f\u0090\u0001\u0000\u0000\u0000\u0090"+ + "\u0019\u0001\u0000\u0000\u0000\u0091\u0092\u0003\u0016\u000b\u0000\u0092"+ + "\u0093\u0003\u001c\u000e\u0000\u0093\u001b\u0001\u0000\u0000\u0000\u0094"+ + "\u0095\u0005,\u0000\u0000\u0095\u001d\u0001\u0000\u0000\u0000\u0096\u009a"+ + "\u0005\u0012\u0000\u0000\u0097\u0099\u0003\"\u0011\u0000\u0098\u0097\u0001"+ + "\u0000\u0000\u0000\u0099\u009c\u0001\u0000\u0000\u0000\u009a\u0098\u0001"+ + "\u0000\u0000\u0000\u009a\u009b\u0001\u0000\u0000\u0000\u009b\u009d\u0001"+ + "\u0000\u0000\u0000\u009c\u009a\u0001\u0000\u0000\u0000\u009d\u009e\u0003"+ + "(\u0014\u0000\u009e\u009f\u0003 \u0010\u0000\u009f\u001f\u0001\u0000\u0000"+ + "\u0000\u00a0\u00a1\u0005\u0013\u0000\u0000\u00a1!\u0001\u0000\u0000\u0000"+ + "\u00a2\u00a3\u0005\u0007\u0000\u0000\u00a3\u00a4\u0003\u0016\u000b\u0000"+ + "\u00a4\u00a9\u0003$\u0012\u0000\u00a5\u00a6\u0005\u0019\u0000\u0000\u00a6"+ + "\u00a8\u0003$\u0012\u0000\u00a7\u00a5\u0001\u0000\u0000\u0000\u00a8\u00ab"+ + "\u0001\u0000\u0000\u0000\u00a9\u00a7\u0001\u0000\u0000\u0000\u00a9\u00aa"+ + "\u0001\u0000\u0000\u0000\u00aa\u00ac\u0001\u0000\u0000\u0000\u00ab\u00a9"+ + "\u0001\u0000\u0000\u0000\u00ac\u00ad\u0005\u001a\u0000\u0000\u00ad#\u0001"+ + "\u0000\u0000\u0000\u00ae\u00af\u0005,\u0000\u0000\u00af%\u0001\u0000\u0000"+ + "\u0000\u00b0\u00b1\u0005,\u0000\u0000\u00b1\'\u0001\u0000\u0000\u0000"+ + "\u00b2\u00b4\u0003*\u0015\u0000\u00b3\u00b2\u0001\u0000\u0000\u0000\u00b4"+ + "\u00b7\u0001\u0000\u0000\u0000\u00b5\u00b3\u0001\u0000\u0000\u0000\u00b5"+ + "\u00b6\u0001\u0000\u0000\u0000\u00b6)\u0001\u0000\u0000\u0000\u00b7\u00b5"+ + "\u0001\u0000\u0000\u0000\u00b8\u00be\u0003,\u0016\u0000\u00b9\u00be\u0003"+ + ".\u0017\u0000\u00ba\u00be\u00034\u001a\u0000\u00bb\u00be\u00036\u001b"+ + "\u0000\u00bc\u00be\u0003<\u001e\u0000\u00bd\u00b8\u0001\u0000\u0000\u0000"+ + "\u00bd\u00b9\u0001\u0000\u0000\u0000\u00bd\u00ba\u0001\u0000\u0000\u0000"+ + "\u00bd\u00bb\u0001\u0000\u0000\u0000\u00bd\u00bc\u0001\u0000\u0000\u0000"+ + "\u00be+\u0001\u0000\u0000\u0000\u00bf\u00c2\u0005\f\u0000\u0000\u00c0"+ + "\u00c3\u0003&\u0013\u0000\u00c1\u00c3\u0003F#\u0000\u00c2\u00c0\u0001"+ + "\u0000\u0000\u0000\u00c2\u00c1\u0001\u0000\u0000\u0000\u00c3\u00c4\u0001"+ + "\u0000\u0000\u0000\u00c4\u00c5\u0005\u001b\u0000\u0000\u00c5\u00c6\u0003"+ + "@ \u0000\u00c6\u00c7\u0005\u001a\u0000\u0000\u00c7-\u0001\u0000\u0000"+ + "\u0000\u00c8\u00ca\u00030\u0018\u0000\u00c9\u00cb\u00032\u0019\u0000\u00ca"+ + "\u00c9\u0001\u0000\u0000\u0000\u00ca\u00cb\u0001\u0000\u0000\u0000\u00cb"+ + "/\u0001\u0000\u0000\u0000\u00cc\u00cd\u0005\u000e\u0000\u0000\u00cd\u00ce"+ + "\u0005\u0014\u0000\u0000\u00ce\u00cf\u0003@ \u0000\u00cf\u00d0\u0005\u0015"+ + "\u0000\u0000\u00d0\u00d1\u0005\u0012\u0000\u0000\u00d1\u00d2\u0003(\u0014"+ + "\u0000\u00d2\u00d3\u0003 \u0010\u0000\u00d31\u0001\u0000\u0000\u0000\u00d4"+ + "\u00d5\u0005\u000f\u0000\u0000\u00d5\u00d6\u0005\u0012\u0000\u0000\u00d6"+ + "\u00d7\u0003(\u0014\u0000\u00d7\u00d8\u0003 \u0010\u0000\u00d83\u0001"+ + "\u0000\u0000\u0000\u00d9\u00da\u0005\u0010\u0000\u0000\u00da\u00db\u0005"+ + "\u0014\u0000\u0000\u00db\u00dc\u0003@ \u0000\u00dc\u00dd\u0005\u0015\u0000"+ + "\u0000\u00dd\u00de\u0005\u0012\u0000\u0000\u00de\u00df\u0003(\u0014\u0000"+ + "\u00df\u00e0\u0003 \u0010\u0000\u00e05\u0001\u0000\u0000\u0000\u00e1\u00e2"+ + "\u0005\r\u0000\u0000\u00e2\u00e3\u00038\u001c\u0000\u00e3\u00e4\u0005"+ + "\u001a\u0000\u0000\u00e47\u0001\u0000\u0000\u0000\u00e5\u00e6\u0003:\u001d"+ + "\u0000\u00e6\u00e7\u0005\u0014\u0000\u0000\u00e7\u00e8\u0003>\u001f\u0000"+ + "\u00e8\u00e9\u0005\u0015\u0000\u0000\u00e99\u0001\u0000\u0000\u0000\u00ea"+ + "\u00ed\u0003\u0004\u0002\u0000\u00eb\u00ed\u0005+\u0000\u0000\u00ec\u00ea"+ + "\u0001\u0000\u0000\u0000\u00ec\u00eb\u0001\u0000\u0000\u0000\u00ed\u00ee"+ + "\u0001\u0000\u0000\u0000\u00ee\u00f0\u0005\u0018\u0000\u0000\u00ef\u00ec"+ + "\u0001\u0000\u0000\u0000\u00ef\u00f0\u0001\u0000\u0000\u0000\u00f0\u00f1"+ + "\u0001\u0000\u0000\u0000\u00f1\u00f2\u0003\u0012\t\u0000\u00f2;\u0001"+ + "\u0000\u0000\u0000\u00f3\u00f5\u0005\u0011\u0000\u0000\u00f4\u00f6\u0003"+ + "@ \u0000\u00f5\u00f4\u0001\u0000\u0000\u0000\u00f5\u00f6\u0001\u0000\u0000"+ + "\u0000\u00f6\u00f7\u0001\u0000\u0000\u0000\u00f7\u00f8\u0005\u001a\u0000"+ + "\u0000\u00f8=\u0001\u0000\u0000\u0000\u00f9\u00fe\u0003@ \u0000\u00fa"+ + "\u00fb\u0005\u0019\u0000\u0000\u00fb\u00fd\u0003@ \u0000\u00fc\u00fa\u0001"+ + "\u0000\u0000\u0000\u00fd\u0100\u0001\u0000\u0000\u0000\u00fe\u00fc\u0001"+ + "\u0000\u0000\u0000\u00fe\u00ff\u0001\u0000\u0000\u0000\u00ff\u0102\u0001"+ + "\u0000\u0000\u0000\u0100\u00fe\u0001\u0000\u0000\u0000\u0101\u00f9\u0001"+ + "\u0000\u0000\u0000\u0101\u0102\u0001\u0000\u0000\u0000\u0102?\u0001\u0000"+ + "\u0000\u0000\u0103\u0104\u0006 \uffff\uffff\u0000\u0104\u010b\u0003H$"+ + "\u0000\u0105\u010b\u0003&\u0013\u0000\u0106\u010b\u00038\u001c\u0000\u0107"+ + "\u010b\u0003F#\u0000\u0108\u010b\u0003D\"\u0000\u0109\u010b\u0003B!\u0000"+ + "\u010a\u0103\u0001\u0000\u0000\u0000\u010a\u0105\u0001\u0000\u0000\u0000"+ + "\u010a\u0106\u0001\u0000\u0000\u0000\u010a\u0107\u0001\u0000\u0000\u0000"+ + "\u010a\u0108\u0001\u0000\u0000\u0000\u010a\u0109\u0001\u0000\u0000\u0000"+ + "\u010b\u0112\u0001\u0000\u0000\u0000\u010c\u010d\n\u0007\u0000\u0000\u010d"+ + "\u010e\u0003L&\u0000\u010e\u010f\u0003@ \b\u010f\u0111\u0001\u0000\u0000"+ + "\u0000\u0110\u010c\u0001\u0000\u0000\u0000\u0111\u0114\u0001\u0000\u0000"+ + "\u0000\u0112\u0110\u0001\u0000\u0000\u0000\u0112\u0113\u0001\u0000\u0000"+ + "\u0000\u0113A\u0001\u0000\u0000\u0000\u0114\u0112\u0001\u0000\u0000\u0000"+ + "\u0115\u0116\u0005\u0014\u0000\u0000\u0116\u0117\u0003@ \u0000\u0117\u0118"+ + "\u0005\u0015\u0000\u0000\u0118C\u0001\u0000\u0000\u0000\u0119\u011a\u0003"+ + "J%\u0000\u011a\u011b\u0003@ \u0000\u011bE\u0001\u0000\u0000\u0000\u011c"+ + "\u011d\u0003&\u0013\u0000\u011d\u011e\u0005\u0016\u0000\u0000\u011e\u011f"+ + "\u0003@ \u0000\u011f\u0120\u0005\u0017\u0000\u0000\u0120G\u0001\u0000"+ + "\u0000\u0000\u0121\u0122\u0007\u0003\u0000\u0000\u0122I\u0001\u0000\u0000"+ + "\u0000\u0123\u0124\u0007\u0004\u0000\u0000\u0124K\u0001\u0000\u0000\u0000"+ + "\u0125\u0126\u0007\u0005\u0000\u0000\u0126M\u0001\u0000\u0000\u0000\u0013"+ + "W]n\u0083\u008c\u008f\u009a\u00a9\u00b5\u00bd\u00c2\u00ca\u00ec\u00ef"+ + "\u00f5\u00fe\u0101\u010a\u0112"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackParser.tokens b/compiler/grammar/.antlr/JackParser.tokens new file mode 100644 index 00000000..8292b05c --- /dev/null +++ b/compiler/grammar/.antlr/JackParser.tokens @@ -0,0 +1,84 @@ +CLASS=1 +CONSTRUCTOR=2 +FUNCTION=3 +METHOD=4 +FIELD=5 +STATIC=6 +VAR=7 +INT=8 +CHAR=9 +BOOLEAN=10 +VOID=11 +LET=12 +DO=13 +IF=14 +ELSE=15 +WHILE=16 +RETURN=17 +LBRACE=18 +RBRACE=19 +LPAREN=20 +RPAREN=21 +LBRACKET=22 +RBRACKET=23 +DOT=24 +COMMA=25 +SEMICOLON=26 +EQUALS=27 +PLUS=28 +MINUS=29 +MUL=30 +DIV=31 +AND=32 +OR=33 +TILDE=34 +LESS_THAN=35 +GREATER_THAN=36 +WS=37 +COMMENT=38 +LINE_COMMENT=39 +INTEGER_LITERAL=40 +BOOLEAN_LITERAL=41 +NULL_LITERAL=42 +THIS_LITERAL=43 +IDENTIFIER=44 +STRING_LITERAL=45 +UnterminatedStringLiteral=46 +'class'=1 +'constructor'=2 +'function'=3 +'method'=4 +'field'=5 +'static'=6 +'var'=7 +'int'=8 +'char'=9 +'boolean'=10 +'void'=11 +'let'=12 +'do'=13 +'if'=14 +'else'=15 +'while'=16 +'return'=17 +'{'=18 +'}'=19 +'('=20 +')'=21 +'['=22 +']'=23 +'.'=24 +','=25 +';'=26 +'='=27 +'+'=28 +'-'=29 +'*'=30 +'/'=31 +'&'=32 +'|'=33 +'~'=34 +'<'=35 +'>'=36 +'null'=42 +'this'=43 diff --git a/compiler/parser-gen/JackLexer.g4 b/compiler/grammar/JackLexer.g4 similarity index 100% rename from compiler/parser-gen/JackLexer.g4 rename to compiler/grammar/JackLexer.g4 diff --git a/compiler/parser-gen/JackParser.g4 b/compiler/grammar/JackParser.g4 similarity index 100% rename from compiler/parser-gen/JackParser.g4 rename to compiler/grammar/JackParser.g4 diff --git a/compiler/package.json b/compiler/package.json index 95c6ad0b..01943b8d 100644 --- a/compiler/package.json +++ b/compiler/package.json @@ -11,7 +11,7 @@ "test-w": "jest --watchAll", "fix": "eslint --fix", "gen": "bash gen.sh", - "watch": "nodemon -e jack,ts -w src -w test -x \"npm run test \"" + "watch-jack": "nodemon -e jack,ts -w src -w test -x \"npm run test \"" }, "nodemonConfig": { "delay": 700 diff --git a/compiler/parser-gen/Main.jack b/compiler/parser-gen/Main.jack deleted file mode 100644 index d3400ca1..00000000 --- a/compiler/parser-gen/Main.jack +++ /dev/null @@ -1,78 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/ConvertToBin/Main.jack -/** - * Unpacks a 16-bit number into its binary representation: - * Takes the 16-bit number stored in RAM[8000] and stores its individual - * bits in RAM[8001]..RAM[8016] (each location will contain 0 or 1). - * Before the conversion, RAM[8001]..RAM[8016] are initialized to -1. - * - * The program should be tested as follows: - * 1) Load the compiled program into the supplied VM emulator - * 2) Put some value in RAM[8000] - * 3) Switch to "no animation" - * 4) Run the program (give it enough time to run) - * 5) Stop the program - * 6) Check that RAM[8001]..RAM[8016] contains the correct binary result, and - * that none of these memory locations contains -1. - */ -class Main { - /** Initializes RAM[8001]..RAM[8016] to -1, - * and converts the value in RAM[8000] to binary. */ - function void main() { - var int value; - do Main.fillMemory(8001, 16, -1); // sets RAM[8001]..RAM[8016] to -1 - let value = Memory.peek(8000); // reads a value from RAM[8000] - do Main.convert(value); // performs the conversion - return; - } - - /** Converts the given decimal value to binary, and puts - * the resulting bits in RAM[8001]..RAM[8016]. */ - function void convert(int value) { - var int mask, position; - var boolean loop; - - let loop = true; - while (loop) { - let position = position + 1; - let mask = Main.nextMask(mask); - - if (~(position > 16)) { - - if (~((value & mask) = 0)) { - do Memory.poke(8000 + position, 1); - } - else { - do Memory.poke(8000 + position, 0); - } - } - else { - let loop = false; - } - } - return; - } - - /** Returns the next mask (the mask that should follow the given mask). */ - function int nextMask(int mask) { - if (mask = 0) { - return 1; - } - else { - return mask * 2; - } - } - - /** Fills 'length' consecutive memory locations with 'value', - * starting at 'startAddress'. */ - function void fillMemory(int startAddress, int length, int value) { - while (length > 0) { - do Memory.poke(startAddress, value); - let length = length - 1; - let startAddress = startAddress + 1; - } - return; - } -} diff --git a/compiler/parser-gen/Makefile b/compiler/parser-gen/Makefile deleted file mode 100644 index 8be4b949..00000000 --- a/compiler/parser-gen/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -trace: - antlr4-parse JackLexer.g4 JackParser.g4 program -tokens -trace< Main.jack - -tokens: - antlr4-parse JackLexer.g4 JackParser.g4 program -tokens < Main.jack - -gui: - antlr4-parse JackLexer.g4 JackParser.g4 program -gui < Main.jack -gen: - antlr4 JackLexer.g4 JackParser.g4 -o ./output \ No newline at end of file diff --git a/compiler/parser-gen/jack.ohm b/compiler/parser-gen/jack.ohm deleted file mode 100644 index f313b9e8..00000000 --- a/compiler/parser-gen/jack.ohm +++ /dev/null @@ -1,78 +0,0 @@ -Jack <: Base { - Root := Class - - whitespace = (lineComment | comment | space) - - class = "class" whitespace+ - Class = class jackIdentifier OpenBrace ClassVarDec* SubroutineDec* CloseBrace - - type = ("int" | "char" | "boolean" | jackIdentifier) whitespace+ - - classVarType = ("static" | "field") whitespace+ - ClassVarDec = classVarType type jackIdentifier TrailingIdentifier* Semi - TrailingIdentifier = Comma jackIdentifier - - void = "void" whitespace+ - returnType = (type | void) - subroutineType = ("constructor" | "function" | "method") whitespace+ - SubroutineDec = subroutineType returnType jackIdentifier OpenParen ParameterList CloseParen SubroutineBody - - - Parameter = type jackIdentifier - Parameters = Parameter TrailingParameter* - TrailingParameter = Comma Parameter - ParameterList = Parameters? - - SubroutineBody = OpenBrace VarDec* Statement* CloseBrace - - var = "var" whitespace+ - VarDec = var type jackIdentifier TrailingIdentifier* Semi - - Statement = LetStatement | IfStatement | WhileStatement | DoStatement | ReturnStatement - - arrayAccessStart = jackIdentifier openSquare - ArrayAccess = arrayAccessStart Expression CloseSquare - - let = "let" whitespace+ - LetTarget = ArrayAccess | jackIdentifier - LetStatement = let LetTarget Equal Expression Semi - - IfStatement = "if" OpenParen Expression CloseParen OpenBrace Statement* CloseBrace ElseBlock? - ElseBlock = "else" OpenBrace Statement* CloseBrace - - WhileStatement = "while" OpenParen Expression CloseParen OpenBrace Statement* CloseBrace - - do = "do" whitespace+ - DoStatement = do SubroutineCall Semi - - return = "return" - returnWithSpace = "return" whitespace+ - ReturnStatement = EmptyReturn | ReturnValue - EmptyReturn = return Semi - ReturnValue = returnWithSpace Expression Semi - - op = "+" | "-" | "*" | "/" | "&" | "|" | "<" | ">" | "=" - ExpressionPart = op Term - Expression = Term ExpressionPart* - - integerConstant = digit+ - stringConstant = doubleQuote (~doubleQuote ~newline any)* doubleQuote - keywordConstant = "true" | "false" | "null" | "this" - - GroupedExpression = OpenParen Expression CloseParen - - unaryOp = "-" | "~" - UnaryExpression = unaryOp Term - - Term = integerConstant | stringConstant | keywordConstant | SubroutineCall | ArrayAccess | jackIdentifier | GroupedExpression | UnaryExpression - - compoundIdentifier = jackIdentifier dot jackIdentifier - SubroutineName = compoundIdentifier | jackIdentifier - SubroutineCall = SubroutineName OpenParen ExpressionList CloseParen - - ExpressionList = Expressions? - Expressions = Expression TrailingExpression* - TrailingExpression = Comma Expression - - jackIdentifier = letter (alnum | underscore)* -} \ No newline at end of file diff --git a/compiler/src/VIsitor.ts b/compiler/src/VIsitor.ts deleted file mode 100644 index 32486b53..00000000 --- a/compiler/src/VIsitor.ts +++ /dev/null @@ -1,55 +0,0 @@ -// import { ClassDeclarationContext, ClassNameContext, SubroutineDecContext } from './generated/JackParser'; -// import { JackParserVisitor } from './generated/JackParserVisitor'; -// import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor' - -// export class Visitor extends AbstractParseTreeVisitor implements JackParserVisitor { -// protected override defaultResult(): string { -// return ""; -// } - -// override aggregateResult(aggregate: string, nextResult: string) { -// return aggregate + nextResult -// } -// visitSubroutineDec(ctx: SubroutineDecContext): string { -// const c = ctx.parent -// return "" + super.visitChildren(ctx); -// }; - -// } - -// /** -// * // Compiled Main.jack: -// function Main.main 0 -// push constant 12 -// call String.new 1 -// push constant 72 -// call String.appendChar 2 -// push constant 101 -// call String.appendChar 2 -// push constant 108 -// call String.appendChar 2 -// push constant 108 -// call String.appendChar 2 -// push constant 111 -// call String.appendChar 2 -// push constant 32 -// call String.appendChar 2 -// push constant 119 -// call String.appendChar 2 -// push constant 111 -// call String.appendChar 2 -// push constant 114 -// call String.appendChar 2 -// push constant 108 -// call String.appendChar 2 -// push constant 100 -// call String.appendChar 2 -// push constant 33 -// call String.appendChar 2 -// call Output.printString 1 -// pop temp 0 -// call Output.println 0 -// pop temp 0 -// push constant 0 -// return -// */ \ No newline at end of file diff --git a/compiler/src/builtins.ts b/compiler/src/builtins.ts index 02fe137c..c9ef3ffc 100644 --- a/compiler/src/builtins.ts +++ b/compiler/src/builtins.ts @@ -8,7 +8,6 @@ interface Range { export const intRange = { min: -32768, max: 32767 } as Range; //TODO: should we convert this to symbols? const builtInFunctionsToArgCount: Record = { - "Array.dispose": 0, //TODO: what is this? // "Array.init": 0, @@ -62,6 +61,11 @@ const builtInFunctionsToArgCount: Record = { "Sys.halt": 0, "Sys.wait": 1, }; +const builtInClasses = ["Array", "Keyboard", "Math", "Memory", "Output", "Screen", "String", "Sys"] +const builtInClassesRecord = builtInClasses.reduce((acc, elem) => ({ + ...acc, + [elem]: {} as GenericSymbol +}), {} as Record) export const builtInSymbols = Object.keys(builtInFunctionsToArgCount).reduce((acc, elem) => ({ ...acc, @@ -71,4 +75,4 @@ export const builtInSymbols = Object.keys(builtInFunctionsToArgCount).reduce((ac type: SubroutineType.Function } } as GenericSymbol -}), {} as Record) \ No newline at end of file +}), builtInClassesRecord) \ No newline at end of file diff --git a/compiler/src/compiler.ts b/compiler/src/compiler.ts index 38558fb3..8049da7e 100644 --- a/compiler/src/compiler.ts +++ b/compiler/src/compiler.ts @@ -13,7 +13,7 @@ export default class Compiler { const globalSymbolsListener = new GlobalSymbolTableListener(); const files = fs.readdirSync(dir).filter(file => file.endsWith(".jack")).map(file => path.join(dir, file)); for (const filePath of files) { - const errorListener = ErrorListener.getInstance() + const errorListener = new ErrorListener(); errorListener.filepath = filePath; const f = fs.readFileSync(filePath, 'utf8'); const inputStream = CharStreams.fromString(f); const lexer = new JackLexer(inputStream); @@ -43,17 +43,15 @@ export default class Compiler { const symbolsErrors = globalSymbolsListener.errors.join("\n") try { expect(globalSymbolsListener.errors.length).toBe(0) - } - catch (e) { + } catch (e) { throw new Error(symbolsErrors); } globalSymbolsListener.resetErrors(); if (globalSymbolsListener.className != path.parse(filePath).name) { console.log("Class name does not match file name: " + globalSymbolsListener.className + " vs " + path.parse(filePath).name); } - - //TODO: add OS builtin functions const validator = new ValidatorListener(globalSymbolsListener.globalSymbolTable); + } return ""; } diff --git a/compiler/src/error.ts b/compiler/src/error.ts index bc71eff0..13888db8 100644 --- a/compiler/src/error.ts +++ b/compiler/src/error.ts @@ -23,6 +23,7 @@ export class LexerOrParserError extends Error { super(msg); } } +//TODO: should add filepath to other errors? export class DuplicatedSubroutineError extends JackCompilerError { constructor(line: number, charPositionInLine: number, subroutineName: string) { super(line, charPositionInLine, `Subroutine ${subroutineName} redeclared.`); @@ -97,7 +98,7 @@ export class UnknownSubroutineCallError extends JackCompilerError { charPositionInLine: number, subroutineName: string, className?: string) { - super(line, charPositionInLine, `Can't find subroutine '${subroutineName}' ${className ? `in ${className}` : ""} `); + super(line, charPositionInLine, `Can't find subroutine '${subroutineName}'${className ? ` in ${className}` : ""}`); Object.setPrototypeOf(this, UnknownSubroutineCallError.prototype); } } diff --git a/compiler/src/listener/error.listener.ts b/compiler/src/listener/error.listener.ts index 5fab50ea..e5a4f4e8 100644 --- a/compiler/src/listener/error.listener.ts +++ b/compiler/src/listener/error.listener.ts @@ -5,7 +5,6 @@ export class ErrorListener implements ANTLRErrorListener { public filepath: string = ""; public errors: JackCompilerError[] = []; - // constructor(private filepath: string, ) { }; /** * Provides a default instance of {@link ConsoleErrorListener}. */ diff --git a/compiler/src/listener/global.symbol.table.listener.ts b/compiler/src/listener/global.symbol.table.listener.ts index 0eeaf6a7..625f94bd 100644 --- a/compiler/src/listener/global.symbol.table.listener.ts +++ b/compiler/src/listener/global.symbol.table.listener.ts @@ -1,4 +1,3 @@ -import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; import { ClassDeclarationContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; @@ -9,10 +8,12 @@ import { GenericSymbol, SubroutineType } from "../symbol"; const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; -export class GlobalSymbolTableListener implements JackParserListener, ParseTreeListener { +/** + * Creates symbol table that contains built-in functions and found classes and subroutines + */ +export class GlobalSymbolTableListener implements JackParserListener { // key can be class or . public globalSymbolTable: Record = structuredClone(builtInSymbols); - //track class variables, local vars, function args public className = ""; public errors: DuplicatedSubroutineError[] = [] @@ -20,8 +21,8 @@ export class GlobalSymbolTableListener implements JackParserListener, ParseTreeL visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; enterClassDeclaration(ctx: ClassDeclarationContext) { - if (this.globalSymbolTable[ctx.className()!.text] != undefined) { - this.errors.push(new DuplicatedSubroutineError(ctx.start.line, ctx.start.startIndex, `Class "${ctx.className()!.text}" already defined.`)); + if (this. globalSymbolTable[ctx.className()!.text] != undefined) { + this.errors.push(new DuplicatedSubroutineError(ctx.start.line, ctx.start.startIndex, `Class "${ctx.className()!.text}" is already defined.`)); return; } this.globalSymbolTable[ctx.className()!.text] = {} as GenericSymbol; diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 736951e5..927eb81f 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -1,81 +1,17 @@ -import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { builtInTypes, intRange } from "../builtins"; import { ConstructorMushReturnThis, DuplicatedVariableException, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunction, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error"; -import { ClassDeclarationContext, ClassNameContext, ClassVarDecContext, ConstantContext, ElseStatementContext, FieldListContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; +import { ClassDeclarationContext, ClassNameContext, ClassVarDecContext, ConstantContext, ElseStatementContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol, LocalSymbolTable, ScopeType, SubroutineType } from "../symbol"; -import { builtInTypes, intRange } from "../builtins"; - -class BinaryTreeNode { - _returns?: boolean; - constructor( - public parent: BinaryTreeNode | undefined, - public left?: BinaryTreeNode, - public right?: BinaryTreeNode) { } - - get returns(): boolean { - if (this._returns) { - return this._returns; - } else if (this.right == undefined && this.left == undefined) { - return false; - } else if (this.right != undefined && this.left != undefined) { - return this.left.returns && this.right.returns; - } else if (this.left != undefined) { - return false; - } else { - throw new Error("Something went wrong - CFG has only right subtree") - } - } - print() { - console.log("Branch returns value") - console.log(".") - console.log(this.printBT()); - } - - printBT(prefix: string = "", side: Side = Side.LEFT) { - let res: string = "" - if (this._returns) { - res += this.#pad(prefix, side) - res += " " + this._returns + "\n"; - return res; - } else { - if (this.right == undefined && this.left == undefined) { - res += this.#pad(prefix, side) - res += " " + false + "\n"; - } else { - res += this.left?.printBT((side == Side.LEFT ? "| " : " "), Side.LEFT); - if (this.right) { - res += prefix - res += this.right?.printBT((side == Side.LEFT ? "|\t" : "\t"), Side.RIGHT); - } else { - res += "\n"; - } - - } - } - return res; - } - #pad(prefix: string, side: Side): string { - return side == Side.LEFT ? "├──" : "└──"; - } - -} -enum Side { - LEFT, - RIGHT -} - -const literalTypes = [ - ...builtInTypes, - "String" -] -export class ValidatorListener implements JackParserListener, ParseTreeListener { - - //why do we need local symbol table? this vars, arguments, local vars. What about types? +/** + * Validates Jack file + */ +export class ValidatorListener implements JackParserListener { localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); subroutineShouldReturnVoidType: boolean = false; - cfgNode: BinaryTreeNode = new BinaryTreeNode(undefined); + controlFlowGraphNode: BinaryTreeNode = new BinaryTreeNode(undefined); subroutineName: string = "" className = "" inConstructor: boolean = false @@ -83,15 +19,19 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener stopProcessingErrorsInThisScope = false; constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } - enterClassName(ctx: ClassNameContext) { - this.className = ctx.IDENTIFIER().text + enterClassDeclaration(ctx: ClassDeclarationContext) { + if (this.className != "") { + throw new Error("Cannot change class name") + } + this.className = ctx.className()?.text; }; + enterClassVarDec(ctx: ClassVarDecContext) { let scope: ScopeType; if (ctx.STATIC() != undefined) { - scope = ScopeType.StaticField; + scope = ScopeType.Static; } else if (ctx.FIELD() != undefined) { - scope = ScopeType.Field; + scope = ScopeType.This; } else { throw new Error("Unknown field modifier ") } @@ -101,7 +41,6 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }); }; enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { - let subroutineType: SubroutineType; if (ctx.subroutineType().CONSTRUCTOR() != undefined) { this.inConstructor = true; if (ctx.subroutineDecWithoutType().subroutineReturnType().text !== this.className) { @@ -114,7 +53,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { const returnType = ctx.subroutineReturnType() this.subroutineShouldReturnVoidType = returnType.VOID() != undefined - this.cfgNode = new BinaryTreeNode(undefined); + this.controlFlowGraphNode = new BinaryTreeNode(undefined); this.subroutineName = ctx.subroutineName().text }; @@ -155,7 +94,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; enterStatement(ctx: StatementContext) { - if (this.cfgNode._returns == true) { + if (this.controlFlowGraphNode._returns == true) { this.#addError(new UnreachableCodeError(ctx.start.line, ctx.start.startIndex)); this.stopProcessingErrorsInThisScope = true; } @@ -167,28 +106,28 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener * Control flow */ enterWhileStatement(ctx: WhileStatementContext) { - this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode); + this.controlFlowGraphNode = this.controlFlowGraphNode.left = new BinaryTreeNode(this.controlFlowGraphNode); }; exitWhileStatement(ctx: WhileStatementContext) { - if (this.cfgNode?.parent != null) { - this.cfgNode = this.cfgNode.parent + if (this.controlFlowGraphNode?.parent != null) { + this.controlFlowGraphNode = this.controlFlowGraphNode.parent } }; enterIfStatement(ctx: IfStatementContext) { - this.cfgNode = this.cfgNode.left = new BinaryTreeNode(this.cfgNode); + this.controlFlowGraphNode = this.controlFlowGraphNode.left = new BinaryTreeNode(this.controlFlowGraphNode); }; exitIfStatement(ctx: IfStatementContext) { - if (this.cfgNode?.parent != null) { - this.cfgNode = this.cfgNode.parent + if (this.controlFlowGraphNode?.parent != null) { + this.controlFlowGraphNode = this.controlFlowGraphNode.parent } }; enterElseStatement(ctx: ElseStatementContext) { - this.cfgNode = this.cfgNode.right = new BinaryTreeNode(this.cfgNode); + this.controlFlowGraphNode = this.controlFlowGraphNode.right = new BinaryTreeNode(this.controlFlowGraphNode); }; exitElseStatement(ctx: ElseStatementContext) { - if (this.cfgNode?.parent != null) { - this.cfgNode = this.cfgNode.parent + if (this.controlFlowGraphNode?.parent != null) { + this.controlFlowGraphNode = this.controlFlowGraphNode.parent } }; @@ -303,7 +242,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener if (!returnsVoid && this.subroutineShouldReturnVoidType) { this.#addError(new VoidSubroutineReturnsValueError(ctx.start.line, ctx.start.startIndex)); } - this.cfgNode._returns = true; + this.controlFlowGraphNode._returns = true; if (this.inConstructor) { if (returnsVoid || ctx.expression()!.expression().length > 1 || ctx.expression()!.constant() == undefined || ctx.expression()!.constant()!.THIS_LITERAL() == undefined) { @@ -313,7 +252,7 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; exitSubroutineBody(ctx: SubroutineBodyContext) { - if (!this.cfgNode.returns) { + if (!this.controlFlowGraphNode.returns) { this.#addError(new SubroutineNotAllPathsReturnError(ctx.start.line, ctx.start.startIndex, this.subroutineName)); } this.inConstructor = false; @@ -322,8 +261,8 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener }; exitClassDeclaration(ctx: ClassDeclarationContext) { - while (this.cfgNode?.parent != undefined) { - this.cfgNode = this.cfgNode.parent + while (this.controlFlowGraphNode?.parent != undefined) { + this.controlFlowGraphNode = this.controlFlowGraphNode.parent } }; @@ -345,8 +284,70 @@ export class ValidatorListener implements JackParserListener, ParseTreeListener } +class BinaryTreeNode { + _returns?: boolean; + constructor( + public parent: BinaryTreeNode | undefined, + public left?: BinaryTreeNode, + public right?: BinaryTreeNode) { } + + get returns(): boolean { + if (this._returns) { + return this._returns; + } else if (this.right == undefined && this.left == undefined) { + return false; + } else if (this.right != undefined && this.left != undefined) { + return this.left.returns && this.right.returns; + } else if (this.left != undefined) { + return false; + } else { + throw new Error("Something went wrong - CFG has only right subtree") + } + } + print() { + console.log("Branch returns value") + console.log(".") + console.log(this.printBT()); + } + + printBT(prefix: string = "", side: Side = Side.LEFT) { + let res: string = "" + if (this._returns) { + res += this.#pad(prefix, side) + res += " " + this._returns + "\n"; + return res; + } else { + if (this.right == undefined && this.left == undefined) { + res += this.#pad(prefix, side) + res += " " + false + "\n"; + } else { + res += this.left?.printBT((side == Side.LEFT ? "| " : " "), Side.LEFT); + if (this.right) { + res += prefix + res += this.right?.printBT((side == Side.LEFT ? "|\t" : "\t"), Side.RIGHT); + } else { + res += "\n"; + } + + } + } + return res; + } + #pad(prefix: string, side: Side): string { + return side == Side.LEFT ? "├──" : "└──"; + } + +} +enum Side { + LEFT, + RIGHT +} +const literalTypes = [ + ...builtInTypes, + "String" +] enum CallType { - VarMethod, - LocalMethod, - ClassFunctionOrConstructor + VarMethod = 1, + LocalMethod = 2, + ClassFunctionOrConstructor = 3 } \ No newline at end of file diff --git a/compiler/src/symbol.table.istener.ts b/compiler/src/symbol.table.istener.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/compiler/src/symbol.ts b/compiler/src/symbol.ts index 6d0a2652..b07f7ae1 100644 --- a/compiler/src/symbol.ts +++ b/compiler/src/symbol.ts @@ -2,14 +2,17 @@ * Generic symbol. Can be used for both class and function symbols */ export enum SubroutineType { - Constructor = "ctor", - Function = "function", - Method = "method", + Constructor, + Function, + Method, } export interface SubroutineInfo { paramsCount: number; type: SubroutineType } +/** + * Symbol that represents class or a subroutine + */ export interface GenericSymbol { subroutineInfo?: SubroutineInfo; } @@ -19,21 +22,24 @@ export function createSubroutineSymbol(paramsCount: number, type: SubroutineType type VariableType = string export enum ScopeType { - StaticField, - Field, + Static, + This, Argument, Local, } +/** + * Symbol table that provides lookup for variables in different scopes in a file + */ export class LocalSymbolTable { private vars: Record> = { - [ScopeType.StaticField]: {}, - [ScopeType.Field]: {}, + [ScopeType.Static]: {}, + [ScopeType.This]: {}, [ScopeType.Argument]: {}, [ScopeType.Local]: {}, }; - static readonly functionScopes = [ScopeType.Local, ScopeType.Argument, ScopeType.StaticField]; + static readonly functionScopes = [ScopeType.Local, ScopeType.Argument, ScopeType.Static]; - existsSymbol(name: string, scopesToSearch = [ScopeType.Local, ScopeType.Argument, ScopeType.Field, ScopeType.StaticField]): boolean { + existsSymbol(name: string, scopesToSearch = [ScopeType.Local, ScopeType.Argument, ScopeType.This, ScopeType.Static]): boolean { for (const scope of scopesToSearch) { if (this.vars[scope][name] != undefined) { return true; @@ -41,7 +47,7 @@ export class LocalSymbolTable { } return false; } - getType(name: string, scopesToSearch = [ScopeType.Local, ScopeType.Argument, ScopeType.Field, ScopeType.StaticField]) { + getType(name: string, scopesToSearch = [ScopeType.Local, ScopeType.Argument, ScopeType.This, ScopeType.Static]) { for (const scope of scopesToSearch) { if (this.vars[scope][name] != undefined) { return this.vars[scope][name]; diff --git a/compiler/test/global.symbol.table.listener.test.ts b/compiler/test/global.symbol.table.listener.test.ts index 590264d8..a5913b61 100644 --- a/compiler/test/global.symbol.table.listener.test.ts +++ b/compiler/test/global.symbol.table.listener.test.ts @@ -32,6 +32,14 @@ describe('Global symbol table', () => { test("basic", () => { const expected = { + "Array": {}, + "Keyboard": {}, + "Math": {}, + "Memory": {}, + "Output": {}, + "Screen": {}, + "String": {}, + "Sys": {}, 'Array.dispose': createSubroutineSymbol(0, SubroutineType.Function), 'Array.new': createSubroutineSymbol(1, SubroutineType.Function), 'Keyboard.init': createSubroutineSymbol(0, SubroutineType.Function), diff --git a/compiler/test/local.symbol.table.test.ts b/compiler/test/local.symbol.table.test.ts index b939e0b1..a7545a3f 100644 --- a/compiler/test/local.symbol.table.test.ts +++ b/compiler/test/local.symbol.table.test.ts @@ -24,12 +24,12 @@ describe('LocalSymbolTable', () => { }); }) - test('push and pop stack', () => { + test('clear subroutine vars test', () => { const localSymbolTable = new LocalSymbolTable(); const classVar = 'a'; const functionVar = 'b'; - localSymbolTable.add(ScopeType.Field, classVar, "boolean"); + localSymbolTable.add(ScopeType.This, classVar, "boolean"); localSymbolTable.add(ScopeType.Local, functionVar, "boolean"); diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index b3e6e514..d9a9d6b9 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -3,7 +3,8 @@ import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.l import path from "path"; import { ErrorListener } from "../src/listener/error.listener"; -import { listenToTheTree, parseJackFile, parseJackText } from "./test.helper"; +import { listenToTheTree, parseJackFile, parseJackText, testResourcesDirs } from "./test.helper"; +import { JackParserListener } from '../src/generated/JackParserListener'; describe('Parser', () => { const jestConsole = console; @@ -15,18 +16,7 @@ describe('Parser', () => { global.console = jestConsole; }); - const dirs: string[] = [ - "Average", - "ConvertToBin", - "Fraction", - "HelloWorld", - "List", - "Pong", - "Square", - "ComplexArrays" - ] - test.each(dirs)('%s', (dir: string) => { - + test.each(testResourcesDirs)('%s', (dir: string) => { console.log("Testing " + dir) testJackDir(path.join(__dirname, "resources", dir)); }); diff --git a/compiler/test/test.helper.ts b/compiler/test/test.helper.ts index 065e5232..a2ebc5e4 100644 --- a/compiler/test/test.helper.ts +++ b/compiler/test/test.helper.ts @@ -58,4 +58,15 @@ export function handleErrors(src: string, errors: JackCompilerError[]) { }).join("\n") console.error(msg); throw new Error(msg) -} \ No newline at end of file +} +export const testResourcesDirs: string[] = [ + "Average", + "ConvertToBin", + "Fraction", + "HelloWorld", + "List", + "Pong", + "Square", + "ComplexArrays" +] + diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index efc60159..8f4fa2ab 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -3,8 +3,11 @@ import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVar import { ErrorListener } from "../src/listener/error.listener" import { ValidatorListener } from "../src/listener/validator.listener" import { createSubroutineSymbol, GenericSymbol, SubroutineType } from "../src/symbol" -import { listenToTheTree, parseJackText } from "./test.helper" - +import { listenToTheTree, parseJackFile, parseJackText, testResourcesDirs } from "./test.helper" +import fs from 'fs'; +import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.listener" +import path from "path" +import { ProgramContext } from "../src/generated/JackParser" const log: Logger = new Logger(); describe('ValidatorListener', () => { const jestConsole = console; @@ -336,6 +339,7 @@ describe('ValidatorListener', () => { } }`, UnknownSubroutineCallError) }) + test('incorrect number of parameters when calling a function', () => { testValidator(` class Main { @@ -582,17 +586,38 @@ describe('ValidatorListener', () => { "Main.a": genericSymbol(SubroutineType.Function, 0), }) }) - /** - * Errors from old java compiler - - * - Expected class name, subroutine name, field, parameter or local or static variable name (currently expected IDENTIFIER) - * - Expected subroutine name in call - * - a numeric value is illegal here - * - this' can't be referenced in a function - * - Illegal casting into String constant - * - A field may not be referenced in a function - */ + + //validate files + test.concurrent.each(testResourcesDirs)('%s', (dir: string) => { + console.log("Testing " + dir) + testJackDir(path.join(__dirname, "resources", dir)); + }); }) + +function testJackDir(testFolder: string): void { + const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); + let trees: Record = {} + let globalSymbolsListener: GlobalSymbolTableListener = new GlobalSymbolTableListener(); + for (const filePath of files) { + const errorListener = new ErrorListener() + errorListener.filepath = filePath; + const tree = parseJackFile(filePath) + trees[filePath] = tree + listenToTheTree(tree, globalSymbolsListener) + expect(globalSymbolsListener.errors).toEqual([]); + } + console.log("Global sym table \n", globalSymbolsListener.globalSymbolTable) + for (const filepath of Object.keys(trees)) { + const tree = trees[filepath] + console.log(tree.toInfoString) + console.log("Testing " + filepath) + const validatorListener = listenToTheTree(tree, new ValidatorListener(globalSymbolsListener.globalSymbolTable)); + expect(validatorListener.errors).toEqual([]); + } + +} + function testValidator(src: string, expectedError?: T, globalSymbolTable: Record = {}) { const name = expect.getState().currentTestName! const errorListener = new ErrorListener(); @@ -618,5 +643,12 @@ function testValidator(src: string, expectedError?: } } - - +/** + * TODO: +* Ideas for improvement - +* - Show "Expected class name, subroutine name, field, parameter or local or static variable name" instead of "expecting IDENTIFIER" +* - Show "Expected subroutine return type followed by a subroutine name" instead of "expecting IDENTIFIER" +* - Expected subroutine name in call +* - a numeric value is illegal here when using non numeric vars +* - validate function call - when using literal in call validate the type +*/ \ No newline at end of file From 5716258b0b38af9d247afd072c91cb88c2a902f9 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 29 Sep 2024 10:33:54 +0200 Subject: [PATCH 23/87] WIP --- compiler/test/validator.listener.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index 8f4fa2ab..36c727b4 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,4 +1,3 @@ -import { ILogObj, Logger } from "tslog" import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange as IntLiteralOverflow, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunction, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { ValidatorListener } from "../src/listener/validator.listener" @@ -8,7 +7,6 @@ import fs from 'fs'; import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.listener" import path from "path" import { ProgramContext } from "../src/generated/JackParser" -const log: Logger = new Logger(); describe('ValidatorListener', () => { const jestConsole = console; beforeEach(() => { From aee5ec7ed694f55fd23eaf6a6d1082f5962bb851 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 29 Sep 2024 22:08:39 +0200 Subject: [PATCH 24/87] WIP --- compiler/.gitignore | 2 +- compiler/grammar/.antlr/JackParser.interp | 2 +- compiler/grammar/.antlr/JackParser.java | 30 +- compiler/grammar/JackParser.g4 | 7 +- compiler/src/compiler.ts | 79 +-- compiler/src/generated/JackParser.interp | 2 +- compiler/src/generated/JackParser.ts | 40 +- compiler/src/generated/JackParserListener.ts | 10 +- compiler/src/generated/JackParserVisitor.ts | 6 +- ...l.table.listener.ts => binder.listener.ts} | 36 +- compiler/src/listener/validator.listener.ts | 10 +- compiler/src/listener/vm.writer.listener.ts | 86 +++ compiler/src/resources/JackLexer.g4 | 61 ++ compiler/src/resources/JackParser.g4 | 90 +++ compiler/src/symbol.ts | 9 +- ...stener.test.ts => binder.listener.test.ts} | 35 +- compiler/test/compiler.test.ts | 617 ++++++++++++++++++ compiler/test/local.symbol.table.test.ts | 21 +- compiler/test/parser.test.ts | 5 +- compiler/test/validator.listener.test.ts | 25 +- 20 files changed, 1009 insertions(+), 164 deletions(-) rename compiler/src/listener/{global.symbol.table.listener.ts => binder.listener.ts} (62%) create mode 100644 compiler/src/listener/vm.writer.listener.ts create mode 100644 compiler/src/resources/JackLexer.g4 create mode 100644 compiler/src/resources/JackParser.g4 rename compiler/test/{global.symbol.table.listener.test.ts => binder.listener.test.ts} (87%) create mode 100644 compiler/test/compiler.test.ts diff --git a/compiler/.gitignore b/compiler/.gitignore index 115dabf4..eee91674 100644 --- a/compiler/.gitignore +++ b/compiler/.gitignore @@ -24,4 +24,4 @@ dist-ssr *.sw? .coverage docs -parser-gen/.antlr \ No newline at end of file +src/resources/.antlr \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackParser.interp b/compiler/grammar/.antlr/JackParser.interp index f2fd9610..860e8c5b 100644 --- a/compiler/grammar/.antlr/JackParser.interp +++ b/compiler/grammar/.antlr/JackParser.interp @@ -131,7 +131,7 @@ returnStatement expressionList expression groupedExpression -unaryOp +unaryOperation arrayAccess constant unaryOperator diff --git a/compiler/grammar/.antlr/JackParser.java b/compiler/grammar/.antlr/JackParser.java index 9b114a26..fb913c4c 100644 --- a/compiler/grammar/.antlr/JackParser.java +++ b/compiler/grammar/.antlr/JackParser.java @@ -34,7 +34,7 @@ public class JackParser extends Parser { RULE_ifElseStatement = 23, RULE_ifStatement = 24, RULE_elseStatement = 25, RULE_whileStatement = 26, RULE_doStatement = 27, RULE_subroutineCall = 28, RULE_subroutineId = 29, RULE_returnStatement = 30, RULE_expressionList = 31, - RULE_expression = 32, RULE_groupedExpression = 33, RULE_unaryOp = 34, + RULE_expression = 32, RULE_groupedExpression = 33, RULE_unaryOperation = 34, RULE_arrayAccess = 35, RULE_constant = 36, RULE_unaryOperator = 37, RULE_binaryOperator = 38; private static String[] makeRuleNames() { return new String[] { @@ -45,7 +45,7 @@ private static String[] makeRuleNames() { "varNameInDeclaration", "varName", "statements", "statement", "letStatement", "ifElseStatement", "ifStatement", "elseStatement", "whileStatement", "doStatement", "subroutineCall", "subroutineId", "returnStatement", "expressionList", - "expression", "groupedExpression", "unaryOp", "arrayAccess", "constant", + "expression", "groupedExpression", "unaryOperation", "arrayAccess", "constant", "unaryOperator", "binaryOperator" }; } @@ -1662,7 +1662,6 @@ public final ExpressionListContext expressionList() throws RecognitionException @SuppressWarnings("CheckReturnValue") public static class ExpressionContext extends ParserRuleContext { - public ExpressionContext binaryOperation; public ConstantContext constant() { return getRuleContext(ConstantContext.class,0); } @@ -1675,21 +1674,21 @@ public SubroutineCallContext subroutineCall() { public ArrayAccessContext arrayAccess() { return getRuleContext(ArrayAccessContext.class,0); } - public UnaryOpContext unaryOp() { - return getRuleContext(UnaryOpContext.class,0); + public UnaryOperationContext unaryOperation() { + return getRuleContext(UnaryOperationContext.class,0); } public GroupedExpressionContext groupedExpression() { return getRuleContext(GroupedExpressionContext.class,0); } - public BinaryOperatorContext binaryOperator() { - return getRuleContext(BinaryOperatorContext.class,0); - } public List expression() { return getRuleContexts(ExpressionContext.class); } public ExpressionContext expression(int i) { return getRuleContext(ExpressionContext.class,i); } + public BinaryOperatorContext binaryOperator() { + return getRuleContext(BinaryOperatorContext.class,0); + } public ExpressionContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -1741,7 +1740,7 @@ private ExpressionContext expression(int _p) throws RecognitionException { case 5: { setState(264); - unaryOp(); + unaryOperation(); } break; case 6: @@ -1762,7 +1761,6 @@ private ExpressionContext expression(int _p) throws RecognitionException { { { _localctx = new ExpressionContext(_parentctx, _parentState); - _localctx.binaryOperation = _prevctx; pushNewRecursionContext(_localctx, _startState, RULE_expression); setState(268); if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); @@ -1829,22 +1827,22 @@ public final GroupedExpressionContext groupedExpression() throws RecognitionExce } @SuppressWarnings("CheckReturnValue") - public static class UnaryOpContext extends ParserRuleContext { + public static class UnaryOperationContext extends ParserRuleContext { public UnaryOperatorContext unaryOperator() { return getRuleContext(UnaryOperatorContext.class,0); } public ExpressionContext expression() { return getRuleContext(ExpressionContext.class,0); } - public UnaryOpContext(ParserRuleContext parent, int invokingState) { + public UnaryOperationContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } - @Override public int getRuleIndex() { return RULE_unaryOp; } + @Override public int getRuleIndex() { return RULE_unaryOperation; } } - public final UnaryOpContext unaryOp() throws RecognitionException { - UnaryOpContext _localctx = new UnaryOpContext(_ctx, getState()); - enterRule(_localctx, 68, RULE_unaryOp); + public final UnaryOperationContext unaryOperation() throws RecognitionException { + UnaryOperationContext _localctx = new UnaryOperationContext(_ctx, getState()); + enterRule(_localctx, 68, RULE_unaryOperation); try { enterOuterAlt(_localctx, 1); { diff --git a/compiler/grammar/JackParser.g4 b/compiler/grammar/JackParser.g4 index c3d3bcd1..a3e45e4c 100644 --- a/compiler/grammar/JackParser.g4 +++ b/compiler/grammar/JackParser.g4 @@ -5,7 +5,6 @@ options { } program: classDeclaration EOF; - classDeclaration: CLASS className LBRACE classVarDec* subroutineDeclaration* rBrace; className: IDENTIFIER; @@ -58,16 +57,16 @@ returnStatement: RETURN expression? SEMICOLON; expressionList: (expression (COMMA expression)*)?; expression: - binaryOperation = expression binaryOperator expression + expression binaryOperator expression | constant | varName | subroutineCall | arrayAccess - | unaryOp + | unaryOperation | groupedExpression; groupedExpression: LPAREN expression RPAREN; -unaryOp: unaryOperator expression; +unaryOperation: unaryOperator expression; arrayAccess: varName LBRACKET expression RBRACKET; constant: diff --git a/compiler/src/compiler.ts b/compiler/src/compiler.ts index 8049da7e..8356276a 100644 --- a/compiler/src/compiler.ts +++ b/compiler/src/compiler.ts @@ -1,5 +1,5 @@ import path from "path"; -import { GlobalSymbolTableListener } from "./listener/global.symbol.table.listener"; +import { BinderListener } from "./listener/binder.listener"; import fs from "fs"; import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; import { JackParser } from "./generated/JackParser"; @@ -7,52 +7,43 @@ import { CharStreams, CommonTokenStream } from "antlr4ts"; import { JackLexer } from "./generated/JackLexer"; import { ErrorListener } from "./listener/error.listener"; import { ValidatorListener } from "./listener/validator.listener"; +import { JackCompilerError } from "./error"; +import { VMWriter } from "./listener/vm.writer.listener"; export default class Compiler { - static compile(dir: string): string { + static compile(src: string): string | JackCompilerError[] { - const globalSymbolsListener = new GlobalSymbolTableListener(); - const files = fs.readdirSync(dir).filter(file => file.endsWith(".jack")).map(file => path.join(dir, file)); - for (const filePath of files) { - const errorListener = new ErrorListener(); - errorListener.filepath = filePath; const f = fs.readFileSync(filePath, 'utf8'); - const inputStream = CharStreams.fromString(f); - const lexer = new JackLexer(inputStream); - if (errorListener) { - - lexer.removeErrorListeners(); - lexer.addErrorListener(errorListener); - } - - const tokenStream = new CommonTokenStream(lexer); - expect(tokenStream.getTokens.length).toBeGreaterThan(0) - const parser = new JackParser(tokenStream); - // parser.isTrace = trace; - if (errorListener != undefined) { - parser.removeErrorListeners(); - parser.addErrorListener(errorListener); - } - const tree = parser.program(); - //TODO add error handling here - if (errorListener.errors.length > 0) { - console.error(errorListener.filepath + " has syntax errors"); - continue - } - // console.log(tree.toStringTree(parser.ruleNames)); + const globalSymbolsListener = new BinderListener(); + const errorListener = new ErrorListener(); + const lexer = new JackLexer(CharStreams.fromString(src)); + if (errorListener) { + lexer.removeErrorListeners(); + lexer.addErrorListener(errorListener); + } + const tokenStream = new CommonTokenStream(lexer); + const parser = new JackParser(tokenStream); + // parser.isTrace = trace; + if (errorListener != undefined) { + parser.removeErrorListeners(); + parser.addErrorListener(errorListener); + } + const tree = parser.program(); + if (errorListener.errors.length > 0) { + return errorListener.errors; + } + // console.log(tree.toStringTree(parser.ruleNames)); - ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); - const symbolsErrors = globalSymbolsListener.errors.join("\n") - try { - expect(globalSymbolsListener.errors.length).toBe(0) - } catch (e) { - throw new Error(symbolsErrors); - } - globalSymbolsListener.resetErrors(); - if (globalSymbolsListener.className != path.parse(filePath).name) { - console.log("Class name does not match file name: " + globalSymbolsListener.className + " vs " + path.parse(filePath).name); - } - const validator = new ValidatorListener(globalSymbolsListener.globalSymbolTable); - + ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); + if (globalSymbolsListener.errors.length > 0) { + return globalSymbolsListener.errors; + } + const validator = new ValidatorListener(globalSymbolsListener.globalSymbolTable); + ParseTreeWalker.DEFAULT.walk(validator, tree); + if (validator.errors.length > 0) { + return globalSymbolsListener.errors; } - return ""; + const vmWriter = new VMWriter(globalSymbolsListener.globalSymbolTable); + ParseTreeWalker.DEFAULT.walk(vmWriter, tree); + + return vmWriter.result; } } \ No newline at end of file diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp index 13be77e9..393935df 100644 --- a/compiler/src/generated/JackParser.interp +++ b/compiler/src/generated/JackParser.interp @@ -131,7 +131,7 @@ returnStatement expressionList expression groupedExpression -unaryOp +unaryOperation arrayAccess constant unaryOperator diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts index 53fbc204..a9c5b930 100644 --- a/compiler/src/generated/JackParser.ts +++ b/compiler/src/generated/JackParser.ts @@ -108,7 +108,7 @@ export class JackParser extends Parser { public static readonly RULE_expressionList = 31; public static readonly RULE_expression = 32; public static readonly RULE_groupedExpression = 33; - public static readonly RULE_unaryOp = 34; + public static readonly RULE_unaryOperation = 34; public static readonly RULE_arrayAccess = 35; public static readonly RULE_constant = 36; public static readonly RULE_unaryOperator = 37; @@ -122,7 +122,7 @@ export class JackParser extends Parser { "varNameInDeclaration", "varName", "statements", "statement", "letStatement", "ifElseStatement", "ifStatement", "elseStatement", "whileStatement", "doStatement", "subroutineCall", "subroutineId", "returnStatement", "expressionList", - "expression", "groupedExpression", "unaryOp", "arrayAccess", "constant", + "expression", "groupedExpression", "unaryOperation", "arrayAccess", "constant", "unaryOperator", "binaryOperator", ]; @@ -1403,7 +1403,7 @@ export class JackParser extends Parser { case 5: { this.state = 264; - this.unaryOp(); + this.unaryOperation(); } break; @@ -1427,7 +1427,6 @@ export class JackParser extends Parser { { { _localctx = new ExpressionContext(_parentctx, _parentState); - _localctx._binaryOperation = _prevctx; this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); this.state = 268; if (!(this.precpred(this._ctx, 7))) { @@ -1490,9 +1489,9 @@ export class JackParser extends Parser { return _localctx; } // @RuleVersion(0) - public unaryOp(): UnaryOpContext { - let _localctx: UnaryOpContext = new UnaryOpContext(this._ctx, this.state); - this.enterRule(_localctx, 68, JackParser.RULE_unaryOp); + public unaryOperation(): UnaryOperationContext { + let _localctx: UnaryOperationContext = new UnaryOperationContext(this._ctx, this.state); + this.enterRule(_localctx, 68, JackParser.RULE_unaryOperation); try { this.enterOuterAlt(_localctx, 1); { @@ -3015,10 +3014,6 @@ export class ExpressionListContext extends ParserRuleContext { export class ExpressionContext extends ParserRuleContext { - public _binaryOperation!: ExpressionContext; - public binaryOperator(): BinaryOperatorContext | undefined { - return this.tryGetRuleContext(0, BinaryOperatorContext); - } public expression(): ExpressionContext[]; public expression(i: number): ExpressionContext; public expression(i?: number): ExpressionContext | ExpressionContext[] { @@ -3028,6 +3023,9 @@ export class ExpressionContext extends ParserRuleContext { return this.getRuleContext(i, ExpressionContext); } } + public binaryOperator(): BinaryOperatorContext | undefined { + return this.tryGetRuleContext(0, BinaryOperatorContext); + } public constant(): ConstantContext | undefined { return this.tryGetRuleContext(0, ConstantContext); } @@ -3040,8 +3038,8 @@ export class ExpressionContext extends ParserRuleContext { public arrayAccess(): ArrayAccessContext | undefined { return this.tryGetRuleContext(0, ArrayAccessContext); } - public unaryOp(): UnaryOpContext | undefined { - return this.tryGetRuleContext(0, UnaryOpContext); + public unaryOperation(): UnaryOperationContext | undefined { + return this.tryGetRuleContext(0, UnaryOperationContext); } public groupedExpression(): GroupedExpressionContext | undefined { return this.tryGetRuleContext(0, GroupedExpressionContext); @@ -3108,7 +3106,7 @@ export class GroupedExpressionContext extends ParserRuleContext { } -export class UnaryOpContext extends ParserRuleContext { +export class UnaryOperationContext extends ParserRuleContext { public unaryOperator(): UnaryOperatorContext { return this.getRuleContext(0, UnaryOperatorContext); } @@ -3119,23 +3117,23 @@ export class UnaryOpContext extends ParserRuleContext { super(parent, invokingState); } // @Override - public override get ruleIndex(): number { return JackParser.RULE_unaryOp; } + public override get ruleIndex(): number { return JackParser.RULE_unaryOperation; } // @Override public override enterRule(listener: JackParserListener): void { - if (listener.enterUnaryOp) { - listener.enterUnaryOp(this); + if (listener.enterUnaryOperation) { + listener.enterUnaryOperation(this); } } // @Override public override exitRule(listener: JackParserListener): void { - if (listener.exitUnaryOp) { - listener.exitUnaryOp(this); + if (listener.exitUnaryOperation) { + listener.exitUnaryOperation(this); } } // @Override public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitUnaryOp) { - return visitor.visitUnaryOp(this); + if (visitor.visitUnaryOperation) { + return visitor.visitUnaryOperation(this); } else { return visitor.visitChildren(this); } diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts index 50b45295..d67200be 100644 --- a/compiler/src/generated/JackParserListener.ts +++ b/compiler/src/generated/JackParserListener.ts @@ -37,7 +37,7 @@ import { ReturnStatementContext } from "./JackParser"; import { ExpressionListContext } from "./JackParser"; import { ExpressionContext } from "./JackParser"; import { GroupedExpressionContext } from "./JackParser"; -import { UnaryOpContext } from "./JackParser"; +import { UnaryOperationContext } from "./JackParser"; import { ArrayAccessContext } from "./JackParser"; import { ConstantContext } from "./JackParser"; import { UnaryOperatorContext } from "./JackParser"; @@ -424,15 +424,15 @@ export interface JackParserListener extends ParseTreeListener { exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; /** - * Enter a parse tree produced by `JackParser.unaryOp`. + * Enter a parse tree produced by `JackParser.unaryOperation`. * @param ctx the parse tree */ - enterUnaryOp?: (ctx: UnaryOpContext) => void; + enterUnaryOperation?: (ctx: UnaryOperationContext) => void; /** - * Exit a parse tree produced by `JackParser.unaryOp`. + * Exit a parse tree produced by `JackParser.unaryOperation`. * @param ctx the parse tree */ - exitUnaryOp?: (ctx: UnaryOpContext) => void; + exitUnaryOperation?: (ctx: UnaryOperationContext) => void; /** * Enter a parse tree produced by `JackParser.arrayAccess`. diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts index 0dc85abc..f4c39796 100644 --- a/compiler/src/generated/JackParserVisitor.ts +++ b/compiler/src/generated/JackParserVisitor.ts @@ -37,7 +37,7 @@ import { ReturnStatementContext } from "./JackParser"; import { ExpressionListContext } from "./JackParser"; import { ExpressionContext } from "./JackParser"; import { GroupedExpressionContext } from "./JackParser"; -import { UnaryOpContext } from "./JackParser"; +import { UnaryOperationContext } from "./JackParser"; import { ArrayAccessContext } from "./JackParser"; import { ConstantContext } from "./JackParser"; import { UnaryOperatorContext } from "./JackParser"; @@ -291,11 +291,11 @@ export interface JackParserVisitor extends ParseTreeVisitor { visitGroupedExpression?: (ctx: GroupedExpressionContext) => Result; /** - * Visit a parse tree produced by `JackParser.unaryOp`. + * Visit a parse tree produced by `JackParser.unaryOperation`. * @param ctx the parse tree * @return the visitor result */ - visitUnaryOp?: (ctx: UnaryOpContext) => Result; + visitUnaryOperation?: (ctx: UnaryOperationContext) => Result; /** * Visit a parse tree produced by `JackParser.arrayAccess`. diff --git a/compiler/src/listener/global.symbol.table.listener.ts b/compiler/src/listener/binder.listener.ts similarity index 62% rename from compiler/src/listener/global.symbol.table.listener.ts rename to compiler/src/listener/binder.listener.ts index 625f94bd..8929fa5c 100644 --- a/compiler/src/listener/global.symbol.table.listener.ts +++ b/compiler/src/listener/binder.listener.ts @@ -1,27 +1,30 @@ import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ClassDeclarationContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext } from "../generated/JackParser"; +import { ClassDeclarationContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameInDeclarationContext } from "../generated/JackParser"; import { JackParserListener } from "../generated/JackParserListener"; import { DuplicatedSubroutineError } from '../error' import { builtInSymbols, builtInTypes } from "../builtins"; -import { GenericSymbol, SubroutineType } from "../symbol"; +import { GenericSymbol, SubroutineInfo, SubroutineType } from "../symbol"; const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; /** - * Creates symbol table that contains built-in functions and found classes and subroutines + * Creates global symbol table that contains built-in functions and found classes and subroutines */ -export class GlobalSymbolTableListener implements JackParserListener { +export class BinderListener implements JackParserListener { // key can be class or . public globalSymbolTable: Record = structuredClone(builtInSymbols); public className = ""; public errors: DuplicatedSubroutineError[] = [] - + private subRoutineInfo: SubroutineInfo = {} as SubroutineInfo; + private subroutineVarsCount: number = 0; + private stopProcessingSubroutines = false; + private subroutineId = ""; //to fix compiler error visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; enterClassDeclaration(ctx: ClassDeclarationContext) { - if (this. globalSymbolTable[ctx.className()!.text] != undefined) { + if (this.globalSymbolTable[ctx.className()!.text] != undefined) { this.errors.push(new DuplicatedSubroutineError(ctx.start.line, ctx.start.startIndex, `Class "${ctx.className()!.text}" is already defined.`)); return; } @@ -46,17 +49,30 @@ export class GlobalSymbolTableListener implements JackParserListener { const id = this.className + "." + subroutineName if (this.globalSymbolTable[id] != undefined) { this.errors.push(new DuplicatedSubroutineError(nameCtx.start.line, nameCtx.start.startIndex, subroutineName)); - } + this.stopProcessingSubroutines = true; + } else { + this.subroutineId = id; const paramsCount = subroutineWithoutTypeCtx.parameterList().parameter().length - this.globalSymbolTable[id] = { - subroutineInfo: { + this.subRoutineInfo = { type: subroutineType, paramsCount: paramsCount, } - } as GenericSymbol; + this.subroutineVarsCount = 0; + this.stopProcessingSubroutines = false; + } } + enterVarNameInDeclaration(ctx: VarNameInDeclarationContext) { + if (this.stopProcessingSubroutines) return; + this.subroutineVarsCount++; + }; + exitSubroutineBody(ctx: SubroutineBodyContext) { + if (this.stopProcessingSubroutines) return; + this.subRoutineInfo.localVarsCount = this.subroutineVarsCount; + this.globalSymbolTable[this.subroutineId] = { subroutineInfo: this.subRoutineInfo } + }; resetErrors() { this.errors = []; } } + diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts index 927eb81f..90e30155 100644 --- a/compiler/src/listener/validator.listener.ts +++ b/compiler/src/listener/validator.listener.ts @@ -11,7 +11,7 @@ import { GenericSymbol, LocalSymbolTable, ScopeType, SubroutineType } from "../s export class ValidatorListener implements JackParserListener { localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); subroutineShouldReturnVoidType: boolean = false; - controlFlowGraphNode: BinaryTreeNode = new BinaryTreeNode(undefined); + controlFlowGraphNode: BinaryTreeNode = new BinaryTreeNode(); subroutineName: string = "" className = "" inConstructor: boolean = false @@ -20,10 +20,11 @@ export class ValidatorListener implements JackParserListener { constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } enterClassDeclaration(ctx: ClassDeclarationContext) { + const newName = ctx.className()?.text if (this.className != "") { throw new Error("Cannot change class name") } - this.className = ctx.className()?.text; + this.className = newName; }; enterClassVarDec(ctx: ClassVarDecContext) { @@ -171,7 +172,7 @@ export class ValidatorListener implements JackParserListener { } } //int min value check - const unaryOp = ctx.expression().unaryOp() + const unaryOp = ctx.expression().unaryOperation() if (varName && unaryOp != undefined && unaryOp.unaryOperator().MINUS() !== undefined && unaryOp!.expression().constant() != undefined && unaryOp!.expression().constant()?.INTEGER_LITERAL() !== undefined) { const value = parseInt(unaryOp!.expression().constant()!.INTEGER_LITERAL()!.text) @@ -287,7 +288,7 @@ export class ValidatorListener implements JackParserListener { class BinaryTreeNode { _returns?: boolean; constructor( - public parent: BinaryTreeNode | undefined, + public parent?: BinaryTreeNode, public left?: BinaryTreeNode, public right?: BinaryTreeNode) { } @@ -336,7 +337,6 @@ class BinaryTreeNode { #pad(prefix: string, side: Side): string { return side == Side.LEFT ? "├──" : "└──"; } - } enum Side { LEFT, diff --git a/compiler/src/listener/vm.writer.listener.ts b/compiler/src/listener/vm.writer.listener.ts new file mode 100644 index 00000000..867ba12c --- /dev/null +++ b/compiler/src/listener/vm.writer.listener.ts @@ -0,0 +1,86 @@ +import { TerminalNode } from "antlr4ts/tree/TerminalNode"; +import { JackParserListener } from "../generated/JackParserListener"; +import { BinaryOperatorContext, ClassDeclarationContext, ConstantContext, ExpressionContext, ReturnStatementContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext } from "../generated/JackParser"; +import { GenericSymbol } from "../symbol"; + +const binaryOperationToVmCmd: Record = { + "+": "add", + "-": "sub", + "*": "call Math.multiply 2", + "/": "call Math.divide 2", + "&": "and", + "|": "or", + "<": "lt", + ">": "gt", + "=": "eq", +}; + +const unaryOperationToVmCmd: Record = { + "-": "neg", + "~": "not", +}; + +export class VMWriter implements JackParserListener { + public result: string = "" + private className: string = ""; + constructor(private globalSymbolTable: Record) { + } + enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { + const name = ctx.subroutineDecWithoutType().subroutineName().IDENTIFIER().text + const symbol = this.globalSymbolTable[this.className + "." + name] + if (symbol == undefined) { + throw new Error(`Can't find subroutine ${name} in class ${this.className} in symbol table`) + } + this.result += `function ${this.className}.${name} ${symbol.subroutineInfo!.localVarsCount}\n`; + + if (ctx.subroutineType().CONSTRUCTOR() != undefined) { + this.result += " push constant 0\n" + this.result += " call Memory.alloc 1\n" + this.result += " pop pointer 0\n" + } else if (ctx.subroutineType().METHOD() != undefined) { + this.result += " push argument 0\n"; + this.result += " pop pointer 0\n"; + } + }; + enterClassDeclaration(ctx: ClassDeclarationContext) { + if (this.className != "") { + throw new Error("Cannot change class name") + } + this.className = ctx.className()!.text; + }; + enterConstant(ctx: ConstantContext) { + if (ctx.INTEGER_LITERAL() != undefined) { + this.result += ` push constant ${ctx.INTEGER_LITERAL()!.text}\n`; + } + }; + exitExpression(ctx: ExpressionContext) { + if (ctx.binaryOperator() != undefined) { + const binaryOp = ctx.binaryOperator()!.text + if (binaryOperationToVmCmd[binaryOp] == undefined) { + throw new Error(`Unknown binary operator ${binaryOp}`) + } + this.result += "\t" + binaryOperationToVmCmd[binaryOp] + "\n"; + } else if (ctx.unaryOperation() != undefined) { + const unaryOp = ctx.unaryOperation()!.unaryOperator().text; + if (unaryOperationToVmCmd[unaryOp] == undefined) { + throw new Error(`Unknown unary operator ${unaryOp}`) + } + this.result += "\t" + unaryOperationToVmCmd[unaryOp] + "\n"; + } + }; + exitReturnStatement(ctx: ReturnStatementContext) { + if (ctx.expression()?.constant()?.THIS_LITERAL() != undefined) { + this.result += " push pointer 0\n"; + } else if (ctx.expression() == undefined) { + this.result += " push constant 0\n"; + } + this.result += " return\n"; + }; + enterSubroutineCall(ctx: SubroutineCallContext) { + this.result += " call A.b 0\n"; + this.result += " pop temp 0\n"; + }; + //to fix compiler error + visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; + +} \ No newline at end of file diff --git a/compiler/src/resources/JackLexer.g4 b/compiler/src/resources/JackLexer.g4 new file mode 100644 index 00000000..7ad3e5ca --- /dev/null +++ b/compiler/src/resources/JackLexer.g4 @@ -0,0 +1,61 @@ +lexer grammar JackLexer; + +CLASS: 'class'; +CONSTRUCTOR: 'constructor'; +FUNCTION: 'function'; +METHOD: 'method'; +FIELD: 'field'; +STATIC: 'static'; +VAR: 'var'; +INT: 'int'; +CHAR: 'char'; +BOOLEAN: 'boolean'; +VOID: 'void'; + +LET: 'let'; +DO: 'do'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +RETURN: 'return'; + + +LBRACE: '{'; +RBRACE: '}'; +LPAREN: '('; +RPAREN: ')'; +LBRACKET: '['; +RBRACKET: ']'; +DOT: '.'; +COMMA: ','; +SEMICOLON: ';'; + +EQUALS: '='; +PLUS: '+'; +MINUS: '-'; +MUL: '*'; +DIV: '/'; +AND: '&'; +OR: '|'; +TILDE: '~'; +LESS_THAN: '<'; +GREATER_THAN: '>'; + +WS: [ \t\r\n]+ -> skip; +COMMENT: '/*' .*? '*/' -> skip; +LINE_COMMENT: '//' ~[\r\n]* -> skip; + +INTEGER_LITERAL: [0-9]+; +BOOLEAN_LITERAL: 'true' | 'false'; +NULL_LITERAL: 'null'; +THIS_LITERAL: 'this'; + +IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; + +STRING_LITERAL + : UnterminatedStringLiteral '"' + ; +UnterminatedStringLiteral + : '"' ~["\\\r\n]* + ; + diff --git a/compiler/src/resources/JackParser.g4 b/compiler/src/resources/JackParser.g4 new file mode 100644 index 00000000..c3d3bcd1 --- /dev/null +++ b/compiler/src/resources/JackParser.g4 @@ -0,0 +1,90 @@ +parser grammar JackParser; + +options { + tokenVocab = JackLexer; +} + +program: classDeclaration EOF; + +classDeclaration: + CLASS className LBRACE classVarDec* subroutineDeclaration* rBrace; +className: IDENTIFIER; +classVarDec: (STATIC | FIELD) fieldList SEMICOLON; +fieldList: varType fieldName ( COMMA fieldName)*; +fieldName: IDENTIFIER; +subroutineDeclaration: subroutineType subroutineDecWithoutType; +subroutineType: CONSTRUCTOR | METHOD | FUNCTION; +subroutineDecWithoutType: + subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; +subroutineName: IDENTIFIER; +subroutineReturnType: varType | VOID; + +varType: INT | CHAR | BOOLEAN | IDENTIFIER; + +parameterList: (parameter (COMMA parameter)*)?; +parameter: varType parameterName; +parameterName: IDENTIFIER; +subroutineBody: LBRACE varDeclaration* statements rBrace; +rBrace: RBRACE; +varDeclaration: + VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; +varNameInDeclaration: IDENTIFIER; +varName: IDENTIFIER; +statements: statement*; +statement: + letStatement + | ifElseStatement + | whileStatement + | doStatement + | returnStatement; + +letStatement: + LET (varName | arrayAccess) EQUALS expression SEMICOLON; //TODO: check if we need right assoc for this + +ifElseStatement: ifStatement elseStatement?; +ifStatement: + IF LPAREN expression RPAREN LBRACE statements rBrace; +elseStatement: ELSE LBRACE statements rBrace; + +whileStatement: + WHILE LPAREN expression RPAREN LBRACE statements rBrace; + +doStatement: DO subroutineCall SEMICOLON; + +subroutineCall: subroutineId LPAREN expressionList RPAREN; +subroutineId: ((className | THIS_LITERAL) DOT)? subroutineName; +returnStatement: RETURN expression? SEMICOLON; + +expressionList: (expression (COMMA expression)*)?; + +expression: + binaryOperation = expression binaryOperator expression + | constant + | varName + | subroutineCall + | arrayAccess + | unaryOp + | groupedExpression; + +groupedExpression: LPAREN expression RPAREN; +unaryOp: unaryOperator expression; +arrayAccess: varName LBRACKET expression RBRACKET; + +constant: + INTEGER_LITERAL + | STRING_LITERAL + | BOOLEAN_LITERAL + | NULL_LITERAL + | THIS_LITERAL; + +unaryOperator: TILDE | MINUS; +binaryOperator: + PLUS + | MINUS + | MUL + | DIV + | AND + | OR + | LESS_THAN + | GREATER_THAN + | EQUALS; \ No newline at end of file diff --git a/compiler/src/symbol.ts b/compiler/src/symbol.ts index b07f7ae1..c8b7a597 100644 --- a/compiler/src/symbol.ts +++ b/compiler/src/symbol.ts @@ -9,6 +9,7 @@ export enum SubroutineType { export interface SubroutineInfo { paramsCount: number; type: SubroutineType + localVarsCount?: number; } /** * Symbol that represents class or a subroutine @@ -16,8 +17,12 @@ export interface SubroutineInfo { export interface GenericSymbol { subroutineInfo?: SubroutineInfo; } -export function createSubroutineSymbol(paramsCount: number, type: SubroutineType) { - return { subroutineInfo: { paramsCount, type } } as GenericSymbol +export function createSubroutineSymbol(paramsCount: number, type: SubroutineType, localVarsCount?: number): GenericSymbol { + const s = { paramsCount, type } as SubroutineInfo; + if (localVarsCount != undefined) { + s.localVarsCount = localVarsCount + } + return { subroutineInfo: s } as GenericSymbol } type VariableType = string diff --git a/compiler/test/global.symbol.table.listener.test.ts b/compiler/test/binder.listener.test.ts similarity index 87% rename from compiler/test/global.symbol.table.listener.test.ts rename to compiler/test/binder.listener.test.ts index a5913b61..600ae71e 100644 --- a/compiler/test/global.symbol.table.listener.test.ts +++ b/compiler/test/binder.listener.test.ts @@ -1,14 +1,11 @@ -import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; -import { ErrorListener } from "../src/listener/error.listener"; -import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.listener"; -import { DuplicatedSubroutineError, JackCompilerError } from "../src/error"; -import { getTestResourcePath, listenToTheTree, handleErrors, parseJackText, parseJackFile } from "./test.helper"; import fs from 'fs'; import path from "path"; -import { ProgramContext } from "../src/generated/JackParser"; +import { DuplicatedSubroutineError } from "../src/error"; +import { BinderListener } from "../src/listener/binder.listener"; import { createSubroutineSymbol, SubroutineType } from "../src/symbol"; +import { getTestResourcePath, listenToTheTree, parseJackFile } from "./test.helper"; -describe('Global symbol table', () => { +describe('Binder', () => { const jestConsole = console; beforeEach(() => { @@ -22,7 +19,7 @@ describe('Global symbol table', () => { test("should fail on duplicated subroutine", () => { const filePath = getTestResourcePath("DuplicatedSubroutine.jack"); const tree = parseJackFile(filePath) - const globalSymbolsListener = new GlobalSymbolTableListener() + const globalSymbolsListener = new BinderListener() listenToTheTree(tree, globalSymbolsListener) const symbolsErrors = globalSymbolsListener.errors expect(globalSymbolsListener.errors.length).toBe(1) @@ -32,6 +29,7 @@ describe('Global symbol table', () => { test("basic", () => { const expected = { + //built in classes "Array": {}, "Keyboard": {}, "Math": {}, @@ -84,19 +82,20 @@ describe('Global symbol table', () => { 'Sys.error': createSubroutineSymbol(1, SubroutineType.Function), 'Sys.halt': createSubroutineSymbol(0, SubroutineType.Function), 'Sys.wait': createSubroutineSymbol(1, SubroutineType.Function), + //test files symbols 'Fraction': {}, - 'Fraction.new': createSubroutineSymbol(2, SubroutineType.Constructor), - 'Fraction.reduce': createSubroutineSymbol(0, SubroutineType.Method), - 'Fraction.getNumerator': createSubroutineSymbol(0, SubroutineType.Method), - 'Fraction.getDenominator': createSubroutineSymbol(0, SubroutineType.Method), - 'Fraction.plus': createSubroutineSymbol(1, SubroutineType.Method), - 'Fraction.dispose': createSubroutineSymbol(0, SubroutineType.Method), - 'Fraction.print': createSubroutineSymbol(0, SubroutineType.Method), - 'Fraction.gcd': createSubroutineSymbol(2, SubroutineType.Function), + 'Fraction.new': createSubroutineSymbol(2, SubroutineType.Constructor, 0), + 'Fraction.reduce': createSubroutineSymbol(0, SubroutineType.Method, 1), + 'Fraction.getNumerator': createSubroutineSymbol(0, SubroutineType.Method, 0), + 'Fraction.getDenominator': createSubroutineSymbol(0, SubroutineType.Method, 0), + 'Fraction.plus': createSubroutineSymbol(1, SubroutineType.Method, 1), + 'Fraction.dispose': createSubroutineSymbol(0, SubroutineType.Method, 0), + 'Fraction.print': createSubroutineSymbol(0, SubroutineType.Method, 0), + 'Fraction.gcd': createSubroutineSymbol(2, SubroutineType.Function, 1), 'Main': {}, - 'Main.main': createSubroutineSymbol(0, SubroutineType.Function), + 'Main.main': createSubroutineSymbol(0, SubroutineType.Function, 3), } - let globalSymbolsListener = new GlobalSymbolTableListener() + let globalSymbolsListener = new BinderListener() const testFolder = getTestResourcePath("Fraction"); const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); diff --git a/compiler/test/compiler.test.ts b/compiler/test/compiler.test.ts new file mode 100644 index 00000000..3429783b --- /dev/null +++ b/compiler/test/compiler.test.ts @@ -0,0 +1,617 @@ +import Compiler from "../src/compiler"; + +describe("Compiler", () => { + test('empty class', () => { + const input = `class A{}` + const expected = ``; + }) + + test('static field', () => { + const input = `class A{ + static int a; + function void init(){ + let a=1; + return; + } + }` + const expected = ` + + `; + }) + test('field', () => { + const input = ` + class A{ + field int a; + method void init(){ + let a=1; + return; + } + }` + const expected = ` + + `; + }) + + test('empty constructor', () => { + const input = `class A{ + constructor A new(){ + return this; + } + }` + const expected = ` + + `; + }) + test('empty function', () => { + const input = ` + class A{ + function void init(){ + return; + } + } + ` + const expected = ` + + `; + }) + test('empty method', () => { + const input = ` + class A{ + method void init(){ + return; + } + }` + const expected = ` + + `; + }) + + test('constructor with parameters', () => { + const input = `` + const expected = ` + + `; + }) + test('method with parameters', () => { + const input = ` + class A{ + method void init(int a, boolean b){ + return; + } + } + ` + const expected = ` + + `; + }) + test('function with parameters', () => { + const input = ` + class A{ + function void init(int a, boolean b){ + return; + } + } + ` + const expected = ` + + `; + }) + + test('int var declaration', () => { + const input = ` + class A{ + function void a(){ + var boolean b; + return; + } + } + ` + const expected = ` + + `; + }) + test('boolean var declaration', () => { + const input = ` + ` + const expected = ` + + `; + }) + test('char var declaration', () => { + const input = ` + ` + const expected = ` + + `; + }) + test('string var declaration', () => { + const input = ` + ` + const expected = ` + + `; + }) + test('class var declaration', () => { + const input = ` + ` + const expected = ` + + `; + }) + //Assign + test('boolean literal assign', () => { + const input = ` + class A{ + function void a(){ + var boolean b; + let b = true; + return; + } + } + ` + const expected = ` + + `; + }) + test('char literal assign', () => { + const input = ` + class A{ + function void a(){ + var char b; + let b = 1; + return; + } + }` + const expected = ` + + `; + }) + test('null literal assign', () => { + const input = ` + class A{ + function void a(){ + var A b; + let a = null; + return; + } + } + ` + const expected = ` + + `; + }) + test('this literal assign', () => { + const input = ` + class A{ + method void a(){ + var A b; + let b = this; + return; + } + } + ` + const expected = ` + + `; + }) + test('int literal assign', () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = 1; + return; + } + } + ` + const expected = ` + + `; + }) + test('assignment for binary operation', () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = 2*3; + return; + } + } + ` + const expected = ` + function A.a 1 + push constant 2 + push constant 3 + call Math.multiply 2 + pop local 0 + push constant 0 + return + `; + testCompiler(input,expected); + }) + test('assignment for varname', () => { + const input = ` + class A{ + function void a(){ + var boolean b,c; + let c=true; + let b=c; + return; + } + } + ` + const expected = ` + function A.a 2 + push constant 1 + neg + pop local 1 + push local 1 + pop local 0 + push constant 0 + return + `; + }) + test('assignment for subroutine call', () => { + const input = ` + class A{ + function int a(){ + return 1; + } + function void b(){ + var boolean b; + let b = A.a(); + return; + } + } + ` + const expected = ` + function A.a 0 + push constant 1 + return + function A.b 1 + call A.a 0 + pop local 0 + push constant 0 + return + `; + }) + test('assignment for array access', () => { + const input = ` + class A{ + function void a(){ + var Array arr; + let arr = Array.new(10); + let arr[0] = 1; + let arr[1] = arr[0]; + return; + } + } + ` + const expected = ` + function A.a 1 + push constant 10 + call Array.new 1 + pop local 0 + push constant 0 + push local 0 + add + push constant 1 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 1 + push local 0 + add + push constant 0 + push local 0 + add + pop pointer 1 + push that 0 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 0 + return + `; + }) + test('assignment to -1', () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = -1; + return; + } + }` + const expected = ` + function A.a 1 + push constant 1 + neg + pop local 0 + push constant 0 + return + `; + testCompiler(input,expected); + }) + test('assignment to ~1', () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = ~1; + return; + } + } + ` + const expected = ` + function A.a 1 + push constant 1 + not + pop local 0 + push constant 0 + return + `; + testCompiler(input,expected); + }) + test('assignment for grouped expr', () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = 2*(3+5); + return; + } + }` + const expected = ` + function A.a 1 + push constant 2 + push constant 3 + push constant 5 + add + call Math.multiply 2 + pop local 0 + push constant 0 + return + `; + }) + + test('if statement', () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = true; + if(b){ + let b = false; + } + return; + } + }` + const expected = ` + function A.a 1 + push constant 1 + neg + pop local 0 + push local 0 + not + if-goto A_1 + push constant 0 + pop local 0 + goto A_0 + label A_1 + label A_0 + push constant 0 + return + `; + }) + test('if else statement', () => { + const input = ` + class A{ + function void a(){ + var boolean b; + var int a; + let b = true; + if(b){ + let a = 1; + }else{ + let a = 2; + } + return; + } + }` + const expected = ` + function A.a 2 + push constant 1 + neg + pop local 0 + push local 0 + not + if-goto A_1 + push constant 1 + pop local 1 + goto A_0 + label A_1 + push constant 2 + pop local 1 + label A_0 + push constant 0 + return + `; + }) + test('while constant', () => { + const input = ` + class A{ + function void a(){ + var int i; + let i = 1; + while(i<10){ + let i=i+1; + } + return; + } + }` + const expected = ` + function A.a 1 + push constant 1 + pop local 0 + label A_0 + push local 0 + push constant 10 + lt + not + if-goto A_1 + push local 0 + push constant 1 + add + pop local 0 + goto A_0 + label A_1 + push constant 0 + return + `; + }) + + test('function call', () => { + const input = ` + class A{ + function void b(){ + return; + } + function void a(){ + do A.b(); + return; + } + }` + const expected = ` + function A.b 0 + push constant 0 + return + function A.a 0 + call A.b 0 + pop temp 0 + push constant 0 + return + `; + testCompiler(input,expected); + }) + test('method call', () => { + const input = ` + class A{ + method void b(){ + return; + } + method void a(){ + do b(); + return; + } + }` + const expected = ` + function A.b 0 + push argument 0 + pop pointer 0 + push constant 0 + return + function A.a 0 + push argument 0 + pop pointer 0 + push pointer 0 + call A.b 1 + pop temp 0 + push constant 0 + return + `; + //TODO: add + // testCompiler(input,expected); + }) + test('constructor', () => { + const input = ` + class A{ + constructor A new(){ + return this; + } + }` + const expected = ` + function A.new 0 + push constant 0 + call Memory.alloc 1 + pop pointer 0 + push pointer 0 + return + `; + testCompiler(input,expected); + }) + + test('return literal', () => { + const input = ` + class A{ + method int a(){ + return 1; + } + }` + const expected = ` + function A.a 0 + push argument 0 + pop pointer 0 + push constant 1 + return + `; + testCompiler(input,expected); + }) + test('method return void', () => { + const input = ` + class A{ + method void a(){ + return; + } + }` + const expected = ` + function A.a 0 + push argument 0 + pop pointer 0 + push constant 0 + return + `; + testCompiler(input,expected); + }) + + test('return simple expression', () => { + const input = ` + class A{ + function int a(){ + return 1+2*3; + } + }` + const expected = ` + function A.a 0 + push constant 1 + push constant 2 + add + push constant 3 + call Math.multiply 2 + return + `; + console.log(expected) + testCompiler(input,expected); + }) +}) + +declare global { + interface String { + trimMultiline(): string; + } +} +String.prototype.trimMultiline = function (): string { + return this.split("\n").map(line => line.trim()) + .filter(str => str.replace(/[\s\t]/g, '').length != 0) + .join("\n") +} +function testCompiler(input: string, expected: string): void { + const res = Compiler.compile(input) + if (Array.isArray(res)) { + throw new Error(`Unexpected compilation errors: ${res.join("\n")}`); + } else { + expect(res.trimMultiline()).toEqual(expected.trimMultiline()); + } +} \ No newline at end of file diff --git a/compiler/test/local.symbol.table.test.ts b/compiler/test/local.symbol.table.test.ts index a7545a3f..19919797 100644 --- a/compiler/test/local.symbol.table.test.ts +++ b/compiler/test/local.symbol.table.test.ts @@ -12,6 +12,7 @@ describe('LocalSymbolTable', () => { }); + test('add', () => { const localSymbolTable = new LocalSymbolTable(); const variableNames = ['testVariable1', 'testVariable2', 'testVariable3']; @@ -22,26 +23,6 @@ describe('LocalSymbolTable', () => { expect(localSymbolTable.existsSymbol(variableName + "_")).toBe(false); }); - - }) - test('clear subroutine vars test', () => { - const localSymbolTable = new LocalSymbolTable(); - const classVar = 'a'; - const functionVar = 'b'; - - localSymbolTable.add(ScopeType.This, classVar, "boolean"); - - - localSymbolTable.add(ScopeType.Local, functionVar, "boolean"); - - expect(localSymbolTable.existsSymbol(classVar)).toBe(true); - expect(localSymbolTable.existsSymbol(functionVar)).toBe(true); - - localSymbolTable.clearSubroutineVars(); - - expect(localSymbolTable.existsSymbol(classVar)).toBe(true); - expect(localSymbolTable.existsSymbol(functionVar)).toBe(false); - }) }); \ No newline at end of file diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts index d9a9d6b9..88daf8b5 100644 --- a/compiler/test/parser.test.ts +++ b/compiler/test/parser.test.ts @@ -1,5 +1,5 @@ import fs from 'fs'; -import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.listener"; +import { BinderListener } from "../src/listener/binder.listener"; import path from "path"; import { ErrorListener } from "../src/listener/error.listener"; @@ -17,7 +17,6 @@ describe('Parser', () => { }); test.each(testResourcesDirs)('%s', (dir: string) => { - console.log("Testing " + dir) testJackDir(path.join(__dirname, "resources", dir)); }); test('expected EOF', () => { @@ -46,7 +45,7 @@ function testJackDir(testFolder: string): void { const errorListener = new ErrorListener() errorListener.filepath = filePath; const tree = parseJackFile(filePath) - const globalSymbolsListener = listenToTheTree(tree, new GlobalSymbolTableListener()); + const globalSymbolsListener = listenToTheTree(tree, new BinderListener()); const symbolsErrors = globalSymbolsListener.errors.join("\n") try { expect(globalSymbolsListener.errors.length).toBe(0) diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts index 36c727b4..4b3046ba 100644 --- a/compiler/test/validator.listener.test.ts +++ b/compiler/test/validator.listener.test.ts @@ -1,10 +1,10 @@ import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange as IntLiteralOverflow, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunction, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../src/error" import { ErrorListener } from "../src/listener/error.listener" import { ValidatorListener } from "../src/listener/validator.listener" -import { createSubroutineSymbol, GenericSymbol, SubroutineType } from "../src/symbol" +import { createSubroutineSymbol, GenericSymbol, LocalSymbolTable, SubroutineType } from "../src/symbol" import { listenToTheTree, parseJackFile, parseJackText, testResourcesDirs } from "./test.helper" import fs from 'fs'; -import { GlobalSymbolTableListener } from "../src/listener/global.symbol.table.listener" +import { BinderListener } from "../src/listener/binder.listener" import path from "path" import { ProgramContext } from "../src/generated/JackParser" describe('ValidatorListener', () => { @@ -337,7 +337,7 @@ describe('ValidatorListener', () => { } }`, UnknownSubroutineCallError) }) - + test('incorrect number of parameters when calling a function', () => { testValidator(` class Main { @@ -582,12 +582,11 @@ describe('ValidatorListener', () => { { "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - }) + },) }) //validate files test.concurrent.each(testResourcesDirs)('%s', (dir: string) => { - console.log("Testing " + dir) testJackDir(path.join(__dirname, "resources", dir)); }); @@ -596,7 +595,7 @@ describe('ValidatorListener', () => { function testJackDir(testFolder: string): void { const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); let trees: Record = {} - let globalSymbolsListener: GlobalSymbolTableListener = new GlobalSymbolTableListener(); + let globalSymbolsListener: BinderListener = new BinderListener(); for (const filePath of files) { const errorListener = new ErrorListener() errorListener.filepath = filePath; @@ -605,18 +604,19 @@ function testJackDir(testFolder: string): void { listenToTheTree(tree, globalSymbolsListener) expect(globalSymbolsListener.errors).toEqual([]); } - console.log("Global sym table \n", globalSymbolsListener.globalSymbolTable) for (const filepath of Object.keys(trees)) { const tree = trees[filepath] - console.log(tree.toInfoString) - console.log("Testing " + filepath) const validatorListener = listenToTheTree(tree, new ValidatorListener(globalSymbolsListener.globalSymbolTable)); expect(validatorListener.errors).toEqual([]); } } -function testValidator(src: string, expectedError?: T, globalSymbolTable: Record = {}) { +function testValidator( + src: string, + expectedError?: T, + globalSymbolTable: Record = {}, +) { const name = expect.getState().currentTestName! const errorListener = new ErrorListener(); errorListener.filepath = name; @@ -639,8 +639,13 @@ function testValidator(src: string, expectedError?: } else { if (validator.errors.length != 0) throw new Error("Didn't expect any errors but got " + validator.errors.join("\n")) } + // if (expectedLocalSymbolTable != undefined) { + // expect(validator.localSymbolTable).toEqual(expectedLocalSymbolTable) + // } } +//TODO: add validation for assgining from void function call +//TODO: Add rule to forbid var use before assignment /** * TODO: * Ideas for improvement - From fec5790ba604fb00196b20ad903f842f6fb312d6 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:19:11 +0200 Subject: [PATCH 25/87] WIP --- .vscode/launch.json | 6 + simulator/package.json | 6 +- simulator/src/jack/builtins.ts | 93 + simulator/src/jack/compiler.test.ts | 1099 ++++- simulator/src/jack/compiler.ts | 712 +--- simulator/src/jack/controlFlow.ts | 180 - simulator/src/jack/error.ts | 256 ++ simulator/src/jack/generated/JackLexer.interp | 158 + simulator/src/jack/generated/JackLexer.tokens | 87 + simulator/src/jack/generated/JackLexer.ts | 398 ++ .../src/jack/generated/JackParser.interp | 148 + .../src/jack/generated/JackParser.tokens | 87 + simulator/src/jack/generated/JackParser.ts | 3739 +++++++++++++++++ .../src/jack/generated/JackParserListener.ts | 486 +++ .../src/jack/listener/binder.listener.test.ts | 138 + .../src/jack/listener/binder.listener.ts | 99 + simulator/src/jack/listener/common.ts | 45 + simulator/src/jack/listener/error.listener.ts | 34 + .../jack/listener/validator.listener.test.ts | 834 ++++ .../src/jack/listener/validator.listener.ts | 583 +++ .../src/jack/listener/vm.writer.listener.ts | 286 ++ simulator/src/jack/parser.test.ts | 60 + .../src/jack/resources/test/Average/Main.jack | 27 + .../src/jack/resources/test/Average/Main.vm | 148 + .../resources/test/ComplexArrays/Main.jack | 69 + .../jack/resources/test/ComplexArrays/Main.vm | 688 +++ .../resources/test/ConvertToBin/Main.jack | 79 + .../jack/resources/test/ConvertToBin/Main.vm | 101 + .../resources/test/Fraction/Fraction.jack | 65 + .../jack/resources/test/Fraction/Fraction.vm | 110 + .../jack/resources/test/Fraction/Main.jack | 16 + .../src/jack/resources/test/Fraction/Main.vm | 17 + .../jack/resources/test/HelloWorld/Main.jack | 14 + .../jack/resources/test/HelloWorld/Main.vm | 31 + .../src/jack/resources/test/List/List.jack | 48 + .../src/jack/resources/test/List/List.vm | 60 + .../src/jack/resources/test/List/Main.jack | 17 + .../src/jack/resources/test/List/Main.vm | 17 + .../src/jack/resources/test/Pong/Ball.jack | 202 + .../src/jack/resources/test/Pong/Ball.vm | 417 ++ .../src/jack/resources/test/Pong/Bat.jack | 103 + simulator/src/jack/resources/test/Pong/Bat.vm | 187 + .../src/jack/resources/test/Pong/Main.jack | 18 + .../src/jack/resources/test/Pong/Main.vm | 10 + .../jack/resources/test/Pong/PongGame.jack | 136 + .../src/jack/resources/test/Pong/PongGame.vm | 287 ++ .../src/jack/resources/test/Square/Main.jack | 15 + .../src/jack/resources/test/Square/Main.vm | 9 + .../jack/resources/test/Square/Square.jack | 113 + .../src/jack/resources/test/Square/Square.vm | 272 ++ .../resources/test/Square/SquareGame.jack | 76 + .../jack/resources/test/Square/SquareGame.vm | 157 + simulator/src/jack/symbol.table.test.ts | 156 + simulator/src/jack/symbol.ts | 131 + simulator/src/jack/test.helper.ts | 82 + simulator/src/languages/grammars/JackLexer.g4 | 62 + .../src/languages/grammars/JackParser.g4 | 99 + 57 files changed, 12652 insertions(+), 921 deletions(-) create mode 100644 simulator/src/jack/builtins.ts delete mode 100644 simulator/src/jack/controlFlow.ts create mode 100644 simulator/src/jack/error.ts create mode 100644 simulator/src/jack/generated/JackLexer.interp create mode 100644 simulator/src/jack/generated/JackLexer.tokens create mode 100644 simulator/src/jack/generated/JackLexer.ts create mode 100644 simulator/src/jack/generated/JackParser.interp create mode 100644 simulator/src/jack/generated/JackParser.tokens create mode 100644 simulator/src/jack/generated/JackParser.ts create mode 100644 simulator/src/jack/generated/JackParserListener.ts create mode 100644 simulator/src/jack/listener/binder.listener.test.ts create mode 100644 simulator/src/jack/listener/binder.listener.ts create mode 100644 simulator/src/jack/listener/common.ts create mode 100644 simulator/src/jack/listener/error.listener.ts create mode 100644 simulator/src/jack/listener/validator.listener.test.ts create mode 100644 simulator/src/jack/listener/validator.listener.ts create mode 100644 simulator/src/jack/listener/vm.writer.listener.ts create mode 100644 simulator/src/jack/parser.test.ts create mode 100644 simulator/src/jack/resources/test/Average/Main.jack create mode 100644 simulator/src/jack/resources/test/Average/Main.vm create mode 100644 simulator/src/jack/resources/test/ComplexArrays/Main.jack create mode 100644 simulator/src/jack/resources/test/ComplexArrays/Main.vm create mode 100644 simulator/src/jack/resources/test/ConvertToBin/Main.jack create mode 100644 simulator/src/jack/resources/test/ConvertToBin/Main.vm create mode 100644 simulator/src/jack/resources/test/Fraction/Fraction.jack create mode 100644 simulator/src/jack/resources/test/Fraction/Fraction.vm create mode 100644 simulator/src/jack/resources/test/Fraction/Main.jack create mode 100644 simulator/src/jack/resources/test/Fraction/Main.vm create mode 100644 simulator/src/jack/resources/test/HelloWorld/Main.jack create mode 100644 simulator/src/jack/resources/test/HelloWorld/Main.vm create mode 100644 simulator/src/jack/resources/test/List/List.jack create mode 100644 simulator/src/jack/resources/test/List/List.vm create mode 100644 simulator/src/jack/resources/test/List/Main.jack create mode 100644 simulator/src/jack/resources/test/List/Main.vm create mode 100644 simulator/src/jack/resources/test/Pong/Ball.jack create mode 100644 simulator/src/jack/resources/test/Pong/Ball.vm create mode 100644 simulator/src/jack/resources/test/Pong/Bat.jack create mode 100644 simulator/src/jack/resources/test/Pong/Bat.vm create mode 100644 simulator/src/jack/resources/test/Pong/Main.jack create mode 100644 simulator/src/jack/resources/test/Pong/Main.vm create mode 100644 simulator/src/jack/resources/test/Pong/PongGame.jack create mode 100644 simulator/src/jack/resources/test/Pong/PongGame.vm create mode 100644 simulator/src/jack/resources/test/Square/Main.jack create mode 100644 simulator/src/jack/resources/test/Square/Main.vm create mode 100644 simulator/src/jack/resources/test/Square/Square.jack create mode 100644 simulator/src/jack/resources/test/Square/Square.vm create mode 100644 simulator/src/jack/resources/test/Square/SquareGame.jack create mode 100644 simulator/src/jack/resources/test/Square/SquareGame.vm create mode 100644 simulator/src/jack/symbol.table.test.ts create mode 100644 simulator/src/jack/symbol.ts create mode 100644 simulator/src/jack/test.helper.ts create mode 100644 simulator/src/languages/grammars/JackLexer.g4 create mode 100644 simulator/src/languages/grammars/JackParser.g4 diff --git a/.vscode/launch.json b/.vscode/launch.json index 6b93aff1..4e0a1a05 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -34,6 +34,12 @@ ], "outFiles": ["${workspaceFolder}/extension/build/test/**/*.js"], "preLaunchTask": "${defaultBuildTask}" + }, { + "type": "chrome", + "request": "launch", + "name": "Test web ide", + "url": "http://localhost:3000/web-ide", + "webRoot": "${workspaceFolder}" } ] } diff --git a/simulator/package.json b/simulator/package.json index 16a81357..347c3989 100644 --- a/simulator/package.json +++ b/simulator/package.json @@ -22,6 +22,8 @@ "@nand2tetris/projects": "^1.0.0", "@nand2tetris/runner": "^1.0.0", "@types/node": "^20.14.2", + "antlr4": "^4.13.2", + "assert": "^2.1.0", "ohm-js": "^17.1.0", "rxjs": "^7.8.1" }, @@ -35,6 +37,8 @@ }, "scripts": { "build": "tsc", - "test": "jest --verbose" + "test": "jest --verbose", + "test-w": "jest --watchAll --verbose", + "gen": "cd src/languages/grammars && antlr4 -Dlanguage=TypeScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" } } diff --git a/simulator/src/jack/builtins.ts b/simulator/src/jack/builtins.ts new file mode 100644 index 00000000..4e73cc06 --- /dev/null +++ b/simulator/src/jack/builtins.ts @@ -0,0 +1,93 @@ +import { GenericSymbol, SubroutineType } from "./symbol.js"; + +export const builtInTypes = ["int", "boolean", "char"]; +interface Range { + min: number; + max: number; +} +export const intRange = { min: -32768, max: 32767 } as Range; +//TODO: should we convert this to symbols? +const builtInFunctionsToArgCount: Record = { + "Array.dispose": 0, + //TODO: what is this? + // "Array.init": 0, + "Array.new": 1, + "Keyboard.init": 0, + "Keyboard.keyPressed": 0, + "Keyboard.readChar": 0, + "Keyboard.readInt": 1, + "Keyboard.readLine": 1, + "Math.abs": 1, + "Math.divide": 2, + //TODO: what is this ? + // "Math.init": 0, + "Math.max": 2, + "Math.min": 2, + "Math.multiply": 2, + "Math.sqrt": 1, + "Memory.alloc": 1, + "Memory.deAlloc": 1, + // "Memory.init": 0, + "Memory.peek": 1, + "Memory.poke": 2, + "Output.backSpace": 0, + // "Output.init": 0, + "Output.moveCursor": 2, + "Output.printChar": 1, + "Output.printInt": 1, + "Output.println": 0, + "Output.printString": 1, + "Screen.clearScreen": 0, + "Screen.drawCircle": 3, + "Screen.drawLine": 4, + "Screen.drawPixel": 2, + "Screen.drawRectangle": 4, + // "Screen.init": 0, + "Screen.setColor": 1, + "String.appendChar": 1, + "String.backSpace": 0, + "String.charAt": 2, + "String.dispose": 0, + "String.doubleQuote": 0, + "String.eraseLastChar": 0, + // "String.init": 0, + "String.intValue": 0, + "String.length": 0, + "String.new": 1, + "String.newLine": 0, + "String.setCharAt": 1, + "String.setInt": 1, + "Sys.error": 1, + "Sys.halt": 0, + "Sys.wait": 1, +}; +const builtInClasses = [ + "Array", + "Keyboard", + "Math", + "Memory", + "Output", + "Screen", + "String", + "Sys", +]; +const builtInClassesRecord = builtInClasses.reduce( + (acc, elem) => ({ + ...acc, + [elem]: {} as GenericSymbol, + }), + {} as Record, +); + +export const builtInSymbols = Object.keys(builtInFunctionsToArgCount).reduce( + (acc, elem) => ({ + ...acc, + [elem]: { + subroutineInfo: { + paramsCount: builtInFunctionsToArgCount[elem], + type: SubroutineType.Function, + }, + } as GenericSymbol, + }), + builtInClassesRecord, +); diff --git a/simulator/src/jack/compiler.test.ts b/simulator/src/jack/compiler.test.ts index 19afc722..1620e4dc 100644 --- a/simulator/src/jack/compiler.test.ts +++ b/simulator/src/jack/compiler.test.ts @@ -1,126 +1,983 @@ -import { Programs } from "@nand2tetris/projects/samples/project_11/index.js"; -import { JACK } from "../languages/jack"; -import { Compiler, compile } from "./compiler"; +import fs from "fs"; +import { getTestResourcePath, testResourceDirs } from "./test.helper"; +import path from "path"; +import { ProgramContext } from "./generated/JackParser"; +import { Compiler } from "./compiler"; +describe("Compiler", () => { + test("static field", () => { + testCompiler( + `class A{ + static int a; + function void init(){ + let a=1; + return; + } + }`, + ` + function A.init 0 + push constant 1 + pop static 0 + push constant 0 + return + `, + ); + }); + test("field", () => { + testCompiler( + ` + class A{ + field int a; + method void init(){ + let a=1; + return; + } + }`, + ` + function A.init 0 + push argument 0 + pop pointer 0 + push constant 1 + pop this 0 + push constant 0 + return + `, + ); + }); -function parse(code: string, rule: string) { - return JACK.semantics(JACK.parser.match(code, rule)); -} + test("function with parameters", () => { + const input = ` + class A{ + function void a(int a){ + var int b; + let b = a + 1; + return; + } + }`; + const expected = ` + function A.a 1 + push argument 0 + push constant 1 + add + pop local 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); -describe("compiler", () => { - it("compiles expression", () => { - const exp = parse("(2 + 3) * 5", "Expression").expression; - - const compiler = new Compiler(); - compiler.compileExpression(exp); - expect(compiler.output).toEqual([ - "push constant 2", - "push constant 3", - "add", - "push constant 5", - "call Math.multiply 2", - ]); - }); - - it("compiles function", () => { - const func = parse( - `function void main() { - var int a; - let a = 4; - return; - }`, - "SubroutineDec", - ).subroutineDec; - - const compiler = new Compiler(); - compiler.className = "Main"; - compiler.compileFunction(func); - expect(compiler.output).toEqual([ - "function Main.main 1", - "push constant 4", - "pop local 0", - "push constant 0", - "return", - ]); - }); - - it("compiles array access", () => { - const statement = parse(`let x = arr[2];`, "Statement").statement; - - const compiler = new Compiler(); - compiler.localSymbolTable = { - x: { - type: "int", - segment: "local", - index: 0, - }, - arr: { - type: "Array", - segment: "local", - index: 1, - }, - }; - compiler.compileStatement(statement); - expect(compiler.output).toEqual([ - "push constant 2", - "push local 1", - "add", - "pop pointer 1", - "push that 0", - "pop local 0", - ]); - }); - - it("compiles if-else", () => { - const statement = parse( - `if (condition) { - let x = 4; - } else { - let x = 5; - }`, - "Statement", - ).statement; - - const compiler = new Compiler(); - compiler.className = "Main"; - compiler.localSymbolTable = { - condition: { - type: "boolean", - segment: "local", - index: 0, - }, - x: { - type: "int", - segment: "local", - index: 1, - }, - }; - compiler.compileStatement(statement); - expect(compiler.output).toEqual([ - "push local 0", - "not", - "if-goto Main_1", - "push constant 4", - "pop local 1", - "goto Main_0", - "label Main_1", - "push constant 5", - "pop local 1", - "label Main_0", - ]); - }); - - it.each(Object.keys(Programs))("%s", (program) => { - const compiled = compile( - Object.fromEntries( - Object.entries(Programs[program]).map(([name, file]) => [ - name, - file.jack, - ]), - ), - ); + test("method with parameters", () => { + const input = ` + class A{ + method void a(int a){ + var int b; + let b = a + 1; + return; + } + }`; + const expected = ` + function A.a 1 + push argument 0 + pop pointer 0 + push argument 1 + push constant 1 + add + pop local 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); - for (const file of Object.keys(compiled)) { - expect(compiled[file]).toEqual(Programs[program][file].compiled); - } + //Assign + test("boolean literal assign", () => { + const input = ` + class A{ + function void a(){ + var boolean b; + let b = true; + return; + } + }`; + const expected = ` + function A.a 1 + //true(-1) + push constant 1 + neg + //let b = + pop local 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("boolean literal assign using logical operators", () => { + const input = ` + class A { + function void a(){ + var boolean b; + let b = (1>2) & (3<4) | (5>6) & (7=7); + return; + } + }`; + const expected = ` + function A.a 1 + //1>2 + push constant 1 + push constant 2 + gt + //3<4 + push constant 3 + push constant 4 + lt + and + //5>6 + push constant 5 + push constant 6 + gt + or + //7=7 + push constant 7 + push constant 7 + eq + and + //let b = + pop local 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("char literal assign", () => { + const input = ` + class A{ + function void a(){ + var char b; + let b = 1; + return; + } + }`; + const expected = ` + function A.a 1 + push constant 1 + pop local 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("null literal assign", () => { + const input = ` + class A { + function void a(){ + var A b; + let b = null; + return; + } + }`; + const expected = ` + function A.a 1 + push constant 0 + pop local 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("this literal assign", () => { + const input = ` + class A{ + method void a(){ + var A b; + let b = this; + return; + } + } + `; + const expected = ` + function A.a 1 + // first arg is this + push argument 0 + pop pointer 0 + // let b= this + push pointer 0 + pop local 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("int literal assign", () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = 1; + return; + } + }`; + const expected = ` + function A.a 1 + push constant 1 + pop local 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("string literal assign", () => { + const input = ` + class A{ + function void a(){ + var String b; + let b = "hello"; + return; + } + } + `; + const expected = ` + function A.a 1 + // string length + push constant 5 + //create string array + call String.new 1 + //append chars one by one + push constant 104 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 111 + call String.appendChar 2 + //leb b= + pop local 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("assignment for binary operation", () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = 2*3; + return; + } + }`; + const expected = ` + function A.a 1 + push constant 2 + push constant 3 + call Math.multiply 2 + pop local 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("assignment for varname", () => { + const input = ` + class A{ + function void a(){ + var boolean b,c; + let c=true; + let b=c; + return; + } + } + `; + const expected = ` + function A.a 2 + // create true value (-1) + push constant 1 + neg + // assign to c + pop local 1 + //let b=c + push local 1 + pop local 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("assignment for subroutine call", () => { + const input = ` + class A{ + function int a(){ + return 1; + } + function void b(){ + var boolean b; + let b = A.a(); + return; + } + } + `; + const expected = ` + function A.a 0 + push constant 1 + return + function A.b 1 + call A.a 0 + //let b = + pop local 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + + test("assign array value to a local var", () => { + const input = ` + class A{ + function void a(){ + var Array arr; + var int a; + let arr = Array.new(10); + let a = arr[5]; + return; + } + }`; + const expected = ` + function A.a 2 + //array new + push constant 10 + call Array.new 1 + //let arr= + pop local 0 + //arr[5] + push constant 5 + push local 0 + add + pop pointer 1 + push that 0 + //let a = + pop local 1 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + + test("assignment for array access", () => { + const input = ` + class A{ + function void a(){ + var Array arr; + let arr = Array.new(10); + let arr[5] = 1; + return; + } + }`; + const expected = ` + function A.a 1 + // let arr = Array.new(10); + push constant 10 + call Array.new 1 + pop local 0 + //arr[5] + push constant 5 + push local 0 + add + //=1 + push constant 1 + pop temp 0 + //assign + pop pointer 1 + push temp 0 + pop that 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("assign array value to array value", () => { + const input = ` + class A{ + function void a(){ + var Array arr; + let arr = Array.new(10); + let arr[0] = arr[5]; + return; + } + }`; + const expected = ` + function A.a 1 + // let arr = Array.new(10); + push constant 10 + call Array.new 1 + pop local 0 + //arr[0] + push constant 0 + push local 0 + add + //arr[5] + push constant 5 + push local 0 + add + + //save arr[5] in temp + pop pointer 1 + push that 0 + pop temp 0 + + //assign to arr[0] + pop pointer 1 + push temp 0 + pop that 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("assignment to -1", () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = -1; + return; + } + }`; + const expected = ` + function A.a 1 + push constant 1 + neg + pop local 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("assignment to ~1", () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = ~1; + return; + } + }`; + const expected = ` + function A.a 1 + // ~1; + push constant 1 + not + // let b = + pop local 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("assignment for grouped expr", () => { + const input = ` + class A{ + function void a(){ + var int b; + let b = 2*(3+5); + return; + } + }`; + const expected = ` + function A.a 1 + push constant 2 + push constant 3 + push constant 5 + add + call Math.multiply 2 + pop local 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + + test("if statement", () => { + const input = ` + class A{ + function void a(){ + var boolean b; + let b = true; + if(b){ + let b = false; + } + return; + } + }`; + const expected = ` + function A.a 1 + //let b=true + push constant 1 + neg + pop local 0 + //if(b) + push local 0 + not + //go to end of if + if-goto A_0 + //let b=false + push constant 0 + pop local 0 + label A_0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("if else statement", () => { + const input = ` + class A{ + function void a(){ + var boolean b; + var int a; + let b = true; + if(b){ + let a = 1; + }else{ + let a = 2; + } + return; + } + }`; + const expected = ` + function A.a 2 + //let b=true + push constant 1 + neg + pop local 0 + //if(b) + push local 0 + not + //go to else + if-goto A_0 + push constant 1 + pop local 1 + // go to end of if else + goto A_1 + label A_0 + push constant 2 + pop local 1 + label A_1 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("while constant", () => { + const input = ` + class A{ + function void a(){ + var int i; + let i = 1; + while(i<10){ + let i=i+1; + } + return; + } + }`; + const expected = ` + function A.a 1 + // let i = 1; + push constant 1 + pop local 0 + //while + label A_0 + // i<10 + push local 0 + push constant 10 + lt + // if not go to end + not + if-goto A_1 + // let i=i+1; + push local 0 + push constant 1 + add + pop local 0 + // go to beginning + goto A_0 + label A_1 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + + test("function call", () => { + const input = ` + class A{ + function void b(){ + return; + } + function void a(){ + do A.b(); + return; + } + }`; + const expected = ` + function A.b 0 + push constant 0 + return + function A.a 0 + call A.b 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("var method call", () => { + const input = ` + class A{ + constructor A new(){ + return this; + } + method void b(){ + return; + } + function void a(){ + var A a; + let a = A.new(); + do a.b(); + return; + } + }`; + const expected = ` + function A.new 0 + push constant 0 + call Memory.alloc 1 + pop pointer 0 + push pointer 0 + return + function A.b 0 + push argument 0 + pop pointer 0 + push constant 0 + return + function A.a 1 + call A.new 0 + pop local 0 + push local 0 + call A.b 1 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("var method call with params", () => { + const input = ` + class A{ + constructor A new(){ + return this; + } + method int sum(int a, int b){ + return a+b; + } + function void a(){ + var A a; + var int b; + let a = A.new(); + let b= a.sum(1,2); + return; + } + }`; + const expected = ` + function A.new 0 + push constant 0 + call Memory.alloc 1 + pop pointer 0 + push pointer 0 + return + function A.sum 0 + push argument 0 + pop pointer 0 + push argument 1 + push argument 2 + add + return + function A.a 2 + call A.new 0 + pop local 0 + push local 0 + push constant 1 + push constant 2 + call A.sum 3 + pop local 1 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test("empty class constructor", () => { + const input = ` + class A{ + constructor A new(){ + return this; + } + }`; + const expected = ` + function A.new 0 + //create this + push constant 0 + call Memory.alloc 1 + pop pointer 0 + //return this + push pointer 0 + return + `; + testCompiler(input, expected); + }); + test("class with fields and a constructor", () => { + const input = ` + class A{ + field int a,b,c; + field char d,e,f; + constructor A new(){ + return this; + } + }`; + const expected = ` + function A.new 0 + push constant 6 + call Memory.alloc 1 + pop pointer 0 + push pointer 0 + return + `; + testCompiler(input, expected); + }); + + test("return literal", () => { + const input = ` + class A{ + method int a(){ + return 1; + } + }`; + const expected = ` + function A.a 0 + // push this + push argument 0 + pop pointer 0 + //return 1 + push constant 1 + return + `; + testCompiler(input, expected); + }); + test("method return void", () => { + const input = ` + class A{ + method void a(){ + return; + } + }`; + const expected = ` + function A.a 0 + push argument 0 + pop pointer 0 + //return + push constant 0 + return + `; + testCompiler(input, expected); + }); + + test("return simple expression", () => { + const input = ` + class A{ + function int a(){ + return 1+2*3; + } + }`; + const expected = ` + function A.a 0 + push constant 1 + push constant 2 + //1+2 + add + push constant 3 + //3*3 + call Math.multiply 2 + return + `; + testCompiler(input, expected); + }); + + test("nested expressions", () => { + const input = ` + class A{ + function void a(){ + var Array a, b, c; + + let a = Array.new(10); + let b = Array.new(5); + + let b[a[4]] = a[3] + 3; + return; + } + }`; + const expected = ` + function A.a 3 + // let a = Array.new(10); + push constant 10 + call Array.new 1 + pop local 0 + // let b = Array.new(5); + push constant 5 + call Array.new 1 + pop local 1 + //a[4] + push constant 4 + push local 0 + add + //what? + pop pointer 1 + push that 0 + push local 1 + add + push constant 3 + push local 0 + add + pop pointer 1 + push that 0 + push constant 3 + add + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 0 + return + `; + testCompiler(input, expected); + }); + + test("mutate args", () => { + const input = ` + class A{ + function void fill(Array a, int size) { + while (size > 0) { + let size = size - 1; + let a[size] = Array.new(3); + } + return; + } + }`; + const expected = ` + function A.fill 0 + label A_0 + //size>0 + push argument 1 + push constant 0 + gt + not + if-goto A_1 + //let size = size - 1 + push argument 1 + push constant 1 + sub + pop argument 1 + //let a[size] = Array.new(3); + push argument 1 + push argument 0 + add + push constant 3 + call Array.new 1 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + goto A_0 + label A_1 + push constant 0 + return + `; + testCompiler(input, expected); + }); + test.concurrent.each(testResourceDirs)("%s", (folder: string) => { + testFilesInFolder(folder); }); }); +function testFilesInFolder(folderInTestResources: string) { + const testFolder = getTestResourcePath(folderInTestResources); + const files = fs + .readdirSync(testFolder) + .filter((file) => file.endsWith(".jack")) + .map((file) => path.join(testFolder, file)); + const trees: Record = {}; + const compiler = new Compiler(); + for (const f of files) { + const input = fs.readFileSync(f, { encoding: "utf8", flag: "r" }); + const treeOrErrors = compiler.parserAndBind(input); + if (Array.isArray(treeOrErrors)) { + throw new Error( + `Unexpected compilation errors: ${treeOrErrors.join("\n")}`, + ); + } + const tree = treeOrErrors as ProgramContext; + trees[f] = tree; + } + for (const f of files) { + const expected = fs.readFileSync(f.replace(".jack", ".vm"), "utf8"); + const res = compiler.compile(trees[f]); + if (Array.isArray(res)) { + throw new Error(`Unexpected compilation errors: ${res.join("\n")}`); + } else { + // console.log(res) + expect(trimAndDeleteComments(res)).toEqual( + trimAndDeleteComments(expected), + ); + } + } +} + +function trimMultiline(text: string): string { + return text + .split("\n") + .map((line) => line.trim()) + .filter((str) => str.replace(/[\s\t]/g, "").length != 0) + .join("\n"); +} +function deleteComments(text: string): string { + return text + .split("\n") + .filter((str) => str.indexOf("//") == -1) + .join("\n"); +} + +const compose = (fn1: (a: T) => T, ...fns: Array<(a: T) => T>) => + fns.reduce((prevFn, nextFn) => (value) => prevFn(nextFn(value)), fn1); + +const trimAndDeleteComments = compose(trimMultiline, deleteComments); +function testCompiler(input: string, expected: string): void { + const compiler = new Compiler(); + const treeOrErrors = compiler.parserAndBind(input); + if (Array.isArray(treeOrErrors)) { + throw new Error( + `Unexpected compilation errors: ${treeOrErrors.join("\n")}`, + ); + } + const tree = treeOrErrors as ProgramContext; + const res = compiler.compile(tree); + if (Array.isArray(res)) { + throw new Error(`Unexpected compilation errors: ${res.join("\n")}`); + } else { + expect(trimAndDeleteComments(res)).toEqual(trimAndDeleteComments(expected)); + } +} diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index a0c58b68..788631f7 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -1,633 +1,107 @@ -import { - Err, - Ok, - Result, - isErr, -} from "@davidsouther/jiffies/lib/esm/result.js"; -import { CompilationError, Span, createError } from "../languages/base.js"; -import { - ArrayAccess, - Class, - ClassVarDec, - DoStatement, - Expression, - IfStatement, - JACK, - KeywordConstant, - LetStatement, - Op, - Parameter, - ReturnStatement, - Statement, - Subroutine, - SubroutineCall, - Term, - Type, - UnaryOp, - VarDec, - Variable, - WhileStatement, - isPrimitive, -} from "../languages/jack.js"; -import { Segment } from "../languages/vm.js"; -import { - VM_BUILTINS, - makeInterface, - overridesOsCorrectly, -} from "../vm/builtins.js"; -import { validateSubroutine } from "./controlFlow.js"; - -const osClasses = new Set([ - "Sys", - "Screen", - "Output", - "Keyboard", - "String", - "Array", - "Memory", - "Math", -]); - -function isOsClass(name: string): boolean { - return osClasses.has(name); -} - -function isError(value: unknown): value is CompilationError { - return (value as CompilationError).message != undefined; -} - -function capitalize(s: string) { - return s.charAt(0).toUpperCase() + s.slice(1); -} +import { BinderListener } from "./listener/binder.listener.js"; +import { CustomErrorListener } from "./listener/error.listener.js"; +import { ValidatorListener } from "./listener/validator.listener.js"; +import { JackCompilerError, LexerOrParserError, Span } from "./error.js"; +import { VMWriter } from "./listener/vm.writer.listener.js"; +import JackParser, { ProgramContext } from "./generated/JackParser.js"; +import { CharStreams, CommonTokenStream, ParseTreeWalker } from "antlr4"; +import JackLexer from "./generated/JackLexer.js"; +import { CompilationError, createError } from "../languages/base.js"; export function compile( - files: Record, + files: Record, ): Record { - const classes: Record = {}; - for (const [name, content] of Object.entries(files)) { - const parsed = JACK.parse(content); - if (isErr(parsed)) { - classes[name] = Err(parsed); - } else { - const cls = Ok(parsed); - const result = validateClass(cls); - classes[name] = - cls.name.value == name - ? isErr(result) - ? Err(result) - : cls - : createError( - `Class name ${cls.name.value} doesn't match file name ${name}`, - cls.name.span, - ); - } - } - - const validClasses: Record = Object.fromEntries( - Object.entries(classes).filter(([_, parsed]) => !isError(parsed)), - ) as Record; - - const vms: Record = {}; - for (const [name, parsed] of Object.entries(classes)) { - if (isError(parsed)) { - vms[name] = parsed; - } else { - try { - const compiled = new Compiler().compile(parsed, validClasses); - if (isErr(compiled)) { - vms[name] = Err(compiled); - } else { - vms[name] = Ok(compiled); + try { + return _compile(files) + } catch (err) { + console.error(err); + if (typeof err === "string") { + const result: Record = {}; + const error: CompilationError = createError(err.toUpperCase()) + for (const name in Object.keys(files)) { + result[name] = error; + } + return result; + } else if (err instanceof Error) { + const result: Record = {}; + const error: CompilationError = createError(err.message) + for (const name in Object.keys(files)) { + result[name] = error; + } + return result; } - } catch (e) { - vms[name] = e as CompilationError; - } } - } - return vms; + //to satisfy compiler + return {}; } - -function validateClass(cls: Class): Result { - const subroutineNames = new Set(); - for (const subroutine of cls.subroutines) { - if (subroutineNames.has(subroutine.name.value)) { - return Err( - createError( - `Subroutine ${subroutine.name.value} already declared`, - subroutine.name.span, - ), - ); +function _compile(files: Record, +): Record { + if (files instanceof LexerOrParserError) { + throw new Error("Expected tree but got a lexer or parser error"); + } + const result: Record = {}; + const trees: Record = {}; + const errors: Record = {}; + const compiler = new Compiler(); + for (const [name, content] of Object.entries(files)) { + const treeOrErrors = compiler.parserAndBind(content); + if (Array.isArray(treeOrErrors)) { + const s = treeOrErrors[0].span + errors[name] = { message: treeOrErrors[0].msg, span: { start: s.start, end: s.end, line: 3 } as Span } as CompilationError; + } + trees[name] = treeOrErrors as ProgramContext; } - subroutineNames.add(subroutine.name.value); - const result = validateSubroutine(subroutine); - if (isErr(result)) { - return result; + if (Object.keys(errors).length > 0) { + return errors; } - } - return Ok(); -} - -interface VariableData { - type: Type; - segment: Segment; - index: number; -} - -const ops: Record = { - "+": "add", - "-": "sub", - "*": "call Math.multiply 2", - "/": "call Math.divide 2", - "&": "and", - "|": "or", - "<": "lt", - ">": "gt", - "=": "eq", -}; - -const unaryOps: Record = { - "-": "neg", - "~": "not", -}; - -interface SubroutineCallAttributes { - className: string; - subroutineName: string; - object?: string; // object being acted upon if this is a method (undefined if function / constructor) + for (const [name, tree] of Object.entries(trees)) { + const compiledOrErrors = compiler.compile(tree); + if (Array.isArray(compiledOrErrors)) { + result[name] = { message: compiledOrErrors[0].msg, span: compiledOrErrors[0].span } as CompilationError; + } else { + result[name] = compiledOrErrors; + } + } + return result; } - export class Compiler { - private instructions: string[] = []; - globalSymbolTable: Record = {}; - localSymbolTable: Record = {}; - - className = ""; - private classes: Record = {}; - - private labelNum = 0; - private fieldNum = 0; - private staticNum = 0; - private localNum = 0; - - get output(): string[] { - return Array.from(this.instructions); - } - - varData(name: string): VariableData | undefined { - return this.localSymbolTable[name] || this.globalSymbolTable[name]; - } - - var(name: string): string; - var(variable: Variable): string; - var(variable: ArrayAccess): string; - var(variable: LetStatement): string; - var(arg: string | Variable | ArrayAccess | LetStatement): string { - let name: string; - let span: Span | undefined; - if (typeof arg == "string") { - name = arg; - } else { - if (typeof arg.name == "string") { - name = arg.name; - span = arg.span; - } else { - name = arg.name.value; - span = arg.name.span; - } - } - const data = this.varData(name); - if (!data) { - throw createError(`Undeclared variable ${name}`, span); - } - return `${data.segment} ${data.index}`; - } - - write(...lines: string[]) { - this.instructions.push(...lines); - } - - getLabel() { - const label = `${this.className}_${this.labelNum}`; - this.labelNum += 1; - return label; - } - - compile( - cls: Class, - other?: Record, - ): Result { - this.className = cls.name.value; - this.classes = other ?? {}; - for (const varDec of cls.varDecs) { - this.compileClassVarDec(varDec); - } - for (const subroutine of cls.subroutines) { - this.compileSubroutineDec(subroutine); - } - return Ok( - this.instructions - .map((inst) => - inst.startsWith("function") || inst.startsWith("label") - ? inst - : " ".concat(inst), - ) - .join("\n"), - ); - } - - validateType(type: string, span?: Span) { - if (isPrimitive(type) || isOsClass(type) || this.classes[type]) { - return; - } - throw createError(`Unknown type ${type}`, span); - } - - validateReturnType(returnType: string, span?: Span) { - if (returnType == "void") { - return; - } - this.validateType(returnType, span); - } - - compileClassVarDec(dec: ClassVarDec) { - this.validateType(dec.type.value, dec.type.span); - for (const name of dec.names) { - if (dec.varType == "field") { - this.globalSymbolTable[name] = { - type: dec.type.value, - segment: "this", - index: this.fieldNum, - }; - this.fieldNum += 1; - } else { - this.globalSymbolTable[name] = { - type: dec.type.value, - segment: "static", - index: this.staticNum, - }; - this.staticNum += 1; - } - } - } - - compileVarDec(dec: VarDec) { - this.validateType(dec.type.value, dec.type.span); - for (const name of dec.names) { - this.localSymbolTable[name] = { - type: dec.type.value, - segment: "local", - index: this.localNum, - }; - this.localNum += 1; - } - } - - registerArgs(params: Parameter[], offset = false) { - let argNum = 0; - for (const param of params) { - this.validateType(param.type.value, param.type.span); - this.localSymbolTable[param.name] = { - type: param.type.value, - segment: "argument", - index: argNum + (offset ? 1 : 0), // when compiling a method the first argument is this, so we offset the others by 1 - }; - argNum += 1; - } - } - - validateSubroutineDec(subroutine: Subroutine) { - this.validateReturnType( - subroutine.returnType.value, - subroutine.returnType.span, - ); - - if (isOsClass(this.className)) { - const builtin = VM_BUILTINS[`${this.className}.${subroutine.name.value}`]; - - if (builtin && !overridesOsCorrectly(this.className, subroutine)) { - throw createError( - `OS subroutine ${this.className}.${subroutine.name.value} must follow the interface ${makeInterface(subroutine.name.value, builtin)})`, - ); - } - } - } - - compileSubroutineDec(subroutine: Subroutine) { - this.validateSubroutineDec(subroutine); - switch (subroutine.type) { - case "method": - this.compileMethod(subroutine); - break; - case "constructor": - this.compileConstructor(subroutine); - break; - case "function": - this.compileFunction(subroutine); - } - } - - compileSubroutineStart(subroutine: Subroutine, isMethod = false) { - this.localSymbolTable = {}; - this.localNum = 0; - this.registerArgs(subroutine.parameters, isMethod); - - const localCount = subroutine.body.varDecs - .map((dec) => dec.names.length) - .reduce((a, b) => a + b, 0); - this.write( - `function ${this.className}.${subroutine.name.value} ${localCount}`, - ); - for (const varDec of subroutine.body.varDecs) { - this.compileVarDec(varDec); - } - } - - compileFunction(subroutine: Subroutine) { - this.compileSubroutineStart(subroutine); - this.compileStatements(subroutine.body.statements); - } - - compileMethod(subroutine: Subroutine) { - this.compileSubroutineStart(subroutine, true); - this.write("push argument 0", "pop pointer 0"); - this.compileStatements(subroutine.body.statements); - } - - compileConstructor(subroutine: Subroutine) { - this.compileSubroutineStart(subroutine); - this.write( - `push constant ${this.fieldNum}`, - "call Memory.alloc 1", - "pop pointer 0", - ); - this.compileStatements(subroutine.body.statements); - } - - compileExpression(expression: Expression) { - this.compileTerm(expression.term); - for (const part of expression.rest) { - this.compileTerm(part.term); - this.compileOp(part.op); // postfix - } - } - - compileOp(op: Op) { - this.write(ops[op]); - } - - compileTerm(term: Term) { - switch (term.termType) { - case "numericLiteral": - this.write(`push constant ${term.value}`); - break; - case "stringLiteral": - this.compileStringLiteral(term.value); - break; - case "variable": - this.write(`push ${this.var(term)}`); - break; - case "keywordLiteral": - this.compileKeywordLiteral(term.value); - break; - case "subroutineCall": - this.compileSubroutineCall(term); - break; - case "arrayAccess": - this.compileExpression(term.index); - this.write( - `push ${this.var(term)}`, - "add", - "pop pointer 1", - "push that 0", - ); - break; - case "groupedExpression": - this.compileExpression(term.expression); - break; - case "unaryExpression": - this.compileTerm(term.term); - this.write(unaryOps[term.op]); - } - } - - validateArgNum(name: string, expected: number, call: SubroutineCall) { - const received = call.parameters.length; - if (expected != received) { - throw createError( - `${name} expected ${expected} arguments, got ${received}`, - call.span, - ); - } - } - - validateSubroutineCall( - className: string, - subroutineName: string, - call: SubroutineCall, - isMethod: boolean, - ) { - const builtin = VM_BUILTINS[`${className}.${subroutineName}`]; - if (builtin) { - if (builtin.type == "method" && !isMethod) { - throw createError( - `Method ${className}.${subroutineName} was called as a function/constructor`, - call.name.span, - ); - } - if (builtin.type != "method" && isMethod) { - throw createError( - `${capitalize( - builtin.type, - )} ${className}.${subroutineName} was called as a method`, - call.name.span, - ); - } - this.validateArgNum( - `${className}.${subroutineName}`, - builtin.args.length, - call, - ); - return; - } else if (this.classes[className]) { - for (const subroutine of this.classes[className].subroutines) { - if (subroutine.name.value == subroutineName) { - if (subroutine.type == "method" && !isMethod) { - throw createError( - `Method ${className}.${subroutineName} was called as a function/constructor`, - call.name.span, + private binder = new BinderListener(); + private errorListener = new CustomErrorListener(); + compile(tree: ProgramContext): string | JackCompilerError[] { + if (Object.keys(this.binder.globalSymbolTable).length == 0) { + throw new Error( + "Please populate global symbol table using parserAndBind method", ); - } - if (subroutine.type != "method" && isMethod) { - throw createError( - `${capitalize( - subroutine.name.value, - )} ${className}.${subroutineName} was called as a method`, - call.name.span, - ); - } - this.validateArgNum( - `${className}.${subroutineName}`, - subroutine.parameters.length, - call, - ); - return; } - } - throw createError( - `Class ${className} doesn't contain a function/constructor ${subroutineName}`, - call.name.span, - ); - } else { - throw createError(`Class ${className} doesn't exist`, call.name.span); - } - } - - classifySubroutineCall(call: SubroutineCall): SubroutineCallAttributes { - let object: string | undefined; - let className = ""; - let subroutineName = ""; - - if (call.name.value.includes(".")) { - const [prefix, suffix] = call.name.value.split(".", 2); - subroutineName = suffix; - const varData = this.varData(prefix); - if (varData) { - // external method call - object = this.var(prefix); - className = varData.type; - } else { - // function / constructor call - className = prefix; - } - } else { - object = "pointer 0"; // this - className = this.className; - subroutineName = call.name.value; - } - - this.validateSubroutineCall( - className, - subroutineName, - call, - object != undefined, - ); - - return { className, subroutineName, object }; - } - - compileSubroutineCall(call: SubroutineCall) { - const attributes = this.classifySubroutineCall(call); - - if (attributes.object) { - this.write(`push ${attributes.object}`); - } - for (const param of call.parameters) { - this.compileExpression(param); - } - this.write( - `call ${attributes.className}.${attributes.subroutineName} ${ - call.parameters.length + (attributes.object ? 1 : 0) - }`, - ); - } - - compileStringLiteral(str: string) { - this.write(`push constant ${str.length}`, `call String.new 1`); - for (let i = 0; i < str.length; i++) { - this.write( - `push constant ${str.charCodeAt(i)}`, - `call String.appendChar 2`, - ); - } - } - - compileKeywordLiteral(keyword: KeywordConstant) { - switch (keyword) { - case "true": - this.write(`push constant 1`, `neg`); - break; - case "false": - this.write(`push constant 0`); - break; - case "null": - this.write(`push constant 0`); - break; - case "this": - this.write(`push pointer 0`); - } - } - - compileStatements(statements: Statement[]) { - for (const statement of statements) { - this.compileStatement(statement); - } - } - - compileStatement(statement: Statement) { - switch (statement.statementType) { - case "doStatement": - this.compileDoStatement(statement); - break; - case "ifStatement": - this.compileIf(statement); - break; - case "letStatement": - this.compileLet(statement); - break; - case "returnStatement": - this.compileReturn(statement); - break; - case "whileStatement": - this.compileWhile(statement); - } - } - - compileReturn(statement: ReturnStatement) { - if (statement.value) { - this.compileExpression(statement.value); - } else { - this.write(`push constant 0`); // return 0 - } - this.write(`return`); - } - - compileLet(statement: LetStatement) { - if (statement.arrayIndex) { - this.compileExpression(statement.arrayIndex); - this.write(`push ${this.var(statement)}`, "add"); - this.compileExpression(statement.value); - this.write("pop temp 0", "pop pointer 1", "push temp 0", "pop that 0"); - } else { - this.compileExpression(statement.value); - this.write(`pop ${this.var(statement)}`); + const validator = new ValidatorListener(this.binder.globalSymbolTable); + ParseTreeWalker.DEFAULT.walk(validator, tree); + if (validator.errors.length > 0) { + console.log("Errors in validator " + JSON.stringify(validator.errors)); + return validator.errors; + } + const vmWriter = new VMWriter(this.binder.globalSymbolTable); + ParseTreeWalker.DEFAULT.walk(vmWriter, tree); + return vmWriter.result; + } + + parserAndBind(src: string): ProgramContext | JackCompilerError[] { + const lexer = new JackLexer(CharStreams.fromString(src)); + lexer.removeErrorListeners(); + lexer.addErrorListener(this.errorListener); + const tokenStream = new CommonTokenStream(lexer); + const parser = new JackParser(tokenStream); + parser.removeErrorListeners(); + parser.addErrorListener(this.errorListener); + const tree = parser.program(); + if (this.errorListener.errors.length > 0) { + console.log("Errors when parsing or lexing"); + return this.errorListener.errors; + } + ParseTreeWalker.DEFAULT.walk(this.binder, tree); + if (this.binder.errors.length > 0) { + console.log("Errors in binder"); + return this.binder.errors; + } + return tree; } - } - - compileDoStatement(statement: DoStatement) { - this.compileSubroutineCall(statement.call); - this.write(`pop temp 0`); - } - - compileIf(statement: IfStatement) { - const condTrue = this.getLabel(); - const condFalse = this.getLabel(); - - this.compileExpression(statement.condition); - this.write("not", `if-goto ${condFalse}`); - this.compileStatements(statement.body); - this.write(`goto ${condTrue}`, `label ${condFalse}`); - this.compileStatements(statement.else); - this.write(`label ${condTrue}`); - } - - compileWhile(statement: WhileStatement) { - const loop = this.getLabel(); - const exit = this.getLabel(); - - this.write(`label ${loop}`); - this.compileExpression(statement.condition); - this.write(`not`, `if-goto ${exit}`); - this.compileStatements(statement.body); - this.write(`goto ${loop}`, `label ${exit}`); - } } diff --git a/simulator/src/jack/controlFlow.ts b/simulator/src/jack/controlFlow.ts deleted file mode 100644 index be962a06..00000000 --- a/simulator/src/jack/controlFlow.ts +++ /dev/null @@ -1,180 +0,0 @@ -import { - Err, - Ok, - Result, - isErr, - unwrap, -} from "@davidsouther/jiffies/lib/esm/result.js"; -import { CompilationError, createError } from "../languages/base.js"; -import { - IfStatement, - ReturnType, - Statement, - Subroutine, - WhileStatement, -} from "../languages/jack.js"; - -class CFGNode { - id: number; - hasReturn = false; - children: CFGNode[] = []; - - static count = 0; - - constructor() { - this.id = CFGNode.count; - CFGNode.count += 1; - } - - alwaysReturns(): boolean { - const visited: Set = new Set(); - - function checkReturn(node: CFGNode): boolean { - if (node.hasReturn) { - return true; - } else if (node.children.length === 0) { - return false; - } - visited.add(node); - for (const child of node.children) { - if (!visited.has(child) && !checkReturn(child)) { - return false; - } - } - return true; - } - - return checkReturn(this); - } - - getLeafs(): CFGNode[] { - const leafs: Set = new Set(); - const visited: Set = new Set(); - - function findLeafs(node: CFGNode) { - if (node.children.length === 0) { - leafs.add(node); - } else { - visited.add(node); - for (const child of node.children) { - if (!visited.has(child)) { - findLeafs(child); - } - } - } - } - - findLeafs(this); - return Array.from(leafs); - } -} - -function processIf( - statement: IfStatement, - returnType: ReturnType, - current: CFGNode, -): Result { - const ifStart = new CFGNode(); - current.children.push(ifStart); - current = ifStart; - const result1 = buildCFG(statement.body, returnType); - const result2 = buildCFG(statement.else, returnType); - if (isErr(result1)) { - return result1; - } - if (isErr(result2)) { - return result2; - } - const path1 = unwrap(result1); - const path2 = unwrap(result2); - current.children.push(path1, path2); - const leafs = path1.getLeafs().concat(path2.getLeafs()); - current = new CFGNode(); - for (const leaf of leafs) { - leaf.children.push(current); - } - return Ok(current); -} - -function processWhile( - statement: WhileStatement, - returnType: ReturnType, - current: CFGNode, -): Result { - const whileStart = new CFGNode(); - current.children.push(whileStart); - current = whileStart; - const result = buildCFG(statement.body, returnType); - if (isErr(result)) { - return result; - } - const body = unwrap(result); - for (const leaf of body.getLeafs()) { - leaf.children.push(current); - } - const next = new CFGNode(); - current.children.push(body, next); - current = next; - return Ok(current); -} - -function buildCFG( - statements: Statement[], - returnType: ReturnType, -): Result { - const root = new CFGNode(); - let current = root; - - let result: Result | undefined; - for (const statement of statements) { - switch (statement.statementType) { - case "letStatement": - case "doStatement": - break; - case "returnStatement": - if (returnType != "void" && statement.value == undefined) { - return Err( - createError( - `A non void subroutine must return a value`, - statement.span, - ), - ); - } - current.hasReturn = true; - break; - case "ifStatement": - result = processIf(statement, returnType, current); - if (isErr(result)) { - return result; - } - current = unwrap(result); - break; - case "whileStatement": - result = processWhile(statement, returnType, current); - if (isErr(result)) { - return result; - } - current = unwrap(result); - break; - } - } - return Ok(root); -} - -export function validateSubroutine( - subroutine: Subroutine, -): Result { - const cfg = buildCFG(subroutine.body.statements, subroutine.returnType.value); - if (isErr(cfg)) { - return cfg; - } - if (!unwrap(cfg).alwaysReturns()) { - return Err( - createError( - `Subroutine ${subroutine.name.value}: not all code paths return a value`, - subroutine.name.span, - ), - ); - } - return Ok(); -} diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts new file mode 100644 index 00000000..983fb7bc --- /dev/null +++ b/simulator/src/jack/error.ts @@ -0,0 +1,256 @@ +export interface Span { + start: number; + end: number; + line: number; +} +export class JackCompilerError { + public span: Span; + constructor( + line: number, + startInd: number, + endIndex: number, + public msg: string, + ) { + this.span = { start: startInd, end: endIndex, line: line }; + } + public toString = (): string => { + return ( + this.constructor.name + + `(${this.span.line}:${this.span.start}:${this.span.end} ${this.msg})` + ); + }; +} + +export class LexerOrParserError extends JackCompilerError {} +export class DuplicatedSubroutineError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + subroutineName: string, + ) { + super(line, startInd, endIndex, `Subroutine ${subroutineName} redeclared.`); + } +} + +export class DuplicatedVariableException extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + variableName: string, + ) { + super( + line, + startInd, + endIndex, + "Duplicated local variable, field, argument or static variable " + + variableName, + ); + } +} + +export class UndeclaredVariableError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + variableName: string, + ) { + super(line, startInd, endIndex, "Undeclared variable " + variableName); + } +} +export class UnknownClassError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + className: string, + ) { + super(line, startInd, endIndex, `Class ${className} doesn't exist`); + } +} + +export class NonVoidFunctionNoReturnError extends JackCompilerError { + constructor(line: number, startInd: number, endIndex: number) { + super( + line, + startInd, + endIndex, + `A non void subroutine must return a value`, + ); + } +} + +export class VoidSubroutineReturnsValueError extends JackCompilerError { + constructor(line: number, startInd: number, endIndex: number) { + super( + line, + startInd, + endIndex, + `Cannot return a value from a void subroutine`, + ); + Object.setPrototypeOf(this, VoidSubroutineReturnsValueError.prototype); + } +} + +export class SubroutineNotAllPathsReturnError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + subroutineName: string, + ) { + super( + line, + startInd, + endIndex, + `Subroutine ${subroutineName}: not all code paths return a value`, + ); + Object.setPrototypeOf(this, SubroutineNotAllPathsReturnError.prototype); + } +} + +export class IncorrectParamsNumberInSubroutineCallError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + subroutineName: string, + expectedParamsCount: number, + actualParamsCount: number, + ) { + super( + line, + startInd, + endIndex, + `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)`, + ); + Object.setPrototypeOf( + this, + IncorrectParamsNumberInSubroutineCallError.prototype, + ); + } +} +export class UnknownSubroutineCallError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + subroutineName: string, + className?: string, + ) { + super( + line, + startInd, + endIndex, + `Can't find subroutine '${subroutineName}'${className ? ` in ${className}` : ""}`, + ); + Object.setPrototypeOf(this, UnknownSubroutineCallError.prototype); + } +} +export class MethodCalledAsFunctionError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + subroutineId: string, + ) { + super( + line, + startInd, + endIndex, + `Method ${subroutineId} was called as a function/constructor`, + ); + Object.setPrototypeOf(this, MethodCalledAsFunctionError.prototype); + } +} +export class FunctionCalledAsMethodError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + subroutineId: string, + ) { + super( + line, + startInd, + endIndex, + `Function or constructor ${subroutineId} was called as a method`, + ); + Object.setPrototypeOf(this, FunctionCalledAsMethodError.prototype); + } +} + +export class IncorrectConstructorReturnType extends JackCompilerError { + constructor(line: number, startInd: number, endIndex: number) { + super( + line, + startInd, + endIndex, + `The return type of a constructor must be of the class type`, + ); + Object.setPrototypeOf(this, IncorrectConstructorReturnType.prototype); + } +} + +export class UnreachableCodeError extends JackCompilerError { + constructor(line: number, startInd: number, endIndex: number) { + super(line, startInd, endIndex, `Unreachable code`); + Object.setPrototypeOf(this, UnreachableCodeError.prototype); + } +} + +export class ConstructorMushReturnThis extends JackCompilerError { + constructor(line: number, startInd: number, endIndex: number) { + super(line, startInd, endIndex, `A constructor must return 'this'`); + Object.setPrototypeOf(this, ConstructorMushReturnThis.prototype); + } +} + +const vowels = "aeiou"; +export class WrongLiteralTypeError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + typeName: string, + ) { + const article = vowels.indexOf(typeName.substring(0, 1)) != -1 ? "an" : "a"; + super(line, startInd, endIndex, `${article} ${typeName} value is expected`); + Object.setPrototypeOf(this, WrongLiteralTypeError.prototype); + } +} + +export class IntLiteralIsOutOfRange extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + value: number, + min: number, + max: number, + ) { + super( + line, + startInd, + endIndex, + `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}`, + ); + Object.setPrototypeOf(this, IntLiteralIsOutOfRange.prototype); + } +} + +export class FieldCantBeReferencedInFunction extends JackCompilerError { + constructor(line: number, startInd: number, endIndex: number) { + super(line, startInd, endIndex, `Field can't be referenced in a function`); + Object.setPrototypeOf(this, FieldCantBeReferencedInFunction.prototype); + } +} + +export class ThisCantBeReferencedInFunction extends JackCompilerError { + constructor(line: number, startInd: number, endIndex: number) { + super(line, startInd, endIndex, `this can't be referenced in a function`); + Object.setPrototypeOf(this, ThisCantBeReferencedInFunction.prototype); + } +} diff --git a/simulator/src/jack/generated/JackLexer.interp b/simulator/src/jack/generated/JackLexer.interp new file mode 100644 index 00000000..f31eda73 --- /dev/null +++ b/simulator/src/jack/generated/JackLexer.interp @@ -0,0 +1,158 @@ +token literal names: +null +'class' +'constructor' +'function' +'method' +'field' +'static' +'var' +'int' +'char' +'boolean' +'void' +'let' +'do' +'if' +'else' +'while' +'return' +'{' +'}' +'(' +')' +'[' +']' +'.' +',' +';' +'=' +'+' +'-' +'*' +'/' +'&' +'|' +'~' +'<' +'>' +null +null +null +null +'true' +'false' +'null' +'this' +null +null +null + +token symbolic names: +null +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +TRUE +FALSE +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +rule names: +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +TRUE +FALSE +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[4, 0, 47, 309, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 4, 36, 236, 8, 36, 11, 36, 12, 36, 237, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 246, 8, 37, 10, 37, 12, 37, 249, 9, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 260, 8, 38, 10, 38, 12, 38, 263, 9, 38, 1, 38, 1, 38, 1, 39, 4, 39, 268, 8, 39, 11, 39, 12, 39, 269, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 5, 44, 295, 8, 44, 10, 44, 12, 44, 298, 9, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 5, 46, 305, 8, 46, 10, 46, 12, 46, 308, 9, 46, 1, 247, 0, 47, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 1, 0, 6, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 314, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 1, 95, 1, 0, 0, 0, 3, 101, 1, 0, 0, 0, 5, 113, 1, 0, 0, 0, 7, 122, 1, 0, 0, 0, 9, 129, 1, 0, 0, 0, 11, 135, 1, 0, 0, 0, 13, 142, 1, 0, 0, 0, 15, 146, 1, 0, 0, 0, 17, 150, 1, 0, 0, 0, 19, 155, 1, 0, 0, 0, 21, 163, 1, 0, 0, 0, 23, 168, 1, 0, 0, 0, 25, 172, 1, 0, 0, 0, 27, 175, 1, 0, 0, 0, 29, 178, 1, 0, 0, 0, 31, 183, 1, 0, 0, 0, 33, 189, 1, 0, 0, 0, 35, 196, 1, 0, 0, 0, 37, 198, 1, 0, 0, 0, 39, 200, 1, 0, 0, 0, 41, 202, 1, 0, 0, 0, 43, 204, 1, 0, 0, 0, 45, 206, 1, 0, 0, 0, 47, 208, 1, 0, 0, 0, 49, 210, 1, 0, 0, 0, 51, 212, 1, 0, 0, 0, 53, 214, 1, 0, 0, 0, 55, 216, 1, 0, 0, 0, 57, 218, 1, 0, 0, 0, 59, 220, 1, 0, 0, 0, 61, 222, 1, 0, 0, 0, 63, 224, 1, 0, 0, 0, 65, 226, 1, 0, 0, 0, 67, 228, 1, 0, 0, 0, 69, 230, 1, 0, 0, 0, 71, 232, 1, 0, 0, 0, 73, 235, 1, 0, 0, 0, 75, 241, 1, 0, 0, 0, 77, 255, 1, 0, 0, 0, 79, 267, 1, 0, 0, 0, 81, 271, 1, 0, 0, 0, 83, 276, 1, 0, 0, 0, 85, 282, 1, 0, 0, 0, 87, 287, 1, 0, 0, 0, 89, 292, 1, 0, 0, 0, 91, 299, 1, 0, 0, 0, 93, 302, 1, 0, 0, 0, 95, 96, 5, 99, 0, 0, 96, 97, 5, 108, 0, 0, 97, 98, 5, 97, 0, 0, 98, 99, 5, 115, 0, 0, 99, 100, 5, 115, 0, 0, 100, 2, 1, 0, 0, 0, 101, 102, 5, 99, 0, 0, 102, 103, 5, 111, 0, 0, 103, 104, 5, 110, 0, 0, 104, 105, 5, 115, 0, 0, 105, 106, 5, 116, 0, 0, 106, 107, 5, 114, 0, 0, 107, 108, 5, 117, 0, 0, 108, 109, 5, 99, 0, 0, 109, 110, 5, 116, 0, 0, 110, 111, 5, 111, 0, 0, 111, 112, 5, 114, 0, 0, 112, 4, 1, 0, 0, 0, 113, 114, 5, 102, 0, 0, 114, 115, 5, 117, 0, 0, 115, 116, 5, 110, 0, 0, 116, 117, 5, 99, 0, 0, 117, 118, 5, 116, 0, 0, 118, 119, 5, 105, 0, 0, 119, 120, 5, 111, 0, 0, 120, 121, 5, 110, 0, 0, 121, 6, 1, 0, 0, 0, 122, 123, 5, 109, 0, 0, 123, 124, 5, 101, 0, 0, 124, 125, 5, 116, 0, 0, 125, 126, 5, 104, 0, 0, 126, 127, 5, 111, 0, 0, 127, 128, 5, 100, 0, 0, 128, 8, 1, 0, 0, 0, 129, 130, 5, 102, 0, 0, 130, 131, 5, 105, 0, 0, 131, 132, 5, 101, 0, 0, 132, 133, 5, 108, 0, 0, 133, 134, 5, 100, 0, 0, 134, 10, 1, 0, 0, 0, 135, 136, 5, 115, 0, 0, 136, 137, 5, 116, 0, 0, 137, 138, 5, 97, 0, 0, 138, 139, 5, 116, 0, 0, 139, 140, 5, 105, 0, 0, 140, 141, 5, 99, 0, 0, 141, 12, 1, 0, 0, 0, 142, 143, 5, 118, 0, 0, 143, 144, 5, 97, 0, 0, 144, 145, 5, 114, 0, 0, 145, 14, 1, 0, 0, 0, 146, 147, 5, 105, 0, 0, 147, 148, 5, 110, 0, 0, 148, 149, 5, 116, 0, 0, 149, 16, 1, 0, 0, 0, 150, 151, 5, 99, 0, 0, 151, 152, 5, 104, 0, 0, 152, 153, 5, 97, 0, 0, 153, 154, 5, 114, 0, 0, 154, 18, 1, 0, 0, 0, 155, 156, 5, 98, 0, 0, 156, 157, 5, 111, 0, 0, 157, 158, 5, 111, 0, 0, 158, 159, 5, 108, 0, 0, 159, 160, 5, 101, 0, 0, 160, 161, 5, 97, 0, 0, 161, 162, 5, 110, 0, 0, 162, 20, 1, 0, 0, 0, 163, 164, 5, 118, 0, 0, 164, 165, 5, 111, 0, 0, 165, 166, 5, 105, 0, 0, 166, 167, 5, 100, 0, 0, 167, 22, 1, 0, 0, 0, 168, 169, 5, 108, 0, 0, 169, 170, 5, 101, 0, 0, 170, 171, 5, 116, 0, 0, 171, 24, 1, 0, 0, 0, 172, 173, 5, 100, 0, 0, 173, 174, 5, 111, 0, 0, 174, 26, 1, 0, 0, 0, 175, 176, 5, 105, 0, 0, 176, 177, 5, 102, 0, 0, 177, 28, 1, 0, 0, 0, 178, 179, 5, 101, 0, 0, 179, 180, 5, 108, 0, 0, 180, 181, 5, 115, 0, 0, 181, 182, 5, 101, 0, 0, 182, 30, 1, 0, 0, 0, 183, 184, 5, 119, 0, 0, 184, 185, 5, 104, 0, 0, 185, 186, 5, 105, 0, 0, 186, 187, 5, 108, 0, 0, 187, 188, 5, 101, 0, 0, 188, 32, 1, 0, 0, 0, 189, 190, 5, 114, 0, 0, 190, 191, 5, 101, 0, 0, 191, 192, 5, 116, 0, 0, 192, 193, 5, 117, 0, 0, 193, 194, 5, 114, 0, 0, 194, 195, 5, 110, 0, 0, 195, 34, 1, 0, 0, 0, 196, 197, 5, 123, 0, 0, 197, 36, 1, 0, 0, 0, 198, 199, 5, 125, 0, 0, 199, 38, 1, 0, 0, 0, 200, 201, 5, 40, 0, 0, 201, 40, 1, 0, 0, 0, 202, 203, 5, 41, 0, 0, 203, 42, 1, 0, 0, 0, 204, 205, 5, 91, 0, 0, 205, 44, 1, 0, 0, 0, 206, 207, 5, 93, 0, 0, 207, 46, 1, 0, 0, 0, 208, 209, 5, 46, 0, 0, 209, 48, 1, 0, 0, 0, 210, 211, 5, 44, 0, 0, 211, 50, 1, 0, 0, 0, 212, 213, 5, 59, 0, 0, 213, 52, 1, 0, 0, 0, 214, 215, 5, 61, 0, 0, 215, 54, 1, 0, 0, 0, 216, 217, 5, 43, 0, 0, 217, 56, 1, 0, 0, 0, 218, 219, 5, 45, 0, 0, 219, 58, 1, 0, 0, 0, 220, 221, 5, 42, 0, 0, 221, 60, 1, 0, 0, 0, 222, 223, 5, 47, 0, 0, 223, 62, 1, 0, 0, 0, 224, 225, 5, 38, 0, 0, 225, 64, 1, 0, 0, 0, 226, 227, 5, 124, 0, 0, 227, 66, 1, 0, 0, 0, 228, 229, 5, 126, 0, 0, 229, 68, 1, 0, 0, 0, 230, 231, 5, 60, 0, 0, 231, 70, 1, 0, 0, 0, 232, 233, 5, 62, 0, 0, 233, 72, 1, 0, 0, 0, 234, 236, 7, 0, 0, 0, 235, 234, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 1, 0, 0, 0, 239, 240, 6, 36, 0, 0, 240, 74, 1, 0, 0, 0, 241, 242, 5, 47, 0, 0, 242, 243, 5, 42, 0, 0, 243, 247, 1, 0, 0, 0, 244, 246, 9, 0, 0, 0, 245, 244, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 250, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 251, 5, 42, 0, 0, 251, 252, 5, 47, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 6, 37, 0, 0, 254, 76, 1, 0, 0, 0, 255, 256, 5, 47, 0, 0, 256, 257, 5, 47, 0, 0, 257, 261, 1, 0, 0, 0, 258, 260, 8, 1, 0, 0, 259, 258, 1, 0, 0, 0, 260, 263, 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 264, 1, 0, 0, 0, 263, 261, 1, 0, 0, 0, 264, 265, 6, 38, 0, 0, 265, 78, 1, 0, 0, 0, 266, 268, 7, 2, 0, 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 80, 1, 0, 0, 0, 271, 272, 5, 116, 0, 0, 272, 273, 5, 114, 0, 0, 273, 274, 5, 117, 0, 0, 274, 275, 5, 101, 0, 0, 275, 82, 1, 0, 0, 0, 276, 277, 5, 102, 0, 0, 277, 278, 5, 97, 0, 0, 278, 279, 5, 108, 0, 0, 279, 280, 5, 115, 0, 0, 280, 281, 5, 101, 0, 0, 281, 84, 1, 0, 0, 0, 282, 283, 5, 110, 0, 0, 283, 284, 5, 117, 0, 0, 284, 285, 5, 108, 0, 0, 285, 286, 5, 108, 0, 0, 286, 86, 1, 0, 0, 0, 287, 288, 5, 116, 0, 0, 288, 289, 5, 104, 0, 0, 289, 290, 5, 105, 0, 0, 290, 291, 5, 115, 0, 0, 291, 88, 1, 0, 0, 0, 292, 296, 7, 3, 0, 0, 293, 295, 7, 4, 0, 0, 294, 293, 1, 0, 0, 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 90, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299, 300, 3, 93, 46, 0, 300, 301, 5, 34, 0, 0, 301, 92, 1, 0, 0, 0, 302, 306, 5, 34, 0, 0, 303, 305, 8, 5, 0, 0, 304, 303, 1, 0, 0, 0, 305, 308, 1, 0, 0, 0, 306, 304, 1, 0, 0, 0, 306, 307, 1, 0, 0, 0, 307, 94, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 7, 0, 237, 247, 261, 269, 296, 306, 1, 6, 0, 0] \ No newline at end of file diff --git a/simulator/src/jack/generated/JackLexer.tokens b/simulator/src/jack/generated/JackLexer.tokens new file mode 100644 index 00000000..225dc556 --- /dev/null +++ b/simulator/src/jack/generated/JackLexer.tokens @@ -0,0 +1,87 @@ +CLASS=1 +CONSTRUCTOR=2 +FUNCTION=3 +METHOD=4 +FIELD=5 +STATIC=6 +VAR=7 +INT=8 +CHAR=9 +BOOLEAN=10 +VOID=11 +LET=12 +DO=13 +IF=14 +ELSE=15 +WHILE=16 +RETURN=17 +LBRACE=18 +RBRACE=19 +LPAREN=20 +RPAREN=21 +LBRACKET=22 +RBRACKET=23 +DOT=24 +COMMA=25 +SEMICOLON=26 +EQUALS=27 +PLUS=28 +MINUS=29 +MUL=30 +DIV=31 +AND=32 +OR=33 +TILDE=34 +LESS_THAN=35 +GREATER_THAN=36 +WS=37 +COMMENT=38 +LINE_COMMENT=39 +INTEGER_LITERAL=40 +TRUE=41 +FALSE=42 +NULL_LITERAL=43 +THIS_LITERAL=44 +IDENTIFIER=45 +STRING_LITERAL=46 +UnterminatedStringLiteral=47 +'class'=1 +'constructor'=2 +'function'=3 +'method'=4 +'field'=5 +'static'=6 +'var'=7 +'int'=8 +'char'=9 +'boolean'=10 +'void'=11 +'let'=12 +'do'=13 +'if'=14 +'else'=15 +'while'=16 +'return'=17 +'{'=18 +'}'=19 +'('=20 +')'=21 +'['=22 +']'=23 +'.'=24 +','=25 +';'=26 +'='=27 +'+'=28 +'-'=29 +'*'=30 +'/'=31 +'&'=32 +'|'=33 +'~'=34 +'<'=35 +'>'=36 +'true'=41 +'false'=42 +'null'=43 +'this'=44 diff --git a/simulator/src/jack/generated/JackLexer.ts b/simulator/src/jack/generated/JackLexer.ts new file mode 100644 index 00000000..55f6427e --- /dev/null +++ b/simulator/src/jack/generated/JackLexer.ts @@ -0,0 +1,398 @@ +// Generated from JackLexer.g4 by ANTLR 4.13.2 +// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols +import { + ATN, + ATNDeserializer, + CharStream, + DecisionState, + DFA, + Lexer, + LexerATNSimulator, + PredictionContextCache, + Token +} from "antlr4"; +export default class JackLexer extends Lexer { + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WS = 37; + public static readonly COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly TRUE = 41; + public static readonly FALSE = 42; + public static readonly NULL_LITERAL = 43; + public static readonly THIS_LITERAL = 44; + public static readonly IDENTIFIER = 45; + public static readonly STRING_LITERAL = 46; + public static readonly UnterminatedStringLiteral = 47; + public static readonly EOF = Token.EOF; + + public static readonly channelNames: string[] = [ + "DEFAULT_TOKEN_CHANNEL", + "HIDDEN", + ]; + public static readonly literalNames: (string | null)[] = [ + null, + "'class'", + "'constructor'", + "'function'", + "'method'", + "'field'", + "'static'", + "'var'", + "'int'", + "'char'", + "'boolean'", + "'void'", + "'let'", + "'do'", + "'if'", + "'else'", + "'while'", + "'return'", + "'{'", + "'}'", + "'('", + "')'", + "'['", + "']'", + "'.'", + "','", + "';'", + "'='", + "'+'", + "'-'", + "'*'", + "'/'", + "'&'", + "'|'", + "'~'", + "'<'", + "'>'", + null, + null, + null, + null, + "'true'", + "'false'", + "'null'", + "'this'", + ]; + public static readonly symbolicNames: (string | null)[] = [ + null, + "CLASS", + "CONSTRUCTOR", + "FUNCTION", + "METHOD", + "FIELD", + "STATIC", + "VAR", + "INT", + "CHAR", + "BOOLEAN", + "VOID", + "LET", + "DO", + "IF", + "ELSE", + "WHILE", + "RETURN", + "LBRACE", + "RBRACE", + "LPAREN", + "RPAREN", + "LBRACKET", + "RBRACKET", + "DOT", + "COMMA", + "SEMICOLON", + "EQUALS", + "PLUS", + "MINUS", + "MUL", + "DIV", + "AND", + "OR", + "TILDE", + "LESS_THAN", + "GREATER_THAN", + "WS", + "COMMENT", + "LINE_COMMENT", + "INTEGER_LITERAL", + "TRUE", + "FALSE", + "NULL_LITERAL", + "THIS_LITERAL", + "IDENTIFIER", + "STRING_LITERAL", + "UnterminatedStringLiteral", + ]; + public static readonly modeNames: string[] = ["DEFAULT_MODE"]; + + public static readonly ruleNames: string[] = [ + "CLASS", + "CONSTRUCTOR", + "FUNCTION", + "METHOD", + "FIELD", + "STATIC", + "VAR", + "INT", + "CHAR", + "BOOLEAN", + "VOID", + "LET", + "DO", + "IF", + "ELSE", + "WHILE", + "RETURN", + "LBRACE", + "RBRACE", + "LPAREN", + "RPAREN", + "LBRACKET", + "RBRACKET", + "DOT", + "COMMA", + "SEMICOLON", + "EQUALS", + "PLUS", + "MINUS", + "MUL", + "DIV", + "AND", + "OR", + "TILDE", + "LESS_THAN", + "GREATER_THAN", + "WS", + "COMMENT", + "LINE_COMMENT", + "INTEGER_LITERAL", + "TRUE", + "FALSE", + "NULL_LITERAL", + "THIS_LITERAL", + "IDENTIFIER", + "STRING_LITERAL", + "UnterminatedStringLiteral", + ]; + + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator( + this, + JackLexer._ATN, + JackLexer.DecisionsToDFA, + new PredictionContextCache(), + ); + } + + public get grammarFileName(): string { + return "JackLexer.g4"; + } + + public get literalNames(): (string | null)[] { + return JackLexer.literalNames; + } + public get symbolicNames(): (string | null)[] { + return JackLexer.symbolicNames; + } + public get ruleNames(): string[] { + return JackLexer.ruleNames; + } + + public get serializedATN(): number[] { + return JackLexer._serializedATN; + } + + public get channelNames(): string[] { + return JackLexer.channelNames; + } + + public get modeNames(): string[] { + return JackLexer.modeNames; + } + + public static readonly _serializedATN: number[] = [ + 4, 0, 47, 309, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, + 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, + 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, + 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, + 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, + 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, + 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, + 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, + 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, + 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, + 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, + 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, + 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, + 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, + 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, + 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, + 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, + 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 4, 36, 236, 8, 36, 11, 36, 12, + 36, 237, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 246, 8, 37, 10, + 37, 12, 37, 249, 9, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, + 38, 1, 38, 5, 38, 260, 8, 38, 10, 38, 12, 38, 263, 9, 38, 1, 38, 1, 38, 1, + 39, 4, 39, 268, 8, 39, 11, 39, 12, 39, 269, 1, 40, 1, 40, 1, 40, 1, 40, 1, + 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, + 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 5, 44, 295, 8, 44, 10, + 44, 12, 44, 298, 9, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 5, 46, 305, 8, + 46, 10, 46, 12, 46, 308, 9, 46, 1, 247, 0, 47, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, + 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, + 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, + 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, + 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, + 44, 89, 45, 91, 46, 93, 47, 1, 0, 6, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, + 10, 13, 13, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, + 90, 95, 95, 97, 122, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 314, 0, 1, 1, 0, + 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, + 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, + 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, + 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, + 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, + 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, + 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, + 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, + 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, + 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, + 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, + 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 1, 95, 1, 0, 0, 0, 3, 101, 1, 0, 0, + 0, 5, 113, 1, 0, 0, 0, 7, 122, 1, 0, 0, 0, 9, 129, 1, 0, 0, 0, 11, 135, 1, + 0, 0, 0, 13, 142, 1, 0, 0, 0, 15, 146, 1, 0, 0, 0, 17, 150, 1, 0, 0, 0, 19, + 155, 1, 0, 0, 0, 21, 163, 1, 0, 0, 0, 23, 168, 1, 0, 0, 0, 25, 172, 1, 0, 0, + 0, 27, 175, 1, 0, 0, 0, 29, 178, 1, 0, 0, 0, 31, 183, 1, 0, 0, 0, 33, 189, + 1, 0, 0, 0, 35, 196, 1, 0, 0, 0, 37, 198, 1, 0, 0, 0, 39, 200, 1, 0, 0, 0, + 41, 202, 1, 0, 0, 0, 43, 204, 1, 0, 0, 0, 45, 206, 1, 0, 0, 0, 47, 208, 1, + 0, 0, 0, 49, 210, 1, 0, 0, 0, 51, 212, 1, 0, 0, 0, 53, 214, 1, 0, 0, 0, 55, + 216, 1, 0, 0, 0, 57, 218, 1, 0, 0, 0, 59, 220, 1, 0, 0, 0, 61, 222, 1, 0, 0, + 0, 63, 224, 1, 0, 0, 0, 65, 226, 1, 0, 0, 0, 67, 228, 1, 0, 0, 0, 69, 230, + 1, 0, 0, 0, 71, 232, 1, 0, 0, 0, 73, 235, 1, 0, 0, 0, 75, 241, 1, 0, 0, 0, + 77, 255, 1, 0, 0, 0, 79, 267, 1, 0, 0, 0, 81, 271, 1, 0, 0, 0, 83, 276, 1, + 0, 0, 0, 85, 282, 1, 0, 0, 0, 87, 287, 1, 0, 0, 0, 89, 292, 1, 0, 0, 0, 91, + 299, 1, 0, 0, 0, 93, 302, 1, 0, 0, 0, 95, 96, 5, 99, 0, 0, 96, 97, 5, 108, + 0, 0, 97, 98, 5, 97, 0, 0, 98, 99, 5, 115, 0, 0, 99, 100, 5, 115, 0, 0, 100, + 2, 1, 0, 0, 0, 101, 102, 5, 99, 0, 0, 102, 103, 5, 111, 0, 0, 103, 104, 5, + 110, 0, 0, 104, 105, 5, 115, 0, 0, 105, 106, 5, 116, 0, 0, 106, 107, 5, 114, + 0, 0, 107, 108, 5, 117, 0, 0, 108, 109, 5, 99, 0, 0, 109, 110, 5, 116, 0, 0, + 110, 111, 5, 111, 0, 0, 111, 112, 5, 114, 0, 0, 112, 4, 1, 0, 0, 0, 113, + 114, 5, 102, 0, 0, 114, 115, 5, 117, 0, 0, 115, 116, 5, 110, 0, 0, 116, 117, + 5, 99, 0, 0, 117, 118, 5, 116, 0, 0, 118, 119, 5, 105, 0, 0, 119, 120, 5, + 111, 0, 0, 120, 121, 5, 110, 0, 0, 121, 6, 1, 0, 0, 0, 122, 123, 5, 109, 0, + 0, 123, 124, 5, 101, 0, 0, 124, 125, 5, 116, 0, 0, 125, 126, 5, 104, 0, 0, + 126, 127, 5, 111, 0, 0, 127, 128, 5, 100, 0, 0, 128, 8, 1, 0, 0, 0, 129, + 130, 5, 102, 0, 0, 130, 131, 5, 105, 0, 0, 131, 132, 5, 101, 0, 0, 132, 133, + 5, 108, 0, 0, 133, 134, 5, 100, 0, 0, 134, 10, 1, 0, 0, 0, 135, 136, 5, 115, + 0, 0, 136, 137, 5, 116, 0, 0, 137, 138, 5, 97, 0, 0, 138, 139, 5, 116, 0, 0, + 139, 140, 5, 105, 0, 0, 140, 141, 5, 99, 0, 0, 141, 12, 1, 0, 0, 0, 142, + 143, 5, 118, 0, 0, 143, 144, 5, 97, 0, 0, 144, 145, 5, 114, 0, 0, 145, 14, + 1, 0, 0, 0, 146, 147, 5, 105, 0, 0, 147, 148, 5, 110, 0, 0, 148, 149, 5, + 116, 0, 0, 149, 16, 1, 0, 0, 0, 150, 151, 5, 99, 0, 0, 151, 152, 5, 104, 0, + 0, 152, 153, 5, 97, 0, 0, 153, 154, 5, 114, 0, 0, 154, 18, 1, 0, 0, 0, 155, + 156, 5, 98, 0, 0, 156, 157, 5, 111, 0, 0, 157, 158, 5, 111, 0, 0, 158, 159, + 5, 108, 0, 0, 159, 160, 5, 101, 0, 0, 160, 161, 5, 97, 0, 0, 161, 162, 5, + 110, 0, 0, 162, 20, 1, 0, 0, 0, 163, 164, 5, 118, 0, 0, 164, 165, 5, 111, 0, + 0, 165, 166, 5, 105, 0, 0, 166, 167, 5, 100, 0, 0, 167, 22, 1, 0, 0, 0, 168, + 169, 5, 108, 0, 0, 169, 170, 5, 101, 0, 0, 170, 171, 5, 116, 0, 0, 171, 24, + 1, 0, 0, 0, 172, 173, 5, 100, 0, 0, 173, 174, 5, 111, 0, 0, 174, 26, 1, 0, + 0, 0, 175, 176, 5, 105, 0, 0, 176, 177, 5, 102, 0, 0, 177, 28, 1, 0, 0, 0, + 178, 179, 5, 101, 0, 0, 179, 180, 5, 108, 0, 0, 180, 181, 5, 115, 0, 0, 181, + 182, 5, 101, 0, 0, 182, 30, 1, 0, 0, 0, 183, 184, 5, 119, 0, 0, 184, 185, 5, + 104, 0, 0, 185, 186, 5, 105, 0, 0, 186, 187, 5, 108, 0, 0, 187, 188, 5, 101, + 0, 0, 188, 32, 1, 0, 0, 0, 189, 190, 5, 114, 0, 0, 190, 191, 5, 101, 0, 0, + 191, 192, 5, 116, 0, 0, 192, 193, 5, 117, 0, 0, 193, 194, 5, 114, 0, 0, 194, + 195, 5, 110, 0, 0, 195, 34, 1, 0, 0, 0, 196, 197, 5, 123, 0, 0, 197, 36, 1, + 0, 0, 0, 198, 199, 5, 125, 0, 0, 199, 38, 1, 0, 0, 0, 200, 201, 5, 40, 0, 0, + 201, 40, 1, 0, 0, 0, 202, 203, 5, 41, 0, 0, 203, 42, 1, 0, 0, 0, 204, 205, + 5, 91, 0, 0, 205, 44, 1, 0, 0, 0, 206, 207, 5, 93, 0, 0, 207, 46, 1, 0, 0, + 0, 208, 209, 5, 46, 0, 0, 209, 48, 1, 0, 0, 0, 210, 211, 5, 44, 0, 0, 211, + 50, 1, 0, 0, 0, 212, 213, 5, 59, 0, 0, 213, 52, 1, 0, 0, 0, 214, 215, 5, 61, + 0, 0, 215, 54, 1, 0, 0, 0, 216, 217, 5, 43, 0, 0, 217, 56, 1, 0, 0, 0, 218, + 219, 5, 45, 0, 0, 219, 58, 1, 0, 0, 0, 220, 221, 5, 42, 0, 0, 221, 60, 1, 0, + 0, 0, 222, 223, 5, 47, 0, 0, 223, 62, 1, 0, 0, 0, 224, 225, 5, 38, 0, 0, + 225, 64, 1, 0, 0, 0, 226, 227, 5, 124, 0, 0, 227, 66, 1, 0, 0, 0, 228, 229, + 5, 126, 0, 0, 229, 68, 1, 0, 0, 0, 230, 231, 5, 60, 0, 0, 231, 70, 1, 0, 0, + 0, 232, 233, 5, 62, 0, 0, 233, 72, 1, 0, 0, 0, 234, 236, 7, 0, 0, 0, 235, + 234, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 238, 1, 0, + 0, 0, 238, 239, 1, 0, 0, 0, 239, 240, 6, 36, 0, 0, 240, 74, 1, 0, 0, 0, 241, + 242, 5, 47, 0, 0, 242, 243, 5, 42, 0, 0, 243, 247, 1, 0, 0, 0, 244, 246, 9, + 0, 0, 0, 245, 244, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, + 247, 245, 1, 0, 0, 0, 248, 250, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 251, + 5, 42, 0, 0, 251, 252, 5, 47, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 6, 37, + 0, 0, 254, 76, 1, 0, 0, 0, 255, 256, 5, 47, 0, 0, 256, 257, 5, 47, 0, 0, + 257, 261, 1, 0, 0, 0, 258, 260, 8, 1, 0, 0, 259, 258, 1, 0, 0, 0, 260, 263, + 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 264, 1, 0, 0, + 0, 263, 261, 1, 0, 0, 0, 264, 265, 6, 38, 0, 0, 265, 78, 1, 0, 0, 0, 266, + 268, 7, 2, 0, 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 267, 1, 0, + 0, 0, 269, 270, 1, 0, 0, 0, 270, 80, 1, 0, 0, 0, 271, 272, 5, 116, 0, 0, + 272, 273, 5, 114, 0, 0, 273, 274, 5, 117, 0, 0, 274, 275, 5, 101, 0, 0, 275, + 82, 1, 0, 0, 0, 276, 277, 5, 102, 0, 0, 277, 278, 5, 97, 0, 0, 278, 279, 5, + 108, 0, 0, 279, 280, 5, 115, 0, 0, 280, 281, 5, 101, 0, 0, 281, 84, 1, 0, 0, + 0, 282, 283, 5, 110, 0, 0, 283, 284, 5, 117, 0, 0, 284, 285, 5, 108, 0, 0, + 285, 286, 5, 108, 0, 0, 286, 86, 1, 0, 0, 0, 287, 288, 5, 116, 0, 0, 288, + 289, 5, 104, 0, 0, 289, 290, 5, 105, 0, 0, 290, 291, 5, 115, 0, 0, 291, 88, + 1, 0, 0, 0, 292, 296, 7, 3, 0, 0, 293, 295, 7, 4, 0, 0, 294, 293, 1, 0, 0, + 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, + 90, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299, 300, 3, 93, 46, 0, 300, 301, 5, + 34, 0, 0, 301, 92, 1, 0, 0, 0, 302, 306, 5, 34, 0, 0, 303, 305, 8, 5, 0, 0, + 304, 303, 1, 0, 0, 0, 305, 308, 1, 0, 0, 0, 306, 304, 1, 0, 0, 0, 306, 307, + 1, 0, 0, 0, 307, 94, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 7, 0, 237, 247, 261, + 269, 296, 306, 1, 6, 0, 0, + ]; + + private static __ATN: ATN; + public static get _ATN(): ATN { + if (!JackLexer.__ATN) { + JackLexer.__ATN = new ATNDeserializer().deserialize( + JackLexer._serializedATN, + ); + } + + return JackLexer.__ATN; + } + + static DecisionsToDFA = JackLexer._ATN.decisionToState.map( + (ds: DecisionState, index: number) => new DFA(ds, index), + ); +} diff --git a/simulator/src/jack/generated/JackParser.interp b/simulator/src/jack/generated/JackParser.interp new file mode 100644 index 00000000..b691bc96 --- /dev/null +++ b/simulator/src/jack/generated/JackParser.interp @@ -0,0 +1,148 @@ +token literal names: +null +'class' +'constructor' +'function' +'method' +'field' +'static' +'var' +'int' +'char' +'boolean' +'void' +'let' +'do' +'if' +'else' +'while' +'return' +'{' +'}' +'(' +')' +'[' +']' +'.' +',' +';' +'=' +'+' +'-' +'*' +'/' +'&' +'|' +'~' +'<' +'>' +null +null +null +null +'true' +'false' +'null' +'this' +null +null +null + +token symbolic names: +null +CLASS +CONSTRUCTOR +FUNCTION +METHOD +FIELD +STATIC +VAR +INT +CHAR +BOOLEAN +VOID +LET +DO +IF +ELSE +WHILE +RETURN +LBRACE +RBRACE +LPAREN +RPAREN +LBRACKET +RBRACKET +DOT +COMMA +SEMICOLON +EQUALS +PLUS +MINUS +MUL +DIV +AND +OR +TILDE +LESS_THAN +GREATER_THAN +WS +COMMENT +LINE_COMMENT +INTEGER_LITERAL +TRUE +FALSE +NULL_LITERAL +THIS_LITERAL +IDENTIFIER +STRING_LITERAL +UnterminatedStringLiteral + +rule names: +program +classDeclaration +className +classVarDec +fieldList +fieldName +subroutineDeclaration +subroutineType +subroutineDecWithoutType +subroutineName +subroutineReturnType +varType +parameterList +parameter +parameterName +subroutineBody +rBrace +varDeclaration +varNameInDeclaration +varName +statements +statement +letStatement +equals +ifElseStatement +ifStatement +ifExpression +elseStatement +whileStatement +whileExpression +doStatement +subroutineCall +subroutineId +returnStatement +expressionList +expression +groupedExpression +unaryOperation +arrayAccess +constant +booleanLiteral +unaryOperator +binaryOperator + + +atn: +[4, 1, 47, 317, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 94, 8, 1, 10, 1, 12, 1, 97, 9, 1, 1, 1, 5, 1, 100, 8, 1, 10, 1, 12, 1, 103, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 117, 8, 4, 10, 4, 12, 4, 120, 9, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 5, 12, 147, 8, 12, 10, 12, 12, 12, 150, 9, 12, 3, 12, 152, 8, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 161, 8, 15, 10, 15, 12, 15, 164, 9, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 176, 8, 17, 10, 17, 12, 17, 179, 9, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 5, 20, 188, 8, 20, 10, 20, 12, 20, 191, 9, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 198, 8, 21, 1, 22, 1, 22, 1, 22, 3, 22, 203, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 3, 24, 213, 8, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 251, 8, 32, 1, 32, 3, 32, 254, 8, 32, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 260, 8, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 5, 34, 267, 8, 34, 10, 34, 12, 34, 270, 9, 34, 3, 34, 272, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 3, 35, 281, 8, 35, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 287, 8, 35, 10, 35, 12, 35, 290, 9, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 309, 8, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 0, 1, 70, 43, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 0, 6, 1, 0, 5, 6, 1, 0, 2, 4, 2, 0, 8, 10, 45, 45, 1, 0, 41, 42, 2, 0, 29, 29, 34, 34, 2, 0, 27, 33, 35, 36, 303, 0, 86, 1, 0, 0, 0, 2, 89, 1, 0, 0, 0, 4, 106, 1, 0, 0, 0, 6, 108, 1, 0, 0, 0, 8, 112, 1, 0, 0, 0, 10, 121, 1, 0, 0, 0, 12, 123, 1, 0, 0, 0, 14, 126, 1, 0, 0, 0, 16, 128, 1, 0, 0, 0, 18, 135, 1, 0, 0, 0, 20, 139, 1, 0, 0, 0, 22, 141, 1, 0, 0, 0, 24, 151, 1, 0, 0, 0, 26, 153, 1, 0, 0, 0, 28, 156, 1, 0, 0, 0, 30, 158, 1, 0, 0, 0, 32, 168, 1, 0, 0, 0, 34, 170, 1, 0, 0, 0, 36, 182, 1, 0, 0, 0, 38, 184, 1, 0, 0, 0, 40, 189, 1, 0, 0, 0, 42, 197, 1, 0, 0, 0, 44, 199, 1, 0, 0, 0, 46, 208, 1, 0, 0, 0, 48, 210, 1, 0, 0, 0, 50, 214, 1, 0, 0, 0, 52, 222, 1, 0, 0, 0, 54, 224, 1, 0, 0, 0, 56, 229, 1, 0, 0, 0, 58, 237, 1, 0, 0, 0, 60, 239, 1, 0, 0, 0, 62, 243, 1, 0, 0, 0, 64, 253, 1, 0, 0, 0, 66, 257, 1, 0, 0, 0, 68, 271, 1, 0, 0, 0, 70, 280, 1, 0, 0, 0, 72, 291, 1, 0, 0, 0, 74, 295, 1, 0, 0, 0, 76, 298, 1, 0, 0, 0, 78, 308, 1, 0, 0, 0, 80, 310, 1, 0, 0, 0, 82, 312, 1, 0, 0, 0, 84, 314, 1, 0, 0, 0, 86, 87, 3, 2, 1, 0, 87, 88, 5, 0, 0, 1, 88, 1, 1, 0, 0, 0, 89, 90, 5, 1, 0, 0, 90, 91, 3, 4, 2, 0, 91, 95, 5, 18, 0, 0, 92, 94, 3, 6, 3, 0, 93, 92, 1, 0, 0, 0, 94, 97, 1, 0, 0, 0, 95, 93, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 101, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 98, 100, 3, 12, 6, 0, 99, 98, 1, 0, 0, 0, 100, 103, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 101, 102, 1, 0, 0, 0, 102, 104, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 104, 105, 3, 32, 16, 0, 105, 3, 1, 0, 0, 0, 106, 107, 5, 45, 0, 0, 107, 5, 1, 0, 0, 0, 108, 109, 7, 0, 0, 0, 109, 110, 3, 8, 4, 0, 110, 111, 5, 26, 0, 0, 111, 7, 1, 0, 0, 0, 112, 113, 3, 22, 11, 0, 113, 118, 3, 10, 5, 0, 114, 115, 5, 25, 0, 0, 115, 117, 3, 10, 5, 0, 116, 114, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 9, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 121, 122, 5, 45, 0, 0, 122, 11, 1, 0, 0, 0, 123, 124, 3, 14, 7, 0, 124, 125, 3, 16, 8, 0, 125, 13, 1, 0, 0, 0, 126, 127, 7, 1, 0, 0, 127, 15, 1, 0, 0, 0, 128, 129, 3, 20, 10, 0, 129, 130, 3, 18, 9, 0, 130, 131, 5, 20, 0, 0, 131, 132, 3, 24, 12, 0, 132, 133, 5, 21, 0, 0, 133, 134, 3, 30, 15, 0, 134, 17, 1, 0, 0, 0, 135, 136, 5, 45, 0, 0, 136, 19, 1, 0, 0, 0, 137, 140, 3, 22, 11, 0, 138, 140, 5, 11, 0, 0, 139, 137, 1, 0, 0, 0, 139, 138, 1, 0, 0, 0, 140, 21, 1, 0, 0, 0, 141, 142, 7, 2, 0, 0, 142, 23, 1, 0, 0, 0, 143, 148, 3, 26, 13, 0, 144, 145, 5, 25, 0, 0, 145, 147, 3, 26, 13, 0, 146, 144, 1, 0, 0, 0, 147, 150, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 148, 149, 1, 0, 0, 0, 149, 152, 1, 0, 0, 0, 150, 148, 1, 0, 0, 0, 151, 143, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 25, 1, 0, 0, 0, 153, 154, 3, 22, 11, 0, 154, 155, 3, 28, 14, 0, 155, 27, 1, 0, 0, 0, 156, 157, 5, 45, 0, 0, 157, 29, 1, 0, 0, 0, 158, 162, 5, 18, 0, 0, 159, 161, 3, 34, 17, 0, 160, 159, 1, 0, 0, 0, 161, 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 165, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 3, 40, 20, 0, 166, 167, 3, 32, 16, 0, 167, 31, 1, 0, 0, 0, 168, 169, 5, 19, 0, 0, 169, 33, 1, 0, 0, 0, 170, 171, 5, 7, 0, 0, 171, 172, 3, 22, 11, 0, 172, 177, 3, 36, 18, 0, 173, 174, 5, 25, 0, 0, 174, 176, 3, 36, 18, 0, 175, 173, 1, 0, 0, 0, 176, 179, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 180, 1, 0, 0, 0, 179, 177, 1, 0, 0, 0, 180, 181, 5, 26, 0, 0, 181, 35, 1, 0, 0, 0, 182, 183, 5, 45, 0, 0, 183, 37, 1, 0, 0, 0, 184, 185, 5, 45, 0, 0, 185, 39, 1, 0, 0, 0, 186, 188, 3, 42, 21, 0, 187, 186, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 41, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 198, 3, 44, 22, 0, 193, 198, 3, 48, 24, 0, 194, 198, 3, 56, 28, 0, 195, 198, 3, 60, 30, 0, 196, 198, 3, 66, 33, 0, 197, 192, 1, 0, 0, 0, 197, 193, 1, 0, 0, 0, 197, 194, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 197, 196, 1, 0, 0, 0, 198, 43, 1, 0, 0, 0, 199, 202, 5, 12, 0, 0, 200, 203, 3, 38, 19, 0, 201, 203, 3, 76, 38, 0, 202, 200, 1, 0, 0, 0, 202, 201, 1, 0, 0, 0, 203, 204, 1, 0, 0, 0, 204, 205, 3, 46, 23, 0, 205, 206, 3, 70, 35, 0, 206, 207, 5, 26, 0, 0, 207, 45, 1, 0, 0, 0, 208, 209, 5, 27, 0, 0, 209, 47, 1, 0, 0, 0, 210, 212, 3, 50, 25, 0, 211, 213, 3, 54, 27, 0, 212, 211, 1, 0, 0, 0, 212, 213, 1, 0, 0, 0, 213, 49, 1, 0, 0, 0, 214, 215, 5, 14, 0, 0, 215, 216, 5, 20, 0, 0, 216, 217, 3, 52, 26, 0, 217, 218, 5, 21, 0, 0, 218, 219, 5, 18, 0, 0, 219, 220, 3, 40, 20, 0, 220, 221, 3, 32, 16, 0, 221, 51, 1, 0, 0, 0, 222, 223, 3, 70, 35, 0, 223, 53, 1, 0, 0, 0, 224, 225, 5, 15, 0, 0, 225, 226, 5, 18, 0, 0, 226, 227, 3, 40, 20, 0, 227, 228, 3, 32, 16, 0, 228, 55, 1, 0, 0, 0, 229, 230, 5, 16, 0, 0, 230, 231, 5, 20, 0, 0, 231, 232, 3, 58, 29, 0, 232, 233, 5, 21, 0, 0, 233, 234, 5, 18, 0, 0, 234, 235, 3, 40, 20, 0, 235, 236, 3, 32, 16, 0, 236, 57, 1, 0, 0, 0, 237, 238, 3, 70, 35, 0, 238, 59, 1, 0, 0, 0, 239, 240, 5, 13, 0, 0, 240, 241, 3, 62, 31, 0, 241, 242, 5, 26, 0, 0, 242, 61, 1, 0, 0, 0, 243, 244, 3, 64, 32, 0, 244, 245, 5, 20, 0, 0, 245, 246, 3, 68, 34, 0, 246, 247, 5, 21, 0, 0, 247, 63, 1, 0, 0, 0, 248, 251, 3, 4, 2, 0, 249, 251, 5, 44, 0, 0, 250, 248, 1, 0, 0, 0, 250, 249, 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 254, 5, 24, 0, 0, 253, 250, 1, 0, 0, 0, 253, 254, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 256, 3, 18, 9, 0, 256, 65, 1, 0, 0, 0, 257, 259, 5, 17, 0, 0, 258, 260, 3, 70, 35, 0, 259, 258, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 262, 5, 26, 0, 0, 262, 67, 1, 0, 0, 0, 263, 268, 3, 70, 35, 0, 264, 265, 5, 25, 0, 0, 265, 267, 3, 70, 35, 0, 266, 264, 1, 0, 0, 0, 267, 270, 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 272, 1, 0, 0, 0, 270, 268, 1, 0, 0, 0, 271, 263, 1, 0, 0, 0, 271, 272, 1, 0, 0, 0, 272, 69, 1, 0, 0, 0, 273, 274, 6, 35, -1, 0, 274, 281, 3, 78, 39, 0, 275, 281, 3, 38, 19, 0, 276, 281, 3, 62, 31, 0, 277, 281, 3, 76, 38, 0, 278, 281, 3, 74, 37, 0, 279, 281, 3, 72, 36, 0, 280, 273, 1, 0, 0, 0, 280, 275, 1, 0, 0, 0, 280, 276, 1, 0, 0, 0, 280, 277, 1, 0, 0, 0, 280, 278, 1, 0, 0, 0, 280, 279, 1, 0, 0, 0, 281, 288, 1, 0, 0, 0, 282, 283, 10, 2, 0, 0, 283, 284, 3, 84, 42, 0, 284, 285, 3, 70, 35, 3, 285, 287, 1, 0, 0, 0, 286, 282, 1, 0, 0, 0, 287, 290, 1, 0, 0, 0, 288, 286, 1, 0, 0, 0, 288, 289, 1, 0, 0, 0, 289, 71, 1, 0, 0, 0, 290, 288, 1, 0, 0, 0, 291, 292, 5, 20, 0, 0, 292, 293, 3, 70, 35, 0, 293, 294, 5, 21, 0, 0, 294, 73, 1, 0, 0, 0, 295, 296, 3, 82, 41, 0, 296, 297, 3, 70, 35, 0, 297, 75, 1, 0, 0, 0, 298, 299, 3, 38, 19, 0, 299, 300, 5, 22, 0, 0, 300, 301, 3, 70, 35, 0, 301, 302, 5, 23, 0, 0, 302, 77, 1, 0, 0, 0, 303, 309, 5, 40, 0, 0, 304, 309, 5, 46, 0, 0, 305, 309, 3, 80, 40, 0, 306, 309, 5, 43, 0, 0, 307, 309, 5, 44, 0, 0, 308, 303, 1, 0, 0, 0, 308, 304, 1, 0, 0, 0, 308, 305, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 308, 307, 1, 0, 0, 0, 309, 79, 1, 0, 0, 0, 310, 311, 7, 3, 0, 0, 311, 81, 1, 0, 0, 0, 312, 313, 7, 4, 0, 0, 313, 83, 1, 0, 0, 0, 314, 315, 7, 5, 0, 0, 315, 85, 1, 0, 0, 0, 20, 95, 101, 118, 139, 148, 151, 162, 177, 189, 197, 202, 212, 250, 253, 259, 268, 271, 280, 288, 308] \ No newline at end of file diff --git a/simulator/src/jack/generated/JackParser.tokens b/simulator/src/jack/generated/JackParser.tokens new file mode 100644 index 00000000..225dc556 --- /dev/null +++ b/simulator/src/jack/generated/JackParser.tokens @@ -0,0 +1,87 @@ +CLASS=1 +CONSTRUCTOR=2 +FUNCTION=3 +METHOD=4 +FIELD=5 +STATIC=6 +VAR=7 +INT=8 +CHAR=9 +BOOLEAN=10 +VOID=11 +LET=12 +DO=13 +IF=14 +ELSE=15 +WHILE=16 +RETURN=17 +LBRACE=18 +RBRACE=19 +LPAREN=20 +RPAREN=21 +LBRACKET=22 +RBRACKET=23 +DOT=24 +COMMA=25 +SEMICOLON=26 +EQUALS=27 +PLUS=28 +MINUS=29 +MUL=30 +DIV=31 +AND=32 +OR=33 +TILDE=34 +LESS_THAN=35 +GREATER_THAN=36 +WS=37 +COMMENT=38 +LINE_COMMENT=39 +INTEGER_LITERAL=40 +TRUE=41 +FALSE=42 +NULL_LITERAL=43 +THIS_LITERAL=44 +IDENTIFIER=45 +STRING_LITERAL=46 +UnterminatedStringLiteral=47 +'class'=1 +'constructor'=2 +'function'=3 +'method'=4 +'field'=5 +'static'=6 +'var'=7 +'int'=8 +'char'=9 +'boolean'=10 +'void'=11 +'let'=12 +'do'=13 +'if'=14 +'else'=15 +'while'=16 +'return'=17 +'{'=18 +'}'=19 +'('=20 +')'=21 +'['=22 +']'=23 +'.'=24 +','=25 +';'=26 +'='=27 +'+'=28 +'-'=29 +'*'=30 +'/'=31 +'&'=32 +'|'=33 +'~'=34 +'<'=35 +'>'=36 +'true'=41 +'false'=42 +'null'=43 +'this'=44 diff --git a/simulator/src/jack/generated/JackParser.ts b/simulator/src/jack/generated/JackParser.ts new file mode 100644 index 00000000..b3205261 --- /dev/null +++ b/simulator/src/jack/generated/JackParser.ts @@ -0,0 +1,3739 @@ +// Generated from JackParser.g4 by ANTLR 4.13.2 +// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols + +import { + ATN, + ATNDeserializer, + DecisionState, + DFA, + FailedPredicateException, + NoViableAltException, + Parser, + ParserATNSimulator, + ParserRuleContext, + PredictionContextCache, + RecognitionException, + RuleContext, + TerminalNode, + Token, + TokenStream +} from "antlr4"; +import JackParserListener from "./JackParserListener.js"; +// for running tests with parameters, TODO: discuss strategy for typed parameters in CI +// eslint-disable-next-line no-unused-vars + +import { LocalSymbolTable, SubroutineScope } from "../symbol.js"; + +export default class JackParser extends Parser { + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WS = 37; + public static readonly COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly TRUE = 41; + public static readonly FALSE = 42; + public static readonly NULL_LITERAL = 43; + public static readonly THIS_LITERAL = 44; + public static readonly IDENTIFIER = 45; + public static readonly STRING_LITERAL = 46; + public static readonly UnterminatedStringLiteral = 47; + public static override readonly EOF = Token.EOF; + public static readonly RULE_program = 0; + public static readonly RULE_classDeclaration = 1; + public static readonly RULE_className = 2; + public static readonly RULE_classVarDec = 3; + public static readonly RULE_fieldList = 4; + public static readonly RULE_fieldName = 5; + public static readonly RULE_subroutineDeclaration = 6; + public static readonly RULE_subroutineType = 7; + public static readonly RULE_subroutineDecWithoutType = 8; + public static readonly RULE_subroutineName = 9; + public static readonly RULE_subroutineReturnType = 10; + public static readonly RULE_varType = 11; + public static readonly RULE_parameterList = 12; + public static readonly RULE_parameter = 13; + public static readonly RULE_parameterName = 14; + public static readonly RULE_subroutineBody = 15; + public static readonly RULE_rBrace = 16; + public static readonly RULE_varDeclaration = 17; + public static readonly RULE_varNameInDeclaration = 18; + public static readonly RULE_varName = 19; + public static readonly RULE_statements = 20; + public static readonly RULE_statement = 21; + public static readonly RULE_letStatement = 22; + public static readonly RULE_equals = 23; + public static readonly RULE_ifElseStatement = 24; + public static readonly RULE_ifStatement = 25; + public static readonly RULE_ifExpression = 26; + public static readonly RULE_elseStatement = 27; + public static readonly RULE_whileStatement = 28; + public static readonly RULE_whileExpression = 29; + public static readonly RULE_doStatement = 30; + public static readonly RULE_subroutineCall = 31; + public static readonly RULE_subroutineId = 32; + public static readonly RULE_returnStatement = 33; + public static readonly RULE_expressionList = 34; + public static readonly RULE_expression = 35; + public static readonly RULE_groupedExpression = 36; + public static readonly RULE_unaryOperation = 37; + public static readonly RULE_arrayAccess = 38; + public static readonly RULE_constant = 39; + public static readonly RULE_booleanLiteral = 40; + public static readonly RULE_unaryOperator = 41; + public static readonly RULE_binaryOperator = 42; + public static readonly literalNames: (string | null)[] = [ + null, + "'class'", + "'constructor'", + "'function'", + "'method'", + "'field'", + "'static'", + "'var'", + "'int'", + "'char'", + "'boolean'", + "'void'", + "'let'", + "'do'", + "'if'", + "'else'", + "'while'", + "'return'", + "'{'", + "'}'", + "'('", + "')'", + "'['", + "']'", + "'.'", + "','", + "';'", + "'='", + "'+'", + "'-'", + "'*'", + "'/'", + "'&'", + "'|'", + "'~'", + "'<'", + "'>'", + null, + null, + null, + null, + "'true'", + "'false'", + "'null'", + "'this'", + ]; + public static readonly symbolicNames: (string | null)[] = [ + null, + "CLASS", + "CONSTRUCTOR", + "FUNCTION", + "METHOD", + "FIELD", + "STATIC", + "VAR", + "INT", + "CHAR", + "BOOLEAN", + "VOID", + "LET", + "DO", + "IF", + "ELSE", + "WHILE", + "RETURN", + "LBRACE", + "RBRACE", + "LPAREN", + "RPAREN", + "LBRACKET", + "RBRACKET", + "DOT", + "COMMA", + "SEMICOLON", + "EQUALS", + "PLUS", + "MINUS", + "MUL", + "DIV", + "AND", + "OR", + "TILDE", + "LESS_THAN", + "GREATER_THAN", + "WS", + "COMMENT", + "LINE_COMMENT", + "INTEGER_LITERAL", + "TRUE", + "FALSE", + "NULL_LITERAL", + "THIS_LITERAL", + "IDENTIFIER", + "STRING_LITERAL", + "UnterminatedStringLiteral", + ]; + // tslint:disable:no-trailing-whitespace + public static readonly ruleNames: string[] = [ + "program", + "classDeclaration", + "className", + "classVarDec", + "fieldList", + "fieldName", + "subroutineDeclaration", + "subroutineType", + "subroutineDecWithoutType", + "subroutineName", + "subroutineReturnType", + "varType", + "parameterList", + "parameter", + "parameterName", + "subroutineBody", + "rBrace", + "varDeclaration", + "varNameInDeclaration", + "varName", + "statements", + "statement", + "letStatement", + "equals", + "ifElseStatement", + "ifStatement", + "ifExpression", + "elseStatement", + "whileStatement", + "whileExpression", + "doStatement", + "subroutineCall", + "subroutineId", + "returnStatement", + "expressionList", + "expression", + "groupedExpression", + "unaryOperation", + "arrayAccess", + "constant", + "booleanLiteral", + "unaryOperator", + "binaryOperator", + ]; + public get grammarFileName(): string { + return "JackParser.g4"; + } + public get literalNames(): (string | null)[] { + return JackParser.literalNames; + } + public get symbolicNames(): (string | null)[] { + return JackParser.symbolicNames; + } + public get ruleNames(): string[] { + return JackParser.ruleNames; + } + public get serializedATN(): number[] { + return JackParser._serializedATN; + } + + protected createFailedPredicateException( + predicate?: string, + message?: string, + ): FailedPredicateException { + return new FailedPredicateException(this, predicate, message); + } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator( + this, + JackParser._ATN, + JackParser.DecisionsToDFA, + new PredictionContextCache(), + ); + } + // @RuleVersion(0) + public program(): ProgramContext { + const localctx: ProgramContext = new ProgramContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 0, JackParser.RULE_program); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 86; + this.classDeclaration(); + this.state = 87; + this.match(JackParser.EOF); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public classDeclaration(): ClassDeclarationContext { + const localctx: ClassDeclarationContext = new ClassDeclarationContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 2, JackParser.RULE_classDeclaration); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 89; + this.match(JackParser.CLASS); + this.state = 90; + this.className(); + this.state = 91; + this.match(JackParser.LBRACE); + this.state = 95; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === 5 || _la === 6) { + { + { + this.state = 92; + this.classVarDec(); + } + } + this.state = 97; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ((_la & ~0x1f) === 0 && ((1 << _la) & 28) !== 0) { + { + { + this.state = 98; + this.subroutineDeclaration(); + } + } + this.state = 103; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 104; + this.rBrace(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public className(): ClassNameContext { + const localctx: ClassNameContext = new ClassNameContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 4, JackParser.RULE_className); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 106; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public classVarDec(): ClassVarDecContext { + const localctx: ClassVarDecContext = new ClassVarDecContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 6, JackParser.RULE_classVarDec); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 108; + _la = this._input.LA(1); + if (!(_la === 5 || _la === 6)) { + this._errHandler.recoverInline(this); + } else { + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 109; + this.fieldList(); + this.state = 110; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public fieldList(): FieldListContext { + const localctx: FieldListContext = new FieldListContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 8, JackParser.RULE_fieldList); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 112; + this.varType(); + this.state = 113; + this.fieldName(); + this.state = 118; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === 25) { + { + { + this.state = 114; + this.match(JackParser.COMMA); + this.state = 115; + this.fieldName(); + } + } + this.state = 120; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public fieldName(): FieldNameContext { + const localctx: FieldNameContext = new FieldNameContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 10, JackParser.RULE_fieldName); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 121; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineDeclaration(): SubroutineDeclarationContext { + const localctx: SubroutineDeclarationContext = + new SubroutineDeclarationContext(this, this._ctx, this.state); + this.enterRule(localctx, 12, JackParser.RULE_subroutineDeclaration); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 123; + this.subroutineType(); + this.state = 124; + this.subroutineDecWithoutType(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineType(): SubroutineTypeContext { + const localctx: SubroutineTypeContext = new SubroutineTypeContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 14, JackParser.RULE_subroutineType); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 126; + _la = this._input.LA(1); + if (!((_la & ~0x1f) === 0 && ((1 << _la) & 28) !== 0)) { + this._errHandler.recoverInline(this); + } else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + const localctx: SubroutineDecWithoutTypeContext = + new SubroutineDecWithoutTypeContext(this, this._ctx, this.state); + this.enterRule(localctx, 16, JackParser.RULE_subroutineDecWithoutType); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 128; + this.subroutineReturnType(); + this.state = 129; + this.subroutineName(); + this.state = 130; + this.match(JackParser.LPAREN); + this.state = 131; + this.parameterList(); + this.state = 132; + this.match(JackParser.RPAREN); + this.state = 133; + this.subroutineBody(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineName(): SubroutineNameContext { + const localctx: SubroutineNameContext = new SubroutineNameContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 18, JackParser.RULE_subroutineName); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 135; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineReturnType(): SubroutineReturnTypeContext { + const localctx: SubroutineReturnTypeContext = + new SubroutineReturnTypeContext(this, this._ctx, this.state); + this.enterRule(localctx, 20, JackParser.RULE_subroutineReturnType); + try { + this.state = 139; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 8: + case 9: + case 10: + case 45: + this.enterOuterAlt(localctx, 1); + { + this.state = 137; + this.varType(); + } + break; + case 11: + this.enterOuterAlt(localctx, 2); + { + this.state = 138; + this.match(JackParser.VOID); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public varType(): VarTypeContext { + const localctx: VarTypeContext = new VarTypeContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 22, JackParser.RULE_varType); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 141; + _la = this._input.LA(1); + if ( + !(((_la & ~0x1f) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45) + ) { + this._errHandler.recoverInline(this); + } else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public parameterList(): ParameterListContext { + const localctx: ParameterListContext = new ParameterListContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 24, JackParser.RULE_parameterList); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 151; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((_la & ~0x1f) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45) { + { + this.state = 143; + this.parameter(); + this.state = 148; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === 25) { + { + { + this.state = 144; + this.match(JackParser.COMMA); + this.state = 145; + this.parameter(); + } + } + this.state = 150; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public parameter(): ParameterContext { + const localctx: ParameterContext = new ParameterContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 26, JackParser.RULE_parameter); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 153; + this.varType(); + this.state = 154; + this.parameterName(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public parameterName(): ParameterNameContext { + const localctx: ParameterNameContext = new ParameterNameContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 28, JackParser.RULE_parameterName); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 156; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineBody(): SubroutineBodyContext { + const localctx: SubroutineBodyContext = new SubroutineBodyContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 30, JackParser.RULE_subroutineBody); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 158; + this.match(JackParser.LBRACE); + this.state = 162; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === 7) { + { + { + this.state = 159; + this.varDeclaration(); + } + } + this.state = 164; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 165; + this.statements(); + this.state = 166; + this.rBrace(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public rBrace(): RBraceContext { + const localctx: RBraceContext = new RBraceContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 32, JackParser.RULE_rBrace); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 168; + this.match(JackParser.RBRACE); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public varDeclaration(): VarDeclarationContext { + const localctx: VarDeclarationContext = new VarDeclarationContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 34, JackParser.RULE_varDeclaration); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 170; + this.match(JackParser.VAR); + this.state = 171; + this.varType(); + this.state = 172; + this.varNameInDeclaration(); + this.state = 177; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === 25) { + { + { + this.state = 173; + this.match(JackParser.COMMA); + this.state = 174; + this.varNameInDeclaration(); + } + } + this.state = 179; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 180; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public varNameInDeclaration(): VarNameInDeclarationContext { + const localctx: VarNameInDeclarationContext = + new VarNameInDeclarationContext(this, this._ctx, this.state); + this.enterRule(localctx, 36, JackParser.RULE_varNameInDeclaration); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 182; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public varName(): VarNameContext { + const localctx: VarNameContext = new VarNameContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 38, JackParser.RULE_varName); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 184; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public statements(): StatementsContext { + const localctx: StatementsContext = new StatementsContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 40, JackParser.RULE_statements); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 189; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ((_la & ~0x1f) === 0 && ((1 << _la) & 225280) !== 0) { + { + { + this.state = 186; + this.statement(); + } + } + this.state = 191; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public statement(): StatementContext { + const localctx: StatementContext = new StatementContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 42, JackParser.RULE_statement); + try { + this.state = 197; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 12: + this.enterOuterAlt(localctx, 1); + { + this.state = 192; + this.letStatement(); + } + break; + case 14: + this.enterOuterAlt(localctx, 2); + { + this.state = 193; + this.ifElseStatement(); + } + break; + case 16: + this.enterOuterAlt(localctx, 3); + { + this.state = 194; + this.whileStatement(); + } + break; + case 13: + this.enterOuterAlt(localctx, 4); + { + this.state = 195; + this.doStatement(); + } + break; + case 17: + this.enterOuterAlt(localctx, 5); + { + this.state = 196; + this.returnStatement(); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public letStatement(): LetStatementContext { + const localctx: LetStatementContext = new LetStatementContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 44, JackParser.RULE_letStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 199; + this.match(JackParser.LET); + this.state = 202; + this._errHandler.sync(this); + switch (this._interp.adaptivePredict(this._input, 10, this._ctx)) { + case 1: + { + this.state = 200; + this.varName(); + } + break; + case 2: + { + this.state = 201; + this.arrayAccess(); + } + break; + } + this.state = 204; + this.equals(); + this.state = 205; + this.expression(0); + this.state = 206; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public equals(): EqualsContext { + const localctx: EqualsContext = new EqualsContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 46, JackParser.RULE_equals); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 208; + this.match(JackParser.EQUALS); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ifElseStatement(): IfElseStatementContext { + const localctx: IfElseStatementContext = new IfElseStatementContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 48, JackParser.RULE_ifElseStatement); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 210; + this.ifStatement(); + this.state = 212; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la === 15) { + { + this.state = 211; + this.elseStatement(); + } + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ifStatement(): IfStatementContext { + const localctx: IfStatementContext = new IfStatementContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 50, JackParser.RULE_ifStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 214; + this.match(JackParser.IF); + this.state = 215; + this.match(JackParser.LPAREN); + this.state = 216; + this.ifExpression(); + this.state = 217; + this.match(JackParser.RPAREN); + this.state = 218; + this.match(JackParser.LBRACE); + this.state = 219; + this.statements(); + this.state = 220; + this.rBrace(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ifExpression(): IfExpressionContext { + const localctx: IfExpressionContext = new IfExpressionContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 52, JackParser.RULE_ifExpression); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 222; + this.expression(0); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public elseStatement(): ElseStatementContext { + const localctx: ElseStatementContext = new ElseStatementContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 54, JackParser.RULE_elseStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 224; + this.match(JackParser.ELSE); + this.state = 225; + this.match(JackParser.LBRACE); + this.state = 226; + this.statements(); + this.state = 227; + this.rBrace(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public whileStatement(): WhileStatementContext { + const localctx: WhileStatementContext = new WhileStatementContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 56, JackParser.RULE_whileStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 229; + this.match(JackParser.WHILE); + this.state = 230; + this.match(JackParser.LPAREN); + this.state = 231; + this.whileExpression(); + this.state = 232; + this.match(JackParser.RPAREN); + this.state = 233; + this.match(JackParser.LBRACE); + this.state = 234; + this.statements(); + this.state = 235; + this.rBrace(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public whileExpression(): WhileExpressionContext { + const localctx: WhileExpressionContext = new WhileExpressionContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 58, JackParser.RULE_whileExpression); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 237; + this.expression(0); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public doStatement(): DoStatementContext { + const localctx: DoStatementContext = new DoStatementContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 60, JackParser.RULE_doStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 239; + this.match(JackParser.DO); + this.state = 240; + this.subroutineCall(); + this.state = 241; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineCall(): SubroutineCallContext { + const localctx: SubroutineCallContext = new SubroutineCallContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 62, JackParser.RULE_subroutineCall); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 243; + this.subroutineId(); + this.state = 244; + this.match(JackParser.LPAREN); + this.state = 245; + this.expressionList(); + this.state = 246; + this.match(JackParser.RPAREN); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineId(): SubroutineIdContext { + const localctx: SubroutineIdContext = new SubroutineIdContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 64, JackParser.RULE_subroutineId); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 253; + this._errHandler.sync(this); + switch (this._interp.adaptivePredict(this._input, 13, this._ctx)) { + case 1: + { + this.state = 250; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 45: + { + this.state = 248; + this.className(); + } + break; + case 44: + { + this.state = 249; + this.match(JackParser.THIS_LITERAL); + } + break; + default: + throw new NoViableAltException(this); + } + this.state = 252; + this.match(JackParser.DOT); + } + break; + } + this.state = 255; + this.subroutineName(); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public returnStatement(): ReturnStatementContext { + const localctx: ReturnStatementContext = new ReturnStatementContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 66, JackParser.RULE_returnStatement); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 257; + this.match(JackParser.RETURN); + this.state = 259; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + ((_la - 20) & ~0x1f) === 0 && + ((1 << (_la - 20)) & 133186049) !== 0 + ) { + { + this.state = 258; + this.expression(0); + } + } + + this.state = 261; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public expressionList(): ExpressionListContext { + const localctx: ExpressionListContext = new ExpressionListContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 68, JackParser.RULE_expressionList); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 271; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ( + ((_la - 20) & ~0x1f) === 0 && + ((1 << (_la - 20)) & 133186049) !== 0 + ) { + { + this.state = 263; + this.expression(0); + this.state = 268; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la === 25) { + { + { + this.state = 264; + this.match(JackParser.COMMA); + this.state = 265; + this.expression(0); + } + } + this.state = 270; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + + public expression(): ExpressionContext; + public expression(_p: number): ExpressionContext; + // @RuleVersion(0) + public expression(_p?: number): ExpressionContext { + if (_p === undefined) { + _p = 0; + } + + const _parentctx: ParserRuleContext = this._ctx; + const _parentState: number = this.state; + let localctx: ExpressionContext = new ExpressionContext( + this, + this._ctx, + _parentState, + ); + const _startState = 70; + this.enterRecursionRule(localctx, 70, JackParser.RULE_expression, _p); + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + this.state = 280; + this._errHandler.sync(this); + switch (this._interp.adaptivePredict(this._input, 17, this._ctx)) { + case 1: + { + this.state = 274; + this.constant(); + } + break; + case 2: + { + this.state = 275; + this.varName(); + } + break; + case 3: + { + this.state = 276; + this.subroutineCall(); + } + break; + case 4: + { + this.state = 277; + this.arrayAccess(); + } + break; + case 5: + { + this.state = 278; + this.unaryOperation(); + } + break; + case 6: + { + this.state = 279; + this.groupedExpression(); + } + break; + } + this._ctx.stop = this._input.LT(-1); + this.state = 288; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 18, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners != null) { + this.triggerExitRuleEvent(); + } + { + { + localctx = new ExpressionContext( + this, + _parentctx, + _parentState, + ); + this.pushNewRecursionContext( + localctx, + _startState, + JackParser.RULE_expression, + ); + this.state = 282; + if (!this.precpred(this._ctx, 2)) { + throw this.createFailedPredicateException( + "this.precpred(this._ctx, 2)", + ); + } + this.state = 283; + this.binaryOperator(); + this.state = 284; + this.expression(3); + } + } + } + this.state = 290; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 18, this._ctx); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.unrollRecursionContexts(_parentctx); + } + return localctx; + } + // @RuleVersion(0) + public groupedExpression(): GroupedExpressionContext { + const localctx: GroupedExpressionContext = new GroupedExpressionContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 72, JackParser.RULE_groupedExpression); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 291; + this.match(JackParser.LPAREN); + this.state = 292; + this.expression(0); + this.state = 293; + this.match(JackParser.RPAREN); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public unaryOperation(): UnaryOperationContext { + const localctx: UnaryOperationContext = new UnaryOperationContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 74, JackParser.RULE_unaryOperation); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 295; + this.unaryOperator(); + this.state = 296; + this.expression(0); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public arrayAccess(): ArrayAccessContext { + const localctx: ArrayAccessContext = new ArrayAccessContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 76, JackParser.RULE_arrayAccess); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 298; + this.varName(); + this.state = 299; + this.match(JackParser.LBRACKET); + this.state = 300; + this.expression(0); + this.state = 301; + this.match(JackParser.RBRACKET); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public constant(): ConstantContext { + const localctx: ConstantContext = new ConstantContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 78, JackParser.RULE_constant); + try { + this.state = 308; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 40: + this.enterOuterAlt(localctx, 1); + { + this.state = 303; + this.match(JackParser.INTEGER_LITERAL); + } + break; + case 46: + this.enterOuterAlt(localctx, 2); + { + this.state = 304; + this.match(JackParser.STRING_LITERAL); + } + break; + case 41: + case 42: + this.enterOuterAlt(localctx, 3); + { + this.state = 305; + this.booleanLiteral(); + } + break; + case 43: + this.enterOuterAlt(localctx, 4); + { + this.state = 306; + this.match(JackParser.NULL_LITERAL); + } + break; + case 44: + this.enterOuterAlt(localctx, 5); + { + this.state = 307; + this.match(JackParser.THIS_LITERAL); + } + break; + default: + throw new NoViableAltException(this); + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public booleanLiteral(): BooleanLiteralContext { + const localctx: BooleanLiteralContext = new BooleanLiteralContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 80, JackParser.RULE_booleanLiteral); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 310; + _la = this._input.LA(1); + if (!(_la === 41 || _la === 42)) { + this._errHandler.recoverInline(this); + } else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public unaryOperator(): UnaryOperatorContext { + const localctx: UnaryOperatorContext = new UnaryOperatorContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 82, JackParser.RULE_unaryOperator); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 312; + _la = this._input.LA(1); + if (!(_la === 29 || _la === 34)) { + this._errHandler.recoverInline(this); + } else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public binaryOperator(): BinaryOperatorContext { + const localctx: BinaryOperatorContext = new BinaryOperatorContext( + this, + this._ctx, + this.state, + ); + this.enterRule(localctx, 84, JackParser.RULE_binaryOperator); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 314; + _la = this._input.LA(1); + if (!(((_la - 27) & ~0x1f) === 0 && ((1 << (_la - 27)) & 895) !== 0)) { + this._errHandler.recoverInline(this); + } else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } + + public sempred( + localctx: RuleContext, + ruleIndex: number, + predIndex: number, + ): boolean { + switch (ruleIndex) { + case 35: + return this.expression_sempred( + localctx as ExpressionContext, + predIndex, + ); + } + return true; + } + private expression_sempred( + localctx: ExpressionContext, + predIndex: number, + ): boolean { + switch (predIndex) { + case 0: + return this.precpred(this._ctx, 2); + } + return true; + } + + public static readonly _serializedATN: number[] = [ + 4, 1, 47, 317, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, + 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, + 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, + 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, + 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, + 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, + 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, + 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 1, 0, 1, 0, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 94, 8, 1, 10, 1, 12, 1, 97, 9, 1, 1, 1, 5, + 1, 100, 8, 1, 10, 1, 12, 1, 103, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 117, 8, 4, 10, 4, 12, 4, 120, 9, + 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, + 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 11, 1, 11, 1, + 12, 1, 12, 1, 12, 5, 12, 147, 8, 12, 10, 12, 12, 12, 150, 9, 12, 3, 12, 152, + 8, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 161, 8, 15, + 10, 15, 12, 15, 164, 9, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, + 1, 17, 1, 17, 1, 17, 5, 17, 176, 8, 17, 10, 17, 12, 17, 179, 9, 17, 1, 17, + 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 5, 20, 188, 8, 20, 10, 20, 12, 20, + 191, 9, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 198, 8, 21, 1, 22, 1, + 22, 1, 22, 3, 22, 203, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, + 24, 1, 24, 3, 24, 213, 8, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, + 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, + 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, + 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 251, 8, 32, 1, + 32, 3, 32, 254, 8, 32, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 260, 8, 33, 1, 33, + 1, 33, 1, 34, 1, 34, 1, 34, 5, 34, 267, 8, 34, 10, 34, 12, 34, 270, 9, 34, + 3, 34, 272, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 3, 35, + 281, 8, 35, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 287, 8, 35, 10, 35, 12, 35, + 290, 9, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, + 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 309, 8, 39, + 1, 40, 1, 40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 0, 1, 70, 43, 0, 2, 4, 6, + 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, + 84, 0, 6, 1, 0, 5, 6, 1, 0, 2, 4, 2, 0, 8, 10, 45, 45, 1, 0, 41, 42, 2, 0, + 29, 29, 34, 34, 2, 0, 27, 33, 35, 36, 303, 0, 86, 1, 0, 0, 0, 2, 89, 1, 0, + 0, 0, 4, 106, 1, 0, 0, 0, 6, 108, 1, 0, 0, 0, 8, 112, 1, 0, 0, 0, 10, 121, + 1, 0, 0, 0, 12, 123, 1, 0, 0, 0, 14, 126, 1, 0, 0, 0, 16, 128, 1, 0, 0, 0, + 18, 135, 1, 0, 0, 0, 20, 139, 1, 0, 0, 0, 22, 141, 1, 0, 0, 0, 24, 151, 1, + 0, 0, 0, 26, 153, 1, 0, 0, 0, 28, 156, 1, 0, 0, 0, 30, 158, 1, 0, 0, 0, 32, + 168, 1, 0, 0, 0, 34, 170, 1, 0, 0, 0, 36, 182, 1, 0, 0, 0, 38, 184, 1, 0, 0, + 0, 40, 189, 1, 0, 0, 0, 42, 197, 1, 0, 0, 0, 44, 199, 1, 0, 0, 0, 46, 208, + 1, 0, 0, 0, 48, 210, 1, 0, 0, 0, 50, 214, 1, 0, 0, 0, 52, 222, 1, 0, 0, 0, + 54, 224, 1, 0, 0, 0, 56, 229, 1, 0, 0, 0, 58, 237, 1, 0, 0, 0, 60, 239, 1, + 0, 0, 0, 62, 243, 1, 0, 0, 0, 64, 253, 1, 0, 0, 0, 66, 257, 1, 0, 0, 0, 68, + 271, 1, 0, 0, 0, 70, 280, 1, 0, 0, 0, 72, 291, 1, 0, 0, 0, 74, 295, 1, 0, 0, + 0, 76, 298, 1, 0, 0, 0, 78, 308, 1, 0, 0, 0, 80, 310, 1, 0, 0, 0, 82, 312, + 1, 0, 0, 0, 84, 314, 1, 0, 0, 0, 86, 87, 3, 2, 1, 0, 87, 88, 5, 0, 0, 1, 88, + 1, 1, 0, 0, 0, 89, 90, 5, 1, 0, 0, 90, 91, 3, 4, 2, 0, 91, 95, 5, 18, 0, 0, + 92, 94, 3, 6, 3, 0, 93, 92, 1, 0, 0, 0, 94, 97, 1, 0, 0, 0, 95, 93, 1, 0, 0, + 0, 95, 96, 1, 0, 0, 0, 96, 101, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 98, 100, 3, + 12, 6, 0, 99, 98, 1, 0, 0, 0, 100, 103, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, + 101, 102, 1, 0, 0, 0, 102, 104, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 104, 105, + 3, 32, 16, 0, 105, 3, 1, 0, 0, 0, 106, 107, 5, 45, 0, 0, 107, 5, 1, 0, 0, 0, + 108, 109, 7, 0, 0, 0, 109, 110, 3, 8, 4, 0, 110, 111, 5, 26, 0, 0, 111, 7, + 1, 0, 0, 0, 112, 113, 3, 22, 11, 0, 113, 118, 3, 10, 5, 0, 114, 115, 5, 25, + 0, 0, 115, 117, 3, 10, 5, 0, 116, 114, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, + 118, 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 9, 1, 0, 0, 0, 120, 118, 1, + 0, 0, 0, 121, 122, 5, 45, 0, 0, 122, 11, 1, 0, 0, 0, 123, 124, 3, 14, 7, 0, + 124, 125, 3, 16, 8, 0, 125, 13, 1, 0, 0, 0, 126, 127, 7, 1, 0, 0, 127, 15, + 1, 0, 0, 0, 128, 129, 3, 20, 10, 0, 129, 130, 3, 18, 9, 0, 130, 131, 5, 20, + 0, 0, 131, 132, 3, 24, 12, 0, 132, 133, 5, 21, 0, 0, 133, 134, 3, 30, 15, 0, + 134, 17, 1, 0, 0, 0, 135, 136, 5, 45, 0, 0, 136, 19, 1, 0, 0, 0, 137, 140, + 3, 22, 11, 0, 138, 140, 5, 11, 0, 0, 139, 137, 1, 0, 0, 0, 139, 138, 1, 0, + 0, 0, 140, 21, 1, 0, 0, 0, 141, 142, 7, 2, 0, 0, 142, 23, 1, 0, 0, 0, 143, + 148, 3, 26, 13, 0, 144, 145, 5, 25, 0, 0, 145, 147, 3, 26, 13, 0, 146, 144, + 1, 0, 0, 0, 147, 150, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 148, 149, 1, 0, 0, + 0, 149, 152, 1, 0, 0, 0, 150, 148, 1, 0, 0, 0, 151, 143, 1, 0, 0, 0, 151, + 152, 1, 0, 0, 0, 152, 25, 1, 0, 0, 0, 153, 154, 3, 22, 11, 0, 154, 155, 3, + 28, 14, 0, 155, 27, 1, 0, 0, 0, 156, 157, 5, 45, 0, 0, 157, 29, 1, 0, 0, 0, + 158, 162, 5, 18, 0, 0, 159, 161, 3, 34, 17, 0, 160, 159, 1, 0, 0, 0, 161, + 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 165, 1, 0, + 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 3, 40, 20, 0, 166, 167, 3, 32, 16, 0, + 167, 31, 1, 0, 0, 0, 168, 169, 5, 19, 0, 0, 169, 33, 1, 0, 0, 0, 170, 171, + 5, 7, 0, 0, 171, 172, 3, 22, 11, 0, 172, 177, 3, 36, 18, 0, 173, 174, 5, 25, + 0, 0, 174, 176, 3, 36, 18, 0, 175, 173, 1, 0, 0, 0, 176, 179, 1, 0, 0, 0, + 177, 175, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 180, 1, 0, 0, 0, 179, 177, + 1, 0, 0, 0, 180, 181, 5, 26, 0, 0, 181, 35, 1, 0, 0, 0, 182, 183, 5, 45, 0, + 0, 183, 37, 1, 0, 0, 0, 184, 185, 5, 45, 0, 0, 185, 39, 1, 0, 0, 0, 186, + 188, 3, 42, 21, 0, 187, 186, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, + 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 41, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, + 192, 198, 3, 44, 22, 0, 193, 198, 3, 48, 24, 0, 194, 198, 3, 56, 28, 0, 195, + 198, 3, 60, 30, 0, 196, 198, 3, 66, 33, 0, 197, 192, 1, 0, 0, 0, 197, 193, + 1, 0, 0, 0, 197, 194, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 197, 196, 1, 0, 0, + 0, 198, 43, 1, 0, 0, 0, 199, 202, 5, 12, 0, 0, 200, 203, 3, 38, 19, 0, 201, + 203, 3, 76, 38, 0, 202, 200, 1, 0, 0, 0, 202, 201, 1, 0, 0, 0, 203, 204, 1, + 0, 0, 0, 204, 205, 3, 46, 23, 0, 205, 206, 3, 70, 35, 0, 206, 207, 5, 26, 0, + 0, 207, 45, 1, 0, 0, 0, 208, 209, 5, 27, 0, 0, 209, 47, 1, 0, 0, 0, 210, + 212, 3, 50, 25, 0, 211, 213, 3, 54, 27, 0, 212, 211, 1, 0, 0, 0, 212, 213, + 1, 0, 0, 0, 213, 49, 1, 0, 0, 0, 214, 215, 5, 14, 0, 0, 215, 216, 5, 20, 0, + 0, 216, 217, 3, 52, 26, 0, 217, 218, 5, 21, 0, 0, 218, 219, 5, 18, 0, 0, + 219, 220, 3, 40, 20, 0, 220, 221, 3, 32, 16, 0, 221, 51, 1, 0, 0, 0, 222, + 223, 3, 70, 35, 0, 223, 53, 1, 0, 0, 0, 224, 225, 5, 15, 0, 0, 225, 226, 5, + 18, 0, 0, 226, 227, 3, 40, 20, 0, 227, 228, 3, 32, 16, 0, 228, 55, 1, 0, 0, + 0, 229, 230, 5, 16, 0, 0, 230, 231, 5, 20, 0, 0, 231, 232, 3, 58, 29, 0, + 232, 233, 5, 21, 0, 0, 233, 234, 5, 18, 0, 0, 234, 235, 3, 40, 20, 0, 235, + 236, 3, 32, 16, 0, 236, 57, 1, 0, 0, 0, 237, 238, 3, 70, 35, 0, 238, 59, 1, + 0, 0, 0, 239, 240, 5, 13, 0, 0, 240, 241, 3, 62, 31, 0, 241, 242, 5, 26, 0, + 0, 242, 61, 1, 0, 0, 0, 243, 244, 3, 64, 32, 0, 244, 245, 5, 20, 0, 0, 245, + 246, 3, 68, 34, 0, 246, 247, 5, 21, 0, 0, 247, 63, 1, 0, 0, 0, 248, 251, 3, + 4, 2, 0, 249, 251, 5, 44, 0, 0, 250, 248, 1, 0, 0, 0, 250, 249, 1, 0, 0, 0, + 251, 252, 1, 0, 0, 0, 252, 254, 5, 24, 0, 0, 253, 250, 1, 0, 0, 0, 253, 254, + 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 256, 3, 18, 9, 0, 256, 65, 1, 0, 0, + 0, 257, 259, 5, 17, 0, 0, 258, 260, 3, 70, 35, 0, 259, 258, 1, 0, 0, 0, 259, + 260, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 262, 5, 26, 0, 0, 262, 67, 1, 0, + 0, 0, 263, 268, 3, 70, 35, 0, 264, 265, 5, 25, 0, 0, 265, 267, 3, 70, 35, 0, + 266, 264, 1, 0, 0, 0, 267, 270, 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 268, 269, + 1, 0, 0, 0, 269, 272, 1, 0, 0, 0, 270, 268, 1, 0, 0, 0, 271, 263, 1, 0, 0, + 0, 271, 272, 1, 0, 0, 0, 272, 69, 1, 0, 0, 0, 273, 274, 6, 35, -1, 0, 274, + 281, 3, 78, 39, 0, 275, 281, 3, 38, 19, 0, 276, 281, 3, 62, 31, 0, 277, 281, + 3, 76, 38, 0, 278, 281, 3, 74, 37, 0, 279, 281, 3, 72, 36, 0, 280, 273, 1, + 0, 0, 0, 280, 275, 1, 0, 0, 0, 280, 276, 1, 0, 0, 0, 280, 277, 1, 0, 0, 0, + 280, 278, 1, 0, 0, 0, 280, 279, 1, 0, 0, 0, 281, 288, 1, 0, 0, 0, 282, 283, + 10, 2, 0, 0, 283, 284, 3, 84, 42, 0, 284, 285, 3, 70, 35, 3, 285, 287, 1, 0, + 0, 0, 286, 282, 1, 0, 0, 0, 287, 290, 1, 0, 0, 0, 288, 286, 1, 0, 0, 0, 288, + 289, 1, 0, 0, 0, 289, 71, 1, 0, 0, 0, 290, 288, 1, 0, 0, 0, 291, 292, 5, 20, + 0, 0, 292, 293, 3, 70, 35, 0, 293, 294, 5, 21, 0, 0, 294, 73, 1, 0, 0, 0, + 295, 296, 3, 82, 41, 0, 296, 297, 3, 70, 35, 0, 297, 75, 1, 0, 0, 0, 298, + 299, 3, 38, 19, 0, 299, 300, 5, 22, 0, 0, 300, 301, 3, 70, 35, 0, 301, 302, + 5, 23, 0, 0, 302, 77, 1, 0, 0, 0, 303, 309, 5, 40, 0, 0, 304, 309, 5, 46, 0, + 0, 305, 309, 3, 80, 40, 0, 306, 309, 5, 43, 0, 0, 307, 309, 5, 44, 0, 0, + 308, 303, 1, 0, 0, 0, 308, 304, 1, 0, 0, 0, 308, 305, 1, 0, 0, 0, 308, 306, + 1, 0, 0, 0, 308, 307, 1, 0, 0, 0, 309, 79, 1, 0, 0, 0, 310, 311, 7, 3, 0, 0, + 311, 81, 1, 0, 0, 0, 312, 313, 7, 4, 0, 0, 313, 83, 1, 0, 0, 0, 314, 315, 7, + 5, 0, 0, 315, 85, 1, 0, 0, 0, 20, 95, 101, 118, 139, 148, 151, 162, 177, + 189, 197, 202, 212, 250, 253, 259, 268, 271, 280, 288, 308, + ]; + + private static __ATN: ATN; + public static get _ATN(): ATN { + if (!JackParser.__ATN) { + JackParser.__ATN = new ATNDeserializer().deserialize( + JackParser._serializedATN, + ); + } + + return JackParser.__ATN; + } + + static DecisionsToDFA = JackParser._ATN.decisionToState.map( + (ds: DecisionState, index: number) => new DFA(ds, index), + ); +} + +export class ProgramContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public classDeclaration(): ClassDeclarationContext { + return this.getTypedRuleContext( + ClassDeclarationContext, + 0, + ) as ClassDeclarationContext; + } + public EOF(): TerminalNode { + return this.getToken(JackParser.EOF, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_program; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterProgram) { + listener.enterProgram(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitProgram) { + listener.exitProgram(this); + } + } +} + +export class ClassDeclarationContext extends ParserRuleContext { + public localSymbolTable: LocalSymbolTable | undefined; + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public CLASS(): TerminalNode { + return this.getToken(JackParser.CLASS, 0); + } + public className(): ClassNameContext { + return this.getTypedRuleContext(ClassNameContext, 0) as ClassNameContext; + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public classVarDec_list(): ClassVarDecContext[] { + return this.getTypedRuleContexts( + ClassVarDecContext, + ) as ClassVarDecContext[]; + } + public classVarDec(i: number): ClassVarDecContext { + return this.getTypedRuleContext( + ClassVarDecContext, + i, + ) as ClassVarDecContext; + } + public subroutineDeclaration_list(): SubroutineDeclarationContext[] { + return this.getTypedRuleContexts( + SubroutineDeclarationContext, + ) as SubroutineDeclarationContext[]; + } + public subroutineDeclaration(i: number): SubroutineDeclarationContext { + return this.getTypedRuleContext( + SubroutineDeclarationContext, + i, + ) as SubroutineDeclarationContext; + } + public get ruleIndex(): number { + return JackParser.RULE_classDeclaration; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterClassDeclaration) { + listener.enterClassDeclaration(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitClassDeclaration) { + listener.exitClassDeclaration(this); + } + } +} + +export class ClassNameContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_className; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterClassName) { + listener.enterClassName(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitClassName) { + listener.exitClassName(this); + } + } +} + +export class ClassVarDecContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public fieldList(): FieldListContext { + return this.getTypedRuleContext(FieldListContext, 0) as FieldListContext; + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public STATIC(): TerminalNode { + return this.getToken(JackParser.STATIC, 0); + } + public FIELD(): TerminalNode { + return this.getToken(JackParser.FIELD, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_classVarDec; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterClassVarDec) { + listener.enterClassVarDec(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitClassVarDec) { + listener.exitClassVarDec(this); + } + } +} + +export class FieldListContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public varType(): VarTypeContext { + return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; + } + public fieldName_list(): FieldNameContext[] { + return this.getTypedRuleContexts(FieldNameContext) as FieldNameContext[]; + } + public fieldName(i: number): FieldNameContext { + return this.getTypedRuleContext(FieldNameContext, i) as FieldNameContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(JackParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(JackParser.COMMA, i); + } + public get ruleIndex(): number { + return JackParser.RULE_fieldList; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterFieldList) { + listener.enterFieldList(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitFieldList) { + listener.exitFieldList(this); + } + } +} + +export class FieldNameContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_fieldName; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterFieldName) { + listener.enterFieldName(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitFieldName) { + listener.exitFieldName(this); + } + } +} + +export class SubroutineDeclarationContext extends ParserRuleContext { + public symbols: SubroutineScope | undefined; + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public subroutineType(): SubroutineTypeContext { + return this.getTypedRuleContext( + SubroutineTypeContext, + 0, + ) as SubroutineTypeContext; + } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + return this.getTypedRuleContext( + SubroutineDecWithoutTypeContext, + 0, + ) as SubroutineDecWithoutTypeContext; + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineDeclaration; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineDeclaration) { + listener.enterSubroutineDeclaration(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineDeclaration) { + listener.exitSubroutineDeclaration(this); + } + } +} + +export class SubroutineTypeContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public CONSTRUCTOR(): TerminalNode { + return this.getToken(JackParser.CONSTRUCTOR, 0); + } + public METHOD(): TerminalNode { + return this.getToken(JackParser.METHOD, 0); + } + public FUNCTION(): TerminalNode { + return this.getToken(JackParser.FUNCTION, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineType; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineType) { + listener.enterSubroutineType(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineType) { + listener.exitSubroutineType(this); + } + } +} + +export class SubroutineDecWithoutTypeContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public subroutineReturnType(): SubroutineReturnTypeContext { + return this.getTypedRuleContext( + SubroutineReturnTypeContext, + 0, + ) as SubroutineReturnTypeContext; + } + public subroutineName(): SubroutineNameContext { + return this.getTypedRuleContext( + SubroutineNameContext, + 0, + ) as SubroutineNameContext; + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public parameterList(): ParameterListContext { + return this.getTypedRuleContext( + ParameterListContext, + 0, + ) as ParameterListContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public subroutineBody(): SubroutineBodyContext { + return this.getTypedRuleContext( + SubroutineBodyContext, + 0, + ) as SubroutineBodyContext; + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineDecWithoutType; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineDecWithoutType) { + listener.enterSubroutineDecWithoutType(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineDecWithoutType) { + listener.exitSubroutineDecWithoutType(this); + } + } +} + +export class SubroutineNameContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineName; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineName) { + listener.enterSubroutineName(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineName) { + listener.exitSubroutineName(this); + } + } +} + +export class SubroutineReturnTypeContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public varType(): VarTypeContext { + return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; + } + public VOID(): TerminalNode { + return this.getToken(JackParser.VOID, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineReturnType; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineReturnType) { + listener.enterSubroutineReturnType(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineReturnType) { + listener.exitSubroutineReturnType(this); + } + } +} + +export class VarTypeContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public INT(): TerminalNode { + return this.getToken(JackParser.INT, 0); + } + public CHAR(): TerminalNode { + return this.getToken(JackParser.CHAR, 0); + } + public BOOLEAN(): TerminalNode { + return this.getToken(JackParser.BOOLEAN, 0); + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_varType; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterVarType) { + listener.enterVarType(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitVarType) { + listener.exitVarType(this); + } + } +} + +export class ParameterListContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public parameter_list(): ParameterContext[] { + return this.getTypedRuleContexts(ParameterContext) as ParameterContext[]; + } + public parameter(i: number): ParameterContext { + return this.getTypedRuleContext(ParameterContext, i) as ParameterContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(JackParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(JackParser.COMMA, i); + } + public get ruleIndex(): number { + return JackParser.RULE_parameterList; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterParameterList) { + listener.enterParameterList(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitParameterList) { + listener.exitParameterList(this); + } + } +} + +export class ParameterContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public varType(): VarTypeContext { + return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; + } + public parameterName(): ParameterNameContext { + return this.getTypedRuleContext( + ParameterNameContext, + 0, + ) as ParameterNameContext; + } + public get ruleIndex(): number { + return JackParser.RULE_parameter; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterParameter) { + listener.enterParameter(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitParameter) { + listener.exitParameter(this); + } + } +} + +export class ParameterNameContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_parameterName; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterParameterName) { + listener.enterParameterName(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitParameterName) { + listener.exitParameterName(this); + } + } +} + +export class SubroutineBodyContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public statements(): StatementsContext { + return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public varDeclaration_list(): VarDeclarationContext[] { + return this.getTypedRuleContexts( + VarDeclarationContext, + ) as VarDeclarationContext[]; + } + public varDeclaration(i: number): VarDeclarationContext { + return this.getTypedRuleContext( + VarDeclarationContext, + i, + ) as VarDeclarationContext; + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineBody; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineBody) { + listener.enterSubroutineBody(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineBody) { + listener.exitSubroutineBody(this); + } + } +} + +export class RBraceContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public RBRACE(): TerminalNode { + return this.getToken(JackParser.RBRACE, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_rBrace; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterRBrace) { + listener.enterRBrace(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitRBrace) { + listener.exitRBrace(this); + } + } +} + +export class VarDeclarationContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public VAR(): TerminalNode { + return this.getToken(JackParser.VAR, 0); + } + public varType(): VarTypeContext { + return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; + } + public varNameInDeclaration_list(): VarNameInDeclarationContext[] { + return this.getTypedRuleContexts( + VarNameInDeclarationContext, + ) as VarNameInDeclarationContext[]; + } + public varNameInDeclaration(i: number): VarNameInDeclarationContext { + return this.getTypedRuleContext( + VarNameInDeclarationContext, + i, + ) as VarNameInDeclarationContext; + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(JackParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(JackParser.COMMA, i); + } + public get ruleIndex(): number { + return JackParser.RULE_varDeclaration; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterVarDeclaration) { + listener.enterVarDeclaration(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitVarDeclaration) { + listener.exitVarDeclaration(this); + } + } +} + +export class VarNameInDeclarationContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_varNameInDeclaration; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterVarNameInDeclaration) { + listener.enterVarNameInDeclaration(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitVarNameInDeclaration) { + listener.exitVarNameInDeclaration(this); + } + } +} + +export class VarNameContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_varName; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterVarName) { + listener.enterVarName(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitVarName) { + listener.exitVarName(this); + } + } +} + +export class StatementsContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public statement_list(): StatementContext[] { + return this.getTypedRuleContexts(StatementContext) as StatementContext[]; + } + public statement(i: number): StatementContext { + return this.getTypedRuleContext(StatementContext, i) as StatementContext; + } + public get ruleIndex(): number { + return JackParser.RULE_statements; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterStatements) { + listener.enterStatements(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitStatements) { + listener.exitStatements(this); + } + } +} + +export class StatementContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public letStatement(): LetStatementContext { + return this.getTypedRuleContext( + LetStatementContext, + 0, + ) as LetStatementContext; + } + public ifElseStatement(): IfElseStatementContext { + return this.getTypedRuleContext( + IfElseStatementContext, + 0, + ) as IfElseStatementContext; + } + public whileStatement(): WhileStatementContext { + return this.getTypedRuleContext( + WhileStatementContext, + 0, + ) as WhileStatementContext; + } + public doStatement(): DoStatementContext { + return this.getTypedRuleContext( + DoStatementContext, + 0, + ) as DoStatementContext; + } + public returnStatement(): ReturnStatementContext { + return this.getTypedRuleContext( + ReturnStatementContext, + 0, + ) as ReturnStatementContext; + } + public get ruleIndex(): number { + return JackParser.RULE_statement; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterStatement) { + listener.enterStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitStatement) { + listener.exitStatement(this); + } + } +} + +export class LetStatementContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public LET(): TerminalNode { + return this.getToken(JackParser.LET, 0); + } + public equals(): EqualsContext { + return this.getTypedRuleContext(EqualsContext, 0) as EqualsContext; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public varName(): VarNameContext { + return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; + } + public arrayAccess(): ArrayAccessContext { + return this.getTypedRuleContext( + ArrayAccessContext, + 0, + ) as ArrayAccessContext; + } + public get ruleIndex(): number { + return JackParser.RULE_letStatement; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterLetStatement) { + listener.enterLetStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitLetStatement) { + listener.exitLetStatement(this); + } + } +} + +export class EqualsContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public EQUALS(): TerminalNode { + return this.getToken(JackParser.EQUALS, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_equals; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterEquals) { + listener.enterEquals(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitEquals) { + listener.exitEquals(this); + } + } +} + +export class IfElseStatementContext extends ParserRuleContext { + public endLabel = ""; + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public ifStatement(): IfStatementContext { + return this.getTypedRuleContext( + IfStatementContext, + 0, + ) as IfStatementContext; + } + public elseStatement(): ElseStatementContext { + return this.getTypedRuleContext( + ElseStatementContext, + 0, + ) as ElseStatementContext; + } + public get ruleIndex(): number { + return JackParser.RULE_ifElseStatement; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterIfElseStatement) { + listener.enterIfElseStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitIfElseStatement) { + listener.exitIfElseStatement(this); + } + } +} + +export class IfStatementContext extends ParserRuleContext { + public endLabel = ""; + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public IF(): TerminalNode { + return this.getToken(JackParser.IF, 0); + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public ifExpression(): IfExpressionContext { + return this.getTypedRuleContext( + IfExpressionContext, + 0, + ) as IfExpressionContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public statements(): StatementsContext { + return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public get ruleIndex(): number { + return JackParser.RULE_ifStatement; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterIfStatement) { + listener.enterIfStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitIfStatement) { + listener.exitIfStatement(this); + } + } +} + +export class IfExpressionContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return JackParser.RULE_ifExpression; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterIfExpression) { + listener.enterIfExpression(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitIfExpression) { + listener.exitIfExpression(this); + } + } +} + +export class ElseStatementContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public ELSE(): TerminalNode { + return this.getToken(JackParser.ELSE, 0); + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public statements(): StatementsContext { + return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public get ruleIndex(): number { + return JackParser.RULE_elseStatement; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterElseStatement) { + listener.enterElseStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitElseStatement) { + listener.exitElseStatement(this); + } + } +} + +export class WhileStatementContext extends ParserRuleContext { + public startLabel = ""; + endLabel = ""; + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public WHILE(): TerminalNode { + return this.getToken(JackParser.WHILE, 0); + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public whileExpression(): WhileExpressionContext { + return this.getTypedRuleContext( + WhileExpressionContext, + 0, + ) as WhileExpressionContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public statements(): StatementsContext { + return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public get ruleIndex(): number { + return JackParser.RULE_whileStatement; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterWhileStatement) { + listener.enterWhileStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitWhileStatement) { + listener.exitWhileStatement(this); + } + } +} + +export class WhileExpressionContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return JackParser.RULE_whileExpression; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterWhileExpression) { + listener.enterWhileExpression(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitWhileExpression) { + listener.exitWhileExpression(this); + } + } +} + +export class DoStatementContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public DO(): TerminalNode { + return this.getToken(JackParser.DO, 0); + } + public subroutineCall(): SubroutineCallContext { + return this.getTypedRuleContext( + SubroutineCallContext, + 0, + ) as SubroutineCallContext; + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_doStatement; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterDoStatement) { + listener.enterDoStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitDoStatement) { + listener.exitDoStatement(this); + } + } +} + +export class SubroutineCallContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public subroutineId(): SubroutineIdContext { + return this.getTypedRuleContext( + SubroutineIdContext, + 0, + ) as SubroutineIdContext; + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public expressionList(): ExpressionListContext { + return this.getTypedRuleContext( + ExpressionListContext, + 0, + ) as ExpressionListContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineCall; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineCall) { + listener.enterSubroutineCall(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineCall) { + listener.exitSubroutineCall(this); + } + } +} + +export class SubroutineIdContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public subroutineName(): SubroutineNameContext { + return this.getTypedRuleContext( + SubroutineNameContext, + 0, + ) as SubroutineNameContext; + } + public DOT(): TerminalNode { + return this.getToken(JackParser.DOT, 0); + } + public className(): ClassNameContext { + return this.getTypedRuleContext(ClassNameContext, 0) as ClassNameContext; + } + public THIS_LITERAL(): TerminalNode { + return this.getToken(JackParser.THIS_LITERAL, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineId; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineId) { + listener.enterSubroutineId(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineId) { + listener.exitSubroutineId(this); + } + } +} + +export class ReturnStatementContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public RETURN(): TerminalNode { + return this.getToken(JackParser.RETURN, 0); + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return JackParser.RULE_returnStatement; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterReturnStatement) { + listener.enterReturnStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitReturnStatement) { + listener.exitReturnStatement(this); + } + } +} + +export class ExpressionListContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public expression_list(): ExpressionContext[] { + return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; + } + public expression(i: number): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(JackParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(JackParser.COMMA, i); + } + public get ruleIndex(): number { + return JackParser.RULE_expressionList; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterExpressionList) { + listener.enterExpressionList(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitExpressionList) { + listener.exitExpressionList(this); + } + } +} + +export class ExpressionContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public constant(): ConstantContext { + return this.getTypedRuleContext(ConstantContext, 0) as ConstantContext; + } + public varName(): VarNameContext { + return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; + } + public subroutineCall(): SubroutineCallContext { + return this.getTypedRuleContext( + SubroutineCallContext, + 0, + ) as SubroutineCallContext; + } + public arrayAccess(): ArrayAccessContext { + return this.getTypedRuleContext( + ArrayAccessContext, + 0, + ) as ArrayAccessContext; + } + public unaryOperation(): UnaryOperationContext { + return this.getTypedRuleContext( + UnaryOperationContext, + 0, + ) as UnaryOperationContext; + } + public groupedExpression(): GroupedExpressionContext { + return this.getTypedRuleContext( + GroupedExpressionContext, + 0, + ) as GroupedExpressionContext; + } + public expression_list(): ExpressionContext[] { + return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; + } + public expression(i: number): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; + } + public binaryOperator(): BinaryOperatorContext { + return this.getTypedRuleContext( + BinaryOperatorContext, + 0, + ) as BinaryOperatorContext; + } + public get ruleIndex(): number { + return JackParser.RULE_expression; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterExpression) { + listener.enterExpression(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitExpression) { + listener.exitExpression(this); + } + } +} + +export class GroupedExpressionContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_groupedExpression; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterGroupedExpression) { + listener.enterGroupedExpression(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitGroupedExpression) { + listener.exitGroupedExpression(this); + } + } +} + +export class UnaryOperationContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public unaryOperator(): UnaryOperatorContext { + return this.getTypedRuleContext( + UnaryOperatorContext, + 0, + ) as UnaryOperatorContext; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return JackParser.RULE_unaryOperation; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterUnaryOperation) { + listener.enterUnaryOperation(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitUnaryOperation) { + listener.exitUnaryOperation(this); + } + } +} + +export class ArrayAccessContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public varName(): VarNameContext { + return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; + } + public LBRACKET(): TerminalNode { + return this.getToken(JackParser.LBRACKET, 0); + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public RBRACKET(): TerminalNode { + return this.getToken(JackParser.RBRACKET, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_arrayAccess; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterArrayAccess) { + listener.enterArrayAccess(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitArrayAccess) { + listener.exitArrayAccess(this); + } + } +} + +export class ConstantContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public INTEGER_LITERAL(): TerminalNode { + return this.getToken(JackParser.INTEGER_LITERAL, 0); + } + public STRING_LITERAL(): TerminalNode { + return this.getToken(JackParser.STRING_LITERAL, 0); + } + public booleanLiteral(): BooleanLiteralContext { + return this.getTypedRuleContext( + BooleanLiteralContext, + 0, + ) as BooleanLiteralContext; + } + public NULL_LITERAL(): TerminalNode { + return this.getToken(JackParser.NULL_LITERAL, 0); + } + public THIS_LITERAL(): TerminalNode { + return this.getToken(JackParser.THIS_LITERAL, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_constant; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterConstant) { + listener.enterConstant(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitConstant) { + listener.exitConstant(this); + } + } +} + +export class BooleanLiteralContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public TRUE(): TerminalNode { + return this.getToken(JackParser.TRUE, 0); + } + public FALSE(): TerminalNode { + return this.getToken(JackParser.FALSE, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_booleanLiteral; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterBooleanLiteral) { + listener.enterBooleanLiteral(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitBooleanLiteral) { + listener.exitBooleanLiteral(this); + } + } +} + +export class UnaryOperatorContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public TILDE(): TerminalNode { + return this.getToken(JackParser.TILDE, 0); + } + public MINUS(): TerminalNode { + return this.getToken(JackParser.MINUS, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_unaryOperator; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterUnaryOperator) { + listener.enterUnaryOperator(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitUnaryOperator) { + listener.exitUnaryOperator(this); + } + } +} + +export class BinaryOperatorContext extends ParserRuleContext { + constructor( + parser?: JackParser, + parent?: ParserRuleContext, + invokingState?: number, + ) { + super(parent, invokingState); + this.parser = parser; + } + public PLUS(): TerminalNode { + return this.getToken(JackParser.PLUS, 0); + } + public MINUS(): TerminalNode { + return this.getToken(JackParser.MINUS, 0); + } + public MUL(): TerminalNode { + return this.getToken(JackParser.MUL, 0); + } + public DIV(): TerminalNode { + return this.getToken(JackParser.DIV, 0); + } + public AND(): TerminalNode { + return this.getToken(JackParser.AND, 0); + } + public OR(): TerminalNode { + return this.getToken(JackParser.OR, 0); + } + public LESS_THAN(): TerminalNode { + return this.getToken(JackParser.LESS_THAN, 0); + } + public GREATER_THAN(): TerminalNode { + return this.getToken(JackParser.GREATER_THAN, 0); + } + public EQUALS(): TerminalNode { + return this.getToken(JackParser.EQUALS, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_binaryOperator; + } + public enterRule(listener: JackParserListener): void { + if (listener.enterBinaryOperator) { + listener.enterBinaryOperator(this); + } + } + public exitRule(listener: JackParserListener): void { + if (listener.exitBinaryOperator) { + listener.exitBinaryOperator(this); + } + } +} diff --git a/simulator/src/jack/generated/JackParserListener.ts b/simulator/src/jack/generated/JackParserListener.ts new file mode 100644 index 00000000..67718c1e --- /dev/null +++ b/simulator/src/jack/generated/JackParserListener.ts @@ -0,0 +1,486 @@ +// Generated from JackParser.g4 by ANTLR 4.13.2 + +import { ParseTreeListener } from "antlr4"; + +import { ProgramContext } from "./JackParser.js"; +import { ClassDeclarationContext } from "./JackParser.js"; +import { ClassNameContext } from "./JackParser.js"; +import { ClassVarDecContext } from "./JackParser.js"; +import { FieldListContext } from "./JackParser.js"; +import { FieldNameContext } from "./JackParser.js"; +import { SubroutineDeclarationContext } from "./JackParser.js"; +import { SubroutineTypeContext } from "./JackParser.js"; +import { SubroutineDecWithoutTypeContext } from "./JackParser.js"; +import { SubroutineNameContext } from "./JackParser.js"; +import { SubroutineReturnTypeContext } from "./JackParser.js"; +import { VarTypeContext } from "./JackParser.js"; +import { ParameterListContext } from "./JackParser.js"; +import { ParameterContext } from "./JackParser.js"; +import { ParameterNameContext } from "./JackParser.js"; +import { SubroutineBodyContext } from "./JackParser.js"; +import { RBraceContext } from "./JackParser.js"; +import { VarDeclarationContext } from "./JackParser.js"; +import { VarNameInDeclarationContext } from "./JackParser.js"; +import { VarNameContext } from "./JackParser.js"; +import { StatementsContext } from "./JackParser.js"; +import { StatementContext } from "./JackParser.js"; +import { LetStatementContext } from "./JackParser.js"; +import { EqualsContext } from "./JackParser.js"; +import { IfElseStatementContext } from "./JackParser.js"; +import { IfStatementContext } from "./JackParser.js"; +import { IfExpressionContext } from "./JackParser.js"; +import { ElseStatementContext } from "./JackParser.js"; +import { WhileStatementContext } from "./JackParser.js"; +import { WhileExpressionContext } from "./JackParser.js"; +import { DoStatementContext } from "./JackParser.js"; +import { SubroutineCallContext } from "./JackParser.js"; +import { SubroutineIdContext } from "./JackParser.js"; +import { ReturnStatementContext } from "./JackParser.js"; +import { ExpressionListContext } from "./JackParser.js"; +import { ExpressionContext } from "./JackParser.js"; +import { GroupedExpressionContext } from "./JackParser.js"; +import { UnaryOperationContext } from "./JackParser.js"; +import { ArrayAccessContext } from "./JackParser.js"; +import { ConstantContext } from "./JackParser.js"; +import { BooleanLiteralContext } from "./JackParser.js"; +import { UnaryOperatorContext } from "./JackParser.js"; +import { BinaryOperatorContext } from "./JackParser.js"; + +/** + * This interface defines a complete listener for a parse tree produced by + * `JackParser`. + */ +export default class JackParserListener extends ParseTreeListener { + /** + * Enter a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + enterProgram?: (ctx: ProgramContext) => void; + /** + * Exit a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + exitProgram?: (ctx: ProgramContext) => void; + /** + * Enter a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + enterClassName?: (ctx: ClassNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + exitClassName?: (ctx: ClassNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + enterClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Exit a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + exitClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Enter a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + enterFieldList?: (ctx: FieldListContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + exitFieldList?: (ctx: FieldListContext) => void; + /** + * Enter a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + enterFieldName?: (ctx: FieldNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + exitFieldName?: (ctx: FieldNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineDeclaration`. + * @param ctx the parse tree + */ + enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDeclaration`. + * @param ctx the parse tree + */ + exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + enterSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + exitSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + enterSubroutineDecWithoutType?: ( + ctx: SubroutineDecWithoutTypeContext, + ) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + enterSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + exitSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + enterVarType?: (ctx: VarTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + exitVarType?: (ctx: VarTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + enterParameterList?: (ctx: ParameterListContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + exitParameterList?: (ctx: ParameterListContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + enterParameter?: (ctx: ParameterContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + exitParameter?: (ctx: ParameterContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + enterParameterName?: (ctx: ParameterNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + exitParameterName?: (ctx: ParameterNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Enter a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + enterRBrace?: (ctx: RBraceContext) => void; + /** + * Exit a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + exitRBrace?: (ctx: RBraceContext) => void; + /** + * Enter a parse tree produced by `JackParser.varDeclaration`. + * @param ctx the parse tree + */ + enterVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varDeclaration`. + * @param ctx the parse tree + */ + exitVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + enterVarName?: (ctx: VarNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + exitVarName?: (ctx: VarNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + enterStatements?: (ctx: StatementsContext) => void; + /** + * Exit a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + exitStatements?: (ctx: StatementsContext) => void; + /** + * Enter a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + enterStatement?: (ctx: StatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + exitStatement?: (ctx: StatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + enterLetStatement?: (ctx: LetStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + exitLetStatement?: (ctx: LetStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.equals`. + * @param ctx the parse tree + */ + enterEquals?: (ctx: EqualsContext) => void; + /** + * Exit a parse tree produced by `JackParser.equals`. + * @param ctx the parse tree + */ + exitEquals?: (ctx: EqualsContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + enterIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + exitIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + enterIfStatement?: (ctx: IfStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + exitIfStatement?: (ctx: IfStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifExpression`. + * @param ctx the parse tree + */ + enterIfExpression?: (ctx: IfExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifExpression`. + * @param ctx the parse tree + */ + exitIfExpression?: (ctx: IfExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + enterElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + exitElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + enterWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + exitWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.whileExpression`. + * @param ctx the parse tree + */ + enterWhileExpression?: (ctx: WhileExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileExpression`. + * @param ctx the parse tree + */ + exitWhileExpression?: (ctx: WhileExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + enterDoStatement?: (ctx: DoStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + exitDoStatement?: (ctx: DoStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + enterSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + exitSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + enterSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + exitSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Enter a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + enterReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + exitReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + enterExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Exit a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + exitExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Enter a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + enterExpression?: (ctx: ExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + exitExpression?: (ctx: ExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.unaryOperation`. + * @param ctx the parse tree + */ + enterUnaryOperation?: (ctx: UnaryOperationContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperation`. + * @param ctx the parse tree + */ + exitUnaryOperation?: (ctx: UnaryOperationContext) => void; + /** + * Enter a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + enterArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Exit a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + exitArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Enter a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + enterConstant?: (ctx: ConstantContext) => void; + /** + * Exit a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + exitConstant?: (ctx: ConstantContext) => void; + /** + * Enter a parse tree produced by `JackParser.booleanLiteral`. + * @param ctx the parse tree + */ + enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Exit a parse tree produced by `JackParser.booleanLiteral`. + * @param ctx the parse tree + */ + exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Enter a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Enter a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; +} diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/binder.listener.test.ts new file mode 100644 index 00000000..09839d28 --- /dev/null +++ b/simulator/src/jack/listener/binder.listener.test.ts @@ -0,0 +1,138 @@ +import fs from "fs"; +import path from "path"; +import { DuplicatedSubroutineError } from "../error"; +import { BinderListener } from "./binder.listener"; +import { createSubroutineSymbol, SubroutineType } from "../symbol"; +import { + getTestResourcePath, + listenToTheTree, + parseJackFile, + parseJackText, +} from "../test.helper"; + +describe("Binder", () => { + const jestConsole = console; + + beforeEach(() => { + global.console = require("console"); + }); + + afterEach(() => { + global.console = jestConsole; + }); + + test("should fail on duplicated subroutine", () => { + const input = ` + class A { + function void f(){ + return; + } + function int f(){ + return 1; + } + }`; + const tree = parseJackText(input); + const globalSymbolsListener = new BinderListener(); + listenToTheTree(tree, globalSymbolsListener); + const symbolsErrors = globalSymbolsListener.errors; + expect(globalSymbolsListener.errors.length).toBe(1); + expect(symbolsErrors[0]).toBeInstanceOf(DuplicatedSubroutineError); + }); + + test("basic", () => { + const expected = { + //built in classes + Array: {}, + Keyboard: {}, + Math: {}, + Memory: {}, + Output: {}, + Screen: {}, + String: {}, + Sys: {}, + "Array.dispose": createSubroutineSymbol(0, SubroutineType.Function), + "Array.new": createSubroutineSymbol(1, SubroutineType.Function), + "Keyboard.init": createSubroutineSymbol(0, SubroutineType.Function), + "Keyboard.keyPressed": createSubroutineSymbol(0, SubroutineType.Function), + "Keyboard.readChar": createSubroutineSymbol(0, SubroutineType.Function), + "Keyboard.readInt": createSubroutineSymbol(1, SubroutineType.Function), + "Keyboard.readLine": createSubroutineSymbol(1, SubroutineType.Function), + "Math.abs": createSubroutineSymbol(1, SubroutineType.Function), + "Math.divide": createSubroutineSymbol(2, SubroutineType.Function), + "Math.max": createSubroutineSymbol(2, SubroutineType.Function), + "Math.min": createSubroutineSymbol(2, SubroutineType.Function), + "Math.multiply": createSubroutineSymbol(2, SubroutineType.Function), + "Math.sqrt": createSubroutineSymbol(1, SubroutineType.Function), + "Memory.alloc": createSubroutineSymbol(1, SubroutineType.Function), + "Memory.deAlloc": createSubroutineSymbol(1, SubroutineType.Function), + "Memory.peek": createSubroutineSymbol(1, SubroutineType.Function), + "Memory.poke": createSubroutineSymbol(2, SubroutineType.Function), + "Output.backSpace": createSubroutineSymbol(0, SubroutineType.Function), + "Output.moveCursor": createSubroutineSymbol(2, SubroutineType.Function), + "Output.printChar": createSubroutineSymbol(1, SubroutineType.Function), + "Output.printInt": createSubroutineSymbol(1, SubroutineType.Function), + "Output.println": createSubroutineSymbol(0, SubroutineType.Function), + "Output.printString": createSubroutineSymbol(1, SubroutineType.Function), + "Screen.clearScreen": createSubroutineSymbol(0, SubroutineType.Function), + "Screen.drawCircle": createSubroutineSymbol(3, SubroutineType.Function), + "Screen.drawLine": createSubroutineSymbol(4, SubroutineType.Function), + "Screen.drawPixel": createSubroutineSymbol(2, SubroutineType.Function), + "Screen.drawRectangle": createSubroutineSymbol( + 4, + SubroutineType.Function, + ), + "Screen.setColor": createSubroutineSymbol(1, SubroutineType.Function), + "String.appendChar": createSubroutineSymbol(1, SubroutineType.Function), + "String.backSpace": createSubroutineSymbol(0, SubroutineType.Function), + "String.charAt": createSubroutineSymbol(2, SubroutineType.Function), + "String.dispose": createSubroutineSymbol(0, SubroutineType.Function), + "String.doubleQuote": createSubroutineSymbol(0, SubroutineType.Function), + "String.eraseLastChar": createSubroutineSymbol( + 0, + SubroutineType.Function, + ), + "String.intValue": createSubroutineSymbol(0, SubroutineType.Function), + "String.length": createSubroutineSymbol(0, SubroutineType.Function), + "String.new": createSubroutineSymbol(1, SubroutineType.Function), + "String.newLine": createSubroutineSymbol(0, SubroutineType.Function), + "String.setCharAt": createSubroutineSymbol(1, SubroutineType.Function), + "String.setInt": createSubroutineSymbol(1, SubroutineType.Function), + "Sys.error": createSubroutineSymbol(1, SubroutineType.Function), + "Sys.halt": createSubroutineSymbol(0, SubroutineType.Function), + "Sys.wait": createSubroutineSymbol(1, SubroutineType.Function), + //test files symbols + Fraction: {}, + "Fraction.new": createSubroutineSymbol(2, SubroutineType.Constructor, 0), + "Fraction.reduce": createSubroutineSymbol(0, SubroutineType.Method, 1), + "Fraction.getNumerator": createSubroutineSymbol( + 0, + SubroutineType.Method, + 0, + ), + "Fraction.getDenominator": createSubroutineSymbol( + 0, + SubroutineType.Method, + 0, + ), + "Fraction.plus": createSubroutineSymbol(1, SubroutineType.Method, 1), + "Fraction.dispose": createSubroutineSymbol(0, SubroutineType.Method, 0), + "Fraction.print": createSubroutineSymbol(0, SubroutineType.Method, 0), + "Fraction.gcd": createSubroutineSymbol(2, SubroutineType.Function, 1), + Main: {}, + "Main.main": createSubroutineSymbol(0, SubroutineType.Function, 3), + }; + let globalSymbolsListener = new BinderListener(); + + const testFolder = getTestResourcePath("Fraction"); + const files = fs + .readdirSync(testFolder) + .filter((file) => file.endsWith(".jack")) + .map((file) => path.join(testFolder, file)); + for (const filePath of files) { + const tree = parseJackFile(filePath); + globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); + // console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) + } + expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); + }); +}); diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts new file mode 100644 index 00000000..38ac1513 --- /dev/null +++ b/simulator/src/jack/listener/binder.listener.ts @@ -0,0 +1,99 @@ +import { + ClassDeclarationContext, + SubroutineBodyContext, + SubroutineDeclarationContext, + VarNameInDeclarationContext, +} from "../generated/JackParser.js"; +import { DuplicatedSubroutineError } from "../error.js"; +import { builtInSymbols, builtInTypes } from "../builtins.js"; +import { + GenericSymbol, + GlobalSymbolTable, + SubroutineInfo, + SubroutineType, +} from "../symbol.js"; +import JackParserListener from "../generated/JackParserListener.js"; + +const primitives = new Set(builtInTypes); +export type Primitive = typeof primitives extends Set ? S : never; +/// +/** + * Creates global symbol table that contains built-in functions and found classes and subroutines + */ +export class BinderListener extends JackParserListener { + // key can be class or . + public globalSymbolTable: GlobalSymbolTable = structuredClone(builtInSymbols); + public className = ""; + public errors: DuplicatedSubroutineError[] = []; + private subRoutineInfo: SubroutineInfo = {} as SubroutineInfo; + private subroutineVarsCount = 0; + private stopProcessingSubroutines = false; + private subroutineId = ""; + + override enterClassDeclaration = (ctx: ClassDeclarationContext) => { + const className = ctx.className()!.IDENTIFIER().getText(); + if (this.globalSymbolTable[className] != undefined) { + this.errors.push( + new DuplicatedSubroutineError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + `Class "${className}" is already defined.`, + ), + ); + return; + } + this.globalSymbolTable[className] = {} as GenericSymbol; + this.className = className; + }; + + override enterSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { + let subroutineType: SubroutineType; + if (ctx.subroutineType().CONSTRUCTOR() != null) { + subroutineType = SubroutineType.Constructor; + } else if (ctx.subroutineType().METHOD() != null) { + subroutineType = SubroutineType.Method; + } else if (ctx.subroutineType().FUNCTION() != null) { + subroutineType = SubroutineType.Function; + } else { + throw new Error("Invalid subroutine type"); + } + const subroutineWithoutTypeCtx = ctx.subroutineDecWithoutType(); + const nameCtx = subroutineWithoutTypeCtx.subroutineName(); + const subroutineName = nameCtx.IDENTIFIER().getText(); + const id = this.className + "." + subroutineName; + if (this.globalSymbolTable[id] != undefined) { + this.errors.push( + new DuplicatedSubroutineError( + nameCtx.IDENTIFIER().symbol.line, + nameCtx.start.start, + nameCtx.start.stop, + subroutineName, + ), + ); + this.stopProcessingSubroutines = true; + } else { + this.subroutineId = id; + const paramsCount = subroutineWithoutTypeCtx + .parameterList() + .parameter_list().length; + this.subRoutineInfo = { + type: subroutineType, + paramsCount: paramsCount, + }; + this.subroutineVarsCount = 0; + this.stopProcessingSubroutines = false; + } + }; + override enterVarNameInDeclaration = (ctx: VarNameInDeclarationContext) => { + if (this.stopProcessingSubroutines) return; + this.subroutineVarsCount++; + }; + override exitSubroutineBody = (ctx: SubroutineBodyContext) => { + if (this.stopProcessingSubroutines) return; + this.subRoutineInfo.localVarsCount = this.subroutineVarsCount; + this.globalSymbolTable[this.subroutineId] = { + subroutineInfo: this.subRoutineInfo, + }; + }; +} diff --git a/simulator/src/jack/listener/common.ts b/simulator/src/jack/listener/common.ts new file mode 100644 index 00000000..dd472da6 --- /dev/null +++ b/simulator/src/jack/listener/common.ts @@ -0,0 +1,45 @@ +import { SubroutineIdContext } from "../generated/JackParser.js"; +import { LocalSymbolTable, VariableSymbol } from "../symbol.js"; + +export interface CallTypeResult { + callType: CallType; + subroutineIdText: string; + symbol?: VariableSymbol; +} + +export enum CallType { + VarMethod = 1, + LocalMethod = 2, + ClassFunctionOrConstructor = 3, +} +export function getCallType( + subroutineId: SubroutineIdContext, + className: string, + localSymbolTable: LocalSymbolTable, +): CallTypeResult { + if (subroutineId.DOT() == undefined) { + //local method + return { + callType: CallType.LocalMethod, + subroutineIdText: + className + "." + subroutineId.subroutineName().getText(), + } as CallTypeResult; + } else { + // var method + const [varName, methodName] = subroutineId.getText().split("."); + const symbol = localSymbolTable.lookup(varName); + if (symbol != undefined) { + return { + callType: CallType.VarMethod, + subroutineIdText: symbol.type + "." + methodName, + symbol: symbol, + } as CallTypeResult; + } else { + // class function/ctor + return { + callType: CallType.ClassFunctionOrConstructor, + subroutineIdText: subroutineId.getText(), + } as CallTypeResult; + } + } +} diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts new file mode 100644 index 00000000..b1b23bda --- /dev/null +++ b/simulator/src/jack/listener/error.listener.ts @@ -0,0 +1,34 @@ +import { ErrorListener, RecognitionException, Recognizer, Token } from "antlr4"; +import { JackCompilerError, LexerOrParserError } from "../error.js"; +export class CustomErrorListener extends ErrorListener { + public errors: JackCompilerError[] = []; + + /** + * Provides a default instance of {@link ConsoleErrorListener}. + */ + override syntaxError = ( + recognizer: Recognizer, + offendingSymbol: any, + line: number, + column: number, + msg: string, + e: RecognitionException | undefined, + ) => { + const t = offendingSymbol as Token; + const endIndex = column + t.text.length; + this.errors.push(new LexerOrParserError(line, column, endIndex, msg)); + }; + +} + +/** + * + We can add next methods (should be properties) to the error listener class to speed up parsing process. This is not part of Error listener ts class but exists in js implementation + reportAmbiguity(recognizer: any, dfa: any, startIndex: any, stopIndex: any, exact: any, ambigAlts: any, configs: any) { + console.log(`Ambiguity detected at ${this.filepath}:${startIndex}:${stopIndex}`); + } + + reportContextSensitivity(recognizer: any, dfa: any, startIndex: any, stopIndex: any, prediction: any, configs: any) { + console.log(`Context sensitivity detected at ${this.filepath}:${startIndex}:${stopIndex}`); + } + */ \ No newline at end of file diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts new file mode 100644 index 00000000..3876cfa8 --- /dev/null +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -0,0 +1,834 @@ +import { + ConstructorMushReturnThis, + DuplicatedVariableException as DuplicatedVariableError, + FieldCantBeReferencedInFunction, + FunctionCalledAsMethodError, + IncorrectConstructorReturnType, + IncorrectParamsNumberInSubroutineCallError, + IntLiteralIsOutOfRange as IntLiteralOverflow, + MethodCalledAsFunctionError, + NonVoidFunctionNoReturnError, + SubroutineNotAllPathsReturnError, + ThisCantBeReferencedInFunction, + UndeclaredVariableError, + UnknownClassError, + UnknownSubroutineCallError, + UnreachableCodeError, + VoidSubroutineReturnsValueError, + WrongLiteralTypeError, +} from "../error"; +import { CustomErrorListener } from "./error.listener"; +import { ValidatorListener } from "./validator.listener"; +import { + createSubroutineSymbol, + GenericSymbol, + SubroutineType, +} from "../symbol"; +import { + getTestResourcePath, + listenToTheTree, + parseJackFile, + parseJackText, + testResourceDirs, +} from "../test.helper"; +import fs from "fs"; +import { BinderListener } from "./binder.listener"; +import path from "path"; +import { ProgramContext } from "../generated/JackParser"; +describe("ValidatorListener", () => { + const jestConsole = console; + beforeEach(() => { + global.console = require("console"); + }); + + afterEach(() => { + global.console = jestConsole; + }); + + function genericSymbol( + type?: SubroutineType, + paramsCount?: number, + ): GenericSymbol { + if (type != undefined && paramsCount != undefined) { + return createSubroutineSymbol(paramsCount, type); + } else { + return {} as GenericSymbol; + } + } + + const duplicateVarClassBodies = [ + ["static", " static int a, a;"], + ["field", " field int a, a;"], + ["static and field", " static int a; field boolean a;"], + ["function args", " function void a(int a, int a){return;}"], + [ + "function var", + ` function void a(){ + var boolean a, a; + return; + }`, + ], + [ + "function var with different types", + ` function void a(){ + var boolean a; + var int a; + return; + }`, + ], + ]; + test.concurrent.each(duplicateVarClassBodies)( + "duplicated %s", + (testName, classBody) => { + testValidator( + ` + class Main { + ${classBody} + }`, + DuplicatedVariableError, + ); + }, + ); + + /** + * Undeclared var + */ + test("let - undeclared variable ", () => { + testValidator( + ` + class Main { + function void a(){ + let b=1; + return; + } + }`, + UndeclaredVariableError, + ); + }); + + test("call function - undeclared variable ", () => { + testValidator( + `class Main { + function void b(int a){ + return; + } + function void a(){ + do Main.b(a); + return; + } + }`, + UndeclaredVariableError, + { + Main: genericSymbol(), + "Main.b": genericSymbol(SubroutineType.Function, 1), + "Main.a": genericSymbol(SubroutineType.Function, 1), + }, + ); + }); + + test("if - undeclared variable ", () => { + testValidator( + `class Main { + function void a(){ + if(a=0){ + return; + }else { + return; + } + } + }`, + UndeclaredVariableError, + ); + }); + + /** + * Unknown class + */ + test("Unknown class for subroutine return type ", () => { + testValidator( + ` + class Main { + function void b(int a){ + var D d; + return; + } + }`, + UnknownClassError, + ); + }); + + test("Known type for subroutine return type ", () => { + testValidator( + ` + class Main { + function D b(int a){ + return D.new(); + } + }`, + undefined, + { + D: genericSymbol(), + "D.new": genericSymbol(SubroutineType.Constructor, 0), + }, + ); + }); + test("Arg Unknown class ", () => { + testValidator( + ` + class Main { + function void b(D a){ + return; + } + }`, + UnknownClassError, + ); + }); + + test("Arg known type ", () => { + testValidator( + ` + + class Main { + function void b(D a){ + return; + } + }`, + undefined, + { D: genericSymbol() }, + ); + }); + test("var Unknown class", () => { + testValidator( + ` + class Main { + function void b(){ + var D d; + return; + } + }`, + UnknownClassError, + ); + }); + test("var known type", () => { + testValidator( + ` + class Main { + function void b(){ + var D d; + return; + } + }`, + undefined, + { D: genericSymbol() }, + ); + }); + test("field Unknown class", () => { + testValidator( + ` + class Main { + field T t; + }`, + UnknownClassError, + ); + }); + test("field known type", () => { + testValidator( + ` + class Main { + field T t; + }`, + undefined, + { T: genericSymbol() }, + ); + }); + test("static field Unknown class", () => { + testValidator( + ` + class Main { + static T t; + }`, + UnknownClassError, + ); + }); + test("static field known type", () => { + testValidator( + ` + class Main { + static T t; + }`, + undefined, + { T: genericSymbol() }, + ); + }); + + /** + * Incorrect return type + */ + + test("non void subroutine must return a value", () => { + testValidator( + ` + class Main { + function int a(){ + return; + } + }`, + NonVoidFunctionNoReturnError, + ); + }); + + test("void subroutine must return not return a value", () => { + testValidator( + ` + class Main { + function void a(){ + return 1; + } + }`, + VoidSubroutineReturnsValueError, + ); + }); + /** + * `Subroutine ${subroutine.name.value}: not all code paths return a value` + */ + + test("if missing return", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + + }else{ + return; + } + } + }`, + SubroutineNotAllPathsReturnError, + ); + }); + test("else missing return ", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + return; + }else{ + + } + } + }`, + SubroutineNotAllPathsReturnError, + ); + }); + + test("while missing return", () => { + testValidator( + ` + class Main { + function int a(){ + var int a; + let a=0; + while(a<10){ + + } + } + }`, + SubroutineNotAllPathsReturnError, + ); + }); + + test(" missing return after while", () => { + testValidator( + ` + class Main { + function int a(){ + var int a; + let a=0; + while(a<10){ + return 0; + } + } + }`, + SubroutineNotAllPathsReturnError, + ); + }); + + test("nested if missing return", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + return; + }else { + + } + }else{ + return; + } + } + }`, + SubroutineNotAllPathsReturnError, + ); + }); + test("nested if missing return 2", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + + }else { + return; + } + }else{ + return; + } + } + }`, + SubroutineNotAllPathsReturnError, + ); + }); + + test("nested if missing return 3", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + return; + }else { + return; + } + }else{ + + } + } + }`, + SubroutineNotAllPathsReturnError, + ); + }); + test("should be valid", () => { + testValidator(` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + }else { + } + } + return; + } + }`); + }); + /** + * Validate function call + */ + test("calling undefined subroutine", () => { + testValidator( + ` + class Main { + function void b(){ + do Main.c(); + return; + } + }`, + UnknownSubroutineCallError, + ); + }); + + test("incorrect number of parameters when calling a function", () => { + testValidator( + ` + class Main { + function void a(int a, int b){ + return; + } + function void b(){ + do Main.a(1); + return; + } + }`, + IncorrectParamsNumberInSubroutineCallError, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 2), + "Main.b": genericSymbol(SubroutineType.Function, 2), + }, + ); + }); + + test("call var method ", () => { + testValidator( + ` + class Main { + constructor Main new(){ + return this; + } + function void a(){ + var Main m; + let m = Main.new(); + do m.b(); + return; + } + method void b(){ + return; + } + }`, + undefined, + { + Main: genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + "Main.a": genericSymbol(SubroutineType.Function, 0), + "Main.b": genericSymbol(SubroutineType.Method, 0), + }, + ); + }); + test("call local method ", () => { + testValidator( + ` + class Main { + method void a(){ + do b(); + return; + } + method void b(){ + return; + } + }`, + undefined, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Method, 0), + "Main.b": genericSymbol(SubroutineType.Method, 0), + }, + ); + }); + + /** + * - `Method ${className}.${subroutineName} was called as a function/constructor` + */ + test("method called as a function/constructor", () => { + testValidator( + ` + class Main { + function void b(){ + do Main.c(); + return; + } + method void c(){ + return; + } + }`, + MethodCalledAsFunctionError, + { + Main: genericSymbol(), + "Main.b": genericSymbol(SubroutineType.Function, 0), + "Main.c": genericSymbol(SubroutineType.Method, 0), + }, + ); + }); + test("function/ctor called as a method", () => { + testValidator( + ` + class Main { + function void b(){ + do c(); + return; + } + function void c(){ + return; + } + }`, + FunctionCalledAsMethodError, + { + Main: genericSymbol(), + "Main.b": genericSymbol(SubroutineType.Function, 0), + "Main.c": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("incorrect return type in constructor", () => { + testValidator( + ` + class Main { + constructor D new(){ + return this; + } + }`, + IncorrectConstructorReturnType, + { + Main: genericSymbol(), + D: genericSymbol(), + }, + ); + }); + test("unreachable code", () => { + testValidator( + ` + class Main { + constructor Main new(){ + return this; + let a=0; + let a=0; + let a=0; + } + }`, + UnreachableCodeError, + { + Main: genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + }, + ); + }); + test("A constructor must return 'this'", () => { + testValidator( + ` + class Main { + constructor Main new(){ + return 1; + } + }`, + ConstructorMushReturnThis, + { + Main: genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + }, + ); + }); + test("Let statement - expected string literal ", () => { + testValidator( + ` + class Main { + function void a(){ + var String foo; + let foo = 1; + return; + } + }`, + WrongLiteralTypeError, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + String: genericSymbol(), + }, + ); + }); + test("Let statement - expected boolean literal ", () => { + testValidator( + ` + class Main { + function void a(){ + var boolean foo; + let foo = 1; + return; + } + }`, + WrongLiteralTypeError, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + + test("Let statement - expected int literal ", () => { + testValidator( + ` + class Main { + function void a(){ + var int foo; + let foo = "asb"; + return; + } + }`, + WrongLiteralTypeError, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("integer constant value is too big", () => { + testValidator( + ` + class Main { + function void a(){ + var int foo; + let foo = 33000; + return; + } + }`, + IntLiteralOverflow, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("integer constant value is too small", () => { + testValidator( + ` + class Main { + function void a(){ + var int foo; + let foo = -33000; + return; + } + }`, + IntLiteralOverflow, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("A field can not be referenced in a function", () => { + testValidator( + ` + class Main { + field int a; + function void a(){ + let a = 1; + return; + } + }`, + FieldCantBeReferencedInFunction, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("A static field can be referenced in a function", () => { + testValidator( + ` + class Main { + static int a; + function void a(){ + let a = 1; + return; + } + }`, + undefined, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("this can't be referenced in a function", () => { + testValidator( + ` + class Main { + function void a(){ + var Main m; + let m = this; + return; + } + }`, + ThisCantBeReferencedInFunction, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + + //validate files + test.concurrent.each(testResourceDirs)("%s", (dir: string) => { + testJackDir(getTestResourcePath(dir)); + }); +}); + +function testJackDir(testFolder: string): void { + const files = fs + .readdirSync(testFolder) + .filter((file) => file.endsWith(".jack")) + .map((file) => path.join(testFolder, file)); + const trees: Record = {}; + const globalSymbolsListener: BinderListener = new BinderListener(); + for (const filePath of files) { + const tree = parseJackFile(filePath); + trees[filePath] = tree; + listenToTheTree(tree, globalSymbolsListener); + expect(globalSymbolsListener.errors).toEqual([]); + } + for (const filepath of Object.keys(trees)) { + const tree = trees[filepath]; + const validatorListener = listenToTheTree( + tree, + new ValidatorListener(globalSymbolsListener.globalSymbolTable), + ); + expect(validatorListener.errors).toEqual([]); + } +} + +function testValidator( + src: string, + expectedError?: T, + globalSymbolTable: Record = {}, +) { + const errorListener = new CustomErrorListener(); + const tree = parseJackText(src, errorListener); + + const validator = listenToTheTree( + tree, + new ValidatorListener(globalSymbolTable), + ); + if (expectedError) { + // if (validator.cfgNode) { + // validator.cfgNode.print() + // } + if (validator.errors.length > 1) { + console.error("Errors", validator.errors); + } + try { + expect(validator.errors.length).toBe(1); + expect(validator.errors[0]).toBeInstanceOf(expectedError); + } catch (e) { + throw new Error( + `Expected error ${expectedError.name} but got '` + + validator.errors.join(",") + + "'", + ); + } + } else { + if (validator.errors.length != 0) + throw new Error( + "Didn't expect any errors but got " + validator.errors.join("\n"), + ); + } + // if (expectedLocalSymbolTable != undefined) { + // expect(validator.localSymbolTable).toEqual(expectedLocalSymbolTable) + // } +} + +//TODO: add validation for assgining from void function call +//TODO: Add rule to forbid var use before assignment +/** + * TODO: + * Ideas for improvement - + * - Show "Expected class name, subroutine name, field, parameter or local or static variable name" instead of "expecting IDENTIFIER" + * - Show "Expected subroutine return type followed by a subroutine name" instead of "expecting IDENTIFIER" + * - Expected subroutine name in call + * - a numeric value is illegal here when using non numeric vars + * - validate function call - when using literal in call validate the type + */ diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts new file mode 100644 index 00000000..8e550b03 --- /dev/null +++ b/simulator/src/jack/listener/validator.listener.ts @@ -0,0 +1,583 @@ +import { ParserRuleContext } from "antlr4"; +import { builtInTypes, intRange } from "../builtins.js"; +import { + ConstructorMushReturnThis, + DuplicatedVariableException, + FieldCantBeReferencedInFunction, + FunctionCalledAsMethodError, + IncorrectConstructorReturnType, + IncorrectParamsNumberInSubroutineCallError, + IntLiteralIsOutOfRange, + JackCompilerError, + MethodCalledAsFunctionError, + NonVoidFunctionNoReturnError, + SubroutineNotAllPathsReturnError, + ThisCantBeReferencedInFunction, + UndeclaredVariableError, + UnknownClassError, + UnknownSubroutineCallError, + UnreachableCodeError, + VoidSubroutineReturnsValueError, + WrongLiteralTypeError, +} from "../error.js"; +import { + ClassDeclarationContext, + ClassVarDecContext, + ConstantContext, + ElseStatementContext, + IfStatementContext, + LetStatementContext, + ParameterContext, + RBraceContext, + ReturnStatementContext, + StatementContext, + SubroutineBodyContext, + SubroutineCallContext, + SubroutineDeclarationContext, + SubroutineDecWithoutTypeContext, + VarDeclarationContext, + VarNameContext, + VarTypeContext, + WhileStatementContext, +} from "../generated/JackParser.js"; +import JackParserListener from "../generated/JackParserListener.js"; +import { + GenericSymbol, + LocalSymbolTable, + ScopeType, + SubroutineType, +} from "../symbol.js"; +import { CallType, getCallType } from "./common.js"; + +/** + * Validates Jack file + */ +export class ValidatorListener extends JackParserListener { + private localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); + private subroutineShouldReturnVoidType = false; + private controlFlowGraphNode: BinaryTreeNode = new BinaryTreeNode(); + private subroutineName = ""; + private className = ""; + private stopProcessingErrorsInThisScope = false; + private subroutineType?: SubroutineType; + constructor( + private globalSymbolTable: Record, + public errors: JackCompilerError[] = [], + ) { + super(); + } + + override enterClassDeclaration = (ctx: ClassDeclarationContext) => { + const newName = ctx.className()?.getText(); + if (this.className != "") { + throw new Error("Cannot change class name"); + } + this.className = newName; + ctx.localSymbolTable = this.localSymbolTable; + }; + + override enterClassVarDec = (ctx: ClassVarDecContext) => { + let scope: ScopeType; + if (ctx.STATIC() != null) { + scope = ScopeType.Static; + } else if (ctx.FIELD() != null) { + scope = ScopeType.This; + } else { + throw new Error("Unknown field modifier "); + } + const type = ctx.fieldList().varType().getText(); + ctx + .fieldList() + .fieldName_list() + .forEach((field) => { + this.#localSymbolTableAdd(ctx, scope, field.getText(), type); + }); + }; + override enterSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { + if (ctx.subroutineType().CONSTRUCTOR() != null) { + this.subroutineType = SubroutineType.Constructor; + if ( + ctx.subroutineDecWithoutType().subroutineReturnType().getText() !== + this.className + ) { + this.#addError( + new IncorrectConstructorReturnType( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + ), + ); + } + } else if (ctx.subroutineType().FUNCTION() != null) { + this.subroutineType = SubroutineType.Function; + } else if (ctx.subroutineType().METHOD != null) { + this.subroutineType = SubroutineType.Method; + } else { + throw new Error("Unknown subroutine type "); + } + }; + override enterSubroutineDecWithoutType = ( + ctx: SubroutineDecWithoutTypeContext, + ) => { + const returnType = ctx.subroutineReturnType(); + this.subroutineShouldReturnVoidType = returnType.VOID() != null; + this.controlFlowGraphNode = new BinaryTreeNode(); + this.subroutineName = ctx.subroutineName().getText(); + }; + + override enterParameter = (ctx: ParameterContext) => { + this.#defineArgument( + ctx, + ctx.parameterName().getText(), + ctx.varType().getText(), + this.subroutineType == SubroutineType.Method, + ); + }; + //Var + override enterVarType = (ctx: VarTypeContext) => { + if (ctx.IDENTIFIER() != null) { + const type = ctx.IDENTIFIER()!.getText(); + if (this.globalSymbolTable[type] == null) { + this.#addError( + new UnknownClassError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + type, + ), + ); + } + } + }; + + override enterVarDeclaration = (ctx: VarDeclarationContext) => { + const type = ctx.varType().getText(); + ctx.varNameInDeclaration_list().forEach((name) => { + this.#localSymbolTableAdd(ctx, ScopeType.Local, name.getText(), type); + }); + }; + + /** + * Var name when using it - do Statement, let ... as opposed to varNameInDeclaration + */ + override enterVarName = (ctx: VarNameContext) => { + const symbol = this.localSymbolTable.lookup(ctx.getText()); + if (symbol == undefined) { + this.#addError( + new UndeclaredVariableError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + ctx.getText(), + ), + ); + } else if ( + this.subroutineType == SubroutineType.Function && + symbol.scope == ScopeType.This + ) { + this.#addError( + new FieldCantBeReferencedInFunction( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + ), + ); + } + }; + + override enterConstant = (ctx: ConstantContext) => { + if ( + ctx.THIS_LITERAL() != null && + this.subroutineType == SubroutineType.Function + ) { + this.#addError( + new ThisCantBeReferencedInFunction( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + ), + ); + } + }; + + override enterStatement = (ctx: StatementContext) => { + if (this.controlFlowGraphNode._returns == true) { + this.#addError( + new UnreachableCodeError( + ctx.start.line, + ctx.start.start, + ctx.stop?.stop ?? ctx.start.stop, + ), + ); + this.stopProcessingErrorsInThisScope = true; + } + }; + override enterRBrace = (ctx: RBraceContext) => { + this.stopProcessingErrorsInThisScope = false; + }; + /** + * Control flow + */ + override enterWhileStatement = (ctx: WhileStatementContext) => { + this.controlFlowGraphNode = this.controlFlowGraphNode.left = + new BinaryTreeNode(this.controlFlowGraphNode); + }; + + override exitWhileStatement = (ctx: WhileStatementContext) => { + if (this.controlFlowGraphNode?.parent != null) { + this.controlFlowGraphNode = this.controlFlowGraphNode.parent; + } + }; + override enterIfStatement = (ctx: IfStatementContext) => { + this.controlFlowGraphNode = this.controlFlowGraphNode.left = + new BinaryTreeNode(this.controlFlowGraphNode); + }; + override exitIfStatement = (ctx: IfStatementContext) => { + if (this.controlFlowGraphNode?.parent != null) { + this.controlFlowGraphNode = this.controlFlowGraphNode.parent; + } + }; + override enterElseStatement = (ctx: ElseStatementContext) => { + this.controlFlowGraphNode = this.controlFlowGraphNode.right = + new BinaryTreeNode(this.controlFlowGraphNode); + }; + override exitElseStatement = (ctx: ElseStatementContext) => { + if (this.controlFlowGraphNode?.parent != null) { + this.controlFlowGraphNode = this.controlFlowGraphNode.parent; + } + }; + override enterLetStatement = (ctx: LetStatementContext) => { + const varName = ctx.varName(); + const constCtx = ctx.expression().constant(); + //corresponding literal type check + if ( + varName != null && + constCtx != null && + this.localSymbolTable.lookup(ctx.varName()!.getText()) && + ctx.expression().constant()!.NULL_LITERAL() == null + ) { + const type = this.localSymbolTable.lookup(ctx.varName()!.getText())!.type; + if (literalTypes.indexOf(type) != -1) { + const constantCtx = ctx.expression().constant()!; + switch (type) { + case "char": + case "int": + if (constantCtx.INTEGER_LITERAL() === null) { + this.#addError( + new WrongLiteralTypeError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + type, + ), + ); + } else { + const value = parseInt(constantCtx.INTEGER_LITERAL()!.getText()); + if (value > intRange.max) { + this.#addError( + new IntLiteralIsOutOfRange( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + value, + intRange.min, + intRange.max, + ), + ); + } + } + break; + case "boolean": + if (constantCtx.booleanLiteral() === null) { + this.#addError( + new WrongLiteralTypeError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + type, + ), + ); + } + break; + case "String": + if (constantCtx.STRING_LITERAL() === null) { + this.#addError( + new WrongLiteralTypeError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + type.toLowerCase(), + ), + ); + } + break; + default: + throw new Error(`Unknown literal type ${type}`); + } + } + } + //int min value check + const unaryOp = ctx.expression().unaryOperation(); + if ( + varName && + unaryOp != null && + unaryOp.unaryOperator().MINUS() !== null && + unaryOp!.expression().constant() != null && + unaryOp!.expression().constant()?.INTEGER_LITERAL() !== null + ) { + const value = parseInt( + unaryOp!.expression().constant()!.INTEGER_LITERAL()!.getText(), + ); + if (-value < intRange.min) { + this.#addError( + new IntLiteralIsOutOfRange( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + value, + intRange.min, + intRange.max, + ), + ); + } + } + }; + + override enterSubroutineCall = (ctx: SubroutineCallContext) => { + //check if variable exists with the name before dot + const subroutineId = ctx.subroutineId(); + const { callType, subroutineIdText } = getCallType( + subroutineId, + this.className, + this.localSymbolTable, + ); + + const symbol = this.globalSymbolTable[subroutineIdText]; + if (symbol == undefined) { + this.#addError( + new UnknownSubroutineCallError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + subroutineId.subroutineName().getText(), + subroutineId.className()?.getText(), + ), + ); + } else { + //method called as a function + if ( + symbol.subroutineInfo?.type == SubroutineType.Method && + callType == CallType.ClassFunctionOrConstructor + ) { + this.#addError( + new MethodCalledAsFunctionError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + subroutineId.subroutineName().getText(), + ), + ); + } + // function called as a method + else if ( + symbol.subroutineInfo?.type == SubroutineType.Function && + callType == CallType.LocalMethod + ) { + this.#addError( + new FunctionCalledAsMethodError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + subroutineId.subroutineName().getText(), + ), + ); + } else { + //check parameter count + const l = ctx.expressionList().expression_list().length; + if (symbol.subroutineInfo!.paramsCount != l) { + this.#addError( + new IncorrectParamsNumberInSubroutineCallError( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + subroutineId.getText(), + symbol.subroutineInfo!.paramsCount, + l, + ), + ); + } + } + } + }; + override enterReturnStatement = (ctx: ReturnStatementContext) => { + const returnsVoid = ctx.expression() == null; + if (returnsVoid && !this.subroutineShouldReturnVoidType) { + this.#addError( + new NonVoidFunctionNoReturnError( + ctx.stop!.line, + ctx.stop!.start, + ctx.stop!.stop, + ), + ); + } + if (!returnsVoid && this.subroutineShouldReturnVoidType) { + this.#addError( + new VoidSubroutineReturnsValueError( + ctx.stop!.line, + ctx.stop!.start, + ctx.stop!.stop, + ), + ); + } + this.controlFlowGraphNode._returns = true; + if (this.subroutineType == SubroutineType.Constructor) { + if ( + returnsVoid || + ctx.expression()!.expression_list().length > 1 || + ctx.expression()!.constant() == null || + ctx.expression()!.constant()!.THIS_LITERAL() == null + ) { + //TODO: test on UI + this.#addError( + new ConstructorMushReturnThis( + ctx.stop!.line, + ctx.stop!.start, + ctx.stop!.stop, + ), + ); + } + } + }; + + override exitSubroutineBody = (ctx: SubroutineBodyContext) => { + if (!this.controlFlowGraphNode.returns) { + //TODO: test on UI + this.#addError( + new SubroutineNotAllPathsReturnError( + ctx.stop!.line, + ctx.stop!.start, + ctx.stop!.stop, + this.subroutineName, + ), + ); + } + this.subroutineType = undefined; + }; + override exitSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { + ctx.symbols = this.localSymbolTable.popStack(); + }; + + override exitClassDeclaration = (ctx: ClassDeclarationContext) => { + while (this.controlFlowGraphNode?.parent != undefined) { + this.controlFlowGraphNode = this.controlFlowGraphNode.parent; + } + }; + + //Utils + #defineArgument( + ctx: ParserRuleContext, + name: string, + type: string, + inMethod: boolean, + ) { + if (this.localSymbolTable.lookup(name)) { + this.#addError( + new DuplicatedVariableException( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + name, + ), + ); + } else { + this.localSymbolTable.defineArgument(name, type, inMethod); + } + } + #localSymbolTableAdd( + ctx: ParserRuleContext, + scope: ScopeType, + name: string, + type: string, + ) { + if (this.localSymbolTable.lookup(name)) { + this.#addError( + new DuplicatedVariableException( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + name, + ), + ); + } else { + this.localSymbolTable.define(scope, name, type); + } + } + #addError(error: T) { + if (!this.stopProcessingErrorsInThisScope) this.errors.push(error); + } +} + +class BinaryTreeNode { + _returns?: boolean; + constructor( + public parent?: BinaryTreeNode, + public left?: BinaryTreeNode, + public right?: BinaryTreeNode, + ) {} + + get returns(): boolean { + if (this._returns) { + return this._returns; + } else if (this.right == undefined && this.left == undefined) { + return false; + } else if (this.right != undefined && this.left != undefined) { + return this.left.returns && this.right.returns; + } else if (this.left != undefined) { + return false; + } else { + throw new Error("Something went wrong - CFG has only right subtree"); + } + } + print() { + console.log("Branch returns value"); + console.log("."); + console.log(this.printBT()); + } + + printBT(prefix = "", side: Side = Side.LEFT) { + let res = ""; + if (this._returns) { + res += this.#pad(prefix, side); + res += " " + this._returns + "\n"; + return res; + } else { + if (this.right == undefined && this.left == undefined) { + res += this.#pad(prefix, side); + res += " " + false + "\n"; + } else { + res += this.left?.printBT( + side == Side.LEFT ? "| " : " ", + Side.LEFT, + ); + if (this.right) { + res += prefix; + res += this.right?.printBT( + side == Side.LEFT ? "|\t" : "\t", + Side.RIGHT, + ); + } else { + res += "\n"; + } + } + } + return res; + } + #pad(prefix: string, side: Side): string { + return side == Side.LEFT ? "├──" : "└──"; + } +} +enum Side { + LEFT, + RIGHT, +} +const literalTypes = [...builtInTypes, "String"]; diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts new file mode 100644 index 00000000..1df55f93 --- /dev/null +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -0,0 +1,286 @@ +import { + ArrayAccessContext, + ClassDeclarationContext, + ConstantContext, + EqualsContext, + ExpressionContext, + IfElseStatementContext, + IfExpressionContext, + IfStatementContext, + LetStatementContext, + ReturnStatementContext, + StatementContext, + SubroutineCallContext, + SubroutineDeclarationContext, + WhileExpressionContext, + WhileStatementContext, +} from "../generated/JackParser.js"; +import JackParserListener from "../generated/JackParserListener.js"; +import { + GenericSymbol, + LocalSymbolTable, + scopeTypeToString, + VariableSymbol, +} from "../symbol.js"; +import { CallType, getCallType } from "./common.js"; + +const binaryOperationToVmCmd: Record = { + "+": "add", + "-": "sub", + "*": "call Math.multiply 2", + "/": "call Math.divide 2", + "&": "and", + "|": "or", + "<": "lt", + ">": "gt", + "=": "eq", +}; + +const unaryOperationToVmCmd: Record = { + "-": "neg", + "~": "not", +}; + +/** + * Transforms parse tree into VM code + */ +export class VMWriter extends JackParserListener { + public result = ""; + private className = ""; + private currentLabelInd = 0; + private localSymbolTable: LocalSymbolTable | undefined; + private afterEquals = false; + constructor(private globalSymbolTable: Record) { + super(); + } + + override enterClassDeclaration = (ctx: ClassDeclarationContext) => { + if (this.className != "") { + throw new Error("Cannot change class name"); + } + if (ctx.localSymbolTable == undefined) { + throw new Error("Local symbol table not found in parse tree"); + } + this.className = ctx.className()!.getText(); + this.localSymbolTable = ctx.localSymbolTable; + }; + + override enterSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { + const name = ctx + .subroutineDecWithoutType() + .subroutineName() + .IDENTIFIER() + .getText(); + const symbol = this.globalSymbolTable[this.className + "." + name]; + if (symbol == undefined) { + throw new Error( + `Can't find subroutine ${name} in class ${this.className} in symbol table`, + ); + } + this.result += `function ${this.className}.${name} ${symbol.subroutineInfo!.localVarsCount}\n`; + + if (ctx.subroutineType().CONSTRUCTOR() != null) { + this.result += ` push constant ${this.localSymbolTable!.fieldsCount()}\n`; + this.result += " call Memory.alloc 1\n"; + this.result += " pop pointer 0\n"; + } else if (ctx.subroutineType().METHOD() != null) { + this.result += " push argument 0\n"; + this.result += " pop pointer 0\n"; + } + + if (ctx.symbols == null) { + throw new Error("Subroutine symbols not found in parse tree"); + } + this.localSymbolTable!.setSubroutineScope(ctx.symbols); + }; + override exitArrayAccess = (ctx: ArrayAccessContext) => { + const varName = ctx.varName().IDENTIFIER().getText(); + const symbol = this.localSymbolTable!.lookup(varName); + if (symbol == undefined) { + throw new Error(`Can't find variable ${varName} in local symbol table`); + } + this.pushSymbolOntoStack(symbol); + this.result += ` add\n`; + if (this.afterEquals || ctx.parentCtx instanceof ExpressionContext) { + this.result += ` pop pointer 1\n`; + this.result += ` push that 0\n`; + } + }; + override enterEquals = (ctx: EqualsContext) => { + this.afterEquals = true; + }; + override exitStatement = (ctx: StatementContext) => { + this.afterEquals = false; + }; + override enterConstant = (ctx: ConstantContext) => { + if (ctx.INTEGER_LITERAL() != null) { + this.result += ` push constant ${ctx.INTEGER_LITERAL()!.getText()}\n`; + } else if (ctx.booleanLiteral() != null) { + if (ctx.booleanLiteral()!.FALSE() != null) { + this.result += ` push constant 0\n`; + } else if (ctx.booleanLiteral()!.TRUE()) { + this.result += ` push constant 1\n`; + this.result += ` neg\n`; + } else { + throw new Error("Unknown boolean literal"); + } + } else if (ctx.THIS_LITERAL() != null) { + this.result += ` push pointer 0\n`; + } else if (ctx.STRING_LITERAL() != null) { + const str = ctx + .STRING_LITERAL()! + .getText() + //cutoff "" + .slice(1, -1); + this.result += ` push constant ${str.length}\n`; + this.result += ` call String.new 1\n`; + for (const char of str) { + this.result += ` push constant ${char.charCodeAt(0)}\n`; + this.result += " call String.appendChar 2\n"; + } + } else if (ctx.NULL_LITERAL() != null) { + this.result += ` push constant 0\n`; + } else { + throw new Error("Unknown constant type"); + } + }; + override exitExpression = (ctx: ExpressionContext) => { + if (ctx.varName() != null) { + const varName = ctx.varName()!.IDENTIFIER().getText(); + const symbol = this.localSymbolTable!.lookup(varName); + if (symbol == undefined) { + throw new Error( + `Cannot find variable ${varName} in arguments or local variables`, + ); + } + this.pushSymbolOntoStack(symbol); + } else if (ctx.binaryOperator() != null) { + const binaryOp = ctx.binaryOperator()!.getText(); + if (binaryOperationToVmCmd[binaryOp] == undefined) { + throw new Error(`Unknown binary operator ${binaryOp}`); + } + this.result += "\t" + binaryOperationToVmCmd[binaryOp] + "\n"; + } else if (ctx.unaryOperation() != null) { + const unaryOp = ctx.unaryOperation()!.unaryOperator().getText(); + if (unaryOperationToVmCmd[unaryOp] == null) { + throw new Error(`Unknown unary operator ${unaryOp}`); + } + this.result += "\t" + unaryOperationToVmCmd[unaryOp] + "\n"; + } + }; + pushSymbolOntoStack(symbol: VariableSymbol) { + this.result += ` push ${scopeTypeToString(symbol.scope)} ${symbol.index}\n`; + } + override exitLetStatement = (ctx: LetStatementContext) => { + if (ctx.varName() != null) { + const symbol = this.localSymbolTable!.lookup( + ctx.varName()!.IDENTIFIER().getText(), + ); + if (symbol == undefined) { + throw new Error( + `Can't find variable ${ctx.varName()!.IDENTIFIER().getText()} in local symbol table`, + ); + } + this.result += ` pop ${scopeTypeToString(symbol.scope)} ${symbol.index}\n`; + } else if (ctx.arrayAccess() != null) { + this.result += "pop temp 0\n"; + this.result += "pop pointer 1\n"; + this.result += "push temp 0\n"; + this.result += "pop that 0\n"; + } else { + throw new Error(`Unknown let statement type`); + } + }; + //if else + override enterIfStatement = (ctx: IfStatementContext) => { + ctx.endLabel = this.createLabel(); + }; + override exitIfStatement = (ctx: IfStatementContext) => { + const parent = ctx.parentCtx as IfElseStatementContext; + if (parent.elseStatement() != null) { + parent.endLabel = this.createLabel(); + this.result += ` goto ${parent.endLabel}\n`; + } + this.result += ` label ${ctx.endLabel}\n`; + }; + override exitIfExpression = (ctx: IfExpressionContext) => { + const parent = ctx.parentCtx as IfStatementContext; + this.ifNotGoto(parent.endLabel); + }; + override exitIfElseStatement = (ctx: IfElseStatementContext) => { + if (ctx.endLabel) { + this.result += ` label ${ctx.endLabel} \n`; + } + }; + //while + override enterWhileStatement = (ctx: WhileStatementContext) => { + ctx.startLabel = this.createLabel(); + ctx.endLabel = this.createLabel(); + this.result += ` label ${ctx.startLabel} \n`; + }; + override exitWhileExpression = (ctx: WhileExpressionContext) => { + const parent = ctx.parentCtx as WhileStatementContext; + this.ifNotGoto(parent.endLabel); + }; + + override exitWhileStatement = (ctx: WhileStatementContext) => { + this.result += ` goto ${ctx.startLabel}\n`; + this.result += ` label ${ctx.endLabel}\n`; + }; + + override enterSubroutineCall = (ctx: SubroutineCallContext) => { + const { callType, symbol } = getCallType( + ctx.subroutineId(), + this.className, + this.localSymbolTable!, + ); + if (callType === CallType.VarMethod) { + this.pushSymbolOntoStack(symbol!); + } else if (callType === CallType.LocalMethod) { + this.result += ` push pointer 0\n`; + } + }; + //do + override exitSubroutineCall = (ctx: SubroutineCallContext) => { + //method call + const { callType, subroutineIdText } = getCallType( + ctx.subroutineId(), + this.className, + this.localSymbolTable!, + ); + switch (callType) { + case CallType.ClassFunctionOrConstructor: { + const argsCount = ctx.expressionList().expression_list().length; + this.result += ` call ${ctx.subroutineId().getText()} ${argsCount}\n`; + break; + } + case CallType.LocalMethod: + case CallType.VarMethod: { + const expressionsCount = ctx.expressionList().expression_list().length; + this.result += ` call ${subroutineIdText} ${expressionsCount + 1}\n`; + break; + } + default: + throw new Error(`Unknown call type ${callType}`); + } + }; + //return + override exitReturnStatement = (ctx: ReturnStatementContext) => { + if (ctx.expression() == null) { + this.result += " push constant 0\n"; + } + this.result += " return\n"; + }; + //Utils + ifNotGoto(endLabel: string) { + this.result += " not\n"; + this.result += ` if-goto ${endLabel} \n`; + } + getLabel(ind: number) { + return `${this.className}_${ind} `; + } + + createLabel() { + return this.getLabel(this.currentLabelInd++); + } +} diff --git a/simulator/src/jack/parser.test.ts b/simulator/src/jack/parser.test.ts new file mode 100644 index 00000000..b3d88db6 --- /dev/null +++ b/simulator/src/jack/parser.test.ts @@ -0,0 +1,60 @@ +import fs from "fs"; + +import path from "path"; +import { + getTestResourcePath, + listenToTheTree, + parseJackFile, + parseJackText, + testResourceDirs, +} from "./test.helper"; +import { BinderListener } from "./listener/binder.listener"; + +describe("Parser", () => { + const jestConsole = console; + beforeEach(() => { + global.console = require("console"); + }); + + afterEach(() => { + global.console = jestConsole; + }); + + test.each(testResourceDirs)("%s", (dir: string) => { + testJackDir(getTestResourcePath(dir)); + }); + test("expected EOF", () => { + try { + parseJackText(` + class A{ + } + var a; + `); + } catch (e) { + if (e instanceof Error) { + expect(e.message).toContain("expecting "); + return; + } else { + fail("Expected Error"); + } + } + fail("Expected Error"); + }); +}); + +function testJackDir(testFolder: string): void { + const files = fs + .readdirSync(testFolder) + .filter((file) => file.endsWith(".jack")) + .map((file) => path.join(testFolder, file)); + for (const filePath of files) { + const tree = parseJackFile(filePath); + const globalSymbolsListener = listenToTheTree(tree, new BinderListener()); + const symbolsErrors = globalSymbolsListener.errors.join("\n"); + try { + expect(globalSymbolsListener.errors.length).toBe(0); + } catch (e) { + throw new Error(symbolsErrors); + } + } +} diff --git a/simulator/src/jack/resources/test/Average/Main.jack b/simulator/src/jack/resources/test/Average/Main.jack new file mode 100644 index 00000000..d53093a2 --- /dev/null +++ b/simulator/src/jack/resources/test/Average/Main.jack @@ -0,0 +1,27 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Average/Main.jack + +// Inputs some numbers and computes their average +class Main { + function void main() { + var Array a; + var int length; + var int i, sum; + + let length = Keyboard.readInt("How many numbers? "); + let a = Array.new(length); // constructs the array + + let i = 0; + while (i < length) { + let a[i] = Keyboard.readInt("Enter a number: "); + let sum = sum + a[i]; + let i = i + 1; + } + + do Output.printString("The average is "); + do Output.printInt(sum / length); + return; + } +} diff --git a/simulator/src/jack/resources/test/Average/Main.vm b/simulator/src/jack/resources/test/Average/Main.vm new file mode 100644 index 00000000..318b396d --- /dev/null +++ b/simulator/src/jack/resources/test/Average/Main.vm @@ -0,0 +1,148 @@ +function Main.main 4 + push constant 18 + call String.new 1 + push constant 72 + call String.appendChar 2 + push constant 111 + call String.appendChar 2 + push constant 119 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 109 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 110 + call String.appendChar 2 + push constant 121 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 110 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 109 + call String.appendChar 2 + push constant 98 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 63 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + call Keyboard.readInt 1 + pop local 1 + push local 1 + call Array.new 1 + pop local 0 + push constant 0 + pop local 2 +label Main_0 + push local 2 + push local 1 + lt + not + if-goto Main_1 + push local 2 + push local 0 + add + push constant 16 + call String.new 1 + push constant 69 + call String.appendChar 2 + push constant 110 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 110 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 109 + call String.appendChar 2 + push constant 98 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + call Keyboard.readInt 1 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push local 3 + push local 2 + push local 0 + add + pop pointer 1 + push that 0 + add + pop local 3 + push local 2 + push constant 1 + add + pop local 2 + goto Main_0 + +label Main_1 + push constant 15 + call String.new 1 + push constant 84 + call String.appendChar 2 + push constant 104 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 118 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 103 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 105 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + call Output.printString 1 + push local 3 + push local 1 + call Math.divide 2 + call Output.printInt 1 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/ComplexArrays/Main.jack b/simulator/src/jack/resources/test/ComplexArrays/Main.jack new file mode 100644 index 00000000..b4d7dca2 --- /dev/null +++ b/simulator/src/jack/resources/test/ComplexArrays/Main.jack @@ -0,0 +1,69 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/ComplexArrays/Main.jack +/** + * Performs several complex array processing tests. + * For each test, the expected result is printed, along with the + * actual result. In each test, the two results should be equal. + */ +class Main { + + function void main() { + var Array a, b, c; + + let a = Array.new(10); + let b = Array.new(5); + let c = Array.new(1); + + let a[3] = 2; + let a[4] = 8; + let a[5] = 4; + let b[a[3]] = a[3] + 3; // b[2] = 5 + let a[b[a[3]]] = a[a[5]] * b[((7 - a[3]) - Main.double(2)) + 1]; // a[5] = 8 * 5 = 40 + let c[0] = null; + let c = c[0]; + + do Output.printString("Test 1: expected result: 5; actual result: "); + do Output.printInt(b[2]); + do Output.println(); + do Output.printString("Test 2: expected result: 40; actual result: "); + do Output.printInt(a[5]); + do Output.println(); + do Output.printString("Test 3: expected result: 0; actual result: "); + do Output.printInt(c); + do Output.println(); + + let c = null; + + if (c = null) { + do Main.fill(a, 10); + let c = a[3]; + let c[1] = 33; + let c = a[7]; + let c[1] = 77; + let b = a[3]; + let b[1] = b[1] + c[1]; // b[1] = 33 + 77 = 110; + } + + do Output.printString("Test 4: expected result: 77; actual result: "); + do Output.printInt(c[1]); + do Output.println(); + do Output.printString("Test 5: expected result: 110; actual result: "); + do Output.printInt(b[1]); + do Output.println(); + return; + } + + function int double(int a) { + return a * 2; + } + + function void fill(Array a, int size) { + while (size > 0) { + let size = size - 1; + let a[size] = Array.new(3); + } + return; + } +} diff --git a/simulator/src/jack/resources/test/ComplexArrays/Main.vm b/simulator/src/jack/resources/test/ComplexArrays/Main.vm new file mode 100644 index 00000000..869dd99a --- /dev/null +++ b/simulator/src/jack/resources/test/ComplexArrays/Main.vm @@ -0,0 +1,688 @@ +function Main.main 3 + push constant 10 + call Array.new 1 + pop local 0 + push constant 5 + call Array.new 1 + pop local 1 + push constant 1 + call Array.new 1 + pop local 2 + push constant 3 + push local 0 + add + push constant 2 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 4 + push local 0 + add + push constant 8 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 5 + push local 0 + add + push constant 4 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 3 + push local 0 + add + pop pointer 1 + push that 0 + push local 1 + add + push constant 3 + push local 0 + add + pop pointer 1 + push that 0 + push constant 3 + add + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 3 + push local 0 + add + pop pointer 1 + push that 0 + push local 1 + add + pop pointer 1 + push that 0 + push local 0 + add + push constant 5 + push local 0 + add + pop pointer 1 + push that 0 + push local 0 + add + pop pointer 1 + push that 0 + push constant 7 + push constant 3 + push local 0 + add + pop pointer 1 + push that 0 + sub + push constant 2 + call Main.double 1 + sub + push constant 1 + add + push local 1 + add + pop pointer 1 + push that 0 + call Math.multiply 2 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 0 + push local 2 + add + push constant 0 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 0 + push local 2 + add + pop pointer 1 + push that 0 + pop local 2 + push constant 43 + call String.new 1 + push constant 84 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 49 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 120 + call String.appendChar 2 + push constant 112 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 100 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 53 + call String.appendChar 2 + push constant 59 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + call Output.printString 1 + push constant 2 + push local 1 + add + pop pointer 1 + push that 0 + call Output.printInt 1 + call Output.println 0 + push constant 44 + call String.new 1 + push constant 84 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 50 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 120 + call String.appendChar 2 + push constant 112 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 100 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 52 + call String.appendChar 2 + push constant 48 + call String.appendChar 2 + push constant 59 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + call Output.printString 1 + push constant 5 + push local 0 + add + pop pointer 1 + push that 0 + call Output.printInt 1 + call Output.println 0 + push constant 43 + call String.new 1 + push constant 84 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 51 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 120 + call String.appendChar 2 + push constant 112 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 100 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 48 + call String.appendChar 2 + push constant 59 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + call Output.printString 1 + push local 2 + call Output.printInt 1 + call Output.println 0 + push constant 0 + pop local 2 + push local 2 + push constant 0 + eq + not + if-goto Main_0 + push local 0 + push constant 10 + call Main.fill 2 + push constant 3 + push local 0 + add + pop pointer 1 + push that 0 + pop local 2 + push constant 1 + push local 2 + add + push constant 33 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 7 + push local 0 + add + pop pointer 1 + push that 0 + pop local 2 + push constant 1 + push local 2 + add + push constant 77 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + push constant 3 + push local 0 + add + pop pointer 1 + push that 0 + pop local 1 + push constant 1 + push local 1 + add + push constant 1 + push local 1 + add + pop pointer 1 + push that 0 + push constant 1 + push local 2 + add + pop pointer 1 + push that 0 + add + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 +label Main_0 + push constant 44 + call String.new 1 + push constant 84 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 52 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 120 + call String.appendChar 2 + push constant 112 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 100 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 55 + call String.appendChar 2 + push constant 55 + call String.appendChar 2 + push constant 59 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + call Output.printString 1 + push constant 1 + push local 2 + add + pop pointer 1 + push that 0 + call Output.printInt 1 + call Output.println 0 + push constant 45 + call String.new 1 + push constant 84 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 53 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 120 + call String.appendChar 2 + push constant 112 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 100 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 49 + call String.appendChar 2 + push constant 49 + call String.appendChar 2 + push constant 48 + call String.appendChar 2 + push constant 59 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 115 + call String.appendChar 2 + push constant 117 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 116 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + call Output.printString 1 + push constant 1 + push local 1 + add + pop pointer 1 + push that 0 + call Output.printInt 1 + call Output.println 0 + push constant 0 + return +function Main.double 0 + push argument 0 + push constant 2 + call Math.multiply 2 + return +function Main.fill 0 +label Main_1 + //size>0 + push argument 1 + push constant 0 + gt + not + if-goto Main_2 + //let size = size-1 + push argument 1 + push constant 1 + sub + pop argument 1 + //let a[size] = Array.new(3); + push argument 1 + push argument 0 + add + push constant 3 + call Array.new 1 + pop temp 0 + pop pointer 1 + push temp 0 + pop that 0 + goto Main_1 +label Main_2 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/ConvertToBin/Main.jack b/simulator/src/jack/resources/test/ConvertToBin/Main.jack new file mode 100644 index 00000000..12ce3ce6 --- /dev/null +++ b/simulator/src/jack/resources/test/ConvertToBin/Main.jack @@ -0,0 +1,79 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/ConvertToBin/Main.jack +/** + * Unpacks a 16-bit number into its binary representation: + * Takes the 16-bit number stored in RAM[8000] and stores its individual + * bits in RAM[8001]..RAM[8016] (each location will contain 0 or 1). + * Before the conversion, RAM[8001]..RAM[8016] are initialized to -1. + * + * The program should be tested as follows: + * 1) Load the compiled program into the supplied VM emulator + * 2) Put some value in RAM[8000] + * 3) Switch to "no animation" + * 4) Run the program (give it enough time to run) + * 5) Stop the program + * 6) Check that RAM[8001]..RAM[8016] contains the correct binary result, and + * that none of these memory locations contains -1. + */ +class Main { + /** Initializes RAM[8001]..RAM[8016] to -1, + * and converts the value in RAM[8000] to binary. */ + function void main() { + var int value; + do Main.fillMemory(8001, 16, -1); // sets RAM[8001]..RAM[8016] to -1 + let value = Memory.peek(8000); // reads a value from RAM[8000] + do Main.convert(value); // performs the conversion + return; + } + + /** Converts the given decimal value to binary, and puts + * the resulting bits in RAM[8001]..RAM[8016]. */ + function void convert(int value) { + var int mask, position; + var boolean loop; + + let loop = true; + while (loop) { + let position = position + 1; + let mask = Main.nextMask(mask); + + if (~(position > 16)) { + + if (~((value & mask) = 0)) { + do Memory.poke(8000 + position, 1); + } + else { + do Memory.poke(8000 + position, 0); + } + } + else { + let loop = false; + } + } + return; + } + + /** Returns the next mask (the mask that should follow the given mask). */ + function int nextMask(int mask) { + if (mask = 0) { + return 1; + } + else { + return mask * 2; + } + } + + /** Fills 'length' consecutive memory locations with 'value', + * starting at 'startAddress'. */ + function void fillMemory(int startAddress, int length, int value) { + while (length > 0) { + do Memory.poke(startAddress, value); + let length = length - 1; + let startAddress = startAddress + 1; + } + return; + } + +} diff --git a/simulator/src/jack/resources/test/ConvertToBin/Main.vm b/simulator/src/jack/resources/test/ConvertToBin/Main.vm new file mode 100644 index 00000000..3b7105da --- /dev/null +++ b/simulator/src/jack/resources/test/ConvertToBin/Main.vm @@ -0,0 +1,101 @@ +function Main.main 1 + push constant 8001 + push constant 16 + push constant 1 + neg + call Main.fillMemory 3 + push constant 8000 + call Memory.peek 1 + pop local 0 + push local 0 + call Main.convert 1 + push constant 0 + return +function Main.convert 3 + push constant 1 + neg + pop local 2 +label Main_0 + push local 2 + not + if-goto Main_1 + push local 1 + push constant 1 + add + pop local 1 + push local 0 + call Main.nextMask 1 + pop local 0 + push local 1 + push constant 16 + gt + not + not + if-goto Main_2 + push argument 0 + push local 0 + and + push constant 0 + eq + not + not + if-goto Main_3 + push constant 8000 + push local 1 + add + push constant 1 + call Memory.poke 2 + goto Main_4 +label Main_3 + push constant 8000 + push local 1 + add + push constant 0 + call Memory.poke 2 +label Main_4 + goto Main_5 +label Main_2 + push constant 0 + pop local 2 +label Main_5 + goto Main_0 +label Main_1 + push constant 0 + return +function Main.nextMask 0 + push argument 0 + push constant 0 + eq + not + if-goto Main_6 + push constant 1 + return + goto Main_7 +label Main_6 + push argument 0 + push constant 2 + call Math.multiply 2 + return +label Main_7 +function Main.fillMemory 0 +label Main_8 + push argument 1 + push constant 0 + gt + not + if-goto Main_9 + push argument 0 + push argument 2 + call Memory.poke 2 + push argument 1 + push constant 1 + sub + pop argument 1 + push argument 0 + push constant 1 + add + pop argument 0 + goto Main_8 +label Main_9 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Fraction/Fraction.jack b/simulator/src/jack/resources/test/Fraction/Fraction.jack new file mode 100644 index 00000000..939df83f --- /dev/null +++ b/simulator/src/jack/resources/test/Fraction/Fraction.jack @@ -0,0 +1,65 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Fraction/Fraction.jack + +/** Represents the Fraction type and related operations. */ +class Fraction { + field int numerator, denominator; // field = property = member variable. + + /** Constructs a (reduced) fraction from the given numerator and denominator. */ + constructor Fraction new(int x, int y) { + let numerator = x; + let denominator = y; + do reduce(); // reduces the fraction + return this; // a constructor is expected to return a reference to the new object + } + + // Reduces this fraction. + method void reduce() { + var int g; + let g = Fraction.gcd(numerator, denominator); + if (g > 1) { + let numerator = numerator / g; + let denominator = denominator / g; + } + return; + } + + /** Accessors. */ + method int getNumerator() { return numerator; } + method int getDenominator() { return denominator; } + + /** Returns the sum of this fraction and the other one. */ + method Fraction plus(Fraction other) { + var int sum; + let sum = (numerator * other.getDenominator()) + (other.getNumerator() * denominator); + return Fraction.new(sum, denominator * other.getDenominator()); + } + + // More fraction-related methods (minus, times, div, invert, etc.) can be added here. + + /** Disposes this fraction. */ + method void dispose() { + do Memory.deAlloc(this); // uses an OS routine to recycle the memory held by the object + return; + } + + /** Prints this fraction in the format x/y. */ + method void print() { + do Output.printInt(numerator); + do Output.printString("/"); + do Output.printInt(denominator); + return; + } + + // Computes the greatest common divisor of the given integers. + function int gcd(int a, int b) { + var int r; + while (~(b = 0)) { // applies Euclid's algorithm + let r = a - (b * (a / b)); // r = remainder of the integer division a/b + let a = b; let b = r; + } + return a; + } +} diff --git a/simulator/src/jack/resources/test/Fraction/Fraction.vm b/simulator/src/jack/resources/test/Fraction/Fraction.vm new file mode 100644 index 00000000..a7beb616 --- /dev/null +++ b/simulator/src/jack/resources/test/Fraction/Fraction.vm @@ -0,0 +1,110 @@ +function Fraction.new 0 + push constant 2 + call Memory.alloc 1 + pop pointer 0 + push argument 0 + pop this 0 + push argument 1 + pop this 1 + push pointer 0 + call Fraction.reduce 1 + push pointer 0 + return +function Fraction.reduce 1 + push argument 0 + pop pointer 0 + push this 0 + push this 1 + call Fraction.gcd 2 + pop local 0 + push local 0 + push constant 1 + gt + not + if-goto Fraction_0 + push this 0 + push local 0 + call Math.divide 2 + pop this 0 + push this 1 + push local 0 + call Math.divide 2 + pop this 1 +label Fraction_0 + push constant 0 + return +function Fraction.getNumerator 0 + push argument 0 + pop pointer 0 + push this 0 + return +function Fraction.getDenominator 0 + push argument 0 + pop pointer 0 + push this 1 + return +function Fraction.plus 1 + push argument 0 + pop pointer 0 + push this 0 + push argument 1 + call Fraction.getDenominator 1 + call Math.multiply 2 + push argument 1 + call Fraction.getNumerator 1 + push this 1 + call Math.multiply 2 + add + pop local 0 + push local 0 + push this 1 + push argument 1 + call Fraction.getDenominator 1 + call Math.multiply 2 + call Fraction.new 2 + return +function Fraction.dispose 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Memory.deAlloc 1 + push constant 0 + return +function Fraction.print 0 + push argument 0 + pop pointer 0 + push this 0 + call Output.printInt 1 + push constant 1 + call String.new 1 + push constant 47 + call String.appendChar 2 + call Output.printString 1 + push this 1 + call Output.printInt 1 + push constant 0 + return +function Fraction.gcd 1 +label Fraction_1 + push argument 1 + push constant 0 + eq + not + not + if-goto Fraction_2 + push argument 0 + push argument 1 + push argument 0 + push argument 1 + call Math.divide 2 + call Math.multiply 2 + sub + pop local 0 + push argument 1 + pop argument 0 + push local 0 + pop argument 1 + goto Fraction_1 +label Fraction_2 + push argument 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Fraction/Main.jack b/simulator/src/jack/resources/test/Fraction/Main.jack new file mode 100644 index 00000000..293bc917 --- /dev/null +++ b/simulator/src/jack/resources/test/Fraction/Main.jack @@ -0,0 +1,16 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Fraction/Main.jack + +// Computes and prints the sum of 2/3 and 1/5. +class Main { + function void main() { + var Fraction a, b, c; + let a = Fraction.new(2,3); + let b = Fraction.new(1,5); + let c = a.plus(b); // Computes c = a + b + do c.print(); // Prints "13/15" + return; + } +} diff --git a/simulator/src/jack/resources/test/Fraction/Main.vm b/simulator/src/jack/resources/test/Fraction/Main.vm new file mode 100644 index 00000000..f3257634 --- /dev/null +++ b/simulator/src/jack/resources/test/Fraction/Main.vm @@ -0,0 +1,17 @@ +function Main.main 3 + push constant 2 + push constant 3 + call Fraction.new 2 + pop local 0 + push constant 1 + push constant 5 + call Fraction.new 2 + pop local 1 + push local 0 + push local 1 + call Fraction.plus 2 + pop local 2 + push local 2 + call Fraction.print 1 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/HelloWorld/Main.jack b/simulator/src/jack/resources/test/HelloWorld/Main.jack new file mode 100644 index 00000000..6cb47f47 --- /dev/null +++ b/simulator/src/jack/resources/test/HelloWorld/Main.jack @@ -0,0 +1,14 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/HelloWorld/Main.jack + +/** Hello World program. */ +class Main { + function void main() { + /* Prints some text using the standard library. */ + do Output.printString("Hello world!"); + do Output.println(); // New line + return; + } +} diff --git a/simulator/src/jack/resources/test/HelloWorld/Main.vm b/simulator/src/jack/resources/test/HelloWorld/Main.vm new file mode 100644 index 00000000..5f7e233a --- /dev/null +++ b/simulator/src/jack/resources/test/HelloWorld/Main.vm @@ -0,0 +1,31 @@ +function Main.main 0 + push constant 12 + call String.new 1 + push constant 72 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 111 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 119 + call String.appendChar 2 + push constant 111 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 108 + call String.appendChar 2 + push constant 100 + call String.appendChar 2 + push constant 33 + call String.appendChar 2 + call Output.printString 1 + call Output.println 0 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/List/List.jack b/simulator/src/jack/resources/test/List/List.jack new file mode 100644 index 00000000..49bc54a8 --- /dev/null +++ b/simulator/src/jack/resources/test/List/List.jack @@ -0,0 +1,48 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/List/List.jack + +/** Represents a linked list of integers. */ +class List { + field int data; // an int value, + field List next; // followed by a list of int values + + /* Creates a List. */ + constructor List new(int car, List cdr) { + let data = car; // the identifiers car and cdr are used in + let next = cdr; // memory of the Lisp programming language + return this; + } + + /** Accessors. */ + method int getData() { return data; } + method int getNext() { return next; } + + /** Prints this list. */ + method void print() { + // Sets current to the first element of this list + var List current; + let current = this; + while (~(current = null)) { + do Output.printInt(current.getData()); + do Output.printChar(32); // prints a space + let current = current.getNext(); + } + return; + } + + /** Disposes this List. */ + // By recursively disposing its tail. + method void dispose() { + if (~(next = null)) { + do next.dispose(); + } + // Calls an OS routine to free the memory of this object. + do Memory.deAlloc(this); + return; + } + + // More list processing methods can come here. + +} diff --git a/simulator/src/jack/resources/test/List/List.vm b/simulator/src/jack/resources/test/List/List.vm new file mode 100644 index 00000000..ebb79850 --- /dev/null +++ b/simulator/src/jack/resources/test/List/List.vm @@ -0,0 +1,60 @@ +function List.new 0 + push constant 2 + call Memory.alloc 1 + pop pointer 0 + push argument 0 + pop this 0 + push argument 1 + pop this 1 + push pointer 0 + return +function List.getData 0 + push argument 0 + pop pointer 0 + push this 0 + return +function List.getNext 0 + push argument 0 + pop pointer 0 + push this 1 + return +function List.print 1 + push argument 0 + pop pointer 0 + push pointer 0 + pop local 0 +label List_0 + push local 0 + push constant 0 + eq + not + not + if-goto List_1 + push local 0 + call List.getData 1 + call Output.printInt 1 + push constant 32 + call Output.printChar 1 + push local 0 + call List.getNext 1 + pop local 0 + goto List_0 +label List_1 + push constant 0 + return +function List.dispose 0 + push argument 0 + pop pointer 0 + push this 1 + push constant 0 + eq + not + not + if-goto List_2 + push this 1 + call List.dispose 1 +label List_2 + push pointer 0 + call Memory.deAlloc 1 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/List/Main.jack b/simulator/src/jack/resources/test/List/Main.jack new file mode 100644 index 00000000..54a39a97 --- /dev/null +++ b/simulator/src/jack/resources/test/List/Main.jack @@ -0,0 +1,17 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/List/Main.jack + +/** An example of creating and using List objects. */ +class Main { + function void main() { + // Creates and uses the list (2,3,5). + var List v; + let v = List.new(5,null); + let v = List.new(2,List.new(3,v)); + do v.print(); // prints 2 3 5 + do v.dispose(); // disposes the list + return; + } +} diff --git a/simulator/src/jack/resources/test/List/Main.vm b/simulator/src/jack/resources/test/List/Main.vm new file mode 100644 index 00000000..94891ba4 --- /dev/null +++ b/simulator/src/jack/resources/test/List/Main.vm @@ -0,0 +1,17 @@ +function Main.main 1 + push constant 5 + push constant 0 + call List.new 2 + pop local 0 + push constant 2 + push constant 3 + push local 0 + call List.new 2 + call List.new 2 + pop local 0 + push local 0 + call List.print 1 + push local 0 + call List.dispose 1 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/Ball.jack b/simulator/src/jack/resources/test/Pong/Ball.jack new file mode 100644 index 00000000..f65a9075 --- /dev/null +++ b/simulator/src/jack/resources/test/Pong/Ball.jack @@ -0,0 +1,202 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Pong/Ball.jack +/** + * A graphical ball in a Pong game. Characterized by a screen location and + * distance of last destination. Has methods for drawing, erasing and moving + * on the screen. The ball is displayed as a filled, 6-by-6 pixles rectangle. + */ +class Ball { + + field int x, y; // the ball's screen location (in pixels) + field int lengthx, lengthy; // distance of last destination (in pixels) + + field int d, straightD, diagonalD; // used for straight line movement computation + field boolean invert, positivex, positivey; // (same) + + field int leftWall, rightWall, topWall, bottomWall; // wall locations + + field int wall; // last wall that the ball was bounced off of + + /** Constructs a new ball with the given initial location and wall locations. */ + constructor Ball new(int Ax, int Ay, + int AleftWall, int ArightWall, int AtopWall, int AbottomWall) { + let x = Ax; + let y = Ay; + let leftWall = AleftWall; + let rightWall = ArightWall - 6; // -6 for ball size + let topWall = AtopWall; + let bottomWall = AbottomWall - 6; // -6 for ball size + let wall = 0; + do show(); + return this; + } + + /** Deallocates the Ball's memory. */ + method void dispose() { + do Memory.deAlloc(this); + return; + } + + /** Shows the ball. */ + method void show() { + do Screen.setColor(true); + do draw(); + return; + } + + /** Hides the ball. */ + method void hide() { + do Screen.setColor(false); + do draw(); + return; + } + + /** Draws the ball. */ + method void draw() { + do Screen.drawRectangle(x, y, x + 5, y + 5); + return; + } + + /** Returns the ball's left edge. */ + method int getLeft() { + return x; + } + + /** Returns the ball's right edge. */ + method int getRight() { + return x + 5; + } + + /** Computes and sets the ball's destination. */ + method void setDestination(int destx, int desty) { + var int dx, dy, temp; + let lengthx = destx - x; + let lengthy = desty - y; + let dx = Math.abs(lengthx); + let dy = Math.abs(lengthy); + let invert = (dx < dy); + + if (invert) { + let temp = dx; // swap dx, dy + let dx = dy; + let dy = temp; + let positivex = (y < desty); + let positivey = (x < destx); + } + else { + let positivex = (x < destx); + let positivey = (y < desty); + } + + let d = (2 * dy) - dx; + let straightD = 2 * dy; + let diagonalD = 2 * (dy - dx); + + return; + } + + /** + * Moves the ball one step towards its destination. + * If the ball has reached a wall, returns 0. + * Else, returns a value according to the wall: + * 1 (left wall), 2 (right wall), 3 (top wall), 4 (bottom wall). + */ + method int move() { + + do hide(); + + if (d < 0) { let d = d + straightD; } + else { + let d = d + diagonalD; + + if (positivey) { + if (invert) { let x = x + 4; } + else { let y = y + 4; } + } + else { + if (invert) { let x = x - 4; } + else { let y = y - 4; } + } + } + + if (positivex) { + if (invert) { let y = y + 4; } + else { let x = x + 4; } + } + else { + if (invert) { let y = y - 4; } + else { let x = x - 4; } + } + + if (~(x > leftWall)) { + let wall = 1; + let x = leftWall; + } + if (~(x < rightWall)) { + let wall = 2; + let x = rightWall; + } + if (~(y > topWall)) { + let wall = 3; + let y = topWall; + } + if (~(y < bottomWall)) { + let wall = 4; + let y = bottomWall; + } + + do show(); + + return wall; + } + + /** + * Bounces off the current wall: sets the new destination + * of the ball according to the ball's angle and the given + * bouncing direction (-1/0/1=left/center/right or up/center/down). + */ + method void bounce(int bouncingDirection) { + var int newx, newy, divLengthx, divLengthy, factor; + + // Since results are too big, divides by 10 + let divLengthx = lengthx / 10; + let divLengthy = lengthy / 10; + if (bouncingDirection = 0) { let factor = 10; } + else { + if (((~(lengthx < 0)) & (bouncingDirection = 1)) | ((lengthx < 0) & (bouncingDirection = (-1)))) { + let factor = 20; // bounce direction is in ball direction + } + else { let factor = 5; } // bounce direction is against ball direction + } + + if (wall = 1) { + let newx = 506; + let newy = (divLengthy * (-50)) / divLengthx; + let newy = y + (newy * factor); + } + else { + if (wall = 2) { + let newx = 0; + let newy = (divLengthy * 50) / divLengthx; + let newy = y + (newy * factor); + } + else { + if (wall = 3) { + let newy = 250; + let newx = (divLengthx * (-25)) / divLengthy; + let newx = x + (newx * factor); + } + else { // assumes wall = 4 + let newy = 0; + let newx = (divLengthx * 25) / divLengthy; + let newx = x + (newx * factor); + } + } + } + + do setDestination(newx, newy); + return; + } +} diff --git a/simulator/src/jack/resources/test/Pong/Ball.vm b/simulator/src/jack/resources/test/Pong/Ball.vm new file mode 100644 index 00000000..b054897f --- /dev/null +++ b/simulator/src/jack/resources/test/Pong/Ball.vm @@ -0,0 +1,417 @@ +function Ball.new 0 + push constant 15 + call Memory.alloc 1 + pop pointer 0 + push argument 0 + pop this 0 + push argument 1 + pop this 1 + push argument 2 + pop this 10 + push argument 3 + push constant 6 + sub + pop this 11 + push argument 4 + pop this 12 + push argument 5 + push constant 6 + sub + pop this 13 + push constant 0 + pop this 14 + push pointer 0 + call Ball.show 1 + push pointer 0 + return +function Ball.dispose 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Memory.deAlloc 1 + push constant 0 + return +function Ball.show 0 + push argument 0 + pop pointer 0 + push constant 1 + neg + call Screen.setColor 1 + push pointer 0 + call Ball.draw 1 + push constant 0 + return +function Ball.hide 0 + push argument 0 + pop pointer 0 + push constant 0 + call Screen.setColor 1 + push pointer 0 + call Ball.draw 1 + push constant 0 + return +function Ball.draw 0 + push argument 0 + pop pointer 0 + push this 0 + push this 1 + push this 0 + push constant 5 + add + push this 1 + push constant 5 + add + call Screen.drawRectangle 4 + push constant 0 + return +function Ball.getLeft 0 + push argument 0 + pop pointer 0 + push this 0 + return +function Ball.getRight 0 + push argument 0 + pop pointer 0 + push this 0 + push constant 5 + add + return +function Ball.setDestination 3 + push argument 0 + pop pointer 0 + push argument 1 + push this 0 + sub + pop this 2 + push argument 2 + push this 1 + sub + pop this 3 + push this 2 + call Math.abs 1 + pop local 0 + push this 3 + call Math.abs 1 + pop local 1 + push local 0 + push local 1 + lt + pop this 7 + push this 7 + not + if-goto Ball_0 + push local 0 + pop local 2 + push local 1 + pop local 0 + push local 2 + pop local 1 + push this 1 + push argument 2 + lt + pop this 8 + push this 0 + push argument 1 + lt + pop this 9 + goto Ball_1 +label Ball_0 + push this 0 + push argument 1 + lt + pop this 8 + push this 1 + push argument 2 + lt + pop this 9 +label Ball_1 + push constant 2 + push local 1 + call Math.multiply 2 + push local 0 + sub + pop this 4 + push constant 2 + push local 1 + call Math.multiply 2 + pop this 5 + push constant 2 + push local 1 + push local 0 + sub + call Math.multiply 2 + pop this 6 + push constant 0 + return +function Ball.move 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Ball.hide 1 + push this 4 + push constant 0 + lt + not + if-goto Ball_2 + push this 4 + push this 5 + add + pop this 4 + goto Ball_3 +label Ball_2 + push this 4 + push this 6 + add + pop this 4 + push this 9 + not + if-goto Ball_4 + push this 7 + not + if-goto Ball_5 + push this 0 + push constant 4 + add + pop this 0 + goto Ball_6 +label Ball_5 + push this 1 + push constant 4 + add + pop this 1 +label Ball_6 + goto Ball_7 +label Ball_4 + push this 7 + not + if-goto Ball_8 + push this 0 + push constant 4 + sub + pop this 0 + goto Ball_9 +label Ball_8 + push this 1 + push constant 4 + sub + pop this 1 +label Ball_9 +label Ball_7 +label Ball_3 + push this 8 + not + if-goto Ball_10 + push this 7 + not + if-goto Ball_11 + push this 1 + push constant 4 + add + pop this 1 + goto Ball_12 +label Ball_11 + push this 0 + push constant 4 + add + pop this 0 +label Ball_12 + goto Ball_13 +label Ball_10 + push this 7 + not + if-goto Ball_14 + push this 1 + push constant 4 + sub + pop this 1 + goto Ball_15 +label Ball_14 + push this 0 + push constant 4 + sub + pop this 0 +label Ball_15 +label Ball_13 + push this 0 + push this 10 + gt + not + not + if-goto Ball_16 + push constant 1 + pop this 14 + push this 10 + pop this 0 +label Ball_16 + push this 0 + push this 11 + lt + not + not + if-goto Ball_17 + push constant 2 + pop this 14 + push this 11 + pop this 0 +label Ball_17 + push this 1 + push this 12 + gt + not + not + if-goto Ball_18 + push constant 3 + pop this 14 + push this 12 + pop this 1 +label Ball_18 + push this 1 + push this 13 + lt + not + not + if-goto Ball_19 + push constant 4 + pop this 14 + push this 13 + pop this 1 +label Ball_19 + push pointer 0 + call Ball.show 1 + push this 14 + return +function Ball.bounce 5 + push argument 0 + pop pointer 0 + push this 2 + push constant 10 + call Math.divide 2 + pop local 2 + push this 3 + push constant 10 + call Math.divide 2 + pop local 3 + push argument 1 + push constant 0 + eq + not + if-goto Ball_20 + push constant 10 + pop local 4 + goto Ball_21 +label Ball_20 + push this 2 + push constant 0 + lt + not + push argument 1 + push constant 1 + eq + and + push this 2 + push constant 0 + lt + push argument 1 + push constant 1 + neg + eq + and + or + not + if-goto Ball_22 + push constant 20 + pop local 4 + goto Ball_23 +label Ball_22 + push constant 5 + pop local 4 +label Ball_23 +label Ball_21 + push this 14 + push constant 1 + eq + not + if-goto Ball_24 + push constant 506 + pop local 0 + push local 3 + push constant 50 + neg + call Math.multiply 2 + push local 2 + call Math.divide 2 + pop local 1 + push this 1 + push local 1 + push local 4 + call Math.multiply 2 + add + pop local 1 + goto Ball_25 +label Ball_24 + push this 14 + push constant 2 + eq + not + if-goto Ball_26 + push constant 0 + pop local 0 + push local 3 + push constant 50 + call Math.multiply 2 + push local 2 + call Math.divide 2 + pop local 1 + push this 1 + push local 1 + push local 4 + call Math.multiply 2 + add + pop local 1 + goto Ball_27 +label Ball_26 + push this 14 + push constant 3 + eq + not + if-goto Ball_28 + push constant 250 + pop local 1 + push local 2 + push constant 25 + neg + call Math.multiply 2 + push local 3 + call Math.divide 2 + pop local 0 + push this 0 + push local 0 + push local 4 + call Math.multiply 2 + add + pop local 0 + goto Ball_29 +label Ball_28 + push constant 0 + pop local 1 + push local 2 + push constant 25 + call Math.multiply 2 + push local 3 + call Math.divide 2 + pop local 0 + push this 0 + push local 0 + push local 4 + call Math.multiply 2 + add + pop local 0 +label Ball_29 +label Ball_27 +label Ball_25 + push pointer 0 + push local 0 + push local 1 + call Ball.setDestination 3 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/Bat.jack b/simulator/src/jack/resources/test/Pong/Bat.jack new file mode 100644 index 00000000..b449c2c5 --- /dev/null +++ b/simulator/src/jack/resources/test/Pong/Bat.jack @@ -0,0 +1,103 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Pong/Bat.jack +/** + * A graphical bat in a Pong game. + * Displayed as a filled horizontal rectangle that has a screen location, + * a width and a height. + * Has methods for drawing, erasing, moving left and right, and changing + * its width (to make the hitting action more challenging). + * This class should have been called "Paddle", following the + * standard Pong terminology. Unaware of this terminology, + * we called it "bat", and the name stuck. + */ +class Bat { + + field int x, y; // the bat's screen location + field int width, height; // the bat's width and height + field int direction; // direction of the bat's movement + // (1 = left, 2 = right) + + /** Constructs a new bat with the given location and width. */ + constructor Bat new(int Ax, int Ay, int Awidth, int Aheight) { + let x = Ax; + let y = Ay; + let width = Awidth; + let height = Aheight; + let direction = 2; + do show(); + return this; + } + + /** Deallocates the object's memory. */ + method void dispose() { + do Memory.deAlloc(this); + return; + } + + /** Shows the bat. */ + method void show() { + do Screen.setColor(true); + do draw(); + return; + } + + /** Hides the bat. */ + method void hide() { + do Screen.setColor(false); + do draw(); + return; + } + + /** Draws the bat. */ + method void draw() { + do Screen.drawRectangle(x, y, x + width, y + height); + return; + } + + /** Sets the bat's direction (0=stop, 1=left, 2=right). */ + method void setDirection(int Adirection) { + let direction = Adirection; + return; + } + + /** Returns the bat's left edge. */ + method int getLeft() { + return x; + } + + /** Returns the bat's right edge. */ + method int getRight() { + return x + width; + } + + /** Sets the bat's width. */ + method void setWidth(int Awidth) { + do hide(); + let width = Awidth; + do show(); + return; + } + + /** Moves the bat one step in the bat's direction. */ + method void move() { + if (direction = 1) { + let x = x - 4; + if (x < 0) { let x = 0; } + do Screen.setColor(false); + do Screen.drawRectangle((x + width) + 1, y, (x + width) + 4, y + height); + do Screen.setColor(true); + do Screen.drawRectangle(x, y, x + 3, y + height); + } + else { + let x = x + 4; + if ((x + width) > 511) { let x = 511 - width; } + do Screen.setColor(false); + do Screen.drawRectangle(x - 4, y, x - 1, y + height); + do Screen.setColor(true); + do Screen.drawRectangle((x + width) - 3, y, x + width, y + height); + } + return; + } +} diff --git a/simulator/src/jack/resources/test/Pong/Bat.vm b/simulator/src/jack/resources/test/Pong/Bat.vm new file mode 100644 index 00000000..6d1ab21e --- /dev/null +++ b/simulator/src/jack/resources/test/Pong/Bat.vm @@ -0,0 +1,187 @@ +function Bat.new 0 + push constant 5 + call Memory.alloc 1 + pop pointer 0 + push argument 0 + pop this 0 + push argument 1 + pop this 1 + push argument 2 + pop this 2 + push argument 3 + pop this 3 + push constant 2 + pop this 4 + push pointer 0 + call Bat.show 1 + push pointer 0 + return +function Bat.dispose 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Memory.deAlloc 1 + push constant 0 + return +function Bat.show 0 + push argument 0 + pop pointer 0 + push constant 1 + neg + call Screen.setColor 1 + push pointer 0 + call Bat.draw 1 + push constant 0 + return +function Bat.hide 0 + push argument 0 + pop pointer 0 + push constant 0 + call Screen.setColor 1 + push pointer 0 + call Bat.draw 1 + push constant 0 + return +function Bat.draw 0 + push argument 0 + pop pointer 0 + push this 0 + push this 1 + push this 0 + push this 2 + add + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + push constant 0 + return +function Bat.setDirection 0 + push argument 0 + pop pointer 0 + push argument 1 + pop this 4 + push constant 0 + return +function Bat.getLeft 0 + push argument 0 + pop pointer 0 + push this 0 + return +function Bat.getRight 0 + push argument 0 + pop pointer 0 + push this 0 + push this 2 + add + return +function Bat.setWidth 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Bat.hide 1 + push argument 1 + pop this 2 + push pointer 0 + call Bat.show 1 + push constant 0 + return +function Bat.move 0 + push argument 0 + pop pointer 0 + push this 4 + push constant 1 + eq + not + if-goto Bat_0 + push this 0 + push constant 4 + sub + pop this 0 + push this 0 + push constant 0 + lt + not + if-goto Bat_1 + push constant 0 + pop this 0 +label Bat_1 + push constant 0 + call Screen.setColor 1 + push this 0 + push this 2 + add + push constant 1 + add + push this 1 + push this 0 + push this 2 + add + push constant 4 + add + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + push constant 1 + neg + call Screen.setColor 1 + push this 0 + push this 1 + push this 0 + push constant 3 + add + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + goto Bat_2 +label Bat_0 + push this 0 + push constant 4 + add + pop this 0 + push this 0 + push this 2 + add + push constant 511 + gt + not + if-goto Bat_3 + push constant 511 + push this 2 + sub + pop this 0 +label Bat_3 + push constant 0 + call Screen.setColor 1 + push this 0 + push constant 4 + sub + push this 1 + push this 0 + push constant 1 + sub + push this 1 + push this 3 + add + call Screen.drawRectangle 4 + push constant 1 + neg + call Screen.setColor 1 + push this 0 + push this 2 + add + push constant 3 + sub + push this 1 + push this 0 + push this 2 + add + push this 1 + push this 3 + add + call Screen.drawRectangle 4 +label Bat_2 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/Main.jack b/simulator/src/jack/resources/test/Pong/Main.jack new file mode 100644 index 00000000..9e65ceb7 --- /dev/null +++ b/simulator/src/jack/resources/test/Pong/Main.jack @@ -0,0 +1,18 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Pong/Main.jack +/** + * Main class of the Pong game. + */ +class Main { + /** Initializes a Pong game and starts running it. */ + function void main() { + var PongGame game; + do PongGame.newInstance(); + let game = PongGame.getInstance(); + do game.run(); + do game.dispose(); + return; + } +} diff --git a/simulator/src/jack/resources/test/Pong/Main.vm b/simulator/src/jack/resources/test/Pong/Main.vm new file mode 100644 index 00000000..72da76af --- /dev/null +++ b/simulator/src/jack/resources/test/Pong/Main.vm @@ -0,0 +1,10 @@ +function Main.main 1 + call PongGame.newInstance 0 + call PongGame.getInstance 0 + pop local 0 + push local 0 + call PongGame.run 1 + push local 0 + call PongGame.dispose 1 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/PongGame.jack b/simulator/src/jack/resources/test/Pong/PongGame.jack new file mode 100644 index 00000000..515ead4a --- /dev/null +++ b/simulator/src/jack/resources/test/Pong/PongGame.jack @@ -0,0 +1,136 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Pong/PongGame.jack +/** + * Represents a Pong game. + */ +class PongGame { + + static PongGame instance; // A Pong game + field Bat bat; // bat + field Ball ball; // ball + field int wall; // current wall that the ball is bouncing off of + field boolean exit; // true when the game is over + field int score; // current score + field int lastWall; // last wall that the ball bounced off of + + // The current width of the bat + field int batWidth; + + /** Constructs a new Pong game. */ + constructor PongGame new() { + do Screen.clearScreen(); + let batWidth = 50; // initial bat size + let bat = Bat.new(230, 229, batWidth, 7); + let ball = Ball.new(253, 222, 0, 511, 0, 229); + do ball.setDestination(400,0); + do Screen.drawRectangle(0, 238, 511, 240); + do Output.moveCursor(22,0); + do Output.printString("Score: 0"); + + let exit = false; + let score = 0; + let wall = 0; + let lastWall = 0; + + return this; + } + + /** Deallocates the object's memory. */ + method void dispose() { + do bat.dispose(); + do ball.dispose(); + do Memory.deAlloc(this); + return; + } + + /** Creates an instance of a Pong game. */ + function void newInstance() { + let instance = PongGame.new(); + return; + } + + /** Returns this Pong game. */ + function PongGame getInstance() { + return instance; + } + + /** Starts the game, and handles inputs from the user that control + * the bat's movement direction. */ + method void run() { + var char key; + + while (~exit) { + // waits for a key to be pressed. + while ((key = 0) & (~exit)) { + let key = Keyboard.keyPressed(); + do bat.move(); + do moveBall(); + do Sys.wait(50); + } + + if (key = 130) { do bat.setDirection(1); } + else { + if (key = 132) { do bat.setDirection(2); } + else { + if (key = 140) { let exit = true; } + } + } + + // Waits for the key to be released. + while ((~(key = 0)) & (~exit)) { + let key = Keyboard.keyPressed(); + do bat.move(); + do moveBall(); + do Sys.wait(50); + } + } + + if (exit) { + do Output.moveCursor(10,27); + do Output.printString("Game Over"); + } + + return; + } + + /** + * Handles ball movement, including bouncing. + * If the ball bounces off a wall, finds its new direction. + * If the ball bounces off the bat, increases the score by one + * and shrinks the bat's size, to make the game more challenging. + */ + method void moveBall() { + var int bouncingDirection, batLeft, batRight, ballLeft, ballRight; + + let wall = ball.move(); + + if ((wall > 0) & (~(wall = lastWall))) { + let lastWall = wall; + let bouncingDirection = 0; + let batLeft = bat.getLeft(); + let batRight = bat.getRight(); + let ballLeft = ball.getLeft(); + let ballRight = ball.getRight(); + + if (wall = 4) { + let exit = (batLeft > ballRight) | (batRight < ballLeft); + if (~exit) { + if (ballRight < (batLeft + 10)) { let bouncingDirection = -1; } + else { + if (ballLeft > (batRight - 10)) { let bouncingDirection = 1; } + } + + let batWidth = batWidth - 2; + do bat.setWidth(batWidth); + let score = score + 1; + do Output.moveCursor(22,7); + do Output.printInt(score); + } + } + do ball.bounce(bouncingDirection); + } + return; + } +} \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/PongGame.vm b/simulator/src/jack/resources/test/Pong/PongGame.vm new file mode 100644 index 00000000..f9e69c74 --- /dev/null +++ b/simulator/src/jack/resources/test/Pong/PongGame.vm @@ -0,0 +1,287 @@ +function PongGame.new 0 + push constant 7 + call Memory.alloc 1 + pop pointer 0 + call Screen.clearScreen 0 + push constant 50 + pop this 6 + push constant 230 + push constant 229 + push this 6 + push constant 7 + call Bat.new 4 + pop this 0 + push constant 253 + push constant 222 + push constant 0 + push constant 511 + push constant 0 + push constant 229 + call Ball.new 6 + pop this 1 + push this 1 + push constant 400 + push constant 0 + call Ball.setDestination 3 + push constant 0 + push constant 238 + push constant 511 + push constant 240 + call Screen.drawRectangle 4 + push constant 22 + push constant 0 + call Output.moveCursor 2 + push constant 8 + call String.new 1 + push constant 83 + call String.appendChar 2 + push constant 99 + call String.appendChar 2 + push constant 111 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 58 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 48 + call String.appendChar 2 + call Output.printString 1 + push constant 0 + pop this 3 + push constant 0 + pop this 4 + push constant 0 + pop this 2 + push constant 0 + pop this 5 + push pointer 0 + return +function PongGame.dispose 0 + push argument 0 + pop pointer 0 + push this 0 + call Bat.dispose 1 + push this 1 + call Ball.dispose 1 + push pointer 0 + call Memory.deAlloc 1 + push constant 0 + return +function PongGame.newInstance 0 + call PongGame.new 0 + pop static 0 + push constant 0 + return +function PongGame.getInstance 0 + push static 0 + return +function PongGame.run 1 + push argument 0 + pop pointer 0 +label PongGame_0 + push this 3 + not + not + if-goto PongGame_1 +label PongGame_2 + push local 0 + push constant 0 + eq + push this 3 + not + and + not + if-goto PongGame_3 + call Keyboard.keyPressed 0 + pop local 0 + push this 0 + call Bat.move 1 + push pointer 0 + call PongGame.moveBall 1 + push constant 50 + call Sys.wait 1 + goto PongGame_2 +label PongGame_3 + push local 0 + push constant 130 + eq + not + if-goto PongGame_4 + push this 0 + push constant 1 + call Bat.setDirection 2 + goto PongGame_5 +label PongGame_4 + push local 0 + push constant 132 + eq + not + if-goto PongGame_6 + push this 0 + push constant 2 + call Bat.setDirection 2 + goto PongGame_7 +label PongGame_6 + push local 0 + push constant 140 + eq + not + if-goto PongGame_8 + push constant 1 + neg + pop this 3 +label PongGame_8 +label PongGame_7 +label PongGame_5 +label PongGame_9 + push local 0 + push constant 0 + eq + not + push this 3 + not + and + not + if-goto PongGame_10 + call Keyboard.keyPressed 0 + pop local 0 + push this 0 + call Bat.move 1 + push pointer 0 + call PongGame.moveBall 1 + push constant 50 + call Sys.wait 1 + goto PongGame_9 +label PongGame_10 + goto PongGame_0 +label PongGame_1 + push this 3 + not + if-goto PongGame_11 + push constant 10 + push constant 27 + call Output.moveCursor 2 + push constant 9 + call String.new 1 + push constant 71 + call String.appendChar 2 + push constant 97 + call String.appendChar 2 + push constant 109 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 32 + call String.appendChar 2 + push constant 79 + call String.appendChar 2 + push constant 118 + call String.appendChar 2 + push constant 101 + call String.appendChar 2 + push constant 114 + call String.appendChar 2 + call Output.printString 1 +label PongGame_11 + push constant 0 + return +function PongGame.moveBall 5 + push argument 0 + pop pointer 0 + push this 1 + call Ball.move 1 + pop this 2 + push this 2 + push constant 0 + gt + push this 2 + push this 5 + eq + not + and + not + if-goto PongGame_12 + push this 2 + pop this 5 + push constant 0 + pop local 0 + push this 0 + call Bat.getLeft 1 + pop local 1 + push this 0 + call Bat.getRight 1 + pop local 2 + push this 1 + call Ball.getLeft 1 + pop local 3 + push this 1 + call Ball.getRight 1 + pop local 4 + push this 2 + push constant 4 + eq + not + if-goto PongGame_13 + push local 1 + push local 4 + gt + push local 2 + push local 3 + lt + or + pop this 3 + push this 3 + not + not + if-goto PongGame_14 + push local 4 + push local 1 + push constant 10 + add + lt + not + if-goto PongGame_15 + push constant 1 + neg + pop local 0 + goto PongGame_16 +label PongGame_15 + push local 3 + push local 2 + push constant 10 + sub + gt + not + if-goto PongGame_17 + push constant 1 + pop local 0 +label PongGame_17 +label PongGame_16 + push this 6 + push constant 2 + sub + pop this 6 + push this 0 + push this 6 + call Bat.setWidth 2 + push this 4 + push constant 1 + add + pop this 4 + push constant 22 + push constant 7 + call Output.moveCursor 2 + push this 4 + call Output.printInt 1 +label PongGame_14 +label PongGame_13 + push this 1 + push local 0 + call Ball.bounce 2 +label PongGame_12 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Square/Main.jack b/simulator/src/jack/resources/test/Square/Main.jack new file mode 100644 index 00000000..bc6732e0 --- /dev/null +++ b/simulator/src/jack/resources/test/Square/Main.jack @@ -0,0 +1,15 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Square/Main.jack + +/** Initializes a new Square game and starts running it. */ +class Main { + function void main() { + var SquareGame game; + let game = SquareGame.new(); + do game.run(); + do game.dispose(); + return; + } +} diff --git a/simulator/src/jack/resources/test/Square/Main.vm b/simulator/src/jack/resources/test/Square/Main.vm new file mode 100644 index 00000000..bcbfcfcc --- /dev/null +++ b/simulator/src/jack/resources/test/Square/Main.vm @@ -0,0 +1,9 @@ +function Main.main 1 + call SquareGame.new 0 + pop local 0 + push local 0 + call SquareGame.run 1 + push local 0 + call SquareGame.dispose 1 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Square/Square.jack b/simulator/src/jack/resources/test/Square/Square.jack new file mode 100644 index 00000000..e4a6590d --- /dev/null +++ b/simulator/src/jack/resources/test/Square/Square.jack @@ -0,0 +1,113 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/9/Square/Square.jack + +/** Implements a graphical square. + The square has top-left x and y coordinates, and a size. */ +class Square { + + field int x, y; // screen location of the top-left corner of this square + field int size; // length of this square, in pixels + + /** Constructs and draws a new square with a given location and size. */ + constructor Square new(int ax, int ay, int asize) { + let x = ax; + let y = ay; + let size = asize; + do draw(); + return this; + } + + /** Disposes this square. */ + method void dispose() { + do Memory.deAlloc(this); + return; + } + + /** Draws this square in its current (x,y) location */ + method void draw() { + // Draws the square using the color black + do Screen.setColor(true); + do Screen.drawRectangle(x, y, x + size, y + size); + return; + } + + /** Erases this square. */ + method void erase() { + // Draws the square using the color white (background color) + do Screen.setColor(false); + do Screen.drawRectangle(x, y, x + size, y + size); + return; + } + + /** Increments the square size by 2 pixels (if possible). */ + method void incSize() { + if (((y + size) < 254) & ((x + size) < 510)) { + do erase(); + let size = size + 2; + do draw(); + } + return; + } + + /** Decrements the square size by 2 pixels (if possible). */ + method void decSize() { + if (size > 2) { + do erase(); + let size = size - 2; + do draw(); + } + return; + } + + /** Moves this square up by 2 pixels (if possible). */ + method void moveUp() { + if (y > 1) { + // Erases the bottom two rows of this square in its current location + do Screen.setColor(false); + do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size); + let y = y - 2; + // Draws the top two rows of this square in its new location + do Screen.setColor(true); + do Screen.drawRectangle(x, y, x + size, y + 1); + } + return; + } + + /** Moves the square down by 2 pixels (if possible). */ + method void moveDown() { + if ((y + size) < 254) { + do Screen.setColor(false); + do Screen.drawRectangle(x, y, x + size, y + 1); + let y = y + 2; + do Screen.setColor(true); + do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size); + } + return; + } + + /** Moves the square left by 2 pixels (if possible). */ + method void moveLeft() { + if (x > 1) { + do Screen.setColor(false); + do Screen.drawRectangle((x + size) - 1, y, x + size, y + size); + let x = x - 2; + do Screen.setColor(true); + do Screen.drawRectangle(x, y, x + 1, y + size); + } + return; + } + + /** Moves the square right by 2 pixels (if possible). */ + method void moveRight() { + if ((x + size) < 510) { + do Screen.setColor(false); + do Screen.drawRectangle(x, y, x + 1, y + size); + let x = x + 2; + do Screen.setColor(true); + do Screen.drawRectangle((x + size) - 1, y, x + size, y + size); + } + return; + } +} diff --git a/simulator/src/jack/resources/test/Square/Square.vm b/simulator/src/jack/resources/test/Square/Square.vm new file mode 100644 index 00000000..99beeb2b --- /dev/null +++ b/simulator/src/jack/resources/test/Square/Square.vm @@ -0,0 +1,272 @@ +function Square.new 0 + push constant 3 + call Memory.alloc 1 + pop pointer 0 + push argument 0 + pop this 0 + push argument 1 + pop this 1 + push argument 2 + pop this 2 + push pointer 0 + call Square.draw 1 + push pointer 0 + return +function Square.dispose 0 + push argument 0 + pop pointer 0 + push pointer 0 + call Memory.deAlloc 1 + push constant 0 + return +function Square.draw 0 + push argument 0 + pop pointer 0 + push constant 1 + neg + call Screen.setColor 1 + push this 0 + push this 1 + push this 0 + push this 2 + add + push this 1 + push this 2 + add + call Screen.drawRectangle 4 + push constant 0 + return +function Square.erase 0 + push argument 0 + pop pointer 0 + push constant 0 + call Screen.setColor 1 + push this 0 + push this 1 + push this 0 + push this 2 + add + push this 1 + push this 2 + add + call Screen.drawRectangle 4 + push constant 0 + return +function Square.incSize 0 + push argument 0 + pop pointer 0 + push this 1 + push this 2 + add + push constant 254 + lt + push this 0 + push this 2 + add + push constant 510 + lt + and + not + if-goto Square_0 + push pointer 0 + call Square.erase 1 + push this 2 + push constant 2 + add + pop this 2 + push pointer 0 + call Square.draw 1 +label Square_0 + push constant 0 + return +function Square.decSize 0 + push argument 0 + pop pointer 0 + push this 2 + push constant 2 + gt + not + if-goto Square_1 + push pointer 0 + call Square.erase 1 + push this 2 + push constant 2 + sub + pop this 2 + push pointer 0 + call Square.draw 1 +label Square_1 + push constant 0 + return +function Square.moveUp 0 + push argument 0 + pop pointer 0 + push this 1 + push constant 1 + gt + not + if-goto Square_2 + push constant 0 + call Screen.setColor 1 + push this 0 + push this 1 + push this 2 + add + push constant 1 + sub + push this 0 + push this 2 + add + push this 1 + push this 2 + add + call Screen.drawRectangle 4 + push this 1 + push constant 2 + sub + pop this 1 + push constant 1 + neg + call Screen.setColor 1 + push this 0 + push this 1 + push this 0 + push this 2 + add + push this 1 + push constant 1 + add + call Screen.drawRectangle 4 +label Square_2 + push constant 0 + return +function Square.moveDown 0 + push argument 0 + pop pointer 0 + push this 1 + push this 2 + add + push constant 254 + lt + not + if-goto Square_3 + push constant 0 + call Screen.setColor 1 + push this 0 + push this 1 + push this 0 + push this 2 + add + push this 1 + push constant 1 + add + call Screen.drawRectangle 4 + push this 1 + push constant 2 + add + pop this 1 + push constant 1 + neg + call Screen.setColor 1 + push this 0 + push this 1 + push this 2 + add + push constant 1 + sub + push this 0 + push this 2 + add + push this 1 + push this 2 + add + call Screen.drawRectangle 4 +label Square_3 + push constant 0 + return +function Square.moveLeft 0 + push argument 0 + pop pointer 0 + push this 0 + push constant 1 + gt + not + if-goto Square_4 + push constant 0 + call Screen.setColor 1 + push this 0 + push this 2 + add + push constant 1 + sub + push this 1 + push this 0 + push this 2 + add + push this 1 + push this 2 + add + call Screen.drawRectangle 4 + push this 0 + push constant 2 + sub + pop this 0 + push constant 1 + neg + call Screen.setColor 1 + push this 0 + push this 1 + push this 0 + push constant 1 + add + push this 1 + push this 2 + add + call Screen.drawRectangle 4 +label Square_4 + push constant 0 + return +function Square.moveRight 0 + push argument 0 + pop pointer 0 + push this 0 + push this 2 + add + push constant 510 + lt + not + if-goto Square_5 + push constant 0 + call Screen.setColor 1 + push this 0 + push this 1 + push this 0 + push constant 1 + add + push this 1 + push this 2 + add + call Screen.drawRectangle 4 + push this 0 + push constant 2 + add + pop this 0 + push constant 1 + neg + call Screen.setColor 1 + push this 0 + push this 2 + add + push constant 1 + sub + push this 1 + push this 0 + push this 2 + add + push this 1 + push this 2 + add + call Screen.drawRectangle 4 +label Square_5 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Square/SquareGame.jack b/simulator/src/jack/resources/test/Square/SquareGame.jack new file mode 100644 index 00000000..fa4ce93e --- /dev/null +++ b/simulator/src/jack/resources/test/Square/SquareGame.jack @@ -0,0 +1,76 @@ +// This file is part of www.nand2tetris.org +// and the book "The Elements of Computing Systems" +// by Nisan and Schocken, MIT Press. +// File name: projects/09/Square/SquareGame.jack +/** + * Implements the Square game. + * This simple game allows the user to move a black square around + * the screen, and change the square's size during the movement. + * When the game starts, a square of 30 by 30 pixels is shown at the + * top-left corner of the screen. The user controls the square as follows. + * The 4 arrow keys are used to move the square up, down, left, and right. + * The 'z' and 'x' keys are used, respectively, to decrement and increment + * the square's size. The 'q' key is used to quit the game. + */ +class SquareGame { + field Square square; // the square of this game + field int direction; // the square's current direction: + // 0=none, 1=up, 2=down, 3=left, 4=right + + /** Constructs a new square game. */ + constructor SquareGame new() { + // The initial square is located in (0,0), has size 30, and is not moving. + let square = Square.new(0, 0, 30); + let direction = 0; + return this; + } + + /** Disposes this game. */ + method void dispose() { + do square.dispose(); + do Memory.deAlloc(this); + return; + } + + /** Moves the square in the current direction. */ + method void moveSquare() { + if (direction = 1) { do square.moveUp(); } + if (direction = 2) { do square.moveDown(); } + if (direction = 3) { do square.moveLeft(); } + if (direction = 4) { do square.moveRight(); } + do Sys.wait(5); // delays the next movement + return; + } + + /** Runs the game: handles the user's inputs and moves the square accordingly */ + method void run() { + var char key; // the key currently pressed by the user + var boolean exit; + let exit = false; + + while (~exit) { + // waits for a key to be pressed + while (key = 0) { + let key = Keyboard.keyPressed(); + do moveSquare(); + } + if (key = 81) { let exit = true; } // q key + if (key = 90) { do square.decSize(); } // z key + if (key = 88) { do square.incSize(); } // x key + if (key = 131) { let direction = 1; } // up arrow + if (key = 133) { let direction = 2; } // down arrow + if (key = 130) { let direction = 3; } // left arrow + if (key = 132) { let direction = 4; } // right arrow + + // waits for the key to be released + while (~(key = 0)) { + let key = Keyboard.keyPressed(); + do moveSquare(); + } + } // while + return; + } +} + + + diff --git a/simulator/src/jack/resources/test/Square/SquareGame.vm b/simulator/src/jack/resources/test/Square/SquareGame.vm new file mode 100644 index 00000000..fcbe7e74 --- /dev/null +++ b/simulator/src/jack/resources/test/Square/SquareGame.vm @@ -0,0 +1,157 @@ +function SquareGame.new 0 + push constant 2 + call Memory.alloc 1 + pop pointer 0 + push constant 0 + push constant 0 + push constant 30 + call Square.new 3 + pop this 0 + push constant 0 + pop this 1 + push pointer 0 + return +function SquareGame.dispose 0 + push argument 0 + pop pointer 0 + push this 0 + call Square.dispose 1 + push pointer 0 + call Memory.deAlloc 1 + push constant 0 + return +function SquareGame.moveSquare 0 + push argument 0 + pop pointer 0 + push this 1 + push constant 1 + eq + not + if-goto SquareGame_0 + push this 0 + call Square.moveUp 1 +label SquareGame_0 + push this 1 + push constant 2 + eq + not + if-goto SquareGame_1 + push this 0 + call Square.moveDown 1 +label SquareGame_1 + push this 1 + push constant 3 + eq + not + if-goto SquareGame_2 + push this 0 + call Square.moveLeft 1 +label SquareGame_2 + push this 1 + push constant 4 + eq + not + if-goto SquareGame_3 + push this 0 + call Square.moveRight 1 +label SquareGame_3 + push constant 5 + call Sys.wait 1 + push constant 0 + return +function SquareGame.run 2 + push argument 0 + pop pointer 0 + push constant 0 + pop local 1 +label SquareGame_4 + push local 1 + not + not + if-goto SquareGame_5 +label SquareGame_6 + push local 0 + push constant 0 + eq + not + if-goto SquareGame_7 + call Keyboard.keyPressed 0 + pop local 0 + push pointer 0 + call SquareGame.moveSquare 1 + goto SquareGame_6 +label SquareGame_7 + push local 0 + push constant 81 + eq + not + if-goto SquareGame_8 + push constant 1 + neg + pop local 1 +label SquareGame_8 + push local 0 + push constant 90 + eq + not + if-goto SquareGame_9 + push this 0 + call Square.decSize 1 +label SquareGame_9 + push local 0 + push constant 88 + eq + not + if-goto SquareGame_10 + push this 0 + call Square.incSize 1 +label SquareGame_10 + push local 0 + push constant 131 + eq + not + if-goto SquareGame_11 + push constant 1 + pop this 1 +label SquareGame_11 + push local 0 + push constant 133 + eq + not + if-goto SquareGame_12 + push constant 2 + pop this 1 +label SquareGame_12 + push local 0 + push constant 130 + eq + not + if-goto SquareGame_13 + push constant 3 + pop this 1 +label SquareGame_13 + push local 0 + push constant 132 + eq + not + if-goto SquareGame_14 + push constant 4 + pop this 1 +label SquareGame_14 +label SquareGame_15 + push local 0 + push constant 0 + eq + not + not + if-goto SquareGame_16 + call Keyboard.keyPressed 0 + pop local 0 + push pointer 0 + call SquareGame.moveSquare 1 + goto SquareGame_15 +label SquareGame_16 + goto SquareGame_4 +label SquareGame_5 + push constant 0 + return \ No newline at end of file diff --git a/simulator/src/jack/symbol.table.test.ts b/simulator/src/jack/symbol.table.test.ts new file mode 100644 index 00000000..97ca4b80 --- /dev/null +++ b/simulator/src/jack/symbol.table.test.ts @@ -0,0 +1,156 @@ +import { + LocalSymbolTable, + VariableSymbol, + ScopeType, + SubroutineScope, +} from "./symbol"; + +describe("LocalSymbolTable", () => { + const jestConsole = console; + + beforeEach(() => { + global.console = require("console"); + }); + + afterEach(() => { + global.console = jestConsole; + }); + + test("add", () => { + const localSymbolTable = new LocalSymbolTable(); + const symbols = [ + { + name: "a1", + type: "int", + scope: ScopeType.Local, + index: 0, + } as VariableSymbol, + { + name: "a2", + type: "char", + scope: ScopeType.Local, + index: 1, + } as VariableSymbol, + + { + name: "a3", + type: "boolean", + scope: ScopeType.Argument, + index: 0, + } as VariableSymbol, + { + name: "a4", + type: "char", + scope: ScopeType.Argument, + index: 1, + } as VariableSymbol, + + { + name: "a5", + type: "int", + scope: ScopeType.This, + index: 0, + } as VariableSymbol, + { + name: "a6", + type: "String", + scope: ScopeType.This, + index: 1, + } as VariableSymbol, + + { + name: "a7", + type: "A", + scope: ScopeType.Static, + index: 0, + } as VariableSymbol, + { + name: "a8", + type: "B", + scope: ScopeType.Static, + index: 1, + } as VariableSymbol, + ]; + for (const s of symbols) { + if (s.scope == ScopeType.Argument) { + localSymbolTable.defineArgument(s.name, s.type, false); + } else { + localSymbolTable.define(s.scope, s.name, s.type); + } + } + for (const s of symbols) { + expect(localSymbolTable.lookup(s.name)).toEqual(s); + expect(localSymbolTable.lookup(s.name + "_")).toBeUndefined(); + } + expect(localSymbolTable.fieldsCount()).toBe(2); + }); + + test("shadowing", () => { + const localSymbolTable = new LocalSymbolTable(); + const symbols = [ + { + name: "a", + type: "char", + scope: ScopeType.This, + index: 0, + } as VariableSymbol, + { + name: "a", + type: "int", + scope: ScopeType.Local, + index: 0, + } as VariableSymbol, + ]; + for (const s of symbols) { + localSymbolTable.define(s.scope, s.name, s.type); + } + expect(localSymbolTable.lookup("a")).toEqual(symbols[1]); + }); + + test("pop stack", () => { + const localSymbolTable = new LocalSymbolTable(); + const symbols = [ + { + name: "a", + type: "int", + scope: ScopeType.Local, + index: 0, + } as VariableSymbol, + ]; + for (const s of symbols) { + localSymbolTable.define(s.scope, s.name, s.type); + } + localSymbolTable.popStack(); + expect(localSymbolTable.lookup("a")).toBeUndefined(); + }); + + test("function vars", () => { + const localSymbolTable = new LocalSymbolTable(); + const symbols = [ + { + name: "a", + type: "int", + scope: ScopeType.Local, + index: 0, + } as VariableSymbol, + { + name: "b", + type: "char", + scope: ScopeType.Argument, + index: 1, + } as VariableSymbol, + ]; + + for (const s of symbols) { + if (s.scope == ScopeType.Argument) { + localSymbolTable.defineArgument(s.name, s.type, true); + } else { + localSymbolTable.define(s.scope, s.name, s.type); + } + } + expect(localSymbolTable.popStack()).toEqual({ + arguments: [symbols[1]], + locals: [symbols[0]], + } as SubroutineScope); + }); +}); diff --git a/simulator/src/jack/symbol.ts b/simulator/src/jack/symbol.ts new file mode 100644 index 00000000..b514485b --- /dev/null +++ b/simulator/src/jack/symbol.ts @@ -0,0 +1,131 @@ +/** + * Generic symbol. Can be used for both class and function symbols + */ +export enum SubroutineType { + Constructor, + Function, + Method, +} +export interface SubroutineInfo { + paramsCount: number; + type: SubroutineType; + localVarsCount?: number; +} +export type GlobalSymbolTable = Record; +/** + * Symbol that represents class or a subroutine + */ +export interface GenericSymbol { + subroutineInfo?: SubroutineInfo; +} +export function createSubroutineSymbol( + paramsCount: number, + type: SubroutineType, + localVarsCount?: number, +): GenericSymbol { + const s = { paramsCount, type } as SubroutineInfo; + if (localVarsCount != undefined) { + s.localVarsCount = localVarsCount; + } + return { subroutineInfo: s } as GenericSymbol; +} + +type VariableType = string; +export enum ScopeType { + Static, + This, + Argument, + Local, +} + +const scopeTypeToStringMap: Record = { + [ScopeType.Static]: "static", + [ScopeType.This]: "this", + [ScopeType.Argument]: "argument", + [ScopeType.Local]: "local", +}; +export function scopeTypeToString(scopeType: ScopeType): string { + if (scopeTypeToStringMap[scopeType] === undefined) { + throw new Error(`Unknown scope type: ${scopeType}`); + } + return scopeTypeToStringMap[scopeType]; +} +export type VariableSymbol = { + name: string; + type: VariableType; + scope: ScopeType; + index: number; +}; + +export type SubroutineScope = { + arguments: VariableSymbol[]; + locals: VariableSymbol[]; +}; +/** + * Symbol table that provides lookup for variables in different scopes in a file + */ +export class LocalSymbolTable { + private scopes: Record = { + [ScopeType.Static]: [], + [ScopeType.This]: [], + [ScopeType.Argument]: [], + [ScopeType.Local]: [], + }; + private static scopesLookupOrder = [ + ScopeType.Local, + ScopeType.Argument, + ScopeType.This, + ScopeType.Static, + ]; + lookup(name: string): VariableSymbol | undefined { + for (const scope of LocalSymbolTable.scopesLookupOrder) { + const symbol = this.scopes[scope].find((v) => v.name == name); + if (symbol != undefined) return symbol; + } + return undefined; + } + defineArgument(name: string, type: VariableType, inMethod: boolean) { + let index = this.scopes[ScopeType.Argument].length; + if (inMethod) { + //in a method first arg is this + index++; + } + this.scopes[ScopeType.Argument].push({ + name, + type, + scope: ScopeType.Argument, + index, + }); + } + //define symbol in scope + define(scope: ScopeType, varName: string, type: VariableType) { + if (scope == ScopeType.Argument) { + throw new Error( + "Please use defineArgument method to define function arguments", + ); + } + this.scopes[scope].push({ + name: varName, + type, + scope, + index: this.scopes[scope].length, + }); + } + + popStack() { + const f = { + arguments: this.scopes[ScopeType.Argument], + locals: this.scopes[ScopeType.Local], + } as SubroutineScope; + this.scopes[ScopeType.Local] = []; + this.scopes[ScopeType.Argument] = []; + return f; + } + setSubroutineScope(subroutineScope: SubroutineScope) { + this.scopes[ScopeType.Argument] = subroutineScope.arguments; + this.scopes[ScopeType.Local] = subroutineScope.locals; + } + fieldsCount() { + return this.scopes[ScopeType.This].length; + } +} diff --git a/simulator/src/jack/test.helper.ts b/simulator/src/jack/test.helper.ts new file mode 100644 index 00000000..e462e4bd --- /dev/null +++ b/simulator/src/jack/test.helper.ts @@ -0,0 +1,82 @@ +import fs from "fs"; +import path from "path"; +import { JackCompilerError } from "./error"; +import { CustomErrorListener } from "./listener/error.listener"; +import { + CharStreams, + CommonTokenStream, + ParseTreeListener, + ParseTreeWalker, +} from "antlr4"; +import JackLexer from "./generated/JackLexer"; +import JackParser, { ProgramContext } from "./generated/JackParser"; + +export function parseJackFile(filePath: string, trace = false) { + const errorListener: CustomErrorListener = new CustomErrorListener(); + const f = fs.readFileSync(filePath, "utf8"); + return parseJackText(f, errorListener, trace); +} + +export function parseJackText( + src: string, + errorListener?: CustomErrorListener, + trace = false, + throwOnErrors = true, +): ProgramContext { + if (errorListener === undefined) { + errorListener = new CustomErrorListener(); + } + const inputStream = CharStreams.fromString(src); + const lexer = new JackLexer(inputStream); + if (errorListener) { + lexer.removeErrorListeners(); + lexer.addErrorListener(errorListener); + } + + const tokenStream = new CommonTokenStream(lexer); + const parser = new JackParser(tokenStream); + if (errorListener != undefined) { + parser.removeErrorListeners(); + parser.addErrorListener(errorListener); + } + const tree = parser.program(); + + expect(tokenStream.tokens.length).toBeGreaterThan(0); + if (errorListener.errors.length > 0) { + console.error("Parser or lexer errors found"); + handleErrors(src, errorListener.errors); + } + return tree; +} + +export function getTestResourcePath(relativePath: string) { + return path.join(__dirname, "resources", "test", relativePath); +} + +export function listenToTheTree( + tree: ProgramContext, + listener: T, +) { + ParseTreeWalker.DEFAULT.walk(listener, tree); + return listener; +} + +export function handleErrors(src: string, errors: JackCompilerError[]) { + const msg = errors + .map((e) => { + return `${e.span.line}:${e.span.start} ${e.msg}\n${src.split("\n")[e.span.line]}`; + }) + .join("\n"); + console.error(msg); + throw new Error(msg); +} +export const testResourceDirs: string[] = [ + "Average", + "ConvertToBin", + "Fraction", + "HelloWorld", + "List", + "Pong", + "Square", + "ComplexArrays", +]; diff --git a/simulator/src/languages/grammars/JackLexer.g4 b/simulator/src/languages/grammars/JackLexer.g4 new file mode 100644 index 00000000..a2268f48 --- /dev/null +++ b/simulator/src/languages/grammars/JackLexer.g4 @@ -0,0 +1,62 @@ +lexer grammar JackLexer; + +CLASS: 'class'; +CONSTRUCTOR: 'constructor'; +FUNCTION: 'function'; +METHOD: 'method'; +FIELD: 'field'; +STATIC: 'static'; +VAR: 'var'; +INT: 'int'; +CHAR: 'char'; +BOOLEAN: 'boolean'; +VOID: 'void'; + +LET: 'let'; +DO: 'do'; +IF: 'if'; +ELSE: 'else'; +WHILE: 'while'; +RETURN: 'return'; + + +LBRACE: '{'; +RBRACE: '}'; +LPAREN: '('; +RPAREN: ')'; +LBRACKET: '['; +RBRACKET: ']'; +DOT: '.'; +COMMA: ','; +SEMICOLON: ';'; + +EQUALS: '='; +PLUS: '+'; +MINUS: '-'; +MUL: '*'; +DIV: '/'; +AND: '&'; +OR: '|'; +TILDE: '~'; +LESS_THAN: '<'; +GREATER_THAN: '>'; + +WS: [ \t\r\n]+ -> skip; +COMMENT: '/*' .*? '*/' -> skip; +LINE_COMMENT: '//' ~[\r\n]* -> skip; + +INTEGER_LITERAL: [0-9]+; +TRUE: 'true'; +FALSE: 'false'; +NULL_LITERAL: 'null'; +THIS_LITERAL: 'this'; + +IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; + +STRING_LITERAL + : UnterminatedStringLiteral '"' + ; +UnterminatedStringLiteral + : '"' ~["\\\r\n]* + ; + diff --git a/simulator/src/languages/grammars/JackParser.g4 b/simulator/src/languages/grammars/JackParser.g4 new file mode 100644 index 00000000..04b06824 --- /dev/null +++ b/simulator/src/languages/grammars/JackParser.g4 @@ -0,0 +1,99 @@ +parser grammar JackParser; + +options { + tokenVocab = JackLexer; +} +@header { + import { SubroutineScope, LocalSymbolTable } from "../symbol"; +} + +program: classDeclaration EOF; +classDeclaration + locals[localSymbolTable: LocalSymbolTable | undefined ]: + CLASS className LBRACE classVarDec* subroutineDeclaration* rBrace; +className: IDENTIFIER; +classVarDec: (STATIC | FIELD) fieldList SEMICOLON; +fieldList: varType fieldName ( COMMA fieldName)*; +fieldName: IDENTIFIER; +subroutineDeclaration + locals[symbols: SubroutineScope | undefined]: + subroutineType subroutineDecWithoutType; +subroutineType: CONSTRUCTOR | METHOD | FUNCTION; +subroutineDecWithoutType: + subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; +subroutineName: IDENTIFIER; +subroutineReturnType: varType | VOID; + +varType: INT | CHAR | BOOLEAN | IDENTIFIER; + +parameterList: (parameter (COMMA parameter)*)?; +parameter: varType parameterName; +parameterName: IDENTIFIER; +subroutineBody: LBRACE varDeclaration* statements rBrace; +rBrace: RBRACE; +varDeclaration: + VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; +varNameInDeclaration: IDENTIFIER; +varName: IDENTIFIER; +statements: statement*; +statement: + letStatement + | ifElseStatement + | whileStatement + | doStatement + | returnStatement; + +letStatement: + LET (varName | arrayAccess) equals expression SEMICOLON; +equals: EQUALS; +ifElseStatement + locals[endLabel:string=""]: ifStatement elseStatement?; +ifStatement + locals[endLabel:string=""]: + IF LPAREN ifExpression RPAREN LBRACE statements rBrace; +ifExpression: expression; +elseStatement: ELSE LBRACE statements rBrace; + +whileStatement + locals[startLabel:string="";endLabel:string="";]: + WHILE LPAREN whileExpression RPAREN LBRACE statements rBrace; +whileExpression: expression; +doStatement: DO subroutineCall SEMICOLON; + +subroutineCall: subroutineId LPAREN expressionList RPAREN; +subroutineId: ((className | THIS_LITERAL) DOT)? subroutineName; +returnStatement: RETURN expression? SEMICOLON; + +expressionList: (expression (COMMA expression)*)?; + +expression: + constant + | varName + | subroutineCall + | arrayAccess + | unaryOperation + | expression binaryOperator expression + | groupedExpression; + +groupedExpression: LPAREN expression RPAREN; +unaryOperation: unaryOperator expression; +arrayAccess: varName LBRACKET expression RBRACKET; + +constant: + INTEGER_LITERAL + | STRING_LITERAL + | booleanLiteral + | NULL_LITERAL + | THIS_LITERAL; +booleanLiteral: TRUE | FALSE; +unaryOperator: TILDE | MINUS; +binaryOperator: + PLUS + | MINUS + | MUL + | DIV + | AND + | OR + | LESS_THAN + | GREATER_THAN + | EQUALS; \ No newline at end of file From 3c1185ab26f4bf66550039e0b61e15eac948f74c Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:20:18 +0200 Subject: [PATCH 26/87] WIP --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ec425396..a850595e 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ out npm-debug.log* yarn-debug.log* yarn-error.log* -**/.vscode/numbered-bookmars.json \ No newline at end of file +**/.vscode/numbered-bookmars.json +**/.antlr \ No newline at end of file From af250f2b9a005d81b9a08bd326e84a8d26dfad9e Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:27:46 +0200 Subject: [PATCH 27/87] WIP --- compiler/.eslintconfig.json | 16 - compiler/.github/workflows/ci.yml | 26 - compiler/.gitignore | 27 - compiler/README.md | 6 - compiler/TODO.md | 3 - compiler/eslint.config.mjs | 46 - compiler/gen.sh | 13 - compiler/grammar/.antlr/JackLexer.interp | 155 - compiler/grammar/.antlr/JackLexer.java | 321 -- compiler/grammar/.antlr/JackLexer.tokens | 84 - compiler/grammar/.antlr/JackParser.interp | 142 - compiler/grammar/.antlr/JackParser.java | 2237 ----------- compiler/grammar/.antlr/JackParser.tokens | 84 - compiler/grammar/JackLexer.g4 | 61 - compiler/grammar/JackParser.g4 | 89 - compiler/index.html | 60 - compiler/jest.config.ts | 203 - compiler/package.json | 40 - compiler/pnpm-lock.yaml | 3489 ----------------- compiler/public/vite.svg | 1 - compiler/src/builtins.ts | 78 - compiler/src/compiler.ts | 49 - compiler/src/error.ts | 172 - compiler/src/generated/JackLexer.interp | 155 - compiler/src/generated/JackLexer.tokens | 84 - compiler/src/generated/JackLexer.ts | 278 -- compiler/src/generated/JackParser.interp | 142 - compiler/src/generated/JackParser.tokens | 84 - compiler/src/generated/JackParser.ts | 3283 ---------------- compiler/src/generated/JackParserListener.ts | 481 --- compiler/src/generated/JackParserVisitor.ts | 328 -- compiler/src/listener/binder.listener.ts | 78 - compiler/src/listener/error.listener.ts | 15 - compiler/src/listener/validator.listener.ts | 353 -- compiler/src/listener/vm.writer.listener.ts | 86 - compiler/src/main.ts | 18 - compiler/src/resources/JackLexer.g4 | 61 - compiler/src/resources/JackParser.g4 | 90 - compiler/src/symbol.ts | 70 - compiler/src/vite-env.d.ts | 1 - compiler/test/binder.listener.test.ts | 111 - compiler/test/compiler.test.ts | 617 --- compiler/test/local.symbol.table.test.ts | 28 - compiler/test/parser.test.ts | 57 - compiler/test/resources/Average/Main.jack | 27 - .../test/resources/ComplexArrays/Main.jack | 69 - .../test/resources/ConvertToBin/Main.jack | 79 - .../test/resources/DuplicatedSubroutine.jack | 8 - .../test/resources/Fraction/Fraction.jack | 65 - compiler/test/resources/Fraction/Main.jack | 16 - compiler/test/resources/HelloWorld/Main.jack | 14 - compiler/test/resources/List/List.jack | 48 - compiler/test/resources/List/Main.jack | 17 - compiler/test/resources/Pong/Ball.jack | 202 - compiler/test/resources/Pong/Bat.jack | 103 - compiler/test/resources/Pong/Main.jack | 18 - compiler/test/resources/Pong/PongGame.jack | 136 - compiler/test/resources/Square/Main.jack | 15 - compiler/test/resources/Square/Square.jack | 113 - .../test/resources/Square/SquareGame.jack | 76 - compiler/test/test.helper.ts | 72 - compiler/test/validator.listener.test.ts | 657 ---- compiler/tsconfig.json | 40 - simulator/src/jack/compiler.ts | 13 +- simulator/src/jack/listener/error.listener.ts | 18 +- 65 files changed, 12 insertions(+), 15616 deletions(-) delete mode 100644 compiler/.eslintconfig.json delete mode 100644 compiler/.github/workflows/ci.yml delete mode 100644 compiler/.gitignore delete mode 100644 compiler/README.md delete mode 100644 compiler/TODO.md delete mode 100644 compiler/eslint.config.mjs delete mode 100644 compiler/gen.sh delete mode 100644 compiler/grammar/.antlr/JackLexer.interp delete mode 100644 compiler/grammar/.antlr/JackLexer.java delete mode 100644 compiler/grammar/.antlr/JackLexer.tokens delete mode 100644 compiler/grammar/.antlr/JackParser.interp delete mode 100644 compiler/grammar/.antlr/JackParser.java delete mode 100644 compiler/grammar/.antlr/JackParser.tokens delete mode 100644 compiler/grammar/JackLexer.g4 delete mode 100644 compiler/grammar/JackParser.g4 delete mode 100644 compiler/index.html delete mode 100644 compiler/jest.config.ts delete mode 100644 compiler/package.json delete mode 100644 compiler/pnpm-lock.yaml delete mode 100644 compiler/public/vite.svg delete mode 100644 compiler/src/builtins.ts delete mode 100644 compiler/src/compiler.ts delete mode 100644 compiler/src/error.ts delete mode 100644 compiler/src/generated/JackLexer.interp delete mode 100644 compiler/src/generated/JackLexer.tokens delete mode 100644 compiler/src/generated/JackLexer.ts delete mode 100644 compiler/src/generated/JackParser.interp delete mode 100644 compiler/src/generated/JackParser.tokens delete mode 100644 compiler/src/generated/JackParser.ts delete mode 100644 compiler/src/generated/JackParserListener.ts delete mode 100644 compiler/src/generated/JackParserVisitor.ts delete mode 100644 compiler/src/listener/binder.listener.ts delete mode 100644 compiler/src/listener/error.listener.ts delete mode 100644 compiler/src/listener/validator.listener.ts delete mode 100644 compiler/src/listener/vm.writer.listener.ts delete mode 100644 compiler/src/main.ts delete mode 100644 compiler/src/resources/JackLexer.g4 delete mode 100644 compiler/src/resources/JackParser.g4 delete mode 100644 compiler/src/symbol.ts delete mode 100644 compiler/src/vite-env.d.ts delete mode 100644 compiler/test/binder.listener.test.ts delete mode 100644 compiler/test/compiler.test.ts delete mode 100644 compiler/test/local.symbol.table.test.ts delete mode 100644 compiler/test/parser.test.ts delete mode 100644 compiler/test/resources/Average/Main.jack delete mode 100644 compiler/test/resources/ComplexArrays/Main.jack delete mode 100644 compiler/test/resources/ConvertToBin/Main.jack delete mode 100644 compiler/test/resources/DuplicatedSubroutine.jack delete mode 100644 compiler/test/resources/Fraction/Fraction.jack delete mode 100644 compiler/test/resources/Fraction/Main.jack delete mode 100644 compiler/test/resources/HelloWorld/Main.jack delete mode 100644 compiler/test/resources/List/List.jack delete mode 100644 compiler/test/resources/List/Main.jack delete mode 100644 compiler/test/resources/Pong/Ball.jack delete mode 100644 compiler/test/resources/Pong/Bat.jack delete mode 100644 compiler/test/resources/Pong/Main.jack delete mode 100644 compiler/test/resources/Pong/PongGame.jack delete mode 100644 compiler/test/resources/Square/Main.jack delete mode 100644 compiler/test/resources/Square/Square.jack delete mode 100644 compiler/test/resources/Square/SquareGame.jack delete mode 100644 compiler/test/test.helper.ts delete mode 100644 compiler/test/validator.listener.test.ts delete mode 100644 compiler/tsconfig.json diff --git a/compiler/.eslintconfig.json b/compiler/.eslintconfig.json deleted file mode 100644 index 33b6926c..00000000 --- a/compiler/.eslintconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": [ - "react-app", - "react-app/jest" - ], - "rules": { - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - "args": "none", - "destructuredArrayIgnorePattern": "^_" - } - ] - } -} \ No newline at end of file diff --git a/compiler/.github/workflows/ci.yml b/compiler/.github/workflows/ci.yml deleted file mode 100644 index 17e9acff..00000000 --- a/compiler/.github/workflows/ci.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Tests - -on: [push] - -jobs: - build: - runs-on: ubuntu-22.04 - strategy: - matrix: - node-version: [20] - steps: - - uses: actions/checkout@v4 - - name: Install pnpm - uses: pnpm/action-setup@v4 - with: - version: 9 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - cache: 'pnpm' - - name: Install dependencies - run: pnpm install - - uses: actions/checkout@v1 - - name: Run Jest - uses: stefanoeb/jest-action@1.0.3 \ No newline at end of file diff --git a/compiler/.gitignore b/compiler/.gitignore deleted file mode 100644 index eee91674..00000000 --- a/compiler/.gitignore +++ /dev/null @@ -1,27 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? -.coverage -docs -src/resources/.antlr \ No newline at end of file diff --git a/compiler/README.md b/compiler/README.md deleted file mode 100644 index 69510622..00000000 --- a/compiler/README.md +++ /dev/null @@ -1,6 +0,0 @@ -TODO: -- add compiled code -- add symbol tbl -- add validations - - Constructor has return this - - \ No newline at end of file diff --git a/compiler/TODO.md b/compiler/TODO.md deleted file mode 100644 index 35b962d7..00000000 --- a/compiler/TODO.md +++ /dev/null @@ -1,3 +0,0 @@ -TODO: -- add error when expecting class/ function name instead of IDENTIFIER -- The class name doesn't match the file name diff --git a/compiler/eslint.config.mjs b/compiler/eslint.config.mjs deleted file mode 100644 index c29682fe..00000000 --- a/compiler/eslint.config.mjs +++ /dev/null @@ -1,46 +0,0 @@ -import typescriptEslint from "@typescript-eslint/eslint-plugin"; -import globals from "globals"; -import tsParser from "@typescript-eslint/parser"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; -import js from "@eslint/js"; -import { FlatCompat } from "@eslint/eslintrc"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all -}); - -export default [ - ...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"), - { - plugins: { - "@typescript-eslint": typescriptEslint, - }, - - languageOptions: { - globals: { - ...globals.browser, - ...globals.jest, - ...globals.node, - }, - - parser: tsParser, - ecmaVersion: "latest", - sourceType: "module", - }, - - settings: { - react: { - version: "detect", - }, - }, - - rules: { - "react/react-in-jsx-scope": 0, - }, - }, -]; \ No newline at end of file diff --git a/compiler/gen.sh b/compiler/gen.sh deleted file mode 100644 index e5784cab..00000000 --- a/compiler/gen.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -echo "Generating" -cd grammar -antlr4ts -Werror -visitor JackLexer.g4 JackParser.g4 -o ../src/generated -cd ../src/generated -sed -i -e 's/public get serializedATN(/public override get serializedATN\(/g' JackLexer.ts -sed -i -e 's/public get serializedATN(/public override get serializedATN\(/g' JackParser.ts -sed -i -e 's/public sempred(/public override sempred\(/g' JackParser.ts -sed -i -e 's/public get ruleIndex(/public override get ruleIndex\(/g' JackParser.ts -sed -i -e 's/public enterRule(/public override enterRule\(/g' JackParser.ts -sed -i -e 's/public exitRule(/public override exitRule\(/g' JackParser.ts -sed -i -e 's/public accept(/public override accept\(/g' JackParser.ts -sed -i -e 's/public copyFrom(/public override copyFrom\(/g' JackParser.ts \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackLexer.interp b/compiler/grammar/.antlr/JackLexer.interp deleted file mode 100644 index 722e32c5..00000000 --- a/compiler/grammar/.antlr/JackLexer.interp +++ /dev/null @@ -1,155 +0,0 @@ -token literal names: -null -'class' -'constructor' -'function' -'method' -'field' -'static' -'var' -'int' -'char' -'boolean' -'void' -'let' -'do' -'if' -'else' -'while' -'return' -'{' -'}' -'(' -')' -'[' -']' -'.' -',' -';' -'=' -'+' -'-' -'*' -'/' -'&' -'|' -'~' -'<' -'>' -null -null -null -null -null -'null' -'this' -null -null -null - -token symbolic names: -null -CLASS -CONSTRUCTOR -FUNCTION -METHOD -FIELD -STATIC -VAR -INT -CHAR -BOOLEAN -VOID -LET -DO -IF -ELSE -WHILE -RETURN -LBRACE -RBRACE -LPAREN -RPAREN -LBRACKET -RBRACKET -DOT -COMMA -SEMICOLON -EQUALS -PLUS -MINUS -MUL -DIV -AND -OR -TILDE -LESS_THAN -GREATER_THAN -WS -COMMENT -LINE_COMMENT -INTEGER_LITERAL -BOOLEAN_LITERAL -NULL_LITERAL -THIS_LITERAL -IDENTIFIER -STRING_LITERAL -UnterminatedStringLiteral - -rule names: -CLASS -CONSTRUCTOR -FUNCTION -METHOD -FIELD -STATIC -VAR -INT -CHAR -BOOLEAN -VOID -LET -DO -IF -ELSE -WHILE -RETURN -LBRACE -RBRACE -LPAREN -RPAREN -LBRACKET -RBRACKET -DOT -COMMA -SEMICOLON -EQUALS -PLUS -MINUS -MUL -DIV -AND -OR -TILDE -LESS_THAN -GREATER_THAN -WS -COMMENT -LINE_COMMENT -INTEGER_LITERAL -BOOLEAN_LITERAL -NULL_LITERAL -THIS_LITERAL -IDENTIFIER -STRING_LITERAL -UnterminatedStringLiteral - -channel names: -DEFAULT_TOKEN_CHANNEL -HIDDEN - -mode names: -DEFAULT_MODE - -atn: -[4, 0, 46, 307, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 4, 36, 234, 8, 36, 11, 36, 12, 36, 235, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 244, 8, 37, 10, 37, 12, 37, 247, 9, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 258, 8, 38, 10, 38, 12, 38, 261, 9, 38, 1, 38, 1, 38, 1, 39, 4, 39, 266, 8, 39, 11, 39, 12, 39, 267, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 279, 8, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 5, 43, 293, 8, 43, 10, 43, 12, 43, 296, 9, 43, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 5, 45, 303, 8, 45, 10, 45, 12, 45, 306, 9, 45, 1, 245, 0, 46, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 1, 0, 6, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 313, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 1, 93, 1, 0, 0, 0, 3, 99, 1, 0, 0, 0, 5, 111, 1, 0, 0, 0, 7, 120, 1, 0, 0, 0, 9, 127, 1, 0, 0, 0, 11, 133, 1, 0, 0, 0, 13, 140, 1, 0, 0, 0, 15, 144, 1, 0, 0, 0, 17, 148, 1, 0, 0, 0, 19, 153, 1, 0, 0, 0, 21, 161, 1, 0, 0, 0, 23, 166, 1, 0, 0, 0, 25, 170, 1, 0, 0, 0, 27, 173, 1, 0, 0, 0, 29, 176, 1, 0, 0, 0, 31, 181, 1, 0, 0, 0, 33, 187, 1, 0, 0, 0, 35, 194, 1, 0, 0, 0, 37, 196, 1, 0, 0, 0, 39, 198, 1, 0, 0, 0, 41, 200, 1, 0, 0, 0, 43, 202, 1, 0, 0, 0, 45, 204, 1, 0, 0, 0, 47, 206, 1, 0, 0, 0, 49, 208, 1, 0, 0, 0, 51, 210, 1, 0, 0, 0, 53, 212, 1, 0, 0, 0, 55, 214, 1, 0, 0, 0, 57, 216, 1, 0, 0, 0, 59, 218, 1, 0, 0, 0, 61, 220, 1, 0, 0, 0, 63, 222, 1, 0, 0, 0, 65, 224, 1, 0, 0, 0, 67, 226, 1, 0, 0, 0, 69, 228, 1, 0, 0, 0, 71, 230, 1, 0, 0, 0, 73, 233, 1, 0, 0, 0, 75, 239, 1, 0, 0, 0, 77, 253, 1, 0, 0, 0, 79, 265, 1, 0, 0, 0, 81, 278, 1, 0, 0, 0, 83, 280, 1, 0, 0, 0, 85, 285, 1, 0, 0, 0, 87, 290, 1, 0, 0, 0, 89, 297, 1, 0, 0, 0, 91, 300, 1, 0, 0, 0, 93, 94, 5, 99, 0, 0, 94, 95, 5, 108, 0, 0, 95, 96, 5, 97, 0, 0, 96, 97, 5, 115, 0, 0, 97, 98, 5, 115, 0, 0, 98, 2, 1, 0, 0, 0, 99, 100, 5, 99, 0, 0, 100, 101, 5, 111, 0, 0, 101, 102, 5, 110, 0, 0, 102, 103, 5, 115, 0, 0, 103, 104, 5, 116, 0, 0, 104, 105, 5, 114, 0, 0, 105, 106, 5, 117, 0, 0, 106, 107, 5, 99, 0, 0, 107, 108, 5, 116, 0, 0, 108, 109, 5, 111, 0, 0, 109, 110, 5, 114, 0, 0, 110, 4, 1, 0, 0, 0, 111, 112, 5, 102, 0, 0, 112, 113, 5, 117, 0, 0, 113, 114, 5, 110, 0, 0, 114, 115, 5, 99, 0, 0, 115, 116, 5, 116, 0, 0, 116, 117, 5, 105, 0, 0, 117, 118, 5, 111, 0, 0, 118, 119, 5, 110, 0, 0, 119, 6, 1, 0, 0, 0, 120, 121, 5, 109, 0, 0, 121, 122, 5, 101, 0, 0, 122, 123, 5, 116, 0, 0, 123, 124, 5, 104, 0, 0, 124, 125, 5, 111, 0, 0, 125, 126, 5, 100, 0, 0, 126, 8, 1, 0, 0, 0, 127, 128, 5, 102, 0, 0, 128, 129, 5, 105, 0, 0, 129, 130, 5, 101, 0, 0, 130, 131, 5, 108, 0, 0, 131, 132, 5, 100, 0, 0, 132, 10, 1, 0, 0, 0, 133, 134, 5, 115, 0, 0, 134, 135, 5, 116, 0, 0, 135, 136, 5, 97, 0, 0, 136, 137, 5, 116, 0, 0, 137, 138, 5, 105, 0, 0, 138, 139, 5, 99, 0, 0, 139, 12, 1, 0, 0, 0, 140, 141, 5, 118, 0, 0, 141, 142, 5, 97, 0, 0, 142, 143, 5, 114, 0, 0, 143, 14, 1, 0, 0, 0, 144, 145, 5, 105, 0, 0, 145, 146, 5, 110, 0, 0, 146, 147, 5, 116, 0, 0, 147, 16, 1, 0, 0, 0, 148, 149, 5, 99, 0, 0, 149, 150, 5, 104, 0, 0, 150, 151, 5, 97, 0, 0, 151, 152, 5, 114, 0, 0, 152, 18, 1, 0, 0, 0, 153, 154, 5, 98, 0, 0, 154, 155, 5, 111, 0, 0, 155, 156, 5, 111, 0, 0, 156, 157, 5, 108, 0, 0, 157, 158, 5, 101, 0, 0, 158, 159, 5, 97, 0, 0, 159, 160, 5, 110, 0, 0, 160, 20, 1, 0, 0, 0, 161, 162, 5, 118, 0, 0, 162, 163, 5, 111, 0, 0, 163, 164, 5, 105, 0, 0, 164, 165, 5, 100, 0, 0, 165, 22, 1, 0, 0, 0, 166, 167, 5, 108, 0, 0, 167, 168, 5, 101, 0, 0, 168, 169, 5, 116, 0, 0, 169, 24, 1, 0, 0, 0, 170, 171, 5, 100, 0, 0, 171, 172, 5, 111, 0, 0, 172, 26, 1, 0, 0, 0, 173, 174, 5, 105, 0, 0, 174, 175, 5, 102, 0, 0, 175, 28, 1, 0, 0, 0, 176, 177, 5, 101, 0, 0, 177, 178, 5, 108, 0, 0, 178, 179, 5, 115, 0, 0, 179, 180, 5, 101, 0, 0, 180, 30, 1, 0, 0, 0, 181, 182, 5, 119, 0, 0, 182, 183, 5, 104, 0, 0, 183, 184, 5, 105, 0, 0, 184, 185, 5, 108, 0, 0, 185, 186, 5, 101, 0, 0, 186, 32, 1, 0, 0, 0, 187, 188, 5, 114, 0, 0, 188, 189, 5, 101, 0, 0, 189, 190, 5, 116, 0, 0, 190, 191, 5, 117, 0, 0, 191, 192, 5, 114, 0, 0, 192, 193, 5, 110, 0, 0, 193, 34, 1, 0, 0, 0, 194, 195, 5, 123, 0, 0, 195, 36, 1, 0, 0, 0, 196, 197, 5, 125, 0, 0, 197, 38, 1, 0, 0, 0, 198, 199, 5, 40, 0, 0, 199, 40, 1, 0, 0, 0, 200, 201, 5, 41, 0, 0, 201, 42, 1, 0, 0, 0, 202, 203, 5, 91, 0, 0, 203, 44, 1, 0, 0, 0, 204, 205, 5, 93, 0, 0, 205, 46, 1, 0, 0, 0, 206, 207, 5, 46, 0, 0, 207, 48, 1, 0, 0, 0, 208, 209, 5, 44, 0, 0, 209, 50, 1, 0, 0, 0, 210, 211, 5, 59, 0, 0, 211, 52, 1, 0, 0, 0, 212, 213, 5, 61, 0, 0, 213, 54, 1, 0, 0, 0, 214, 215, 5, 43, 0, 0, 215, 56, 1, 0, 0, 0, 216, 217, 5, 45, 0, 0, 217, 58, 1, 0, 0, 0, 218, 219, 5, 42, 0, 0, 219, 60, 1, 0, 0, 0, 220, 221, 5, 47, 0, 0, 221, 62, 1, 0, 0, 0, 222, 223, 5, 38, 0, 0, 223, 64, 1, 0, 0, 0, 224, 225, 5, 124, 0, 0, 225, 66, 1, 0, 0, 0, 226, 227, 5, 126, 0, 0, 227, 68, 1, 0, 0, 0, 228, 229, 5, 60, 0, 0, 229, 70, 1, 0, 0, 0, 230, 231, 5, 62, 0, 0, 231, 72, 1, 0, 0, 0, 232, 234, 7, 0, 0, 0, 233, 232, 1, 0, 0, 0, 234, 235, 1, 0, 0, 0, 235, 233, 1, 0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, 6, 36, 0, 0, 238, 74, 1, 0, 0, 0, 239, 240, 5, 47, 0, 0, 240, 241, 5, 42, 0, 0, 241, 245, 1, 0, 0, 0, 242, 244, 9, 0, 0, 0, 243, 242, 1, 0, 0, 0, 244, 247, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 246, 248, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 249, 5, 42, 0, 0, 249, 250, 5, 47, 0, 0, 250, 251, 1, 0, 0, 0, 251, 252, 6, 37, 0, 0, 252, 76, 1, 0, 0, 0, 253, 254, 5, 47, 0, 0, 254, 255, 5, 47, 0, 0, 255, 259, 1, 0, 0, 0, 256, 258, 8, 1, 0, 0, 257, 256, 1, 0, 0, 0, 258, 261, 1, 0, 0, 0, 259, 257, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 262, 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 262, 263, 6, 38, 0, 0, 263, 78, 1, 0, 0, 0, 264, 266, 7, 2, 0, 0, 265, 264, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 267, 268, 1, 0, 0, 0, 268, 80, 1, 0, 0, 0, 269, 270, 5, 116, 0, 0, 270, 271, 5, 114, 0, 0, 271, 272, 5, 117, 0, 0, 272, 279, 5, 101, 0, 0, 273, 274, 5, 102, 0, 0, 274, 275, 5, 97, 0, 0, 275, 276, 5, 108, 0, 0, 276, 277, 5, 115, 0, 0, 277, 279, 5, 101, 0, 0, 278, 269, 1, 0, 0, 0, 278, 273, 1, 0, 0, 0, 279, 82, 1, 0, 0, 0, 280, 281, 5, 110, 0, 0, 281, 282, 5, 117, 0, 0, 282, 283, 5, 108, 0, 0, 283, 284, 5, 108, 0, 0, 284, 84, 1, 0, 0, 0, 285, 286, 5, 116, 0, 0, 286, 287, 5, 104, 0, 0, 287, 288, 5, 105, 0, 0, 288, 289, 5, 115, 0, 0, 289, 86, 1, 0, 0, 0, 290, 294, 7, 3, 0, 0, 291, 293, 7, 4, 0, 0, 292, 291, 1, 0, 0, 0, 293, 296, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, 294, 295, 1, 0, 0, 0, 295, 88, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 297, 298, 3, 91, 45, 0, 298, 299, 5, 34, 0, 0, 299, 90, 1, 0, 0, 0, 300, 304, 5, 34, 0, 0, 301, 303, 8, 5, 0, 0, 302, 301, 1, 0, 0, 0, 303, 306, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 92, 1, 0, 0, 0, 306, 304, 1, 0, 0, 0, 8, 0, 235, 245, 259, 267, 278, 294, 304, 1, 6, 0, 0] \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackLexer.java b/compiler/grammar/.antlr/JackLexer.java deleted file mode 100644 index 6a4699be..00000000 --- a/compiler/grammar/.antlr/JackLexer.java +++ /dev/null @@ -1,321 +0,0 @@ -// Generated from /home/babkamen/git/nand2tetris/tools/web-ide/compiler/grammar/JackLexer.g4 by ANTLR 4.13.1 -import org.antlr.v4.runtime.Lexer; -import org.antlr.v4.runtime.CharStream; -import org.antlr.v4.runtime.Token; -import org.antlr.v4.runtime.TokenStream; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.misc.*; - -@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"}) -public class JackLexer extends Lexer { - static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); } - - protected static final DFA[] _decisionToDFA; - protected static final PredictionContextCache _sharedContextCache = - new PredictionContextCache(); - public static final int - CLASS=1, CONSTRUCTOR=2, FUNCTION=3, METHOD=4, FIELD=5, STATIC=6, VAR=7, - INT=8, CHAR=9, BOOLEAN=10, VOID=11, LET=12, DO=13, IF=14, ELSE=15, WHILE=16, - RETURN=17, LBRACE=18, RBRACE=19, LPAREN=20, RPAREN=21, LBRACKET=22, RBRACKET=23, - DOT=24, COMMA=25, SEMICOLON=26, EQUALS=27, PLUS=28, MINUS=29, MUL=30, - DIV=31, AND=32, OR=33, TILDE=34, LESS_THAN=35, GREATER_THAN=36, WS=37, - COMMENT=38, LINE_COMMENT=39, INTEGER_LITERAL=40, BOOLEAN_LITERAL=41, NULL_LITERAL=42, - THIS_LITERAL=43, IDENTIFIER=44, STRING_LITERAL=45, UnterminatedStringLiteral=46; - public static String[] channelNames = { - "DEFAULT_TOKEN_CHANNEL", "HIDDEN" - }; - - public static String[] modeNames = { - "DEFAULT_MODE" - }; - - private static String[] makeRuleNames() { - return new String[] { - "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", "VAR", - "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", - "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", - "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", - "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", - "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", - "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral" - }; - } - public static final String[] ruleNames = makeRuleNames(); - - private static String[] makeLiteralNames() { - return new String[] { - null, "'class'", "'constructor'", "'function'", "'method'", "'field'", - "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", - "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", - "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", - "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", null, null, null, null, null, - "'null'", "'this'" - }; - } - private static final String[] _LITERAL_NAMES = makeLiteralNames(); - private static String[] makeSymbolicNames() { - return new String[] { - null, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", - "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", - "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", - "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", - "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", - "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", - "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral" - }; - } - private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); - public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); - - /** - * @deprecated Use {@link #VOCABULARY} instead. - */ - @Deprecated - public static final String[] tokenNames; - static { - tokenNames = new String[_SYMBOLIC_NAMES.length]; - for (int i = 0; i < tokenNames.length; i++) { - tokenNames[i] = VOCABULARY.getLiteralName(i); - if (tokenNames[i] == null) { - tokenNames[i] = VOCABULARY.getSymbolicName(i); - } - - if (tokenNames[i] == null) { - tokenNames[i] = ""; - } - } - } - - @Override - @Deprecated - public String[] getTokenNames() { - return tokenNames; - } - - @Override - - public Vocabulary getVocabulary() { - return VOCABULARY; - } - - - public JackLexer(CharStream input) { - super(input); - _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); - } - - @Override - public String getGrammarFileName() { return "JackLexer.g4"; } - - @Override - public String[] getRuleNames() { return ruleNames; } - - @Override - public String getSerializedATN() { return _serializedATN; } - - @Override - public String[] getChannelNames() { return channelNames; } - - @Override - public String[] getModeNames() { return modeNames; } - - @Override - public ATN getATN() { return _ATN; } - - public static final String _serializedATN = - "\u0004\u0000.\u0133\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001"+ - "\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004"+ - "\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007"+ - "\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b"+ - "\u0007\u000b\u0002\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e\u0002"+ - "\u000f\u0007\u000f\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011\u0002"+ - "\u0012\u0007\u0012\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014\u0002"+ - "\u0015\u0007\u0015\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017\u0002"+ - "\u0018\u0007\u0018\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a\u0002"+ - "\u001b\u0007\u001b\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d\u0002"+ - "\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007"+ - "!\u0002\"\u0007\"\u0002#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007"+ - "&\u0002\'\u0007\'\u0002(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002+\u0007"+ - "+\u0002,\u0007,\u0002-\u0007-\u0001\u0000\u0001\u0000\u0001\u0000\u0001"+ - "\u0000\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001"+ - "\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001"+ - "\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001"+ - "\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001"+ - "\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0004\u0001"+ - "\u0004\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001\u0005\u0001"+ - "\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0006\u0001"+ - "\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001"+ - "\b\u0001\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+ - "\t\u0001\n\u0001\n\u0001\n\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001"+ - "\u000b\u0001\u000b\u0001\f\u0001\f\u0001\f\u0001\r\u0001\r\u0001\r\u0001"+ - "\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000f\u0001"+ - "\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001"+ - "\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0001"+ - "\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001"+ - "\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001"+ - "\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001"+ - "\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001"+ - "\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001f\u0001\u001f\u0001"+ - " \u0001 \u0001!\u0001!\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0004$\u00ea"+ - "\b$\u000b$\f$\u00eb\u0001$\u0001$\u0001%\u0001%\u0001%\u0001%\u0005%\u00f4"+ - "\b%\n%\f%\u00f7\t%\u0001%\u0001%\u0001%\u0001%\u0001%\u0001&\u0001&\u0001"+ - "&\u0001&\u0005&\u0102\b&\n&\f&\u0105\t&\u0001&\u0001&\u0001\'\u0004\'"+ - "\u010a\b\'\u000b\'\f\'\u010b\u0001(\u0001(\u0001(\u0001(\u0001(\u0001"+ - "(\u0001(\u0001(\u0001(\u0003(\u0117\b(\u0001)\u0001)\u0001)\u0001)\u0001"+ - ")\u0001*\u0001*\u0001*\u0001*\u0001*\u0001+\u0001+\u0005+\u0125\b+\n+"+ - "\f+\u0128\t+\u0001,\u0001,\u0001,\u0001-\u0001-\u0005-\u012f\b-\n-\f-"+ - "\u0132\t-\u0001\u00f5\u0000.\u0001\u0001\u0003\u0002\u0005\u0003\u0007"+ - "\u0004\t\u0005\u000b\u0006\r\u0007\u000f\b\u0011\t\u0013\n\u0015\u000b"+ - "\u0017\f\u0019\r\u001b\u000e\u001d\u000f\u001f\u0010!\u0011#\u0012%\u0013"+ - "\'\u0014)\u0015+\u0016-\u0017/\u00181\u00193\u001a5\u001b7\u001c9\u001d"+ - ";\u001e=\u001f? A!C\"E#G$I%K&M\'O(Q)S*U+W,Y-[.\u0001\u0000\u0006\u0003"+ - "\u0000\t\n\r\r \u0002\u0000\n\n\r\r\u0001\u000009\u0003\u0000AZ__az\u0004"+ - "\u000009AZ__az\u0004\u0000\n\n\r\r\"\"\\\\\u0139\u0000\u0001\u0001\u0000"+ - "\u0000\u0000\u0000\u0003\u0001\u0000\u0000\u0000\u0000\u0005\u0001\u0000"+ - "\u0000\u0000\u0000\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001\u0000\u0000"+ - "\u0000\u0000\u000b\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000\u0000\u0000"+ - "\u0000\u000f\u0001\u0000\u0000\u0000\u0000\u0011\u0001\u0000\u0000\u0000"+ - "\u0000\u0013\u0001\u0000\u0000\u0000\u0000\u0015\u0001\u0000\u0000\u0000"+ - "\u0000\u0017\u0001\u0000\u0000\u0000\u0000\u0019\u0001\u0000\u0000\u0000"+ - "\u0000\u001b\u0001\u0000\u0000\u0000\u0000\u001d\u0001\u0000\u0000\u0000"+ - "\u0000\u001f\u0001\u0000\u0000\u0000\u0000!\u0001\u0000\u0000\u0000\u0000"+ - "#\u0001\u0000\u0000\u0000\u0000%\u0001\u0000\u0000\u0000\u0000\'\u0001"+ - "\u0000\u0000\u0000\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001\u0000\u0000"+ - "\u0000\u0000-\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000\u0000\u0000"+ - "1\u0001\u0000\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u00005\u0001"+ - "\u0000\u0000\u0000\u00007\u0001\u0000\u0000\u0000\u00009\u0001\u0000\u0000"+ - "\u0000\u0000;\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000\u0000\u0000"+ - "?\u0001\u0000\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000C\u0001"+ - "\u0000\u0000\u0000\u0000E\u0001\u0000\u0000\u0000\u0000G\u0001\u0000\u0000"+ - "\u0000\u0000I\u0001\u0000\u0000\u0000\u0000K\u0001\u0000\u0000\u0000\u0000"+ - "M\u0001\u0000\u0000\u0000\u0000O\u0001\u0000\u0000\u0000\u0000Q\u0001"+ - "\u0000\u0000\u0000\u0000S\u0001\u0000\u0000\u0000\u0000U\u0001\u0000\u0000"+ - "\u0000\u0000W\u0001\u0000\u0000\u0000\u0000Y\u0001\u0000\u0000\u0000\u0000"+ - "[\u0001\u0000\u0000\u0000\u0001]\u0001\u0000\u0000\u0000\u0003c\u0001"+ - "\u0000\u0000\u0000\u0005o\u0001\u0000\u0000\u0000\u0007x\u0001\u0000\u0000"+ - "\u0000\t\u007f\u0001\u0000\u0000\u0000\u000b\u0085\u0001\u0000\u0000\u0000"+ - "\r\u008c\u0001\u0000\u0000\u0000\u000f\u0090\u0001\u0000\u0000\u0000\u0011"+ - "\u0094\u0001\u0000\u0000\u0000\u0013\u0099\u0001\u0000\u0000\u0000\u0015"+ - "\u00a1\u0001\u0000\u0000\u0000\u0017\u00a6\u0001\u0000\u0000\u0000\u0019"+ - "\u00aa\u0001\u0000\u0000\u0000\u001b\u00ad\u0001\u0000\u0000\u0000\u001d"+ - "\u00b0\u0001\u0000\u0000\u0000\u001f\u00b5\u0001\u0000\u0000\u0000!\u00bb"+ - "\u0001\u0000\u0000\u0000#\u00c2\u0001\u0000\u0000\u0000%\u00c4\u0001\u0000"+ - "\u0000\u0000\'\u00c6\u0001\u0000\u0000\u0000)\u00c8\u0001\u0000\u0000"+ - "\u0000+\u00ca\u0001\u0000\u0000\u0000-\u00cc\u0001\u0000\u0000\u0000/"+ - "\u00ce\u0001\u0000\u0000\u00001\u00d0\u0001\u0000\u0000\u00003\u00d2\u0001"+ - "\u0000\u0000\u00005\u00d4\u0001\u0000\u0000\u00007\u00d6\u0001\u0000\u0000"+ - "\u00009\u00d8\u0001\u0000\u0000\u0000;\u00da\u0001\u0000\u0000\u0000="+ - "\u00dc\u0001\u0000\u0000\u0000?\u00de\u0001\u0000\u0000\u0000A\u00e0\u0001"+ - "\u0000\u0000\u0000C\u00e2\u0001\u0000\u0000\u0000E\u00e4\u0001\u0000\u0000"+ - "\u0000G\u00e6\u0001\u0000\u0000\u0000I\u00e9\u0001\u0000\u0000\u0000K"+ - "\u00ef\u0001\u0000\u0000\u0000M\u00fd\u0001\u0000\u0000\u0000O\u0109\u0001"+ - "\u0000\u0000\u0000Q\u0116\u0001\u0000\u0000\u0000S\u0118\u0001\u0000\u0000"+ - "\u0000U\u011d\u0001\u0000\u0000\u0000W\u0122\u0001\u0000\u0000\u0000Y"+ - "\u0129\u0001\u0000\u0000\u0000[\u012c\u0001\u0000\u0000\u0000]^\u0005"+ - "c\u0000\u0000^_\u0005l\u0000\u0000_`\u0005a\u0000\u0000`a\u0005s\u0000"+ - "\u0000ab\u0005s\u0000\u0000b\u0002\u0001\u0000\u0000\u0000cd\u0005c\u0000"+ - "\u0000de\u0005o\u0000\u0000ef\u0005n\u0000\u0000fg\u0005s\u0000\u0000"+ - "gh\u0005t\u0000\u0000hi\u0005r\u0000\u0000ij\u0005u\u0000\u0000jk\u0005"+ - "c\u0000\u0000kl\u0005t\u0000\u0000lm\u0005o\u0000\u0000mn\u0005r\u0000"+ - "\u0000n\u0004\u0001\u0000\u0000\u0000op\u0005f\u0000\u0000pq\u0005u\u0000"+ - "\u0000qr\u0005n\u0000\u0000rs\u0005c\u0000\u0000st\u0005t\u0000\u0000"+ - "tu\u0005i\u0000\u0000uv\u0005o\u0000\u0000vw\u0005n\u0000\u0000w\u0006"+ - "\u0001\u0000\u0000\u0000xy\u0005m\u0000\u0000yz\u0005e\u0000\u0000z{\u0005"+ - "t\u0000\u0000{|\u0005h\u0000\u0000|}\u0005o\u0000\u0000}~\u0005d\u0000"+ - "\u0000~\b\u0001\u0000\u0000\u0000\u007f\u0080\u0005f\u0000\u0000\u0080"+ - "\u0081\u0005i\u0000\u0000\u0081\u0082\u0005e\u0000\u0000\u0082\u0083\u0005"+ - "l\u0000\u0000\u0083\u0084\u0005d\u0000\u0000\u0084\n\u0001\u0000\u0000"+ - "\u0000\u0085\u0086\u0005s\u0000\u0000\u0086\u0087\u0005t\u0000\u0000\u0087"+ - "\u0088\u0005a\u0000\u0000\u0088\u0089\u0005t\u0000\u0000\u0089\u008a\u0005"+ - "i\u0000\u0000\u008a\u008b\u0005c\u0000\u0000\u008b\f\u0001\u0000\u0000"+ - "\u0000\u008c\u008d\u0005v\u0000\u0000\u008d\u008e\u0005a\u0000\u0000\u008e"+ - "\u008f\u0005r\u0000\u0000\u008f\u000e\u0001\u0000\u0000\u0000\u0090\u0091"+ - "\u0005i\u0000\u0000\u0091\u0092\u0005n\u0000\u0000\u0092\u0093\u0005t"+ - "\u0000\u0000\u0093\u0010\u0001\u0000\u0000\u0000\u0094\u0095\u0005c\u0000"+ - "\u0000\u0095\u0096\u0005h\u0000\u0000\u0096\u0097\u0005a\u0000\u0000\u0097"+ - "\u0098\u0005r\u0000\u0000\u0098\u0012\u0001\u0000\u0000\u0000\u0099\u009a"+ - "\u0005b\u0000\u0000\u009a\u009b\u0005o\u0000\u0000\u009b\u009c\u0005o"+ - "\u0000\u0000\u009c\u009d\u0005l\u0000\u0000\u009d\u009e\u0005e\u0000\u0000"+ - "\u009e\u009f\u0005a\u0000\u0000\u009f\u00a0\u0005n\u0000\u0000\u00a0\u0014"+ - "\u0001\u0000\u0000\u0000\u00a1\u00a2\u0005v\u0000\u0000\u00a2\u00a3\u0005"+ - "o\u0000\u0000\u00a3\u00a4\u0005i\u0000\u0000\u00a4\u00a5\u0005d\u0000"+ - "\u0000\u00a5\u0016\u0001\u0000\u0000\u0000\u00a6\u00a7\u0005l\u0000\u0000"+ - "\u00a7\u00a8\u0005e\u0000\u0000\u00a8\u00a9\u0005t\u0000\u0000\u00a9\u0018"+ - "\u0001\u0000\u0000\u0000\u00aa\u00ab\u0005d\u0000\u0000\u00ab\u00ac\u0005"+ - "o\u0000\u0000\u00ac\u001a\u0001\u0000\u0000\u0000\u00ad\u00ae\u0005i\u0000"+ - "\u0000\u00ae\u00af\u0005f\u0000\u0000\u00af\u001c\u0001\u0000\u0000\u0000"+ - "\u00b0\u00b1\u0005e\u0000\u0000\u00b1\u00b2\u0005l\u0000\u0000\u00b2\u00b3"+ - "\u0005s\u0000\u0000\u00b3\u00b4\u0005e\u0000\u0000\u00b4\u001e\u0001\u0000"+ - "\u0000\u0000\u00b5\u00b6\u0005w\u0000\u0000\u00b6\u00b7\u0005h\u0000\u0000"+ - "\u00b7\u00b8\u0005i\u0000\u0000\u00b8\u00b9\u0005l\u0000\u0000\u00b9\u00ba"+ - "\u0005e\u0000\u0000\u00ba \u0001\u0000\u0000\u0000\u00bb\u00bc\u0005r"+ - "\u0000\u0000\u00bc\u00bd\u0005e\u0000\u0000\u00bd\u00be\u0005t\u0000\u0000"+ - "\u00be\u00bf\u0005u\u0000\u0000\u00bf\u00c0\u0005r\u0000\u0000\u00c0\u00c1"+ - "\u0005n\u0000\u0000\u00c1\"\u0001\u0000\u0000\u0000\u00c2\u00c3\u0005"+ - "{\u0000\u0000\u00c3$\u0001\u0000\u0000\u0000\u00c4\u00c5\u0005}\u0000"+ - "\u0000\u00c5&\u0001\u0000\u0000\u0000\u00c6\u00c7\u0005(\u0000\u0000\u00c7"+ - "(\u0001\u0000\u0000\u0000\u00c8\u00c9\u0005)\u0000\u0000\u00c9*\u0001"+ - "\u0000\u0000\u0000\u00ca\u00cb\u0005[\u0000\u0000\u00cb,\u0001\u0000\u0000"+ - "\u0000\u00cc\u00cd\u0005]\u0000\u0000\u00cd.\u0001\u0000\u0000\u0000\u00ce"+ - "\u00cf\u0005.\u0000\u0000\u00cf0\u0001\u0000\u0000\u0000\u00d0\u00d1\u0005"+ - ",\u0000\u0000\u00d12\u0001\u0000\u0000\u0000\u00d2\u00d3\u0005;\u0000"+ - "\u0000\u00d34\u0001\u0000\u0000\u0000\u00d4\u00d5\u0005=\u0000\u0000\u00d5"+ - "6\u0001\u0000\u0000\u0000\u00d6\u00d7\u0005+\u0000\u0000\u00d78\u0001"+ - "\u0000\u0000\u0000\u00d8\u00d9\u0005-\u0000\u0000\u00d9:\u0001\u0000\u0000"+ - "\u0000\u00da\u00db\u0005*\u0000\u0000\u00db<\u0001\u0000\u0000\u0000\u00dc"+ - "\u00dd\u0005/\u0000\u0000\u00dd>\u0001\u0000\u0000\u0000\u00de\u00df\u0005"+ - "&\u0000\u0000\u00df@\u0001\u0000\u0000\u0000\u00e0\u00e1\u0005|\u0000"+ - "\u0000\u00e1B\u0001\u0000\u0000\u0000\u00e2\u00e3\u0005~\u0000\u0000\u00e3"+ - "D\u0001\u0000\u0000\u0000\u00e4\u00e5\u0005<\u0000\u0000\u00e5F\u0001"+ - "\u0000\u0000\u0000\u00e6\u00e7\u0005>\u0000\u0000\u00e7H\u0001\u0000\u0000"+ - "\u0000\u00e8\u00ea\u0007\u0000\u0000\u0000\u00e9\u00e8\u0001\u0000\u0000"+ - "\u0000\u00ea\u00eb\u0001\u0000\u0000\u0000\u00eb\u00e9\u0001\u0000\u0000"+ - "\u0000\u00eb\u00ec\u0001\u0000\u0000\u0000\u00ec\u00ed\u0001\u0000\u0000"+ - "\u0000\u00ed\u00ee\u0006$\u0000\u0000\u00eeJ\u0001\u0000\u0000\u0000\u00ef"+ - "\u00f0\u0005/\u0000\u0000\u00f0\u00f1\u0005*\u0000\u0000\u00f1\u00f5\u0001"+ - "\u0000\u0000\u0000\u00f2\u00f4\t\u0000\u0000\u0000\u00f3\u00f2\u0001\u0000"+ - "\u0000\u0000\u00f4\u00f7\u0001\u0000\u0000\u0000\u00f5\u00f6\u0001\u0000"+ - "\u0000\u0000\u00f5\u00f3\u0001\u0000\u0000\u0000\u00f6\u00f8\u0001\u0000"+ - "\u0000\u0000\u00f7\u00f5\u0001\u0000\u0000\u0000\u00f8\u00f9\u0005*\u0000"+ - "\u0000\u00f9\u00fa\u0005/\u0000\u0000\u00fa\u00fb\u0001\u0000\u0000\u0000"+ - "\u00fb\u00fc\u0006%\u0000\u0000\u00fcL\u0001\u0000\u0000\u0000\u00fd\u00fe"+ - "\u0005/\u0000\u0000\u00fe\u00ff\u0005/\u0000\u0000\u00ff\u0103\u0001\u0000"+ - "\u0000\u0000\u0100\u0102\b\u0001\u0000\u0000\u0101\u0100\u0001\u0000\u0000"+ - "\u0000\u0102\u0105\u0001\u0000\u0000\u0000\u0103\u0101\u0001\u0000\u0000"+ - "\u0000\u0103\u0104\u0001\u0000\u0000\u0000\u0104\u0106\u0001\u0000\u0000"+ - "\u0000\u0105\u0103\u0001\u0000\u0000\u0000\u0106\u0107\u0006&\u0000\u0000"+ - "\u0107N\u0001\u0000\u0000\u0000\u0108\u010a\u0007\u0002\u0000\u0000\u0109"+ - "\u0108\u0001\u0000\u0000\u0000\u010a\u010b\u0001\u0000\u0000\u0000\u010b"+ - "\u0109\u0001\u0000\u0000\u0000\u010b\u010c\u0001\u0000\u0000\u0000\u010c"+ - "P\u0001\u0000\u0000\u0000\u010d\u010e\u0005t\u0000\u0000\u010e\u010f\u0005"+ - "r\u0000\u0000\u010f\u0110\u0005u\u0000\u0000\u0110\u0117\u0005e\u0000"+ - "\u0000\u0111\u0112\u0005f\u0000\u0000\u0112\u0113\u0005a\u0000\u0000\u0113"+ - "\u0114\u0005l\u0000\u0000\u0114\u0115\u0005s\u0000\u0000\u0115\u0117\u0005"+ - "e\u0000\u0000\u0116\u010d\u0001\u0000\u0000\u0000\u0116\u0111\u0001\u0000"+ - "\u0000\u0000\u0117R\u0001\u0000\u0000\u0000\u0118\u0119\u0005n\u0000\u0000"+ - "\u0119\u011a\u0005u\u0000\u0000\u011a\u011b\u0005l\u0000\u0000\u011b\u011c"+ - "\u0005l\u0000\u0000\u011cT\u0001\u0000\u0000\u0000\u011d\u011e\u0005t"+ - "\u0000\u0000\u011e\u011f\u0005h\u0000\u0000\u011f\u0120\u0005i\u0000\u0000"+ - "\u0120\u0121\u0005s\u0000\u0000\u0121V\u0001\u0000\u0000\u0000\u0122\u0126"+ - "\u0007\u0003\u0000\u0000\u0123\u0125\u0007\u0004\u0000\u0000\u0124\u0123"+ - "\u0001\u0000\u0000\u0000\u0125\u0128\u0001\u0000\u0000\u0000\u0126\u0124"+ - "\u0001\u0000\u0000\u0000\u0126\u0127\u0001\u0000\u0000\u0000\u0127X\u0001"+ - "\u0000\u0000\u0000\u0128\u0126\u0001\u0000\u0000\u0000\u0129\u012a\u0003"+ - "[-\u0000\u012a\u012b\u0005\"\u0000\u0000\u012bZ\u0001\u0000\u0000\u0000"+ - "\u012c\u0130\u0005\"\u0000\u0000\u012d\u012f\b\u0005\u0000\u0000\u012e"+ - "\u012d\u0001\u0000\u0000\u0000\u012f\u0132\u0001\u0000\u0000\u0000\u0130"+ - "\u012e\u0001\u0000\u0000\u0000\u0130\u0131\u0001\u0000\u0000\u0000\u0131"+ - "\\\u0001\u0000\u0000\u0000\u0132\u0130\u0001\u0000\u0000\u0000\b\u0000"+ - "\u00eb\u00f5\u0103\u010b\u0116\u0126\u0130\u0001\u0006\u0000\u0000"; - public static final ATN _ATN = - new ATNDeserializer().deserialize(_serializedATN.toCharArray()); - static { - _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; - for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { - _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); - } - } -} \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackLexer.tokens b/compiler/grammar/.antlr/JackLexer.tokens deleted file mode 100644 index 8292b05c..00000000 --- a/compiler/grammar/.antlr/JackLexer.tokens +++ /dev/null @@ -1,84 +0,0 @@ -CLASS=1 -CONSTRUCTOR=2 -FUNCTION=3 -METHOD=4 -FIELD=5 -STATIC=6 -VAR=7 -INT=8 -CHAR=9 -BOOLEAN=10 -VOID=11 -LET=12 -DO=13 -IF=14 -ELSE=15 -WHILE=16 -RETURN=17 -LBRACE=18 -RBRACE=19 -LPAREN=20 -RPAREN=21 -LBRACKET=22 -RBRACKET=23 -DOT=24 -COMMA=25 -SEMICOLON=26 -EQUALS=27 -PLUS=28 -MINUS=29 -MUL=30 -DIV=31 -AND=32 -OR=33 -TILDE=34 -LESS_THAN=35 -GREATER_THAN=36 -WS=37 -COMMENT=38 -LINE_COMMENT=39 -INTEGER_LITERAL=40 -BOOLEAN_LITERAL=41 -NULL_LITERAL=42 -THIS_LITERAL=43 -IDENTIFIER=44 -STRING_LITERAL=45 -UnterminatedStringLiteral=46 -'class'=1 -'constructor'=2 -'function'=3 -'method'=4 -'field'=5 -'static'=6 -'var'=7 -'int'=8 -'char'=9 -'boolean'=10 -'void'=11 -'let'=12 -'do'=13 -'if'=14 -'else'=15 -'while'=16 -'return'=17 -'{'=18 -'}'=19 -'('=20 -')'=21 -'['=22 -']'=23 -'.'=24 -','=25 -';'=26 -'='=27 -'+'=28 -'-'=29 -'*'=30 -'/'=31 -'&'=32 -'|'=33 -'~'=34 -'<'=35 -'>'=36 -'null'=42 -'this'=43 diff --git a/compiler/grammar/.antlr/JackParser.interp b/compiler/grammar/.antlr/JackParser.interp deleted file mode 100644 index 860e8c5b..00000000 --- a/compiler/grammar/.antlr/JackParser.interp +++ /dev/null @@ -1,142 +0,0 @@ -token literal names: -null -'class' -'constructor' -'function' -'method' -'field' -'static' -'var' -'int' -'char' -'boolean' -'void' -'let' -'do' -'if' -'else' -'while' -'return' -'{' -'}' -'(' -')' -'[' -']' -'.' -',' -';' -'=' -'+' -'-' -'*' -'/' -'&' -'|' -'~' -'<' -'>' -null -null -null -null -null -'null' -'this' -null -null -null - -token symbolic names: -null -CLASS -CONSTRUCTOR -FUNCTION -METHOD -FIELD -STATIC -VAR -INT -CHAR -BOOLEAN -VOID -LET -DO -IF -ELSE -WHILE -RETURN -LBRACE -RBRACE -LPAREN -RPAREN -LBRACKET -RBRACKET -DOT -COMMA -SEMICOLON -EQUALS -PLUS -MINUS -MUL -DIV -AND -OR -TILDE -LESS_THAN -GREATER_THAN -WS -COMMENT -LINE_COMMENT -INTEGER_LITERAL -BOOLEAN_LITERAL -NULL_LITERAL -THIS_LITERAL -IDENTIFIER -STRING_LITERAL -UnterminatedStringLiteral - -rule names: -program -classDeclaration -className -classVarDec -fieldList -fieldName -subroutineDeclaration -subroutineType -subroutineDecWithoutType -subroutineName -subroutineReturnType -varType -parameterList -parameter -parameterName -subroutineBody -rBrace -varDeclaration -varNameInDeclaration -varName -statements -statement -letStatement -ifElseStatement -ifStatement -elseStatement -whileStatement -doStatement -subroutineCall -subroutineId -returnStatement -expressionList -expression -groupedExpression -unaryOperation -arrayAccess -constant -unaryOperator -binaryOperator - - -atn: -[4, 1, 46, 296, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 86, 8, 1, 10, 1, 12, 1, 89, 9, 1, 1, 1, 5, 1, 92, 8, 1, 10, 1, 12, 1, 95, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 109, 8, 4, 10, 4, 12, 4, 112, 9, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 132, 8, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 5, 12, 139, 8, 12, 10, 12, 12, 12, 142, 9, 12, 3, 12, 144, 8, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 153, 8, 15, 10, 15, 12, 15, 156, 9, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 168, 8, 17, 10, 17, 12, 17, 171, 9, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 5, 20, 180, 8, 20, 10, 20, 12, 20, 183, 9, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 190, 8, 21, 1, 22, 1, 22, 1, 22, 3, 22, 195, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 3, 23, 203, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 3, 29, 237, 8, 29, 1, 29, 3, 29, 240, 8, 29, 1, 29, 1, 29, 1, 30, 1, 30, 3, 30, 246, 8, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 5, 31, 253, 8, 31, 10, 31, 12, 31, 256, 9, 31, 3, 31, 258, 8, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 267, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 273, 8, 32, 10, 32, 12, 32, 276, 9, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 0, 1, 64, 39, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 0, 6, 1, 0, 5, 6, 1, 0, 2, 4, 2, 0, 8, 10, 44, 44, 2, 0, 40, 43, 45, 45, 2, 0, 29, 29, 34, 34, 2, 0, 27, 33, 35, 36, 282, 0, 78, 1, 0, 0, 0, 2, 81, 1, 0, 0, 0, 4, 98, 1, 0, 0, 0, 6, 100, 1, 0, 0, 0, 8, 104, 1, 0, 0, 0, 10, 113, 1, 0, 0, 0, 12, 115, 1, 0, 0, 0, 14, 118, 1, 0, 0, 0, 16, 120, 1, 0, 0, 0, 18, 127, 1, 0, 0, 0, 20, 131, 1, 0, 0, 0, 22, 133, 1, 0, 0, 0, 24, 143, 1, 0, 0, 0, 26, 145, 1, 0, 0, 0, 28, 148, 1, 0, 0, 0, 30, 150, 1, 0, 0, 0, 32, 160, 1, 0, 0, 0, 34, 162, 1, 0, 0, 0, 36, 174, 1, 0, 0, 0, 38, 176, 1, 0, 0, 0, 40, 181, 1, 0, 0, 0, 42, 189, 1, 0, 0, 0, 44, 191, 1, 0, 0, 0, 46, 200, 1, 0, 0, 0, 48, 204, 1, 0, 0, 0, 50, 212, 1, 0, 0, 0, 52, 217, 1, 0, 0, 0, 54, 225, 1, 0, 0, 0, 56, 229, 1, 0, 0, 0, 58, 239, 1, 0, 0, 0, 60, 243, 1, 0, 0, 0, 62, 257, 1, 0, 0, 0, 64, 266, 1, 0, 0, 0, 66, 277, 1, 0, 0, 0, 68, 281, 1, 0, 0, 0, 70, 284, 1, 0, 0, 0, 72, 289, 1, 0, 0, 0, 74, 291, 1, 0, 0, 0, 76, 293, 1, 0, 0, 0, 78, 79, 3, 2, 1, 0, 79, 80, 5, 0, 0, 1, 80, 1, 1, 0, 0, 0, 81, 82, 5, 1, 0, 0, 82, 83, 3, 4, 2, 0, 83, 87, 5, 18, 0, 0, 84, 86, 3, 6, 3, 0, 85, 84, 1, 0, 0, 0, 86, 89, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 93, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 90, 92, 3, 12, 6, 0, 91, 90, 1, 0, 0, 0, 92, 95, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 96, 1, 0, 0, 0, 95, 93, 1, 0, 0, 0, 96, 97, 3, 32, 16, 0, 97, 3, 1, 0, 0, 0, 98, 99, 5, 44, 0, 0, 99, 5, 1, 0, 0, 0, 100, 101, 7, 0, 0, 0, 101, 102, 3, 8, 4, 0, 102, 103, 5, 26, 0, 0, 103, 7, 1, 0, 0, 0, 104, 105, 3, 22, 11, 0, 105, 110, 3, 10, 5, 0, 106, 107, 5, 25, 0, 0, 107, 109, 3, 10, 5, 0, 108, 106, 1, 0, 0, 0, 109, 112, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 110, 111, 1, 0, 0, 0, 111, 9, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 113, 114, 5, 44, 0, 0, 114, 11, 1, 0, 0, 0, 115, 116, 3, 14, 7, 0, 116, 117, 3, 16, 8, 0, 117, 13, 1, 0, 0, 0, 118, 119, 7, 1, 0, 0, 119, 15, 1, 0, 0, 0, 120, 121, 3, 20, 10, 0, 121, 122, 3, 18, 9, 0, 122, 123, 5, 20, 0, 0, 123, 124, 3, 24, 12, 0, 124, 125, 5, 21, 0, 0, 125, 126, 3, 30, 15, 0, 126, 17, 1, 0, 0, 0, 127, 128, 5, 44, 0, 0, 128, 19, 1, 0, 0, 0, 129, 132, 3, 22, 11, 0, 130, 132, 5, 11, 0, 0, 131, 129, 1, 0, 0, 0, 131, 130, 1, 0, 0, 0, 132, 21, 1, 0, 0, 0, 133, 134, 7, 2, 0, 0, 134, 23, 1, 0, 0, 0, 135, 140, 3, 26, 13, 0, 136, 137, 5, 25, 0, 0, 137, 139, 3, 26, 13, 0, 138, 136, 1, 0, 0, 0, 139, 142, 1, 0, 0, 0, 140, 138, 1, 0, 0, 0, 140, 141, 1, 0, 0, 0, 141, 144, 1, 0, 0, 0, 142, 140, 1, 0, 0, 0, 143, 135, 1, 0, 0, 0, 143, 144, 1, 0, 0, 0, 144, 25, 1, 0, 0, 0, 145, 146, 3, 22, 11, 0, 146, 147, 3, 28, 14, 0, 147, 27, 1, 0, 0, 0, 148, 149, 5, 44, 0, 0, 149, 29, 1, 0, 0, 0, 150, 154, 5, 18, 0, 0, 151, 153, 3, 34, 17, 0, 152, 151, 1, 0, 0, 0, 153, 156, 1, 0, 0, 0, 154, 152, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 157, 1, 0, 0, 0, 156, 154, 1, 0, 0, 0, 157, 158, 3, 40, 20, 0, 158, 159, 3, 32, 16, 0, 159, 31, 1, 0, 0, 0, 160, 161, 5, 19, 0, 0, 161, 33, 1, 0, 0, 0, 162, 163, 5, 7, 0, 0, 163, 164, 3, 22, 11, 0, 164, 169, 3, 36, 18, 0, 165, 166, 5, 25, 0, 0, 166, 168, 3, 36, 18, 0, 167, 165, 1, 0, 0, 0, 168, 171, 1, 0, 0, 0, 169, 167, 1, 0, 0, 0, 169, 170, 1, 0, 0, 0, 170, 172, 1, 0, 0, 0, 171, 169, 1, 0, 0, 0, 172, 173, 5, 26, 0, 0, 173, 35, 1, 0, 0, 0, 174, 175, 5, 44, 0, 0, 175, 37, 1, 0, 0, 0, 176, 177, 5, 44, 0, 0, 177, 39, 1, 0, 0, 0, 178, 180, 3, 42, 21, 0, 179, 178, 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 41, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 190, 3, 44, 22, 0, 185, 190, 3, 46, 23, 0, 186, 190, 3, 52, 26, 0, 187, 190, 3, 54, 27, 0, 188, 190, 3, 60, 30, 0, 189, 184, 1, 0, 0, 0, 189, 185, 1, 0, 0, 0, 189, 186, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 188, 1, 0, 0, 0, 190, 43, 1, 0, 0, 0, 191, 194, 5, 12, 0, 0, 192, 195, 3, 38, 19, 0, 193, 195, 3, 70, 35, 0, 194, 192, 1, 0, 0, 0, 194, 193, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 197, 5, 27, 0, 0, 197, 198, 3, 64, 32, 0, 198, 199, 5, 26, 0, 0, 199, 45, 1, 0, 0, 0, 200, 202, 3, 48, 24, 0, 201, 203, 3, 50, 25, 0, 202, 201, 1, 0, 0, 0, 202, 203, 1, 0, 0, 0, 203, 47, 1, 0, 0, 0, 204, 205, 5, 14, 0, 0, 205, 206, 5, 20, 0, 0, 206, 207, 3, 64, 32, 0, 207, 208, 5, 21, 0, 0, 208, 209, 5, 18, 0, 0, 209, 210, 3, 40, 20, 0, 210, 211, 3, 32, 16, 0, 211, 49, 1, 0, 0, 0, 212, 213, 5, 15, 0, 0, 213, 214, 5, 18, 0, 0, 214, 215, 3, 40, 20, 0, 215, 216, 3, 32, 16, 0, 216, 51, 1, 0, 0, 0, 217, 218, 5, 16, 0, 0, 218, 219, 5, 20, 0, 0, 219, 220, 3, 64, 32, 0, 220, 221, 5, 21, 0, 0, 221, 222, 5, 18, 0, 0, 222, 223, 3, 40, 20, 0, 223, 224, 3, 32, 16, 0, 224, 53, 1, 0, 0, 0, 225, 226, 5, 13, 0, 0, 226, 227, 3, 56, 28, 0, 227, 228, 5, 26, 0, 0, 228, 55, 1, 0, 0, 0, 229, 230, 3, 58, 29, 0, 230, 231, 5, 20, 0, 0, 231, 232, 3, 62, 31, 0, 232, 233, 5, 21, 0, 0, 233, 57, 1, 0, 0, 0, 234, 237, 3, 4, 2, 0, 235, 237, 5, 43, 0, 0, 236, 234, 1, 0, 0, 0, 236, 235, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 240, 5, 24, 0, 0, 239, 236, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 242, 3, 18, 9, 0, 242, 59, 1, 0, 0, 0, 243, 245, 5, 17, 0, 0, 244, 246, 3, 64, 32, 0, 245, 244, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 247, 1, 0, 0, 0, 247, 248, 5, 26, 0, 0, 248, 61, 1, 0, 0, 0, 249, 254, 3, 64, 32, 0, 250, 251, 5, 25, 0, 0, 251, 253, 3, 64, 32, 0, 252, 250, 1, 0, 0, 0, 253, 256, 1, 0, 0, 0, 254, 252, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 258, 1, 0, 0, 0, 256, 254, 1, 0, 0, 0, 257, 249, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 63, 1, 0, 0, 0, 259, 260, 6, 32, -1, 0, 260, 267, 3, 72, 36, 0, 261, 267, 3, 38, 19, 0, 262, 267, 3, 56, 28, 0, 263, 267, 3, 70, 35, 0, 264, 267, 3, 68, 34, 0, 265, 267, 3, 66, 33, 0, 266, 259, 1, 0, 0, 0, 266, 261, 1, 0, 0, 0, 266, 262, 1, 0, 0, 0, 266, 263, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 266, 265, 1, 0, 0, 0, 267, 274, 1, 0, 0, 0, 268, 269, 10, 7, 0, 0, 269, 270, 3, 76, 38, 0, 270, 271, 3, 64, 32, 8, 271, 273, 1, 0, 0, 0, 272, 268, 1, 0, 0, 0, 273, 276, 1, 0, 0, 0, 274, 272, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 65, 1, 0, 0, 0, 276, 274, 1, 0, 0, 0, 277, 278, 5, 20, 0, 0, 278, 279, 3, 64, 32, 0, 279, 280, 5, 21, 0, 0, 280, 67, 1, 0, 0, 0, 281, 282, 3, 74, 37, 0, 282, 283, 3, 64, 32, 0, 283, 69, 1, 0, 0, 0, 284, 285, 3, 38, 19, 0, 285, 286, 5, 22, 0, 0, 286, 287, 3, 64, 32, 0, 287, 288, 5, 23, 0, 0, 288, 71, 1, 0, 0, 0, 289, 290, 7, 3, 0, 0, 290, 73, 1, 0, 0, 0, 291, 292, 7, 4, 0, 0, 292, 75, 1, 0, 0, 0, 293, 294, 7, 5, 0, 0, 294, 77, 1, 0, 0, 0, 19, 87, 93, 110, 131, 140, 143, 154, 169, 181, 189, 194, 202, 236, 239, 245, 254, 257, 266, 274] \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackParser.java b/compiler/grammar/.antlr/JackParser.java deleted file mode 100644 index fb913c4c..00000000 --- a/compiler/grammar/.antlr/JackParser.java +++ /dev/null @@ -1,2237 +0,0 @@ -// Generated from /home/babkamen/git/nand2tetris/tools/web-ide/compiler/grammar/JackParser.g4 by ANTLR 4.13.1 -import org.antlr.v4.runtime.atn.*; -import org.antlr.v4.runtime.dfa.DFA; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.misc.*; -import org.antlr.v4.runtime.tree.*; -import java.util.List; -import java.util.Iterator; -import java.util.ArrayList; - -@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue"}) -public class JackParser extends Parser { - static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); } - - protected static final DFA[] _decisionToDFA; - protected static final PredictionContextCache _sharedContextCache = - new PredictionContextCache(); - public static final int - CLASS=1, CONSTRUCTOR=2, FUNCTION=3, METHOD=4, FIELD=5, STATIC=6, VAR=7, - INT=8, CHAR=9, BOOLEAN=10, VOID=11, LET=12, DO=13, IF=14, ELSE=15, WHILE=16, - RETURN=17, LBRACE=18, RBRACE=19, LPAREN=20, RPAREN=21, LBRACKET=22, RBRACKET=23, - DOT=24, COMMA=25, SEMICOLON=26, EQUALS=27, PLUS=28, MINUS=29, MUL=30, - DIV=31, AND=32, OR=33, TILDE=34, LESS_THAN=35, GREATER_THAN=36, WS=37, - COMMENT=38, LINE_COMMENT=39, INTEGER_LITERAL=40, BOOLEAN_LITERAL=41, NULL_LITERAL=42, - THIS_LITERAL=43, IDENTIFIER=44, STRING_LITERAL=45, UnterminatedStringLiteral=46; - public static final int - RULE_program = 0, RULE_classDeclaration = 1, RULE_className = 2, RULE_classVarDec = 3, - RULE_fieldList = 4, RULE_fieldName = 5, RULE_subroutineDeclaration = 6, - RULE_subroutineType = 7, RULE_subroutineDecWithoutType = 8, RULE_subroutineName = 9, - RULE_subroutineReturnType = 10, RULE_varType = 11, RULE_parameterList = 12, - RULE_parameter = 13, RULE_parameterName = 14, RULE_subroutineBody = 15, - RULE_rBrace = 16, RULE_varDeclaration = 17, RULE_varNameInDeclaration = 18, - RULE_varName = 19, RULE_statements = 20, RULE_statement = 21, RULE_letStatement = 22, - RULE_ifElseStatement = 23, RULE_ifStatement = 24, RULE_elseStatement = 25, - RULE_whileStatement = 26, RULE_doStatement = 27, RULE_subroutineCall = 28, - RULE_subroutineId = 29, RULE_returnStatement = 30, RULE_expressionList = 31, - RULE_expression = 32, RULE_groupedExpression = 33, RULE_unaryOperation = 34, - RULE_arrayAccess = 35, RULE_constant = 36, RULE_unaryOperator = 37, RULE_binaryOperator = 38; - private static String[] makeRuleNames() { - return new String[] { - "program", "classDeclaration", "className", "classVarDec", "fieldList", - "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", - "subroutineName", "subroutineReturnType", "varType", "parameterList", - "parameter", "parameterName", "subroutineBody", "rBrace", "varDeclaration", - "varNameInDeclaration", "varName", "statements", "statement", "letStatement", - "ifElseStatement", "ifStatement", "elseStatement", "whileStatement", - "doStatement", "subroutineCall", "subroutineId", "returnStatement", "expressionList", - "expression", "groupedExpression", "unaryOperation", "arrayAccess", "constant", - "unaryOperator", "binaryOperator" - }; - } - public static final String[] ruleNames = makeRuleNames(); - - private static String[] makeLiteralNames() { - return new String[] { - null, "'class'", "'constructor'", "'function'", "'method'", "'field'", - "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", - "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", - "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", - "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", null, null, null, null, null, - "'null'", "'this'" - }; - } - private static final String[] _LITERAL_NAMES = makeLiteralNames(); - private static String[] makeSymbolicNames() { - return new String[] { - null, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", - "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", - "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", - "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", - "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", - "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", - "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral" - }; - } - private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames(); - public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); - - /** - * @deprecated Use {@link #VOCABULARY} instead. - */ - @Deprecated - public static final String[] tokenNames; - static { - tokenNames = new String[_SYMBOLIC_NAMES.length]; - for (int i = 0; i < tokenNames.length; i++) { - tokenNames[i] = VOCABULARY.getLiteralName(i); - if (tokenNames[i] == null) { - tokenNames[i] = VOCABULARY.getSymbolicName(i); - } - - if (tokenNames[i] == null) { - tokenNames[i] = ""; - } - } - } - - @Override - @Deprecated - public String[] getTokenNames() { - return tokenNames; - } - - @Override - - public Vocabulary getVocabulary() { - return VOCABULARY; - } - - @Override - public String getGrammarFileName() { return "JackParser.g4"; } - - @Override - public String[] getRuleNames() { return ruleNames; } - - @Override - public String getSerializedATN() { return _serializedATN; } - - @Override - public ATN getATN() { return _ATN; } - - public JackParser(TokenStream input) { - super(input); - _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); - } - - @SuppressWarnings("CheckReturnValue") - public static class ProgramContext extends ParserRuleContext { - public ClassDeclarationContext classDeclaration() { - return getRuleContext(ClassDeclarationContext.class,0); - } - public TerminalNode EOF() { return getToken(JackParser.EOF, 0); } - public ProgramContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_program; } - } - - public final ProgramContext program() throws RecognitionException { - ProgramContext _localctx = new ProgramContext(_ctx, getState()); - enterRule(_localctx, 0, RULE_program); - try { - enterOuterAlt(_localctx, 1); - { - setState(78); - classDeclaration(); - setState(79); - match(EOF); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ClassDeclarationContext extends ParserRuleContext { - public TerminalNode CLASS() { return getToken(JackParser.CLASS, 0); } - public ClassNameContext className() { - return getRuleContext(ClassNameContext.class,0); - } - public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } - public RBraceContext rBrace() { - return getRuleContext(RBraceContext.class,0); - } - public List classVarDec() { - return getRuleContexts(ClassVarDecContext.class); - } - public ClassVarDecContext classVarDec(int i) { - return getRuleContext(ClassVarDecContext.class,i); - } - public List subroutineDeclaration() { - return getRuleContexts(SubroutineDeclarationContext.class); - } - public SubroutineDeclarationContext subroutineDeclaration(int i) { - return getRuleContext(SubroutineDeclarationContext.class,i); - } - public ClassDeclarationContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_classDeclaration; } - } - - public final ClassDeclarationContext classDeclaration() throws RecognitionException { - ClassDeclarationContext _localctx = new ClassDeclarationContext(_ctx, getState()); - enterRule(_localctx, 2, RULE_classDeclaration); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(81); - match(CLASS); - setState(82); - className(); - setState(83); - match(LBRACE); - setState(87); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==FIELD || _la==STATIC) { - { - { - setState(84); - classVarDec(); - } - } - setState(89); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(93); - _errHandler.sync(this); - _la = _input.LA(1); - while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 28L) != 0)) { - { - { - setState(90); - subroutineDeclaration(); - } - } - setState(95); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(96); - rBrace(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ClassNameContext extends ParserRuleContext { - public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } - public ClassNameContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_className; } - } - - public final ClassNameContext className() throws RecognitionException { - ClassNameContext _localctx = new ClassNameContext(_ctx, getState()); - enterRule(_localctx, 4, RULE_className); - try { - enterOuterAlt(_localctx, 1); - { - setState(98); - match(IDENTIFIER); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ClassVarDecContext extends ParserRuleContext { - public FieldListContext fieldList() { - return getRuleContext(FieldListContext.class,0); - } - public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } - public TerminalNode STATIC() { return getToken(JackParser.STATIC, 0); } - public TerminalNode FIELD() { return getToken(JackParser.FIELD, 0); } - public ClassVarDecContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_classVarDec; } - } - - public final ClassVarDecContext classVarDec() throws RecognitionException { - ClassVarDecContext _localctx = new ClassVarDecContext(_ctx, getState()); - enterRule(_localctx, 6, RULE_classVarDec); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(100); - _la = _input.LA(1); - if ( !(_la==FIELD || _la==STATIC) ) { - _errHandler.recoverInline(this); - } - else { - if ( _input.LA(1)==Token.EOF ) matchedEOF = true; - _errHandler.reportMatch(this); - consume(); - } - setState(101); - fieldList(); - setState(102); - match(SEMICOLON); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class FieldListContext extends ParserRuleContext { - public VarTypeContext varType() { - return getRuleContext(VarTypeContext.class,0); - } - public List fieldName() { - return getRuleContexts(FieldNameContext.class); - } - public FieldNameContext fieldName(int i) { - return getRuleContext(FieldNameContext.class,i); - } - public List COMMA() { return getTokens(JackParser.COMMA); } - public TerminalNode COMMA(int i) { - return getToken(JackParser.COMMA, i); - } - public FieldListContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_fieldList; } - } - - public final FieldListContext fieldList() throws RecognitionException { - FieldListContext _localctx = new FieldListContext(_ctx, getState()); - enterRule(_localctx, 8, RULE_fieldList); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(104); - varType(); - setState(105); - fieldName(); - setState(110); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==COMMA) { - { - { - setState(106); - match(COMMA); - setState(107); - fieldName(); - } - } - setState(112); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class FieldNameContext extends ParserRuleContext { - public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } - public FieldNameContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_fieldName; } - } - - public final FieldNameContext fieldName() throws RecognitionException { - FieldNameContext _localctx = new FieldNameContext(_ctx, getState()); - enterRule(_localctx, 10, RULE_fieldName); - try { - enterOuterAlt(_localctx, 1); - { - setState(113); - match(IDENTIFIER); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class SubroutineDeclarationContext extends ParserRuleContext { - public SubroutineTypeContext subroutineType() { - return getRuleContext(SubroutineTypeContext.class,0); - } - public SubroutineDecWithoutTypeContext subroutineDecWithoutType() { - return getRuleContext(SubroutineDecWithoutTypeContext.class,0); - } - public SubroutineDeclarationContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subroutineDeclaration; } - } - - public final SubroutineDeclarationContext subroutineDeclaration() throws RecognitionException { - SubroutineDeclarationContext _localctx = new SubroutineDeclarationContext(_ctx, getState()); - enterRule(_localctx, 12, RULE_subroutineDeclaration); - try { - enterOuterAlt(_localctx, 1); - { - setState(115); - subroutineType(); - setState(116); - subroutineDecWithoutType(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class SubroutineTypeContext extends ParserRuleContext { - public TerminalNode CONSTRUCTOR() { return getToken(JackParser.CONSTRUCTOR, 0); } - public TerminalNode METHOD() { return getToken(JackParser.METHOD, 0); } - public TerminalNode FUNCTION() { return getToken(JackParser.FUNCTION, 0); } - public SubroutineTypeContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subroutineType; } - } - - public final SubroutineTypeContext subroutineType() throws RecognitionException { - SubroutineTypeContext _localctx = new SubroutineTypeContext(_ctx, getState()); - enterRule(_localctx, 14, RULE_subroutineType); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(118); - _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 28L) != 0)) ) { - _errHandler.recoverInline(this); - } - else { - if ( _input.LA(1)==Token.EOF ) matchedEOF = true; - _errHandler.reportMatch(this); - consume(); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class SubroutineDecWithoutTypeContext extends ParserRuleContext { - public SubroutineReturnTypeContext subroutineReturnType() { - return getRuleContext(SubroutineReturnTypeContext.class,0); - } - public SubroutineNameContext subroutineName() { - return getRuleContext(SubroutineNameContext.class,0); - } - public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } - public ParameterListContext parameterList() { - return getRuleContext(ParameterListContext.class,0); - } - public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } - public SubroutineBodyContext subroutineBody() { - return getRuleContext(SubroutineBodyContext.class,0); - } - public SubroutineDecWithoutTypeContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subroutineDecWithoutType; } - } - - public final SubroutineDecWithoutTypeContext subroutineDecWithoutType() throws RecognitionException { - SubroutineDecWithoutTypeContext _localctx = new SubroutineDecWithoutTypeContext(_ctx, getState()); - enterRule(_localctx, 16, RULE_subroutineDecWithoutType); - try { - enterOuterAlt(_localctx, 1); - { - setState(120); - subroutineReturnType(); - setState(121); - subroutineName(); - setState(122); - match(LPAREN); - setState(123); - parameterList(); - setState(124); - match(RPAREN); - setState(125); - subroutineBody(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class SubroutineNameContext extends ParserRuleContext { - public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } - public SubroutineNameContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subroutineName; } - } - - public final SubroutineNameContext subroutineName() throws RecognitionException { - SubroutineNameContext _localctx = new SubroutineNameContext(_ctx, getState()); - enterRule(_localctx, 18, RULE_subroutineName); - try { - enterOuterAlt(_localctx, 1); - { - setState(127); - match(IDENTIFIER); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class SubroutineReturnTypeContext extends ParserRuleContext { - public VarTypeContext varType() { - return getRuleContext(VarTypeContext.class,0); - } - public TerminalNode VOID() { return getToken(JackParser.VOID, 0); } - public SubroutineReturnTypeContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subroutineReturnType; } - } - - public final SubroutineReturnTypeContext subroutineReturnType() throws RecognitionException { - SubroutineReturnTypeContext _localctx = new SubroutineReturnTypeContext(_ctx, getState()); - enterRule(_localctx, 20, RULE_subroutineReturnType); - try { - setState(131); - _errHandler.sync(this); - switch (_input.LA(1)) { - case INT: - case CHAR: - case BOOLEAN: - case IDENTIFIER: - enterOuterAlt(_localctx, 1); - { - setState(129); - varType(); - } - break; - case VOID: - enterOuterAlt(_localctx, 2); - { - setState(130); - match(VOID); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class VarTypeContext extends ParserRuleContext { - public TerminalNode INT() { return getToken(JackParser.INT, 0); } - public TerminalNode CHAR() { return getToken(JackParser.CHAR, 0); } - public TerminalNode BOOLEAN() { return getToken(JackParser.BOOLEAN, 0); } - public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } - public VarTypeContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_varType; } - } - - public final VarTypeContext varType() throws RecognitionException { - VarTypeContext _localctx = new VarTypeContext(_ctx, getState()); - enterRule(_localctx, 22, RULE_varType); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(133); - _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 17592186046208L) != 0)) ) { - _errHandler.recoverInline(this); - } - else { - if ( _input.LA(1)==Token.EOF ) matchedEOF = true; - _errHandler.reportMatch(this); - consume(); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ParameterListContext extends ParserRuleContext { - public List parameter() { - return getRuleContexts(ParameterContext.class); - } - public ParameterContext parameter(int i) { - return getRuleContext(ParameterContext.class,i); - } - public List COMMA() { return getTokens(JackParser.COMMA); } - public TerminalNode COMMA(int i) { - return getToken(JackParser.COMMA, i); - } - public ParameterListContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_parameterList; } - } - - public final ParameterListContext parameterList() throws RecognitionException { - ParameterListContext _localctx = new ParameterListContext(_ctx, getState()); - enterRule(_localctx, 24, RULE_parameterList); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(143); - _errHandler.sync(this); - _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & 17592186046208L) != 0)) { - { - setState(135); - parameter(); - setState(140); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==COMMA) { - { - { - setState(136); - match(COMMA); - setState(137); - parameter(); - } - } - setState(142); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ParameterContext extends ParserRuleContext { - public VarTypeContext varType() { - return getRuleContext(VarTypeContext.class,0); - } - public ParameterNameContext parameterName() { - return getRuleContext(ParameterNameContext.class,0); - } - public ParameterContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_parameter; } - } - - public final ParameterContext parameter() throws RecognitionException { - ParameterContext _localctx = new ParameterContext(_ctx, getState()); - enterRule(_localctx, 26, RULE_parameter); - try { - enterOuterAlt(_localctx, 1); - { - setState(145); - varType(); - setState(146); - parameterName(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ParameterNameContext extends ParserRuleContext { - public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } - public ParameterNameContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_parameterName; } - } - - public final ParameterNameContext parameterName() throws RecognitionException { - ParameterNameContext _localctx = new ParameterNameContext(_ctx, getState()); - enterRule(_localctx, 28, RULE_parameterName); - try { - enterOuterAlt(_localctx, 1); - { - setState(148); - match(IDENTIFIER); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class SubroutineBodyContext extends ParserRuleContext { - public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } - public StatementsContext statements() { - return getRuleContext(StatementsContext.class,0); - } - public RBraceContext rBrace() { - return getRuleContext(RBraceContext.class,0); - } - public List varDeclaration() { - return getRuleContexts(VarDeclarationContext.class); - } - public VarDeclarationContext varDeclaration(int i) { - return getRuleContext(VarDeclarationContext.class,i); - } - public SubroutineBodyContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subroutineBody; } - } - - public final SubroutineBodyContext subroutineBody() throws RecognitionException { - SubroutineBodyContext _localctx = new SubroutineBodyContext(_ctx, getState()); - enterRule(_localctx, 30, RULE_subroutineBody); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(150); - match(LBRACE); - setState(154); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==VAR) { - { - { - setState(151); - varDeclaration(); - } - } - setState(156); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(157); - statements(); - setState(158); - rBrace(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class RBraceContext extends ParserRuleContext { - public TerminalNode RBRACE() { return getToken(JackParser.RBRACE, 0); } - public RBraceContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_rBrace; } - } - - public final RBraceContext rBrace() throws RecognitionException { - RBraceContext _localctx = new RBraceContext(_ctx, getState()); - enterRule(_localctx, 32, RULE_rBrace); - try { - enterOuterAlt(_localctx, 1); - { - setState(160); - match(RBRACE); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class VarDeclarationContext extends ParserRuleContext { - public TerminalNode VAR() { return getToken(JackParser.VAR, 0); } - public VarTypeContext varType() { - return getRuleContext(VarTypeContext.class,0); - } - public List varNameInDeclaration() { - return getRuleContexts(VarNameInDeclarationContext.class); - } - public VarNameInDeclarationContext varNameInDeclaration(int i) { - return getRuleContext(VarNameInDeclarationContext.class,i); - } - public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } - public List COMMA() { return getTokens(JackParser.COMMA); } - public TerminalNode COMMA(int i) { - return getToken(JackParser.COMMA, i); - } - public VarDeclarationContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_varDeclaration; } - } - - public final VarDeclarationContext varDeclaration() throws RecognitionException { - VarDeclarationContext _localctx = new VarDeclarationContext(_ctx, getState()); - enterRule(_localctx, 34, RULE_varDeclaration); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(162); - match(VAR); - setState(163); - varType(); - setState(164); - varNameInDeclaration(); - setState(169); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==COMMA) { - { - { - setState(165); - match(COMMA); - setState(166); - varNameInDeclaration(); - } - } - setState(171); - _errHandler.sync(this); - _la = _input.LA(1); - } - setState(172); - match(SEMICOLON); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class VarNameInDeclarationContext extends ParserRuleContext { - public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } - public VarNameInDeclarationContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_varNameInDeclaration; } - } - - public final VarNameInDeclarationContext varNameInDeclaration() throws RecognitionException { - VarNameInDeclarationContext _localctx = new VarNameInDeclarationContext(_ctx, getState()); - enterRule(_localctx, 36, RULE_varNameInDeclaration); - try { - enterOuterAlt(_localctx, 1); - { - setState(174); - match(IDENTIFIER); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class VarNameContext extends ParserRuleContext { - public TerminalNode IDENTIFIER() { return getToken(JackParser.IDENTIFIER, 0); } - public VarNameContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_varName; } - } - - public final VarNameContext varName() throws RecognitionException { - VarNameContext _localctx = new VarNameContext(_ctx, getState()); - enterRule(_localctx, 38, RULE_varName); - try { - enterOuterAlt(_localctx, 1); - { - setState(176); - match(IDENTIFIER); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class StatementsContext extends ParserRuleContext { - public List statement() { - return getRuleContexts(StatementContext.class); - } - public StatementContext statement(int i) { - return getRuleContext(StatementContext.class,i); - } - public StatementsContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_statements; } - } - - public final StatementsContext statements() throws RecognitionException { - StatementsContext _localctx = new StatementsContext(_ctx, getState()); - enterRule(_localctx, 40, RULE_statements); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(181); - _errHandler.sync(this); - _la = _input.LA(1); - while ((((_la) & ~0x3f) == 0 && ((1L << _la) & 225280L) != 0)) { - { - { - setState(178); - statement(); - } - } - setState(183); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class StatementContext extends ParserRuleContext { - public LetStatementContext letStatement() { - return getRuleContext(LetStatementContext.class,0); - } - public IfElseStatementContext ifElseStatement() { - return getRuleContext(IfElseStatementContext.class,0); - } - public WhileStatementContext whileStatement() { - return getRuleContext(WhileStatementContext.class,0); - } - public DoStatementContext doStatement() { - return getRuleContext(DoStatementContext.class,0); - } - public ReturnStatementContext returnStatement() { - return getRuleContext(ReturnStatementContext.class,0); - } - public StatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_statement; } - } - - public final StatementContext statement() throws RecognitionException { - StatementContext _localctx = new StatementContext(_ctx, getState()); - enterRule(_localctx, 42, RULE_statement); - try { - setState(189); - _errHandler.sync(this); - switch (_input.LA(1)) { - case LET: - enterOuterAlt(_localctx, 1); - { - setState(184); - letStatement(); - } - break; - case IF: - enterOuterAlt(_localctx, 2); - { - setState(185); - ifElseStatement(); - } - break; - case WHILE: - enterOuterAlt(_localctx, 3); - { - setState(186); - whileStatement(); - } - break; - case DO: - enterOuterAlt(_localctx, 4); - { - setState(187); - doStatement(); - } - break; - case RETURN: - enterOuterAlt(_localctx, 5); - { - setState(188); - returnStatement(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class LetStatementContext extends ParserRuleContext { - public TerminalNode LET() { return getToken(JackParser.LET, 0); } - public TerminalNode EQUALS() { return getToken(JackParser.EQUALS, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } - public VarNameContext varName() { - return getRuleContext(VarNameContext.class,0); - } - public ArrayAccessContext arrayAccess() { - return getRuleContext(ArrayAccessContext.class,0); - } - public LetStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_letStatement; } - } - - public final LetStatementContext letStatement() throws RecognitionException { - LetStatementContext _localctx = new LetStatementContext(_ctx, getState()); - enterRule(_localctx, 44, RULE_letStatement); - try { - enterOuterAlt(_localctx, 1); - { - setState(191); - match(LET); - setState(194); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { - case 1: - { - setState(192); - varName(); - } - break; - case 2: - { - setState(193); - arrayAccess(); - } - break; - } - setState(196); - match(EQUALS); - setState(197); - expression(0); - setState(198); - match(SEMICOLON); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class IfElseStatementContext extends ParserRuleContext { - public IfStatementContext ifStatement() { - return getRuleContext(IfStatementContext.class,0); - } - public ElseStatementContext elseStatement() { - return getRuleContext(ElseStatementContext.class,0); - } - public IfElseStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_ifElseStatement; } - } - - public final IfElseStatementContext ifElseStatement() throws RecognitionException { - IfElseStatementContext _localctx = new IfElseStatementContext(_ctx, getState()); - enterRule(_localctx, 46, RULE_ifElseStatement); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(200); - ifStatement(); - setState(202); - _errHandler.sync(this); - _la = _input.LA(1); - if (_la==ELSE) { - { - setState(201); - elseStatement(); - } - } - - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class IfStatementContext extends ParserRuleContext { - public TerminalNode IF() { return getToken(JackParser.IF, 0); } - public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } - public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } - public StatementsContext statements() { - return getRuleContext(StatementsContext.class,0); - } - public RBraceContext rBrace() { - return getRuleContext(RBraceContext.class,0); - } - public IfStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_ifStatement; } - } - - public final IfStatementContext ifStatement() throws RecognitionException { - IfStatementContext _localctx = new IfStatementContext(_ctx, getState()); - enterRule(_localctx, 48, RULE_ifStatement); - try { - enterOuterAlt(_localctx, 1); - { - setState(204); - match(IF); - setState(205); - match(LPAREN); - setState(206); - expression(0); - setState(207); - match(RPAREN); - setState(208); - match(LBRACE); - setState(209); - statements(); - setState(210); - rBrace(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ElseStatementContext extends ParserRuleContext { - public TerminalNode ELSE() { return getToken(JackParser.ELSE, 0); } - public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } - public StatementsContext statements() { - return getRuleContext(StatementsContext.class,0); - } - public RBraceContext rBrace() { - return getRuleContext(RBraceContext.class,0); - } - public ElseStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_elseStatement; } - } - - public final ElseStatementContext elseStatement() throws RecognitionException { - ElseStatementContext _localctx = new ElseStatementContext(_ctx, getState()); - enterRule(_localctx, 50, RULE_elseStatement); - try { - enterOuterAlt(_localctx, 1); - { - setState(212); - match(ELSE); - setState(213); - match(LBRACE); - setState(214); - statements(); - setState(215); - rBrace(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class WhileStatementContext extends ParserRuleContext { - public TerminalNode WHILE() { return getToken(JackParser.WHILE, 0); } - public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } - public TerminalNode LBRACE() { return getToken(JackParser.LBRACE, 0); } - public StatementsContext statements() { - return getRuleContext(StatementsContext.class,0); - } - public RBraceContext rBrace() { - return getRuleContext(RBraceContext.class,0); - } - public WhileStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_whileStatement; } - } - - public final WhileStatementContext whileStatement() throws RecognitionException { - WhileStatementContext _localctx = new WhileStatementContext(_ctx, getState()); - enterRule(_localctx, 52, RULE_whileStatement); - try { - enterOuterAlt(_localctx, 1); - { - setState(217); - match(WHILE); - setState(218); - match(LPAREN); - setState(219); - expression(0); - setState(220); - match(RPAREN); - setState(221); - match(LBRACE); - setState(222); - statements(); - setState(223); - rBrace(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class DoStatementContext extends ParserRuleContext { - public TerminalNode DO() { return getToken(JackParser.DO, 0); } - public SubroutineCallContext subroutineCall() { - return getRuleContext(SubroutineCallContext.class,0); - } - public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } - public DoStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_doStatement; } - } - - public final DoStatementContext doStatement() throws RecognitionException { - DoStatementContext _localctx = new DoStatementContext(_ctx, getState()); - enterRule(_localctx, 54, RULE_doStatement); - try { - enterOuterAlt(_localctx, 1); - { - setState(225); - match(DO); - setState(226); - subroutineCall(); - setState(227); - match(SEMICOLON); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class SubroutineCallContext extends ParserRuleContext { - public SubroutineIdContext subroutineId() { - return getRuleContext(SubroutineIdContext.class,0); - } - public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } - public ExpressionListContext expressionList() { - return getRuleContext(ExpressionListContext.class,0); - } - public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } - public SubroutineCallContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subroutineCall; } - } - - public final SubroutineCallContext subroutineCall() throws RecognitionException { - SubroutineCallContext _localctx = new SubroutineCallContext(_ctx, getState()); - enterRule(_localctx, 56, RULE_subroutineCall); - try { - enterOuterAlt(_localctx, 1); - { - setState(229); - subroutineId(); - setState(230); - match(LPAREN); - setState(231); - expressionList(); - setState(232); - match(RPAREN); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class SubroutineIdContext extends ParserRuleContext { - public SubroutineNameContext subroutineName() { - return getRuleContext(SubroutineNameContext.class,0); - } - public TerminalNode DOT() { return getToken(JackParser.DOT, 0); } - public ClassNameContext className() { - return getRuleContext(ClassNameContext.class,0); - } - public TerminalNode THIS_LITERAL() { return getToken(JackParser.THIS_LITERAL, 0); } - public SubroutineIdContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_subroutineId; } - } - - public final SubroutineIdContext subroutineId() throws RecognitionException { - SubroutineIdContext _localctx = new SubroutineIdContext(_ctx, getState()); - enterRule(_localctx, 58, RULE_subroutineId); - try { - enterOuterAlt(_localctx, 1); - { - setState(239); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,13,_ctx) ) { - case 1: - { - setState(236); - _errHandler.sync(this); - switch (_input.LA(1)) { - case IDENTIFIER: - { - setState(234); - className(); - } - break; - case THIS_LITERAL: - { - setState(235); - match(THIS_LITERAL); - } - break; - default: - throw new NoViableAltException(this); - } - setState(238); - match(DOT); - } - break; - } - setState(241); - subroutineName(); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ReturnStatementContext extends ParserRuleContext { - public TerminalNode RETURN() { return getToken(JackParser.RETURN, 0); } - public TerminalNode SEMICOLON() { return getToken(JackParser.SEMICOLON, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public ReturnStatementContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_returnStatement; } - } - - public final ReturnStatementContext returnStatement() throws RecognitionException { - ReturnStatementContext _localctx = new ReturnStatementContext(_ctx, getState()); - enterRule(_localctx, 60, RULE_returnStatement); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(243); - match(RETURN); - setState(245); - _errHandler.sync(this); - _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & 69286950338560L) != 0)) { - { - setState(244); - expression(0); - } - } - - setState(247); - match(SEMICOLON); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ExpressionListContext extends ParserRuleContext { - public List expression() { - return getRuleContexts(ExpressionContext.class); - } - public ExpressionContext expression(int i) { - return getRuleContext(ExpressionContext.class,i); - } - public List COMMA() { return getTokens(JackParser.COMMA); } - public TerminalNode COMMA(int i) { - return getToken(JackParser.COMMA, i); - } - public ExpressionListContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_expressionList; } - } - - public final ExpressionListContext expressionList() throws RecognitionException { - ExpressionListContext _localctx = new ExpressionListContext(_ctx, getState()); - enterRule(_localctx, 62, RULE_expressionList); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(257); - _errHandler.sync(this); - _la = _input.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & 69286950338560L) != 0)) { - { - setState(249); - expression(0); - setState(254); - _errHandler.sync(this); - _la = _input.LA(1); - while (_la==COMMA) { - { - { - setState(250); - match(COMMA); - setState(251); - expression(0); - } - } - setState(256); - _errHandler.sync(this); - _la = _input.LA(1); - } - } - } - - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ExpressionContext extends ParserRuleContext { - public ConstantContext constant() { - return getRuleContext(ConstantContext.class,0); - } - public VarNameContext varName() { - return getRuleContext(VarNameContext.class,0); - } - public SubroutineCallContext subroutineCall() { - return getRuleContext(SubroutineCallContext.class,0); - } - public ArrayAccessContext arrayAccess() { - return getRuleContext(ArrayAccessContext.class,0); - } - public UnaryOperationContext unaryOperation() { - return getRuleContext(UnaryOperationContext.class,0); - } - public GroupedExpressionContext groupedExpression() { - return getRuleContext(GroupedExpressionContext.class,0); - } - public List expression() { - return getRuleContexts(ExpressionContext.class); - } - public ExpressionContext expression(int i) { - return getRuleContext(ExpressionContext.class,i); - } - public BinaryOperatorContext binaryOperator() { - return getRuleContext(BinaryOperatorContext.class,0); - } - public ExpressionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_expression; } - } - - public final ExpressionContext expression() throws RecognitionException { - return expression(0); - } - - private ExpressionContext expression(int _p) throws RecognitionException { - ParserRuleContext _parentctx = _ctx; - int _parentState = getState(); - ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState); - ExpressionContext _prevctx = _localctx; - int _startState = 64; - enterRecursionRule(_localctx, 64, RULE_expression, _p); - try { - int _alt; - enterOuterAlt(_localctx, 1); - { - setState(266); - _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) { - case 1: - { - setState(260); - constant(); - } - break; - case 2: - { - setState(261); - varName(); - } - break; - case 3: - { - setState(262); - subroutineCall(); - } - break; - case 4: - { - setState(263); - arrayAccess(); - } - break; - case 5: - { - setState(264); - unaryOperation(); - } - break; - case 6: - { - setState(265); - groupedExpression(); - } - break; - } - _ctx.stop = _input.LT(-1); - setState(274); - _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,18,_ctx); - while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { - if ( _alt==1 ) { - if ( _parseListeners!=null ) triggerExitRuleEvent(); - _prevctx = _localctx; - { - { - _localctx = new ExpressionContext(_parentctx, _parentState); - pushNewRecursionContext(_localctx, _startState, RULE_expression); - setState(268); - if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); - setState(269); - binaryOperator(); - setState(270); - expression(8); - } - } - } - setState(276); - _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,18,_ctx); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - unrollRecursionContexts(_parentctx); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class GroupedExpressionContext extends ParserRuleContext { - public TerminalNode LPAREN() { return getToken(JackParser.LPAREN, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode RPAREN() { return getToken(JackParser.RPAREN, 0); } - public GroupedExpressionContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_groupedExpression; } - } - - public final GroupedExpressionContext groupedExpression() throws RecognitionException { - GroupedExpressionContext _localctx = new GroupedExpressionContext(_ctx, getState()); - enterRule(_localctx, 66, RULE_groupedExpression); - try { - enterOuterAlt(_localctx, 1); - { - setState(277); - match(LPAREN); - setState(278); - expression(0); - setState(279); - match(RPAREN); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class UnaryOperationContext extends ParserRuleContext { - public UnaryOperatorContext unaryOperator() { - return getRuleContext(UnaryOperatorContext.class,0); - } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public UnaryOperationContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_unaryOperation; } - } - - public final UnaryOperationContext unaryOperation() throws RecognitionException { - UnaryOperationContext _localctx = new UnaryOperationContext(_ctx, getState()); - enterRule(_localctx, 68, RULE_unaryOperation); - try { - enterOuterAlt(_localctx, 1); - { - setState(281); - unaryOperator(); - setState(282); - expression(0); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ArrayAccessContext extends ParserRuleContext { - public VarNameContext varName() { - return getRuleContext(VarNameContext.class,0); - } - public TerminalNode LBRACKET() { return getToken(JackParser.LBRACKET, 0); } - public ExpressionContext expression() { - return getRuleContext(ExpressionContext.class,0); - } - public TerminalNode RBRACKET() { return getToken(JackParser.RBRACKET, 0); } - public ArrayAccessContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_arrayAccess; } - } - - public final ArrayAccessContext arrayAccess() throws RecognitionException { - ArrayAccessContext _localctx = new ArrayAccessContext(_ctx, getState()); - enterRule(_localctx, 70, RULE_arrayAccess); - try { - enterOuterAlt(_localctx, 1); - { - setState(284); - varName(); - setState(285); - match(LBRACKET); - setState(286); - expression(0); - setState(287); - match(RBRACKET); - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class ConstantContext extends ParserRuleContext { - public TerminalNode INTEGER_LITERAL() { return getToken(JackParser.INTEGER_LITERAL, 0); } - public TerminalNode STRING_LITERAL() { return getToken(JackParser.STRING_LITERAL, 0); } - public TerminalNode BOOLEAN_LITERAL() { return getToken(JackParser.BOOLEAN_LITERAL, 0); } - public TerminalNode NULL_LITERAL() { return getToken(JackParser.NULL_LITERAL, 0); } - public TerminalNode THIS_LITERAL() { return getToken(JackParser.THIS_LITERAL, 0); } - public ConstantContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_constant; } - } - - public final ConstantContext constant() throws RecognitionException { - ConstantContext _localctx = new ConstantContext(_ctx, getState()); - enterRule(_localctx, 72, RULE_constant); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(289); - _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 51677046505472L) != 0)) ) { - _errHandler.recoverInline(this); - } - else { - if ( _input.LA(1)==Token.EOF ) matchedEOF = true; - _errHandler.reportMatch(this); - consume(); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class UnaryOperatorContext extends ParserRuleContext { - public TerminalNode TILDE() { return getToken(JackParser.TILDE, 0); } - public TerminalNode MINUS() { return getToken(JackParser.MINUS, 0); } - public UnaryOperatorContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_unaryOperator; } - } - - public final UnaryOperatorContext unaryOperator() throws RecognitionException { - UnaryOperatorContext _localctx = new UnaryOperatorContext(_ctx, getState()); - enterRule(_localctx, 74, RULE_unaryOperator); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(291); - _la = _input.LA(1); - if ( !(_la==MINUS || _la==TILDE) ) { - _errHandler.recoverInline(this); - } - else { - if ( _input.LA(1)==Token.EOF ) matchedEOF = true; - _errHandler.reportMatch(this); - consume(); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - @SuppressWarnings("CheckReturnValue") - public static class BinaryOperatorContext extends ParserRuleContext { - public TerminalNode PLUS() { return getToken(JackParser.PLUS, 0); } - public TerminalNode MINUS() { return getToken(JackParser.MINUS, 0); } - public TerminalNode MUL() { return getToken(JackParser.MUL, 0); } - public TerminalNode DIV() { return getToken(JackParser.DIV, 0); } - public TerminalNode AND() { return getToken(JackParser.AND, 0); } - public TerminalNode OR() { return getToken(JackParser.OR, 0); } - public TerminalNode LESS_THAN() { return getToken(JackParser.LESS_THAN, 0); } - public TerminalNode GREATER_THAN() { return getToken(JackParser.GREATER_THAN, 0); } - public TerminalNode EQUALS() { return getToken(JackParser.EQUALS, 0); } - public BinaryOperatorContext(ParserRuleContext parent, int invokingState) { - super(parent, invokingState); - } - @Override public int getRuleIndex() { return RULE_binaryOperator; } - } - - public final BinaryOperatorContext binaryOperator() throws RecognitionException { - BinaryOperatorContext _localctx = new BinaryOperatorContext(_ctx, getState()); - enterRule(_localctx, 76, RULE_binaryOperator); - int _la; - try { - enterOuterAlt(_localctx, 1); - { - setState(293); - _la = _input.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & 120124866560L) != 0)) ) { - _errHandler.recoverInline(this); - } - else { - if ( _input.LA(1)==Token.EOF ) matchedEOF = true; - _errHandler.reportMatch(this); - consume(); - } - } - } - catch (RecognitionException re) { - _localctx.exception = re; - _errHandler.reportError(this, re); - _errHandler.recover(this, re); - } - finally { - exitRule(); - } - return _localctx; - } - - public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { - switch (ruleIndex) { - case 32: - return expression_sempred((ExpressionContext)_localctx, predIndex); - } - return true; - } - private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { - switch (predIndex) { - case 0: - return precpred(_ctx, 7); - } - return true; - } - - public static final String _serializedATN = - "\u0004\u0001.\u0128\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ - "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002"+ - "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002"+ - "\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b\u0007\u000b\u0002"+ - "\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e\u0002\u000f\u0007\u000f"+ - "\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011\u0002\u0012\u0007\u0012"+ - "\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014\u0002\u0015\u0007\u0015"+ - "\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017\u0002\u0018\u0007\u0018"+ - "\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a\u0002\u001b\u0007\u001b"+ - "\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d\u0002\u001e\u0007\u001e"+ - "\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007!\u0002\"\u0007\"\u0002"+ - "#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007&\u0001\u0000\u0001\u0000"+ - "\u0001\u0000\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0005\u0001"+ - "V\b\u0001\n\u0001\f\u0001Y\t\u0001\u0001\u0001\u0005\u0001\\\b\u0001\n"+ - "\u0001\f\u0001_\t\u0001\u0001\u0001\u0001\u0001\u0001\u0002\u0001\u0002"+ - "\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0004\u0001\u0004"+ - "\u0001\u0004\u0001\u0004\u0005\u0004m\b\u0004\n\u0004\f\u0004p\t\u0004"+ - "\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007"+ - "\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b\u0001"+ - "\t\u0001\t\u0001\n\u0001\n\u0003\n\u0084\b\n\u0001\u000b\u0001\u000b\u0001"+ - "\f\u0001\f\u0001\f\u0005\f\u008b\b\f\n\f\f\f\u008e\t\f\u0003\f\u0090\b"+ - "\f\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f"+ - "\u0005\u000f\u0099\b\u000f\n\u000f\f\u000f\u009c\t\u000f\u0001\u000f\u0001"+ - "\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001"+ - "\u0011\u0001\u0011\u0001\u0011\u0005\u0011\u00a8\b\u0011\n\u0011\f\u0011"+ - "\u00ab\t\u0011\u0001\u0011\u0001\u0011\u0001\u0012\u0001\u0012\u0001\u0013"+ - "\u0001\u0013\u0001\u0014\u0005\u0014\u00b4\b\u0014\n\u0014\f\u0014\u00b7"+ - "\t\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0003"+ - "\u0015\u00be\b\u0015\u0001\u0016\u0001\u0016\u0001\u0016\u0003\u0016\u00c3"+ - "\b\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0016\u0001\u0017\u0001"+ - "\u0017\u0003\u0017\u00cb\b\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001"+ - "\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019\u0001"+ - "\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001"+ - "\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001"+ - "\u001b\u0001\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001"+ - "\u001c\u0001\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0003\u001d\u00ed"+ - "\b\u001d\u0001\u001d\u0003\u001d\u00f0\b\u001d\u0001\u001d\u0001\u001d"+ - "\u0001\u001e\u0001\u001e\u0003\u001e\u00f6\b\u001e\u0001\u001e\u0001\u001e"+ - "\u0001\u001f\u0001\u001f\u0001\u001f\u0005\u001f\u00fd\b\u001f\n\u001f"+ - "\f\u001f\u0100\t\u001f\u0003\u001f\u0102\b\u001f\u0001 \u0001 \u0001 "+ - "\u0001 \u0001 \u0001 \u0001 \u0003 \u010b\b \u0001 \u0001 \u0001 \u0001"+ - " \u0005 \u0111\b \n \f \u0114\t \u0001!\u0001!\u0001!\u0001!\u0001\"\u0001"+ - "\"\u0001\"\u0001#\u0001#\u0001#\u0001#\u0001#\u0001$\u0001$\u0001%\u0001"+ - "%\u0001&\u0001&\u0001&\u0000\u0001@\'\u0000\u0002\u0004\u0006\b\n\f\u000e"+ - "\u0010\u0012\u0014\u0016\u0018\u001a\u001c\u001e \"$&(*,.02468:<>@BDF"+ - "HJL\u0000\u0006\u0001\u0000\u0005\u0006\u0001\u0000\u0002\u0004\u0002"+ - "\u0000\b\n,,\u0002\u0000(+--\u0002\u0000\u001d\u001d\"\"\u0002\u0000\u001b"+ - "!#$\u011a\u0000N\u0001\u0000\u0000\u0000\u0002Q\u0001\u0000\u0000\u0000"+ - "\u0004b\u0001\u0000\u0000\u0000\u0006d\u0001\u0000\u0000\u0000\bh\u0001"+ - "\u0000\u0000\u0000\nq\u0001\u0000\u0000\u0000\fs\u0001\u0000\u0000\u0000"+ - "\u000ev\u0001\u0000\u0000\u0000\u0010x\u0001\u0000\u0000\u0000\u0012\u007f"+ - "\u0001\u0000\u0000\u0000\u0014\u0083\u0001\u0000\u0000\u0000\u0016\u0085"+ - "\u0001\u0000\u0000\u0000\u0018\u008f\u0001\u0000\u0000\u0000\u001a\u0091"+ - "\u0001\u0000\u0000\u0000\u001c\u0094\u0001\u0000\u0000\u0000\u001e\u0096"+ - "\u0001\u0000\u0000\u0000 \u00a0\u0001\u0000\u0000\u0000\"\u00a2\u0001"+ - "\u0000\u0000\u0000$\u00ae\u0001\u0000\u0000\u0000&\u00b0\u0001\u0000\u0000"+ - "\u0000(\u00b5\u0001\u0000\u0000\u0000*\u00bd\u0001\u0000\u0000\u0000,"+ - "\u00bf\u0001\u0000\u0000\u0000.\u00c8\u0001\u0000\u0000\u00000\u00cc\u0001"+ - "\u0000\u0000\u00002\u00d4\u0001\u0000\u0000\u00004\u00d9\u0001\u0000\u0000"+ - "\u00006\u00e1\u0001\u0000\u0000\u00008\u00e5\u0001\u0000\u0000\u0000:"+ - "\u00ef\u0001\u0000\u0000\u0000<\u00f3\u0001\u0000\u0000\u0000>\u0101\u0001"+ - "\u0000\u0000\u0000@\u010a\u0001\u0000\u0000\u0000B\u0115\u0001\u0000\u0000"+ - "\u0000D\u0119\u0001\u0000\u0000\u0000F\u011c\u0001\u0000\u0000\u0000H"+ - "\u0121\u0001\u0000\u0000\u0000J\u0123\u0001\u0000\u0000\u0000L\u0125\u0001"+ - "\u0000\u0000\u0000NO\u0003\u0002\u0001\u0000OP\u0005\u0000\u0000\u0001"+ - "P\u0001\u0001\u0000\u0000\u0000QR\u0005\u0001\u0000\u0000RS\u0003\u0004"+ - "\u0002\u0000SW\u0005\u0012\u0000\u0000TV\u0003\u0006\u0003\u0000UT\u0001"+ - "\u0000\u0000\u0000VY\u0001\u0000\u0000\u0000WU\u0001\u0000\u0000\u0000"+ - "WX\u0001\u0000\u0000\u0000X]\u0001\u0000\u0000\u0000YW\u0001\u0000\u0000"+ - "\u0000Z\\\u0003\f\u0006\u0000[Z\u0001\u0000\u0000\u0000\\_\u0001\u0000"+ - "\u0000\u0000][\u0001\u0000\u0000\u0000]^\u0001\u0000\u0000\u0000^`\u0001"+ - "\u0000\u0000\u0000_]\u0001\u0000\u0000\u0000`a\u0003 \u0010\u0000a\u0003"+ - "\u0001\u0000\u0000\u0000bc\u0005,\u0000\u0000c\u0005\u0001\u0000\u0000"+ - "\u0000de\u0007\u0000\u0000\u0000ef\u0003\b\u0004\u0000fg\u0005\u001a\u0000"+ - "\u0000g\u0007\u0001\u0000\u0000\u0000hi\u0003\u0016\u000b\u0000in\u0003"+ - "\n\u0005\u0000jk\u0005\u0019\u0000\u0000km\u0003\n\u0005\u0000lj\u0001"+ - "\u0000\u0000\u0000mp\u0001\u0000\u0000\u0000nl\u0001\u0000\u0000\u0000"+ - "no\u0001\u0000\u0000\u0000o\t\u0001\u0000\u0000\u0000pn\u0001\u0000\u0000"+ - "\u0000qr\u0005,\u0000\u0000r\u000b\u0001\u0000\u0000\u0000st\u0003\u000e"+ - "\u0007\u0000tu\u0003\u0010\b\u0000u\r\u0001\u0000\u0000\u0000vw\u0007"+ - "\u0001\u0000\u0000w\u000f\u0001\u0000\u0000\u0000xy\u0003\u0014\n\u0000"+ - "yz\u0003\u0012\t\u0000z{\u0005\u0014\u0000\u0000{|\u0003\u0018\f\u0000"+ - "|}\u0005\u0015\u0000\u0000}~\u0003\u001e\u000f\u0000~\u0011\u0001\u0000"+ - "\u0000\u0000\u007f\u0080\u0005,\u0000\u0000\u0080\u0013\u0001\u0000\u0000"+ - "\u0000\u0081\u0084\u0003\u0016\u000b\u0000\u0082\u0084\u0005\u000b\u0000"+ - "\u0000\u0083\u0081\u0001\u0000\u0000\u0000\u0083\u0082\u0001\u0000\u0000"+ - "\u0000\u0084\u0015\u0001\u0000\u0000\u0000\u0085\u0086\u0007\u0002\u0000"+ - "\u0000\u0086\u0017\u0001\u0000\u0000\u0000\u0087\u008c\u0003\u001a\r\u0000"+ - "\u0088\u0089\u0005\u0019\u0000\u0000\u0089\u008b\u0003\u001a\r\u0000\u008a"+ - "\u0088\u0001\u0000\u0000\u0000\u008b\u008e\u0001\u0000\u0000\u0000\u008c"+ - "\u008a\u0001\u0000\u0000\u0000\u008c\u008d\u0001\u0000\u0000\u0000\u008d"+ - "\u0090\u0001\u0000\u0000\u0000\u008e\u008c\u0001\u0000\u0000\u0000\u008f"+ - "\u0087\u0001\u0000\u0000\u0000\u008f\u0090\u0001\u0000\u0000\u0000\u0090"+ - "\u0019\u0001\u0000\u0000\u0000\u0091\u0092\u0003\u0016\u000b\u0000\u0092"+ - "\u0093\u0003\u001c\u000e\u0000\u0093\u001b\u0001\u0000\u0000\u0000\u0094"+ - "\u0095\u0005,\u0000\u0000\u0095\u001d\u0001\u0000\u0000\u0000\u0096\u009a"+ - "\u0005\u0012\u0000\u0000\u0097\u0099\u0003\"\u0011\u0000\u0098\u0097\u0001"+ - "\u0000\u0000\u0000\u0099\u009c\u0001\u0000\u0000\u0000\u009a\u0098\u0001"+ - "\u0000\u0000\u0000\u009a\u009b\u0001\u0000\u0000\u0000\u009b\u009d\u0001"+ - "\u0000\u0000\u0000\u009c\u009a\u0001\u0000\u0000\u0000\u009d\u009e\u0003"+ - "(\u0014\u0000\u009e\u009f\u0003 \u0010\u0000\u009f\u001f\u0001\u0000\u0000"+ - "\u0000\u00a0\u00a1\u0005\u0013\u0000\u0000\u00a1!\u0001\u0000\u0000\u0000"+ - "\u00a2\u00a3\u0005\u0007\u0000\u0000\u00a3\u00a4\u0003\u0016\u000b\u0000"+ - "\u00a4\u00a9\u0003$\u0012\u0000\u00a5\u00a6\u0005\u0019\u0000\u0000\u00a6"+ - "\u00a8\u0003$\u0012\u0000\u00a7\u00a5\u0001\u0000\u0000\u0000\u00a8\u00ab"+ - "\u0001\u0000\u0000\u0000\u00a9\u00a7\u0001\u0000\u0000\u0000\u00a9\u00aa"+ - "\u0001\u0000\u0000\u0000\u00aa\u00ac\u0001\u0000\u0000\u0000\u00ab\u00a9"+ - "\u0001\u0000\u0000\u0000\u00ac\u00ad\u0005\u001a\u0000\u0000\u00ad#\u0001"+ - "\u0000\u0000\u0000\u00ae\u00af\u0005,\u0000\u0000\u00af%\u0001\u0000\u0000"+ - "\u0000\u00b0\u00b1\u0005,\u0000\u0000\u00b1\'\u0001\u0000\u0000\u0000"+ - "\u00b2\u00b4\u0003*\u0015\u0000\u00b3\u00b2\u0001\u0000\u0000\u0000\u00b4"+ - "\u00b7\u0001\u0000\u0000\u0000\u00b5\u00b3\u0001\u0000\u0000\u0000\u00b5"+ - "\u00b6\u0001\u0000\u0000\u0000\u00b6)\u0001\u0000\u0000\u0000\u00b7\u00b5"+ - "\u0001\u0000\u0000\u0000\u00b8\u00be\u0003,\u0016\u0000\u00b9\u00be\u0003"+ - ".\u0017\u0000\u00ba\u00be\u00034\u001a\u0000\u00bb\u00be\u00036\u001b"+ - "\u0000\u00bc\u00be\u0003<\u001e\u0000\u00bd\u00b8\u0001\u0000\u0000\u0000"+ - "\u00bd\u00b9\u0001\u0000\u0000\u0000\u00bd\u00ba\u0001\u0000\u0000\u0000"+ - "\u00bd\u00bb\u0001\u0000\u0000\u0000\u00bd\u00bc\u0001\u0000\u0000\u0000"+ - "\u00be+\u0001\u0000\u0000\u0000\u00bf\u00c2\u0005\f\u0000\u0000\u00c0"+ - "\u00c3\u0003&\u0013\u0000\u00c1\u00c3\u0003F#\u0000\u00c2\u00c0\u0001"+ - "\u0000\u0000\u0000\u00c2\u00c1\u0001\u0000\u0000\u0000\u00c3\u00c4\u0001"+ - "\u0000\u0000\u0000\u00c4\u00c5\u0005\u001b\u0000\u0000\u00c5\u00c6\u0003"+ - "@ \u0000\u00c6\u00c7\u0005\u001a\u0000\u0000\u00c7-\u0001\u0000\u0000"+ - "\u0000\u00c8\u00ca\u00030\u0018\u0000\u00c9\u00cb\u00032\u0019\u0000\u00ca"+ - "\u00c9\u0001\u0000\u0000\u0000\u00ca\u00cb\u0001\u0000\u0000\u0000\u00cb"+ - "/\u0001\u0000\u0000\u0000\u00cc\u00cd\u0005\u000e\u0000\u0000\u00cd\u00ce"+ - "\u0005\u0014\u0000\u0000\u00ce\u00cf\u0003@ \u0000\u00cf\u00d0\u0005\u0015"+ - "\u0000\u0000\u00d0\u00d1\u0005\u0012\u0000\u0000\u00d1\u00d2\u0003(\u0014"+ - "\u0000\u00d2\u00d3\u0003 \u0010\u0000\u00d31\u0001\u0000\u0000\u0000\u00d4"+ - "\u00d5\u0005\u000f\u0000\u0000\u00d5\u00d6\u0005\u0012\u0000\u0000\u00d6"+ - "\u00d7\u0003(\u0014\u0000\u00d7\u00d8\u0003 \u0010\u0000\u00d83\u0001"+ - "\u0000\u0000\u0000\u00d9\u00da\u0005\u0010\u0000\u0000\u00da\u00db\u0005"+ - "\u0014\u0000\u0000\u00db\u00dc\u0003@ \u0000\u00dc\u00dd\u0005\u0015\u0000"+ - "\u0000\u00dd\u00de\u0005\u0012\u0000\u0000\u00de\u00df\u0003(\u0014\u0000"+ - "\u00df\u00e0\u0003 \u0010\u0000\u00e05\u0001\u0000\u0000\u0000\u00e1\u00e2"+ - "\u0005\r\u0000\u0000\u00e2\u00e3\u00038\u001c\u0000\u00e3\u00e4\u0005"+ - "\u001a\u0000\u0000\u00e47\u0001\u0000\u0000\u0000\u00e5\u00e6\u0003:\u001d"+ - "\u0000\u00e6\u00e7\u0005\u0014\u0000\u0000\u00e7\u00e8\u0003>\u001f\u0000"+ - "\u00e8\u00e9\u0005\u0015\u0000\u0000\u00e99\u0001\u0000\u0000\u0000\u00ea"+ - "\u00ed\u0003\u0004\u0002\u0000\u00eb\u00ed\u0005+\u0000\u0000\u00ec\u00ea"+ - "\u0001\u0000\u0000\u0000\u00ec\u00eb\u0001\u0000\u0000\u0000\u00ed\u00ee"+ - "\u0001\u0000\u0000\u0000\u00ee\u00f0\u0005\u0018\u0000\u0000\u00ef\u00ec"+ - "\u0001\u0000\u0000\u0000\u00ef\u00f0\u0001\u0000\u0000\u0000\u00f0\u00f1"+ - "\u0001\u0000\u0000\u0000\u00f1\u00f2\u0003\u0012\t\u0000\u00f2;\u0001"+ - "\u0000\u0000\u0000\u00f3\u00f5\u0005\u0011\u0000\u0000\u00f4\u00f6\u0003"+ - "@ \u0000\u00f5\u00f4\u0001\u0000\u0000\u0000\u00f5\u00f6\u0001\u0000\u0000"+ - "\u0000\u00f6\u00f7\u0001\u0000\u0000\u0000\u00f7\u00f8\u0005\u001a\u0000"+ - "\u0000\u00f8=\u0001\u0000\u0000\u0000\u00f9\u00fe\u0003@ \u0000\u00fa"+ - "\u00fb\u0005\u0019\u0000\u0000\u00fb\u00fd\u0003@ \u0000\u00fc\u00fa\u0001"+ - "\u0000\u0000\u0000\u00fd\u0100\u0001\u0000\u0000\u0000\u00fe\u00fc\u0001"+ - "\u0000\u0000\u0000\u00fe\u00ff\u0001\u0000\u0000\u0000\u00ff\u0102\u0001"+ - "\u0000\u0000\u0000\u0100\u00fe\u0001\u0000\u0000\u0000\u0101\u00f9\u0001"+ - "\u0000\u0000\u0000\u0101\u0102\u0001\u0000\u0000\u0000\u0102?\u0001\u0000"+ - "\u0000\u0000\u0103\u0104\u0006 \uffff\uffff\u0000\u0104\u010b\u0003H$"+ - "\u0000\u0105\u010b\u0003&\u0013\u0000\u0106\u010b\u00038\u001c\u0000\u0107"+ - "\u010b\u0003F#\u0000\u0108\u010b\u0003D\"\u0000\u0109\u010b\u0003B!\u0000"+ - "\u010a\u0103\u0001\u0000\u0000\u0000\u010a\u0105\u0001\u0000\u0000\u0000"+ - "\u010a\u0106\u0001\u0000\u0000\u0000\u010a\u0107\u0001\u0000\u0000\u0000"+ - "\u010a\u0108\u0001\u0000\u0000\u0000\u010a\u0109\u0001\u0000\u0000\u0000"+ - "\u010b\u0112\u0001\u0000\u0000\u0000\u010c\u010d\n\u0007\u0000\u0000\u010d"+ - "\u010e\u0003L&\u0000\u010e\u010f\u0003@ \b\u010f\u0111\u0001\u0000\u0000"+ - "\u0000\u0110\u010c\u0001\u0000\u0000\u0000\u0111\u0114\u0001\u0000\u0000"+ - "\u0000\u0112\u0110\u0001\u0000\u0000\u0000\u0112\u0113\u0001\u0000\u0000"+ - "\u0000\u0113A\u0001\u0000\u0000\u0000\u0114\u0112\u0001\u0000\u0000\u0000"+ - "\u0115\u0116\u0005\u0014\u0000\u0000\u0116\u0117\u0003@ \u0000\u0117\u0118"+ - "\u0005\u0015\u0000\u0000\u0118C\u0001\u0000\u0000\u0000\u0119\u011a\u0003"+ - "J%\u0000\u011a\u011b\u0003@ \u0000\u011bE\u0001\u0000\u0000\u0000\u011c"+ - "\u011d\u0003&\u0013\u0000\u011d\u011e\u0005\u0016\u0000\u0000\u011e\u011f"+ - "\u0003@ \u0000\u011f\u0120\u0005\u0017\u0000\u0000\u0120G\u0001\u0000"+ - "\u0000\u0000\u0121\u0122\u0007\u0003\u0000\u0000\u0122I\u0001\u0000\u0000"+ - "\u0000\u0123\u0124\u0007\u0004\u0000\u0000\u0124K\u0001\u0000\u0000\u0000"+ - "\u0125\u0126\u0007\u0005\u0000\u0000\u0126M\u0001\u0000\u0000\u0000\u0013"+ - "W]n\u0083\u008c\u008f\u009a\u00a9\u00b5\u00bd\u00c2\u00ca\u00ec\u00ef"+ - "\u00f5\u00fe\u0101\u010a\u0112"; - public static final ATN _ATN = - new ATNDeserializer().deserialize(_serializedATN.toCharArray()); - static { - _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; - for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { - _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); - } - } -} \ No newline at end of file diff --git a/compiler/grammar/.antlr/JackParser.tokens b/compiler/grammar/.antlr/JackParser.tokens deleted file mode 100644 index 8292b05c..00000000 --- a/compiler/grammar/.antlr/JackParser.tokens +++ /dev/null @@ -1,84 +0,0 @@ -CLASS=1 -CONSTRUCTOR=2 -FUNCTION=3 -METHOD=4 -FIELD=5 -STATIC=6 -VAR=7 -INT=8 -CHAR=9 -BOOLEAN=10 -VOID=11 -LET=12 -DO=13 -IF=14 -ELSE=15 -WHILE=16 -RETURN=17 -LBRACE=18 -RBRACE=19 -LPAREN=20 -RPAREN=21 -LBRACKET=22 -RBRACKET=23 -DOT=24 -COMMA=25 -SEMICOLON=26 -EQUALS=27 -PLUS=28 -MINUS=29 -MUL=30 -DIV=31 -AND=32 -OR=33 -TILDE=34 -LESS_THAN=35 -GREATER_THAN=36 -WS=37 -COMMENT=38 -LINE_COMMENT=39 -INTEGER_LITERAL=40 -BOOLEAN_LITERAL=41 -NULL_LITERAL=42 -THIS_LITERAL=43 -IDENTIFIER=44 -STRING_LITERAL=45 -UnterminatedStringLiteral=46 -'class'=1 -'constructor'=2 -'function'=3 -'method'=4 -'field'=5 -'static'=6 -'var'=7 -'int'=8 -'char'=9 -'boolean'=10 -'void'=11 -'let'=12 -'do'=13 -'if'=14 -'else'=15 -'while'=16 -'return'=17 -'{'=18 -'}'=19 -'('=20 -')'=21 -'['=22 -']'=23 -'.'=24 -','=25 -';'=26 -'='=27 -'+'=28 -'-'=29 -'*'=30 -'/'=31 -'&'=32 -'|'=33 -'~'=34 -'<'=35 -'>'=36 -'null'=42 -'this'=43 diff --git a/compiler/grammar/JackLexer.g4 b/compiler/grammar/JackLexer.g4 deleted file mode 100644 index 7ad3e5ca..00000000 --- a/compiler/grammar/JackLexer.g4 +++ /dev/null @@ -1,61 +0,0 @@ -lexer grammar JackLexer; - -CLASS: 'class'; -CONSTRUCTOR: 'constructor'; -FUNCTION: 'function'; -METHOD: 'method'; -FIELD: 'field'; -STATIC: 'static'; -VAR: 'var'; -INT: 'int'; -CHAR: 'char'; -BOOLEAN: 'boolean'; -VOID: 'void'; - -LET: 'let'; -DO: 'do'; -IF: 'if'; -ELSE: 'else'; -WHILE: 'while'; -RETURN: 'return'; - - -LBRACE: '{'; -RBRACE: '}'; -LPAREN: '('; -RPAREN: ')'; -LBRACKET: '['; -RBRACKET: ']'; -DOT: '.'; -COMMA: ','; -SEMICOLON: ';'; - -EQUALS: '='; -PLUS: '+'; -MINUS: '-'; -MUL: '*'; -DIV: '/'; -AND: '&'; -OR: '|'; -TILDE: '~'; -LESS_THAN: '<'; -GREATER_THAN: '>'; - -WS: [ \t\r\n]+ -> skip; -COMMENT: '/*' .*? '*/' -> skip; -LINE_COMMENT: '//' ~[\r\n]* -> skip; - -INTEGER_LITERAL: [0-9]+; -BOOLEAN_LITERAL: 'true' | 'false'; -NULL_LITERAL: 'null'; -THIS_LITERAL: 'this'; - -IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; - -STRING_LITERAL - : UnterminatedStringLiteral '"' - ; -UnterminatedStringLiteral - : '"' ~["\\\r\n]* - ; - diff --git a/compiler/grammar/JackParser.g4 b/compiler/grammar/JackParser.g4 deleted file mode 100644 index a3e45e4c..00000000 --- a/compiler/grammar/JackParser.g4 +++ /dev/null @@ -1,89 +0,0 @@ -parser grammar JackParser; - -options { - tokenVocab = JackLexer; -} - -program: classDeclaration EOF; -classDeclaration: - CLASS className LBRACE classVarDec* subroutineDeclaration* rBrace; -className: IDENTIFIER; -classVarDec: (STATIC | FIELD) fieldList SEMICOLON; -fieldList: varType fieldName ( COMMA fieldName)*; -fieldName: IDENTIFIER; -subroutineDeclaration: subroutineType subroutineDecWithoutType; -subroutineType: CONSTRUCTOR | METHOD | FUNCTION; -subroutineDecWithoutType: - subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; -subroutineName: IDENTIFIER; -subroutineReturnType: varType | VOID; - -varType: INT | CHAR | BOOLEAN | IDENTIFIER; - -parameterList: (parameter (COMMA parameter)*)?; -parameter: varType parameterName; -parameterName: IDENTIFIER; -subroutineBody: LBRACE varDeclaration* statements rBrace; -rBrace: RBRACE; -varDeclaration: - VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; -varNameInDeclaration: IDENTIFIER; -varName: IDENTIFIER; -statements: statement*; -statement: - letStatement - | ifElseStatement - | whileStatement - | doStatement - | returnStatement; - -letStatement: - LET (varName | arrayAccess) EQUALS expression SEMICOLON; //TODO: check if we need right assoc for this - -ifElseStatement: ifStatement elseStatement?; -ifStatement: - IF LPAREN expression RPAREN LBRACE statements rBrace; -elseStatement: ELSE LBRACE statements rBrace; - -whileStatement: - WHILE LPAREN expression RPAREN LBRACE statements rBrace; - -doStatement: DO subroutineCall SEMICOLON; - -subroutineCall: subroutineId LPAREN expressionList RPAREN; -subroutineId: ((className | THIS_LITERAL) DOT)? subroutineName; -returnStatement: RETURN expression? SEMICOLON; - -expressionList: (expression (COMMA expression)*)?; - -expression: - expression binaryOperator expression - | constant - | varName - | subroutineCall - | arrayAccess - | unaryOperation - | groupedExpression; - -groupedExpression: LPAREN expression RPAREN; -unaryOperation: unaryOperator expression; -arrayAccess: varName LBRACKET expression RBRACKET; - -constant: - INTEGER_LITERAL - | STRING_LITERAL - | BOOLEAN_LITERAL - | NULL_LITERAL - | THIS_LITERAL; - -unaryOperator: TILDE | MINUS; -binaryOperator: - PLUS - | MINUS - | MUL - | DIV - | AND - | OR - | LESS_THAN - | GREATER_THAN - | EQUALS; \ No newline at end of file diff --git a/compiler/index.html b/compiler/index.html deleted file mode 100644 index 8fb68e12..00000000 --- a/compiler/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - Jack image converter - - - - - - - - - - - Jack image converter - - - - -
-
-
- - -
- - -
-
-
-
- -
-
- - - -
- -
- - - - - - - - - - \ No newline at end of file diff --git a/compiler/jest.config.ts b/compiler/jest.config.ts deleted file mode 100644 index ff8a25d8..00000000 --- a/compiler/jest.config.ts +++ /dev/null @@ -1,203 +0,0 @@ -/** - * For a detailed explanation regarding each configuration property, visit: - * https://jestjs.io/docs/configuration - */ - -/** @type {import('jest').Config} */ -const config = { - - - - // All imported modules in your tests should be mocked automatically - // automock: false, - - // Stop running tests after `n` failures - // bail: 0, - - // The directory where Jest should store its cached dependency information - // cacheDirectory: "/tmp/jest_rs", - - // Automatically clear mock calls, instances, contexts and results before every test - // clearMocks: false, - - // Indicates whether the coverage information should be collected while executing the test - // collectCoverage: false, - - // An array of glob patterns indicating a set of files for which coverage information should be collected - // collectCoverageFrom: undefined, - - // The directory where Jest should output its coverage files - // coverageDirectory: undefined, - - // An array of regexp pattern strings used to skip coverage collection - // coveragePathIgnorePatterns: [ - // "/node_modules/" - // ], - - // Indicates which provider should be used to instrument code for coverage - coverageProvider: "v8", - - // A list of reporter names that Jest uses when writing coverage reports - // coverageReporters: [ - // "json", - // "text", - // "lcov", - // "clover" - // ], - - // An object that configures minimum threshold enforcement for coverage results - // coverageThreshold: undefined, - - // A path to a custom dependency extractor - // dependencyExtractor: undefined, - - // Make calling deprecated APIs throw helpful error messages - errorOnDeprecated: true, - - // The default configuration for fake timers - // fakeTimers: { - // "enableGlobally": false - // }, - - // Force coverage collection from ignored files using an array of glob patterns - // forceCoverageMatch: [], - - // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: undefined, - - // A path to a module which exports an async function that is triggered once after all test suites - // globalTeardown: undefined, - - // A set of global variables that need to be available in all test environments - // globals: {}, - - // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. - maxWorkers: "50%", - - // An array of directory names to be searched recursively up from the requiring module's location - moduleDirectories: [ - "node_modules" - ], - - // An array of file extensions your modules use - // moduleFileExtensions: [ - // "js", - // "mjs", - // "cjs", - // "jsx", - // "ts", - // "tsx", - // "json", - // "node" - // ], - - // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module - // moduleNameMapper: {}, - - // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], - - // Activates notifications for test results - //TODO: try out - notify: true, - - - // An enum that specifies notification mode. Requires { notify: true } - // notifyMode: "failure-change", - - // A preset that is used as a base for Jest's configuration - preset: 'ts-jest', - - // Run tests from one or more projects - // projects: undefined, - - // Use this configuration option to add custom reporters to Jest - // reporters: undefined, - - // Automatically reset mock state before every test - // resetMocks: false, - - // Reset the module registry before running each individual test - // resetModules: false, - - // A path to a custom resolver - // resolver: undefined, - - // Automatically restore mock state and implementation before every test - // restoreMocks: false, - - // The root directory that Jest should scan for tests and modules within - // rootDir: undefined, - - // A list of paths to directories that Jest should use to search for files in - // roots: [ - // "" - // ], - - // Allows you to use a custom runner instead of Jest's default test runner - // runner: "jest-runner", - - // The paths to modules that run some code to configure or set up the testing environment before each test - // setupFiles: [], - - // A list of paths to modules that run some code to configure or set up the testing framework before each test - // setupFilesAfterEnv: [], - - // The number of seconds after which a test is considered as slow and reported as such in the results. - slowTestThreshold: 5, - - // A list of paths to snapshot serializer modules Jest should use for snapshot testing - // snapshotSerializers: [], - - // The test environment that will be used for testing - testEnvironment: 'node', - - // Options that will be passed to the testEnvironment - // testEnvironmentOptions: {}, - - // Adds a location field to test results - // testLocationInResults: false, - - // The glob patterns Jest uses to detect test files - // testMatch: [ - // "**/__tests__/**/*.[jt]s?(x)", - // "**/?(*.)+(spec|test).[tj]s?(x)" - // ], - - // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - testPathIgnorePatterns: [ - "/node_modules/" - ], - - // The regexp pattern or array of patterns that Jest uses to detect test files - // testRegex: [], - - // This option allows the use of a custom results processor - // testResultsProcessor: undefined, - - // This option allows use of a custom test runner - // testRunner: "jest-circus/runner", - - // A map from regular expressions to paths to transformers - // transform: undefined, - - // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "/node_modules/", - // "\\.pnp\\.[^\\/]+$" - // ], - - // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them - // unmockedModulePathPatterns: undefined, - - // Indicates whether each individual test should be reported during the run - verbose: true, - - // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode - // watchPathIgnorePatterns: [], - - // Whether to use watchman for file crawling - watchman: true, -}; - -export default config; diff --git a/compiler/package.json b/compiler/package.json deleted file mode 100644 index 01943b8d..00000000 --- a/compiler/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "compiler", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "preview": "vite preview", - "test": "jest", - "test-w": "jest --watchAll", - "fix": "eslint --fix", - "gen": "bash gen.sh", - "watch-jack": "nodemon -e jack,ts -w src -w test -x \"npm run test \"" - }, - "nodemonConfig": { - "delay": 700 - }, - "modulePaths": [ - "/src/" - ], - "devDependencies": { - "@types/jest": "^29.5.13", - "@types/node": "^22.5.5", - "antlr4ts-cli": "0.5.0-alpha.4", - "jest": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-text-transformer": "^1.0.4", - "node-notifier": "^10.0.1", - "nodemon": "^3.1.7", - "npm-watch": "^0.13.0", - "ts-jest": "^29.2.5", - "ts-node": "^10.9.2", - "typescript": "^5.5.3", - "vite": "^5.4.1" - }, - "dependencies": { - "antlr4ts": "0.5.0-alpha.4" - } -} diff --git a/compiler/pnpm-lock.yaml b/compiler/pnpm-lock.yaml deleted file mode 100644 index 64b3bc0d..00000000 --- a/compiler/pnpm-lock.yaml +++ /dev/null @@ -1,3489 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - antlr4ts: - specifier: 0.5.0-alpha.4 - version: 0.5.0-alpha.4 - devDependencies: - '@types/jest': - specifier: ^29.5.13 - version: 29.5.13 - '@types/node': - specifier: ^22.5.5 - version: 22.5.5 - antlr4ts-cli: - specifier: 0.5.0-alpha.4 - version: 0.5.0-alpha.4 - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - jest-matcher-utils: - specifier: ^29.7.0 - version: 29.7.0 - jest-text-transformer: - specifier: ^1.0.4 - version: 1.0.4 - node-notifier: - specifier: ^10.0.1 - version: 10.0.1 - nodemon: - specifier: ^3.1.7 - version: 3.1.7 - npm-watch: - specifier: ^0.13.0 - version: 0.13.0 - ts-jest: - specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)))(typescript@5.6.2) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@22.5.5)(typescript@5.6.2) - typescript: - specifier: ^5.5.3 - version: 5.6.2 - vite: - specifier: ^5.4.1 - version: 5.4.7(@types/node@22.5.5) - -packages: - - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - - '@babel/code-frame@7.24.7': - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.25.4': - resolution: {integrity: sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.25.2': - resolution: {integrity: sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.25.6': - resolution: {integrity: sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.25.2': - resolution: {integrity: sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.24.7': - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.25.2': - resolution: {integrity: sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.24.8': - resolution: {integrity: sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-simple-access@7.24.7': - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.24.8': - resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.24.7': - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.24.8': - resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.25.6': - resolution: {integrity: sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==} - engines: {node: '>=6.9.0'} - - '@babel/highlight@7.24.7': - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.25.6': - resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-bigint@7.8.3': - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-attributes@7.25.6': - resolution: {integrity: sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-jsx@7.24.7': - resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-typescript@7.25.4': - resolution: {integrity: sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/template@7.25.0': - resolution: {integrity: sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.25.6': - resolution: {integrity: sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.25.6': - resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==} - engines: {node: '>=6.9.0'} - - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@istanbuljs/load-nyc-config@1.1.0': - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - - '@istanbuljs/schema@0.1.3': - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - - '@jest/console@29.7.0': - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/core@29.7.0': - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/environment@29.7.0': - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect-utils@29.7.0': - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect@29.7.0': - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/fake-timers@29.7.0': - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/globals@29.7.0': - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/reporters@29.7.0': - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/source-map@29.6.3': - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-result@29.7.0': - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-sequencer@29.7.0': - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/transform@29.7.0': - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/types@29.6.3': - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jridgewell/gen-mapping@0.3.5': - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - - '@rollup/rollup-android-arm-eabi@4.22.4': - resolution: {integrity: sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.22.4': - resolution: {integrity: sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.22.4': - resolution: {integrity: sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.22.4': - resolution: {integrity: sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-linux-arm-gnueabihf@4.22.4': - resolution: {integrity: sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.22.4': - resolution: {integrity: sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.22.4': - resolution: {integrity: sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.22.4': - resolution: {integrity: sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': - resolution: {integrity: sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.22.4': - resolution: {integrity: sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.22.4': - resolution: {integrity: sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.22.4': - resolution: {integrity: sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.22.4': - resolution: {integrity: sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-win32-arm64-msvc@4.22.4': - resolution: {integrity: sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.22.4': - resolution: {integrity: sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.22.4': - resolution: {integrity: sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==} - cpu: [x64] - os: [win32] - - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - - '@sinonjs/fake-timers@10.3.0': - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.6.8': - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.20.6': - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - - '@types/graceful-fs@4.1.9': - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - - '@types/istanbul-lib-coverage@2.0.6': - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - - '@types/istanbul-lib-report@3.0.3': - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - - '@types/istanbul-reports@3.0.4': - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - - '@types/jest@29.5.13': - resolution: {integrity: sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==} - - '@types/node@22.5.5': - resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==} - - '@types/stack-utils@2.0.3': - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - - '@types/yargs-parser@21.0.3': - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - '@types/yargs@17.0.33': - resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - - acorn@8.12.1: - resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} - engines: {node: '>=0.4.0'} - hasBin: true - - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - antlr4ts-cli@0.5.0-alpha.4: - resolution: {integrity: sha512-lVPVBTA2CVHRYILSKilL6Jd4hAumhSZZWA7UbQNQrmaSSj7dPmmYaN4bOmZG79cOy0lS00i4LY68JZZjZMWVrw==} - hasBin: true - - antlr4ts@0.5.0-alpha.4: - resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} - - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - - babel-jest@29.7.0: - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - - babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - - babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - babel-preset-current-node-syntax@1.1.0: - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 - - babel-preset-jest@29.6.3: - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - - brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - browserslist@4.23.3: - resolution: {integrity: sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - - bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - caniuse-lite@1.0.30001662: - resolution: {integrity: sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==} - - chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - - cjs-module-lexer@1.4.1: - resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - - co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - - collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - - color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - create-jest@29.7.0: - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - - cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - - debug@4.3.7: - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - - ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - - electron-to-chromium@1.5.27: - resolution: {integrity: sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==} - - emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - - expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - growly@1.3.0: - resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} - - has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - ignore-by-default@1.0.1: - resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} - - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - - is-core-module@2.15.1: - resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} - engines: {node: '>= 0.4'} - - is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - - is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - istanbul-lib-coverage@3.2.2: - resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} - engines: {node: '>=8'} - - istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - - istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - - istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} - - istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - - istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} - engines: {node: '>=8'} - - jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - - jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-cli@29.7.0: - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - jest-config@29.7.0: - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - - jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-pnp-resolver@1.2.3: - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - - jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-text-transformer@1.0.4: - resolution: {integrity: sha512-Qi3FpWP6EFxZimSD05Zlmd/WER8l/3agVG7e5voHgdnM2vTs45sxS/i8qMWMO/dBkoxajndrGXfJTvhEENnjqw==} - engines: {node: '>=9.5.0', npm: '>=5.8.0'} - - jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest@29.7.0: - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - - jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - - leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - - node-notifier@10.0.1: - resolution: {integrity: sha512-YX7TSyDukOZ0g+gmzjB6abKu+hTGvO8+8+gIFDsRCU2t8fLV/P2unmt+LGFaIa4y64aX98Qksa97rgz4vMNeLQ==} - - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - - nodemon@3.1.7: - resolution: {integrity: sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==} - engines: {node: '>=10'} - hasBin: true - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - npm-watch@0.13.0: - resolution: {integrity: sha512-MYcgocqCzYA44feZhFoYj69FfSaO0EeRE1gcRcmPaXIpNhUMAhNJ1pwic2C4Hn0OPOQmZKSl90CPgmwvOsVhTg==} - hasBin: true - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - picocolors@1.1.0: - resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - - postcss@8.4.47: - resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} - engines: {node: ^10 || ^12 || >=14} - - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - - pstree.remy@1.1.8: - resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} - - pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - resolve.exports@2.0.2: - resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} - engines: {node: '>=10'} - - resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - - rollup@4.22.4: - resolution: {integrity: sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - - shellwords@0.1.1: - resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} - - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - simple-update-notifier@2.0.0: - resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} - engines: {node: '>=10'} - - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - - stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} - - string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - - supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - - through2@4.0.2: - resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} - - tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - touch@3.1.1: - resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} - hasBin: true - - ts-jest@29.2.5: - resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - typescript@5.6.2: - resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} - engines: {node: '>=14.17'} - hasBin: true - - undefsafe@2.0.5: - resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} - - undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - - update-browserslist-db@1.1.0: - resolution: {integrity: sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - uuid@3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - hasBin: true - - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - - v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} - - vite@5.4.7: - resolution: {integrity: sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - -snapshots: - - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - - '@babel/code-frame@7.24.7': - dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.1.0 - - '@babel/compat-data@7.25.4': {} - - '@babel/core@7.25.2': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 - '@babel/helper-compilation-targets': 7.25.2 - '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) - '@babel/helpers': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 - convert-source-map: 2.0.0 - debug: 4.3.7(supports-color@5.5.0) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.25.6': - dependencies: - '@babel/types': 7.25.6 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - - '@babel/helper-compilation-targets@7.25.2': - dependencies: - '@babel/compat-data': 7.25.4 - '@babel/helper-validator-option': 7.24.8 - browserslist: 4.23.3 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-module-imports@7.24.7': - dependencies: - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.25.2(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.24.8': {} - - '@babel/helper-simple-access@7.24.7': - dependencies: - '@babel/traverse': 7.25.6 - '@babel/types': 7.25.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-string-parser@7.24.8': {} - - '@babel/helper-validator-identifier@7.24.7': {} - - '@babel/helper-validator-option@7.24.8': {} - - '@babel/helpers@7.25.6': - dependencies: - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 - - '@babel/highlight@7.24.7': - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.1.0 - - '@babel/parser@7.25.6': - dependencies: - '@babel/types': 7.25.6 - - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-import-attributes@7.25.6(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-plugin-utils': 7.24.8 - - '@babel/template@7.25.0': - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 - - '@babel/traverse@7.25.6': - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.25.6 - '@babel/parser': 7.25.6 - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 - debug: 4.3.7(supports-color@5.5.0) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - - '@babel/types@7.25.6': - dependencies: - '@babel/helper-string-parser': 7.24.8 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 - - '@bcoe/v8-coverage@0.2.3': {} - - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-x64@0.21.5': - optional: true - - '@esbuild/darwin-arm64@0.21.5': - optional: true - - '@esbuild/darwin-x64@0.21.5': - optional: true - - '@esbuild/freebsd-arm64@0.21.5': - optional: true - - '@esbuild/freebsd-x64@0.21.5': - optional: true - - '@esbuild/linux-arm64@0.21.5': - optional: true - - '@esbuild/linux-arm@0.21.5': - optional: true - - '@esbuild/linux-ia32@0.21.5': - optional: true - - '@esbuild/linux-loong64@0.21.5': - optional: true - - '@esbuild/linux-mips64el@0.21.5': - optional: true - - '@esbuild/linux-ppc64@0.21.5': - optional: true - - '@esbuild/linux-riscv64@0.21.5': - optional: true - - '@esbuild/linux-s390x@0.21.5': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/netbsd-x64@0.21.5': - optional: true - - '@esbuild/openbsd-x64@0.21.5': - optional: true - - '@esbuild/sunos-x64@0.21.5': - optional: true - - '@esbuild/win32-arm64@0.21.5': - optional: true - - '@esbuild/win32-ia32@0.21.5': - optional: true - - '@esbuild/win32-x64@0.21.5': - optional: true - - '@istanbuljs/load-nyc-config@1.1.0': - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - - '@istanbuljs/schema@0.1.3': {} - - '@jest/console@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - - '@jest/core@29.7.0(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2))': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0(node-notifier@10.0.1) - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - optionalDependencies: - node-notifier: 10.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - '@jest/environment@29.7.0': - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - jest-mock: 29.7.0 - - '@jest/expect-utils@29.7.0': - dependencies: - jest-get-type: 29.6.3 - - '@jest/expect@29.7.0': - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.5.5 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - '@jest/globals@29.7.0': - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/reporters@29.7.0(node-notifier@10.0.1)': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.5.5 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - optionalDependencies: - node-notifier: 10.0.1 - transitivePeerDependencies: - - supports-color - - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - - '@jest/source-map@29.6.3': - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - '@jest/test-result@29.7.0': - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - - '@jest/test-sequencer@29.7.0': - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - - '@jest/transform@29.7.0': - dependencies: - '@babel/core': 7.25.2 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.6 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - - '@jest/types@29.6.3': - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 22.5.5 - '@types/yargs': 17.0.33 - chalk: 4.1.2 - - '@jridgewell/gen-mapping@0.3.5': - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@rollup/rollup-android-arm-eabi@4.22.4': - optional: true - - '@rollup/rollup-android-arm64@4.22.4': - optional: true - - '@rollup/rollup-darwin-arm64@4.22.4': - optional: true - - '@rollup/rollup-darwin-x64@4.22.4': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.22.4': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.22.4': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.22.4': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.22.4': - optional: true - - '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.22.4': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.22.4': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.22.4': - optional: true - - '@rollup/rollup-linux-x64-musl@4.22.4': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.22.4': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.22.4': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.22.4': - optional: true - - '@sinclair/typebox@0.27.8': {} - - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 - - '@sinonjs/fake-timers@10.3.0': - dependencies: - '@sinonjs/commons': 3.0.1 - - '@tsconfig/node10@1.0.11': {} - - '@tsconfig/node12@1.0.11': {} - - '@tsconfig/node14@1.0.3': {} - - '@tsconfig/node16@1.0.4': {} - - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 - - '@types/babel__generator@7.6.8': - dependencies: - '@babel/types': 7.25.6 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.25.6 - '@babel/types': 7.25.6 - - '@types/babel__traverse@7.20.6': - dependencies: - '@babel/types': 7.25.6 - - '@types/estree@1.0.5': {} - - '@types/graceful-fs@4.1.9': - dependencies: - '@types/node': 22.5.5 - - '@types/istanbul-lib-coverage@2.0.6': {} - - '@types/istanbul-lib-report@3.0.3': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - - '@types/istanbul-reports@3.0.4': - dependencies: - '@types/istanbul-lib-report': 3.0.3 - - '@types/jest@29.5.13': - dependencies: - expect: 29.7.0 - pretty-format: 29.7.0 - - '@types/node@22.5.5': - dependencies: - undici-types: 6.19.8 - - '@types/stack-utils@2.0.3': {} - - '@types/yargs-parser@21.0.3': {} - - '@types/yargs@17.0.33': - dependencies: - '@types/yargs-parser': 21.0.3 - - acorn-walk@8.3.4: - dependencies: - acorn: 8.12.1 - - acorn@8.12.1: {} - - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 - - ansi-regex@5.0.1: {} - - ansi-styles@3.2.1: - dependencies: - color-convert: 1.9.3 - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@5.2.0: {} - - antlr4ts-cli@0.5.0-alpha.4: {} - - antlr4ts@0.5.0-alpha.4: {} - - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - arg@4.1.3: {} - - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 - - async@3.2.6: {} - - babel-jest@29.7.0(@babel/core@7.25.2): - dependencies: - '@babel/core': 7.25.2 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.25.2) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-istanbul@6.1.1: - dependencies: - '@babel/helper-plugin-utils': 7.24.8 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-jest-hoist@29.6.3: - dependencies: - '@babel/template': 7.25.0 - '@babel/types': 7.25.6 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.6 - - babel-preset-current-node-syntax@1.1.0(@babel/core@7.25.2): - dependencies: - '@babel/core': 7.25.2 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2) - '@babel/plugin-syntax-import-attributes': 7.25.6(@babel/core@7.25.2) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.25.2) - - babel-preset-jest@29.6.3(@babel/core@7.25.2): - dependencies: - '@babel/core': 7.25.2 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.2) - - balanced-match@1.0.2: {} - - binary-extensions@2.3.0: {} - - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - brace-expansion@2.0.1: - dependencies: - balanced-match: 1.0.2 - - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - - browserslist@4.23.3: - dependencies: - caniuse-lite: 1.0.30001662 - electron-to-chromium: 1.5.27 - node-releases: 2.0.18 - update-browserslist-db: 1.1.0(browserslist@4.23.3) - - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 - - bser@2.1.1: - dependencies: - node-int64: 0.4.0 - - buffer-from@1.1.2: {} - - callsites@3.1.0: {} - - camelcase@5.3.1: {} - - camelcase@6.3.0: {} - - caniuse-lite@1.0.30001662: {} - - chalk@2.4.2: - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - char-regex@1.0.2: {} - - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - - ci-info@3.9.0: {} - - cjs-module-lexer@1.4.1: {} - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - co@4.6.0: {} - - collect-v8-coverage@1.0.2: {} - - color-convert@1.9.3: - dependencies: - color-name: 1.1.3 - - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.3: {} - - color-name@1.1.4: {} - - concat-map@0.0.1: {} - - convert-source-map@2.0.0: {} - - create-jest@29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - create-require@1.1.1: {} - - cross-spawn@7.0.3: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - debug@4.3.7(supports-color@5.5.0): - dependencies: - ms: 2.1.3 - optionalDependencies: - supports-color: 5.5.0 - - dedent@1.5.3: {} - - deepmerge@4.3.1: {} - - detect-newline@3.1.0: {} - - diff-sequences@29.6.3: {} - - diff@4.0.2: {} - - ejs@3.1.10: - dependencies: - jake: 10.9.2 - - electron-to-chromium@1.5.27: {} - - emittery@0.13.1: {} - - emoji-regex@8.0.0: {} - - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - - esbuild@0.21.5: - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - - escalade@3.2.0: {} - - escape-string-regexp@1.0.5: {} - - escape-string-regexp@2.0.0: {} - - esprima@4.0.1: {} - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - exit@0.1.2: {} - - expect@29.7.0: - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - - fast-json-stable-stringify@2.1.0: {} - - fb-watchman@2.0.2: - dependencies: - bser: 2.1.1 - - filelist@1.0.4: - dependencies: - minimatch: 5.1.6 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - fs.realpath@1.0.0: {} - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - - get-package-type@0.1.0: {} - - get-stream@6.0.1: {} - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - globals@11.12.0: {} - - graceful-fs@4.2.11: {} - - growly@1.3.0: {} - - has-flag@3.0.0: {} - - has-flag@4.0.0: {} - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - html-escaper@2.0.2: {} - - human-signals@2.1.0: {} - - ignore-by-default@1.0.1: {} - - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - - imurmurhash@0.1.4: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-arrayish@0.2.1: {} - - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - - is-core-module@2.15.1: - dependencies: - hasown: 2.0.2 - - is-docker@2.2.1: {} - - is-extglob@2.1.1: {} - - is-fullwidth-code-point@3.0.0: {} - - is-generator-fn@2.1.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-stream@2.0.1: {} - - is-wsl@2.2.0: - dependencies: - is-docker: 2.2.1 - - isexe@2.0.0: {} - - istanbul-lib-coverage@3.2.2: {} - - istanbul-lib-instrument@5.2.1: - dependencies: - '@babel/core': 7.25.2 - '@babel/parser': 7.25.6 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - istanbul-lib-instrument@6.0.3: - dependencies: - '@babel/core': 7.25.2 - '@babel/parser': 7.25.6 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - istanbul-lib-report@3.0.1: - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 - - istanbul-lib-source-maps@4.0.1: - dependencies: - debug: 4.3.7(supports-color@5.5.0) - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - - istanbul-reports@3.1.7: - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - - jake@10.9.2: - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - - jest-changed-files@29.7.0: - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - - jest-circus@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.3 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-cli@29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)): - dependencies: - '@jest/core': 29.7.0(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - optionalDependencies: - node-notifier: 10.0.1 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest-config@29.7.0(@types/node@22.5.5)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)): - dependencies: - '@babel/core': 7.25.2 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.25.2) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 22.5.5 - ts-node: 10.9.2(@types/node@22.5.5)(typescript@5.6.2) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-diff@29.7.0: - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-docblock@29.7.0: - dependencies: - detect-newline: 3.1.0 - - jest-each@29.7.0: - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - - jest-environment-node@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - jest-get-type@29.6.3: {} - - jest-haste-map@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 22.5.5 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - - jest-leak-detector@29.7.0: - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-matcher-utils@29.7.0: - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-message-util@29.7.0: - dependencies: - '@babel/code-frame': 7.24.7 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - - jest-mock@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - jest-util: 29.7.0 - - jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - optionalDependencies: - jest-resolve: 29.7.0 - - jest-regex-util@29.6.3: {} - - jest-resolve-dependencies@29.7.0: - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - jest-resolve@29.7.0: - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.8 - resolve.exports: 2.0.2 - slash: 3.0.0 - - jest-runner@29.7.0: - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - - jest-runtime@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - chalk: 4.1.2 - cjs-module-lexer: 1.4.1 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - - jest-snapshot@29.7.0: - dependencies: - '@babel/core': 7.25.2 - '@babel/generator': 7.25.6 - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) - '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2) - '@babel/types': 7.25.6 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.25.2) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - - jest-text-transformer@1.0.4: - dependencies: - uuid: 3.4.0 - - jest-util@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - - jest-validate@29.7.0: - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - - jest-watcher@29.7.0: - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.5.5 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - - jest-worker@29.7.0: - dependencies: - '@types/node': 22.5.5 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - jest@29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)): - dependencies: - '@jest/core': 29.7.0(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - optionalDependencies: - node-notifier: 10.0.1 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - js-tokens@4.0.0: {} - - js-yaml@3.14.1: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - jsesc@2.5.2: {} - - json-parse-even-better-errors@2.3.1: {} - - json5@2.2.3: {} - - kleur@3.0.3: {} - - leven@3.1.0: {} - - lines-and-columns@1.2.4: {} - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - lodash.memoize@4.1.2: {} - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - make-dir@4.0.0: - dependencies: - semver: 7.6.3 - - make-error@1.3.6: {} - - makeerror@1.0.12: - dependencies: - tmpl: 1.0.5 - - merge-stream@2.0.0: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mimic-fn@2.1.0: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.1 - - ms@2.1.3: {} - - nanoid@3.3.7: {} - - natural-compare@1.4.0: {} - - node-int64@0.4.0: {} - - node-notifier@10.0.1: - dependencies: - growly: 1.3.0 - is-wsl: 2.2.0 - semver: 7.6.3 - shellwords: 0.1.1 - uuid: 8.3.2 - which: 2.0.2 - - node-releases@2.0.18: {} - - nodemon@3.1.7: - dependencies: - chokidar: 3.6.0 - debug: 4.3.7(supports-color@5.5.0) - ignore-by-default: 1.0.1 - minimatch: 3.1.2 - pstree.remy: 1.1.8 - semver: 7.6.3 - simple-update-notifier: 2.0.0 - supports-color: 5.5.0 - touch: 3.1.1 - undefsafe: 2.0.5 - - normalize-path@3.0.0: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - npm-watch@0.13.0: - dependencies: - nodemon: 3.1.7 - through2: 4.0.2 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - - p-try@2.2.0: {} - - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.24.7 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - - path-key@3.1.1: {} - - path-parse@1.0.7: {} - - picocolors@1.1.0: {} - - picomatch@2.3.1: {} - - pirates@4.0.6: {} - - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - - postcss@8.4.47: - dependencies: - nanoid: 3.3.7 - picocolors: 1.1.0 - source-map-js: 1.2.1 - - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - - pstree.remy@1.1.8: {} - - pure-rand@6.1.0: {} - - react-is@18.3.1: {} - - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - - require-directory@2.1.1: {} - - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 - - resolve-from@5.0.0: {} - - resolve.exports@2.0.2: {} - - resolve@1.22.8: - dependencies: - is-core-module: 2.15.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - rollup@4.22.4: - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.22.4 - '@rollup/rollup-android-arm64': 4.22.4 - '@rollup/rollup-darwin-arm64': 4.22.4 - '@rollup/rollup-darwin-x64': 4.22.4 - '@rollup/rollup-linux-arm-gnueabihf': 4.22.4 - '@rollup/rollup-linux-arm-musleabihf': 4.22.4 - '@rollup/rollup-linux-arm64-gnu': 4.22.4 - '@rollup/rollup-linux-arm64-musl': 4.22.4 - '@rollup/rollup-linux-powerpc64le-gnu': 4.22.4 - '@rollup/rollup-linux-riscv64-gnu': 4.22.4 - '@rollup/rollup-linux-s390x-gnu': 4.22.4 - '@rollup/rollup-linux-x64-gnu': 4.22.4 - '@rollup/rollup-linux-x64-musl': 4.22.4 - '@rollup/rollup-win32-arm64-msvc': 4.22.4 - '@rollup/rollup-win32-ia32-msvc': 4.22.4 - '@rollup/rollup-win32-x64-msvc': 4.22.4 - fsevents: 2.3.3 - - safe-buffer@5.2.1: {} - - semver@6.3.1: {} - - semver@7.6.3: {} - - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - - shellwords@0.1.1: {} - - signal-exit@3.0.7: {} - - simple-update-notifier@2.0.0: - dependencies: - semver: 7.6.3 - - sisteransi@1.0.5: {} - - slash@3.0.0: {} - - source-map-js@1.2.1: {} - - source-map-support@0.5.13: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - sprintf-js@1.0.3: {} - - stack-utils@2.0.6: - dependencies: - escape-string-regexp: 2.0.0 - - string-length@4.0.2: - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-bom@4.0.0: {} - - strip-final-newline@2.0.0: {} - - strip-json-comments@3.1.1: {} - - supports-color@5.5.0: - dependencies: - has-flag: 3.0.0 - - supports-color@7.2.0: - dependencies: - has-flag: 4.0.0 - - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - test-exclude@6.0.0: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - - through2@4.0.2: - dependencies: - readable-stream: 3.6.2 - - tmpl@1.0.5: {} - - to-fast-properties@2.0.0: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - - touch@3.1.1: {} - - ts-jest@29.2.5(@babel/core@7.25.2)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)))(typescript@5.6.2): - dependencies: - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.5.5)(node-notifier@10.0.1)(ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2)) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.6.3 - typescript: 5.6.2 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.25.2 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.25.2) - - ts-node@10.9.2(@types/node@22.5.5)(typescript@5.6.2): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 22.5.5 - acorn: 8.12.1 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.6.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - - type-detect@4.0.8: {} - - type-fest@0.21.3: {} - - typescript@5.6.2: {} - - undefsafe@2.0.5: {} - - undici-types@6.19.8: {} - - update-browserslist-db@1.1.0(browserslist@4.23.3): - dependencies: - browserslist: 4.23.3 - escalade: 3.2.0 - picocolors: 1.1.0 - - util-deprecate@1.0.2: {} - - uuid@3.4.0: {} - - uuid@8.3.2: {} - - v8-compile-cache-lib@3.0.1: {} - - v8-to-istanbul@9.3.0: - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 - - vite@5.4.7(@types/node@22.5.5): - dependencies: - esbuild: 0.21.5 - postcss: 8.4.47 - rollup: 4.22.4 - optionalDependencies: - '@types/node': 22.5.5 - fsevents: 2.3.3 - - walker@1.0.8: - dependencies: - makeerror: 1.0.12 - - which@2.0.2: - dependencies: - isexe: 2.0.0 - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - write-file-atomic@4.0.2: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - - y18n@5.0.8: {} - - yallist@3.1.1: {} - - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yn@3.1.1: {} - - yocto-queue@0.1.0: {} diff --git a/compiler/public/vite.svg b/compiler/public/vite.svg deleted file mode 100644 index e7b8dfb1..00000000 --- a/compiler/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/compiler/src/builtins.ts b/compiler/src/builtins.ts deleted file mode 100644 index c9ef3ffc..00000000 --- a/compiler/src/builtins.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { GenericSymbol, SubroutineType } from "./symbol"; - -export const builtInTypes = ["int", "boolean", "char"] -interface Range { - min: number; - max: number; -} -export const intRange = { min: -32768, max: 32767 } as Range; -//TODO: should we convert this to symbols? -const builtInFunctionsToArgCount: Record = { - "Array.dispose": 0, - //TODO: what is this? - // "Array.init": 0, - "Array.new": 1, - "Keyboard.init": 0, - "Keyboard.keyPressed": 0, - "Keyboard.readChar": 0, - "Keyboard.readInt": 1, - "Keyboard.readLine": 1, - "Math.abs": 1, - "Math.divide": 2, - //TODO: what is this ? - // "Math.init": 0, - "Math.max": 2, - "Math.min": 2, - "Math.multiply": 2, - "Math.sqrt": 1, - "Memory.alloc": 1, - "Memory.deAlloc": 1, - // "Memory.init": 0, - "Memory.peek": 1, - "Memory.poke": 2, - "Output.backSpace": 0, - // "Output.init": 0, - "Output.moveCursor": 2, - "Output.printChar": 1, - "Output.printInt": 1, - "Output.println": 0, - "Output.printString": 1, - "Screen.clearScreen": 0, - "Screen.drawCircle": 3, - "Screen.drawLine": 4, - "Screen.drawPixel": 2, - "Screen.drawRectangle": 4, - // "Screen.init": 0, - "Screen.setColor": 1, - "String.appendChar": 1, - "String.backSpace": 0, - "String.charAt": 2, - "String.dispose": 0, - "String.doubleQuote": 0, - "String.eraseLastChar": 0, - // "String.init": 0, - "String.intValue": 0, - "String.length": 0, - "String.new": 1, - "String.newLine": 0, - "String.setCharAt": 1, - "String.setInt": 1, - "Sys.error": 1, - "Sys.halt": 0, - "Sys.wait": 1, -}; -const builtInClasses = ["Array", "Keyboard", "Math", "Memory", "Output", "Screen", "String", "Sys"] -const builtInClassesRecord = builtInClasses.reduce((acc, elem) => ({ - ...acc, - [elem]: {} as GenericSymbol -}), {} as Record) - -export const builtInSymbols = Object.keys(builtInFunctionsToArgCount).reduce((acc, elem) => ({ - ...acc, - [elem]: { - subroutineInfo: { - paramsCount: builtInFunctionsToArgCount[elem], - type: SubroutineType.Function - } - } as GenericSymbol -}), builtInClassesRecord) \ No newline at end of file diff --git a/compiler/src/compiler.ts b/compiler/src/compiler.ts deleted file mode 100644 index 8356276a..00000000 --- a/compiler/src/compiler.ts +++ /dev/null @@ -1,49 +0,0 @@ -import path from "path"; -import { BinderListener } from "./listener/binder.listener"; -import fs from "fs"; -import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; -import { JackParser } from "./generated/JackParser"; -import { CharStreams, CommonTokenStream } from "antlr4ts"; -import { JackLexer } from "./generated/JackLexer"; -import { ErrorListener } from "./listener/error.listener"; -import { ValidatorListener } from "./listener/validator.listener"; -import { JackCompilerError } from "./error"; -import { VMWriter } from "./listener/vm.writer.listener"; -export default class Compiler { - static compile(src: string): string | JackCompilerError[] { - - const globalSymbolsListener = new BinderListener(); - const errorListener = new ErrorListener(); - const lexer = new JackLexer(CharStreams.fromString(src)); - if (errorListener) { - lexer.removeErrorListeners(); - lexer.addErrorListener(errorListener); - } - const tokenStream = new CommonTokenStream(lexer); - const parser = new JackParser(tokenStream); - // parser.isTrace = trace; - if (errorListener != undefined) { - parser.removeErrorListeners(); - parser.addErrorListener(errorListener); - } - const tree = parser.program(); - if (errorListener.errors.length > 0) { - return errorListener.errors; - } - // console.log(tree.toStringTree(parser.ruleNames)); - - ParseTreeWalker.DEFAULT.walk(globalSymbolsListener, tree); - if (globalSymbolsListener.errors.length > 0) { - return globalSymbolsListener.errors; - } - const validator = new ValidatorListener(globalSymbolsListener.globalSymbolTable); - ParseTreeWalker.DEFAULT.walk(validator, tree); - if (validator.errors.length > 0) { - return globalSymbolsListener.errors; - } - const vmWriter = new VMWriter(globalSymbolsListener.globalSymbolTable); - ParseTreeWalker.DEFAULT.walk(vmWriter, tree); - - return vmWriter.result; - } -} \ No newline at end of file diff --git a/compiler/src/error.ts b/compiler/src/error.ts deleted file mode 100644 index 13888db8..00000000 --- a/compiler/src/error.ts +++ /dev/null @@ -1,172 +0,0 @@ -export class JackCompilerError { - /** - * - * @param line - line number - * @param charPositionInLine - charPositionInLine in the line - * @param msg - error message - */ - constructor(public line: number, public charPositionInLine: number, public msg: string) { - } - public toString = (): string => { - return this.constructor.name + `(${this.line}:${this.charPositionInLine} ${this.msg})`; - } -} - -export class LexerOrParserError extends Error { - /** - * - * @param line - line number - * @param charPositionInLine - charPositionInLine in the line - * @param msg - error message - */ - constructor(public filepath: string, public line: number, public charPositionInLine: number, public msg: string) { - super(msg); - } -} -//TODO: should add filepath to other errors? -export class DuplicatedSubroutineError extends JackCompilerError { - constructor(line: number, charPositionInLine: number, subroutineName: string) { - super(line, charPositionInLine, `Subroutine ${subroutineName} redeclared.`); - } -} - -export class DuplicatedVariableException extends JackCompilerError { - constructor(line: number, charPositionInLine: number, variableName: string) { - super(line, charPositionInLine, "Duplicated variable " + variableName); - } -} - - -export class UndeclaredVariableError extends JackCompilerError { - constructor(line: number, charPositionInLine: number, variableName: string) { - super(line, charPositionInLine, "Undeclared variable " + variableName); - } - -} - - -export class UnknownClassError extends JackCompilerError { - constructor(line: number, charPositionInLine: number, className: string) { - super(line, charPositionInLine, `Class ${className} doesn't exist`); - } - -} - -export class NonVoidFunctionNoReturnError extends JackCompilerError { - - //TODO: should we add a subroutine name? - constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `A non void subroutine must return a value`); - } - -} - -export class VoidSubroutineReturnsValueError extends JackCompilerError { - - constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `Cannot return a value from a void subroutine`); - Object.setPrototypeOf(this, VoidSubroutineReturnsValueError.prototype); - } - -} - -export class SubroutineNotAllPathsReturnError extends JackCompilerError { - - constructor(line: number, charPositionInLine: number, subroutineName: string) { - super(line, charPositionInLine, `Subroutine ${subroutineName}: not all code paths return a value`); - Object.setPrototypeOf(this, SubroutineNotAllPathsReturnError.prototype); - } - -} - -export class IncorrectParamsNumberInSubroutineCallError extends JackCompilerError { - - constructor(line: number, - charPositionInLine: number, - subroutineName: string, - expectedParamsCount: number, - actualParamsCount: number) { - - super(line, charPositionInLine, - `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)`); - Object.setPrototypeOf(this, IncorrectParamsNumberInSubroutineCallError.prototype); - } - -} -export class UnknownSubroutineCallError extends JackCompilerError { - constructor(line: number, - charPositionInLine: number, - subroutineName: string, - className?: string) { - super(line, charPositionInLine, `Can't find subroutine '${subroutineName}'${className ? ` in ${className}` : ""}`); - Object.setPrototypeOf(this, UnknownSubroutineCallError.prototype); - } -} -export class MethodCalledAsFunctionError extends JackCompilerError { - constructor(line: number, - charPositionInLine: number, - subroutineId: string) { - super(line, charPositionInLine, `Method ${subroutineId} was called as a function/constructor`); - Object.setPrototypeOf(this, MethodCalledAsFunctionError.prototype); - } -} -export class FunctionCalledAsMethodError extends JackCompilerError { - constructor(line: number, - charPositionInLine: number, - subroutineId: string) { - super(line, charPositionInLine, `Function or constructor ${subroutineId} was called as a method`); - Object.setPrototypeOf(this, FunctionCalledAsMethodError.prototype); - } -} - -export class IncorrectConstructorReturnType extends JackCompilerError { - constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `The return type of a constructor must be of the class type`); - Object.setPrototypeOf(this, IncorrectConstructorReturnType.prototype); - } -} - -export class UnreachableCodeError extends JackCompilerError { - constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `Unreachable code`); - Object.setPrototypeOf(this, UnreachableCodeError.prototype); - } -} - -export class ConstructorMushReturnThis extends JackCompilerError { - constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `A constructor must return 'this'`); - Object.setPrototypeOf(this, ConstructorMushReturnThis.prototype); - } -} - -const vowels = "aeiou" -export class WrongLiteralTypeError extends JackCompilerError { - constructor(line: number, charPositionInLine: number, typeName: string) { - const article = vowels.indexOf(typeName.substring(0, 1)) != -1 ? "an" : "a"; - super(line, charPositionInLine, `${article} ${typeName} value is expected`); - Object.setPrototypeOf(this, WrongLiteralTypeError.prototype); - } -} - -export class IntLiteralIsOutOfRange extends JackCompilerError { - constructor(line: number, charPositionInLine: number, value: number, min: number, max: number) { - super(line, charPositionInLine, `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}`); - Object.setPrototypeOf(this, IntLiteralIsOutOfRange.prototype); - } -} - - -export class FieldCantBeReferencedInFunction extends JackCompilerError { - constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `Field can't be referenced in a function`); - Object.setPrototypeOf(this, FieldCantBeReferencedInFunction.prototype); - } -} - -export class ThisCantBeReferencedInFunction extends JackCompilerError { - constructor(line: number, charPositionInLine: number) { - super(line, charPositionInLine, `this can't be referenced in a function`); - Object.setPrototypeOf(this, ThisCantBeReferencedInFunction.prototype); - } -} diff --git a/compiler/src/generated/JackLexer.interp b/compiler/src/generated/JackLexer.interp deleted file mode 100644 index 42ef73e8..00000000 --- a/compiler/src/generated/JackLexer.interp +++ /dev/null @@ -1,155 +0,0 @@ -token literal names: -null -'class' -'constructor' -'function' -'method' -'field' -'static' -'var' -'int' -'char' -'boolean' -'void' -'let' -'do' -'if' -'else' -'while' -'return' -'{' -'}' -'(' -')' -'[' -']' -'.' -',' -';' -'=' -'+' -'-' -'*' -'/' -'&' -'|' -'~' -'<' -'>' -null -null -null -null -null -'null' -'this' -null -null -null - -token symbolic names: -null -CLASS -CONSTRUCTOR -FUNCTION -METHOD -FIELD -STATIC -VAR -INT -CHAR -BOOLEAN -VOID -LET -DO -IF -ELSE -WHILE -RETURN -LBRACE -RBRACE -LPAREN -RPAREN -LBRACKET -RBRACKET -DOT -COMMA -SEMICOLON -EQUALS -PLUS -MINUS -MUL -DIV -AND -OR -TILDE -LESS_THAN -GREATER_THAN -WS -COMMENT -LINE_COMMENT -INTEGER_LITERAL -BOOLEAN_LITERAL -NULL_LITERAL -THIS_LITERAL -IDENTIFIER -STRING_LITERAL -UnterminatedStringLiteral - -rule names: -CLASS -CONSTRUCTOR -FUNCTION -METHOD -FIELD -STATIC -VAR -INT -CHAR -BOOLEAN -VOID -LET -DO -IF -ELSE -WHILE -RETURN -LBRACE -RBRACE -LPAREN -RPAREN -LBRACKET -RBRACKET -DOT -COMMA -SEMICOLON -EQUALS -PLUS -MINUS -MUL -DIV -AND -OR -TILDE -LESS_THAN -GREATER_THAN -WS -COMMENT -LINE_COMMENT -INTEGER_LITERAL -BOOLEAN_LITERAL -NULL_LITERAL -THIS_LITERAL -IDENTIFIER -STRING_LITERAL -UnterminatedStringLiteral - -channel names: -DEFAULT_TOKEN_CHANNEL -HIDDEN - -mode names: -DEFAULT_MODE - -atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 2, 48, 309, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3, 27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 3, 31, 3, 31, 3, 32, 3, 32, 3, 33, 3, 33, 3, 34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 3, 37, 3, 38, 6, 38, 236, 10, 38, 13, 38, 14, 38, 237, 3, 38, 3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 7, 39, 246, 10, 39, 12, 39, 14, 39, 249, 11, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 7, 40, 260, 10, 40, 12, 40, 14, 40, 263, 11, 40, 3, 40, 3, 40, 3, 41, 6, 41, 268, 10, 41, 13, 41, 14, 41, 269, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 3, 42, 5, 42, 281, 10, 42, 3, 43, 3, 43, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 44, 3, 44, 3, 44, 3, 45, 3, 45, 7, 45, 295, 10, 45, 12, 45, 14, 45, 298, 11, 45, 3, 46, 3, 46, 3, 46, 3, 47, 3, 47, 7, 47, 305, 10, 47, 12, 47, 14, 47, 308, 11, 47, 3, 247, 2, 2, 48, 3, 2, 3, 5, 2, 4, 7, 2, 5, 9, 2, 6, 11, 2, 7, 13, 2, 8, 15, 2, 9, 17, 2, 10, 19, 2, 11, 21, 2, 12, 23, 2, 13, 25, 2, 14, 27, 2, 15, 29, 2, 16, 31, 2, 17, 33, 2, 18, 35, 2, 19, 37, 2, 20, 39, 2, 21, 41, 2, 22, 43, 2, 23, 45, 2, 24, 47, 2, 25, 49, 2, 26, 51, 2, 27, 53, 2, 28, 55, 2, 29, 57, 2, 30, 59, 2, 31, 61, 2, 32, 63, 2, 33, 65, 2, 34, 67, 2, 35, 69, 2, 36, 71, 2, 37, 73, 2, 38, 75, 2, 39, 77, 2, 40, 79, 2, 41, 81, 2, 42, 83, 2, 43, 85, 2, 44, 87, 2, 45, 89, 2, 46, 91, 2, 47, 93, 2, 48, 3, 2, 8, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 3, 2, 50, 59, 5, 2, 67, 92, 97, 97, 99, 124, 6, 2, 50, 59, 67, 92, 97, 97, 99, 124, 6, 2, 12, 12, 15, 15, 36, 36, 94, 94, 2, 315, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2, 2, 91, 3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 3, 95, 3, 2, 2, 2, 5, 101, 3, 2, 2, 2, 7, 113, 3, 2, 2, 2, 9, 122, 3, 2, 2, 2, 11, 129, 3, 2, 2, 2, 13, 135, 3, 2, 2, 2, 15, 142, 3, 2, 2, 2, 17, 146, 3, 2, 2, 2, 19, 150, 3, 2, 2, 2, 21, 155, 3, 2, 2, 2, 23, 163, 3, 2, 2, 2, 25, 168, 3, 2, 2, 2, 27, 172, 3, 2, 2, 2, 29, 175, 3, 2, 2, 2, 31, 178, 3, 2, 2, 2, 33, 183, 3, 2, 2, 2, 35, 189, 3, 2, 2, 2, 37, 196, 3, 2, 2, 2, 39, 198, 3, 2, 2, 2, 41, 200, 3, 2, 2, 2, 43, 202, 3, 2, 2, 2, 45, 204, 3, 2, 2, 2, 47, 206, 3, 2, 2, 2, 49, 208, 3, 2, 2, 2, 51, 210, 3, 2, 2, 2, 53, 212, 3, 2, 2, 2, 55, 214, 3, 2, 2, 2, 57, 216, 3, 2, 2, 2, 59, 218, 3, 2, 2, 2, 61, 220, 3, 2, 2, 2, 63, 222, 3, 2, 2, 2, 65, 224, 3, 2, 2, 2, 67, 226, 3, 2, 2, 2, 69, 228, 3, 2, 2, 2, 71, 230, 3, 2, 2, 2, 73, 232, 3, 2, 2, 2, 75, 235, 3, 2, 2, 2, 77, 241, 3, 2, 2, 2, 79, 255, 3, 2, 2, 2, 81, 267, 3, 2, 2, 2, 83, 280, 3, 2, 2, 2, 85, 282, 3, 2, 2, 2, 87, 287, 3, 2, 2, 2, 89, 292, 3, 2, 2, 2, 91, 299, 3, 2, 2, 2, 93, 302, 3, 2, 2, 2, 95, 96, 7, 101, 2, 2, 96, 97, 7, 110, 2, 2, 97, 98, 7, 99, 2, 2, 98, 99, 7, 117, 2, 2, 99, 100, 7, 117, 2, 2, 100, 4, 3, 2, 2, 2, 101, 102, 7, 101, 2, 2, 102, 103, 7, 113, 2, 2, 103, 104, 7, 112, 2, 2, 104, 105, 7, 117, 2, 2, 105, 106, 7, 118, 2, 2, 106, 107, 7, 116, 2, 2, 107, 108, 7, 119, 2, 2, 108, 109, 7, 101, 2, 2, 109, 110, 7, 118, 2, 2, 110, 111, 7, 113, 2, 2, 111, 112, 7, 116, 2, 2, 112, 6, 3, 2, 2, 2, 113, 114, 7, 104, 2, 2, 114, 115, 7, 119, 2, 2, 115, 116, 7, 112, 2, 2, 116, 117, 7, 101, 2, 2, 117, 118, 7, 118, 2, 2, 118, 119, 7, 107, 2, 2, 119, 120, 7, 113, 2, 2, 120, 121, 7, 112, 2, 2, 121, 8, 3, 2, 2, 2, 122, 123, 7, 111, 2, 2, 123, 124, 7, 103, 2, 2, 124, 125, 7, 118, 2, 2, 125, 126, 7, 106, 2, 2, 126, 127, 7, 113, 2, 2, 127, 128, 7, 102, 2, 2, 128, 10, 3, 2, 2, 2, 129, 130, 7, 104, 2, 2, 130, 131, 7, 107, 2, 2, 131, 132, 7, 103, 2, 2, 132, 133, 7, 110, 2, 2, 133, 134, 7, 102, 2, 2, 134, 12, 3, 2, 2, 2, 135, 136, 7, 117, 2, 2, 136, 137, 7, 118, 2, 2, 137, 138, 7, 99, 2, 2, 138, 139, 7, 118, 2, 2, 139, 140, 7, 107, 2, 2, 140, 141, 7, 101, 2, 2, 141, 14, 3, 2, 2, 2, 142, 143, 7, 120, 2, 2, 143, 144, 7, 99, 2, 2, 144, 145, 7, 116, 2, 2, 145, 16, 3, 2, 2, 2, 146, 147, 7, 107, 2, 2, 147, 148, 7, 112, 2, 2, 148, 149, 7, 118, 2, 2, 149, 18, 3, 2, 2, 2, 150, 151, 7, 101, 2, 2, 151, 152, 7, 106, 2, 2, 152, 153, 7, 99, 2, 2, 153, 154, 7, 116, 2, 2, 154, 20, 3, 2, 2, 2, 155, 156, 7, 100, 2, 2, 156, 157, 7, 113, 2, 2, 157, 158, 7, 113, 2, 2, 158, 159, 7, 110, 2, 2, 159, 160, 7, 103, 2, 2, 160, 161, 7, 99, 2, 2, 161, 162, 7, 112, 2, 2, 162, 22, 3, 2, 2, 2, 163, 164, 7, 120, 2, 2, 164, 165, 7, 113, 2, 2, 165, 166, 7, 107, 2, 2, 166, 167, 7, 102, 2, 2, 167, 24, 3, 2, 2, 2, 168, 169, 7, 110, 2, 2, 169, 170, 7, 103, 2, 2, 170, 171, 7, 118, 2, 2, 171, 26, 3, 2, 2, 2, 172, 173, 7, 102, 2, 2, 173, 174, 7, 113, 2, 2, 174, 28, 3, 2, 2, 2, 175, 176, 7, 107, 2, 2, 176, 177, 7, 104, 2, 2, 177, 30, 3, 2, 2, 2, 178, 179, 7, 103, 2, 2, 179, 180, 7, 110, 2, 2, 180, 181, 7, 117, 2, 2, 181, 182, 7, 103, 2, 2, 182, 32, 3, 2, 2, 2, 183, 184, 7, 121, 2, 2, 184, 185, 7, 106, 2, 2, 185, 186, 7, 107, 2, 2, 186, 187, 7, 110, 2, 2, 187, 188, 7, 103, 2, 2, 188, 34, 3, 2, 2, 2, 189, 190, 7, 116, 2, 2, 190, 191, 7, 103, 2, 2, 191, 192, 7, 118, 2, 2, 192, 193, 7, 119, 2, 2, 193, 194, 7, 116, 2, 2, 194, 195, 7, 112, 2, 2, 195, 36, 3, 2, 2, 2, 196, 197, 7, 125, 2, 2, 197, 38, 3, 2, 2, 2, 198, 199, 7, 127, 2, 2, 199, 40, 3, 2, 2, 2, 200, 201, 7, 42, 2, 2, 201, 42, 3, 2, 2, 2, 202, 203, 7, 43, 2, 2, 203, 44, 3, 2, 2, 2, 204, 205, 7, 93, 2, 2, 205, 46, 3, 2, 2, 2, 206, 207, 7, 95, 2, 2, 207, 48, 3, 2, 2, 2, 208, 209, 7, 48, 2, 2, 209, 50, 3, 2, 2, 2, 210, 211, 7, 46, 2, 2, 211, 52, 3, 2, 2, 2, 212, 213, 7, 61, 2, 2, 213, 54, 3, 2, 2, 2, 214, 215, 7, 63, 2, 2, 215, 56, 3, 2, 2, 2, 216, 217, 7, 45, 2, 2, 217, 58, 3, 2, 2, 2, 218, 219, 7, 47, 2, 2, 219, 60, 3, 2, 2, 2, 220, 221, 7, 44, 2, 2, 221, 62, 3, 2, 2, 2, 222, 223, 7, 49, 2, 2, 223, 64, 3, 2, 2, 2, 224, 225, 7, 40, 2, 2, 225, 66, 3, 2, 2, 2, 226, 227, 7, 126, 2, 2, 227, 68, 3, 2, 2, 2, 228, 229, 7, 128, 2, 2, 229, 70, 3, 2, 2, 2, 230, 231, 7, 62, 2, 2, 231, 72, 3, 2, 2, 2, 232, 233, 7, 64, 2, 2, 233, 74, 3, 2, 2, 2, 234, 236, 9, 2, 2, 2, 235, 234, 3, 2, 2, 2, 236, 237, 3, 2, 2, 2, 237, 235, 3, 2, 2, 2, 237, 238, 3, 2, 2, 2, 238, 239, 3, 2, 2, 2, 239, 240, 8, 38, 2, 2, 240, 76, 3, 2, 2, 2, 241, 242, 7, 49, 2, 2, 242, 243, 7, 44, 2, 2, 243, 247, 3, 2, 2, 2, 244, 246, 11, 2, 2, 2, 245, 244, 3, 2, 2, 2, 246, 249, 3, 2, 2, 2, 247, 248, 3, 2, 2, 2, 247, 245, 3, 2, 2, 2, 248, 250, 3, 2, 2, 2, 249, 247, 3, 2, 2, 2, 250, 251, 7, 44, 2, 2, 251, 252, 7, 49, 2, 2, 252, 253, 3, 2, 2, 2, 253, 254, 8, 39, 2, 2, 254, 78, 3, 2, 2, 2, 255, 256, 7, 49, 2, 2, 256, 257, 7, 49, 2, 2, 257, 261, 3, 2, 2, 2, 258, 260, 10, 3, 2, 2, 259, 258, 3, 2, 2, 2, 260, 263, 3, 2, 2, 2, 261, 259, 3, 2, 2, 2, 261, 262, 3, 2, 2, 2, 262, 264, 3, 2, 2, 2, 263, 261, 3, 2, 2, 2, 264, 265, 8, 40, 2, 2, 265, 80, 3, 2, 2, 2, 266, 268, 9, 4, 2, 2, 267, 266, 3, 2, 2, 2, 268, 269, 3, 2, 2, 2, 269, 267, 3, 2, 2, 2, 269, 270, 3, 2, 2, 2, 270, 82, 3, 2, 2, 2, 271, 272, 7, 118, 2, 2, 272, 273, 7, 116, 2, 2, 273, 274, 7, 119, 2, 2, 274, 281, 7, 103, 2, 2, 275, 276, 7, 104, 2, 2, 276, 277, 7, 99, 2, 2, 277, 278, 7, 110, 2, 2, 278, 279, 7, 117, 2, 2, 279, 281, 7, 103, 2, 2, 280, 271, 3, 2, 2, 2, 280, 275, 3, 2, 2, 2, 281, 84, 3, 2, 2, 2, 282, 283, 7, 112, 2, 2, 283, 284, 7, 119, 2, 2, 284, 285, 7, 110, 2, 2, 285, 286, 7, 110, 2, 2, 286, 86, 3, 2, 2, 2, 287, 288, 7, 118, 2, 2, 288, 289, 7, 106, 2, 2, 289, 290, 7, 107, 2, 2, 290, 291, 7, 117, 2, 2, 291, 88, 3, 2, 2, 2, 292, 296, 9, 5, 2, 2, 293, 295, 9, 6, 2, 2, 294, 293, 3, 2, 2, 2, 295, 298, 3, 2, 2, 2, 296, 294, 3, 2, 2, 2, 296, 297, 3, 2, 2, 2, 297, 90, 3, 2, 2, 2, 298, 296, 3, 2, 2, 2, 299, 300, 5, 93, 47, 2, 300, 301, 7, 36, 2, 2, 301, 92, 3, 2, 2, 2, 302, 306, 7, 36, 2, 2, 303, 305, 10, 7, 2, 2, 304, 303, 3, 2, 2, 2, 305, 308, 3, 2, 2, 2, 306, 304, 3, 2, 2, 2, 306, 307, 3, 2, 2, 2, 307, 94, 3, 2, 2, 2, 308, 306, 3, 2, 2, 2, 10, 2, 237, 247, 261, 269, 280, 296, 306, 3, 8, 2, 2] \ No newline at end of file diff --git a/compiler/src/generated/JackLexer.tokens b/compiler/src/generated/JackLexer.tokens deleted file mode 100644 index 8292b05c..00000000 --- a/compiler/src/generated/JackLexer.tokens +++ /dev/null @@ -1,84 +0,0 @@ -CLASS=1 -CONSTRUCTOR=2 -FUNCTION=3 -METHOD=4 -FIELD=5 -STATIC=6 -VAR=7 -INT=8 -CHAR=9 -BOOLEAN=10 -VOID=11 -LET=12 -DO=13 -IF=14 -ELSE=15 -WHILE=16 -RETURN=17 -LBRACE=18 -RBRACE=19 -LPAREN=20 -RPAREN=21 -LBRACKET=22 -RBRACKET=23 -DOT=24 -COMMA=25 -SEMICOLON=26 -EQUALS=27 -PLUS=28 -MINUS=29 -MUL=30 -DIV=31 -AND=32 -OR=33 -TILDE=34 -LESS_THAN=35 -GREATER_THAN=36 -WS=37 -COMMENT=38 -LINE_COMMENT=39 -INTEGER_LITERAL=40 -BOOLEAN_LITERAL=41 -NULL_LITERAL=42 -THIS_LITERAL=43 -IDENTIFIER=44 -STRING_LITERAL=45 -UnterminatedStringLiteral=46 -'class'=1 -'constructor'=2 -'function'=3 -'method'=4 -'field'=5 -'static'=6 -'var'=7 -'int'=8 -'char'=9 -'boolean'=10 -'void'=11 -'let'=12 -'do'=13 -'if'=14 -'else'=15 -'while'=16 -'return'=17 -'{'=18 -'}'=19 -'('=20 -')'=21 -'['=22 -']'=23 -'.'=24 -','=25 -';'=26 -'='=27 -'+'=28 -'-'=29 -'*'=30 -'/'=31 -'&'=32 -'|'=33 -'~'=34 -'<'=35 -'>'=36 -'null'=42 -'this'=43 diff --git a/compiler/src/generated/JackLexer.ts b/compiler/src/generated/JackLexer.ts deleted file mode 100644 index 65243b37..00000000 --- a/compiler/src/generated/JackLexer.ts +++ /dev/null @@ -1,278 +0,0 @@ -// Generated from JackLexer.g4 by ANTLR 4.9.0-SNAPSHOT - - -import { ATN } from "antlr4ts/atn/ATN"; -import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; -import { CharStream } from "antlr4ts/CharStream"; -import { Lexer } from "antlr4ts/Lexer"; -import { LexerATNSimulator } from "antlr4ts/atn/LexerATNSimulator"; -import { NotNull } from "antlr4ts/Decorators"; -import { Override } from "antlr4ts/Decorators"; -import { RuleContext } from "antlr4ts/RuleContext"; -import { Vocabulary } from "antlr4ts/Vocabulary"; -import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; - -import * as Utils from "antlr4ts/misc/Utils"; - - -export class JackLexer extends Lexer { - public static readonly CLASS = 1; - public static readonly CONSTRUCTOR = 2; - public static readonly FUNCTION = 3; - public static readonly METHOD = 4; - public static readonly FIELD = 5; - public static readonly STATIC = 6; - public static readonly VAR = 7; - public static readonly INT = 8; - public static readonly CHAR = 9; - public static readonly BOOLEAN = 10; - public static readonly VOID = 11; - public static readonly LET = 12; - public static readonly DO = 13; - public static readonly IF = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly RETURN = 17; - public static readonly LBRACE = 18; - public static readonly RBRACE = 19; - public static readonly LPAREN = 20; - public static readonly RPAREN = 21; - public static readonly LBRACKET = 22; - public static readonly RBRACKET = 23; - public static readonly DOT = 24; - public static readonly COMMA = 25; - public static readonly SEMICOLON = 26; - public static readonly EQUALS = 27; - public static readonly PLUS = 28; - public static readonly MINUS = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly AND = 32; - public static readonly OR = 33; - public static readonly TILDE = 34; - public static readonly LESS_THAN = 35; - public static readonly GREATER_THAN = 36; - public static readonly WS = 37; - public static readonly COMMENT = 38; - public static readonly LINE_COMMENT = 39; - public static readonly INTEGER_LITERAL = 40; - public static readonly BOOLEAN_LITERAL = 41; - public static readonly NULL_LITERAL = 42; - public static readonly THIS_LITERAL = 43; - public static readonly IDENTIFIER = 44; - public static readonly STRING_LITERAL = 45; - public static readonly UnterminatedStringLiteral = 46; - - // tslint:disable:no-trailing-whitespace - public static readonly channelNames: string[] = [ - "DEFAULT_TOKEN_CHANNEL", "HIDDEN", - ]; - - // tslint:disable:no-trailing-whitespace - public static readonly modeNames: string[] = [ - "DEFAULT_MODE", - ]; - - public static readonly ruleNames: string[] = [ - "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", "VAR", - "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", - "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", - "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", - "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", - "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", - "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral", - ]; - - private static readonly _LITERAL_NAMES: Array = [ - undefined, "'class'", "'constructor'", "'function'", "'method'", "'field'", - "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", - "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", - "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", - "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", undefined, undefined, undefined, - undefined, undefined, "'null'", "'this'", - ]; - private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", - "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", - "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", - "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", - "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", - "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", - "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral", - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(JackLexer._LITERAL_NAMES, JackLexer._SYMBOLIC_NAMES, []); - - // @Override - // @NotNull - public get vocabulary(): Vocabulary { - return JackLexer.VOCABULARY; - } - // tslint:enable:no-trailing-whitespace - - - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(JackLexer._ATN, this); - } - - // @Override - public get grammarFileName(): string { return "JackLexer.g4"; } - - // @Override - public get ruleNames(): string[] { return JackLexer.ruleNames; } - - // @Override - public override get serializedATN(): string { return JackLexer._serializedATN; } - - // @Override - public get channelNames(): string[] { return JackLexer.channelNames; } - - // @Override - public get modeNames(): string[] { return JackLexer.modeNames; } - - public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x020\u0135\b\x01" + - "\x04\x02\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06" + - "\x04\x07\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r" + - "\t\r\x04\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t" + - "\x12\x04\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t" + - "\x17\x04\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t" + - "\x1C\x04\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t" + - "\"\x04#\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x04)\t)\x04*\t*\x04" + - "+\t+\x04,\t,\x04-\t-\x04.\t.\x04/\t/\x03\x02\x03\x02\x03\x02\x03\x02\x03" + - "\x02\x03\x02\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" + - "\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x04\x03\x04\x03\x04\x03\x04\x03" + - "\x04\x03\x04\x03\x04\x03\x04\x03\x04\x03\x05\x03\x05\x03\x05\x03\x05\x03" + - "\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03\x06\x03" + - "\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\x07\x03\b\x03\b\x03\b" + - "\x03\b\x03\t\x03\t\x03\t\x03\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03" + - "\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\v\x03\f\x03\f\x03\f\x03\f\x03\f\x03" + - "\r\x03\r\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x03\x0F\x03\x0F\x03\x0F\x03" + - "\x10\x03\x10\x03\x10\x03\x10\x03\x10\x03\x11\x03\x11\x03\x11\x03\x11\x03" + - "\x11\x03\x11\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03\x12\x03" + - "\x13\x03\x13\x03\x14\x03\x14\x03\x15\x03\x15\x03\x16\x03\x16\x03\x17\x03" + - "\x17\x03\x18\x03\x18\x03\x19\x03\x19\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03" + - "\x1C\x03\x1C\x03\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x03 \x03" + - " \x03!\x03!\x03\"\x03\"\x03#\x03#\x03$\x03$\x03%\x03%\x03&\x06&\xEC\n" + - "&\r&\x0E&\xED\x03&\x03&\x03\'\x03\'\x03\'\x03\'\x07\'\xF6\n\'\f\'\x0E" + - "\'\xF9\v\'\x03\'\x03\'\x03\'\x03\'\x03\'\x03(\x03(\x03(\x03(\x07(\u0104" + - "\n(\f(\x0E(\u0107\v(\x03(\x03(\x03)\x06)\u010C\n)\r)\x0E)\u010D\x03*\x03" + - "*\x03*\x03*\x03*\x03*\x03*\x03*\x03*\x05*\u0119\n*\x03+\x03+\x03+\x03" + - "+\x03+\x03,\x03,\x03,\x03,\x03,\x03-\x03-\x07-\u0127\n-\f-\x0E-\u012A" + - "\v-\x03.\x03.\x03.\x03/\x03/\x07/\u0131\n/\f/\x0E/\u0134\v/\x03\xF7\x02" + - "\x020\x03\x02\x03\x05\x02\x04\x07\x02\x05\t\x02\x06\v\x02\x07\r\x02\b" + - "\x0F\x02\t\x11\x02\n\x13\x02\v\x15\x02\f\x17\x02\r\x19\x02\x0E\x1B\x02" + - "\x0F\x1D\x02\x10\x1F\x02\x11!\x02\x12#\x02\x13%\x02\x14\'\x02\x15)\x02" + - "\x16+\x02\x17-\x02\x18/\x02\x191\x02\x1A3\x02\x1B5\x02\x1C7\x02\x1D9\x02" + - "\x1E;\x02\x1F=\x02 ?\x02!A\x02\"C\x02#E\x02$G\x02%I\x02&K\x02\'M\x02(" + - "O\x02)Q\x02*S\x02+U\x02,W\x02-Y\x02.[\x02/]\x020\x03\x02\b\x05\x02\v\f" + - "\x0F\x0F\"\"\x04\x02\f\f\x0F\x0F\x03\x022;\x05\x02C\\aac|\x06\x022;C\\" + - "aac|\x06\x02\f\f\x0F\x0F$$^^\x02\u013B\x02\x03\x03\x02\x02\x02\x02\x05" + - "\x03\x02\x02\x02\x02\x07\x03\x02\x02\x02\x02\t\x03\x02\x02\x02\x02\v\x03" + - "\x02\x02\x02\x02\r\x03\x02\x02\x02\x02\x0F\x03\x02\x02\x02\x02\x11\x03" + - "\x02\x02\x02\x02\x13\x03\x02\x02\x02\x02\x15\x03\x02\x02\x02\x02\x17\x03" + - "\x02\x02\x02\x02\x19\x03\x02\x02\x02\x02\x1B\x03\x02\x02\x02\x02\x1D\x03" + - "\x02\x02\x02\x02\x1F\x03\x02\x02\x02\x02!\x03\x02\x02\x02\x02#\x03\x02" + - "\x02\x02\x02%\x03\x02\x02\x02\x02\'\x03\x02\x02\x02\x02)\x03\x02\x02\x02" + - "\x02+\x03\x02\x02\x02\x02-\x03\x02\x02\x02\x02/\x03\x02\x02\x02\x021\x03" + - "\x02\x02\x02\x023\x03\x02\x02\x02\x025\x03\x02\x02\x02\x027\x03\x02\x02" + - "\x02\x029\x03\x02\x02\x02\x02;\x03\x02\x02\x02\x02=\x03\x02\x02\x02\x02" + - "?\x03\x02\x02\x02\x02A\x03\x02\x02\x02\x02C\x03\x02\x02\x02\x02E\x03\x02" + - "\x02\x02\x02G\x03\x02\x02\x02\x02I\x03\x02\x02\x02\x02K\x03\x02\x02\x02" + - "\x02M\x03\x02\x02\x02\x02O\x03\x02\x02\x02\x02Q\x03\x02\x02\x02\x02S\x03" + - "\x02\x02\x02\x02U\x03\x02\x02\x02\x02W\x03\x02\x02\x02\x02Y\x03\x02\x02" + - "\x02\x02[\x03\x02\x02\x02\x02]\x03\x02\x02\x02\x03_\x03\x02\x02\x02\x05" + - "e\x03\x02\x02\x02\x07q\x03\x02\x02\x02\tz\x03\x02\x02\x02\v\x81\x03\x02" + - "\x02\x02\r\x87\x03\x02\x02\x02\x0F\x8E\x03\x02\x02\x02\x11\x92\x03\x02" + - "\x02\x02\x13\x96\x03\x02\x02\x02\x15\x9B\x03\x02\x02\x02\x17\xA3\x03\x02" + - "\x02\x02\x19\xA8\x03\x02\x02\x02\x1B\xAC\x03\x02\x02\x02\x1D\xAF\x03\x02" + - "\x02\x02\x1F\xB2\x03\x02\x02\x02!\xB7\x03\x02\x02\x02#\xBD\x03\x02\x02" + - "\x02%\xC4\x03\x02\x02\x02\'\xC6\x03\x02\x02\x02)\xC8\x03\x02\x02\x02+" + - "\xCA\x03\x02\x02\x02-\xCC\x03\x02\x02\x02/\xCE\x03\x02\x02\x021\xD0\x03" + - "\x02\x02\x023\xD2\x03\x02\x02\x025\xD4\x03\x02\x02\x027\xD6\x03\x02\x02" + - "\x029\xD8\x03\x02\x02\x02;\xDA\x03\x02\x02\x02=\xDC\x03\x02\x02\x02?\xDE" + - "\x03\x02\x02\x02A\xE0\x03\x02\x02\x02C\xE2\x03\x02\x02\x02E\xE4\x03\x02" + - "\x02\x02G\xE6\x03\x02\x02\x02I\xE8\x03\x02\x02\x02K\xEB\x03\x02\x02\x02" + - "M\xF1\x03\x02\x02\x02O\xFF\x03\x02\x02\x02Q\u010B\x03\x02\x02\x02S\u0118" + - "\x03\x02\x02\x02U\u011A\x03\x02\x02\x02W\u011F\x03\x02\x02\x02Y\u0124" + - "\x03\x02\x02\x02[\u012B\x03\x02\x02\x02]\u012E\x03\x02\x02\x02_`\x07e" + - "\x02\x02`a\x07n\x02\x02ab\x07c\x02\x02bc\x07u\x02\x02cd\x07u\x02\x02d" + - "\x04\x03\x02\x02\x02ef\x07e\x02\x02fg\x07q\x02\x02gh\x07p\x02\x02hi\x07" + - "u\x02\x02ij\x07v\x02\x02jk\x07t\x02\x02kl\x07w\x02\x02lm\x07e\x02\x02" + - "mn\x07v\x02\x02no\x07q\x02\x02op\x07t\x02\x02p\x06\x03\x02\x02\x02qr\x07" + - "h\x02\x02rs\x07w\x02\x02st\x07p\x02\x02tu\x07e\x02\x02uv\x07v\x02\x02" + - "vw\x07k\x02\x02wx\x07q\x02\x02xy\x07p\x02\x02y\b\x03\x02\x02\x02z{\x07" + - "o\x02\x02{|\x07g\x02\x02|}\x07v\x02\x02}~\x07j\x02\x02~\x7F\x07q\x02\x02" + - "\x7F\x80\x07f\x02\x02\x80\n\x03\x02\x02\x02\x81\x82\x07h\x02\x02\x82\x83" + - "\x07k\x02\x02\x83\x84\x07g\x02\x02\x84\x85\x07n\x02\x02\x85\x86\x07f\x02" + - "\x02\x86\f\x03\x02\x02\x02\x87\x88\x07u\x02\x02\x88\x89\x07v\x02\x02\x89" + - "\x8A\x07c\x02\x02\x8A\x8B\x07v\x02\x02\x8B\x8C\x07k\x02\x02\x8C\x8D\x07" + - "e\x02\x02\x8D\x0E\x03\x02\x02\x02\x8E\x8F\x07x\x02\x02\x8F\x90\x07c\x02" + - "\x02\x90\x91\x07t\x02\x02\x91\x10\x03\x02\x02\x02\x92\x93\x07k\x02\x02" + - "\x93\x94\x07p\x02\x02\x94\x95\x07v\x02\x02\x95\x12\x03\x02\x02\x02\x96" + - "\x97\x07e\x02\x02\x97\x98\x07j\x02\x02\x98\x99\x07c\x02\x02\x99\x9A\x07" + - "t\x02\x02\x9A\x14\x03\x02\x02\x02\x9B\x9C\x07d\x02\x02\x9C\x9D\x07q\x02" + - "\x02\x9D\x9E\x07q\x02\x02\x9E\x9F\x07n\x02\x02\x9F\xA0\x07g\x02\x02\xA0" + - "\xA1\x07c\x02\x02\xA1\xA2\x07p\x02\x02\xA2\x16\x03\x02\x02\x02\xA3\xA4" + - "\x07x\x02\x02\xA4\xA5\x07q\x02\x02\xA5\xA6\x07k\x02\x02\xA6\xA7\x07f\x02" + - "\x02\xA7\x18\x03\x02\x02\x02\xA8\xA9\x07n\x02\x02\xA9\xAA\x07g\x02\x02" + - "\xAA\xAB\x07v\x02\x02\xAB\x1A\x03\x02\x02\x02\xAC\xAD\x07f\x02\x02\xAD" + - "\xAE\x07q\x02\x02\xAE\x1C\x03\x02\x02\x02\xAF\xB0\x07k\x02\x02\xB0\xB1" + - "\x07h\x02\x02\xB1\x1E\x03\x02\x02\x02\xB2\xB3\x07g\x02\x02\xB3\xB4\x07" + - "n\x02\x02\xB4\xB5\x07u\x02\x02\xB5\xB6\x07g\x02\x02\xB6 \x03\x02\x02\x02" + - "\xB7\xB8\x07y\x02\x02\xB8\xB9\x07j\x02\x02\xB9\xBA\x07k\x02\x02\xBA\xBB" + - "\x07n\x02\x02\xBB\xBC\x07g\x02\x02\xBC\"\x03\x02\x02\x02\xBD\xBE\x07t" + - "\x02\x02\xBE\xBF\x07g\x02\x02\xBF\xC0\x07v\x02\x02\xC0\xC1\x07w\x02\x02" + - "\xC1\xC2\x07t\x02\x02\xC2\xC3\x07p\x02\x02\xC3$\x03\x02\x02\x02\xC4\xC5" + - "\x07}\x02\x02\xC5&\x03\x02\x02\x02\xC6\xC7\x07\x7F\x02\x02\xC7(\x03\x02" + - "\x02\x02\xC8\xC9\x07*\x02\x02\xC9*\x03\x02\x02\x02\xCA\xCB\x07+\x02\x02" + - "\xCB,\x03\x02\x02\x02\xCC\xCD\x07]\x02\x02\xCD.\x03\x02\x02\x02\xCE\xCF" + - "\x07_\x02\x02\xCF0\x03\x02\x02\x02\xD0\xD1\x070\x02\x02\xD12\x03\x02\x02" + - "\x02\xD2\xD3\x07.\x02\x02\xD34\x03\x02\x02\x02\xD4\xD5\x07=\x02\x02\xD5" + - "6\x03\x02\x02\x02\xD6\xD7\x07?\x02\x02\xD78\x03\x02\x02\x02\xD8\xD9\x07" + - "-\x02\x02\xD9:\x03\x02\x02\x02\xDA\xDB\x07/\x02\x02\xDB<\x03\x02\x02\x02" + - "\xDC\xDD\x07,\x02\x02\xDD>\x03\x02\x02\x02\xDE\xDF\x071\x02\x02\xDF@\x03" + - "\x02\x02\x02\xE0\xE1\x07(\x02\x02\xE1B\x03\x02\x02\x02\xE2\xE3\x07~\x02" + - "\x02\xE3D\x03\x02\x02\x02\xE4\xE5\x07\x80\x02\x02\xE5F\x03\x02\x02\x02" + - "\xE6\xE7\x07>\x02\x02\xE7H\x03\x02\x02\x02\xE8\xE9\x07@\x02\x02\xE9J\x03" + - "\x02\x02\x02\xEA\xEC\t\x02\x02\x02\xEB\xEA\x03\x02\x02\x02\xEC\xED\x03" + - "\x02\x02\x02\xED\xEB\x03\x02\x02\x02\xED\xEE\x03\x02\x02\x02\xEE\xEF\x03" + - "\x02\x02\x02\xEF\xF0\b&\x02\x02\xF0L\x03\x02\x02\x02\xF1\xF2\x071\x02" + - "\x02\xF2\xF3\x07,\x02\x02\xF3\xF7\x03\x02\x02\x02\xF4\xF6\v\x02\x02\x02" + - "\xF5\xF4\x03\x02\x02\x02\xF6\xF9\x03\x02\x02\x02\xF7\xF8\x03\x02\x02\x02" + - "\xF7\xF5\x03\x02\x02\x02\xF8\xFA\x03\x02\x02\x02\xF9\xF7\x03\x02\x02\x02" + - "\xFA\xFB\x07,\x02\x02\xFB\xFC\x071\x02\x02\xFC\xFD\x03\x02\x02\x02\xFD" + - "\xFE\b\'\x02\x02\xFEN\x03\x02\x02\x02\xFF\u0100\x071\x02\x02\u0100\u0101" + - "\x071\x02\x02\u0101\u0105\x03\x02\x02\x02\u0102\u0104\n\x03\x02\x02\u0103" + - "\u0102\x03\x02\x02\x02\u0104\u0107\x03\x02\x02\x02\u0105\u0103\x03\x02" + - "\x02\x02\u0105\u0106\x03\x02\x02\x02\u0106\u0108\x03\x02\x02\x02\u0107" + - "\u0105\x03\x02\x02\x02\u0108\u0109\b(\x02\x02\u0109P\x03\x02\x02\x02\u010A" + - "\u010C\t\x04\x02\x02\u010B\u010A\x03\x02\x02\x02\u010C\u010D\x03\x02\x02" + - "\x02\u010D\u010B\x03\x02\x02\x02\u010D\u010E\x03\x02\x02\x02\u010ER\x03" + - "\x02\x02\x02\u010F\u0110\x07v\x02\x02\u0110\u0111\x07t\x02\x02\u0111\u0112" + - "\x07w\x02\x02\u0112\u0119\x07g\x02\x02\u0113\u0114\x07h\x02\x02\u0114" + - "\u0115\x07c\x02\x02\u0115\u0116\x07n\x02\x02\u0116\u0117\x07u\x02\x02" + - "\u0117\u0119\x07g\x02\x02\u0118\u010F\x03\x02\x02\x02\u0118\u0113\x03" + - "\x02\x02\x02\u0119T\x03\x02\x02\x02\u011A\u011B\x07p\x02\x02\u011B\u011C" + - "\x07w\x02\x02\u011C\u011D\x07n\x02\x02\u011D\u011E\x07n\x02\x02\u011E" + - "V\x03\x02\x02\x02\u011F\u0120\x07v\x02\x02\u0120\u0121\x07j\x02\x02\u0121" + - "\u0122\x07k\x02\x02\u0122\u0123\x07u\x02\x02\u0123X\x03\x02\x02\x02\u0124" + - "\u0128\t\x05\x02\x02\u0125\u0127\t\x06\x02\x02\u0126\u0125\x03\x02\x02" + - "\x02\u0127\u012A\x03\x02\x02\x02\u0128\u0126\x03\x02\x02\x02\u0128\u0129" + - "\x03\x02\x02\x02\u0129Z\x03\x02\x02\x02\u012A\u0128\x03\x02\x02\x02\u012B" + - "\u012C\x05]/\x02\u012C\u012D\x07$\x02\x02\u012D\\\x03\x02\x02\x02\u012E" + - "\u0132\x07$\x02\x02\u012F\u0131\n\x07\x02\x02\u0130\u012F\x03\x02\x02" + - "\x02\u0131\u0134\x03\x02\x02\x02\u0132\u0130\x03\x02\x02\x02\u0132\u0133" + - "\x03\x02\x02\x02\u0133^\x03\x02\x02\x02\u0134\u0132\x03\x02\x02\x02\n" + - "\x02\xED\xF7\u0105\u010D\u0118\u0128\u0132\x03\b\x02\x02"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!JackLexer.__ATN) { - JackLexer.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(JackLexer._serializedATN)); - } - - return JackLexer.__ATN; - } - -} - diff --git a/compiler/src/generated/JackParser.interp b/compiler/src/generated/JackParser.interp deleted file mode 100644 index 393935df..00000000 --- a/compiler/src/generated/JackParser.interp +++ /dev/null @@ -1,142 +0,0 @@ -token literal names: -null -'class' -'constructor' -'function' -'method' -'field' -'static' -'var' -'int' -'char' -'boolean' -'void' -'let' -'do' -'if' -'else' -'while' -'return' -'{' -'}' -'(' -')' -'[' -']' -'.' -',' -';' -'=' -'+' -'-' -'*' -'/' -'&' -'|' -'~' -'<' -'>' -null -null -null -null -null -'null' -'this' -null -null -null - -token symbolic names: -null -CLASS -CONSTRUCTOR -FUNCTION -METHOD -FIELD -STATIC -VAR -INT -CHAR -BOOLEAN -VOID -LET -DO -IF -ELSE -WHILE -RETURN -LBRACE -RBRACE -LPAREN -RPAREN -LBRACKET -RBRACKET -DOT -COMMA -SEMICOLON -EQUALS -PLUS -MINUS -MUL -DIV -AND -OR -TILDE -LESS_THAN -GREATER_THAN -WS -COMMENT -LINE_COMMENT -INTEGER_LITERAL -BOOLEAN_LITERAL -NULL_LITERAL -THIS_LITERAL -IDENTIFIER -STRING_LITERAL -UnterminatedStringLiteral - -rule names: -program -classDeclaration -className -classVarDec -fieldList -fieldName -subroutineDeclaration -subroutineType -subroutineDecWithoutType -subroutineName -subroutineReturnType -varType -parameterList -parameter -parameterName -subroutineBody -rBrace -varDeclaration -varNameInDeclaration -varName -statements -statement -letStatement -ifElseStatement -ifStatement -elseStatement -whileStatement -doStatement -subroutineCall -subroutineId -returnStatement -expressionList -expression -groupedExpression -unaryOperation -arrayAccess -constant -unaryOperator -binaryOperator - - -atn: -[3, 51485, 51898, 1421, 44986, 20307, 1543, 60043, 49729, 3, 48, 298, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 88, 10, 3, 12, 3, 14, 3, 91, 11, 3, 3, 3, 7, 3, 94, 10, 3, 12, 3, 14, 3, 97, 11, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 7, 6, 111, 10, 6, 12, 6, 14, 6, 114, 11, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12, 3, 12, 5, 12, 134, 10, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 7, 14, 141, 10, 14, 12, 14, 14, 14, 144, 11, 14, 5, 14, 146, 10, 14, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 17, 3, 17, 7, 17, 155, 10, 17, 12, 17, 14, 17, 158, 11, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 7, 19, 170, 10, 19, 12, 19, 14, 19, 173, 11, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 7, 22, 182, 10, 22, 12, 22, 14, 22, 185, 11, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 5, 23, 192, 10, 23, 3, 24, 3, 24, 3, 24, 5, 24, 197, 10, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 5, 25, 205, 10, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 5, 31, 239, 10, 31, 3, 31, 5, 31, 242, 10, 31, 3, 31, 3, 31, 3, 32, 3, 32, 5, 32, 248, 10, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 7, 33, 255, 10, 33, 12, 33, 14, 33, 258, 11, 33, 5, 33, 260, 10, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 5, 34, 269, 10, 34, 3, 34, 3, 34, 3, 34, 3, 34, 7, 34, 275, 10, 34, 12, 34, 14, 34, 278, 11, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 2, 2, 3, 66, 41, 2, 2, 4, 2, 6, 2, 8, 2, 10, 2, 12, 2, 14, 2, 16, 2, 18, 2, 20, 2, 22, 2, 24, 2, 26, 2, 28, 2, 30, 2, 32, 2, 34, 2, 36, 2, 38, 2, 40, 2, 42, 2, 44, 2, 46, 2, 48, 2, 50, 2, 52, 2, 54, 2, 56, 2, 58, 2, 60, 2, 62, 2, 64, 2, 66, 2, 68, 2, 70, 2, 72, 2, 74, 2, 76, 2, 78, 2, 2, 8, 3, 2, 7, 8, 3, 2, 4, 6, 4, 2, 10, 12, 46, 46, 4, 2, 42, 45, 47, 47, 4, 2, 31, 31, 36, 36, 4, 2, 29, 35, 37, 38, 2, 284, 2, 80, 3, 2, 2, 2, 4, 83, 3, 2, 2, 2, 6, 100, 3, 2, 2, 2, 8, 102, 3, 2, 2, 2, 10, 106, 3, 2, 2, 2, 12, 115, 3, 2, 2, 2, 14, 117, 3, 2, 2, 2, 16, 120, 3, 2, 2, 2, 18, 122, 3, 2, 2, 2, 20, 129, 3, 2, 2, 2, 22, 133, 3, 2, 2, 2, 24, 135, 3, 2, 2, 2, 26, 145, 3, 2, 2, 2, 28, 147, 3, 2, 2, 2, 30, 150, 3, 2, 2, 2, 32, 152, 3, 2, 2, 2, 34, 162, 3, 2, 2, 2, 36, 164, 3, 2, 2, 2, 38, 176, 3, 2, 2, 2, 40, 178, 3, 2, 2, 2, 42, 183, 3, 2, 2, 2, 44, 191, 3, 2, 2, 2, 46, 193, 3, 2, 2, 2, 48, 202, 3, 2, 2, 2, 50, 206, 3, 2, 2, 2, 52, 214, 3, 2, 2, 2, 54, 219, 3, 2, 2, 2, 56, 227, 3, 2, 2, 2, 58, 231, 3, 2, 2, 2, 60, 241, 3, 2, 2, 2, 62, 245, 3, 2, 2, 2, 64, 259, 3, 2, 2, 2, 66, 268, 3, 2, 2, 2, 68, 279, 3, 2, 2, 2, 70, 283, 3, 2, 2, 2, 72, 286, 3, 2, 2, 2, 74, 291, 3, 2, 2, 2, 76, 293, 3, 2, 2, 2, 78, 295, 3, 2, 2, 2, 80, 81, 5, 4, 3, 2, 81, 82, 7, 2, 2, 3, 82, 3, 3, 2, 2, 2, 83, 84, 7, 3, 2, 2, 84, 85, 5, 6, 4, 2, 85, 89, 7, 20, 2, 2, 86, 88, 5, 8, 5, 2, 87, 86, 3, 2, 2, 2, 88, 91, 3, 2, 2, 2, 89, 87, 3, 2, 2, 2, 89, 90, 3, 2, 2, 2, 90, 95, 3, 2, 2, 2, 91, 89, 3, 2, 2, 2, 92, 94, 5, 14, 8, 2, 93, 92, 3, 2, 2, 2, 94, 97, 3, 2, 2, 2, 95, 93, 3, 2, 2, 2, 95, 96, 3, 2, 2, 2, 96, 98, 3, 2, 2, 2, 97, 95, 3, 2, 2, 2, 98, 99, 5, 34, 18, 2, 99, 5, 3, 2, 2, 2, 100, 101, 7, 46, 2, 2, 101, 7, 3, 2, 2, 2, 102, 103, 9, 2, 2, 2, 103, 104, 5, 10, 6, 2, 104, 105, 7, 28, 2, 2, 105, 9, 3, 2, 2, 2, 106, 107, 5, 24, 13, 2, 107, 112, 5, 12, 7, 2, 108, 109, 7, 27, 2, 2, 109, 111, 5, 12, 7, 2, 110, 108, 3, 2, 2, 2, 111, 114, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 112, 113, 3, 2, 2, 2, 113, 11, 3, 2, 2, 2, 114, 112, 3, 2, 2, 2, 115, 116, 7, 46, 2, 2, 116, 13, 3, 2, 2, 2, 117, 118, 5, 16, 9, 2, 118, 119, 5, 18, 10, 2, 119, 15, 3, 2, 2, 2, 120, 121, 9, 3, 2, 2, 121, 17, 3, 2, 2, 2, 122, 123, 5, 22, 12, 2, 123, 124, 5, 20, 11, 2, 124, 125, 7, 22, 2, 2, 125, 126, 5, 26, 14, 2, 126, 127, 7, 23, 2, 2, 127, 128, 5, 32, 17, 2, 128, 19, 3, 2, 2, 2, 129, 130, 7, 46, 2, 2, 130, 21, 3, 2, 2, 2, 131, 134, 5, 24, 13, 2, 132, 134, 7, 13, 2, 2, 133, 131, 3, 2, 2, 2, 133, 132, 3, 2, 2, 2, 134, 23, 3, 2, 2, 2, 135, 136, 9, 4, 2, 2, 136, 25, 3, 2, 2, 2, 137, 142, 5, 28, 15, 2, 138, 139, 7, 27, 2, 2, 139, 141, 5, 28, 15, 2, 140, 138, 3, 2, 2, 2, 141, 144, 3, 2, 2, 2, 142, 140, 3, 2, 2, 2, 142, 143, 3, 2, 2, 2, 143, 146, 3, 2, 2, 2, 144, 142, 3, 2, 2, 2, 145, 137, 3, 2, 2, 2, 145, 146, 3, 2, 2, 2, 146, 27, 3, 2, 2, 2, 147, 148, 5, 24, 13, 2, 148, 149, 5, 30, 16, 2, 149, 29, 3, 2, 2, 2, 150, 151, 7, 46, 2, 2, 151, 31, 3, 2, 2, 2, 152, 156, 7, 20, 2, 2, 153, 155, 5, 36, 19, 2, 154, 153, 3, 2, 2, 2, 155, 158, 3, 2, 2, 2, 156, 154, 3, 2, 2, 2, 156, 157, 3, 2, 2, 2, 157, 159, 3, 2, 2, 2, 158, 156, 3, 2, 2, 2, 159, 160, 5, 42, 22, 2, 160, 161, 5, 34, 18, 2, 161, 33, 3, 2, 2, 2, 162, 163, 7, 21, 2, 2, 163, 35, 3, 2, 2, 2, 164, 165, 7, 9, 2, 2, 165, 166, 5, 24, 13, 2, 166, 171, 5, 38, 20, 2, 167, 168, 7, 27, 2, 2, 168, 170, 5, 38, 20, 2, 169, 167, 3, 2, 2, 2, 170, 173, 3, 2, 2, 2, 171, 169, 3, 2, 2, 2, 171, 172, 3, 2, 2, 2, 172, 174, 3, 2, 2, 2, 173, 171, 3, 2, 2, 2, 174, 175, 7, 28, 2, 2, 175, 37, 3, 2, 2, 2, 176, 177, 7, 46, 2, 2, 177, 39, 3, 2, 2, 2, 178, 179, 7, 46, 2, 2, 179, 41, 3, 2, 2, 2, 180, 182, 5, 44, 23, 2, 181, 180, 3, 2, 2, 2, 182, 185, 3, 2, 2, 2, 183, 181, 3, 2, 2, 2, 183, 184, 3, 2, 2, 2, 184, 43, 3, 2, 2, 2, 185, 183, 3, 2, 2, 2, 186, 192, 5, 46, 24, 2, 187, 192, 5, 48, 25, 2, 188, 192, 5, 54, 28, 2, 189, 192, 5, 56, 29, 2, 190, 192, 5, 62, 32, 2, 191, 186, 3, 2, 2, 2, 191, 187, 3, 2, 2, 2, 191, 188, 3, 2, 2, 2, 191, 189, 3, 2, 2, 2, 191, 190, 3, 2, 2, 2, 192, 45, 3, 2, 2, 2, 193, 196, 7, 14, 2, 2, 194, 197, 5, 40, 21, 2, 195, 197, 5, 72, 37, 2, 196, 194, 3, 2, 2, 2, 196, 195, 3, 2, 2, 2, 197, 198, 3, 2, 2, 2, 198, 199, 7, 29, 2, 2, 199, 200, 5, 66, 34, 2, 200, 201, 7, 28, 2, 2, 201, 47, 3, 2, 2, 2, 202, 204, 5, 50, 26, 2, 203, 205, 5, 52, 27, 2, 204, 203, 3, 2, 2, 2, 204, 205, 3, 2, 2, 2, 205, 49, 3, 2, 2, 2, 206, 207, 7, 16, 2, 2, 207, 208, 7, 22, 2, 2, 208, 209, 5, 66, 34, 2, 209, 210, 7, 23, 2, 2, 210, 211, 7, 20, 2, 2, 211, 212, 5, 42, 22, 2, 212, 213, 5, 34, 18, 2, 213, 51, 3, 2, 2, 2, 214, 215, 7, 17, 2, 2, 215, 216, 7, 20, 2, 2, 216, 217, 5, 42, 22, 2, 217, 218, 5, 34, 18, 2, 218, 53, 3, 2, 2, 2, 219, 220, 7, 18, 2, 2, 220, 221, 7, 22, 2, 2, 221, 222, 5, 66, 34, 2, 222, 223, 7, 23, 2, 2, 223, 224, 7, 20, 2, 2, 224, 225, 5, 42, 22, 2, 225, 226, 5, 34, 18, 2, 226, 55, 3, 2, 2, 2, 227, 228, 7, 15, 2, 2, 228, 229, 5, 58, 30, 2, 229, 230, 7, 28, 2, 2, 230, 57, 3, 2, 2, 2, 231, 232, 5, 60, 31, 2, 232, 233, 7, 22, 2, 2, 233, 234, 5, 64, 33, 2, 234, 235, 7, 23, 2, 2, 235, 59, 3, 2, 2, 2, 236, 239, 5, 6, 4, 2, 237, 239, 7, 45, 2, 2, 238, 236, 3, 2, 2, 2, 238, 237, 3, 2, 2, 2, 239, 240, 3, 2, 2, 2, 240, 242, 7, 26, 2, 2, 241, 238, 3, 2, 2, 2, 241, 242, 3, 2, 2, 2, 242, 243, 3, 2, 2, 2, 243, 244, 5, 20, 11, 2, 244, 61, 3, 2, 2, 2, 245, 247, 7, 19, 2, 2, 246, 248, 5, 66, 34, 2, 247, 246, 3, 2, 2, 2, 247, 248, 3, 2, 2, 2, 248, 249, 3, 2, 2, 2, 249, 250, 7, 28, 2, 2, 250, 63, 3, 2, 2, 2, 251, 256, 5, 66, 34, 2, 252, 253, 7, 27, 2, 2, 253, 255, 5, 66, 34, 2, 254, 252, 3, 2, 2, 2, 255, 258, 3, 2, 2, 2, 256, 254, 3, 2, 2, 2, 256, 257, 3, 2, 2, 2, 257, 260, 3, 2, 2, 2, 258, 256, 3, 2, 2, 2, 259, 251, 3, 2, 2, 2, 259, 260, 3, 2, 2, 2, 260, 65, 3, 2, 2, 2, 261, 262, 8, 34, 1, 2, 262, 269, 5, 74, 38, 2, 263, 269, 5, 40, 21, 2, 264, 269, 5, 58, 30, 2, 265, 269, 5, 72, 37, 2, 266, 269, 5, 70, 36, 2, 267, 269, 5, 68, 35, 2, 268, 261, 3, 2, 2, 2, 268, 263, 3, 2, 2, 2, 268, 264, 3, 2, 2, 2, 268, 265, 3, 2, 2, 2, 268, 266, 3, 2, 2, 2, 268, 267, 3, 2, 2, 2, 269, 276, 3, 2, 2, 2, 270, 271, 12, 9, 2, 2, 271, 272, 5, 78, 40, 2, 272, 273, 5, 66, 34, 10, 273, 275, 3, 2, 2, 2, 274, 270, 3, 2, 2, 2, 275, 278, 3, 2, 2, 2, 276, 274, 3, 2, 2, 2, 276, 277, 3, 2, 2, 2, 277, 67, 3, 2, 2, 2, 278, 276, 3, 2, 2, 2, 279, 280, 7, 22, 2, 2, 280, 281, 5, 66, 34, 2, 281, 282, 7, 23, 2, 2, 282, 69, 3, 2, 2, 2, 283, 284, 5, 76, 39, 2, 284, 285, 5, 66, 34, 2, 285, 71, 3, 2, 2, 2, 286, 287, 5, 40, 21, 2, 287, 288, 7, 24, 2, 2, 288, 289, 5, 66, 34, 2, 289, 290, 7, 25, 2, 2, 290, 73, 3, 2, 2, 2, 291, 292, 9, 5, 2, 2, 292, 75, 3, 2, 2, 2, 293, 294, 9, 6, 2, 2, 294, 77, 3, 2, 2, 2, 295, 296, 9, 7, 2, 2, 296, 79, 3, 2, 2, 2, 21, 89, 95, 112, 133, 142, 145, 156, 171, 183, 191, 196, 204, 238, 241, 247, 256, 259, 268, 276] \ No newline at end of file diff --git a/compiler/src/generated/JackParser.tokens b/compiler/src/generated/JackParser.tokens deleted file mode 100644 index 8292b05c..00000000 --- a/compiler/src/generated/JackParser.tokens +++ /dev/null @@ -1,84 +0,0 @@ -CLASS=1 -CONSTRUCTOR=2 -FUNCTION=3 -METHOD=4 -FIELD=5 -STATIC=6 -VAR=7 -INT=8 -CHAR=9 -BOOLEAN=10 -VOID=11 -LET=12 -DO=13 -IF=14 -ELSE=15 -WHILE=16 -RETURN=17 -LBRACE=18 -RBRACE=19 -LPAREN=20 -RPAREN=21 -LBRACKET=22 -RBRACKET=23 -DOT=24 -COMMA=25 -SEMICOLON=26 -EQUALS=27 -PLUS=28 -MINUS=29 -MUL=30 -DIV=31 -AND=32 -OR=33 -TILDE=34 -LESS_THAN=35 -GREATER_THAN=36 -WS=37 -COMMENT=38 -LINE_COMMENT=39 -INTEGER_LITERAL=40 -BOOLEAN_LITERAL=41 -NULL_LITERAL=42 -THIS_LITERAL=43 -IDENTIFIER=44 -STRING_LITERAL=45 -UnterminatedStringLiteral=46 -'class'=1 -'constructor'=2 -'function'=3 -'method'=4 -'field'=5 -'static'=6 -'var'=7 -'int'=8 -'char'=9 -'boolean'=10 -'void'=11 -'let'=12 -'do'=13 -'if'=14 -'else'=15 -'while'=16 -'return'=17 -'{'=18 -'}'=19 -'('=20 -')'=21 -'['=22 -']'=23 -'.'=24 -','=25 -';'=26 -'='=27 -'+'=28 -'-'=29 -'*'=30 -'/'=31 -'&'=32 -'|'=33 -'~'=34 -'<'=35 -'>'=36 -'null'=42 -'this'=43 diff --git a/compiler/src/generated/JackParser.ts b/compiler/src/generated/JackParser.ts deleted file mode 100644 index a9c5b930..00000000 --- a/compiler/src/generated/JackParser.ts +++ /dev/null @@ -1,3283 +0,0 @@ -// Generated from JackParser.g4 by ANTLR 4.9.0-SNAPSHOT - - -import { ATN } from "antlr4ts/atn/ATN"; -import { ATNDeserializer } from "antlr4ts/atn/ATNDeserializer"; -import { FailedPredicateException } from "antlr4ts/FailedPredicateException"; -import { NotNull } from "antlr4ts/Decorators"; -import { NoViableAltException } from "antlr4ts/NoViableAltException"; -import { Override } from "antlr4ts/Decorators"; -import { Parser } from "antlr4ts/Parser"; -import { ParserRuleContext } from "antlr4ts/ParserRuleContext"; -import { ParserATNSimulator } from "antlr4ts/atn/ParserATNSimulator"; -import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; -import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; -import { RecognitionException } from "antlr4ts/RecognitionException"; -import { RuleContext } from "antlr4ts/RuleContext"; -//import { RuleVersion } from "antlr4ts/RuleVersion"; -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { Token } from "antlr4ts/Token"; -import { TokenStream } from "antlr4ts/TokenStream"; -import { Vocabulary } from "antlr4ts/Vocabulary"; -import { VocabularyImpl } from "antlr4ts/VocabularyImpl"; - -import * as Utils from "antlr4ts/misc/Utils"; - -import { JackParserListener } from "./JackParserListener"; -import { JackParserVisitor } from "./JackParserVisitor"; - - -export class JackParser extends Parser { - public static readonly CLASS = 1; - public static readonly CONSTRUCTOR = 2; - public static readonly FUNCTION = 3; - public static readonly METHOD = 4; - public static readonly FIELD = 5; - public static readonly STATIC = 6; - public static readonly VAR = 7; - public static readonly INT = 8; - public static readonly CHAR = 9; - public static readonly BOOLEAN = 10; - public static readonly VOID = 11; - public static readonly LET = 12; - public static readonly DO = 13; - public static readonly IF = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly RETURN = 17; - public static readonly LBRACE = 18; - public static readonly RBRACE = 19; - public static readonly LPAREN = 20; - public static readonly RPAREN = 21; - public static readonly LBRACKET = 22; - public static readonly RBRACKET = 23; - public static readonly DOT = 24; - public static readonly COMMA = 25; - public static readonly SEMICOLON = 26; - public static readonly EQUALS = 27; - public static readonly PLUS = 28; - public static readonly MINUS = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly AND = 32; - public static readonly OR = 33; - public static readonly TILDE = 34; - public static readonly LESS_THAN = 35; - public static readonly GREATER_THAN = 36; - public static readonly WS = 37; - public static readonly COMMENT = 38; - public static readonly LINE_COMMENT = 39; - public static readonly INTEGER_LITERAL = 40; - public static readonly BOOLEAN_LITERAL = 41; - public static readonly NULL_LITERAL = 42; - public static readonly THIS_LITERAL = 43; - public static readonly IDENTIFIER = 44; - public static readonly STRING_LITERAL = 45; - public static readonly UnterminatedStringLiteral = 46; - public static readonly RULE_program = 0; - public static readonly RULE_classDeclaration = 1; - public static readonly RULE_className = 2; - public static readonly RULE_classVarDec = 3; - public static readonly RULE_fieldList = 4; - public static readonly RULE_fieldName = 5; - public static readonly RULE_subroutineDeclaration = 6; - public static readonly RULE_subroutineType = 7; - public static readonly RULE_subroutineDecWithoutType = 8; - public static readonly RULE_subroutineName = 9; - public static readonly RULE_subroutineReturnType = 10; - public static readonly RULE_varType = 11; - public static readonly RULE_parameterList = 12; - public static readonly RULE_parameter = 13; - public static readonly RULE_parameterName = 14; - public static readonly RULE_subroutineBody = 15; - public static readonly RULE_rBrace = 16; - public static readonly RULE_varDeclaration = 17; - public static readonly RULE_varNameInDeclaration = 18; - public static readonly RULE_varName = 19; - public static readonly RULE_statements = 20; - public static readonly RULE_statement = 21; - public static readonly RULE_letStatement = 22; - public static readonly RULE_ifElseStatement = 23; - public static readonly RULE_ifStatement = 24; - public static readonly RULE_elseStatement = 25; - public static readonly RULE_whileStatement = 26; - public static readonly RULE_doStatement = 27; - public static readonly RULE_subroutineCall = 28; - public static readonly RULE_subroutineId = 29; - public static readonly RULE_returnStatement = 30; - public static readonly RULE_expressionList = 31; - public static readonly RULE_expression = 32; - public static readonly RULE_groupedExpression = 33; - public static readonly RULE_unaryOperation = 34; - public static readonly RULE_arrayAccess = 35; - public static readonly RULE_constant = 36; - public static readonly RULE_unaryOperator = 37; - public static readonly RULE_binaryOperator = 38; - // tslint:disable:no-trailing-whitespace - public static readonly ruleNames: string[] = [ - "program", "classDeclaration", "className", "classVarDec", "fieldList", - "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", - "subroutineName", "subroutineReturnType", "varType", "parameterList", - "parameter", "parameterName", "subroutineBody", "rBrace", "varDeclaration", - "varNameInDeclaration", "varName", "statements", "statement", "letStatement", - "ifElseStatement", "ifStatement", "elseStatement", "whileStatement", "doStatement", - "subroutineCall", "subroutineId", "returnStatement", "expressionList", - "expression", "groupedExpression", "unaryOperation", "arrayAccess", "constant", - "unaryOperator", "binaryOperator", - ]; - - private static readonly _LITERAL_NAMES: Array = [ - undefined, "'class'", "'constructor'", "'function'", "'method'", "'field'", - "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", - "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", - "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", - "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", undefined, undefined, undefined, - undefined, undefined, "'null'", "'this'", - ]; - private static readonly _SYMBOLIC_NAMES: Array = [ - undefined, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", - "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", - "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", - "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", - "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WS", "COMMENT", "LINE_COMMENT", - "INTEGER_LITERAL", "BOOLEAN_LITERAL", "NULL_LITERAL", "THIS_LITERAL", - "IDENTIFIER", "STRING_LITERAL", "UnterminatedStringLiteral", - ]; - public static readonly VOCABULARY: Vocabulary = new VocabularyImpl(JackParser._LITERAL_NAMES, JackParser._SYMBOLIC_NAMES, []); - - // @Override - // @NotNull - public get vocabulary(): Vocabulary { - return JackParser.VOCABULARY; - } - // tslint:enable:no-trailing-whitespace - - // @Override - public get grammarFileName(): string { return "JackParser.g4"; } - - // @Override - public get ruleNames(): string[] { return JackParser.ruleNames; } - - // @Override - public override get serializedATN(): string { return JackParser._serializedATN; } - - protected createFailedPredicateException(predicate?: string, message?: string): FailedPredicateException { - return new FailedPredicateException(this, predicate, message); - } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(JackParser._ATN, this); - } - // @RuleVersion(0) - public program(): ProgramContext { - let _localctx: ProgramContext = new ProgramContext(this._ctx, this.state); - this.enterRule(_localctx, 0, JackParser.RULE_program); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 78; - this.classDeclaration(); - this.state = 79; - this.match(JackParser.EOF); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public classDeclaration(): ClassDeclarationContext { - let _localctx: ClassDeclarationContext = new ClassDeclarationContext(this._ctx, this.state); - this.enterRule(_localctx, 2, JackParser.RULE_classDeclaration); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 81; - this.match(JackParser.CLASS); - this.state = 82; - this.className(); - this.state = 83; - this.match(JackParser.LBRACE); - this.state = 87; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === JackParser.FIELD || _la === JackParser.STATIC) { - { - { - this.state = 84; - this.classVarDec(); - } - } - this.state = 89; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 93; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0)) { - { - { - this.state = 90; - this.subroutineDeclaration(); - } - } - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 96; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public className(): ClassNameContext { - let _localctx: ClassNameContext = new ClassNameContext(this._ctx, this.state); - this.enterRule(_localctx, 4, JackParser.RULE_className); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 98; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public classVarDec(): ClassVarDecContext { - let _localctx: ClassVarDecContext = new ClassVarDecContext(this._ctx, this.state); - this.enterRule(_localctx, 6, JackParser.RULE_classVarDec); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 100; - _la = this._input.LA(1); - if (!(_la === JackParser.FIELD || _la === JackParser.STATIC)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - this.state = 101; - this.fieldList(); - this.state = 102; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public fieldList(): FieldListContext { - let _localctx: FieldListContext = new FieldListContext(this._ctx, this.state); - this.enterRule(_localctx, 8, JackParser.RULE_fieldList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 104; - this.varType(); - this.state = 105; - this.fieldName(); - this.state = 110; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === JackParser.COMMA) { - { - { - this.state = 106; - this.match(JackParser.COMMA); - this.state = 107; - this.fieldName(); - } - } - this.state = 112; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public fieldName(): FieldNameContext { - let _localctx: FieldNameContext = new FieldNameContext(this._ctx, this.state); - this.enterRule(_localctx, 10, JackParser.RULE_fieldName); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 113; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public subroutineDeclaration(): SubroutineDeclarationContext { - let _localctx: SubroutineDeclarationContext = new SubroutineDeclarationContext(this._ctx, this.state); - this.enterRule(_localctx, 12, JackParser.RULE_subroutineDeclaration); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 115; - this.subroutineType(); - this.state = 116; - this.subroutineDecWithoutType(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public subroutineType(): SubroutineTypeContext { - let _localctx: SubroutineTypeContext = new SubroutineTypeContext(this._ctx, this.state); - this.enterRule(_localctx, 14, JackParser.RULE_subroutineType); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 118; - _la = this._input.LA(1); - if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.CONSTRUCTOR) | (1 << JackParser.FUNCTION) | (1 << JackParser.METHOD))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - let _localctx: SubroutineDecWithoutTypeContext = new SubroutineDecWithoutTypeContext(this._ctx, this.state); - this.enterRule(_localctx, 16, JackParser.RULE_subroutineDecWithoutType); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 120; - this.subroutineReturnType(); - this.state = 121; - this.subroutineName(); - this.state = 122; - this.match(JackParser.LPAREN); - this.state = 123; - this.parameterList(); - this.state = 124; - this.match(JackParser.RPAREN); - this.state = 125; - this.subroutineBody(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public subroutineName(): SubroutineNameContext { - let _localctx: SubroutineNameContext = new SubroutineNameContext(this._ctx, this.state); - this.enterRule(_localctx, 18, JackParser.RULE_subroutineName); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 127; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public subroutineReturnType(): SubroutineReturnTypeContext { - let _localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this._ctx, this.state); - this.enterRule(_localctx, 20, JackParser.RULE_subroutineReturnType); - try { - this.state = 131; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case JackParser.INT: - case JackParser.CHAR: - case JackParser.BOOLEAN: - case JackParser.IDENTIFIER: - this.enterOuterAlt(_localctx, 1); - { - this.state = 129; - this.varType(); - } - break; - case JackParser.VOID: - this.enterOuterAlt(_localctx, 2); - { - this.state = 130; - this.match(JackParser.VOID); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public varType(): VarTypeContext { - let _localctx: VarTypeContext = new VarTypeContext(this._ctx, this.state); - this.enterRule(_localctx, 22, JackParser.RULE_varType); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 133; - _la = this._input.LA(1); - if (!((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public parameterList(): ParameterListContext { - let _localctx: ParameterListContext = new ParameterListContext(this._ctx, this.state); - this.enterRule(_localctx, 24, JackParser.RULE_parameterList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 143; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.INT) | (1 << JackParser.CHAR) | (1 << JackParser.BOOLEAN))) !== 0) || _la === JackParser.IDENTIFIER) { - { - this.state = 135; - this.parameter(); - this.state = 140; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === JackParser.COMMA) { - { - { - this.state = 136; - this.match(JackParser.COMMA); - this.state = 137; - this.parameter(); - } - } - this.state = 142; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public parameter(): ParameterContext { - let _localctx: ParameterContext = new ParameterContext(this._ctx, this.state); - this.enterRule(_localctx, 26, JackParser.RULE_parameter); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 145; - this.varType(); - this.state = 146; - this.parameterName(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public parameterName(): ParameterNameContext { - let _localctx: ParameterNameContext = new ParameterNameContext(this._ctx, this.state); - this.enterRule(_localctx, 28, JackParser.RULE_parameterName); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 148; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public subroutineBody(): SubroutineBodyContext { - let _localctx: SubroutineBodyContext = new SubroutineBodyContext(this._ctx, this.state); - this.enterRule(_localctx, 30, JackParser.RULE_subroutineBody); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 150; - this.match(JackParser.LBRACE); - this.state = 154; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === JackParser.VAR) { - { - { - this.state = 151; - this.varDeclaration(); - } - } - this.state = 156; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 157; - this.statements(); - this.state = 158; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public rBrace(): RBraceContext { - let _localctx: RBraceContext = new RBraceContext(this._ctx, this.state); - this.enterRule(_localctx, 32, JackParser.RULE_rBrace); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 160; - this.match(JackParser.RBRACE); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public varDeclaration(): VarDeclarationContext { - let _localctx: VarDeclarationContext = new VarDeclarationContext(this._ctx, this.state); - this.enterRule(_localctx, 34, JackParser.RULE_varDeclaration); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 162; - this.match(JackParser.VAR); - this.state = 163; - this.varType(); - this.state = 164; - this.varNameInDeclaration(); - this.state = 169; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === JackParser.COMMA) { - { - { - this.state = 165; - this.match(JackParser.COMMA); - this.state = 166; - this.varNameInDeclaration(); - } - } - this.state = 171; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 172; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public varNameInDeclaration(): VarNameInDeclarationContext { - let _localctx: VarNameInDeclarationContext = new VarNameInDeclarationContext(this._ctx, this.state); - this.enterRule(_localctx, 36, JackParser.RULE_varNameInDeclaration); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 174; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public varName(): VarNameContext { - let _localctx: VarNameContext = new VarNameContext(this._ctx, this.state); - this.enterRule(_localctx, 38, JackParser.RULE_varName); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 176; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public statements(): StatementsContext { - let _localctx: StatementsContext = new StatementsContext(this._ctx, this.state); - this.enterRule(_localctx, 40, JackParser.RULE_statements); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 181; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & ((1 << JackParser.LET) | (1 << JackParser.DO) | (1 << JackParser.IF) | (1 << JackParser.WHILE) | (1 << JackParser.RETURN))) !== 0)) { - { - { - this.state = 178; - this.statement(); - } - } - this.state = 183; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public statement(): StatementContext { - let _localctx: StatementContext = new StatementContext(this._ctx, this.state); - this.enterRule(_localctx, 42, JackParser.RULE_statement); - try { - this.state = 189; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case JackParser.LET: - this.enterOuterAlt(_localctx, 1); - { - this.state = 184; - this.letStatement(); - } - break; - case JackParser.IF: - this.enterOuterAlt(_localctx, 2); - { - this.state = 185; - this.ifElseStatement(); - } - break; - case JackParser.WHILE: - this.enterOuterAlt(_localctx, 3); - { - this.state = 186; - this.whileStatement(); - } - break; - case JackParser.DO: - this.enterOuterAlt(_localctx, 4); - { - this.state = 187; - this.doStatement(); - } - break; - case JackParser.RETURN: - this.enterOuterAlt(_localctx, 5); - { - this.state = 188; - this.returnStatement(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public letStatement(): LetStatementContext { - let _localctx: LetStatementContext = new LetStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 44, JackParser.RULE_letStatement); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 191; - this.match(JackParser.LET); - this.state = 194; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 10, this._ctx) ) { - case 1: - { - this.state = 192; - this.varName(); - } - break; - - case 2: - { - this.state = 193; - this.arrayAccess(); - } - break; - } - this.state = 196; - this.match(JackParser.EQUALS); - this.state = 197; - this.expression(0); - this.state = 198; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public ifElseStatement(): IfElseStatementContext { - let _localctx: IfElseStatementContext = new IfElseStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 46, JackParser.RULE_ifElseStatement); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 200; - this.ifStatement(); - this.state = 202; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === JackParser.ELSE) { - { - this.state = 201; - this.elseStatement(); - } - } - - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public ifStatement(): IfStatementContext { - let _localctx: IfStatementContext = new IfStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 48, JackParser.RULE_ifStatement); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 204; - this.match(JackParser.IF); - this.state = 205; - this.match(JackParser.LPAREN); - this.state = 206; - this.expression(0); - this.state = 207; - this.match(JackParser.RPAREN); - this.state = 208; - this.match(JackParser.LBRACE); - this.state = 209; - this.statements(); - this.state = 210; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public elseStatement(): ElseStatementContext { - let _localctx: ElseStatementContext = new ElseStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 50, JackParser.RULE_elseStatement); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 212; - this.match(JackParser.ELSE); - this.state = 213; - this.match(JackParser.LBRACE); - this.state = 214; - this.statements(); - this.state = 215; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public whileStatement(): WhileStatementContext { - let _localctx: WhileStatementContext = new WhileStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 52, JackParser.RULE_whileStatement); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 217; - this.match(JackParser.WHILE); - this.state = 218; - this.match(JackParser.LPAREN); - this.state = 219; - this.expression(0); - this.state = 220; - this.match(JackParser.RPAREN); - this.state = 221; - this.match(JackParser.LBRACE); - this.state = 222; - this.statements(); - this.state = 223; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public doStatement(): DoStatementContext { - let _localctx: DoStatementContext = new DoStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 54, JackParser.RULE_doStatement); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 225; - this.match(JackParser.DO); - this.state = 226; - this.subroutineCall(); - this.state = 227; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public subroutineCall(): SubroutineCallContext { - let _localctx: SubroutineCallContext = new SubroutineCallContext(this._ctx, this.state); - this.enterRule(_localctx, 56, JackParser.RULE_subroutineCall); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 229; - this.subroutineId(); - this.state = 230; - this.match(JackParser.LPAREN); - this.state = 231; - this.expressionList(); - this.state = 232; - this.match(JackParser.RPAREN); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public subroutineId(): SubroutineIdContext { - let _localctx: SubroutineIdContext = new SubroutineIdContext(this._ctx, this.state); - this.enterRule(_localctx, 58, JackParser.RULE_subroutineId); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 239; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 13, this._ctx) ) { - case 1: - { - this.state = 236; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case JackParser.IDENTIFIER: - { - this.state = 234; - this.className(); - } - break; - case JackParser.THIS_LITERAL: - { - this.state = 235; - this.match(JackParser.THIS_LITERAL); - } - break; - default: - throw new NoViableAltException(this); - } - this.state = 238; - this.match(JackParser.DOT); - } - break; - } - this.state = 241; - this.subroutineName(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public returnStatement(): ReturnStatementContext { - let _localctx: ReturnStatementContext = new ReturnStatementContext(this._ctx, this.state); - this.enterRule(_localctx, 60, JackParser.RULE_returnStatement); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 243; - this.match(JackParser.RETURN); - this.state = 245; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { - { - this.state = 244; - this.expression(0); - } - } - - this.state = 247; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public expressionList(): ExpressionListContext { - let _localctx: ExpressionListContext = new ExpressionListContext(this._ctx, this.state); - this.enterRule(_localctx, 62, JackParser.RULE_expressionList); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 257; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & ((1 << (JackParser.LPAREN - 20)) | (1 << (JackParser.MINUS - 20)) | (1 << (JackParser.TILDE - 20)) | (1 << (JackParser.INTEGER_LITERAL - 20)) | (1 << (JackParser.BOOLEAN_LITERAL - 20)) | (1 << (JackParser.NULL_LITERAL - 20)) | (1 << (JackParser.THIS_LITERAL - 20)) | (1 << (JackParser.IDENTIFIER - 20)) | (1 << (JackParser.STRING_LITERAL - 20)))) !== 0)) { - { - this.state = 249; - this.expression(0); - this.state = 254; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === JackParser.COMMA) { - { - { - this.state = 250; - this.match(JackParser.COMMA); - this.state = 251; - this.expression(0); - } - } - this.state = 256; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public expression(): ExpressionContext; - public expression(_p: number): ExpressionContext; - // @RuleVersion(0) - public expression(_p?: number): ExpressionContext { - if (_p === undefined) { - _p = 0; - } - - let _parentctx: ParserRuleContext = this._ctx; - let _parentState: number = this.state; - let _localctx: ExpressionContext = new ExpressionContext(this._ctx, _parentState); - let _prevctx: ExpressionContext = _localctx; - let _startState: number = 64; - this.enterRecursionRule(_localctx, 64, JackParser.RULE_expression, _p); - try { - let _alt: number; - this.enterOuterAlt(_localctx, 1); - { - this.state = 266; - this._errHandler.sync(this); - switch ( this.interpreter.adaptivePredict(this._input, 17, this._ctx) ) { - case 1: - { - this.state = 260; - this.constant(); - } - break; - - case 2: - { - this.state = 261; - this.varName(); - } - break; - - case 3: - { - this.state = 262; - this.subroutineCall(); - } - break; - - case 4: - { - this.state = 263; - this.arrayAccess(); - } - break; - - case 5: - { - this.state = 264; - this.unaryOperation(); - } - break; - - case 6: - { - this.state = 265; - this.groupedExpression(); - } - break; - } - this._ctx._stop = this._input.tryLT(-1); - this.state = 274; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - if (this._parseListeners != null) { - this.triggerExitRuleEvent(); - } - _prevctx = _localctx; - { - { - _localctx = new ExpressionContext(_parentctx, _parentState); - this.pushNewRecursionContext(_localctx, _startState, JackParser.RULE_expression); - this.state = 268; - if (!(this.precpred(this._ctx, 7))) { - throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); - } - this.state = 269; - this.binaryOperator(); - this.state = 270; - this.expression(8); - } - } - } - this.state = 276; - this._errHandler.sync(this); - _alt = this.interpreter.adaptivePredict(this._input, 18, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.unrollRecursionContexts(_parentctx); - } - return _localctx; - } - // @RuleVersion(0) - public groupedExpression(): GroupedExpressionContext { - let _localctx: GroupedExpressionContext = new GroupedExpressionContext(this._ctx, this.state); - this.enterRule(_localctx, 66, JackParser.RULE_groupedExpression); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 277; - this.match(JackParser.LPAREN); - this.state = 278; - this.expression(0); - this.state = 279; - this.match(JackParser.RPAREN); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public unaryOperation(): UnaryOperationContext { - let _localctx: UnaryOperationContext = new UnaryOperationContext(this._ctx, this.state); - this.enterRule(_localctx, 68, JackParser.RULE_unaryOperation); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 281; - this.unaryOperator(); - this.state = 282; - this.expression(0); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public arrayAccess(): ArrayAccessContext { - let _localctx: ArrayAccessContext = new ArrayAccessContext(this._ctx, this.state); - this.enterRule(_localctx, 70, JackParser.RULE_arrayAccess); - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 284; - this.varName(); - this.state = 285; - this.match(JackParser.LBRACKET); - this.state = 286; - this.expression(0); - this.state = 287; - this.match(JackParser.RBRACKET); - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public constant(): ConstantContext { - let _localctx: ConstantContext = new ConstantContext(this._ctx, this.state); - this.enterRule(_localctx, 72, JackParser.RULE_constant); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 289; - _la = this._input.LA(1); - if (!(((((_la - 40)) & ~0x1F) === 0 && ((1 << (_la - 40)) & ((1 << (JackParser.INTEGER_LITERAL - 40)) | (1 << (JackParser.BOOLEAN_LITERAL - 40)) | (1 << (JackParser.NULL_LITERAL - 40)) | (1 << (JackParser.THIS_LITERAL - 40)) | (1 << (JackParser.STRING_LITERAL - 40)))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public unaryOperator(): UnaryOperatorContext { - let _localctx: UnaryOperatorContext = new UnaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 74, JackParser.RULE_unaryOperator); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 291; - _la = this._input.LA(1); - if (!(_la === JackParser.MINUS || _la === JackParser.TILDE)) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - // @RuleVersion(0) - public binaryOperator(): BinaryOperatorContext { - let _localctx: BinaryOperatorContext = new BinaryOperatorContext(this._ctx, this.state); - this.enterRule(_localctx, 76, JackParser.RULE_binaryOperator); - let _la: number; - try { - this.enterOuterAlt(_localctx, 1); - { - this.state = 293; - _la = this._input.LA(1); - if (!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & ((1 << (JackParser.EQUALS - 27)) | (1 << (JackParser.PLUS - 27)) | (1 << (JackParser.MINUS - 27)) | (1 << (JackParser.MUL - 27)) | (1 << (JackParser.DIV - 27)) | (1 << (JackParser.AND - 27)) | (1 << (JackParser.OR - 27)) | (1 << (JackParser.LESS_THAN - 27)) | (1 << (JackParser.GREATER_THAN - 27)))) !== 0))) { - this._errHandler.recoverInline(this); - } else { - if (this._input.LA(1) === Token.EOF) { - this.matchedEOF = true; - } - - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - _localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return _localctx; - } - - public override sempred(_localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 32: - return this.expression_sempred(_localctx as ExpressionContext, predIndex); - } - return true; - } - private expression_sempred(_localctx: ExpressionContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return this.precpred(this._ctx, 7); - } - return true; - } - - public static readonly _serializedATN: string = - "\x03\uC91D\uCABA\u058D\uAFBA\u4F53\u0607\uEA8B\uC241\x030\u012A\x04\x02" + - "\t\x02\x04\x03\t\x03\x04\x04\t\x04\x04\x05\t\x05\x04\x06\t\x06\x04\x07" + - "\t\x07\x04\b\t\b\x04\t\t\t\x04\n\t\n\x04\v\t\v\x04\f\t\f\x04\r\t\r\x04" + - "\x0E\t\x0E\x04\x0F\t\x0F\x04\x10\t\x10\x04\x11\t\x11\x04\x12\t\x12\x04" + - "\x13\t\x13\x04\x14\t\x14\x04\x15\t\x15\x04\x16\t\x16\x04\x17\t\x17\x04" + - "\x18\t\x18\x04\x19\t\x19\x04\x1A\t\x1A\x04\x1B\t\x1B\x04\x1C\t\x1C\x04" + - "\x1D\t\x1D\x04\x1E\t\x1E\x04\x1F\t\x1F\x04 \t \x04!\t!\x04\"\t\"\x04#" + - "\t#\x04$\t$\x04%\t%\x04&\t&\x04\'\t\'\x04(\t(\x03\x02\x03\x02\x03\x02" + - "\x03\x03\x03\x03\x03\x03\x03\x03\x07\x03X\n\x03\f\x03\x0E\x03[\v\x03\x03" + - "\x03\x07\x03^\n\x03\f\x03\x0E\x03a\v\x03\x03\x03\x03\x03\x03\x04\x03\x04" + - "\x03\x05\x03\x05\x03\x05\x03\x05\x03\x06\x03\x06\x03\x06\x03\x06\x07\x06" + - "o\n\x06\f\x06\x0E\x06r\v\x06\x03\x07\x03\x07\x03\b\x03\b\x03\b\x03\t\x03" + - "\t\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\n\x03\v\x03\v\x03\f\x03\f\x05" + - "\f\x86\n\f\x03\r\x03\r\x03\x0E\x03\x0E\x03\x0E\x07\x0E\x8D\n\x0E\f\x0E" + - "\x0E\x0E\x90\v\x0E\x05\x0E\x92\n\x0E\x03\x0F\x03\x0F\x03\x0F\x03\x10\x03" + - "\x10\x03\x11\x03\x11\x07\x11\x9B\n\x11\f\x11\x0E\x11\x9E\v\x11\x03\x11" + - "\x03\x11\x03\x11\x03\x12\x03\x12\x03\x13\x03\x13\x03\x13\x03\x13\x03\x13" + - "\x07\x13\xAA\n\x13\f\x13\x0E\x13\xAD\v\x13\x03\x13\x03\x13\x03\x14\x03" + - "\x14\x03\x15\x03\x15\x03\x16\x07\x16\xB6\n\x16\f\x16\x0E\x16\xB9\v\x16" + - "\x03\x17\x03\x17\x03\x17\x03\x17\x03\x17\x05\x17\xC0\n\x17\x03\x18\x03" + - "\x18\x03\x18\x05\x18\xC5\n\x18\x03\x18\x03\x18\x03\x18\x03\x18\x03\x19" + - "\x03\x19\x05\x19\xCD\n\x19\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03\x1A\x03" + - "\x1A\x03\x1A\x03\x1A\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1B\x03\x1C\x03" + - "\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1C\x03\x1D\x03\x1D\x03" + - "\x1D\x03\x1D\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03\x1E\x03\x1F\x03\x1F\x05" + - "\x1F\xEF\n\x1F\x03\x1F\x05\x1F\xF2\n\x1F\x03\x1F\x03\x1F\x03 \x03 \x05" + - " \xF8\n \x03 \x03 \x03!\x03!\x03!\x07!\xFF\n!\f!\x0E!\u0102\v!\x05!\u0104" + - "\n!\x03\"\x03\"\x03\"\x03\"\x03\"\x03\"\x03\"\x05\"\u010D\n\"\x03\"\x03" + - "\"\x03\"\x03\"\x07\"\u0113\n\"\f\"\x0E\"\u0116\v\"\x03#\x03#\x03#\x03" + - "#\x03$\x03$\x03$\x03%\x03%\x03%\x03%\x03%\x03&\x03&\x03\'\x03\'\x03(\x03" + - "(\x03(\x02\x02\x03B)\x02\x02\x04\x02\x06\x02\b\x02\n\x02\f\x02\x0E\x02" + - "\x10\x02\x12\x02\x14\x02\x16\x02\x18\x02\x1A\x02\x1C\x02\x1E\x02 \x02" + - "\"\x02$\x02&\x02(\x02*\x02,\x02.\x020\x022\x024\x026\x028\x02:\x02<\x02" + - ">\x02@\x02B\x02D\x02F\x02H\x02J\x02L\x02N\x02\x02\b\x03\x02\x07\b\x03" + - "\x02\x04\x06\x04\x02\n\f..\x04\x02*-//\x04\x02\x1F\x1F$$\x04\x02\x1D#" + - "%&\x02\u011C\x02P\x03\x02\x02\x02\x04S\x03\x02\x02\x02\x06d\x03\x02\x02" + - "\x02\bf\x03\x02\x02\x02\nj\x03\x02\x02\x02\fs\x03\x02\x02\x02\x0Eu\x03" + - "\x02\x02\x02\x10x\x03\x02\x02\x02\x12z\x03\x02\x02\x02\x14\x81\x03\x02" + - "\x02\x02\x16\x85\x03\x02\x02\x02\x18\x87\x03\x02\x02\x02\x1A\x91\x03\x02" + - "\x02\x02\x1C\x93\x03\x02\x02\x02\x1E\x96\x03\x02\x02\x02 \x98\x03\x02" + - "\x02\x02\"\xA2\x03\x02\x02\x02$\xA4\x03\x02\x02\x02&\xB0\x03\x02\x02\x02" + - "(\xB2\x03\x02\x02\x02*\xB7\x03\x02\x02\x02,\xBF\x03\x02\x02\x02.\xC1\x03" + - "\x02\x02\x020\xCA\x03\x02\x02\x022\xCE\x03\x02\x02\x024\xD6\x03\x02\x02" + - "\x026\xDB\x03\x02\x02\x028\xE3\x03\x02\x02\x02:\xE7\x03\x02\x02\x02<\xF1" + - "\x03\x02\x02\x02>\xF5\x03\x02\x02\x02@\u0103\x03\x02\x02\x02B\u010C\x03" + - "\x02\x02\x02D\u0117\x03\x02\x02\x02F\u011B\x03\x02\x02\x02H\u011E\x03" + - "\x02\x02\x02J\u0123\x03\x02\x02\x02L\u0125\x03\x02\x02\x02N\u0127\x03" + - "\x02\x02\x02PQ\x05\x04\x03\x02QR\x07\x02\x02\x03R\x03\x03\x02\x02\x02" + - "ST\x07\x03\x02\x02TU\x05\x06\x04\x02UY\x07\x14\x02\x02VX\x05\b\x05\x02" + - "WV\x03\x02\x02\x02X[\x03\x02\x02\x02YW\x03\x02\x02\x02YZ\x03\x02\x02\x02" + - "Z_\x03\x02\x02\x02[Y\x03\x02\x02\x02\\^\x05\x0E\b\x02]\\\x03\x02\x02\x02" + - "^a\x03\x02\x02\x02_]\x03\x02\x02\x02_`\x03\x02\x02\x02`b\x03\x02\x02\x02" + - "a_\x03\x02\x02\x02bc\x05\"\x12\x02c\x05\x03\x02\x02\x02de\x07.\x02\x02" + - "e\x07\x03\x02\x02\x02fg\t\x02\x02\x02gh\x05\n\x06\x02hi\x07\x1C\x02\x02" + - "i\t\x03\x02\x02\x02jk\x05\x18\r\x02kp\x05\f\x07\x02lm\x07\x1B\x02\x02" + - "mo\x05\f\x07\x02nl\x03\x02\x02\x02or\x03\x02\x02\x02pn\x03\x02\x02\x02" + - "pq\x03\x02\x02\x02q\v\x03\x02\x02\x02rp\x03\x02\x02\x02st\x07.\x02\x02" + - "t\r\x03\x02\x02\x02uv\x05\x10\t\x02vw\x05\x12\n\x02w\x0F\x03\x02\x02\x02" + - "xy\t\x03\x02\x02y\x11\x03\x02\x02\x02z{\x05\x16\f\x02{|\x05\x14\v\x02" + - "|}\x07\x16\x02\x02}~\x05\x1A\x0E\x02~\x7F\x07\x17\x02\x02\x7F\x80\x05" + - " \x11\x02\x80\x13\x03\x02\x02\x02\x81\x82\x07.\x02\x02\x82\x15\x03\x02" + - "\x02\x02\x83\x86\x05\x18\r\x02\x84\x86\x07\r\x02\x02\x85\x83\x03\x02\x02" + - "\x02\x85\x84\x03\x02\x02\x02\x86\x17\x03\x02\x02\x02\x87\x88\t\x04\x02" + - "\x02\x88\x19\x03\x02\x02\x02\x89\x8E\x05\x1C\x0F\x02\x8A\x8B\x07\x1B\x02" + - "\x02\x8B\x8D\x05\x1C\x0F\x02\x8C\x8A\x03\x02\x02\x02\x8D\x90\x03\x02\x02" + - "\x02\x8E\x8C\x03\x02\x02\x02\x8E\x8F\x03\x02\x02\x02\x8F\x92\x03\x02\x02" + - "\x02\x90\x8E\x03\x02\x02\x02\x91\x89\x03\x02\x02\x02\x91\x92\x03\x02\x02" + - "\x02\x92\x1B\x03\x02\x02\x02\x93\x94\x05\x18\r\x02\x94\x95\x05\x1E\x10" + - "\x02\x95\x1D\x03\x02\x02\x02\x96\x97\x07.\x02\x02\x97\x1F\x03\x02\x02" + - "\x02\x98\x9C\x07\x14\x02\x02\x99\x9B\x05$\x13\x02\x9A\x99\x03\x02\x02" + - "\x02\x9B\x9E\x03\x02\x02\x02\x9C\x9A\x03\x02\x02\x02\x9C\x9D\x03\x02\x02" + - "\x02\x9D\x9F\x03\x02\x02\x02\x9E\x9C\x03\x02\x02\x02\x9F\xA0\x05*\x16" + - "\x02\xA0\xA1\x05\"\x12\x02\xA1!\x03\x02\x02\x02\xA2\xA3\x07\x15\x02\x02" + - "\xA3#\x03\x02\x02\x02\xA4\xA5\x07\t\x02\x02\xA5\xA6\x05\x18\r\x02\xA6" + - "\xAB\x05&\x14\x02\xA7\xA8\x07\x1B\x02\x02\xA8\xAA\x05&\x14\x02\xA9\xA7" + - "\x03\x02\x02\x02\xAA\xAD\x03\x02\x02\x02\xAB\xA9\x03\x02\x02\x02\xAB\xAC" + - "\x03\x02\x02\x02\xAC\xAE\x03\x02\x02\x02\xAD\xAB\x03\x02\x02\x02\xAE\xAF" + - "\x07\x1C\x02\x02\xAF%\x03\x02\x02\x02\xB0\xB1\x07.\x02\x02\xB1\'\x03\x02" + - "\x02\x02\xB2\xB3\x07.\x02\x02\xB3)\x03\x02\x02\x02\xB4\xB6\x05,\x17\x02" + - "\xB5\xB4\x03\x02\x02\x02\xB6\xB9\x03\x02\x02\x02\xB7\xB5\x03\x02\x02\x02" + - "\xB7\xB8\x03\x02\x02\x02\xB8+\x03\x02\x02\x02\xB9\xB7\x03\x02\x02\x02" + - "\xBA\xC0\x05.\x18\x02\xBB\xC0\x050\x19\x02\xBC\xC0\x056\x1C\x02\xBD\xC0" + - "\x058\x1D\x02\xBE\xC0\x05> \x02\xBF\xBA\x03\x02\x02\x02\xBF\xBB\x03\x02" + - "\x02\x02\xBF\xBC\x03\x02\x02\x02\xBF\xBD\x03\x02\x02\x02\xBF\xBE\x03\x02" + - "\x02\x02\xC0-\x03\x02\x02\x02\xC1\xC4\x07\x0E\x02\x02\xC2\xC5\x05(\x15" + - "\x02\xC3\xC5\x05H%\x02\xC4\xC2\x03\x02\x02\x02\xC4\xC3\x03\x02\x02\x02" + - "\xC5\xC6\x03\x02\x02\x02\xC6\xC7\x07\x1D\x02\x02\xC7\xC8\x05B\"\x02\xC8" + - "\xC9\x07\x1C\x02\x02\xC9/\x03\x02\x02\x02\xCA\xCC\x052\x1A\x02\xCB\xCD" + - "\x054\x1B\x02\xCC\xCB\x03\x02\x02\x02\xCC\xCD\x03\x02\x02\x02\xCD1\x03" + - "\x02\x02\x02\xCE\xCF\x07\x10\x02\x02\xCF\xD0\x07\x16\x02\x02\xD0\xD1\x05" + - "B\"\x02\xD1\xD2\x07\x17\x02\x02\xD2\xD3\x07\x14\x02\x02\xD3\xD4\x05*\x16" + - "\x02\xD4\xD5\x05\"\x12\x02\xD53\x03\x02\x02\x02\xD6\xD7\x07\x11\x02\x02" + - "\xD7\xD8\x07\x14\x02\x02\xD8\xD9\x05*\x16\x02\xD9\xDA\x05\"\x12\x02\xDA" + - "5\x03\x02\x02\x02\xDB\xDC\x07\x12\x02\x02\xDC\xDD\x07\x16\x02\x02\xDD" + - "\xDE\x05B\"\x02\xDE\xDF\x07\x17\x02\x02\xDF\xE0\x07\x14\x02\x02\xE0\xE1" + - "\x05*\x16\x02\xE1\xE2\x05\"\x12\x02\xE27\x03\x02\x02\x02\xE3\xE4\x07\x0F" + - "\x02\x02\xE4\xE5\x05:\x1E\x02\xE5\xE6\x07\x1C\x02\x02\xE69\x03\x02\x02" + - "\x02\xE7\xE8\x05<\x1F\x02\xE8\xE9\x07\x16\x02\x02\xE9\xEA\x05@!\x02\xEA" + - "\xEB\x07\x17\x02\x02\xEB;\x03\x02\x02\x02\xEC\xEF\x05\x06\x04\x02\xED" + - "\xEF\x07-\x02\x02\xEE\xEC\x03\x02\x02\x02\xEE\xED\x03\x02\x02\x02\xEF" + - "\xF0\x03\x02\x02\x02\xF0\xF2\x07\x1A\x02\x02\xF1\xEE\x03\x02\x02\x02\xF1" + - "\xF2\x03\x02\x02\x02\xF2\xF3\x03\x02\x02\x02\xF3\xF4\x05\x14\v\x02\xF4" + - "=\x03\x02\x02\x02\xF5\xF7\x07\x13\x02\x02\xF6\xF8\x05B\"\x02\xF7\xF6\x03" + - "\x02\x02\x02\xF7\xF8\x03\x02\x02\x02\xF8\xF9\x03\x02\x02\x02\xF9\xFA\x07" + - "\x1C\x02\x02\xFA?\x03\x02\x02\x02\xFB\u0100\x05B\"\x02\xFC\xFD\x07\x1B" + - "\x02\x02\xFD\xFF\x05B\"\x02\xFE\xFC\x03\x02\x02\x02\xFF\u0102\x03\x02" + - "\x02\x02\u0100\xFE\x03\x02\x02\x02\u0100\u0101\x03\x02\x02\x02\u0101\u0104" + - "\x03\x02\x02\x02\u0102\u0100\x03\x02\x02\x02\u0103\xFB\x03\x02\x02\x02" + - "\u0103\u0104\x03\x02\x02\x02\u0104A\x03\x02\x02\x02\u0105\u0106\b\"\x01" + - "\x02\u0106\u010D\x05J&\x02\u0107\u010D\x05(\x15\x02\u0108\u010D\x05:\x1E" + - "\x02\u0109\u010D\x05H%\x02\u010A\u010D\x05F$\x02\u010B\u010D\x05D#\x02" + - "\u010C\u0105\x03\x02\x02\x02\u010C\u0107\x03\x02\x02\x02\u010C\u0108\x03" + - "\x02\x02\x02\u010C\u0109\x03\x02\x02\x02\u010C\u010A\x03\x02\x02\x02\u010C" + - "\u010B\x03\x02\x02\x02\u010D\u0114\x03\x02\x02\x02\u010E\u010F\f\t\x02" + - "\x02\u010F\u0110\x05N(\x02\u0110\u0111\x05B\"\n\u0111\u0113\x03\x02\x02" + - "\x02\u0112\u010E\x03\x02\x02\x02\u0113\u0116\x03\x02\x02\x02\u0114\u0112" + - "\x03\x02\x02\x02\u0114\u0115\x03\x02\x02\x02\u0115C\x03\x02\x02\x02\u0116" + - "\u0114\x03\x02\x02\x02\u0117\u0118\x07\x16\x02\x02\u0118\u0119\x05B\"" + - "\x02\u0119\u011A\x07\x17\x02\x02\u011AE\x03\x02\x02\x02\u011B\u011C\x05" + - "L\'\x02\u011C\u011D\x05B\"\x02\u011DG\x03\x02\x02\x02\u011E\u011F\x05" + - "(\x15\x02\u011F\u0120\x07\x18\x02\x02\u0120\u0121\x05B\"\x02\u0121\u0122" + - "\x07\x19\x02\x02\u0122I\x03\x02\x02\x02\u0123\u0124\t\x05\x02\x02\u0124" + - "K\x03\x02\x02\x02\u0125\u0126\t\x06\x02\x02\u0126M\x03\x02\x02\x02\u0127" + - "\u0128\t\x07\x02\x02\u0128O\x03\x02\x02\x02\x15Y_p\x85\x8E\x91\x9C\xAB" + - "\xB7\xBF\xC4\xCC\xEE\xF1\xF7\u0100\u0103\u010C\u0114"; - public static __ATN: ATN; - public static get _ATN(): ATN { - if (!JackParser.__ATN) { - JackParser.__ATN = new ATNDeserializer().deserialize(Utils.toCharArray(JackParser._serializedATN)); - } - - return JackParser.__ATN; - } - -} - -export class ProgramContext extends ParserRuleContext { - public classDeclaration(): ClassDeclarationContext { - return this.getRuleContext(0, ClassDeclarationContext); - } - public EOF(): TerminalNode { return this.getToken(JackParser.EOF, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_program; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterProgram) { - listener.enterProgram(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitProgram) { - listener.exitProgram(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitProgram) { - return visitor.visitProgram(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ClassDeclarationContext extends ParserRuleContext { - public CLASS(): TerminalNode { return this.getToken(JackParser.CLASS, 0); } - public className(): ClassNameContext { - return this.getRuleContext(0, ClassNameContext); - } - public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext); - } - public classVarDec(): ClassVarDecContext[]; - public classVarDec(i: number): ClassVarDecContext; - public classVarDec(i?: number): ClassVarDecContext | ClassVarDecContext[] { - if (i === undefined) { - return this.getRuleContexts(ClassVarDecContext); - } else { - return this.getRuleContext(i, ClassVarDecContext); - } - } - public subroutineDeclaration(): SubroutineDeclarationContext[]; - public subroutineDeclaration(i: number): SubroutineDeclarationContext; - public subroutineDeclaration(i?: number): SubroutineDeclarationContext | SubroutineDeclarationContext[] { - if (i === undefined) { - return this.getRuleContexts(SubroutineDeclarationContext); - } else { - return this.getRuleContext(i, SubroutineDeclarationContext); - } - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_classDeclaration; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterClassDeclaration) { - listener.enterClassDeclaration(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitClassDeclaration) { - listener.exitClassDeclaration(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitClassDeclaration) { - return visitor.visitClassDeclaration(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ClassNameContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_className; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterClassName) { - listener.enterClassName(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitClassName) { - listener.exitClassName(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitClassName) { - return visitor.visitClassName(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ClassVarDecContext extends ParserRuleContext { - public fieldList(): FieldListContext { - return this.getRuleContext(0, FieldListContext); - } - public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } - public STATIC(): TerminalNode | undefined { return this.tryGetToken(JackParser.STATIC, 0); } - public FIELD(): TerminalNode | undefined { return this.tryGetToken(JackParser.FIELD, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_classVarDec; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterClassVarDec) { - listener.enterClassVarDec(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitClassVarDec) { - listener.exitClassVarDec(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitClassVarDec) { - return visitor.visitClassVarDec(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class FieldListContext extends ParserRuleContext { - public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext); - } - public fieldName(): FieldNameContext[]; - public fieldName(i: number): FieldNameContext; - public fieldName(i?: number): FieldNameContext | FieldNameContext[] { - if (i === undefined) { - return this.getRuleContexts(FieldNameContext); - } else { - return this.getRuleContext(i, FieldNameContext); - } - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.COMMA); - } else { - return this.getToken(JackParser.COMMA, i); - } - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_fieldList; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterFieldList) { - listener.enterFieldList(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitFieldList) { - listener.exitFieldList(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitFieldList) { - return visitor.visitFieldList(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class FieldNameContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_fieldName; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterFieldName) { - listener.enterFieldName(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitFieldName) { - listener.exitFieldName(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitFieldName) { - return visitor.visitFieldName(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class SubroutineDeclarationContext extends ParserRuleContext { - public subroutineType(): SubroutineTypeContext { - return this.getRuleContext(0, SubroutineTypeContext); - } - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - return this.getRuleContext(0, SubroutineDecWithoutTypeContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineDeclaration; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineDeclaration) { - listener.enterSubroutineDeclaration(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineDeclaration) { - listener.exitSubroutineDeclaration(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitSubroutineDeclaration) { - return visitor.visitSubroutineDeclaration(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class SubroutineTypeContext extends ParserRuleContext { - public CONSTRUCTOR(): TerminalNode | undefined { return this.tryGetToken(JackParser.CONSTRUCTOR, 0); } - public METHOD(): TerminalNode | undefined { return this.tryGetToken(JackParser.METHOD, 0); } - public FUNCTION(): TerminalNode | undefined { return this.tryGetToken(JackParser.FUNCTION, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineType; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineType) { - listener.enterSubroutineType(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineType) { - listener.exitSubroutineType(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitSubroutineType) { - return visitor.visitSubroutineType(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class SubroutineDecWithoutTypeContext extends ParserRuleContext { - public subroutineReturnType(): SubroutineReturnTypeContext { - return this.getRuleContext(0, SubroutineReturnTypeContext); - } - public subroutineName(): SubroutineNameContext { - return this.getRuleContext(0, SubroutineNameContext); - } - public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } - public parameterList(): ParameterListContext { - return this.getRuleContext(0, ParameterListContext); - } - public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } - public subroutineBody(): SubroutineBodyContext { - return this.getRuleContext(0, SubroutineBodyContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineDecWithoutType; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineDecWithoutType) { - listener.enterSubroutineDecWithoutType(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineDecWithoutType) { - listener.exitSubroutineDecWithoutType(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitSubroutineDecWithoutType) { - return visitor.visitSubroutineDecWithoutType(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class SubroutineNameContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineName; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineName) { - listener.enterSubroutineName(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineName) { - listener.exitSubroutineName(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitSubroutineName) { - return visitor.visitSubroutineName(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class SubroutineReturnTypeContext extends ParserRuleContext { - public varType(): VarTypeContext | undefined { - return this.tryGetRuleContext(0, VarTypeContext); - } - public VOID(): TerminalNode | undefined { return this.tryGetToken(JackParser.VOID, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineReturnType; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineReturnType) { - listener.enterSubroutineReturnType(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineReturnType) { - listener.exitSubroutineReturnType(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitSubroutineReturnType) { - return visitor.visitSubroutineReturnType(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class VarTypeContext extends ParserRuleContext { - public INT(): TerminalNode | undefined { return this.tryGetToken(JackParser.INT, 0); } - public CHAR(): TerminalNode | undefined { return this.tryGetToken(JackParser.CHAR, 0); } - public BOOLEAN(): TerminalNode | undefined { return this.tryGetToken(JackParser.BOOLEAN, 0); } - public IDENTIFIER(): TerminalNode | undefined { return this.tryGetToken(JackParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_varType; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterVarType) { - listener.enterVarType(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitVarType) { - listener.exitVarType(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitVarType) { - return visitor.visitVarType(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ParameterListContext extends ParserRuleContext { - public parameter(): ParameterContext[]; - public parameter(i: number): ParameterContext; - public parameter(i?: number): ParameterContext | ParameterContext[] { - if (i === undefined) { - return this.getRuleContexts(ParameterContext); - } else { - return this.getRuleContext(i, ParameterContext); - } - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.COMMA); - } else { - return this.getToken(JackParser.COMMA, i); - } - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_parameterList; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterParameterList) { - listener.enterParameterList(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitParameterList) { - listener.exitParameterList(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitParameterList) { - return visitor.visitParameterList(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ParameterContext extends ParserRuleContext { - public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext); - } - public parameterName(): ParameterNameContext { - return this.getRuleContext(0, ParameterNameContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_parameter; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterParameter) { - listener.enterParameter(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitParameter) { - listener.exitParameter(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitParameter) { - return visitor.visitParameter(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ParameterNameContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_parameterName; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterParameterName) { - listener.enterParameterName(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitParameterName) { - listener.exitParameterName(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitParameterName) { - return visitor.visitParameterName(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class SubroutineBodyContext extends ParserRuleContext { - public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } - public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext); - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext); - } - public varDeclaration(): VarDeclarationContext[]; - public varDeclaration(i: number): VarDeclarationContext; - public varDeclaration(i?: number): VarDeclarationContext | VarDeclarationContext[] { - if (i === undefined) { - return this.getRuleContexts(VarDeclarationContext); - } else { - return this.getRuleContext(i, VarDeclarationContext); - } - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineBody; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineBody) { - listener.enterSubroutineBody(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineBody) { - listener.exitSubroutineBody(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitSubroutineBody) { - return visitor.visitSubroutineBody(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class RBraceContext extends ParserRuleContext { - public RBRACE(): TerminalNode { return this.getToken(JackParser.RBRACE, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_rBrace; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterRBrace) { - listener.enterRBrace(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitRBrace) { - listener.exitRBrace(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitRBrace) { - return visitor.visitRBrace(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class VarDeclarationContext extends ParserRuleContext { - public VAR(): TerminalNode { return this.getToken(JackParser.VAR, 0); } - public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext); - } - public varNameInDeclaration(): VarNameInDeclarationContext[]; - public varNameInDeclaration(i: number): VarNameInDeclarationContext; - public varNameInDeclaration(i?: number): VarNameInDeclarationContext | VarNameInDeclarationContext[] { - if (i === undefined) { - return this.getRuleContexts(VarNameInDeclarationContext); - } else { - return this.getRuleContext(i, VarNameInDeclarationContext); - } - } - public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.COMMA); - } else { - return this.getToken(JackParser.COMMA, i); - } - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_varDeclaration; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterVarDeclaration) { - listener.enterVarDeclaration(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitVarDeclaration) { - listener.exitVarDeclaration(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitVarDeclaration) { - return visitor.visitVarDeclaration(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class VarNameInDeclarationContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_varNameInDeclaration; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterVarNameInDeclaration) { - listener.enterVarNameInDeclaration(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitVarNameInDeclaration) { - listener.exitVarNameInDeclaration(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitVarNameInDeclaration) { - return visitor.visitVarNameInDeclaration(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class VarNameContext extends ParserRuleContext { - public IDENTIFIER(): TerminalNode { return this.getToken(JackParser.IDENTIFIER, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_varName; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterVarName) { - listener.enterVarName(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitVarName) { - listener.exitVarName(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitVarName) { - return visitor.visitVarName(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class StatementsContext extends ParserRuleContext { - public statement(): StatementContext[]; - public statement(i: number): StatementContext; - public statement(i?: number): StatementContext | StatementContext[] { - if (i === undefined) { - return this.getRuleContexts(StatementContext); - } else { - return this.getRuleContext(i, StatementContext); - } - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_statements; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterStatements) { - listener.enterStatements(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitStatements) { - listener.exitStatements(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitStatements) { - return visitor.visitStatements(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class StatementContext extends ParserRuleContext { - public letStatement(): LetStatementContext | undefined { - return this.tryGetRuleContext(0, LetStatementContext); - } - public ifElseStatement(): IfElseStatementContext | undefined { - return this.tryGetRuleContext(0, IfElseStatementContext); - } - public whileStatement(): WhileStatementContext | undefined { - return this.tryGetRuleContext(0, WhileStatementContext); - } - public doStatement(): DoStatementContext | undefined { - return this.tryGetRuleContext(0, DoStatementContext); - } - public returnStatement(): ReturnStatementContext | undefined { - return this.tryGetRuleContext(0, ReturnStatementContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_statement; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterStatement) { - listener.enterStatement(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitStatement) { - listener.exitStatement(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitStatement) { - return visitor.visitStatement(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class LetStatementContext extends ParserRuleContext { - public LET(): TerminalNode { return this.getToken(JackParser.LET, 0); } - public EQUALS(): TerminalNode { return this.getToken(JackParser.EQUALS, 0); } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext); - } - public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } - public varName(): VarNameContext | undefined { - return this.tryGetRuleContext(0, VarNameContext); - } - public arrayAccess(): ArrayAccessContext | undefined { - return this.tryGetRuleContext(0, ArrayAccessContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_letStatement; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterLetStatement) { - listener.enterLetStatement(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitLetStatement) { - listener.exitLetStatement(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitLetStatement) { - return visitor.visitLetStatement(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class IfElseStatementContext extends ParserRuleContext { - public ifStatement(): IfStatementContext { - return this.getRuleContext(0, IfStatementContext); - } - public elseStatement(): ElseStatementContext | undefined { - return this.tryGetRuleContext(0, ElseStatementContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_ifElseStatement; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterIfElseStatement) { - listener.enterIfElseStatement(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitIfElseStatement) { - listener.exitIfElseStatement(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitIfElseStatement) { - return visitor.visitIfElseStatement(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class IfStatementContext extends ParserRuleContext { - public IF(): TerminalNode { return this.getToken(JackParser.IF, 0); } - public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext); - } - public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } - public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } - public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext); - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_ifStatement; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterIfStatement) { - listener.enterIfStatement(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitIfStatement) { - listener.exitIfStatement(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitIfStatement) { - return visitor.visitIfStatement(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ElseStatementContext extends ParserRuleContext { - public ELSE(): TerminalNode { return this.getToken(JackParser.ELSE, 0); } - public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } - public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext); - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_elseStatement; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterElseStatement) { - listener.enterElseStatement(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitElseStatement) { - listener.exitElseStatement(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitElseStatement) { - return visitor.visitElseStatement(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class WhileStatementContext extends ParserRuleContext { - public WHILE(): TerminalNode { return this.getToken(JackParser.WHILE, 0); } - public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext); - } - public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } - public LBRACE(): TerminalNode { return this.getToken(JackParser.LBRACE, 0); } - public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext); - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_whileStatement; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterWhileStatement) { - listener.enterWhileStatement(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitWhileStatement) { - listener.exitWhileStatement(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitWhileStatement) { - return visitor.visitWhileStatement(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class DoStatementContext extends ParserRuleContext { - public DO(): TerminalNode { return this.getToken(JackParser.DO, 0); } - public subroutineCall(): SubroutineCallContext { - return this.getRuleContext(0, SubroutineCallContext); - } - public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_doStatement; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterDoStatement) { - listener.enterDoStatement(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitDoStatement) { - listener.exitDoStatement(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitDoStatement) { - return visitor.visitDoStatement(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class SubroutineCallContext extends ParserRuleContext { - public subroutineId(): SubroutineIdContext { - return this.getRuleContext(0, SubroutineIdContext); - } - public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } - public expressionList(): ExpressionListContext { - return this.getRuleContext(0, ExpressionListContext); - } - public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineCall; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineCall) { - listener.enterSubroutineCall(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineCall) { - listener.exitSubroutineCall(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitSubroutineCall) { - return visitor.visitSubroutineCall(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class SubroutineIdContext extends ParserRuleContext { - public subroutineName(): SubroutineNameContext { - return this.getRuleContext(0, SubroutineNameContext); - } - public DOT(): TerminalNode | undefined { return this.tryGetToken(JackParser.DOT, 0); } - public className(): ClassNameContext | undefined { - return this.tryGetRuleContext(0, ClassNameContext); - } - public THIS_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.THIS_LITERAL, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_subroutineId; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineId) { - listener.enterSubroutineId(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineId) { - listener.exitSubroutineId(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitSubroutineId) { - return visitor.visitSubroutineId(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ReturnStatementContext extends ParserRuleContext { - public RETURN(): TerminalNode { return this.getToken(JackParser.RETURN, 0); } - public SEMICOLON(): TerminalNode { return this.getToken(JackParser.SEMICOLON, 0); } - public expression(): ExpressionContext | undefined { - return this.tryGetRuleContext(0, ExpressionContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_returnStatement; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterReturnStatement) { - listener.enterReturnStatement(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitReturnStatement) { - listener.exitReturnStatement(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitReturnStatement) { - return visitor.visitReturnStatement(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ExpressionListContext extends ParserRuleContext { - public expression(): ExpressionContext[]; - public expression(i: number): ExpressionContext; - public expression(i?: number): ExpressionContext | ExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(ExpressionContext); - } else { - return this.getRuleContext(i, ExpressionContext); - } - } - public COMMA(): TerminalNode[]; - public COMMA(i: number): TerminalNode; - public COMMA(i?: number): TerminalNode | TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.COMMA); - } else { - return this.getToken(JackParser.COMMA, i); - } - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_expressionList; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterExpressionList) { - listener.enterExpressionList(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitExpressionList) { - listener.exitExpressionList(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitExpressionList) { - return visitor.visitExpressionList(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ExpressionContext extends ParserRuleContext { - public expression(): ExpressionContext[]; - public expression(i: number): ExpressionContext; - public expression(i?: number): ExpressionContext | ExpressionContext[] { - if (i === undefined) { - return this.getRuleContexts(ExpressionContext); - } else { - return this.getRuleContext(i, ExpressionContext); - } - } - public binaryOperator(): BinaryOperatorContext | undefined { - return this.tryGetRuleContext(0, BinaryOperatorContext); - } - public constant(): ConstantContext | undefined { - return this.tryGetRuleContext(0, ConstantContext); - } - public varName(): VarNameContext | undefined { - return this.tryGetRuleContext(0, VarNameContext); - } - public subroutineCall(): SubroutineCallContext | undefined { - return this.tryGetRuleContext(0, SubroutineCallContext); - } - public arrayAccess(): ArrayAccessContext | undefined { - return this.tryGetRuleContext(0, ArrayAccessContext); - } - public unaryOperation(): UnaryOperationContext | undefined { - return this.tryGetRuleContext(0, UnaryOperationContext); - } - public groupedExpression(): GroupedExpressionContext | undefined { - return this.tryGetRuleContext(0, GroupedExpressionContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_expression; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterExpression) { - listener.enterExpression(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitExpression) { - listener.exitExpression(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitExpression) { - return visitor.visitExpression(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class GroupedExpressionContext extends ParserRuleContext { - public LPAREN(): TerminalNode { return this.getToken(JackParser.LPAREN, 0); } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext); - } - public RPAREN(): TerminalNode { return this.getToken(JackParser.RPAREN, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_groupedExpression; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterGroupedExpression) { - listener.enterGroupedExpression(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitGroupedExpression) { - listener.exitGroupedExpression(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitGroupedExpression) { - return visitor.visitGroupedExpression(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class UnaryOperationContext extends ParserRuleContext { - public unaryOperator(): UnaryOperatorContext { - return this.getRuleContext(0, UnaryOperatorContext); - } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext); - } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_unaryOperation; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterUnaryOperation) { - listener.enterUnaryOperation(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitUnaryOperation) { - listener.exitUnaryOperation(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitUnaryOperation) { - return visitor.visitUnaryOperation(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ArrayAccessContext extends ParserRuleContext { - public varName(): VarNameContext { - return this.getRuleContext(0, VarNameContext); - } - public LBRACKET(): TerminalNode { return this.getToken(JackParser.LBRACKET, 0); } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext); - } - public RBRACKET(): TerminalNode { return this.getToken(JackParser.RBRACKET, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_arrayAccess; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterArrayAccess) { - listener.enterArrayAccess(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitArrayAccess) { - listener.exitArrayAccess(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitArrayAccess) { - return visitor.visitArrayAccess(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class ConstantContext extends ParserRuleContext { - public INTEGER_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.INTEGER_LITERAL, 0); } - public STRING_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.STRING_LITERAL, 0); } - public BOOLEAN_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.BOOLEAN_LITERAL, 0); } - public NULL_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.NULL_LITERAL, 0); } - public THIS_LITERAL(): TerminalNode | undefined { return this.tryGetToken(JackParser.THIS_LITERAL, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_constant; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterConstant) { - listener.enterConstant(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitConstant) { - listener.exitConstant(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitConstant) { - return visitor.visitConstant(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class UnaryOperatorContext extends ParserRuleContext { - public TILDE(): TerminalNode | undefined { return this.tryGetToken(JackParser.TILDE, 0); } - public MINUS(): TerminalNode | undefined { return this.tryGetToken(JackParser.MINUS, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_unaryOperator; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterUnaryOperator) { - listener.enterUnaryOperator(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitUnaryOperator) { - listener.exitUnaryOperator(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitUnaryOperator) { - return visitor.visitUnaryOperator(this); - } else { - return visitor.visitChildren(this); - } - } -} - - -export class BinaryOperatorContext extends ParserRuleContext { - public PLUS(): TerminalNode | undefined { return this.tryGetToken(JackParser.PLUS, 0); } - public MINUS(): TerminalNode | undefined { return this.tryGetToken(JackParser.MINUS, 0); } - public MUL(): TerminalNode | undefined { return this.tryGetToken(JackParser.MUL, 0); } - public DIV(): TerminalNode | undefined { return this.tryGetToken(JackParser.DIV, 0); } - public AND(): TerminalNode | undefined { return this.tryGetToken(JackParser.AND, 0); } - public OR(): TerminalNode | undefined { return this.tryGetToken(JackParser.OR, 0); } - public LESS_THAN(): TerminalNode | undefined { return this.tryGetToken(JackParser.LESS_THAN, 0); } - public GREATER_THAN(): TerminalNode | undefined { return this.tryGetToken(JackParser.GREATER_THAN, 0); } - public EQUALS(): TerminalNode | undefined { return this.tryGetToken(JackParser.EQUALS, 0); } - constructor(parent: ParserRuleContext | undefined, invokingState: number) { - super(parent, invokingState); - } - // @Override - public override get ruleIndex(): number { return JackParser.RULE_binaryOperator; } - // @Override - public override enterRule(listener: JackParserListener): void { - if (listener.enterBinaryOperator) { - listener.enterBinaryOperator(this); - } - } - // @Override - public override exitRule(listener: JackParserListener): void { - if (listener.exitBinaryOperator) { - listener.exitBinaryOperator(this); - } - } - // @Override - public override accept(visitor: JackParserVisitor): Result { - if (visitor.visitBinaryOperator) { - return visitor.visitBinaryOperator(this); - } else { - return visitor.visitChildren(this); - } - } -} - - diff --git a/compiler/src/generated/JackParserListener.ts b/compiler/src/generated/JackParserListener.ts deleted file mode 100644 index d67200be..00000000 --- a/compiler/src/generated/JackParserListener.ts +++ /dev/null @@ -1,481 +0,0 @@ -// Generated from JackParser.g4 by ANTLR 4.9.0-SNAPSHOT - - -import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; - -import { ProgramContext } from "./JackParser"; -import { ClassDeclarationContext } from "./JackParser"; -import { ClassNameContext } from "./JackParser"; -import { ClassVarDecContext } from "./JackParser"; -import { FieldListContext } from "./JackParser"; -import { FieldNameContext } from "./JackParser"; -import { SubroutineDeclarationContext } from "./JackParser"; -import { SubroutineTypeContext } from "./JackParser"; -import { SubroutineDecWithoutTypeContext } from "./JackParser"; -import { SubroutineNameContext } from "./JackParser"; -import { SubroutineReturnTypeContext } from "./JackParser"; -import { VarTypeContext } from "./JackParser"; -import { ParameterListContext } from "./JackParser"; -import { ParameterContext } from "./JackParser"; -import { ParameterNameContext } from "./JackParser"; -import { SubroutineBodyContext } from "./JackParser"; -import { RBraceContext } from "./JackParser"; -import { VarDeclarationContext } from "./JackParser"; -import { VarNameInDeclarationContext } from "./JackParser"; -import { VarNameContext } from "./JackParser"; -import { StatementsContext } from "./JackParser"; -import { StatementContext } from "./JackParser"; -import { LetStatementContext } from "./JackParser"; -import { IfElseStatementContext } from "./JackParser"; -import { IfStatementContext } from "./JackParser"; -import { ElseStatementContext } from "./JackParser"; -import { WhileStatementContext } from "./JackParser"; -import { DoStatementContext } from "./JackParser"; -import { SubroutineCallContext } from "./JackParser"; -import { SubroutineIdContext } from "./JackParser"; -import { ReturnStatementContext } from "./JackParser"; -import { ExpressionListContext } from "./JackParser"; -import { ExpressionContext } from "./JackParser"; -import { GroupedExpressionContext } from "./JackParser"; -import { UnaryOperationContext } from "./JackParser"; -import { ArrayAccessContext } from "./JackParser"; -import { ConstantContext } from "./JackParser"; -import { UnaryOperatorContext } from "./JackParser"; -import { BinaryOperatorContext } from "./JackParser"; - - -/** - * This interface defines a complete listener for a parse tree produced by - * `JackParser`. - */ -export interface JackParserListener extends ParseTreeListener { - /** - * Enter a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - */ - enterProgram?: (ctx: ProgramContext) => void; - /** - * Exit a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - */ - exitProgram?: (ctx: ProgramContext) => void; - - /** - * Enter a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - */ - enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - */ - exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; - - /** - * Enter a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - */ - enterClassName?: (ctx: ClassNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - */ - exitClassName?: (ctx: ClassNameContext) => void; - - /** - * Enter a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - */ - enterClassVarDec?: (ctx: ClassVarDecContext) => void; - /** - * Exit a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - */ - exitClassVarDec?: (ctx: ClassVarDecContext) => void; - - /** - * Enter a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - */ - enterFieldList?: (ctx: FieldListContext) => void; - /** - * Exit a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - */ - exitFieldList?: (ctx: FieldListContext) => void; - - /** - * Enter a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - */ - enterFieldName?: (ctx: FieldNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - */ - exitFieldName?: (ctx: FieldNameContext) => void; - - /** - * Enter a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; - - /** - * Enter a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - */ - enterSubroutineType?: (ctx: SubroutineTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - */ - exitSubroutineType?: (ctx: SubroutineTypeContext) => void; - - /** - * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - */ - enterSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - */ - exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; - - /** - * Enter a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - */ - enterSubroutineName?: (ctx: SubroutineNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - */ - exitSubroutineName?: (ctx: SubroutineNameContext) => void; - - /** - * Enter a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - */ - enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - */ - exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; - - /** - * Enter a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - */ - enterVarType?: (ctx: VarTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - */ - exitVarType?: (ctx: VarTypeContext) => void; - - /** - * Enter a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - */ - enterParameterList?: (ctx: ParameterListContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - */ - exitParameterList?: (ctx: ParameterListContext) => void; - - /** - * Enter a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - */ - enterParameter?: (ctx: ParameterContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - */ - exitParameter?: (ctx: ParameterContext) => void; - - /** - * Enter a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - */ - enterParameterName?: (ctx: ParameterNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - */ - exitParameterName?: (ctx: ParameterNameContext) => void; - - /** - * Enter a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - */ - enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - */ - exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; - - /** - * Enter a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - */ - enterRBrace?: (ctx: RBraceContext) => void; - /** - * Exit a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - */ - exitRBrace?: (ctx: RBraceContext) => void; - - /** - * Enter a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - */ - enterVarDeclaration?: (ctx: VarDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - */ - exitVarDeclaration?: (ctx: VarDeclarationContext) => void; - - /** - * Enter a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - */ - enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - */ - exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; - - /** - * Enter a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - */ - enterVarName?: (ctx: VarNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - */ - exitVarName?: (ctx: VarNameContext) => void; - - /** - * Enter a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - */ - enterStatements?: (ctx: StatementsContext) => void; - /** - * Exit a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - */ - exitStatements?: (ctx: StatementsContext) => void; - - /** - * Enter a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - */ - enterStatement?: (ctx: StatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - */ - exitStatement?: (ctx: StatementContext) => void; - - /** - * Enter a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - */ - enterLetStatement?: (ctx: LetStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - */ - exitLetStatement?: (ctx: LetStatementContext) => void; - - /** - * Enter a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - */ - enterIfElseStatement?: (ctx: IfElseStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - */ - exitIfElseStatement?: (ctx: IfElseStatementContext) => void; - - /** - * Enter a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - */ - enterIfStatement?: (ctx: IfStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - */ - exitIfStatement?: (ctx: IfStatementContext) => void; - - /** - * Enter a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - */ - enterElseStatement?: (ctx: ElseStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - */ - exitElseStatement?: (ctx: ElseStatementContext) => void; - - /** - * Enter a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - */ - enterWhileStatement?: (ctx: WhileStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - */ - exitWhileStatement?: (ctx: WhileStatementContext) => void; - - /** - * Enter a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - */ - enterDoStatement?: (ctx: DoStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - */ - exitDoStatement?: (ctx: DoStatementContext) => void; - - /** - * Enter a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - */ - enterSubroutineCall?: (ctx: SubroutineCallContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - */ - exitSubroutineCall?: (ctx: SubroutineCallContext) => void; - - /** - * Enter a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - */ - enterSubroutineId?: (ctx: SubroutineIdContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - */ - exitSubroutineId?: (ctx: SubroutineIdContext) => void; - - /** - * Enter a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - */ - enterReturnStatement?: (ctx: ReturnStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - */ - exitReturnStatement?: (ctx: ReturnStatementContext) => void; - - /** - * Enter a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - */ - enterExpressionList?: (ctx: ExpressionListContext) => void; - /** - * Exit a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - */ - exitExpressionList?: (ctx: ExpressionListContext) => void; - - /** - * Enter a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - */ - enterExpression?: (ctx: ExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - */ - exitExpression?: (ctx: ExpressionContext) => void; - - /** - * Enter a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - */ - enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - */ - exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; - - /** - * Enter a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - */ - enterUnaryOperation?: (ctx: UnaryOperationContext) => void; - /** - * Exit a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - */ - exitUnaryOperation?: (ctx: UnaryOperationContext) => void; - - /** - * Enter a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - */ - enterArrayAccess?: (ctx: ArrayAccessContext) => void; - /** - * Exit a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - */ - exitArrayAccess?: (ctx: ArrayAccessContext) => void; - - /** - * Enter a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - */ - enterConstant?: (ctx: ConstantContext) => void; - /** - * Exit a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - */ - exitConstant?: (ctx: ConstantContext) => void; - - /** - * Enter a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - */ - enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; - /** - * Exit a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - */ - exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; - - /** - * Enter a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - */ - enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; - /** - * Exit a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - */ - exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; -} - diff --git a/compiler/src/generated/JackParserVisitor.ts b/compiler/src/generated/JackParserVisitor.ts deleted file mode 100644 index f4c39796..00000000 --- a/compiler/src/generated/JackParserVisitor.ts +++ /dev/null @@ -1,328 +0,0 @@ -// Generated from JackParser.g4 by ANTLR 4.9.0-SNAPSHOT - - -import { ParseTreeVisitor } from "antlr4ts/tree/ParseTreeVisitor"; - -import { ProgramContext } from "./JackParser"; -import { ClassDeclarationContext } from "./JackParser"; -import { ClassNameContext } from "./JackParser"; -import { ClassVarDecContext } from "./JackParser"; -import { FieldListContext } from "./JackParser"; -import { FieldNameContext } from "./JackParser"; -import { SubroutineDeclarationContext } from "./JackParser"; -import { SubroutineTypeContext } from "./JackParser"; -import { SubroutineDecWithoutTypeContext } from "./JackParser"; -import { SubroutineNameContext } from "./JackParser"; -import { SubroutineReturnTypeContext } from "./JackParser"; -import { VarTypeContext } from "./JackParser"; -import { ParameterListContext } from "./JackParser"; -import { ParameterContext } from "./JackParser"; -import { ParameterNameContext } from "./JackParser"; -import { SubroutineBodyContext } from "./JackParser"; -import { RBraceContext } from "./JackParser"; -import { VarDeclarationContext } from "./JackParser"; -import { VarNameInDeclarationContext } from "./JackParser"; -import { VarNameContext } from "./JackParser"; -import { StatementsContext } from "./JackParser"; -import { StatementContext } from "./JackParser"; -import { LetStatementContext } from "./JackParser"; -import { IfElseStatementContext } from "./JackParser"; -import { IfStatementContext } from "./JackParser"; -import { ElseStatementContext } from "./JackParser"; -import { WhileStatementContext } from "./JackParser"; -import { DoStatementContext } from "./JackParser"; -import { SubroutineCallContext } from "./JackParser"; -import { SubroutineIdContext } from "./JackParser"; -import { ReturnStatementContext } from "./JackParser"; -import { ExpressionListContext } from "./JackParser"; -import { ExpressionContext } from "./JackParser"; -import { GroupedExpressionContext } from "./JackParser"; -import { UnaryOperationContext } from "./JackParser"; -import { ArrayAccessContext } from "./JackParser"; -import { ConstantContext } from "./JackParser"; -import { UnaryOperatorContext } from "./JackParser"; -import { BinaryOperatorContext } from "./JackParser"; - - -/** - * This interface defines a complete generic visitor for a parse tree produced - * by `JackParser`. - * - * @param The return type of the visit operation. Use `void` for - * operations with no return type. - */ -export interface JackParserVisitor extends ParseTreeVisitor { - /** - * Visit a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - * @return the visitor result - */ - visitProgram?: (ctx: ProgramContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - * @return the visitor result - */ - visitClassDeclaration?: (ctx: ClassDeclarationContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - * @return the visitor result - */ - visitClassName?: (ctx: ClassNameContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - * @return the visitor result - */ - visitClassVarDec?: (ctx: ClassVarDecContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitFieldList?: (ctx: FieldListContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - * @return the visitor result - */ - visitFieldName?: (ctx: FieldNameContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - * @return the visitor result - */ - visitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - * @return the visitor result - */ - visitSubroutineType?: (ctx: SubroutineTypeContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - * @return the visitor result - */ - visitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - * @return the visitor result - */ - visitSubroutineName?: (ctx: SubroutineNameContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - * @return the visitor result - */ - visitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - * @return the visitor result - */ - visitVarType?: (ctx: VarTypeContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitParameterList?: (ctx: ParameterListContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - * @return the visitor result - */ - visitParameter?: (ctx: ParameterContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - * @return the visitor result - */ - visitParameterName?: (ctx: ParameterNameContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - * @return the visitor result - */ - visitSubroutineBody?: (ctx: SubroutineBodyContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - * @return the visitor result - */ - visitRBrace?: (ctx: RBraceContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - * @return the visitor result - */ - visitVarDeclaration?: (ctx: VarDeclarationContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - * @return the visitor result - */ - visitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - * @return the visitor result - */ - visitVarName?: (ctx: VarNameContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - * @return the visitor result - */ - visitStatements?: (ctx: StatementsContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - * @return the visitor result - */ - visitStatement?: (ctx: StatementContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - * @return the visitor result - */ - visitLetStatement?: (ctx: LetStatementContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - * @return the visitor result - */ - visitIfElseStatement?: (ctx: IfElseStatementContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - * @return the visitor result - */ - visitIfStatement?: (ctx: IfStatementContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - * @return the visitor result - */ - visitElseStatement?: (ctx: ElseStatementContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - * @return the visitor result - */ - visitWhileStatement?: (ctx: WhileStatementContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - * @return the visitor result - */ - visitDoStatement?: (ctx: DoStatementContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - * @return the visitor result - */ - visitSubroutineCall?: (ctx: SubroutineCallContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - * @return the visitor result - */ - visitSubroutineId?: (ctx: SubroutineIdContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - * @return the visitor result - */ - visitReturnStatement?: (ctx: ReturnStatementContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - * @return the visitor result - */ - visitExpressionList?: (ctx: ExpressionListContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - * @return the visitor result - */ - visitExpression?: (ctx: ExpressionContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - * @return the visitor result - */ - visitGroupedExpression?: (ctx: GroupedExpressionContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - * @return the visitor result - */ - visitUnaryOperation?: (ctx: UnaryOperationContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - * @return the visitor result - */ - visitArrayAccess?: (ctx: ArrayAccessContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - * @return the visitor result - */ - visitConstant?: (ctx: ConstantContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - * @return the visitor result - */ - visitUnaryOperator?: (ctx: UnaryOperatorContext) => Result; - - /** - * Visit a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - * @return the visitor result - */ - visitBinaryOperator?: (ctx: BinaryOperatorContext) => Result; -} - diff --git a/compiler/src/listener/binder.listener.ts b/compiler/src/listener/binder.listener.ts deleted file mode 100644 index 8929fa5c..00000000 --- a/compiler/src/listener/binder.listener.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { ClassDeclarationContext, SubroutineBodyContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameInDeclarationContext } from "../generated/JackParser"; -import { JackParserListener } from "../generated/JackParserListener"; -import { DuplicatedSubroutineError } from '../error' -import { builtInSymbols, builtInTypes } from "../builtins"; -import { GenericSymbol, SubroutineInfo, SubroutineType } from "../symbol"; - -const primitives = new Set(builtInTypes); -export type Primitive = typeof primitives extends Set ? S : never; - -/** - * Creates global symbol table that contains built-in functions and found classes and subroutines - */ -export class BinderListener implements JackParserListener { - // key can be class or . - public globalSymbolTable: Record = structuredClone(builtInSymbols); - public className = ""; - public errors: DuplicatedSubroutineError[] = [] - private subRoutineInfo: SubroutineInfo = {} as SubroutineInfo; - private subroutineVarsCount: number = 0; - private stopProcessingSubroutines = false; - private subroutineId = ""; - //to fix compiler error - visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; - - enterClassDeclaration(ctx: ClassDeclarationContext) { - if (this.globalSymbolTable[ctx.className()!.text] != undefined) { - this.errors.push(new DuplicatedSubroutineError(ctx.start.line, ctx.start.startIndex, `Class "${ctx.className()!.text}" is already defined.`)); - return; - } - this.globalSymbolTable[ctx.className()!.text] = {} as GenericSymbol; - this.className = ctx.className()?.text; - }; - - enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { - let subroutineType: SubroutineType; - if (ctx.subroutineType().CONSTRUCTOR() != undefined) { - subroutineType = SubroutineType.Constructor; - } else if (ctx.subroutineType().METHOD() != undefined) { - subroutineType = SubroutineType.Method; - } else if (ctx.subroutineType().FUNCTION() != undefined) { - subroutineType = SubroutineType.Function; - } else { - throw new Error("Invalid subroutine type") - } - const subroutineWithoutTypeCtx = ctx.subroutineDecWithoutType() - const nameCtx = subroutineWithoutTypeCtx.subroutineName() - const subroutineName = nameCtx.text - const id = this.className + "." + subroutineName - if (this.globalSymbolTable[id] != undefined) { - this.errors.push(new DuplicatedSubroutineError(nameCtx.start.line, nameCtx.start.startIndex, subroutineName)); - this.stopProcessingSubroutines = true; - } else { - this.subroutineId = id; - const paramsCount = subroutineWithoutTypeCtx.parameterList().parameter().length - this.subRoutineInfo = { - type: subroutineType, - paramsCount: paramsCount, - } - this.subroutineVarsCount = 0; - this.stopProcessingSubroutines = false; - } - } - enterVarNameInDeclaration(ctx: VarNameInDeclarationContext) { - if (this.stopProcessingSubroutines) return; - this.subroutineVarsCount++; - }; - exitSubroutineBody(ctx: SubroutineBodyContext) { - if (this.stopProcessingSubroutines) return; - this.subRoutineInfo.localVarsCount = this.subroutineVarsCount; - this.globalSymbolTable[this.subroutineId] = { subroutineInfo: this.subRoutineInfo } - }; - - resetErrors() { - this.errors = []; - } -} - diff --git a/compiler/src/listener/error.listener.ts b/compiler/src/listener/error.listener.ts deleted file mode 100644 index e5a4f4e8..00000000 --- a/compiler/src/listener/error.listener.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ANTLRErrorListener, RecognitionException, Recognizer } from 'antlr4ts'; -import { JackCompilerError, LexerOrParserError } from '../error'; -export class ErrorListener implements ANTLRErrorListener { - static instance: ErrorListener; - public filepath: string = ""; - public errors: JackCompilerError[] = []; - - /** - * Provides a default instance of {@link ConsoleErrorListener}. - */ - syntaxError(recognizer: Recognizer, offendingSymbol: T | undefined, line: number, charPositionInLine: number, msg: string, e: RecognitionException | undefined) { - this.errors.push(new LexerOrParserError(this.filepath, line, charPositionInLine, msg)); - console.error(`${this.filepath}:${line}:${charPositionInLine} \n${msg}`); - }; -} \ No newline at end of file diff --git a/compiler/src/listener/validator.listener.ts b/compiler/src/listener/validator.listener.ts deleted file mode 100644 index 90e30155..00000000 --- a/compiler/src/listener/validator.listener.ts +++ /dev/null @@ -1,353 +0,0 @@ -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { builtInTypes, intRange } from "../builtins"; -import { ConstructorMushReturnThis, DuplicatedVariableException, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunction, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error"; -import { ClassDeclarationContext, ClassNameContext, ClassVarDecContext, ConstantContext, ElseStatementContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, VarTypeContext, WhileStatementContext } from "../generated/JackParser"; -import { JackParserListener } from "../generated/JackParserListener"; -import { GenericSymbol, LocalSymbolTable, ScopeType, SubroutineType } from "../symbol"; - -/** - * Validates Jack file - */ -export class ValidatorListener implements JackParserListener { - localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); - subroutineShouldReturnVoidType: boolean = false; - controlFlowGraphNode: BinaryTreeNode = new BinaryTreeNode(); - subroutineName: string = "" - className = "" - inConstructor: boolean = false - inFunction: boolean = false - stopProcessingErrorsInThisScope = false; - constructor(private globalSymbolTable: Record, public errors: JackCompilerError[] = []) { } - - enterClassDeclaration(ctx: ClassDeclarationContext) { - const newName = ctx.className()?.text - if (this.className != "") { - throw new Error("Cannot change class name") - } - this.className = newName; - }; - - enterClassVarDec(ctx: ClassVarDecContext) { - let scope: ScopeType; - if (ctx.STATIC() != undefined) { - scope = ScopeType.Static; - } else if (ctx.FIELD() != undefined) { - scope = ScopeType.This; - } else { - throw new Error("Unknown field modifier ") - } - const type = ctx.fieldList().varType().text - ctx.fieldList().fieldName().forEach(field => { - this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, scope, field.text, type); - }); - }; - enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { - if (ctx.subroutineType().CONSTRUCTOR() != undefined) { - this.inConstructor = true; - if (ctx.subroutineDecWithoutType().subroutineReturnType().text !== this.className) { - this.#addError(new IncorrectConstructorReturnType(ctx.start.line, ctx.start.startIndex)); - } - } else if (ctx.subroutineType().FUNCTION() != undefined) { - this.inFunction = true; - } - } - enterSubroutineDecWithoutType(ctx: SubroutineDecWithoutTypeContext) { - const returnType = ctx.subroutineReturnType() - this.subroutineShouldReturnVoidType = returnType.VOID() != undefined - this.controlFlowGraphNode = new BinaryTreeNode(undefined); - this.subroutineName = ctx.subroutineName().text - }; - - enterParameter(ctx: ParameterContext) { - this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ScopeType.Argument, ctx.parameterName().text, ctx.varType().text); - }; - //Var - enterVarType(ctx: VarTypeContext) { - if (ctx.IDENTIFIER() != undefined) { - const type = ctx.IDENTIFIER()!.text - if (this.globalSymbolTable[type] === undefined) { - this.#addError(new UnknownClassError(ctx.start.line, ctx.start.startIndex, type)); - } - } - }; - - enterVarDeclaration(ctx: VarDeclarationContext) { - const type = ctx.varType().text - ctx.varNameInDeclaration().forEach(name => { - this.#localSymbolTableAdd(ctx.start.line, ctx.start.startIndex, ScopeType.Local, name.text, type); - }) - }; - - /** - * Var name when using it - do Statement, let ... as oposed to varNameInDeclaration - */ - enterVarName(ctx: VarNameContext) { - if (this.inFunction && this.localSymbolTable.existsSymbol(ctx.text) && !this.localSymbolTable.existsSymbol(ctx.text, LocalSymbolTable.functionScopes)) { - this.#addError(new FieldCantBeReferencedInFunction(ctx.start.line, ctx.start.startIndex)); - } else if (!this.localSymbolTable.existsSymbol(ctx.text)) { - this.#addError(new UndeclaredVariableError(ctx.start.line, ctx.start.startIndex, ctx.text)); - } - }; - enterConstant(ctx: ConstantContext) { - if (ctx.THIS_LITERAL() != undefined && this.inFunction) { - this.#addError(new ThisCantBeReferencedInFunction(ctx.start.line, ctx.start.startIndex)); - } - }; - - enterStatement(ctx: StatementContext) { - if (this.controlFlowGraphNode._returns == true) { - this.#addError(new UnreachableCodeError(ctx.start.line, ctx.start.startIndex)); - this.stopProcessingErrorsInThisScope = true; - } - }; - enterRBrace(ctx: RBraceContext) { - this.stopProcessingErrorsInThisScope = false; - }; - /** - * Control flow - */ - enterWhileStatement(ctx: WhileStatementContext) { - this.controlFlowGraphNode = this.controlFlowGraphNode.left = new BinaryTreeNode(this.controlFlowGraphNode); - }; - - exitWhileStatement(ctx: WhileStatementContext) { - if (this.controlFlowGraphNode?.parent != null) { - this.controlFlowGraphNode = this.controlFlowGraphNode.parent - } - }; - enterIfStatement(ctx: IfStatementContext) { - this.controlFlowGraphNode = this.controlFlowGraphNode.left = new BinaryTreeNode(this.controlFlowGraphNode); - }; - exitIfStatement(ctx: IfStatementContext) { - if (this.controlFlowGraphNode?.parent != null) { - this.controlFlowGraphNode = this.controlFlowGraphNode.parent - } - }; - enterElseStatement(ctx: ElseStatementContext) { - this.controlFlowGraphNode = this.controlFlowGraphNode.right = new BinaryTreeNode(this.controlFlowGraphNode); - }; - exitElseStatement(ctx: ElseStatementContext) { - if (this.controlFlowGraphNode?.parent != null) { - this.controlFlowGraphNode = this.controlFlowGraphNode.parent - } - - }; - enterLetStatement(ctx: LetStatementContext) { - const varName = ctx.varName() - const constCtx = ctx.expression().constant() - //corresponding literal type check - if (varName != undefined && constCtx != undefined && - this.localSymbolTable.existsSymbol(ctx.varName()!.text) && - ctx.expression().constant()!.NULL_LITERAL() == undefined) { - const type = this.localSymbolTable.getType(ctx.varName()!.text)! - if (literalTypes.indexOf(type) != -1) { - const constantCtx = ctx.expression().constant()! - switch (type) { - case "int": - if (constantCtx.INTEGER_LITERAL() === undefined) { - this.#addError(new WrongLiteralTypeError(ctx.start.line, ctx.start.startIndex, type)); - } else { - const value = parseInt(constantCtx.INTEGER_LITERAL()!.text) - if (value > intRange.max) { - this.#addError(new IntLiteralIsOutOfRange(ctx.start.line, ctx.start.startIndex, value, intRange.min, intRange.max)) - } - } - break; - case "boolean": - if (constantCtx.BOOLEAN_LITERAL() === undefined) { - this.#addError(new WrongLiteralTypeError(ctx.start.line, ctx.start.startIndex, type)); - } - break; - case "char": - //TODO: add. Is char literal same as int literal? - break; - case "String": - if (constantCtx.STRING_LITERAL() === undefined) { - this.#addError(new WrongLiteralTypeError(ctx.start.line, ctx.start.startIndex, type.toLowerCase())); - } - break; - default: - throw new Error(`Unknown literal type ${type}`) - } - } - } - //int min value check - const unaryOp = ctx.expression().unaryOperation() - if (varName && unaryOp != undefined && unaryOp.unaryOperator().MINUS() !== undefined && - unaryOp!.expression().constant() != undefined && unaryOp!.expression().constant()?.INTEGER_LITERAL() !== undefined) { - const value = parseInt(unaryOp!.expression().constant()!.INTEGER_LITERAL()!.text) - if (-value < intRange.min) { - this.#addError(new IntLiteralIsOutOfRange(ctx.start.line, ctx.start.startIndex, value, intRange.min, intRange.max)); - } - } - }; - - enterSubroutineCall(ctx: SubroutineCallContext) { - //check if variable exists with the name before dot - const subroutineId = ctx.subroutineId() - let callType: CallType; - - let subroutineIdText: string; - if (subroutineId.text.indexOf('.') == -1) { - //local method - callType = CallType.LocalMethod - subroutineIdText = this.className + "." + subroutineId.subroutineName().text - } else { - // var method - const [varName, methodName] = subroutineId.text.split('.') - if (this.localSymbolTable.existsSymbol(varName)) { - const varType = this.localSymbolTable.getType(varName) - subroutineIdText = varType + "." + methodName - callType = CallType.VarMethod; - } else { - // class function/ctor - subroutineIdText = subroutineId.text - callType = CallType.ClassFunctionOrConstructor; - } - } - - const symbol = this.globalSymbolTable[subroutineIdText] - if (symbol == undefined) { - this.#addError(new UnknownSubroutineCallError(ctx.start.line, ctx.start.startIndex, - subroutineId.subroutineName().text, - subroutineId.className()?.text - )); - } else { - //method called as a function - if (symbol.subroutineInfo?.type == SubroutineType.Method - && callType == CallType.ClassFunctionOrConstructor) { - this.#addError(new MethodCalledAsFunctionError(ctx.start.line, ctx.start.startIndex, - subroutineId.subroutineName().text)); - } - // function called as a method - else if (symbol.subroutineInfo?.type == SubroutineType.Function - && callType == CallType.LocalMethod) { - this.#addError(new FunctionCalledAsMethodError(ctx.start.line, ctx.start.startIndex, - subroutineId.subroutineName().text)); - } else { - //check parameter count - const l = ctx.expressionList().expression().length - if (symbol.subroutineInfo!.paramsCount != l) { - this.#addError(new IncorrectParamsNumberInSubroutineCallError(ctx.start.line, ctx.start.startIndex, subroutineId.text, - symbol.subroutineInfo!.paramsCount, l)); - } - } - } - - }; - enterReturnStatement(ctx: ReturnStatementContext) { - const returnsVoid = ctx.expression() == undefined - if (returnsVoid && !this.subroutineShouldReturnVoidType) { - this.#addError(new NonVoidFunctionNoReturnError(ctx.start.line, ctx.start.startIndex)); - } - if (!returnsVoid && this.subroutineShouldReturnVoidType) { - this.#addError(new VoidSubroutineReturnsValueError(ctx.start.line, ctx.start.startIndex)); - } - this.controlFlowGraphNode._returns = true; - if (this.inConstructor) { - if (returnsVoid || ctx.expression()!.expression().length > 1 || - ctx.expression()!.constant() == undefined || ctx.expression()!.constant()!.THIS_LITERAL() == undefined) { - this.#addError(new ConstructorMushReturnThis(ctx.start.line, ctx.start.startIndex)) - } - } - }; - - exitSubroutineBody(ctx: SubroutineBodyContext) { - if (!this.controlFlowGraphNode.returns) { - this.#addError(new SubroutineNotAllPathsReturnError(ctx.start.line, ctx.start.startIndex, this.subroutineName)); - } - this.inConstructor = false; - this.inFunction = false; - this.localSymbolTable.clearSubroutineVars(); - }; - - exitClassDeclaration(ctx: ClassDeclarationContext) { - while (this.controlFlowGraphNode?.parent != undefined) { - this.controlFlowGraphNode = this.controlFlowGraphNode.parent - } - }; - - //Utils - #localSymbolTableAdd(line: number, position: number, scope: ScopeType, name: string, type: string) { - if (this.localSymbolTable.existsSymbol(name)) { - this.#addError(new DuplicatedVariableException(line, position, name)); - } else { - this.localSymbolTable.add(scope, name, type); - } - } - #addError(error: T) { - if (!this.stopProcessingErrorsInThisScope) - this.errors.push(error); - } - //to fix compiler error - visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; - -} - - -class BinaryTreeNode { - _returns?: boolean; - constructor( - public parent?: BinaryTreeNode, - public left?: BinaryTreeNode, - public right?: BinaryTreeNode) { } - - get returns(): boolean { - if (this._returns) { - return this._returns; - } else if (this.right == undefined && this.left == undefined) { - return false; - } else if (this.right != undefined && this.left != undefined) { - return this.left.returns && this.right.returns; - } else if (this.left != undefined) { - return false; - } else { - throw new Error("Something went wrong - CFG has only right subtree") - } - } - print() { - console.log("Branch returns value") - console.log(".") - console.log(this.printBT()); - } - - printBT(prefix: string = "", side: Side = Side.LEFT) { - let res: string = "" - if (this._returns) { - res += this.#pad(prefix, side) - res += " " + this._returns + "\n"; - return res; - } else { - if (this.right == undefined && this.left == undefined) { - res += this.#pad(prefix, side) - res += " " + false + "\n"; - } else { - res += this.left?.printBT((side == Side.LEFT ? "| " : " "), Side.LEFT); - if (this.right) { - res += prefix - res += this.right?.printBT((side == Side.LEFT ? "|\t" : "\t"), Side.RIGHT); - } else { - res += "\n"; - } - - } - } - return res; - } - #pad(prefix: string, side: Side): string { - return side == Side.LEFT ? "├──" : "└──"; - } -} -enum Side { - LEFT, - RIGHT -} -const literalTypes = [ - ...builtInTypes, - "String" -] -enum CallType { - VarMethod = 1, - LocalMethod = 2, - ClassFunctionOrConstructor = 3 -} \ No newline at end of file diff --git a/compiler/src/listener/vm.writer.listener.ts b/compiler/src/listener/vm.writer.listener.ts deleted file mode 100644 index 867ba12c..00000000 --- a/compiler/src/listener/vm.writer.listener.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { TerminalNode } from "antlr4ts/tree/TerminalNode"; -import { JackParserListener } from "../generated/JackParserListener"; -import { BinaryOperatorContext, ClassDeclarationContext, ConstantContext, ExpressionContext, ReturnStatementContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext } from "../generated/JackParser"; -import { GenericSymbol } from "../symbol"; - -const binaryOperationToVmCmd: Record = { - "+": "add", - "-": "sub", - "*": "call Math.multiply 2", - "/": "call Math.divide 2", - "&": "and", - "|": "or", - "<": "lt", - ">": "gt", - "=": "eq", -}; - -const unaryOperationToVmCmd: Record = { - "-": "neg", - "~": "not", -}; - -export class VMWriter implements JackParserListener { - public result: string = "" - private className: string = ""; - constructor(private globalSymbolTable: Record) { - } - enterSubroutineDeclaration(ctx: SubroutineDeclarationContext) { - const name = ctx.subroutineDecWithoutType().subroutineName().IDENTIFIER().text - const symbol = this.globalSymbolTable[this.className + "." + name] - if (symbol == undefined) { - throw new Error(`Can't find subroutine ${name} in class ${this.className} in symbol table`) - } - this.result += `function ${this.className}.${name} ${symbol.subroutineInfo!.localVarsCount}\n`; - - if (ctx.subroutineType().CONSTRUCTOR() != undefined) { - this.result += " push constant 0\n" - this.result += " call Memory.alloc 1\n" - this.result += " pop pointer 0\n" - } else if (ctx.subroutineType().METHOD() != undefined) { - this.result += " push argument 0\n"; - this.result += " pop pointer 0\n"; - } - }; - enterClassDeclaration(ctx: ClassDeclarationContext) { - if (this.className != "") { - throw new Error("Cannot change class name") - } - this.className = ctx.className()!.text; - }; - enterConstant(ctx: ConstantContext) { - if (ctx.INTEGER_LITERAL() != undefined) { - this.result += ` push constant ${ctx.INTEGER_LITERAL()!.text}\n`; - } - }; - exitExpression(ctx: ExpressionContext) { - if (ctx.binaryOperator() != undefined) { - const binaryOp = ctx.binaryOperator()!.text - if (binaryOperationToVmCmd[binaryOp] == undefined) { - throw new Error(`Unknown binary operator ${binaryOp}`) - } - this.result += "\t" + binaryOperationToVmCmd[binaryOp] + "\n"; - } else if (ctx.unaryOperation() != undefined) { - const unaryOp = ctx.unaryOperation()!.unaryOperator().text; - if (unaryOperationToVmCmd[unaryOp] == undefined) { - throw new Error(`Unknown unary operator ${unaryOp}`) - } - this.result += "\t" + unaryOperationToVmCmd[unaryOp] + "\n"; - } - }; - exitReturnStatement(ctx: ReturnStatementContext) { - if (ctx.expression()?.constant()?.THIS_LITERAL() != undefined) { - this.result += " push pointer 0\n"; - } else if (ctx.expression() == undefined) { - this.result += " push constant 0\n"; - } - this.result += " return\n"; - }; - enterSubroutineCall(ctx: SubroutineCallContext) { - this.result += " call A.b 0\n"; - this.result += " pop temp 0\n"; - }; - //to fix compiler error - visitTerminal?: (/*@NotNull*/ node: TerminalNode) => void; - -} \ No newline at end of file diff --git a/compiler/src/main.ts b/compiler/src/main.ts deleted file mode 100644 index b1176014..00000000 --- a/compiler/src/main.ts +++ /dev/null @@ -1,18 +0,0 @@ -import Compiler from "./compiler"; - -function compile() { - console.log('Compiling ...'); - const code = document.querySelector('#input')?.value ?? ""; - const res = Compiler.compile(code); - console.log(res); - document.querySelector('#output')!.value = res; -} -document.querySelector('#compile')?.addEventListener('click', () => compile()); - -// function error(line: number, message: string): string { -// return report(line, "", message); -// } - -// function report(line: number, where: string, message: string): string { -// return `[line ${line} Error ${where}:${message}`; -// } diff --git a/compiler/src/resources/JackLexer.g4 b/compiler/src/resources/JackLexer.g4 deleted file mode 100644 index 7ad3e5ca..00000000 --- a/compiler/src/resources/JackLexer.g4 +++ /dev/null @@ -1,61 +0,0 @@ -lexer grammar JackLexer; - -CLASS: 'class'; -CONSTRUCTOR: 'constructor'; -FUNCTION: 'function'; -METHOD: 'method'; -FIELD: 'field'; -STATIC: 'static'; -VAR: 'var'; -INT: 'int'; -CHAR: 'char'; -BOOLEAN: 'boolean'; -VOID: 'void'; - -LET: 'let'; -DO: 'do'; -IF: 'if'; -ELSE: 'else'; -WHILE: 'while'; -RETURN: 'return'; - - -LBRACE: '{'; -RBRACE: '}'; -LPAREN: '('; -RPAREN: ')'; -LBRACKET: '['; -RBRACKET: ']'; -DOT: '.'; -COMMA: ','; -SEMICOLON: ';'; - -EQUALS: '='; -PLUS: '+'; -MINUS: '-'; -MUL: '*'; -DIV: '/'; -AND: '&'; -OR: '|'; -TILDE: '~'; -LESS_THAN: '<'; -GREATER_THAN: '>'; - -WS: [ \t\r\n]+ -> skip; -COMMENT: '/*' .*? '*/' -> skip; -LINE_COMMENT: '//' ~[\r\n]* -> skip; - -INTEGER_LITERAL: [0-9]+; -BOOLEAN_LITERAL: 'true' | 'false'; -NULL_LITERAL: 'null'; -THIS_LITERAL: 'this'; - -IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; - -STRING_LITERAL - : UnterminatedStringLiteral '"' - ; -UnterminatedStringLiteral - : '"' ~["\\\r\n]* - ; - diff --git a/compiler/src/resources/JackParser.g4 b/compiler/src/resources/JackParser.g4 deleted file mode 100644 index c3d3bcd1..00000000 --- a/compiler/src/resources/JackParser.g4 +++ /dev/null @@ -1,90 +0,0 @@ -parser grammar JackParser; - -options { - tokenVocab = JackLexer; -} - -program: classDeclaration EOF; - -classDeclaration: - CLASS className LBRACE classVarDec* subroutineDeclaration* rBrace; -className: IDENTIFIER; -classVarDec: (STATIC | FIELD) fieldList SEMICOLON; -fieldList: varType fieldName ( COMMA fieldName)*; -fieldName: IDENTIFIER; -subroutineDeclaration: subroutineType subroutineDecWithoutType; -subroutineType: CONSTRUCTOR | METHOD | FUNCTION; -subroutineDecWithoutType: - subroutineReturnType subroutineName LPAREN parameterList RPAREN subroutineBody; -subroutineName: IDENTIFIER; -subroutineReturnType: varType | VOID; - -varType: INT | CHAR | BOOLEAN | IDENTIFIER; - -parameterList: (parameter (COMMA parameter)*)?; -parameter: varType parameterName; -parameterName: IDENTIFIER; -subroutineBody: LBRACE varDeclaration* statements rBrace; -rBrace: RBRACE; -varDeclaration: - VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; -varNameInDeclaration: IDENTIFIER; -varName: IDENTIFIER; -statements: statement*; -statement: - letStatement - | ifElseStatement - | whileStatement - | doStatement - | returnStatement; - -letStatement: - LET (varName | arrayAccess) EQUALS expression SEMICOLON; //TODO: check if we need right assoc for this - -ifElseStatement: ifStatement elseStatement?; -ifStatement: - IF LPAREN expression RPAREN LBRACE statements rBrace; -elseStatement: ELSE LBRACE statements rBrace; - -whileStatement: - WHILE LPAREN expression RPAREN LBRACE statements rBrace; - -doStatement: DO subroutineCall SEMICOLON; - -subroutineCall: subroutineId LPAREN expressionList RPAREN; -subroutineId: ((className | THIS_LITERAL) DOT)? subroutineName; -returnStatement: RETURN expression? SEMICOLON; - -expressionList: (expression (COMMA expression)*)?; - -expression: - binaryOperation = expression binaryOperator expression - | constant - | varName - | subroutineCall - | arrayAccess - | unaryOp - | groupedExpression; - -groupedExpression: LPAREN expression RPAREN; -unaryOp: unaryOperator expression; -arrayAccess: varName LBRACKET expression RBRACKET; - -constant: - INTEGER_LITERAL - | STRING_LITERAL - | BOOLEAN_LITERAL - | NULL_LITERAL - | THIS_LITERAL; - -unaryOperator: TILDE | MINUS; -binaryOperator: - PLUS - | MINUS - | MUL - | DIV - | AND - | OR - | LESS_THAN - | GREATER_THAN - | EQUALS; \ No newline at end of file diff --git a/compiler/src/symbol.ts b/compiler/src/symbol.ts deleted file mode 100644 index c8b7a597..00000000 --- a/compiler/src/symbol.ts +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Generic symbol. Can be used for both class and function symbols - */ -export enum SubroutineType { - Constructor, - Function, - Method, -} -export interface SubroutineInfo { - paramsCount: number; - type: SubroutineType - localVarsCount?: number; -} -/** - * Symbol that represents class or a subroutine - */ -export interface GenericSymbol { - subroutineInfo?: SubroutineInfo; -} -export function createSubroutineSymbol(paramsCount: number, type: SubroutineType, localVarsCount?: number): GenericSymbol { - const s = { paramsCount, type } as SubroutineInfo; - if (localVarsCount != undefined) { - s.localVarsCount = localVarsCount - } - return { subroutineInfo: s } as GenericSymbol -} - -type VariableType = string -export enum ScopeType { - Static, - This, - Argument, - Local, -} -/** - * Symbol table that provides lookup for variables in different scopes in a file - */ -export class LocalSymbolTable { - private vars: Record> = { - [ScopeType.Static]: {}, - [ScopeType.This]: {}, - [ScopeType.Argument]: {}, - [ScopeType.Local]: {}, - }; - static readonly functionScopes = [ScopeType.Local, ScopeType.Argument, ScopeType.Static]; - - existsSymbol(name: string, scopesToSearch = [ScopeType.Local, ScopeType.Argument, ScopeType.This, ScopeType.Static]): boolean { - for (const scope of scopesToSearch) { - if (this.vars[scope][name] != undefined) { - return true; - } - } - return false; - } - getType(name: string, scopesToSearch = [ScopeType.Local, ScopeType.Argument, ScopeType.This, ScopeType.Static]) { - for (const scope of scopesToSearch) { - if (this.vars[scope][name] != undefined) { - return this.vars[scope][name]; - } - } - return undefined; - } - add(scope: ScopeType, varName: string, type: VariableType) { - this.vars[scope][varName] = type; - } - clearSubroutineVars() { - this.vars[ScopeType.Argument] = {}; - this.vars[ScopeType.Local] = {}; - } -} \ No newline at end of file diff --git a/compiler/src/vite-env.d.ts b/compiler/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2..00000000 --- a/compiler/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/compiler/test/binder.listener.test.ts b/compiler/test/binder.listener.test.ts deleted file mode 100644 index 600ae71e..00000000 --- a/compiler/test/binder.listener.test.ts +++ /dev/null @@ -1,111 +0,0 @@ -import fs from 'fs'; -import path from "path"; -import { DuplicatedSubroutineError } from "../src/error"; -import { BinderListener } from "../src/listener/binder.listener"; -import { createSubroutineSymbol, SubroutineType } from "../src/symbol"; -import { getTestResourcePath, listenToTheTree, parseJackFile } from "./test.helper"; - -describe('Binder', () => { - const jestConsole = console; - - beforeEach(() => { - global.console = require('console'); - }); - - afterEach(() => { - global.console = jestConsole; - }); - - test("should fail on duplicated subroutine", () => { - const filePath = getTestResourcePath("DuplicatedSubroutine.jack"); - const tree = parseJackFile(filePath) - const globalSymbolsListener = new BinderListener() - listenToTheTree(tree, globalSymbolsListener) - const symbolsErrors = globalSymbolsListener.errors - expect(globalSymbolsListener.errors.length).toBe(1) - expect(symbolsErrors[0]).toBeInstanceOf(DuplicatedSubroutineError) - }) - - test("basic", () => { - - const expected = { - //built in classes - "Array": {}, - "Keyboard": {}, - "Math": {}, - "Memory": {}, - "Output": {}, - "Screen": {}, - "String": {}, - "Sys": {}, - 'Array.dispose': createSubroutineSymbol(0, SubroutineType.Function), - 'Array.new': createSubroutineSymbol(1, SubroutineType.Function), - 'Keyboard.init': createSubroutineSymbol(0, SubroutineType.Function), - 'Keyboard.keyPressed': createSubroutineSymbol(0, SubroutineType.Function), - 'Keyboard.readChar': createSubroutineSymbol(0, SubroutineType.Function), - 'Keyboard.readInt': createSubroutineSymbol(1, SubroutineType.Function), - 'Keyboard.readLine': createSubroutineSymbol(1, SubroutineType.Function), - 'Math.abs': createSubroutineSymbol(1, SubroutineType.Function), - 'Math.divide': createSubroutineSymbol(2, SubroutineType.Function), - 'Math.max': createSubroutineSymbol(2, SubroutineType.Function), - 'Math.min': createSubroutineSymbol(2, SubroutineType.Function), - 'Math.multiply': createSubroutineSymbol(2, SubroutineType.Function), - 'Math.sqrt': createSubroutineSymbol(1, SubroutineType.Function), - 'Memory.alloc': createSubroutineSymbol(1, SubroutineType.Function), - 'Memory.deAlloc': createSubroutineSymbol(1, SubroutineType.Function), - 'Memory.peek': createSubroutineSymbol(1, SubroutineType.Function), - 'Memory.poke': createSubroutineSymbol(2, SubroutineType.Function), - 'Output.backSpace': createSubroutineSymbol(0, SubroutineType.Function), - 'Output.moveCursor': createSubroutineSymbol(2, SubroutineType.Function), - 'Output.printChar': createSubroutineSymbol(1, SubroutineType.Function), - 'Output.printInt': createSubroutineSymbol(1, SubroutineType.Function), - 'Output.println': createSubroutineSymbol(0, SubroutineType.Function), - 'Output.printString': createSubroutineSymbol(1, SubroutineType.Function), - 'Screen.clearScreen': createSubroutineSymbol(0, SubroutineType.Function), - 'Screen.drawCircle': createSubroutineSymbol(3, SubroutineType.Function), - 'Screen.drawLine': createSubroutineSymbol(4, SubroutineType.Function), - 'Screen.drawPixel': createSubroutineSymbol(2, SubroutineType.Function), - 'Screen.drawRectangle': createSubroutineSymbol(4, SubroutineType.Function), - 'Screen.setColor': createSubroutineSymbol(1, SubroutineType.Function), - 'String.appendChar': createSubroutineSymbol(1, SubroutineType.Function), - 'String.backSpace': createSubroutineSymbol(0, SubroutineType.Function), - 'String.charAt': createSubroutineSymbol(2, SubroutineType.Function), - 'String.dispose': createSubroutineSymbol(0, SubroutineType.Function), - 'String.doubleQuote': createSubroutineSymbol(0, SubroutineType.Function), - 'String.eraseLastChar': createSubroutineSymbol(0, SubroutineType.Function), - 'String.intValue': createSubroutineSymbol(0, SubroutineType.Function), - 'String.length': createSubroutineSymbol(0, SubroutineType.Function), - 'String.new': createSubroutineSymbol(1, SubroutineType.Function), - 'String.newLine': createSubroutineSymbol(0, SubroutineType.Function), - 'String.setCharAt': createSubroutineSymbol(1, SubroutineType.Function), - 'String.setInt': createSubroutineSymbol(1, SubroutineType.Function), - 'Sys.error': createSubroutineSymbol(1, SubroutineType.Function), - 'Sys.halt': createSubroutineSymbol(0, SubroutineType.Function), - 'Sys.wait': createSubroutineSymbol(1, SubroutineType.Function), - //test files symbols - 'Fraction': {}, - 'Fraction.new': createSubroutineSymbol(2, SubroutineType.Constructor, 0), - 'Fraction.reduce': createSubroutineSymbol(0, SubroutineType.Method, 1), - 'Fraction.getNumerator': createSubroutineSymbol(0, SubroutineType.Method, 0), - 'Fraction.getDenominator': createSubroutineSymbol(0, SubroutineType.Method, 0), - 'Fraction.plus': createSubroutineSymbol(1, SubroutineType.Method, 1), - 'Fraction.dispose': createSubroutineSymbol(0, SubroutineType.Method, 0), - 'Fraction.print': createSubroutineSymbol(0, SubroutineType.Method, 0), - 'Fraction.gcd': createSubroutineSymbol(2, SubroutineType.Function, 1), - 'Main': {}, - 'Main.main': createSubroutineSymbol(0, SubroutineType.Function, 3), - } - let globalSymbolsListener = new BinderListener() - - const testFolder = getTestResourcePath("Fraction"); - const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); - for (const filePath of files) { - const tree = parseJackFile(filePath) - globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); - // console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) - } - expect(globalSymbolsListener.globalSymbolTable).toEqual(expected) - }) -}) - - diff --git a/compiler/test/compiler.test.ts b/compiler/test/compiler.test.ts deleted file mode 100644 index 3429783b..00000000 --- a/compiler/test/compiler.test.ts +++ /dev/null @@ -1,617 +0,0 @@ -import Compiler from "../src/compiler"; - -describe("Compiler", () => { - test('empty class', () => { - const input = `class A{}` - const expected = ``; - }) - - test('static field', () => { - const input = `class A{ - static int a; - function void init(){ - let a=1; - return; - } - }` - const expected = ` - - `; - }) - test('field', () => { - const input = ` - class A{ - field int a; - method void init(){ - let a=1; - return; - } - }` - const expected = ` - - `; - }) - - test('empty constructor', () => { - const input = `class A{ - constructor A new(){ - return this; - } - }` - const expected = ` - - `; - }) - test('empty function', () => { - const input = ` - class A{ - function void init(){ - return; - } - } - ` - const expected = ` - - `; - }) - test('empty method', () => { - const input = ` - class A{ - method void init(){ - return; - } - }` - const expected = ` - - `; - }) - - test('constructor with parameters', () => { - const input = `` - const expected = ` - - `; - }) - test('method with parameters', () => { - const input = ` - class A{ - method void init(int a, boolean b){ - return; - } - } - ` - const expected = ` - - `; - }) - test('function with parameters', () => { - const input = ` - class A{ - function void init(int a, boolean b){ - return; - } - } - ` - const expected = ` - - `; - }) - - test('int var declaration', () => { - const input = ` - class A{ - function void a(){ - var boolean b; - return; - } - } - ` - const expected = ` - - `; - }) - test('boolean var declaration', () => { - const input = ` - ` - const expected = ` - - `; - }) - test('char var declaration', () => { - const input = ` - ` - const expected = ` - - `; - }) - test('string var declaration', () => { - const input = ` - ` - const expected = ` - - `; - }) - test('class var declaration', () => { - const input = ` - ` - const expected = ` - - `; - }) - //Assign - test('boolean literal assign', () => { - const input = ` - class A{ - function void a(){ - var boolean b; - let b = true; - return; - } - } - ` - const expected = ` - - `; - }) - test('char literal assign', () => { - const input = ` - class A{ - function void a(){ - var char b; - let b = 1; - return; - } - }` - const expected = ` - - `; - }) - test('null literal assign', () => { - const input = ` - class A{ - function void a(){ - var A b; - let a = null; - return; - } - } - ` - const expected = ` - - `; - }) - test('this literal assign', () => { - const input = ` - class A{ - method void a(){ - var A b; - let b = this; - return; - } - } - ` - const expected = ` - - `; - }) - test('int literal assign', () => { - const input = ` - class A{ - function void a(){ - var int b; - let b = 1; - return; - } - } - ` - const expected = ` - - `; - }) - test('assignment for binary operation', () => { - const input = ` - class A{ - function void a(){ - var int b; - let b = 2*3; - return; - } - } - ` - const expected = ` - function A.a 1 - push constant 2 - push constant 3 - call Math.multiply 2 - pop local 0 - push constant 0 - return - `; - testCompiler(input,expected); - }) - test('assignment for varname', () => { - const input = ` - class A{ - function void a(){ - var boolean b,c; - let c=true; - let b=c; - return; - } - } - ` - const expected = ` - function A.a 2 - push constant 1 - neg - pop local 1 - push local 1 - pop local 0 - push constant 0 - return - `; - }) - test('assignment for subroutine call', () => { - const input = ` - class A{ - function int a(){ - return 1; - } - function void b(){ - var boolean b; - let b = A.a(); - return; - } - } - ` - const expected = ` - function A.a 0 - push constant 1 - return - function A.b 1 - call A.a 0 - pop local 0 - push constant 0 - return - `; - }) - test('assignment for array access', () => { - const input = ` - class A{ - function void a(){ - var Array arr; - let arr = Array.new(10); - let arr[0] = 1; - let arr[1] = arr[0]; - return; - } - } - ` - const expected = ` - function A.a 1 - push constant 10 - call Array.new 1 - pop local 0 - push constant 0 - push local 0 - add - push constant 1 - pop temp 0 - pop pointer 1 - push temp 0 - pop that 0 - push constant 1 - push local 0 - add - push constant 0 - push local 0 - add - pop pointer 1 - push that 0 - pop temp 0 - pop pointer 1 - push temp 0 - pop that 0 - push constant 0 - return - `; - }) - test('assignment to -1', () => { - const input = ` - class A{ - function void a(){ - var int b; - let b = -1; - return; - } - }` - const expected = ` - function A.a 1 - push constant 1 - neg - pop local 0 - push constant 0 - return - `; - testCompiler(input,expected); - }) - test('assignment to ~1', () => { - const input = ` - class A{ - function void a(){ - var int b; - let b = ~1; - return; - } - } - ` - const expected = ` - function A.a 1 - push constant 1 - not - pop local 0 - push constant 0 - return - `; - testCompiler(input,expected); - }) - test('assignment for grouped expr', () => { - const input = ` - class A{ - function void a(){ - var int b; - let b = 2*(3+5); - return; - } - }` - const expected = ` - function A.a 1 - push constant 2 - push constant 3 - push constant 5 - add - call Math.multiply 2 - pop local 0 - push constant 0 - return - `; - }) - - test('if statement', () => { - const input = ` - class A{ - function void a(){ - var int b; - let b = true; - if(b){ - let b = false; - } - return; - } - }` - const expected = ` - function A.a 1 - push constant 1 - neg - pop local 0 - push local 0 - not - if-goto A_1 - push constant 0 - pop local 0 - goto A_0 - label A_1 - label A_0 - push constant 0 - return - `; - }) - test('if else statement', () => { - const input = ` - class A{ - function void a(){ - var boolean b; - var int a; - let b = true; - if(b){ - let a = 1; - }else{ - let a = 2; - } - return; - } - }` - const expected = ` - function A.a 2 - push constant 1 - neg - pop local 0 - push local 0 - not - if-goto A_1 - push constant 1 - pop local 1 - goto A_0 - label A_1 - push constant 2 - pop local 1 - label A_0 - push constant 0 - return - `; - }) - test('while constant', () => { - const input = ` - class A{ - function void a(){ - var int i; - let i = 1; - while(i<10){ - let i=i+1; - } - return; - } - }` - const expected = ` - function A.a 1 - push constant 1 - pop local 0 - label A_0 - push local 0 - push constant 10 - lt - not - if-goto A_1 - push local 0 - push constant 1 - add - pop local 0 - goto A_0 - label A_1 - push constant 0 - return - `; - }) - - test('function call', () => { - const input = ` - class A{ - function void b(){ - return; - } - function void a(){ - do A.b(); - return; - } - }` - const expected = ` - function A.b 0 - push constant 0 - return - function A.a 0 - call A.b 0 - pop temp 0 - push constant 0 - return - `; - testCompiler(input,expected); - }) - test('method call', () => { - const input = ` - class A{ - method void b(){ - return; - } - method void a(){ - do b(); - return; - } - }` - const expected = ` - function A.b 0 - push argument 0 - pop pointer 0 - push constant 0 - return - function A.a 0 - push argument 0 - pop pointer 0 - push pointer 0 - call A.b 1 - pop temp 0 - push constant 0 - return - `; - //TODO: add - // testCompiler(input,expected); - }) - test('constructor', () => { - const input = ` - class A{ - constructor A new(){ - return this; - } - }` - const expected = ` - function A.new 0 - push constant 0 - call Memory.alloc 1 - pop pointer 0 - push pointer 0 - return - `; - testCompiler(input,expected); - }) - - test('return literal', () => { - const input = ` - class A{ - method int a(){ - return 1; - } - }` - const expected = ` - function A.a 0 - push argument 0 - pop pointer 0 - push constant 1 - return - `; - testCompiler(input,expected); - }) - test('method return void', () => { - const input = ` - class A{ - method void a(){ - return; - } - }` - const expected = ` - function A.a 0 - push argument 0 - pop pointer 0 - push constant 0 - return - `; - testCompiler(input,expected); - }) - - test('return simple expression', () => { - const input = ` - class A{ - function int a(){ - return 1+2*3; - } - }` - const expected = ` - function A.a 0 - push constant 1 - push constant 2 - add - push constant 3 - call Math.multiply 2 - return - `; - console.log(expected) - testCompiler(input,expected); - }) -}) - -declare global { - interface String { - trimMultiline(): string; - } -} -String.prototype.trimMultiline = function (): string { - return this.split("\n").map(line => line.trim()) - .filter(str => str.replace(/[\s\t]/g, '').length != 0) - .join("\n") -} -function testCompiler(input: string, expected: string): void { - const res = Compiler.compile(input) - if (Array.isArray(res)) { - throw new Error(`Unexpected compilation errors: ${res.join("\n")}`); - } else { - expect(res.trimMultiline()).toEqual(expected.trimMultiline()); - } -} \ No newline at end of file diff --git a/compiler/test/local.symbol.table.test.ts b/compiler/test/local.symbol.table.test.ts deleted file mode 100644 index 19919797..00000000 --- a/compiler/test/local.symbol.table.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { LocalSymbolTable, ScopeType } from "../src/symbol"; - -describe('LocalSymbolTable', () => { - const jestConsole = console; - - beforeEach(() => { - global.console = require('console'); - }); - - afterEach(() => { - global.console = jestConsole; - }); - - - - test('add', () => { - const localSymbolTable = new LocalSymbolTable(); - const variableNames = ['testVariable1', 'testVariable2', 'testVariable3']; - - variableNames.forEach(variableName => { - localSymbolTable.add(ScopeType.Local, variableName, "int") - expect(localSymbolTable.existsSymbol(variableName)).toBe(true); - expect(localSymbolTable.existsSymbol(variableName + "_")).toBe(false); - - }); - }) - -}); \ No newline at end of file diff --git a/compiler/test/parser.test.ts b/compiler/test/parser.test.ts deleted file mode 100644 index 88daf8b5..00000000 --- a/compiler/test/parser.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -import fs from 'fs'; -import { BinderListener } from "../src/listener/binder.listener"; - -import path from "path"; -import { ErrorListener } from "../src/listener/error.listener"; -import { listenToTheTree, parseJackFile, parseJackText, testResourcesDirs } from "./test.helper"; -import { JackParserListener } from '../src/generated/JackParserListener'; - -describe('Parser', () => { - const jestConsole = console; - beforeEach(() => { - global.console = require('console'); - }); - - afterEach(() => { - global.console = jestConsole; - }); - - test.each(testResourcesDirs)('%s', (dir: string) => { - testJackDir(path.join(__dirname, "resources", dir)); - }); - test('expected EOF', () => { - try { - parseJackText(` - class A{ - } - var a; - `) - } catch (e) { - if (e instanceof Error) { - expect(e.message).toContain("expecting ") - return; - } else { - fail("Expected Error"); - } - } - fail('Expected Error'); - }) - -}); - -function testJackDir(testFolder: string): void { - const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); - for (const filePath of files) { - const errorListener = new ErrorListener() - errorListener.filepath = filePath; - const tree = parseJackFile(filePath) - const globalSymbolsListener = listenToTheTree(tree, new BinderListener()); - const symbolsErrors = globalSymbolsListener.errors.join("\n") - try { - expect(globalSymbolsListener.errors.length).toBe(0) - } catch (e) { - throw new Error(symbolsErrors); - } - globalSymbolsListener.resetErrors(); - } -} diff --git a/compiler/test/resources/Average/Main.jack b/compiler/test/resources/Average/Main.jack deleted file mode 100644 index d53093a2..00000000 --- a/compiler/test/resources/Average/Main.jack +++ /dev/null @@ -1,27 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Average/Main.jack - -// Inputs some numbers and computes their average -class Main { - function void main() { - var Array a; - var int length; - var int i, sum; - - let length = Keyboard.readInt("How many numbers? "); - let a = Array.new(length); // constructs the array - - let i = 0; - while (i < length) { - let a[i] = Keyboard.readInt("Enter a number: "); - let sum = sum + a[i]; - let i = i + 1; - } - - do Output.printString("The average is "); - do Output.printInt(sum / length); - return; - } -} diff --git a/compiler/test/resources/ComplexArrays/Main.jack b/compiler/test/resources/ComplexArrays/Main.jack deleted file mode 100644 index b4d7dca2..00000000 --- a/compiler/test/resources/ComplexArrays/Main.jack +++ /dev/null @@ -1,69 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/ComplexArrays/Main.jack -/** - * Performs several complex array processing tests. - * For each test, the expected result is printed, along with the - * actual result. In each test, the two results should be equal. - */ -class Main { - - function void main() { - var Array a, b, c; - - let a = Array.new(10); - let b = Array.new(5); - let c = Array.new(1); - - let a[3] = 2; - let a[4] = 8; - let a[5] = 4; - let b[a[3]] = a[3] + 3; // b[2] = 5 - let a[b[a[3]]] = a[a[5]] * b[((7 - a[3]) - Main.double(2)) + 1]; // a[5] = 8 * 5 = 40 - let c[0] = null; - let c = c[0]; - - do Output.printString("Test 1: expected result: 5; actual result: "); - do Output.printInt(b[2]); - do Output.println(); - do Output.printString("Test 2: expected result: 40; actual result: "); - do Output.printInt(a[5]); - do Output.println(); - do Output.printString("Test 3: expected result: 0; actual result: "); - do Output.printInt(c); - do Output.println(); - - let c = null; - - if (c = null) { - do Main.fill(a, 10); - let c = a[3]; - let c[1] = 33; - let c = a[7]; - let c[1] = 77; - let b = a[3]; - let b[1] = b[1] + c[1]; // b[1] = 33 + 77 = 110; - } - - do Output.printString("Test 4: expected result: 77; actual result: "); - do Output.printInt(c[1]); - do Output.println(); - do Output.printString("Test 5: expected result: 110; actual result: "); - do Output.printInt(b[1]); - do Output.println(); - return; - } - - function int double(int a) { - return a * 2; - } - - function void fill(Array a, int size) { - while (size > 0) { - let size = size - 1; - let a[size] = Array.new(3); - } - return; - } -} diff --git a/compiler/test/resources/ConvertToBin/Main.jack b/compiler/test/resources/ConvertToBin/Main.jack deleted file mode 100644 index 12ce3ce6..00000000 --- a/compiler/test/resources/ConvertToBin/Main.jack +++ /dev/null @@ -1,79 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/ConvertToBin/Main.jack -/** - * Unpacks a 16-bit number into its binary representation: - * Takes the 16-bit number stored in RAM[8000] and stores its individual - * bits in RAM[8001]..RAM[8016] (each location will contain 0 or 1). - * Before the conversion, RAM[8001]..RAM[8016] are initialized to -1. - * - * The program should be tested as follows: - * 1) Load the compiled program into the supplied VM emulator - * 2) Put some value in RAM[8000] - * 3) Switch to "no animation" - * 4) Run the program (give it enough time to run) - * 5) Stop the program - * 6) Check that RAM[8001]..RAM[8016] contains the correct binary result, and - * that none of these memory locations contains -1. - */ -class Main { - /** Initializes RAM[8001]..RAM[8016] to -1, - * and converts the value in RAM[8000] to binary. */ - function void main() { - var int value; - do Main.fillMemory(8001, 16, -1); // sets RAM[8001]..RAM[8016] to -1 - let value = Memory.peek(8000); // reads a value from RAM[8000] - do Main.convert(value); // performs the conversion - return; - } - - /** Converts the given decimal value to binary, and puts - * the resulting bits in RAM[8001]..RAM[8016]. */ - function void convert(int value) { - var int mask, position; - var boolean loop; - - let loop = true; - while (loop) { - let position = position + 1; - let mask = Main.nextMask(mask); - - if (~(position > 16)) { - - if (~((value & mask) = 0)) { - do Memory.poke(8000 + position, 1); - } - else { - do Memory.poke(8000 + position, 0); - } - } - else { - let loop = false; - } - } - return; - } - - /** Returns the next mask (the mask that should follow the given mask). */ - function int nextMask(int mask) { - if (mask = 0) { - return 1; - } - else { - return mask * 2; - } - } - - /** Fills 'length' consecutive memory locations with 'value', - * starting at 'startAddress'. */ - function void fillMemory(int startAddress, int length, int value) { - while (length > 0) { - do Memory.poke(startAddress, value); - let length = length - 1; - let startAddress = startAddress + 1; - } - return; - } - -} diff --git a/compiler/test/resources/DuplicatedSubroutine.jack b/compiler/test/resources/DuplicatedSubroutine.jack deleted file mode 100644 index b56aa83a..00000000 --- a/compiler/test/resources/DuplicatedSubroutine.jack +++ /dev/null @@ -1,8 +0,0 @@ -class DuplicatedSubroutine { - function void f(){ - return; - } - function int f(){ - return 1; - } -} \ No newline at end of file diff --git a/compiler/test/resources/Fraction/Fraction.jack b/compiler/test/resources/Fraction/Fraction.jack deleted file mode 100644 index 939df83f..00000000 --- a/compiler/test/resources/Fraction/Fraction.jack +++ /dev/null @@ -1,65 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Fraction/Fraction.jack - -/** Represents the Fraction type and related operations. */ -class Fraction { - field int numerator, denominator; // field = property = member variable. - - /** Constructs a (reduced) fraction from the given numerator and denominator. */ - constructor Fraction new(int x, int y) { - let numerator = x; - let denominator = y; - do reduce(); // reduces the fraction - return this; // a constructor is expected to return a reference to the new object - } - - // Reduces this fraction. - method void reduce() { - var int g; - let g = Fraction.gcd(numerator, denominator); - if (g > 1) { - let numerator = numerator / g; - let denominator = denominator / g; - } - return; - } - - /** Accessors. */ - method int getNumerator() { return numerator; } - method int getDenominator() { return denominator; } - - /** Returns the sum of this fraction and the other one. */ - method Fraction plus(Fraction other) { - var int sum; - let sum = (numerator * other.getDenominator()) + (other.getNumerator() * denominator); - return Fraction.new(sum, denominator * other.getDenominator()); - } - - // More fraction-related methods (minus, times, div, invert, etc.) can be added here. - - /** Disposes this fraction. */ - method void dispose() { - do Memory.deAlloc(this); // uses an OS routine to recycle the memory held by the object - return; - } - - /** Prints this fraction in the format x/y. */ - method void print() { - do Output.printInt(numerator); - do Output.printString("/"); - do Output.printInt(denominator); - return; - } - - // Computes the greatest common divisor of the given integers. - function int gcd(int a, int b) { - var int r; - while (~(b = 0)) { // applies Euclid's algorithm - let r = a - (b * (a / b)); // r = remainder of the integer division a/b - let a = b; let b = r; - } - return a; - } -} diff --git a/compiler/test/resources/Fraction/Main.jack b/compiler/test/resources/Fraction/Main.jack deleted file mode 100644 index 293bc917..00000000 --- a/compiler/test/resources/Fraction/Main.jack +++ /dev/null @@ -1,16 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Fraction/Main.jack - -// Computes and prints the sum of 2/3 and 1/5. -class Main { - function void main() { - var Fraction a, b, c; - let a = Fraction.new(2,3); - let b = Fraction.new(1,5); - let c = a.plus(b); // Computes c = a + b - do c.print(); // Prints "13/15" - return; - } -} diff --git a/compiler/test/resources/HelloWorld/Main.jack b/compiler/test/resources/HelloWorld/Main.jack deleted file mode 100644 index 6cb47f47..00000000 --- a/compiler/test/resources/HelloWorld/Main.jack +++ /dev/null @@ -1,14 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/HelloWorld/Main.jack - -/** Hello World program. */ -class Main { - function void main() { - /* Prints some text using the standard library. */ - do Output.printString("Hello world!"); - do Output.println(); // New line - return; - } -} diff --git a/compiler/test/resources/List/List.jack b/compiler/test/resources/List/List.jack deleted file mode 100644 index 49bc54a8..00000000 --- a/compiler/test/resources/List/List.jack +++ /dev/null @@ -1,48 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/List/List.jack - -/** Represents a linked list of integers. */ -class List { - field int data; // an int value, - field List next; // followed by a list of int values - - /* Creates a List. */ - constructor List new(int car, List cdr) { - let data = car; // the identifiers car and cdr are used in - let next = cdr; // memory of the Lisp programming language - return this; - } - - /** Accessors. */ - method int getData() { return data; } - method int getNext() { return next; } - - /** Prints this list. */ - method void print() { - // Sets current to the first element of this list - var List current; - let current = this; - while (~(current = null)) { - do Output.printInt(current.getData()); - do Output.printChar(32); // prints a space - let current = current.getNext(); - } - return; - } - - /** Disposes this List. */ - // By recursively disposing its tail. - method void dispose() { - if (~(next = null)) { - do next.dispose(); - } - // Calls an OS routine to free the memory of this object. - do Memory.deAlloc(this); - return; - } - - // More list processing methods can come here. - -} diff --git a/compiler/test/resources/List/Main.jack b/compiler/test/resources/List/Main.jack deleted file mode 100644 index 54a39a97..00000000 --- a/compiler/test/resources/List/Main.jack +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/List/Main.jack - -/** An example of creating and using List objects. */ -class Main { - function void main() { - // Creates and uses the list (2,3,5). - var List v; - let v = List.new(5,null); - let v = List.new(2,List.new(3,v)); - do v.print(); // prints 2 3 5 - do v.dispose(); // disposes the list - return; - } -} diff --git a/compiler/test/resources/Pong/Ball.jack b/compiler/test/resources/Pong/Ball.jack deleted file mode 100644 index f65a9075..00000000 --- a/compiler/test/resources/Pong/Ball.jack +++ /dev/null @@ -1,202 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Pong/Ball.jack -/** - * A graphical ball in a Pong game. Characterized by a screen location and - * distance of last destination. Has methods for drawing, erasing and moving - * on the screen. The ball is displayed as a filled, 6-by-6 pixles rectangle. - */ -class Ball { - - field int x, y; // the ball's screen location (in pixels) - field int lengthx, lengthy; // distance of last destination (in pixels) - - field int d, straightD, diagonalD; // used for straight line movement computation - field boolean invert, positivex, positivey; // (same) - - field int leftWall, rightWall, topWall, bottomWall; // wall locations - - field int wall; // last wall that the ball was bounced off of - - /** Constructs a new ball with the given initial location and wall locations. */ - constructor Ball new(int Ax, int Ay, - int AleftWall, int ArightWall, int AtopWall, int AbottomWall) { - let x = Ax; - let y = Ay; - let leftWall = AleftWall; - let rightWall = ArightWall - 6; // -6 for ball size - let topWall = AtopWall; - let bottomWall = AbottomWall - 6; // -6 for ball size - let wall = 0; - do show(); - return this; - } - - /** Deallocates the Ball's memory. */ - method void dispose() { - do Memory.deAlloc(this); - return; - } - - /** Shows the ball. */ - method void show() { - do Screen.setColor(true); - do draw(); - return; - } - - /** Hides the ball. */ - method void hide() { - do Screen.setColor(false); - do draw(); - return; - } - - /** Draws the ball. */ - method void draw() { - do Screen.drawRectangle(x, y, x + 5, y + 5); - return; - } - - /** Returns the ball's left edge. */ - method int getLeft() { - return x; - } - - /** Returns the ball's right edge. */ - method int getRight() { - return x + 5; - } - - /** Computes and sets the ball's destination. */ - method void setDestination(int destx, int desty) { - var int dx, dy, temp; - let lengthx = destx - x; - let lengthy = desty - y; - let dx = Math.abs(lengthx); - let dy = Math.abs(lengthy); - let invert = (dx < dy); - - if (invert) { - let temp = dx; // swap dx, dy - let dx = dy; - let dy = temp; - let positivex = (y < desty); - let positivey = (x < destx); - } - else { - let positivex = (x < destx); - let positivey = (y < desty); - } - - let d = (2 * dy) - dx; - let straightD = 2 * dy; - let diagonalD = 2 * (dy - dx); - - return; - } - - /** - * Moves the ball one step towards its destination. - * If the ball has reached a wall, returns 0. - * Else, returns a value according to the wall: - * 1 (left wall), 2 (right wall), 3 (top wall), 4 (bottom wall). - */ - method int move() { - - do hide(); - - if (d < 0) { let d = d + straightD; } - else { - let d = d + diagonalD; - - if (positivey) { - if (invert) { let x = x + 4; } - else { let y = y + 4; } - } - else { - if (invert) { let x = x - 4; } - else { let y = y - 4; } - } - } - - if (positivex) { - if (invert) { let y = y + 4; } - else { let x = x + 4; } - } - else { - if (invert) { let y = y - 4; } - else { let x = x - 4; } - } - - if (~(x > leftWall)) { - let wall = 1; - let x = leftWall; - } - if (~(x < rightWall)) { - let wall = 2; - let x = rightWall; - } - if (~(y > topWall)) { - let wall = 3; - let y = topWall; - } - if (~(y < bottomWall)) { - let wall = 4; - let y = bottomWall; - } - - do show(); - - return wall; - } - - /** - * Bounces off the current wall: sets the new destination - * of the ball according to the ball's angle and the given - * bouncing direction (-1/0/1=left/center/right or up/center/down). - */ - method void bounce(int bouncingDirection) { - var int newx, newy, divLengthx, divLengthy, factor; - - // Since results are too big, divides by 10 - let divLengthx = lengthx / 10; - let divLengthy = lengthy / 10; - if (bouncingDirection = 0) { let factor = 10; } - else { - if (((~(lengthx < 0)) & (bouncingDirection = 1)) | ((lengthx < 0) & (bouncingDirection = (-1)))) { - let factor = 20; // bounce direction is in ball direction - } - else { let factor = 5; } // bounce direction is against ball direction - } - - if (wall = 1) { - let newx = 506; - let newy = (divLengthy * (-50)) / divLengthx; - let newy = y + (newy * factor); - } - else { - if (wall = 2) { - let newx = 0; - let newy = (divLengthy * 50) / divLengthx; - let newy = y + (newy * factor); - } - else { - if (wall = 3) { - let newy = 250; - let newx = (divLengthx * (-25)) / divLengthy; - let newx = x + (newx * factor); - } - else { // assumes wall = 4 - let newy = 0; - let newx = (divLengthx * 25) / divLengthy; - let newx = x + (newx * factor); - } - } - } - - do setDestination(newx, newy); - return; - } -} diff --git a/compiler/test/resources/Pong/Bat.jack b/compiler/test/resources/Pong/Bat.jack deleted file mode 100644 index b449c2c5..00000000 --- a/compiler/test/resources/Pong/Bat.jack +++ /dev/null @@ -1,103 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Pong/Bat.jack -/** - * A graphical bat in a Pong game. - * Displayed as a filled horizontal rectangle that has a screen location, - * a width and a height. - * Has methods for drawing, erasing, moving left and right, and changing - * its width (to make the hitting action more challenging). - * This class should have been called "Paddle", following the - * standard Pong terminology. Unaware of this terminology, - * we called it "bat", and the name stuck. - */ -class Bat { - - field int x, y; // the bat's screen location - field int width, height; // the bat's width and height - field int direction; // direction of the bat's movement - // (1 = left, 2 = right) - - /** Constructs a new bat with the given location and width. */ - constructor Bat new(int Ax, int Ay, int Awidth, int Aheight) { - let x = Ax; - let y = Ay; - let width = Awidth; - let height = Aheight; - let direction = 2; - do show(); - return this; - } - - /** Deallocates the object's memory. */ - method void dispose() { - do Memory.deAlloc(this); - return; - } - - /** Shows the bat. */ - method void show() { - do Screen.setColor(true); - do draw(); - return; - } - - /** Hides the bat. */ - method void hide() { - do Screen.setColor(false); - do draw(); - return; - } - - /** Draws the bat. */ - method void draw() { - do Screen.drawRectangle(x, y, x + width, y + height); - return; - } - - /** Sets the bat's direction (0=stop, 1=left, 2=right). */ - method void setDirection(int Adirection) { - let direction = Adirection; - return; - } - - /** Returns the bat's left edge. */ - method int getLeft() { - return x; - } - - /** Returns the bat's right edge. */ - method int getRight() { - return x + width; - } - - /** Sets the bat's width. */ - method void setWidth(int Awidth) { - do hide(); - let width = Awidth; - do show(); - return; - } - - /** Moves the bat one step in the bat's direction. */ - method void move() { - if (direction = 1) { - let x = x - 4; - if (x < 0) { let x = 0; } - do Screen.setColor(false); - do Screen.drawRectangle((x + width) + 1, y, (x + width) + 4, y + height); - do Screen.setColor(true); - do Screen.drawRectangle(x, y, x + 3, y + height); - } - else { - let x = x + 4; - if ((x + width) > 511) { let x = 511 - width; } - do Screen.setColor(false); - do Screen.drawRectangle(x - 4, y, x - 1, y + height); - do Screen.setColor(true); - do Screen.drawRectangle((x + width) - 3, y, x + width, y + height); - } - return; - } -} diff --git a/compiler/test/resources/Pong/Main.jack b/compiler/test/resources/Pong/Main.jack deleted file mode 100644 index 9e65ceb7..00000000 --- a/compiler/test/resources/Pong/Main.jack +++ /dev/null @@ -1,18 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Pong/Main.jack -/** - * Main class of the Pong game. - */ -class Main { - /** Initializes a Pong game and starts running it. */ - function void main() { - var PongGame game; - do PongGame.newInstance(); - let game = PongGame.getInstance(); - do game.run(); - do game.dispose(); - return; - } -} diff --git a/compiler/test/resources/Pong/PongGame.jack b/compiler/test/resources/Pong/PongGame.jack deleted file mode 100644 index 515ead4a..00000000 --- a/compiler/test/resources/Pong/PongGame.jack +++ /dev/null @@ -1,136 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Pong/PongGame.jack -/** - * Represents a Pong game. - */ -class PongGame { - - static PongGame instance; // A Pong game - field Bat bat; // bat - field Ball ball; // ball - field int wall; // current wall that the ball is bouncing off of - field boolean exit; // true when the game is over - field int score; // current score - field int lastWall; // last wall that the ball bounced off of - - // The current width of the bat - field int batWidth; - - /** Constructs a new Pong game. */ - constructor PongGame new() { - do Screen.clearScreen(); - let batWidth = 50; // initial bat size - let bat = Bat.new(230, 229, batWidth, 7); - let ball = Ball.new(253, 222, 0, 511, 0, 229); - do ball.setDestination(400,0); - do Screen.drawRectangle(0, 238, 511, 240); - do Output.moveCursor(22,0); - do Output.printString("Score: 0"); - - let exit = false; - let score = 0; - let wall = 0; - let lastWall = 0; - - return this; - } - - /** Deallocates the object's memory. */ - method void dispose() { - do bat.dispose(); - do ball.dispose(); - do Memory.deAlloc(this); - return; - } - - /** Creates an instance of a Pong game. */ - function void newInstance() { - let instance = PongGame.new(); - return; - } - - /** Returns this Pong game. */ - function PongGame getInstance() { - return instance; - } - - /** Starts the game, and handles inputs from the user that control - * the bat's movement direction. */ - method void run() { - var char key; - - while (~exit) { - // waits for a key to be pressed. - while ((key = 0) & (~exit)) { - let key = Keyboard.keyPressed(); - do bat.move(); - do moveBall(); - do Sys.wait(50); - } - - if (key = 130) { do bat.setDirection(1); } - else { - if (key = 132) { do bat.setDirection(2); } - else { - if (key = 140) { let exit = true; } - } - } - - // Waits for the key to be released. - while ((~(key = 0)) & (~exit)) { - let key = Keyboard.keyPressed(); - do bat.move(); - do moveBall(); - do Sys.wait(50); - } - } - - if (exit) { - do Output.moveCursor(10,27); - do Output.printString("Game Over"); - } - - return; - } - - /** - * Handles ball movement, including bouncing. - * If the ball bounces off a wall, finds its new direction. - * If the ball bounces off the bat, increases the score by one - * and shrinks the bat's size, to make the game more challenging. - */ - method void moveBall() { - var int bouncingDirection, batLeft, batRight, ballLeft, ballRight; - - let wall = ball.move(); - - if ((wall > 0) & (~(wall = lastWall))) { - let lastWall = wall; - let bouncingDirection = 0; - let batLeft = bat.getLeft(); - let batRight = bat.getRight(); - let ballLeft = ball.getLeft(); - let ballRight = ball.getRight(); - - if (wall = 4) { - let exit = (batLeft > ballRight) | (batRight < ballLeft); - if (~exit) { - if (ballRight < (batLeft + 10)) { let bouncingDirection = -1; } - else { - if (ballLeft > (batRight - 10)) { let bouncingDirection = 1; } - } - - let batWidth = batWidth - 2; - do bat.setWidth(batWidth); - let score = score + 1; - do Output.moveCursor(22,7); - do Output.printInt(score); - } - } - do ball.bounce(bouncingDirection); - } - return; - } -} \ No newline at end of file diff --git a/compiler/test/resources/Square/Main.jack b/compiler/test/resources/Square/Main.jack deleted file mode 100644 index bc6732e0..00000000 --- a/compiler/test/resources/Square/Main.jack +++ /dev/null @@ -1,15 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Square/Main.jack - -/** Initializes a new Square game and starts running it. */ -class Main { - function void main() { - var SquareGame game; - let game = SquareGame.new(); - do game.run(); - do game.dispose(); - return; - } -} diff --git a/compiler/test/resources/Square/Square.jack b/compiler/test/resources/Square/Square.jack deleted file mode 100644 index e4a6590d..00000000 --- a/compiler/test/resources/Square/Square.jack +++ /dev/null @@ -1,113 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/9/Square/Square.jack - -/** Implements a graphical square. - The square has top-left x and y coordinates, and a size. */ -class Square { - - field int x, y; // screen location of the top-left corner of this square - field int size; // length of this square, in pixels - - /** Constructs and draws a new square with a given location and size. */ - constructor Square new(int ax, int ay, int asize) { - let x = ax; - let y = ay; - let size = asize; - do draw(); - return this; - } - - /** Disposes this square. */ - method void dispose() { - do Memory.deAlloc(this); - return; - } - - /** Draws this square in its current (x,y) location */ - method void draw() { - // Draws the square using the color black - do Screen.setColor(true); - do Screen.drawRectangle(x, y, x + size, y + size); - return; - } - - /** Erases this square. */ - method void erase() { - // Draws the square using the color white (background color) - do Screen.setColor(false); - do Screen.drawRectangle(x, y, x + size, y + size); - return; - } - - /** Increments the square size by 2 pixels (if possible). */ - method void incSize() { - if (((y + size) < 254) & ((x + size) < 510)) { - do erase(); - let size = size + 2; - do draw(); - } - return; - } - - /** Decrements the square size by 2 pixels (if possible). */ - method void decSize() { - if (size > 2) { - do erase(); - let size = size - 2; - do draw(); - } - return; - } - - /** Moves this square up by 2 pixels (if possible). */ - method void moveUp() { - if (y > 1) { - // Erases the bottom two rows of this square in its current location - do Screen.setColor(false); - do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size); - let y = y - 2; - // Draws the top two rows of this square in its new location - do Screen.setColor(true); - do Screen.drawRectangle(x, y, x + size, y + 1); - } - return; - } - - /** Moves the square down by 2 pixels (if possible). */ - method void moveDown() { - if ((y + size) < 254) { - do Screen.setColor(false); - do Screen.drawRectangle(x, y, x + size, y + 1); - let y = y + 2; - do Screen.setColor(true); - do Screen.drawRectangle(x, (y + size) - 1, x + size, y + size); - } - return; - } - - /** Moves the square left by 2 pixels (if possible). */ - method void moveLeft() { - if (x > 1) { - do Screen.setColor(false); - do Screen.drawRectangle((x + size) - 1, y, x + size, y + size); - let x = x - 2; - do Screen.setColor(true); - do Screen.drawRectangle(x, y, x + 1, y + size); - } - return; - } - - /** Moves the square right by 2 pixels (if possible). */ - method void moveRight() { - if ((x + size) < 510) { - do Screen.setColor(false); - do Screen.drawRectangle(x, y, x + 1, y + size); - let x = x + 2; - do Screen.setColor(true); - do Screen.drawRectangle((x + size) - 1, y, x + size, y + size); - } - return; - } -} diff --git a/compiler/test/resources/Square/SquareGame.jack b/compiler/test/resources/Square/SquareGame.jack deleted file mode 100644 index fa4ce93e..00000000 --- a/compiler/test/resources/Square/SquareGame.jack +++ /dev/null @@ -1,76 +0,0 @@ -// This file is part of www.nand2tetris.org -// and the book "The Elements of Computing Systems" -// by Nisan and Schocken, MIT Press. -// File name: projects/09/Square/SquareGame.jack -/** - * Implements the Square game. - * This simple game allows the user to move a black square around - * the screen, and change the square's size during the movement. - * When the game starts, a square of 30 by 30 pixels is shown at the - * top-left corner of the screen. The user controls the square as follows. - * The 4 arrow keys are used to move the square up, down, left, and right. - * The 'z' and 'x' keys are used, respectively, to decrement and increment - * the square's size. The 'q' key is used to quit the game. - */ -class SquareGame { - field Square square; // the square of this game - field int direction; // the square's current direction: - // 0=none, 1=up, 2=down, 3=left, 4=right - - /** Constructs a new square game. */ - constructor SquareGame new() { - // The initial square is located in (0,0), has size 30, and is not moving. - let square = Square.new(0, 0, 30); - let direction = 0; - return this; - } - - /** Disposes this game. */ - method void dispose() { - do square.dispose(); - do Memory.deAlloc(this); - return; - } - - /** Moves the square in the current direction. */ - method void moveSquare() { - if (direction = 1) { do square.moveUp(); } - if (direction = 2) { do square.moveDown(); } - if (direction = 3) { do square.moveLeft(); } - if (direction = 4) { do square.moveRight(); } - do Sys.wait(5); // delays the next movement - return; - } - - /** Runs the game: handles the user's inputs and moves the square accordingly */ - method void run() { - var char key; // the key currently pressed by the user - var boolean exit; - let exit = false; - - while (~exit) { - // waits for a key to be pressed - while (key = 0) { - let key = Keyboard.keyPressed(); - do moveSquare(); - } - if (key = 81) { let exit = true; } // q key - if (key = 90) { do square.decSize(); } // z key - if (key = 88) { do square.incSize(); } // x key - if (key = 131) { let direction = 1; } // up arrow - if (key = 133) { let direction = 2; } // down arrow - if (key = 130) { let direction = 3; } // left arrow - if (key = 132) { let direction = 4; } // right arrow - - // waits for the key to be released - while (~(key = 0)) { - let key = Keyboard.keyPressed(); - do moveSquare(); - } - } // while - return; - } -} - - - diff --git a/compiler/test/test.helper.ts b/compiler/test/test.helper.ts deleted file mode 100644 index a2ebc5e4..00000000 --- a/compiler/test/test.helper.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { ANTLRErrorListener, CharStreams, CommonTokenStream, ParserRuleContext } from "antlr4ts"; -import { JackParser, ProgramContext } from "../src/generated/JackParser"; -import { JackLexer } from "../src/generated/JackLexer"; -import fs from 'fs'; -import path from "path"; -import { ParseTreeListener } from "antlr4ts/tree/ParseTreeListener"; -import { ParseTreeWalker } from "antlr4ts/tree/ParseTreeWalker"; -import { JackCompilerError } from "../src/error"; -import { ErrorListener } from "../src/listener/error.listener"; - -export function parseJackFile(filePath: string, trace = false) { - const errorListener: ErrorListener = new ErrorListener() - errorListener.filepath = filePath - const f = fs.readFileSync(filePath, 'utf8'); - return parseJackText(f, errorListener, trace); -} - -export function parseJackText(src: string, errorListener?: ErrorListener, trace: boolean = false): ProgramContext { - if (errorListener === undefined) { - errorListener = new ErrorListener(); - } - const inputStream = CharStreams.fromString(src); - const lexer = new JackLexer(inputStream); - if (errorListener) { - lexer.removeErrorListeners(); - lexer.addErrorListener(errorListener); - } - - const tokenStream = new CommonTokenStream(lexer); - expect(tokenStream.getTokens.length).toBeGreaterThan(0); - const parser = new JackParser(tokenStream); - parser.isTrace = trace; - if (errorListener != undefined) { - parser.removeErrorListeners(); - parser.addErrorListener(errorListener); - } - const tree = parser.program() - if (errorListener.errors.length > 0) { - console.error("Parser or lexer errors found"); - handleErrors(src, errorListener.errors); - } - return tree; -} - -export function getTestResourcePath(relativePath: string) { - return path.join(__dirname, "resources", relativePath); -} - -export function listenToTheTree(tree: ProgramContext, listener: T) { - ParseTreeWalker.DEFAULT.walk(listener, tree); - return listener; -} - - -export function handleErrors(src: string, errors: JackCompilerError[]) { - const msg = errors.map(e => { - return `${e.line}:${e.charPositionInLine} ${e.msg}\n${src.split("\n")[e.line]}` - }).join("\n") - console.error(msg); - throw new Error(msg) -} -export const testResourcesDirs: string[] = [ - "Average", - "ConvertToBin", - "Fraction", - "HelloWorld", - "List", - "Pong", - "Square", - "ComplexArrays" -] - diff --git a/compiler/test/validator.listener.test.ts b/compiler/test/validator.listener.test.ts deleted file mode 100644 index 4b3046ba..00000000 --- a/compiler/test/validator.listener.test.ts +++ /dev/null @@ -1,657 +0,0 @@ -import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FieldCantBeReferencedInFunction, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRange as IntLiteralOverflow, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunction, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../src/error" -import { ErrorListener } from "../src/listener/error.listener" -import { ValidatorListener } from "../src/listener/validator.listener" -import { createSubroutineSymbol, GenericSymbol, LocalSymbolTable, SubroutineType } from "../src/symbol" -import { listenToTheTree, parseJackFile, parseJackText, testResourcesDirs } from "./test.helper" -import fs from 'fs'; -import { BinderListener } from "../src/listener/binder.listener" -import path from "path" -import { ProgramContext } from "../src/generated/JackParser" -describe('ValidatorListener', () => { - const jestConsole = console; - beforeEach(() => { - - global.console = require('console'); - }); - - afterEach(() => { - global.console = jestConsole; - }); - - function genericSymbol(type?: SubroutineType, paramsCount?: number): GenericSymbol { - if (type != undefined && paramsCount != undefined) { - return createSubroutineSymbol(paramsCount, type) - } else { - return {} as GenericSymbol - } - } - - const duplicateVarClassBodies = [ - ["static", ' static int a, a;'], - ["field", ' field int a, a;'], - ["static and field", ' static int a; field boolean a;'], - ["function args", ' function void a(int a, int a){return;}'], - ["function var", ` function void a(){ - var boolean a, a; - return; - }`], - ["function var with different types", ` function void a(){ - var boolean a; - var int a; - return; - }`], - ] - test.concurrent.each(duplicateVarClassBodies)('duplicated %s', (testName, classBody) => { - testValidator(` - class Main { - ${classBody} - }`, DuplicatedVariableError) - }) - - /** - * Undeclared var - */ - test('let - undeclared variable ', () => { - testValidator(` - class Main { - function void a(){ - let b=1; - return; - } - }`, UndeclaredVariableError) - }) - - test('call function - undeclared variable ', () => { - testValidator( - `class Main { - function void b(int a){ - return; - } - function void a(){ - do Main.b(a); - return; - } - }`, UndeclaredVariableError, - { - "Main": genericSymbol(), - "Main.b": genericSymbol(SubroutineType.Function, 1), - "Main.a": genericSymbol(SubroutineType.Function, 1) - }) - }) - - test('if - undeclared variable ', () => { - testValidator( - `class Main { - function void a(){ - if(a=0){ - return; - }else { - return; - } - } - }`, UndeclaredVariableError) - }) - - /** - * Unknown class - */ - test('Unknown class for subroutine return type ', () => { - testValidator(` - class Main { - function void b(int a){ - var D d; - return; - } - }`, UnknownClassError) - }) - - test('Known type for subroutine return type ', () => { - testValidator(` - class Main { - function D b(int a){ - return D.new(); - } - }`, undefined, { "D": genericSymbol(), "D.new": genericSymbol(SubroutineType.Constructor, 0) }) - }) - test('Arg Unknown class ', () => { - testValidator(` - class Main { - function void b(D a){ - return; - } - }`, UnknownClassError) - }) - - test('Arg known type ', () => { - testValidator(` - - class Main { - function void b(D a){ - return; - } - }`, undefined, { "D": genericSymbol() }) - }) - test('var Unknown class', () => { - testValidator(` - class Main { - function void b(){ - var D d; - return; - } - }`, UnknownClassError) - }) - test('var known type', () => { - testValidator(` - class Main { - function void b(){ - var D d; - return; - } - }`, undefined, { "D": genericSymbol() }) - }) - test('field Unknown class', () => { - testValidator(` - class Main { - field T t; - }`, UnknownClassError) - }) - test('field known type', () => { - testValidator(` - class Main { - field T t; - }`, undefined, { "T": genericSymbol() }) - }) - test('static field Unknown class', () => { - testValidator(` - class Main { - static T t; - }`, UnknownClassError) - }) - test('static field known type', () => { - testValidator(` - class Main { - static T t; - }`, undefined, { "T": genericSymbol() }) - }) - - /** - * Incorrect return type - */ - - test('non void subroutine must return a value', () => { - testValidator(` - class Main { - function int a(){ - return; - } - }`, NonVoidFunctionNoReturnError) - }) - - - test('void subroutine must return not return a value', () => { - testValidator(` - class Main { - function void a(){ - return 1; - } - }`, VoidSubroutineReturnsValueError) - }) - /** - * `Subroutine ${subroutine.name.value}: not all code paths return a value` - */ - - test('if missing return', () => { - testValidator(` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - - }else{ - return; - } - } - }`, SubroutineNotAllPathsReturnError) - }) - test('else missing return ', () => { - testValidator(` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - return; - }else{ - - } - } - }`, SubroutineNotAllPathsReturnError) - }) - - test('while missing return', () => { - testValidator(` - class Main { - function int a(){ - var int a; - let a=0; - while(a<10){ - - } - } - }`, SubroutineNotAllPathsReturnError) - }) - - test(' missing return after while', () => { - testValidator(` - class Main { - function int a(){ - var int a; - let a=0; - while(a<10){ - return 0; - } - } - }`, SubroutineNotAllPathsReturnError) - }) - - test('nested if missing return', () => { - testValidator(` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - if(a=1){ - return; - }else { - - } - }else{ - return; - } - } - }`, SubroutineNotAllPathsReturnError) - }) - test('nested if missing return 2', () => { - testValidator(` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - if(a=1){ - - }else { - return; - } - }else{ - return; - } - } - }`, SubroutineNotAllPathsReturnError) - }) - - test('nested if missing return 3', () => { - testValidator(` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - if(a=1){ - return; - }else { - return; - } - }else{ - - } - } - }`, SubroutineNotAllPathsReturnError) - }) - test('should be valid', () => { - testValidator(` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - if(a=1){ - }else { - } - } - return; - } - }`) - }) - /** - * Validate function call - */ - test('calling undefined subroutine', () => { - testValidator(` - class Main { - function void b(){ - do Main.c(); - return; - } - }`, UnknownSubroutineCallError) - }) - - test('incorrect number of parameters when calling a function', () => { - testValidator(` - class Main { - function void a(int a, int b){ - return; - } - function void b(){ - do Main.a(1); - return; - } - }`, IncorrectParamsNumberInSubroutineCallError, { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 2), - "Main.b": genericSymbol(SubroutineType.Function, 2) - }) - }) - - test('call var method ', () => { - testValidator(` - class Main { - constructor Main new(){ - return this; - } - function void a(){ - var Main m; - let m = Main.new(); - do m.b(); - return; - } - method void b(){ - return; - } - }`, undefined, { - "Main": genericSymbol(), - "Main.new": genericSymbol(SubroutineType.Constructor, 0), - "Main.a": genericSymbol(SubroutineType.Function, 0), - "Main.b": genericSymbol(SubroutineType.Method, 0) - }) - }) - test('call local method ', () => { - testValidator(` - class Main { - method void a(){ - do b(); - return; - } - method void b(){ - return; - } - }`, undefined, { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Method, 0), - "Main.b": genericSymbol(SubroutineType.Method, 0) - }) - }) - - /** - * - `Method ${className}.${subroutineName} was called as a function/constructor` - */ - test('method called as a function/constructor', () => { - testValidator(` - class Main { - function void b(){ - do Main.c(); - return; - } - method void c(){ - return; - } - }`, MethodCalledAsFunctionError, - { - "Main": genericSymbol(), - "Main.b": genericSymbol(SubroutineType.Function, 0), - "Main.c": genericSymbol(SubroutineType.Method, 0) - }) - }) - test('function/ctor called as a method', () => { - testValidator(` - class Main { - function void b(){ - do c(); - return; - } - function void c(){ - return; - } - }`, FunctionCalledAsMethodError, - { - "Main": genericSymbol(), - "Main.b": genericSymbol(SubroutineType.Function, 0), - "Main.c": genericSymbol(SubroutineType.Function, 0) - }) - }) - test('incorrect return type in constructor', () => { - testValidator(` - class Main { - constructor D new(){ - return this; - } - }`, IncorrectConstructorReturnType, - { - "Main": genericSymbol(), - "D": genericSymbol(), - }) - }); - test('unreachable code', () => { - testValidator(` - class Main { - constructor Main new(){ - return this; - let a=0; - let a=0; - let a=0; - } - }`, UnreachableCodeError, - { - "Main": genericSymbol(), - "Main.new": genericSymbol(SubroutineType.Constructor, 0), - }) - }); - test("A constructor must return 'this'", () => { - testValidator(` - class Main { - constructor Main new(){ - return 1; - } - }`, ConstructorMushReturnThis, - { - "Main": genericSymbol(), - "Main.new": genericSymbol(SubroutineType.Constructor, 0), - }) - }) - test("Let statement - expected string literal ", () => { - testValidator(` - class Main { - function void a(){ - var String foo; - let foo = 1; - return; - } - }`, WrongLiteralTypeError, - { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - "String": genericSymbol(), - }) - }) - test("Let statement - expected boolean literal ", () => { - testValidator(` - class Main { - function void a(){ - var boolean foo; - let foo = 1; - return; - } - }`, WrongLiteralTypeError, - { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }) - }) - - test("Let statement - expected int literal ", () => { - testValidator(` - class Main { - function void a(){ - var int foo; - let foo = "asb"; - return; - } - }`, WrongLiteralTypeError, - { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }) - }) - test("integer constant value is too big", () => { - testValidator(` - class Main { - function void a(){ - var int foo; - let foo = 33000; - return; - } - }`, IntLiteralOverflow, - { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }) - }) - test("integer constant value is too small", () => { - testValidator(` - class Main { - function void a(){ - var int foo; - let foo = -33000; - return; - } - }`, IntLiteralOverflow, - { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }) - }) - test("A field can not be referenced in a function", () => { - testValidator(` - class Main { - field int a; - function void a(){ - let a = 1; - return; - } - }`, FieldCantBeReferencedInFunction, - { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }) - }) - test("A static field can be referenced in a function", () => { - testValidator(` - class Main { - static int a; - function void a(){ - let a = 1; - return; - } - }`, undefined, - { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }) - }) - test("this can't be referenced in a function", () => { - testValidator(` - class Main { - function void a(){ - var Main m; - let m = this; - return; - } - }`, ThisCantBeReferencedInFunction, - { - "Main": genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - },) - }) - - //validate files - test.concurrent.each(testResourcesDirs)('%s', (dir: string) => { - testJackDir(path.join(__dirname, "resources", dir)); - }); - -}) - -function testJackDir(testFolder: string): void { - const files = fs.readdirSync(testFolder).filter(file => file.endsWith(".jack")).map(file => path.join(testFolder, file)); - let trees: Record = {} - let globalSymbolsListener: BinderListener = new BinderListener(); - for (const filePath of files) { - const errorListener = new ErrorListener() - errorListener.filepath = filePath; - const tree = parseJackFile(filePath) - trees[filePath] = tree - listenToTheTree(tree, globalSymbolsListener) - expect(globalSymbolsListener.errors).toEqual([]); - } - for (const filepath of Object.keys(trees)) { - const tree = trees[filepath] - const validatorListener = listenToTheTree(tree, new ValidatorListener(globalSymbolsListener.globalSymbolTable)); - expect(validatorListener.errors).toEqual([]); - } - -} - -function testValidator( - src: string, - expectedError?: T, - globalSymbolTable: Record = {}, -) { - const name = expect.getState().currentTestName! - const errorListener = new ErrorListener(); - errorListener.filepath = name; - const tree = parseJackText(src, errorListener) - - const validator = listenToTheTree(tree, new ValidatorListener(globalSymbolTable)) - if (expectedError) { - // if (validator.cfgNode) { - // validator.cfgNode.print() - // } - if (validator.errors.length > 1) { - console.error("Errors", validator.errors) - } - try { - expect(validator.errors.length).toBe(1) - expect(validator.errors[0]).toBeInstanceOf(expectedError) - } catch (e) { - throw new Error(`Expected error ${expectedError.name} but got '` + validator.errors.join(",") + "'") - } - } else { - if (validator.errors.length != 0) throw new Error("Didn't expect any errors but got " + validator.errors.join("\n")) - } - // if (expectedLocalSymbolTable != undefined) { - // expect(validator.localSymbolTable).toEqual(expectedLocalSymbolTable) - // } -} - -//TODO: add validation for assgining from void function call -//TODO: Add rule to forbid var use before assignment -/** - * TODO: -* Ideas for improvement - -* - Show "Expected class name, subroutine name, field, parameter or local or static variable name" instead of "expecting IDENTIFIER" -* - Show "Expected subroutine return type followed by a subroutine name" instead of "expecting IDENTIFIER" -* - Expected subroutine name in call -* - a numeric value is illegal here when using non numeric vars -* - validate function call - when using literal in call validate the type -*/ \ No newline at end of file diff --git a/compiler/tsconfig.json b/compiler/tsconfig.json deleted file mode 100644 index 4116586e..00000000 --- a/compiler/tsconfig.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "compilerOptions": { - // Workspace projects - "composite": true, - - // Assume browser environment & esm - "lib": ["es2022", "DOM", "DOM.Iterable"], - "target": "es2022", - "module": "ESNext", - "moduleResolution": "node", - "allowJs": true, - "checkJs": false, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": false, - "jsx": "react-jsx", - "sourceMap": true, - - // Checks and strictness - "strict": true, - "allowUnreachableCode": false, - "allowUnusedLabels": false, - // "exactOptionalPropertyTypes": true, - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - "noImplicitReturns": true, - // "noPropertyAccessFromIndexSignature": true, - // "noUncheckedIndexedAccess": true, - // "noUnusedLocals": true, - // "noUnusedParameters": true, - - "incremental": true, - "declaration": true, - - }, - -} diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index 788631f7..5d043d89 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -31,7 +31,7 @@ export function compile( return result; } } - //to satisfy compiler + console.error("Should've returned from catch or try"); return {}; } function _compile(files: Record, @@ -40,6 +40,9 @@ function _compile(files: Record, throw new Error("Expected tree but got a lexer or parser error"); } const result: Record = {}; + for (const name of Object.keys(files)) { + result[name] = ""; + } const trees: Record = {}; const errors: Record = {}; const compiler = new Compiler(); @@ -47,13 +50,17 @@ function _compile(files: Record, const treeOrErrors = compiler.parserAndBind(content); if (Array.isArray(treeOrErrors)) { const s = treeOrErrors[0].span - errors[name] = { message: treeOrErrors[0].msg, span: { start: s.start, end: s.end, line: 3 } as Span } as CompilationError; + errors[name] = { message: `Line ${s.line}: ${treeOrErrors[0].msg}`, span: { start: s.start, end: s.end, line: 3 } as Span } as CompilationError; } trees[name] = treeOrErrors as ProgramContext; } if (Object.keys(errors).length > 0) { - return errors; + for (const [name, error] of Object.entries(errors)) { + result[name] = error; + } + return result; } + for (const [name, tree] of Object.entries(trees)) { const compiledOrErrors = compiler.compile(tree); if (Array.isArray(compiledOrErrors)) { diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index b1b23bda..2f4eb7a1 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -15,20 +15,6 @@ export class CustomErrorListener extends ErrorListener { e: RecognitionException | undefined, ) => { const t = offendingSymbol as Token; - const endIndex = column + t.text.length; - this.errors.push(new LexerOrParserError(line, column, endIndex, msg)); + this.errors.push(new LexerOrParserError(line, t.start, t.stop+1, msg)); }; - -} - -/** - * - We can add next methods (should be properties) to the error listener class to speed up parsing process. This is not part of Error listener ts class but exists in js implementation - reportAmbiguity(recognizer: any, dfa: any, startIndex: any, stopIndex: any, exact: any, ambigAlts: any, configs: any) { - console.log(`Ambiguity detected at ${this.filepath}:${startIndex}:${stopIndex}`); - } - - reportContextSensitivity(recognizer: any, dfa: any, startIndex: any, stopIndex: any, prediction: any, configs: any) { - console.log(`Context sensitivity detected at ${this.filepath}:${startIndex}:${stopIndex}`); - } - */ \ No newline at end of file +} \ No newline at end of file From cf2c04cc166fbd860f2e3c8fe60f95d424364eb4 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:10:48 +0200 Subject: [PATCH 28/87] WIP --- .vscode/launch.json | 6 --- .vscode/numbered-bookmarks.json | 49 ------------------- simulator/src/jack/builtins.ts | 1 - simulator/src/jack/compiler.ts | 36 ++++++-------- .../src/jack/listener/binder.listener.ts | 1 - simulator/src/jack/listener/error.listener.ts | 3 -- 6 files changed, 15 insertions(+), 81 deletions(-) delete mode 100644 .vscode/numbered-bookmarks.json diff --git a/.vscode/launch.json b/.vscode/launch.json index 4e0a1a05..6b93aff1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -34,12 +34,6 @@ ], "outFiles": ["${workspaceFolder}/extension/build/test/**/*.js"], "preLaunchTask": "${defaultBuildTask}" - }, { - "type": "chrome", - "request": "launch", - "name": "Test web ide", - "url": "http://localhost:3000/web-ide", - "webRoot": "${workspaceFolder}" } ] } diff --git a/.vscode/numbered-bookmarks.json b/.vscode/numbered-bookmarks.json deleted file mode 100644 index 5268caba..00000000 --- a/.vscode/numbered-bookmarks.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "files": [ - { - "path": "simulator/src/jack/compiler.ts", - "bookmarks": [ - { - "line": -1, - "column": 0 - }, - { - "line": -1, - "column": 0 - }, - { - "line": -1, - "column": 0 - }, - { - "line": 160, - "column": 2 - }, - { - "line": -1, - "column": 0 - }, - { - "line": -1, - "column": 0 - }, - { - "line": -1, - "column": 0 - }, - { - "line": -1, - "column": 0 - }, - { - "line": -1, - "column": 0 - }, - { - "line": -1, - "column": 0 - } - ] - } - ] -} \ No newline at end of file diff --git a/simulator/src/jack/builtins.ts b/simulator/src/jack/builtins.ts index 4e73cc06..cbb14ddd 100644 --- a/simulator/src/jack/builtins.ts +++ b/simulator/src/jack/builtins.ts @@ -6,7 +6,6 @@ interface Range { max: number; } export const intRange = { min: -32768, max: 32767 } as Range; -//TODO: should we convert this to symbols? const builtInFunctionsToArgCount: Record = { "Array.dispose": 0, //TODO: what is this? diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index 5d043d89..debb48c2 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -1,12 +1,12 @@ import { BinderListener } from "./listener/binder.listener.js"; import { CustomErrorListener } from "./listener/error.listener.js"; import { ValidatorListener } from "./listener/validator.listener.js"; -import { JackCompilerError, LexerOrParserError, Span } from "./error.js"; +import { JackCompilerError, LexerOrParserError } from "./error.js"; import { VMWriter } from "./listener/vm.writer.listener.js"; import JackParser, { ProgramContext } from "./generated/JackParser.js"; import { CharStreams, CommonTokenStream, ParseTreeWalker } from "antlr4"; import JackLexer from "./generated/JackLexer.js"; -import { CompilationError, createError } from "../languages/base.js"; +import { CompilationError } from "../languages/base.js"; export function compile( files: Record, @@ -14,25 +14,14 @@ export function compile( try { return _compile(files) } catch (err) { + const result: Record = {}; console.error(err); - if (typeof err === "string") { - const result: Record = {}; - const error: CompilationError = createError(err.toUpperCase()) - for (const name in Object.keys(files)) { - result[name] = error; - } - return result; - } else if (err instanceof Error) { - const result: Record = {}; - const error: CompilationError = createError(err.message) - for (const name in Object.keys(files)) { - result[name] = error; - } - return result; + const keys = Object.keys(files); + for (const name of keys) { + result[name] = { message: "Something went wrong while compiling files. Please create a bug report" } as CompilationError; } + return result; } - console.error("Should've returned from catch or try"); - return {}; } function _compile(files: Record, ): Record { @@ -49,8 +38,7 @@ function _compile(files: Record, for (const [name, content] of Object.entries(files)) { const treeOrErrors = compiler.parserAndBind(content); if (Array.isArray(treeOrErrors)) { - const s = treeOrErrors[0].span - errors[name] = { message: `Line ${s.line}: ${treeOrErrors[0].msg}`, span: { start: s.start, end: s.end, line: 3 } as Span } as CompilationError; + errors[name] = toCompilerError(treeOrErrors); } trees[name] = treeOrErrors as ProgramContext; } @@ -64,13 +52,19 @@ function _compile(files: Record, for (const [name, tree] of Object.entries(trees)) { const compiledOrErrors = compiler.compile(tree); if (Array.isArray(compiledOrErrors)) { - result[name] = { message: compiledOrErrors[0].msg, span: compiledOrErrors[0].span } as CompilationError; + result[name] = toCompilerError(compiledOrErrors); } else { result[name] = compiledOrErrors; } } return result; } +function toCompilerError(errors: JackCompilerError[]): CompilationError { + const err = errors[0]; + return { message: `Line ${err.span.line}: ${err.msg}`, span: err.span } as CompilationError +} + + export class Compiler { private binder = new BinderListener(); private errorListener = new CustomErrorListener(); diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts index 38ac1513..8adca608 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/binder.listener.ts @@ -16,7 +16,6 @@ import JackParserListener from "../generated/JackParserListener.js"; const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; -/// /** * Creates global symbol table that contains built-in functions and found classes and subroutines */ diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 2f4eb7a1..1d443cd4 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -3,9 +3,6 @@ import { JackCompilerError, LexerOrParserError } from "../error.js"; export class CustomErrorListener extends ErrorListener { public errors: JackCompilerError[] = []; - /** - * Provides a default instance of {@link ConsoleErrorListener}. - */ override syntaxError = ( recognizer: Recognizer, offendingSymbol: any, From ecadfb2fd960b57c64fac0462bb2749f5a49bb59 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:11:32 +0200 Subject: [PATCH 29/87] WIP --- simulator/.vscode/numbered-bookmarks.json | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 simulator/.vscode/numbered-bookmarks.json diff --git a/simulator/.vscode/numbered-bookmarks.json b/simulator/.vscode/numbered-bookmarks.json deleted file mode 100644 index 5916671d..00000000 --- a/simulator/.vscode/numbered-bookmarks.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": [] -} \ No newline at end of file From be5142ad78aae67c9de49d918cf77e7ace99c517 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:13:59 +0200 Subject: [PATCH 30/87] WIP --- simulator/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/simulator/package.json b/simulator/package.json index 347c3989..d6d538b1 100644 --- a/simulator/package.json +++ b/simulator/package.json @@ -23,7 +23,6 @@ "@nand2tetris/runner": "^1.0.0", "@types/node": "^20.14.2", "antlr4": "^4.13.2", - "assert": "^2.1.0", "ohm-js": "^17.1.0", "rxjs": "^7.8.1" }, From 1b9a3484b134bc341a4fc31fdb091535b9136ffa Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:30:07 +0200 Subject: [PATCH 31/87] WIP --- .../src/jack/listener/validator.listener.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 8e550b03..b2e8db2e 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -201,7 +201,7 @@ export class ValidatorListener extends JackParserListener { }; override enterStatement = (ctx: StatementContext) => { - if (this.controlFlowGraphNode._returns == true) { + if (this.controlFlowGraphNode.returns == true) { this.#addError( new UnreachableCodeError( ctx.start.line, @@ -429,7 +429,7 @@ export class ValidatorListener extends JackParserListener { ), ); } - this.controlFlowGraphNode._returns = true; + this.controlFlowGraphNode.returns = true; if (this.subroutineType == SubroutineType.Constructor) { if ( returnsVoid || @@ -437,7 +437,6 @@ export class ValidatorListener extends JackParserListener { ctx.expression()!.constant() == null || ctx.expression()!.constant()!.THIS_LITERAL() == null ) { - //TODO: test on UI this.#addError( new ConstructorMushReturnThis( ctx.stop!.line, @@ -451,7 +450,6 @@ export class ValidatorListener extends JackParserListener { override exitSubroutineBody = (ctx: SubroutineBodyContext) => { if (!this.controlFlowGraphNode.returns) { - //TODO: test on UI this.#addError( new SubroutineNotAllPathsReturnError( ctx.stop!.line, @@ -518,14 +516,14 @@ export class ValidatorListener extends JackParserListener { } class BinaryTreeNode { - _returns?: boolean; + private _returns?: boolean; constructor( public parent?: BinaryTreeNode, public left?: BinaryTreeNode, public right?: BinaryTreeNode, - ) {} + ) { } - get returns(): boolean { + public get returns(): boolean { if (this._returns) { return this._returns; } else if (this.right == undefined && this.left == undefined) { @@ -538,6 +536,10 @@ class BinaryTreeNode { throw new Error("Something went wrong - CFG has only right subtree"); } } + + public set returns(_returns: boolean) { + this._returns = _returns; + } print() { console.log("Branch returns value"); console.log("."); From afbf33b8a2b3d1d262c2e30d17ee925cbc514ed9 Mon Sep 17 00:00:00 2001 From: happytomatoe <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:32:37 +0200 Subject: [PATCH 32/87] WIP --- simulator/src/jack/compiler.ts | 166 +++++++++--------- simulator/src/jack/generated/JackLexer.ts | 2 +- simulator/src/jack/generated/JackParser.ts | 30 ++-- simulator/src/jack/listener/error.listener.ts | 4 +- .../jack/listener/validator.listener.test.ts | 4 +- .../src/jack/listener/validator.listener.ts | 2 +- simulator/src/jack/parser.test.ts | 80 ++++----- simulator/src/jack/test.helper.ts | 106 +++++------ 8 files changed, 200 insertions(+), 194 deletions(-) diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index debb48c2..105302b4 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -9,100 +9,106 @@ import JackLexer from "./generated/JackLexer.js"; import { CompilationError } from "../languages/base.js"; export function compile( - files: Record, + files: Record, ): Record { - try { - return _compile(files) - } catch (err) { - const result: Record = {}; - console.error(err); - const keys = Object.keys(files); - for (const name of keys) { - result[name] = { message: "Something went wrong while compiling files. Please create a bug report" } as CompilationError; - } - return result; + try { + return _compile(files); + } catch (err) { + const result: Record = {}; + console.error(err); + const keys = Object.keys(files); + for (const name of keys) { + result[name] = { + message: + "Something went wrong while compiling files. Please create a bug report", + } as CompilationError; } + return result; + } } -function _compile(files: Record, +function _compile( + files: Record, ): Record { - if (files instanceof LexerOrParserError) { - throw new Error("Expected tree but got a lexer or parser error"); - } - const result: Record = {}; - for (const name of Object.keys(files)) { - result[name] = ""; + if (files instanceof LexerOrParserError) { + throw new Error("Expected tree but got a lexer or parser error"); + } + const result: Record = {}; + for (const name of Object.keys(files)) { + result[name] = ""; + } + const trees: Record = {}; + const errors: Record = {}; + const compiler = new Compiler(); + for (const [name, content] of Object.entries(files)) { + const treeOrErrors = compiler.parserAndBind(content); + if (Array.isArray(treeOrErrors)) { + errors[name] = toCompilerError(treeOrErrors); } - const trees: Record = {}; - const errors: Record = {}; - const compiler = new Compiler(); - for (const [name, content] of Object.entries(files)) { - const treeOrErrors = compiler.parserAndBind(content); - if (Array.isArray(treeOrErrors)) { - errors[name] = toCompilerError(treeOrErrors); - } - trees[name] = treeOrErrors as ProgramContext; - } - if (Object.keys(errors).length > 0) { - for (const [name, error] of Object.entries(errors)) { - result[name] = error; - } - return result; + trees[name] = treeOrErrors as ProgramContext; + } + if (Object.keys(errors).length > 0) { + for (const [name, error] of Object.entries(errors)) { + result[name] = error; } + return result; + } - for (const [name, tree] of Object.entries(trees)) { - const compiledOrErrors = compiler.compile(tree); - if (Array.isArray(compiledOrErrors)) { - result[name] = toCompilerError(compiledOrErrors); - } else { - result[name] = compiledOrErrors; - } + for (const [name, tree] of Object.entries(trees)) { + const compiledOrErrors = compiler.compile(tree); + if (Array.isArray(compiledOrErrors)) { + result[name] = toCompilerError(compiledOrErrors); + } else { + result[name] = compiledOrErrors; } - return result; + } + return result; } function toCompilerError(errors: JackCompilerError[]): CompilationError { - const err = errors[0]; - return { message: `Line ${err.span.line}: ${err.msg}`, span: err.span } as CompilationError + const err = errors[0]; + return { + message: `Line ${err.span.line}: ${err.msg}`, + span: err.span, + } as CompilationError; } - export class Compiler { - private binder = new BinderListener(); - private errorListener = new CustomErrorListener(); - compile(tree: ProgramContext): string | JackCompilerError[] { - if (Object.keys(this.binder.globalSymbolTable).length == 0) { - throw new Error( - "Please populate global symbol table using parserAndBind method", - ); - } - const validator = new ValidatorListener(this.binder.globalSymbolTable); - ParseTreeWalker.DEFAULT.walk(validator, tree); - if (validator.errors.length > 0) { - console.log("Errors in validator " + JSON.stringify(validator.errors)); - return validator.errors; - } - const vmWriter = new VMWriter(this.binder.globalSymbolTable); - ParseTreeWalker.DEFAULT.walk(vmWriter, tree); - return vmWriter.result; + private binder = new BinderListener(); + private errorListener = new CustomErrorListener(); + compile(tree: ProgramContext): string | JackCompilerError[] { + if (Object.keys(this.binder.globalSymbolTable).length == 0) { + throw new Error( + "Please populate global symbol table using parserAndBind method", + ); } + const validator = new ValidatorListener(this.binder.globalSymbolTable); + ParseTreeWalker.DEFAULT.walk(validator, tree); + if (validator.errors.length > 0) { + console.log("Errors in validator " + JSON.stringify(validator.errors)); + return validator.errors; + } + const vmWriter = new VMWriter(this.binder.globalSymbolTable); + ParseTreeWalker.DEFAULT.walk(vmWriter, tree); + return vmWriter.result; + } - parserAndBind(src: string): ProgramContext | JackCompilerError[] { - const lexer = new JackLexer(CharStreams.fromString(src)); - lexer.removeErrorListeners(); - lexer.addErrorListener(this.errorListener); - const tokenStream = new CommonTokenStream(lexer); - const parser = new JackParser(tokenStream); - parser.removeErrorListeners(); - parser.addErrorListener(this.errorListener); - const tree = parser.program(); - if (this.errorListener.errors.length > 0) { - console.log("Errors when parsing or lexing"); - return this.errorListener.errors; - } - ParseTreeWalker.DEFAULT.walk(this.binder, tree); - if (this.binder.errors.length > 0) { - console.log("Errors in binder"); - return this.binder.errors; - } - return tree; + parserAndBind(src: string): ProgramContext | JackCompilerError[] { + const lexer = new JackLexer(CharStreams.fromString(src)); + lexer.removeErrorListeners(); + lexer.addErrorListener(this.errorListener); + const tokenStream = new CommonTokenStream(lexer); + const parser = new JackParser(tokenStream); + parser.removeErrorListeners(); + parser.addErrorListener(this.errorListener); + const tree = parser.program(); + if (this.errorListener.errors.length > 0) { + console.log("Errors when parsing or lexing"); + return this.errorListener.errors; + } + ParseTreeWalker.DEFAULT.walk(this.binder, tree); + if (this.binder.errors.length > 0) { + console.log("Errors in binder"); + return this.binder.errors; } + return tree; + } } diff --git a/simulator/src/jack/generated/JackLexer.ts b/simulator/src/jack/generated/JackLexer.ts index 55f6427e..c5a8dc22 100644 --- a/simulator/src/jack/generated/JackLexer.ts +++ b/simulator/src/jack/generated/JackLexer.ts @@ -9,7 +9,7 @@ import { Lexer, LexerATNSimulator, PredictionContextCache, - Token + Token, } from "antlr4"; export default class JackLexer extends Lexer { public static readonly CLASS = 1; diff --git a/simulator/src/jack/generated/JackParser.ts b/simulator/src/jack/generated/JackParser.ts index b3205261..85b6338f 100644 --- a/simulator/src/jack/generated/JackParser.ts +++ b/simulator/src/jack/generated/JackParser.ts @@ -2,21 +2,21 @@ // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { - ATN, - ATNDeserializer, - DecisionState, - DFA, - FailedPredicateException, - NoViableAltException, - Parser, - ParserATNSimulator, - ParserRuleContext, - PredictionContextCache, - RecognitionException, - RuleContext, - TerminalNode, - Token, - TokenStream + ATN, + ATNDeserializer, + DecisionState, + DFA, + FailedPredicateException, + NoViableAltException, + Parser, + ParserATNSimulator, + ParserRuleContext, + PredictionContextCache, + RecognitionException, + RuleContext, + TerminalNode, + Token, + TokenStream, } from "antlr4"; import JackParserListener from "./JackParserListener.js"; // for running tests with parameters, TODO: discuss strategy for typed parameters in CI diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 1d443cd4..63b6594a 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -12,6 +12,6 @@ export class CustomErrorListener extends ErrorListener { e: RecognitionException | undefined, ) => { const t = offendingSymbol as Token; - this.errors.push(new LexerOrParserError(line, t.start, t.stop+1, msg)); + this.errors.push(new LexerOrParserError(line, t.start, t.stop + 1, msg)); }; -} \ No newline at end of file +} diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index 3876cfa8..ce0ed44f 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -806,8 +806,8 @@ function testValidator( } catch (e) { throw new Error( `Expected error ${expectedError.name} but got '` + - validator.errors.join(",") + - "'", + validator.errors.join(",") + + "'", ); } } else { diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index b2e8db2e..d2ccb209 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -521,7 +521,7 @@ class BinaryTreeNode { public parent?: BinaryTreeNode, public left?: BinaryTreeNode, public right?: BinaryTreeNode, - ) { } + ) {} public get returns(): boolean { if (this._returns) { diff --git a/simulator/src/jack/parser.test.ts b/simulator/src/jack/parser.test.ts index b3d88db6..73e22789 100644 --- a/simulator/src/jack/parser.test.ts +++ b/simulator/src/jack/parser.test.ts @@ -2,59 +2,59 @@ import fs from "fs"; import path from "path"; import { - getTestResourcePath, - listenToTheTree, - parseJackFile, - parseJackText, - testResourceDirs, + getTestResourcePath, + listenToTheTree, + parseJackFile, + parseJackText, + testResourceDirs, } from "./test.helper"; import { BinderListener } from "./listener/binder.listener"; describe("Parser", () => { - const jestConsole = console; - beforeEach(() => { - global.console = require("console"); - }); + const jestConsole = console; + beforeEach(() => { + global.console = require("console"); + }); - afterEach(() => { - global.console = jestConsole; - }); + afterEach(() => { + global.console = jestConsole; + }); - test.each(testResourceDirs)("%s", (dir: string) => { - testJackDir(getTestResourcePath(dir)); - }); - test("expected EOF", () => { - try { - parseJackText(` + test.each(testResourceDirs)("%s", (dir: string) => { + testJackDir(getTestResourcePath(dir)); + }); + test("expected EOF", () => { + try { + parseJackText(` class A{ } var a; `); - } catch (e) { - if (e instanceof Error) { - expect(e.message).toContain("expecting "); - return; - } else { - fail("Expected Error"); - } - } + } catch (e) { + if (e instanceof Error) { + expect(e.message).toContain("expecting "); + return; + } else { fail("Expected Error"); - }); + } + } + fail("Expected Error"); + }); }); function testJackDir(testFolder: string): void { - const files = fs - .readdirSync(testFolder) - .filter((file) => file.endsWith(".jack")) - .map((file) => path.join(testFolder, file)); - for (const filePath of files) { - const tree = parseJackFile(filePath); - const globalSymbolsListener = listenToTheTree(tree, new BinderListener()); - const symbolsErrors = globalSymbolsListener.errors.join("\n"); - try { - expect(globalSymbolsListener.errors.length).toBe(0); - } catch (e) { - throw new Error(symbolsErrors); - } + const files = fs + .readdirSync(testFolder) + .filter((file) => file.endsWith(".jack")) + .map((file) => path.join(testFolder, file)); + for (const filePath of files) { + const tree = parseJackFile(filePath); + const globalSymbolsListener = listenToTheTree(tree, new BinderListener()); + const symbolsErrors = globalSymbolsListener.errors.join("\n"); + try { + expect(globalSymbolsListener.errors.length).toBe(0); + } catch (e) { + throw new Error(symbolsErrors); } + } } diff --git a/simulator/src/jack/test.helper.ts b/simulator/src/jack/test.helper.ts index e462e4bd..81d3c602 100644 --- a/simulator/src/jack/test.helper.ts +++ b/simulator/src/jack/test.helper.ts @@ -3,80 +3,80 @@ import path from "path"; import { JackCompilerError } from "./error"; import { CustomErrorListener } from "./listener/error.listener"; import { - CharStreams, - CommonTokenStream, - ParseTreeListener, - ParseTreeWalker, + CharStreams, + CommonTokenStream, + ParseTreeListener, + ParseTreeWalker, } from "antlr4"; import JackLexer from "./generated/JackLexer"; import JackParser, { ProgramContext } from "./generated/JackParser"; export function parseJackFile(filePath: string, trace = false) { - const errorListener: CustomErrorListener = new CustomErrorListener(); - const f = fs.readFileSync(filePath, "utf8"); - return parseJackText(f, errorListener, trace); + const errorListener: CustomErrorListener = new CustomErrorListener(); + const f = fs.readFileSync(filePath, "utf8"); + return parseJackText(f, errorListener, trace); } export function parseJackText( - src: string, - errorListener?: CustomErrorListener, - trace = false, - throwOnErrors = true, + src: string, + errorListener?: CustomErrorListener, + trace = false, + throwOnErrors = true, ): ProgramContext { - if (errorListener === undefined) { - errorListener = new CustomErrorListener(); - } - const inputStream = CharStreams.fromString(src); - const lexer = new JackLexer(inputStream); - if (errorListener) { - lexer.removeErrorListeners(); - lexer.addErrorListener(errorListener); - } + if (errorListener === undefined) { + errorListener = new CustomErrorListener(); + } + const inputStream = CharStreams.fromString(src); + const lexer = new JackLexer(inputStream); + if (errorListener) { + lexer.removeErrorListeners(); + lexer.addErrorListener(errorListener); + } - const tokenStream = new CommonTokenStream(lexer); - const parser = new JackParser(tokenStream); - if (errorListener != undefined) { - parser.removeErrorListeners(); - parser.addErrorListener(errorListener); - } - const tree = parser.program(); + const tokenStream = new CommonTokenStream(lexer); + const parser = new JackParser(tokenStream); + if (errorListener != undefined) { + parser.removeErrorListeners(); + parser.addErrorListener(errorListener); + } + const tree = parser.program(); - expect(tokenStream.tokens.length).toBeGreaterThan(0); - if (errorListener.errors.length > 0) { - console.error("Parser or lexer errors found"); - handleErrors(src, errorListener.errors); - } - return tree; + expect(tokenStream.tokens.length).toBeGreaterThan(0); + if (errorListener.errors.length > 0) { + console.error("Parser or lexer errors found"); + handleErrors(src, errorListener.errors); + } + return tree; } export function getTestResourcePath(relativePath: string) { - return path.join(__dirname, "resources", "test", relativePath); + return path.join(__dirname, "resources", "test", relativePath); } export function listenToTheTree( - tree: ProgramContext, - listener: T, + tree: ProgramContext, + listener: T, ) { - ParseTreeWalker.DEFAULT.walk(listener, tree); - return listener; + ParseTreeWalker.DEFAULT.walk(listener, tree); + return listener; } export function handleErrors(src: string, errors: JackCompilerError[]) { - const msg = errors - .map((e) => { - return `${e.span.line}:${e.span.start} ${e.msg}\n${src.split("\n")[e.span.line]}`; - }) - .join("\n"); - console.error(msg); - throw new Error(msg); + const msg = errors + .map((e) => { + return `${e.span.line}:${e.span.start} ${e.msg}\n${src.split("\n")[e.span.line]}`; + }) + .join("\n"); + console.error(msg); + throw new Error(msg); } export const testResourceDirs: string[] = [ - "Average", - "ConvertToBin", - "Fraction", - "HelloWorld", - "List", - "Pong", - "Square", - "ComplexArrays", + "Average", + "ConvertToBin", + "Fraction", + "HelloWorld", + "List", + "Pong", + "Square", + "ComplexArrays", ]; From faef67d7c44e156ff80292a69f57d82aef35efec Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:26:46 +0200 Subject: [PATCH 33/87] Fix lexer error handling --- .vscode/launch.json | 7 ++++++ simulator/src/jack/listener/error.listener.ts | 23 ++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 6b93aff1..184dfbb0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -34,6 +34,13 @@ ], "outFiles": ["${workspaceFolder}/extension/build/test/**/*.js"], "preLaunchTask": "${defaultBuildTask}" + }, + { + "type": "chrome", + "request": "launch", + "name": "Test web ide", + "url": "http://localhost:3000/web-ide", + "webRoot": "${workspaceFolder}" } ] } diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 63b6594a..38a6c6da 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -1,5 +1,8 @@ -import { ErrorListener, RecognitionException, Recognizer, Token } from "antlr4"; +import { ErrorListener, NoViableAltException, RecognitionException, Recognizer, Token } from "antlr4"; import { JackCompilerError, LexerOrParserError } from "../error.js"; +interface LexerNoViableAltException { + startIndex: number; +} export class CustomErrorListener extends ErrorListener { public errors: JackCompilerError[] = []; @@ -11,7 +14,21 @@ export class CustomErrorListener extends ErrorListener { msg: string, e: RecognitionException | undefined, ) => { - const t = offendingSymbol as Token; - this.errors.push(new LexerOrParserError(line, t.start, t.stop + 1, msg)); + if (offendingSymbol != null || e != null && e.offendingToken != null) { + const t = offendingSymbol ?? e!.offendingToken as Token; + this.errors.push(new LexerOrParserError(line, t.start, t.stop + 1, msg)); + } else if (e instanceof NoViableAltException) { + this.errors.push(new LexerOrParserError(line, e.startToken.start, e.startToken.stop + 1, msg)); + + } + //antlr doesn't provide a class for LexerNoViableAltException atm. Once https://github.com/antlr/antlr4/pull/4711 is release we can change it + else if (e != null && 'startIndex' in e) { + const err = e as LexerNoViableAltException; + this.errors.push(new LexerOrParserError(line, err.startIndex, err.startIndex + 1, msg)); + } else { + console.error("Don't know how to handle this error"); + throw new Error("Don't know how to handle this error"); + } }; } + From dd918cb316f254369c095f81294bcc5c4ee69b29 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:44:38 +0200 Subject: [PATCH 34/87] WIP --- simulator/src/jack/listener/error.listener.ts | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 38a6c6da..88af922e 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -1,4 +1,10 @@ -import { ErrorListener, NoViableAltException, RecognitionException, Recognizer, Token } from "antlr4"; +import { + ErrorListener, + NoViableAltException, + RecognitionException, + Recognizer, + Token, +} from "antlr4"; import { JackCompilerError, LexerOrParserError } from "../error.js"; interface LexerNoViableAltException { startIndex: number; @@ -14,21 +20,28 @@ export class CustomErrorListener extends ErrorListener { msg: string, e: RecognitionException | undefined, ) => { - if (offendingSymbol != null || e != null && e.offendingToken != null) { - const t = offendingSymbol ?? e!.offendingToken as Token; + if (offendingSymbol != null || (e != null && e.offendingToken != null)) { + const t = offendingSymbol ?? (e!.offendingToken as Token); this.errors.push(new LexerOrParserError(line, t.start, t.stop + 1, msg)); } else if (e instanceof NoViableAltException) { - this.errors.push(new LexerOrParserError(line, e.startToken.start, e.startToken.stop + 1, msg)); - + this.errors.push( + new LexerOrParserError( + line, + e.startToken.start, + e.startToken.stop + 1, + msg, + ), + ); } //antlr doesn't provide a class for LexerNoViableAltException atm. Once https://github.com/antlr/antlr4/pull/4711 is release we can change it - else if (e != null && 'startIndex' in e) { + else if (e != null && "startIndex" in e) { const err = e as LexerNoViableAltException; - this.errors.push(new LexerOrParserError(line, err.startIndex, err.startIndex + 1, msg)); + this.errors.push( + new LexerOrParserError(line, err.startIndex, err.startIndex + 1, msg), + ); } else { console.error("Don't know how to handle this error"); throw new Error("Don't know how to handle this error"); } }; } - From ae65cc5850a7eb294c983d172f6d6e9021bed969 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:48:48 +0200 Subject: [PATCH 35/87] WIP --- simulator/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 simulator/README.md diff --git a/simulator/README.md b/simulator/README.md new file mode 100644 index 00000000..31efb9ad --- /dev/null +++ b/simulator/README.md @@ -0,0 +1,11 @@ +To run + +``` +npm run gen +``` + +Install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md) + +``` +pip install antlr4-tools +``` \ No newline at end of file From 694dbcd551cef0adac5ceebf95765e3db28372c5 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Thu, 3 Oct 2024 21:21:51 +0200 Subject: [PATCH 36/87] Add compiler validate methods --- components/src/stores/compiler.store.ts | 28 ++++++++- simulator/src/jack/compiler.ts | 63 +++++++++++++++---- .../src/jack/listener/vm.writer.listener.ts | 4 +- web/src/pages/compiler.tsx | 1 + 4 files changed, 78 insertions(+), 18 deletions(-) diff --git a/components/src/stores/compiler.store.ts b/components/src/stores/compiler.store.ts index 12de210c..a15086e0 100644 --- a/components/src/stores/compiler.store.ts +++ b/components/src/stores/compiler.store.ts @@ -1,5 +1,5 @@ import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; -import { compile } from "@nand2tetris/simulator/jack/compiler.js"; +import { compile, validate } from "@nand2tetris/simulator/jack/compiler.js"; import { CompilationError } from "@nand2tetris/simulator/languages/base.js"; import { Dispatch, MutableRefObject, useContext, useMemo, useRef } from "react"; import { useImmerReducer } from "../react.js"; @@ -51,8 +51,6 @@ export function makeCompilerStore( { name, content }: { name: string; content: string }, ) { state.files[name] = content; - state.isCompiled = false; - this.compile(state); }, // the keys of 'files' have to be the full file path, not basename @@ -62,6 +60,27 @@ export function makeCompilerStore( this.compile(state); }, + validate(state: CompilerPageState) { + state.isCompiled = false; + const compiledFiles = validate(state.files); + state.compiled = {}; + for (const [name, compiled] of Object.entries(compiledFiles)) { + if (typeof compiled === "string") { + state.compiled[name] = { + valid: true, + vm: compiled, + }; + } else { + state.compiled[name] = { + valid: false, + error: compiled, + }; + } + } + state.isValid = Object.keys(state.files).every( + (file) => state.compiled[file].valid, + ); + }, compile(state: CompilerPageState) { const compiledFiles = compile(state.files); state.compiled = {}; @@ -145,6 +164,9 @@ export function makeCompilerStore( async compile() { dispatch.current({ action: "writeCompiled" }); }, + async validate() { + dispatch.current({ action: "validate" }); + }, }; const initialState: CompilerPageState = { diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index 105302b4..f6914cfe 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -11,8 +11,17 @@ import { CompilationError } from "../languages/base.js"; export function compile( files: Record, ): Record { + return _doWithTryCatch(files, Command.Compile); +} + +export function validate( + files: Record, +): Record { + return _doWithTryCatch(files, Command.Validate); +} +function _doWithTryCatch(files: Record, cmd: Command) { try { - return _compile(files); + return _do(files, cmd); } catch (err) { const result: Record = {}; console.error(err); @@ -26,8 +35,13 @@ export function compile( return result; } } -function _compile( - files: Record, +enum Command { + Compile, + Validate +} + +function _do( + files: Record, cmd: Command ): Record { if (files instanceof LexerOrParserError) { throw new Error("Expected tree but got a lexer or parser error"); @@ -54,11 +68,27 @@ function _compile( } for (const [name, tree] of Object.entries(trees)) { - const compiledOrErrors = compiler.compile(tree); - if (Array.isArray(compiledOrErrors)) { - result[name] = toCompilerError(compiledOrErrors); - } else { - result[name] = compiledOrErrors; + let compiledOrValidatedOrErrors; + switch (cmd) { + case Command.Compile: + compiledOrValidatedOrErrors = compiler.compile(tree); + + if (Array.isArray(compiledOrValidatedOrErrors)) { + result[name] = toCompilerError(compiledOrValidatedOrErrors); + } else { + result[name] = compiledOrValidatedOrErrors; + } + break; + case Command.Validate: + compiledOrValidatedOrErrors = compiler.validate(tree); + if (Array.isArray(compiledOrValidatedOrErrors)) { + result[name] = toCompilerError(compiledOrValidatedOrErrors); + } else { + result[name] = ""; + } + break; + default: + throw new Error("Invalid command"); } } return result; @@ -74,7 +104,7 @@ function toCompilerError(errors: JackCompilerError[]): CompilationError { export class Compiler { private binder = new BinderListener(); private errorListener = new CustomErrorListener(); - compile(tree: ProgramContext): string | JackCompilerError[] { + validate(tree: ProgramContext): ProgramContext | JackCompilerError[] { if (Object.keys(this.binder.globalSymbolTable).length == 0) { throw new Error( "Please populate global symbol table using parserAndBind method", @@ -82,12 +112,19 @@ export class Compiler { } const validator = new ValidatorListener(this.binder.globalSymbolTable); ParseTreeWalker.DEFAULT.walk(validator, tree); - if (validator.errors.length > 0) { - console.log("Errors in validator " + JSON.stringify(validator.errors)); - return validator.errors; + + return tree + } + compile(tree: ProgramContext): string | JackCompilerError[] { + const treeOrErrors = this.validate(tree); + if (Array.isArray(treeOrErrors)) { + const errors = treeOrErrors as JackCompilerError[]; + console.log("Errors in validator " + JSON.stringify(errors)); + return errors; } + const validateTree = treeOrErrors as ProgramContext; const vmWriter = new VMWriter(this.binder.globalSymbolTable); - ParseTreeWalker.DEFAULT.walk(vmWriter, tree); + ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); return vmWriter.result; } diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index 1df55f93..e883c22c 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -135,8 +135,8 @@ export class VMWriter extends JackParserListener { this.result += ` push constant ${str.length}\n`; this.result += ` call String.new 1\n`; for (const char of str) { - this.result += ` push constant ${char.charCodeAt(0)}\n`; - this.result += " call String.appendChar 2\n"; + this.result += ` push constant ${char.charCodeAt(0)}\n`; + this.result += " call String.appendChar 2\n"; } } else if (ctx.NULL_LITERAL() != null) { this.result += ` push constant 0\n`; diff --git a/web/src/pages/compiler.tsx b/web/src/pages/compiler.tsx index af2de31c..124082cd 100644 --- a/web/src/pages/compiler.tsx +++ b/web/src/pages/compiler.tsx @@ -218,6 +218,7 @@ export const Compiler = () => { value={state.files[file]} onChange={(source: string) => { actions.writeFile(file, source); + actions.validate(); }} error={state.compiled[file].error} language={"jack"} From 6bd99b83edfbd01547c4b35d42931e6547cf446e Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Thu, 3 Oct 2024 21:25:56 +0200 Subject: [PATCH 37/87] WIP --- simulator/src/jack/compiler.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index f6914cfe..d5222f67 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -37,11 +37,12 @@ function _doWithTryCatch(files: Record, cmd: Command) { } enum Command { Compile, - Validate + Validate, } function _do( - files: Record, cmd: Command + files: Record, + cmd: Command, ): Record { if (files instanceof LexerOrParserError) { throw new Error("Expected tree but got a lexer or parser error"); @@ -113,7 +114,7 @@ export class Compiler { const validator = new ValidatorListener(this.binder.globalSymbolTable); ParseTreeWalker.DEFAULT.walk(validator, tree); - return tree + return tree; } compile(tree: ProgramContext): string | JackCompilerError[] { const treeOrErrors = this.validate(tree); From d67729e4632c0fe6ad01ea68078dec0cf7b0fad3 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:02:18 +0200 Subject: [PATCH 38/87] WIP --- simulator/package.json | 2 + simulator/src/jack/builtins.ts | 14 +++-- simulator/src/jack/compiler.test.ts | 2 +- .../src/jack/listener/binder.listener.test.ts | 2 +- .../jack/listener/validator.listener.test.ts | 51 +++++++++---------- simulator/src/jack/parser.test.ts | 2 +- simulator/src/jack/symbol.table.test.ts | 2 +- 7 files changed, 35 insertions(+), 40 deletions(-) diff --git a/simulator/package.json b/simulator/package.json index d6d538b1..cbdc9e86 100644 --- a/simulator/package.json +++ b/simulator/package.json @@ -38,6 +38,8 @@ "build": "tsc", "test": "jest --verbose", "test-w": "jest --watchAll --verbose", + "test-jack": "npm run test -- -t \"Jack\"", + "test-jack-w": "npm run test-w -- -t \"Jack\"", "gen": "cd src/languages/grammars && antlr4 -Dlanguage=TypeScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" } } diff --git a/simulator/src/jack/builtins.ts b/simulator/src/jack/builtins.ts index cbb14ddd..672dc2f2 100644 --- a/simulator/src/jack/builtins.ts +++ b/simulator/src/jack/builtins.ts @@ -8,8 +8,7 @@ interface Range { export const intRange = { min: -32768, max: 32767 } as Range; const builtInFunctionsToArgCount: Record = { "Array.dispose": 0, - //TODO: what is this? - // "Array.init": 0, + "Array.init": 0, "Array.new": 1, "Keyboard.init": 0, "Keyboard.keyPressed": 0, @@ -18,19 +17,18 @@ const builtInFunctionsToArgCount: Record = { "Keyboard.readLine": 1, "Math.abs": 1, "Math.divide": 2, - //TODO: what is this ? - // "Math.init": 0, + "Math.init": 0, "Math.max": 2, "Math.min": 2, "Math.multiply": 2, "Math.sqrt": 1, "Memory.alloc": 1, "Memory.deAlloc": 1, - // "Memory.init": 0, + "Memory.init": 0, "Memory.peek": 1, "Memory.poke": 2, "Output.backSpace": 0, - // "Output.init": 0, + "Output.init": 0, "Output.moveCursor": 2, "Output.printChar": 1, "Output.printInt": 1, @@ -41,7 +39,7 @@ const builtInFunctionsToArgCount: Record = { "Screen.drawLine": 4, "Screen.drawPixel": 2, "Screen.drawRectangle": 4, - // "Screen.init": 0, + "Screen.init": 0, "Screen.setColor": 1, "String.appendChar": 1, "String.backSpace": 0, @@ -49,7 +47,7 @@ const builtInFunctionsToArgCount: Record = { "String.dispose": 0, "String.doubleQuote": 0, "String.eraseLastChar": 0, - // "String.init": 0, + "String.init": 0, "String.intValue": 0, "String.length": 0, "String.new": 1, diff --git a/simulator/src/jack/compiler.test.ts b/simulator/src/jack/compiler.test.ts index 1620e4dc..9be784b7 100644 --- a/simulator/src/jack/compiler.test.ts +++ b/simulator/src/jack/compiler.test.ts @@ -3,7 +3,7 @@ import { getTestResourcePath, testResourceDirs } from "./test.helper"; import path from "path"; import { ProgramContext } from "./generated/JackParser"; import { Compiler } from "./compiler"; -describe("Compiler", () => { +describe("Jack compiler", () => { test("static field", () => { testCompiler( `class A{ diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/binder.listener.test.ts index 09839d28..6c9769ff 100644 --- a/simulator/src/jack/listener/binder.listener.test.ts +++ b/simulator/src/jack/listener/binder.listener.test.ts @@ -10,7 +10,7 @@ import { parseJackText, } from "../test.helper"; -describe("Binder", () => { +describe("Jack binder", () => { const jestConsole = console; beforeEach(() => { diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index ce0ed44f..33c58436 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -35,7 +35,7 @@ import fs from "fs"; import { BinderListener } from "./binder.listener"; import path from "path"; import { ProgramContext } from "../generated/JackParser"; -describe("ValidatorListener", () => { +describe("Jack validator listener", () => { const jestConsole = console; beforeEach(() => { global.console = require("console"); @@ -119,7 +119,7 @@ describe("ValidatorListener", () => { }`, UndeclaredVariableError, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 1), "Main.a": genericSymbol(SubroutineType.Function, 1), }, @@ -468,7 +468,7 @@ describe("ValidatorListener", () => { }`, IncorrectParamsNumberInSubroutineCallError, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 2), "Main.b": genericSymbol(SubroutineType.Function, 2), }, @@ -494,7 +494,7 @@ describe("ValidatorListener", () => { }`, undefined, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), "Main.a": genericSymbol(SubroutineType.Function, 0), "Main.b": genericSymbol(SubroutineType.Method, 0), @@ -515,7 +515,7 @@ describe("ValidatorListener", () => { }`, undefined, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Method, 0), "Main.b": genericSymbol(SubroutineType.Method, 0), }, @@ -539,7 +539,7 @@ describe("ValidatorListener", () => { }`, MethodCalledAsFunctionError, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), "Main.c": genericSymbol(SubroutineType.Method, 0), }, @@ -559,7 +559,7 @@ describe("ValidatorListener", () => { }`, FunctionCalledAsMethodError, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), "Main.c": genericSymbol(SubroutineType.Function, 0), }, @@ -575,7 +575,7 @@ describe("ValidatorListener", () => { }`, IncorrectConstructorReturnType, { - Main: genericSymbol(), + "Main": genericSymbol(), D: genericSymbol(), }, ); @@ -593,7 +593,7 @@ describe("ValidatorListener", () => { }`, UnreachableCodeError, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), }, ); @@ -608,7 +608,7 @@ describe("ValidatorListener", () => { }`, ConstructorMushReturnThis, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), }, ); @@ -625,7 +625,7 @@ describe("ValidatorListener", () => { }`, WrongLiteralTypeError, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), String: genericSymbol(), }, @@ -643,7 +643,7 @@ describe("ValidatorListener", () => { }`, WrongLiteralTypeError, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -661,7 +661,7 @@ describe("ValidatorListener", () => { }`, WrongLiteralTypeError, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -678,7 +678,7 @@ describe("ValidatorListener", () => { }`, IntLiteralOverflow, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -695,7 +695,7 @@ describe("ValidatorListener", () => { }`, IntLiteralOverflow, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -712,7 +712,7 @@ describe("ValidatorListener", () => { }`, FieldCantBeReferencedInFunction, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -729,7 +729,7 @@ describe("ValidatorListener", () => { }`, undefined, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -746,7 +746,7 @@ describe("ValidatorListener", () => { }`, ThisCantBeReferencedInFunction, { - Main: genericSymbol(), + "Main": genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -794,9 +794,6 @@ function testValidator( new ValidatorListener(globalSymbolTable), ); if (expectedError) { - // if (validator.cfgNode) { - // validator.cfgNode.print() - // } if (validator.errors.length > 1) { console.error("Errors", validator.errors); } @@ -806,8 +803,8 @@ function testValidator( } catch (e) { throw new Error( `Expected error ${expectedError.name} but got '` + - validator.errors.join(",") + - "'", + validator.errors.join(",") + + "'", ); } } else { @@ -816,13 +813,9 @@ function testValidator( "Didn't expect any errors but got " + validator.errors.join("\n"), ); } - // if (expectedLocalSymbolTable != undefined) { - // expect(validator.localSymbolTable).toEqual(expectedLocalSymbolTable) - // } } -//TODO: add validation for assgining from void function call -//TODO: Add rule to forbid var use before assignment + /** * TODO: * Ideas for improvement - @@ -831,4 +824,6 @@ function testValidator( * - Expected subroutine name in call * - a numeric value is illegal here when using non numeric vars * - validate function call - when using literal in call validate the type + * add validation for assigning from void function call + * add rule to forbid var use before assignment */ diff --git a/simulator/src/jack/parser.test.ts b/simulator/src/jack/parser.test.ts index 73e22789..3de130d1 100644 --- a/simulator/src/jack/parser.test.ts +++ b/simulator/src/jack/parser.test.ts @@ -10,7 +10,7 @@ import { } from "./test.helper"; import { BinderListener } from "./listener/binder.listener"; -describe("Parser", () => { +describe("Jack parser", () => { const jestConsole = console; beforeEach(() => { global.console = require("console"); diff --git a/simulator/src/jack/symbol.table.test.ts b/simulator/src/jack/symbol.table.test.ts index 97ca4b80..021c21c5 100644 --- a/simulator/src/jack/symbol.table.test.ts +++ b/simulator/src/jack/symbol.table.test.ts @@ -5,7 +5,7 @@ import { SubroutineScope, } from "./symbol"; -describe("LocalSymbolTable", () => { +describe("Jack local symbol table", () => { const jestConsole = console; beforeEach(() => { From 375001dc1e67e3aa71c852c89a9855680e3d3646 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:16:49 +0200 Subject: [PATCH 39/87] WIP --- .../jack/listener/validator.listener.test.ts | 39 +++++++++---------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index 33c58436..18b603b3 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -119,7 +119,7 @@ describe("Jack validator listener", () => { }`, UndeclaredVariableError, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 1), "Main.a": genericSymbol(SubroutineType.Function, 1), }, @@ -468,7 +468,7 @@ describe("Jack validator listener", () => { }`, IncorrectParamsNumberInSubroutineCallError, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 2), "Main.b": genericSymbol(SubroutineType.Function, 2), }, @@ -494,7 +494,7 @@ describe("Jack validator listener", () => { }`, undefined, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), "Main.a": genericSymbol(SubroutineType.Function, 0), "Main.b": genericSymbol(SubroutineType.Method, 0), @@ -515,7 +515,7 @@ describe("Jack validator listener", () => { }`, undefined, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Method, 0), "Main.b": genericSymbol(SubroutineType.Method, 0), }, @@ -539,7 +539,7 @@ describe("Jack validator listener", () => { }`, MethodCalledAsFunctionError, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), "Main.c": genericSymbol(SubroutineType.Method, 0), }, @@ -559,7 +559,7 @@ describe("Jack validator listener", () => { }`, FunctionCalledAsMethodError, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), "Main.c": genericSymbol(SubroutineType.Function, 0), }, @@ -575,7 +575,7 @@ describe("Jack validator listener", () => { }`, IncorrectConstructorReturnType, { - "Main": genericSymbol(), + Main: genericSymbol(), D: genericSymbol(), }, ); @@ -593,7 +593,7 @@ describe("Jack validator listener", () => { }`, UnreachableCodeError, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), }, ); @@ -608,7 +608,7 @@ describe("Jack validator listener", () => { }`, ConstructorMushReturnThis, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), }, ); @@ -625,7 +625,7 @@ describe("Jack validator listener", () => { }`, WrongLiteralTypeError, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), String: genericSymbol(), }, @@ -643,7 +643,7 @@ describe("Jack validator listener", () => { }`, WrongLiteralTypeError, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -661,7 +661,7 @@ describe("Jack validator listener", () => { }`, WrongLiteralTypeError, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -678,7 +678,7 @@ describe("Jack validator listener", () => { }`, IntLiteralOverflow, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -695,7 +695,7 @@ describe("Jack validator listener", () => { }`, IntLiteralOverflow, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -712,7 +712,7 @@ describe("Jack validator listener", () => { }`, FieldCantBeReferencedInFunction, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -729,7 +729,7 @@ describe("Jack validator listener", () => { }`, undefined, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -746,7 +746,7 @@ describe("Jack validator listener", () => { }`, ThisCantBeReferencedInFunction, { - "Main": genericSymbol(), + Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), }, ); @@ -803,8 +803,8 @@ function testValidator( } catch (e) { throw new Error( `Expected error ${expectedError.name} but got '` + - validator.errors.join(",") + - "'", + validator.errors.join(",") + + "'", ); } } else { @@ -815,7 +815,6 @@ function testValidator( } } - /** * TODO: * Ideas for improvement - From a170adf9b9e58d159e567e53a34322371d8379d8 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 09:57:22 +0200 Subject: [PATCH 40/87] Fix bug - when creating new file there is an error --- components/src/stores/compiler.store.ts | 52 ++++++++++--------- .../src/jack/listener/validator.listener.ts | 2 +- web/src/pages/compiler.tsx | 2 +- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/components/src/stores/compiler.store.ts b/components/src/stores/compiler.store.ts index a15086e0..34021f5b 100644 --- a/components/src/stores/compiler.store.ts +++ b/components/src/stores/compiler.store.ts @@ -30,7 +30,9 @@ export type CompilerStoreDispatch = Dispatch<{ function classTemplate(name: string) { return `class ${name} {\n\n}\n`; } - +interface FileEntry { + name: string; content: string +} export function makeCompilerStore( setStatus: Action, dispatch: MutableRefObject, @@ -48,9 +50,15 @@ export function makeCompilerStore( setFile( state: CompilerPageState, - { name, content }: { name: string; content: string }, + { name, content }: FileEntry, ) { state.files[name] = content; + state.isCompiled = false; + }, + setFileAndValidate(state: CompilerPageState, + entry: FileEntry,) { + this.setFile(state, entry); + this.validate(state); }, // the keys of 'files' have to be the full file path, not basename @@ -59,12 +67,9 @@ export function makeCompilerStore( state.isCompiled = false; this.compile(state); }, - - validate(state: CompilerPageState) { - state.isCompiled = false; - const compiledFiles = validate(state.files); + _processCompilationResults(state: CompilerPageState, files: Record) { state.compiled = {}; - for (const [name, compiled] of Object.entries(compiledFiles)) { + for (const [name, compiled] of Object.entries(files)) { if (typeof compiled === "string") { state.compiled[name] = { valid: true, @@ -81,25 +86,14 @@ export function makeCompilerStore( (file) => state.compiled[file].valid, ); }, + validate(state: CompilerPageState) { + state.isCompiled = false; + this._processCompilationResults(state, validate(state.files)) + }, + compile(state: CompilerPageState) { - const compiledFiles = compile(state.files); - state.compiled = {}; - for (const [name, compiled] of Object.entries(compiledFiles)) { - if (typeof compiled === "string") { - state.compiled[name] = { - valid: true, - vm: compiled, - }; - } else { - state.compiled[name] = { - valid: false, - error: compiled, - }; - } - } - state.isValid = Object.keys(state.files).every( - (file) => state.compiled[file].valid, - ); + state.isCompiled = false; + this._processCompilationResults(state, compile(state.files)); }, writeCompiled(state: CompilerPageState) { @@ -155,6 +149,13 @@ export function makeCompilerStore( await fs.writeFile(`${name}.jack`, content); } }, + async writeNewFile(name: string, content?: string) { + content ??= classTemplate(name); + dispatch.current({ action: "setFileAndValidate", payload: { name, content } }); + if (fs) { + await fs.writeFile(`${name}.jack`, content); + } + }, async reset() { fs = undefined; @@ -162,6 +163,7 @@ export function makeCompilerStore( }, async compile() { + dispatch.current({ action: "compile" }); dispatch.current({ action: "writeCompiled" }); }, async validate() { diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index d2ccb209..4b002403 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -158,7 +158,7 @@ export class ValidatorListener extends JackParserListener { }; /** - * Var name when using it - do Statement, let ... as opposed to varNameInDeclaration + * Var name when doing some actions - do statement, let ... We have a different rule for a var name that is used in declaration */ override enterVarName = (ctx: VarNameContext) => { const symbol = this.localSymbolTable.lookup(ctx.getText()); diff --git a/web/src/pages/compiler.tsx b/web/src/pages/compiler.tsx index 124082cd..aac814c9 100644 --- a/web/src/pages/compiler.tsx +++ b/web/src/pages/compiler.tsx @@ -129,7 +129,7 @@ export const Compiler = () => { const onCreateFile = async (name?: string) => { if (name) { - await actions.writeFile(name); + await actions.writeNewFile(name); onSelect(name); setSuppressStatus(false); } From aa8a8ca3fd0649d03676265089a28f164508a04a Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:44:24 +0200 Subject: [PATCH 41/87] Fix incorrect error message --- simulator/src/jack/error.ts | 15 ++- .../src/jack/listener/binder.listener.test.ts | 113 +++++++----------- .../src/jack/listener/binder.listener.ts | 6 +- 3 files changed, 62 insertions(+), 72 deletions(-) diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 983fb7bc..2bc97fa2 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,3 +1,5 @@ +import { ClassNameContext } from "./generated/JackParser"; + export interface Span { start: number; end: number; @@ -29,10 +31,21 @@ export class DuplicatedSubroutineError extends JackCompilerError { endIndex: number, subroutineName: string, ) { - super(line, startInd, endIndex, `Subroutine ${subroutineName} redeclared.`); + super(line, startInd, endIndex, `Subroutine ${subroutineName} is already defined.`); + } +} +export class DuplicatedClassError extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + className: string, + ) { + super(line, startInd, endIndex, `Class ${ClassNameContext} is already defined.`); } } + export class DuplicatedVariableException extends JackCompilerError { constructor( line: number, diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/binder.listener.test.ts index 6c9769ff..ffda3ef1 100644 --- a/simulator/src/jack/listener/binder.listener.test.ts +++ b/simulator/src/jack/listener/binder.listener.test.ts @@ -1,8 +1,9 @@ import fs from "fs"; import path from "path"; -import { DuplicatedSubroutineError } from "../error"; +import { DuplicatedClassError, DuplicatedSubroutineError } from "../error"; import { BinderListener } from "./binder.listener"; -import { createSubroutineSymbol, SubroutineType } from "../symbol"; +import { createSubroutineSymbol, GlobalSymbolTable, SubroutineType } from "../symbol"; +import { builtInSymbols, builtInClassesRecord } from "../builtins"; import { getTestResourcePath, listenToTheTree, @@ -31,76 +32,26 @@ describe("Jack binder", () => { return 1; } }`; - const tree = parseJackText(input); - const globalSymbolsListener = new BinderListener(); - listenToTheTree(tree, globalSymbolsListener); - const symbolsErrors = globalSymbolsListener.errors; - expect(globalSymbolsListener.errors.length).toBe(1); - expect(symbolsErrors[0]).toBeInstanceOf(DuplicatedSubroutineError); + testBinder(input, DuplicatedSubroutineError) }); + test("duplicated class", () => { + const input = ` + class A { + }`; + const binder = new BinderListener(); + testBinder(input, undefined, binder); + testBinder(input, DuplicatedClassError, binder); + }); + test("duplicated built in class", () => { + const input = ` + class Math { + }`; + testBinder(input, DuplicatedClassError); + }); test("basic", () => { const expected = { - //built in classes - Array: {}, - Keyboard: {}, - Math: {}, - Memory: {}, - Output: {}, - Screen: {}, - String: {}, - Sys: {}, - "Array.dispose": createSubroutineSymbol(0, SubroutineType.Function), - "Array.new": createSubroutineSymbol(1, SubroutineType.Function), - "Keyboard.init": createSubroutineSymbol(0, SubroutineType.Function), - "Keyboard.keyPressed": createSubroutineSymbol(0, SubroutineType.Function), - "Keyboard.readChar": createSubroutineSymbol(0, SubroutineType.Function), - "Keyboard.readInt": createSubroutineSymbol(1, SubroutineType.Function), - "Keyboard.readLine": createSubroutineSymbol(1, SubroutineType.Function), - "Math.abs": createSubroutineSymbol(1, SubroutineType.Function), - "Math.divide": createSubroutineSymbol(2, SubroutineType.Function), - "Math.max": createSubroutineSymbol(2, SubroutineType.Function), - "Math.min": createSubroutineSymbol(2, SubroutineType.Function), - "Math.multiply": createSubroutineSymbol(2, SubroutineType.Function), - "Math.sqrt": createSubroutineSymbol(1, SubroutineType.Function), - "Memory.alloc": createSubroutineSymbol(1, SubroutineType.Function), - "Memory.deAlloc": createSubroutineSymbol(1, SubroutineType.Function), - "Memory.peek": createSubroutineSymbol(1, SubroutineType.Function), - "Memory.poke": createSubroutineSymbol(2, SubroutineType.Function), - "Output.backSpace": createSubroutineSymbol(0, SubroutineType.Function), - "Output.moveCursor": createSubroutineSymbol(2, SubroutineType.Function), - "Output.printChar": createSubroutineSymbol(1, SubroutineType.Function), - "Output.printInt": createSubroutineSymbol(1, SubroutineType.Function), - "Output.println": createSubroutineSymbol(0, SubroutineType.Function), - "Output.printString": createSubroutineSymbol(1, SubroutineType.Function), - "Screen.clearScreen": createSubroutineSymbol(0, SubroutineType.Function), - "Screen.drawCircle": createSubroutineSymbol(3, SubroutineType.Function), - "Screen.drawLine": createSubroutineSymbol(4, SubroutineType.Function), - "Screen.drawPixel": createSubroutineSymbol(2, SubroutineType.Function), - "Screen.drawRectangle": createSubroutineSymbol( - 4, - SubroutineType.Function, - ), - "Screen.setColor": createSubroutineSymbol(1, SubroutineType.Function), - "String.appendChar": createSubroutineSymbol(1, SubroutineType.Function), - "String.backSpace": createSubroutineSymbol(0, SubroutineType.Function), - "String.charAt": createSubroutineSymbol(2, SubroutineType.Function), - "String.dispose": createSubroutineSymbol(0, SubroutineType.Function), - "String.doubleQuote": createSubroutineSymbol(0, SubroutineType.Function), - "String.eraseLastChar": createSubroutineSymbol( - 0, - SubroutineType.Function, - ), - "String.intValue": createSubroutineSymbol(0, SubroutineType.Function), - "String.length": createSubroutineSymbol(0, SubroutineType.Function), - "String.new": createSubroutineSymbol(1, SubroutineType.Function), - "String.newLine": createSubroutineSymbol(0, SubroutineType.Function), - "String.setCharAt": createSubroutineSymbol(1, SubroutineType.Function), - "String.setInt": createSubroutineSymbol(1, SubroutineType.Function), - "Sys.error": createSubroutineSymbol(1, SubroutineType.Function), - "Sys.halt": createSubroutineSymbol(0, SubroutineType.Function), - "Sys.wait": createSubroutineSymbol(1, SubroutineType.Function), - //test files symbols + ...builtInSymbols, Fraction: {}, "Fraction.new": createSubroutineSymbol(2, SubroutineType.Constructor, 0), "Fraction.reduce": createSubroutineSymbol(0, SubroutineType.Method, 1), @@ -136,3 +87,29 @@ describe("Jack binder", () => { expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); }); }); +function testBinder(input: string, expectedError?: T, binder = new BinderListener()) { + const tree = parseJackText(input); + listenToTheTree(tree, binder); + const errors = binder.errors; + if (expectedError) { + if (errors.length > 1) { + console.error("Errors", errors); + } + try { + expect(errors.length).toBe(1); + expect(errors[0]).toBeInstanceOf(expectedError); + } catch (e) { + throw new Error( + `Expected error ${expectedError.name} but got '` + + errors.join(",") + + "'", + ); + } + } else { + if (errors.length != 0) + throw new Error( + "Didn't expect any errors but got " + errors.join("\n"), + ); + } + +} \ No newline at end of file diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts index 8adca608..d0898bde 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/binder.listener.ts @@ -4,7 +4,7 @@ import { SubroutineDeclarationContext, VarNameInDeclarationContext, } from "../generated/JackParser.js"; -import { DuplicatedSubroutineError } from "../error.js"; +import { DuplicatedClassError, DuplicatedSubroutineError } from "../error.js"; import { builtInSymbols, builtInTypes } from "../builtins.js"; import { GenericSymbol, @@ -33,11 +33,11 @@ export class BinderListener extends JackParserListener { const className = ctx.className()!.IDENTIFIER().getText(); if (this.globalSymbolTable[className] != undefined) { this.errors.push( - new DuplicatedSubroutineError( + new DuplicatedClassError( ctx.start.line, ctx.start.start, ctx.start.stop, - `Class "${className}" is already defined.`, + className ), ); return; From 4a51cafec2aa587a3d5392f006b9fa701bc174e8 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:49:16 +0200 Subject: [PATCH 42/87] WIP --- simulator/src/jack/error.ts | 2 +- simulator/src/jack/listener/binder.listener.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 2bc97fa2..68cf4301 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,4 +1,4 @@ -import { ClassNameContext } from "./generated/JackParser"; +import { ClassNameContext } from "./generated/JackParser.js"; export interface Span { start: number; diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/binder.listener.test.ts index ffda3ef1..f0cfe979 100644 --- a/simulator/src/jack/listener/binder.listener.test.ts +++ b/simulator/src/jack/listener/binder.listener.test.ts @@ -2,8 +2,8 @@ import fs from "fs"; import path from "path"; import { DuplicatedClassError, DuplicatedSubroutineError } from "../error"; import { BinderListener } from "./binder.listener"; -import { createSubroutineSymbol, GlobalSymbolTable, SubroutineType } from "../symbol"; -import { builtInSymbols, builtInClassesRecord } from "../builtins"; +import { createSubroutineSymbol, SubroutineType } from "../symbol"; +import { builtInSymbols } from "../builtins"; import { getTestResourcePath, listenToTheTree, From ae414f24868862941069a8d4a48158fb4c1ac75e Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:52:01 +0200 Subject: [PATCH 43/87] WIP --- components/src/stores/compiler.store.ts | 23 +++++++++++-------- simulator/src/jack/error.ts | 15 +++++++++--- .../src/jack/listener/binder.listener.test.ts | 19 +++++++-------- .../src/jack/listener/binder.listener.ts | 2 +- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/components/src/stores/compiler.store.ts b/components/src/stores/compiler.store.ts index 34021f5b..2e57862f 100644 --- a/components/src/stores/compiler.store.ts +++ b/components/src/stores/compiler.store.ts @@ -31,7 +31,8 @@ function classTemplate(name: string) { return `class ${name} {\n\n}\n`; } interface FileEntry { - name: string; content: string + name: string; + content: string; } export function makeCompilerStore( setStatus: Action, @@ -48,15 +49,11 @@ export function makeCompilerStore( state.title = undefined; }, - setFile( - state: CompilerPageState, - { name, content }: FileEntry, - ) { + setFile(state: CompilerPageState, { name, content }: FileEntry) { state.files[name] = content; state.isCompiled = false; }, - setFileAndValidate(state: CompilerPageState, - entry: FileEntry,) { + setFileAndValidate(state: CompilerPageState, entry: FileEntry) { this.setFile(state, entry); this.validate(state); }, @@ -67,7 +64,10 @@ export function makeCompilerStore( state.isCompiled = false; this.compile(state); }, - _processCompilationResults(state: CompilerPageState, files: Record) { + _processCompilationResults( + state: CompilerPageState, + files: Record, + ) { state.compiled = {}; for (const [name, compiled] of Object.entries(files)) { if (typeof compiled === "string") { @@ -88,7 +88,7 @@ export function makeCompilerStore( }, validate(state: CompilerPageState) { state.isCompiled = false; - this._processCompilationResults(state, validate(state.files)) + this._processCompilationResults(state, validate(state.files)); }, compile(state: CompilerPageState) { @@ -151,7 +151,10 @@ export function makeCompilerStore( }, async writeNewFile(name: string, content?: string) { content ??= classTemplate(name); - dispatch.current({ action: "setFileAndValidate", payload: { name, content } }); + dispatch.current({ + action: "setFileAndValidate", + payload: { name, content }, + }); if (fs) { await fs.writeFile(`${name}.jack`, content); } diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 68cf4301..36590ab2 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -31,7 +31,12 @@ export class DuplicatedSubroutineError extends JackCompilerError { endIndex: number, subroutineName: string, ) { - super(line, startInd, endIndex, `Subroutine ${subroutineName} is already defined.`); + super( + line, + startInd, + endIndex, + `Subroutine ${subroutineName} is already defined.`, + ); } } export class DuplicatedClassError extends JackCompilerError { @@ -41,11 +46,15 @@ export class DuplicatedClassError extends JackCompilerError { endIndex: number, className: string, ) { - super(line, startInd, endIndex, `Class ${ClassNameContext} is already defined.`); + super( + line, + startInd, + endIndex, + `Class ${ClassNameContext} is already defined.`, + ); } } - export class DuplicatedVariableException extends JackCompilerError { constructor( line: number, diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/binder.listener.test.ts index f0cfe979..996c8cc6 100644 --- a/simulator/src/jack/listener/binder.listener.test.ts +++ b/simulator/src/jack/listener/binder.listener.test.ts @@ -32,7 +32,7 @@ describe("Jack binder", () => { return 1; } }`; - testBinder(input, DuplicatedSubroutineError) + testBinder(input, DuplicatedSubroutineError); }); test("duplicated class", () => { @@ -87,7 +87,11 @@ describe("Jack binder", () => { expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); }); }); -function testBinder(input: string, expectedError?: T, binder = new BinderListener()) { +function testBinder( + input: string, + expectedError?: T, + binder = new BinderListener(), +) { const tree = parseJackText(input); listenToTheTree(tree, binder); const errors = binder.errors; @@ -101,15 +105,12 @@ function testBinder(input: string, expectedError?: T } catch (e) { throw new Error( `Expected error ${expectedError.name} but got '` + - errors.join(",") + - "'", + errors.join(",") + + "'", ); } } else { if (errors.length != 0) - throw new Error( - "Didn't expect any errors but got " + errors.join("\n"), - ); + throw new Error("Didn't expect any errors but got " + errors.join("\n")); } - -} \ No newline at end of file +} diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts index d0898bde..df5e6ef7 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/binder.listener.ts @@ -37,7 +37,7 @@ export class BinderListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - className + className, ), ); return; From 771c2cd78facb32ea54a40c3ef6ed4209d078df3 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:04:11 +0200 Subject: [PATCH 44/87] Bug fixes --- simulator/package.json | 2 +- simulator/src/jack/compiler.ts | 14 +++++------ simulator/src/jack/error.ts | 24 +++++++++++++++---- .../src/jack/listener/binder.listener.ts | 16 ++++++------- .../jack/listener/validator.listener.test.ts | 23 ++++++++++++------ .../src/jack/listener/validator.listener.ts | 14 ++++++++++- 6 files changed, 64 insertions(+), 29 deletions(-) diff --git a/simulator/package.json b/simulator/package.json index cbdc9e86..00b7e2b7 100644 --- a/simulator/package.json +++ b/simulator/package.json @@ -40,6 +40,6 @@ "test-w": "jest --watchAll --verbose", "test-jack": "npm run test -- -t \"Jack\"", "test-jack-w": "npm run test-w -- -t \"Jack\"", - "gen": "cd src/languages/grammars && antlr4 -Dlanguage=TypeScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" + "gen": "cd src/languages/grammars && antlr4 -v 4.13.2 -Dlanguage=JavaScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" } } diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index d5222f67..8ac8357e 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -72,7 +72,7 @@ function _do( let compiledOrValidatedOrErrors; switch (cmd) { case Command.Compile: - compiledOrValidatedOrErrors = compiler.compile(tree); + compiledOrValidatedOrErrors = compiler.compile(tree, name); if (Array.isArray(compiledOrValidatedOrErrors)) { result[name] = toCompilerError(compiledOrValidatedOrErrors); @@ -81,7 +81,7 @@ function _do( } break; case Command.Validate: - compiledOrValidatedOrErrors = compiler.validate(tree); + compiledOrValidatedOrErrors = compiler.validate(tree, name); if (Array.isArray(compiledOrValidatedOrErrors)) { result[name] = toCompilerError(compiledOrValidatedOrErrors); } else { @@ -105,19 +105,19 @@ function toCompilerError(errors: JackCompilerError[]): CompilationError { export class Compiler { private binder = new BinderListener(); private errorListener = new CustomErrorListener(); - validate(tree: ProgramContext): ProgramContext | JackCompilerError[] { + validate(tree: ProgramContext, filename?: string): ProgramContext | JackCompilerError[] { if (Object.keys(this.binder.globalSymbolTable).length == 0) { throw new Error( "Please populate global symbol table using parserAndBind method", ); } - const validator = new ValidatorListener(this.binder.globalSymbolTable); + const validator = new ValidatorListener(this.binder.globalSymbolTable, filename); ParseTreeWalker.DEFAULT.walk(validator, tree); - return tree; + return validator.errors.length > 0 ? validator.errors : tree; } - compile(tree: ProgramContext): string | JackCompilerError[] { - const treeOrErrors = this.validate(tree); + compile(tree: ProgramContext, filename?: string,): string | JackCompilerError[] { + const treeOrErrors = this.validate(tree, filename); if (Array.isArray(treeOrErrors)) { const errors = treeOrErrors as JackCompilerError[]; console.log("Errors in validator " + JSON.stringify(errors)); diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 36590ab2..98191e85 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,5 +1,3 @@ -import { ClassNameContext } from "./generated/JackParser.js"; - export interface Span { start: number; end: number; @@ -23,7 +21,7 @@ export class JackCompilerError { }; } -export class LexerOrParserError extends JackCompilerError {} +export class LexerOrParserError extends JackCompilerError { } export class DuplicatedSubroutineError extends JackCompilerError { constructor( line: number, @@ -50,7 +48,23 @@ export class DuplicatedClassError extends JackCompilerError { line, startInd, endIndex, - `Class ${ClassNameContext} is already defined.`, + `Class ${className} is already defined.`, + ); + } +} +export class FilenameDoesntMatchClassName extends JackCompilerError { + constructor( + line: number, + startInd: number, + endIndex: number, + filename: string, + className: string, + ) { + super( + line, + startInd, + endIndex, + `Class name ${className} doesn't match file name ${filename}`, ); } } @@ -67,7 +81,7 @@ export class DuplicatedVariableException extends JackCompilerError { startInd, endIndex, "Duplicated local variable, field, argument or static variable " + - variableName, + variableName, ); } } diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts index df5e6ef7..e51a6e4a 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/binder.listener.ts @@ -30,16 +30,16 @@ export class BinderListener extends JackParserListener { private subroutineId = ""; override enterClassDeclaration = (ctx: ClassDeclarationContext) => { - const className = ctx.className()!.IDENTIFIER().getText(); + const id = ctx.className()!.IDENTIFIER(); + const className = id.getText(); if (this.globalSymbolTable[className] != undefined) { - this.errors.push( - new DuplicatedClassError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - className, - ), + const e = new DuplicatedClassError( + ctx.className()!.start.line, + ctx.className()!.start.start, + ctx.className()!.stop.stop+1, + className, ); + this.errors.push(e); return; } this.globalSymbolTable[className] = {} as GenericSymbol; diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index 18b603b3..390b27ce 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -2,6 +2,7 @@ import { ConstructorMushReturnThis, DuplicatedVariableException as DuplicatedVariableError, FieldCantBeReferencedInFunction, + FilenameDoesntMatchClassName, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, @@ -751,6 +752,16 @@ describe("Jack validator listener", () => { }, ); }); + test("class name doesn't match filename", () => { + testValidator( + `class A {}`, + FilenameDoesntMatchClassName, + { + A: genericSymbol(), + }, + "B" + ); + }); //validate files test.concurrent.each(testResourceDirs)("%s", (dir: string) => { @@ -785,14 +796,12 @@ function testValidator( src: string, expectedError?: T, globalSymbolTable: Record = {}, + filename?: string ) { const errorListener = new CustomErrorListener(); const tree = parseJackText(src, errorListener); - - const validator = listenToTheTree( - tree, - new ValidatorListener(globalSymbolTable), - ); + const listener = filename != null ? new ValidatorListener(globalSymbolTable, filename) : new ValidatorListener(globalSymbolTable); + const validator = listenToTheTree(tree, listener); if (expectedError) { if (validator.errors.length > 1) { console.error("Errors", validator.errors); @@ -803,8 +812,8 @@ function testValidator( } catch (e) { throw new Error( `Expected error ${expectedError.name} but got '` + - validator.errors.join(",") + - "'", + validator.errors.join(",") + + "'", ); } } else { diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 4b002403..a8386825 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -4,6 +4,7 @@ import { ConstructorMushReturnThis, DuplicatedVariableException, FieldCantBeReferencedInFunction, + FilenameDoesntMatchClassName, FunctionCalledAsMethodError, IncorrectConstructorReturnType, IncorrectParamsNumberInSubroutineCallError, @@ -62,6 +63,7 @@ export class ValidatorListener extends JackParserListener { private subroutineType?: SubroutineType; constructor( private globalSymbolTable: Record, + private filename?: string, public errors: JackCompilerError[] = [], ) { super(); @@ -73,6 +75,16 @@ export class ValidatorListener extends JackParserListener { throw new Error("Cannot change class name"); } this.className = newName; + console.log("Filename", this.filename != null, this.filename != this.className); + if (this.filename != null && this.filename != this.className) { + console.error("FilenameDoesntMatchClassName") + this.errors.push(new FilenameDoesntMatchClassName(ctx.start.line, + ctx.start.start, + ctx.start.stop, + this.filename, + this.className, + )); + } ctx.localSymbolTable = this.localSymbolTable; }; @@ -521,7 +533,7 @@ class BinaryTreeNode { public parent?: BinaryTreeNode, public left?: BinaryTreeNode, public right?: BinaryTreeNode, - ) {} + ) { } public get returns(): boolean { if (this._returns) { From d92b385c38fe410835dd8350a71274dc1d82f35a Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:05:13 +0200 Subject: [PATCH 45/87] WIP --- simulator/src/jack/compiler.ts | 15 ++++++++--- simulator/src/jack/error.ts | 11 +++----- .../src/jack/listener/binder.listener.ts | 2 +- .../jack/listener/validator.listener.test.ts | 13 ++++++---- .../src/jack/listener/validator.listener.ts | 25 ++++++++++++------- 5 files changed, 40 insertions(+), 26 deletions(-) diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index 8ac8357e..f8f10262 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -105,18 +105,27 @@ function toCompilerError(errors: JackCompilerError[]): CompilationError { export class Compiler { private binder = new BinderListener(); private errorListener = new CustomErrorListener(); - validate(tree: ProgramContext, filename?: string): ProgramContext | JackCompilerError[] { + validate( + tree: ProgramContext, + filename?: string, + ): ProgramContext | JackCompilerError[] { if (Object.keys(this.binder.globalSymbolTable).length == 0) { throw new Error( "Please populate global symbol table using parserAndBind method", ); } - const validator = new ValidatorListener(this.binder.globalSymbolTable, filename); + const validator = new ValidatorListener( + this.binder.globalSymbolTable, + filename, + ); ParseTreeWalker.DEFAULT.walk(validator, tree); return validator.errors.length > 0 ? validator.errors : tree; } - compile(tree: ProgramContext, filename?: string,): string | JackCompilerError[] { + compile( + tree: ProgramContext, + filename?: string, + ): string | JackCompilerError[] { const treeOrErrors = this.validate(tree, filename); if (Array.isArray(treeOrErrors)) { const errors = treeOrErrors as JackCompilerError[]; diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 98191e85..9f2a3684 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -21,7 +21,7 @@ export class JackCompilerError { }; } -export class LexerOrParserError extends JackCompilerError { } +export class LexerOrParserError extends JackCompilerError {} export class DuplicatedSubroutineError extends JackCompilerError { constructor( line: number, @@ -44,12 +44,7 @@ export class DuplicatedClassError extends JackCompilerError { endIndex: number, className: string, ) { - super( - line, - startInd, - endIndex, - `Class ${className} is already defined.`, - ); + super(line, startInd, endIndex, `Class ${className} is already defined.`); } } export class FilenameDoesntMatchClassName extends JackCompilerError { @@ -81,7 +76,7 @@ export class DuplicatedVariableException extends JackCompilerError { startInd, endIndex, "Duplicated local variable, field, argument or static variable " + - variableName, + variableName, ); } } diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts index e51a6e4a..497d94f9 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/binder.listener.ts @@ -36,7 +36,7 @@ export class BinderListener extends JackParserListener { const e = new DuplicatedClassError( ctx.className()!.start.line, ctx.className()!.start.start, - ctx.className()!.stop.stop+1, + ctx.className()!.stop.stop + 1, className, ); this.errors.push(e); diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index 390b27ce..86818398 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -759,7 +759,7 @@ describe("Jack validator listener", () => { { A: genericSymbol(), }, - "B" + "B", ); }); @@ -796,11 +796,14 @@ function testValidator( src: string, expectedError?: T, globalSymbolTable: Record = {}, - filename?: string + filename?: string, ) { const errorListener = new CustomErrorListener(); const tree = parseJackText(src, errorListener); - const listener = filename != null ? new ValidatorListener(globalSymbolTable, filename) : new ValidatorListener(globalSymbolTable); + const listener = + filename != null + ? new ValidatorListener(globalSymbolTable, filename) + : new ValidatorListener(globalSymbolTable); const validator = listenToTheTree(tree, listener); if (expectedError) { if (validator.errors.length > 1) { @@ -812,8 +815,8 @@ function testValidator( } catch (e) { throw new Error( `Expected error ${expectedError.name} but got '` + - validator.errors.join(",") + - "'", + validator.errors.join(",") + + "'", ); } } else { diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index a8386825..16ca74c1 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -75,15 +75,22 @@ export class ValidatorListener extends JackParserListener { throw new Error("Cannot change class name"); } this.className = newName; - console.log("Filename", this.filename != null, this.filename != this.className); + console.log( + "Filename", + this.filename != null, + this.filename != this.className, + ); if (this.filename != null && this.filename != this.className) { - console.error("FilenameDoesntMatchClassName") - this.errors.push(new FilenameDoesntMatchClassName(ctx.start.line, - ctx.start.start, - ctx.start.stop, - this.filename, - this.className, - )); + console.error("FilenameDoesntMatchClassName"); + this.errors.push( + new FilenameDoesntMatchClassName( + ctx.start.line, + ctx.start.start, + ctx.start.stop, + this.filename, + this.className, + ), + ); } ctx.localSymbolTable = this.localSymbolTable; }; @@ -533,7 +540,7 @@ class BinaryTreeNode { public parent?: BinaryTreeNode, public left?: BinaryTreeNode, public right?: BinaryTreeNode, - ) { } + ) {} public get returns(): boolean { if (this._returns) { From 4ae599786800a81f8be2f3d3b6c8a0d222b246b3 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:07:37 +0200 Subject: [PATCH 46/87] WIP --- simulator/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulator/package.json b/simulator/package.json index 00b7e2b7..bb0ce903 100644 --- a/simulator/package.json +++ b/simulator/package.json @@ -40,6 +40,6 @@ "test-w": "jest --watchAll --verbose", "test-jack": "npm run test -- -t \"Jack\"", "test-jack-w": "npm run test-w -- -t \"Jack\"", - "gen": "cd src/languages/grammars && antlr4 -v 4.13.2 -Dlanguage=JavaScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" + "gen": "cd src/languages/grammars && antlr4 -v 4.13.2 -Dlanguage=TypeScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" } } From d5c7f270b8590b2d2008958a93cd6bb665c9e482 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:25:41 +0200 Subject: [PATCH 47/87] WIP --- simulator/src/jack/listener/binder.listener.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts index 497d94f9..3ec21f7a 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/binder.listener.ts @@ -36,7 +36,7 @@ export class BinderListener extends JackParserListener { const e = new DuplicatedClassError( ctx.className()!.start.line, ctx.className()!.start.start, - ctx.className()!.stop.stop + 1, + ctx.className()!.stop!.stop + 1, className, ); this.errors.push(e); From f1c9ea33fe660d3da3950018a3339c80e9a5f873 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+RomanLukash340@users.noreply.github.com> Date: Fri, 4 Oct 2024 15:51:10 +0200 Subject: [PATCH 48/87] WIP --- simulator/src/jack/listener/binder.listener.ts | 1 + simulator/src/jack/listener/validator.listener.ts | 2 +- simulator/src/jack/listener/vm.writer.listener.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts index 3ec21f7a..7266e142 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/binder.listener.ts @@ -16,6 +16,7 @@ import JackParserListener from "../generated/JackParserListener.js"; const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; +/* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * Creates global symbol table that contains built-in functions and found classes and subroutines */ diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 16ca74c1..20c40fd7 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -49,7 +49,7 @@ import { SubroutineType, } from "../symbol.js"; import { CallType, getCallType } from "./common.js"; - +/* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * Validates Jack file */ diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index e883c22c..cdad0911 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -40,7 +40,7 @@ const unaryOperationToVmCmd: Record = { "-": "neg", "~": "not", }; - +/* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * Transforms parse tree into VM code */ From 560f04363ea5ff238f4234418b5eff03d739c684 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:31:39 +0200 Subject: [PATCH 49/87] WIP --- components/src/stores/compiler.store.ts | 3 + package-lock.json | 93 +++++++++++++++++++ simulator/README.md | 10 +- .../src/jack/listener/validator.listener.ts | 60 ++++++------ 4 files changed, 132 insertions(+), 34 deletions(-) diff --git a/components/src/stores/compiler.store.ts b/components/src/stores/compiler.store.ts index 2e57862f..27e82112 100644 --- a/components/src/stores/compiler.store.ts +++ b/components/src/stores/compiler.store.ts @@ -53,6 +53,7 @@ export function makeCompilerStore( state.files[name] = content; state.isCompiled = false; }, + setFileAndValidate(state: CompilerPageState, entry: FileEntry) { this.setFile(state, entry); this.validate(state); @@ -64,6 +65,7 @@ export function makeCompilerStore( state.isCompiled = false; this.compile(state); }, + _processCompilationResults( state: CompilerPageState, files: Record, @@ -86,6 +88,7 @@ export function makeCompilerStore( (file) => state.compiled[file].valid, ); }, + validate(state: CompilerPageState) { state.isCompiled = false; this._processCompilationResults(state, validate(state.files)); diff --git a/package-lock.json b/package-lock.json index 3132a695..8b4d34ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "web" ], "devDependencies": { + "concurrently": "^9.0.1", "cross-env": "^7.0.3", "shx": "^0.3.4" }, @@ -5340,6 +5341,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/antlr4": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.2.tgz", + "integrity": "sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=16" + } + }, "node_modules/any-promise": { "version": "1.3.0", "license": "MIT" @@ -6679,6 +6689,78 @@ "version": "0.0.1", "license": "MIT" }, + "node_modules/concurrently": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.0.1.tgz", + "integrity": "sha512-wYKvCd/f54sTXJMSfV6Ln/B8UrfLBKOYa+lzc6CHay3Qek+LorVSBdMVfyewFhRbH0Rbabsk4D+3PL/VjQ5gzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "license": "MIT" @@ -20858,6 +20940,16 @@ "punycode": "^2.1.0" } }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "dev": true, @@ -22532,6 +22624,7 @@ "@nand2tetris/projects": "^1.0.0", "@nand2tetris/runner": "^1.0.0", "@types/node": "^20.14.2", + "antlr4": "^4.13.2", "ohm-js": "^17.1.0", "rxjs": "^7.8.1" }, diff --git a/simulator/README.md b/simulator/README.md index 31efb9ad..cc05af99 100644 --- a/simulator/README.md +++ b/simulator/README.md @@ -1,11 +1,13 @@ -To run +# Regenerate generated files Jack Lexer and Parser + +Next command gives us ability to regenerate parser and lexer after we've changed the grammar (.g4 files) for [lexer](src/languages/grammars/JackLexer.g4) or [parser](src/languages/grammars/JackParser.g4) ``` npm run gen ``` - -Install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md) +To run this command we would need to install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md) ``` pip install antlr4-tools -``` \ No newline at end of file +``` +Underneath the covers previous command will install Java runtime(JRE)(if you don't have java installed on your machine) and antlr4-{version}-complete.jar from maven. \ No newline at end of file diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 20c40fd7..8bff6342 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -109,7 +109,7 @@ export class ValidatorListener extends JackParserListener { .fieldList() .fieldName_list() .forEach((field) => { - this.#localSymbolTableAdd(ctx, scope, field.getText(), type); + this.localSymbolTableAdd(ctx, scope, field.getText(), type); }); }; override enterSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { @@ -119,7 +119,7 @@ export class ValidatorListener extends JackParserListener { ctx.subroutineDecWithoutType().subroutineReturnType().getText() !== this.className ) { - this.#addError( + this.addError( new IncorrectConstructorReturnType( ctx.start.line, ctx.start.start, @@ -145,7 +145,7 @@ export class ValidatorListener extends JackParserListener { }; override enterParameter = (ctx: ParameterContext) => { - this.#defineArgument( + this.defineArgument( ctx, ctx.parameterName().getText(), ctx.varType().getText(), @@ -157,7 +157,7 @@ export class ValidatorListener extends JackParserListener { if (ctx.IDENTIFIER() != null) { const type = ctx.IDENTIFIER()!.getText(); if (this.globalSymbolTable[type] == null) { - this.#addError( + this.addError( new UnknownClassError( ctx.start.line, ctx.start.start, @@ -172,7 +172,7 @@ export class ValidatorListener extends JackParserListener { override enterVarDeclaration = (ctx: VarDeclarationContext) => { const type = ctx.varType().getText(); ctx.varNameInDeclaration_list().forEach((name) => { - this.#localSymbolTableAdd(ctx, ScopeType.Local, name.getText(), type); + this.localSymbolTableAdd(ctx, ScopeType.Local, name.getText(), type); }); }; @@ -182,7 +182,7 @@ export class ValidatorListener extends JackParserListener { override enterVarName = (ctx: VarNameContext) => { const symbol = this.localSymbolTable.lookup(ctx.getText()); if (symbol == undefined) { - this.#addError( + this.addError( new UndeclaredVariableError( ctx.start.line, ctx.start.start, @@ -194,7 +194,7 @@ export class ValidatorListener extends JackParserListener { this.subroutineType == SubroutineType.Function && symbol.scope == ScopeType.This ) { - this.#addError( + this.addError( new FieldCantBeReferencedInFunction( ctx.start.line, ctx.start.start, @@ -209,7 +209,7 @@ export class ValidatorListener extends JackParserListener { ctx.THIS_LITERAL() != null && this.subroutineType == SubroutineType.Function ) { - this.#addError( + this.addError( new ThisCantBeReferencedInFunction( ctx.start.line, ctx.start.start, @@ -221,7 +221,7 @@ export class ValidatorListener extends JackParserListener { override enterStatement = (ctx: StatementContext) => { if (this.controlFlowGraphNode.returns == true) { - this.#addError( + this.addError( new UnreachableCodeError( ctx.start.line, ctx.start.start, @@ -282,7 +282,7 @@ export class ValidatorListener extends JackParserListener { case "char": case "int": if (constantCtx.INTEGER_LITERAL() === null) { - this.#addError( + this.addError( new WrongLiteralTypeError( ctx.start.line, ctx.start.start, @@ -293,7 +293,7 @@ export class ValidatorListener extends JackParserListener { } else { const value = parseInt(constantCtx.INTEGER_LITERAL()!.getText()); if (value > intRange.max) { - this.#addError( + this.addError( new IntLiteralIsOutOfRange( ctx.start.line, ctx.start.start, @@ -308,7 +308,7 @@ export class ValidatorListener extends JackParserListener { break; case "boolean": if (constantCtx.booleanLiteral() === null) { - this.#addError( + this.addError( new WrongLiteralTypeError( ctx.start.line, ctx.start.start, @@ -320,7 +320,7 @@ export class ValidatorListener extends JackParserListener { break; case "String": if (constantCtx.STRING_LITERAL() === null) { - this.#addError( + this.addError( new WrongLiteralTypeError( ctx.start.line, ctx.start.start, @@ -348,7 +348,7 @@ export class ValidatorListener extends JackParserListener { unaryOp!.expression().constant()!.INTEGER_LITERAL()!.getText(), ); if (-value < intRange.min) { - this.#addError( + this.addError( new IntLiteralIsOutOfRange( ctx.start.line, ctx.start.start, @@ -373,7 +373,7 @@ export class ValidatorListener extends JackParserListener { const symbol = this.globalSymbolTable[subroutineIdText]; if (symbol == undefined) { - this.#addError( + this.addError( new UnknownSubroutineCallError( ctx.start.line, ctx.start.start, @@ -388,7 +388,7 @@ export class ValidatorListener extends JackParserListener { symbol.subroutineInfo?.type == SubroutineType.Method && callType == CallType.ClassFunctionOrConstructor ) { - this.#addError( + this.addError( new MethodCalledAsFunctionError( ctx.start.line, ctx.start.start, @@ -402,7 +402,7 @@ export class ValidatorListener extends JackParserListener { symbol.subroutineInfo?.type == SubroutineType.Function && callType == CallType.LocalMethod ) { - this.#addError( + this.addError( new FunctionCalledAsMethodError( ctx.start.line, ctx.start.start, @@ -414,7 +414,7 @@ export class ValidatorListener extends JackParserListener { //check parameter count const l = ctx.expressionList().expression_list().length; if (symbol.subroutineInfo!.paramsCount != l) { - this.#addError( + this.addError( new IncorrectParamsNumberInSubroutineCallError( ctx.start.line, ctx.start.start, @@ -431,7 +431,7 @@ export class ValidatorListener extends JackParserListener { override enterReturnStatement = (ctx: ReturnStatementContext) => { const returnsVoid = ctx.expression() == null; if (returnsVoid && !this.subroutineShouldReturnVoidType) { - this.#addError( + this.addError( new NonVoidFunctionNoReturnError( ctx.stop!.line, ctx.stop!.start, @@ -440,7 +440,7 @@ export class ValidatorListener extends JackParserListener { ); } if (!returnsVoid && this.subroutineShouldReturnVoidType) { - this.#addError( + this.addError( new VoidSubroutineReturnsValueError( ctx.stop!.line, ctx.stop!.start, @@ -456,7 +456,7 @@ export class ValidatorListener extends JackParserListener { ctx.expression()!.constant() == null || ctx.expression()!.constant()!.THIS_LITERAL() == null ) { - this.#addError( + this.addError( new ConstructorMushReturnThis( ctx.stop!.line, ctx.stop!.start, @@ -469,7 +469,7 @@ export class ValidatorListener extends JackParserListener { override exitSubroutineBody = (ctx: SubroutineBodyContext) => { if (!this.controlFlowGraphNode.returns) { - this.#addError( + this.addError( new SubroutineNotAllPathsReturnError( ctx.stop!.line, ctx.stop!.start, @@ -491,14 +491,14 @@ export class ValidatorListener extends JackParserListener { }; //Utils - #defineArgument( + defineArgument( ctx: ParserRuleContext, name: string, type: string, inMethod: boolean, ) { if (this.localSymbolTable.lookup(name)) { - this.#addError( + this.addError( new DuplicatedVariableException( ctx.start.line, ctx.start.start, @@ -510,14 +510,14 @@ export class ValidatorListener extends JackParserListener { this.localSymbolTable.defineArgument(name, type, inMethod); } } - #localSymbolTableAdd( + localSymbolTableAdd( ctx: ParserRuleContext, scope: ScopeType, name: string, type: string, ) { if (this.localSymbolTable.lookup(name)) { - this.#addError( + this.addError( new DuplicatedVariableException( ctx.start.line, ctx.start.start, @@ -529,7 +529,7 @@ export class ValidatorListener extends JackParserListener { this.localSymbolTable.define(scope, name, type); } } - #addError(error: T) { + addError(error: T) { if (!this.stopProcessingErrorsInThisScope) this.errors.push(error); } } @@ -568,12 +568,12 @@ class BinaryTreeNode { printBT(prefix = "", side: Side = Side.LEFT) { let res = ""; if (this._returns) { - res += this.#pad(prefix, side); + res += this.pad(prefix, side); res += " " + this._returns + "\n"; return res; } else { if (this.right == undefined && this.left == undefined) { - res += this.#pad(prefix, side); + res += this.pad(prefix, side); res += " " + false + "\n"; } else { res += this.left?.printBT( @@ -593,7 +593,7 @@ class BinaryTreeNode { } return res; } - #pad(prefix: string, side: Side): string { + pad(prefix: string, side: Side): string { return side == Side.LEFT ? "├──" : "└──"; } } From 1c0c9ab95475854c88b0639c640497b23b2516ac Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:37:14 +0200 Subject: [PATCH 50/87] WIP --- simulator/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simulator/README.md b/simulator/README.md index cc05af99..a2369e1a 100644 --- a/simulator/README.md +++ b/simulator/README.md @@ -1,11 +1,11 @@ -# Regenerate generated files Jack Lexer and Parser +# Regenerate Jack Lexer and Parser files Next command gives us ability to regenerate parser and lexer after we've changed the grammar (.g4 files) for [lexer](src/languages/grammars/JackLexer.g4) or [parser](src/languages/grammars/JackParser.g4) ``` npm run gen ``` -To run this command we would need to install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md) +To run this command we would need to install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md). Antlr 4 tools provides commands to generate lexer and parser files. Beside that it includes `antlr4-parse` that you can use to parser an input jack file and visualize the AST tree or view the token stream. More details on [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md) page. ``` pip install antlr4-tools From 2aba5fb996c6cb886aff67048b2220bc5ed7842c Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:38:27 +0200 Subject: [PATCH 51/87] WIP --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a850595e..dbfb0494 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,4 @@ npm-debug.log* yarn-debug.log* yarn-error.log* **/.vscode/numbered-bookmars.json -**/.antlr \ No newline at end of file +**/.antlr From d27f3918ee889578040a4bd0c2dd1882fec3081b Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:59:28 +0200 Subject: [PATCH 52/87] WIP --- simulator/src/jack/anltr_compiler.ts | 161 ++++ ...ompiler.test.ts => antlr_compiler.test.ts} | 2 +- simulator/src/jack/compiler.ts | 767 ++++++++++++++---- .../src/jack/listener/vm.writer.listener.ts | 12 +- 4 files changed, 788 insertions(+), 154 deletions(-) create mode 100644 simulator/src/jack/anltr_compiler.ts rename simulator/src/jack/{compiler.test.ts => antlr_compiler.test.ts} (99%) diff --git a/simulator/src/jack/anltr_compiler.ts b/simulator/src/jack/anltr_compiler.ts new file mode 100644 index 00000000..f8f10262 --- /dev/null +++ b/simulator/src/jack/anltr_compiler.ts @@ -0,0 +1,161 @@ +import { BinderListener } from "./listener/binder.listener.js"; +import { CustomErrorListener } from "./listener/error.listener.js"; +import { ValidatorListener } from "./listener/validator.listener.js"; +import { JackCompilerError, LexerOrParserError } from "./error.js"; +import { VMWriter } from "./listener/vm.writer.listener.js"; +import JackParser, { ProgramContext } from "./generated/JackParser.js"; +import { CharStreams, CommonTokenStream, ParseTreeWalker } from "antlr4"; +import JackLexer from "./generated/JackLexer.js"; +import { CompilationError } from "../languages/base.js"; + +export function compile( + files: Record, +): Record { + return _doWithTryCatch(files, Command.Compile); +} + +export function validate( + files: Record, +): Record { + return _doWithTryCatch(files, Command.Validate); +} +function _doWithTryCatch(files: Record, cmd: Command) { + try { + return _do(files, cmd); + } catch (err) { + const result: Record = {}; + console.error(err); + const keys = Object.keys(files); + for (const name of keys) { + result[name] = { + message: + "Something went wrong while compiling files. Please create a bug report", + } as CompilationError; + } + return result; + } +} +enum Command { + Compile, + Validate, +} + +function _do( + files: Record, + cmd: Command, +): Record { + if (files instanceof LexerOrParserError) { + throw new Error("Expected tree but got a lexer or parser error"); + } + const result: Record = {}; + for (const name of Object.keys(files)) { + result[name] = ""; + } + const trees: Record = {}; + const errors: Record = {}; + const compiler = new Compiler(); + for (const [name, content] of Object.entries(files)) { + const treeOrErrors = compiler.parserAndBind(content); + if (Array.isArray(treeOrErrors)) { + errors[name] = toCompilerError(treeOrErrors); + } + trees[name] = treeOrErrors as ProgramContext; + } + if (Object.keys(errors).length > 0) { + for (const [name, error] of Object.entries(errors)) { + result[name] = error; + } + return result; + } + + for (const [name, tree] of Object.entries(trees)) { + let compiledOrValidatedOrErrors; + switch (cmd) { + case Command.Compile: + compiledOrValidatedOrErrors = compiler.compile(tree, name); + + if (Array.isArray(compiledOrValidatedOrErrors)) { + result[name] = toCompilerError(compiledOrValidatedOrErrors); + } else { + result[name] = compiledOrValidatedOrErrors; + } + break; + case Command.Validate: + compiledOrValidatedOrErrors = compiler.validate(tree, name); + if (Array.isArray(compiledOrValidatedOrErrors)) { + result[name] = toCompilerError(compiledOrValidatedOrErrors); + } else { + result[name] = ""; + } + break; + default: + throw new Error("Invalid command"); + } + } + return result; +} +function toCompilerError(errors: JackCompilerError[]): CompilationError { + const err = errors[0]; + return { + message: `Line ${err.span.line}: ${err.msg}`, + span: err.span, + } as CompilationError; +} + +export class Compiler { + private binder = new BinderListener(); + private errorListener = new CustomErrorListener(); + validate( + tree: ProgramContext, + filename?: string, + ): ProgramContext | JackCompilerError[] { + if (Object.keys(this.binder.globalSymbolTable).length == 0) { + throw new Error( + "Please populate global symbol table using parserAndBind method", + ); + } + const validator = new ValidatorListener( + this.binder.globalSymbolTable, + filename, + ); + ParseTreeWalker.DEFAULT.walk(validator, tree); + + return validator.errors.length > 0 ? validator.errors : tree; + } + compile( + tree: ProgramContext, + filename?: string, + ): string | JackCompilerError[] { + const treeOrErrors = this.validate(tree, filename); + if (Array.isArray(treeOrErrors)) { + const errors = treeOrErrors as JackCompilerError[]; + console.log("Errors in validator " + JSON.stringify(errors)); + return errors; + } + const validateTree = treeOrErrors as ProgramContext; + const vmWriter = new VMWriter(this.binder.globalSymbolTable); + ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); + return vmWriter.result; + } + + parserAndBind(src: string): ProgramContext | JackCompilerError[] { + const lexer = new JackLexer(CharStreams.fromString(src)); + lexer.removeErrorListeners(); + lexer.addErrorListener(this.errorListener); + const tokenStream = new CommonTokenStream(lexer); + const parser = new JackParser(tokenStream); + parser.removeErrorListeners(); + parser.addErrorListener(this.errorListener); + const tree = parser.program(); + if (this.errorListener.errors.length > 0) { + console.log("Errors when parsing or lexing"); + return this.errorListener.errors; + } + ParseTreeWalker.DEFAULT.walk(this.binder, tree); + if (this.binder.errors.length > 0) { + console.log("Errors in binder"); + return this.binder.errors; + } + return tree; + } +} diff --git a/simulator/src/jack/compiler.test.ts b/simulator/src/jack/antlr_compiler.test.ts similarity index 99% rename from simulator/src/jack/compiler.test.ts rename to simulator/src/jack/antlr_compiler.test.ts index 9be784b7..edb35450 100644 --- a/simulator/src/jack/compiler.test.ts +++ b/simulator/src/jack/antlr_compiler.test.ts @@ -2,7 +2,7 @@ import fs from "fs"; import { getTestResourcePath, testResourceDirs } from "./test.helper"; import path from "path"; import { ProgramContext } from "./generated/JackParser"; -import { Compiler } from "./compiler"; +import { Compiler } from "./anltr_compiler"; describe("Jack compiler", () => { test("static field", () => { testCompiler( diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index f8f10262..f82234fb 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -1,161 +1,634 @@ -import { BinderListener } from "./listener/binder.listener.js"; -import { CustomErrorListener } from "./listener/error.listener.js"; -import { ValidatorListener } from "./listener/validator.listener.js"; -import { JackCompilerError, LexerOrParserError } from "./error.js"; -import { VMWriter } from "./listener/vm.writer.listener.js"; -import JackParser, { ProgramContext } from "./generated/JackParser.js"; -import { CharStreams, CommonTokenStream, ParseTreeWalker } from "antlr4"; -import JackLexer from "./generated/JackLexer.js"; -import { CompilationError } from "../languages/base.js"; - -export function compile( - files: Record, -): Record { - return _doWithTryCatch(files, Command.Compile); -} - -export function validate( - files: Record, -): Record { - return _doWithTryCatch(files, Command.Validate); -} -function _doWithTryCatch(files: Record, cmd: Command) { - try { - return _do(files, cmd); - } catch (err) { - const result: Record = {}; - console.error(err); - const keys = Object.keys(files); - for (const name of keys) { - result[name] = { - message: - "Something went wrong while compiling files. Please create a bug report", - } as CompilationError; - } - return result; +import { + Err, + Ok, + Result, + isErr, + } from "@davidsouther/jiffies/lib/esm/result.js"; + import { CompilationError, Span, createError } from "../languages/base.js"; + import { + ArrayAccess, + Class, + ClassVarDec, + DoStatement, + Expression, + IfStatement, + JACK, + KeywordConstant, + LetStatement, + Op, + Parameter, + ReturnStatement, + Statement, + Subroutine, + SubroutineCall, + Term, + Type, + UnaryOp, + VarDec, + Variable, + WhileStatement, + isPrimitive, + } from "../languages/jack.js"; + import { Segment } from "../languages/vm.js"; + import { + VM_BUILTINS, + makeInterface, + overridesOsCorrectly, + } from "../vm/builtins.js"; + import { validateSubroutine } from "./controlFlow.js"; + + const osClasses = new Set([ + "Sys", + "Screen", + "Output", + "Keyboard", + "String", + "Array", + "Memory", + "Math", + ]); + + function isOsClass(name: string): boolean { + return osClasses.has(name); } -} -enum Command { - Compile, - Validate, -} - -function _do( - files: Record, - cmd: Command, -): Record { - if (files instanceof LexerOrParserError) { - throw new Error("Expected tree but got a lexer or parser error"); + + function isError(value: unknown): value is CompilationError { + return (value as CompilationError).message != undefined; } - const result: Record = {}; - for (const name of Object.keys(files)) { - result[name] = ""; + + function capitalize(s: string) { + return s.charAt(0).toUpperCase() + s.slice(1); } - const trees: Record = {}; - const errors: Record = {}; - const compiler = new Compiler(); - for (const [name, content] of Object.entries(files)) { - const treeOrErrors = compiler.parserAndBind(content); - if (Array.isArray(treeOrErrors)) { - errors[name] = toCompilerError(treeOrErrors); - } - trees[name] = treeOrErrors as ProgramContext; + + export function compile( + files: Record, + ): Record { + const classes: Record = {}; + for (const [name, content] of Object.entries(files)) { + const parsed = JACK.parse(content); + if (isErr(parsed)) { + classes[name] = Err(parsed); + } else { + const cls = Ok(parsed); + const result = validateClass(cls); + classes[name] = + cls.name.value == name + ? isErr(result) + ? Err(result) + : cls + : createError( + `Class name ${cls.name.value} doesn't match file name ${name}`, + cls.name.span, + ); + } + } + + const validClasses: Record = Object.fromEntries( + Object.entries(classes).filter(([_, parsed]) => !isError(parsed)), + ) as Record; + + const vms: Record = {}; + for (const [name, parsed] of Object.entries(classes)) { + if (isError(parsed)) { + vms[name] = parsed; + } else { + try { + const compiled = new Compiler().compile(parsed, validClasses); + if (isErr(compiled)) { + vms[name] = Err(compiled); + } else { + vms[name] = Ok(compiled); + } + } catch (e) { + vms[name] = e as CompilationError; + } + } + } + return vms; } - if (Object.keys(errors).length > 0) { - for (const [name, error] of Object.entries(errors)) { - result[name] = error; + + function validateClass(cls: Class): Result { + const subroutineNames = new Set(); + for (const subroutine of cls.subroutines) { + if (subroutineNames.has(subroutine.name.value)) { + return Err( + createError( + `Subroutine ${subroutine.name.value} already declared`, + subroutine.name.span, + ), + ); + } + subroutineNames.add(subroutine.name.value); + const result = validateSubroutine(subroutine); + if (isErr(result)) { + return result; + } } - return result; + return Ok(); + } + + interface VariableData { + type: Type; + segment: Segment; + index: number; } - - for (const [name, tree] of Object.entries(trees)) { - let compiledOrValidatedOrErrors; - switch (cmd) { - case Command.Compile: - compiledOrValidatedOrErrors = compiler.compile(tree, name); - - if (Array.isArray(compiledOrValidatedOrErrors)) { - result[name] = toCompilerError(compiledOrValidatedOrErrors); + + const ops: Record = { + "+": "add", + "-": "sub", + "*": "call Math.multiply 2", + "/": "call Math.divide 2", + "&": "and", + "|": "or", + "<": "lt", + ">": "gt", + "=": "eq", + }; + + const unaryOps: Record = { + "-": "neg", + "~": "not", + }; + + interface SubroutineCallAttributes { + className: string; + subroutineName: string; + object?: string; // object being acted upon if this is a method (undefined if function / constructor) + } + + export class Compiler { + private instructions: string[] = []; + globalSymbolTable: Record = {}; + localSymbolTable: Record = {}; + + className = ""; + private classes: Record = {}; + + private labelNum = 0; + private fieldNum = 0; + private staticNum = 0; + private localNum = 0; + + get output(): string[] { + return Array.from(this.instructions); + } + + varData(name: string): VariableData | undefined { + return this.localSymbolTable[name] || this.globalSymbolTable[name]; + } + + var(name: string): string; + var(variable: Variable): string; + var(variable: ArrayAccess): string; + var(variable: LetStatement): string; + var(arg: string | Variable | ArrayAccess | LetStatement): string { + let name: string; + let span: Span | undefined; + if (typeof arg == "string") { + name = arg; + } else { + if (typeof arg.name == "string") { + name = arg.name; + span = arg.span; } else { - result[name] = compiledOrValidatedOrErrors; + name = arg.name.value; + span = arg.name.span; } - break; - case Command.Validate: - compiledOrValidatedOrErrors = compiler.validate(tree, name); - if (Array.isArray(compiledOrValidatedOrErrors)) { - result[name] = toCompilerError(compiledOrValidatedOrErrors); + } + const data = this.varData(name); + if (!data) { + throw createError(`Undeclared variable ${name}`, span); + } + return `${data.segment} ${data.index}`; + } + + write(...lines: string[]) { + this.instructions.push(...lines); + } + + getLabel() { + const label = `${this.className}_${this.labelNum}`; + this.labelNum += 1; + return label; + } + + compile( + cls: Class, + other?: Record, + ): Result { + this.className = cls.name.value; + this.classes = other ?? {}; + for (const varDec of cls.varDecs) { + this.compileClassVarDec(varDec); + } + for (const subroutine of cls.subroutines) { + this.compileSubroutineDec(subroutine); + } + return Ok( + this.instructions + .map((inst) => + inst.startsWith("function") || inst.startsWith("label") + ? inst + : " ".concat(inst), + ) + .join("\n"), + ); + } + + validateType(type: string, span?: Span) { + if (isPrimitive(type) || isOsClass(type) || this.classes[type]) { + return; + } + throw createError(`Unknown type ${type}`, span); + } + + validateReturnType(returnType: string, span?: Span) { + if (returnType == "void") { + return; + } + this.validateType(returnType, span); + } + + compileClassVarDec(dec: ClassVarDec) { + this.validateType(dec.type.value, dec.type.span); + for (const name of dec.names) { + if (dec.varType == "field") { + this.globalSymbolTable[name] = { + type: dec.type.value, + segment: "this", + index: this.fieldNum, + }; + this.fieldNum += 1; } else { - result[name] = ""; + this.globalSymbolTable[name] = { + type: dec.type.value, + segment: "static", + index: this.staticNum, + }; + this.staticNum += 1; } - break; - default: - throw new Error("Invalid command"); + } } - } - return result; -} -function toCompilerError(errors: JackCompilerError[]): CompilationError { - const err = errors[0]; - return { - message: `Line ${err.span.line}: ${err.msg}`, - span: err.span, - } as CompilationError; -} - -export class Compiler { - private binder = new BinderListener(); - private errorListener = new CustomErrorListener(); - validate( - tree: ProgramContext, - filename?: string, - ): ProgramContext | JackCompilerError[] { - if (Object.keys(this.binder.globalSymbolTable).length == 0) { - throw new Error( - "Please populate global symbol table using parserAndBind method", + + compileVarDec(dec: VarDec) { + this.validateType(dec.type.value, dec.type.span); + for (const name of dec.names) { + this.localSymbolTable[name] = { + type: dec.type.value, + segment: "local", + index: this.localNum, + }; + this.localNum += 1; + } + } + + registerArgs(params: Parameter[], offset = false) { + let argNum = 0; + for (const param of params) { + this.validateType(param.type.value, param.type.span); + this.localSymbolTable[param.name] = { + type: param.type.value, + segment: "argument", + index: argNum + (offset ? 1 : 0), // when compiling a method the first argument is this, so we offset the others by 1 + }; + argNum += 1; + } + } + + validateSubroutineDec(subroutine: Subroutine) { + this.validateReturnType( + subroutine.returnType.value, + subroutine.returnType.span, ); + + if (isOsClass(this.className)) { + const builtin = VM_BUILTINS[`${this.className}.${subroutine.name.value}`]; + + if (builtin && !overridesOsCorrectly(this.className, subroutine)) { + throw createError( + `OS subroutine ${this.className}.${subroutine.name.value} must follow the interface ${makeInterface(subroutine.name.value, builtin)})`, + ); + } + } + } + + compileSubroutineDec(subroutine: Subroutine) { + this.validateSubroutineDec(subroutine); + switch (subroutine.type) { + case "method": + this.compileMethod(subroutine); + break; + case "constructor": + this.compileConstructor(subroutine); + break; + case "function": + this.compileFunction(subroutine); + } + } + + compileSubroutineStart(subroutine: Subroutine, isMethod = false) { + this.localSymbolTable = {}; + this.localNum = 0; + this.registerArgs(subroutine.parameters, isMethod); + + const localCount = subroutine.body.varDecs + .map((dec) => dec.names.length) + .reduce((a, b) => a + b, 0); + this.write( + `function ${this.className}.${subroutine.name.value} ${localCount}`, + ); + for (const varDec of subroutine.body.varDecs) { + this.compileVarDec(varDec); + } + } + + compileFunction(subroutine: Subroutine) { + this.compileSubroutineStart(subroutine); + this.compileStatements(subroutine.body.statements); + } + + compileMethod(subroutine: Subroutine) { + this.compileSubroutineStart(subroutine, true); + this.write("push argument 0", "pop pointer 0"); + this.compileStatements(subroutine.body.statements); + } + + compileConstructor(subroutine: Subroutine) { + this.compileSubroutineStart(subroutine); + this.write( + `push constant ${this.fieldNum}`, + "call Memory.alloc 1", + "pop pointer 0", + ); + this.compileStatements(subroutine.body.statements); + } + + compileExpression(expression: Expression) { + this.compileTerm(expression.term); + for (const part of expression.rest) { + this.compileTerm(part.term); + this.compileOp(part.op); // postfix + } + } + + compileOp(op: Op) { + this.write(ops[op]); + } + + compileTerm(term: Term) { + switch (term.termType) { + case "numericLiteral": + this.write(`push constant ${term.value}`); + break; + case "stringLiteral": + this.compileStringLiteral(term.value); + break; + case "variable": + this.write(`push ${this.var(term)}`); + break; + case "keywordLiteral": + this.compileKeywordLiteral(term.value); + break; + case "subroutineCall": + this.compileSubroutineCall(term); + break; + case "arrayAccess": + this.compileExpression(term.index); + this.write( + `push ${this.var(term)}`, + "add", + "pop pointer 1", + "push that 0", + ); + break; + case "groupedExpression": + this.compileExpression(term.expression); + break; + case "unaryExpression": + this.compileTerm(term.term); + this.write(unaryOps[term.op]); + } + } + + validateArgNum(name: string, expected: number, call: SubroutineCall) { + const received = call.parameters.length; + if (expected != received) { + throw createError( + `${name} expected ${expected} arguments, got ${received}`, + call.span, + ); + } + } + + validateSubroutineCall( + className: string, + subroutineName: string, + call: SubroutineCall, + isMethod: boolean, + ) { + const builtin = VM_BUILTINS[`${className}.${subroutineName}`]; + if (builtin) { + if (builtin.type == "method" && !isMethod) { + throw createError( + `Method ${className}.${subroutineName} was called as a function/constructor`, + call.name.span, + ); + } + if (builtin.type != "method" && isMethod) { + throw createError( + `${capitalize( + builtin.type, + )} ${className}.${subroutineName} was called as a method`, + call.name.span, + ); + } + this.validateArgNum( + `${className}.${subroutineName}`, + builtin.args.length, + call, + ); + return; + } else if (this.classes[className]) { + for (const subroutine of this.classes[className].subroutines) { + if (subroutine.name.value == subroutineName) { + if (subroutine.type == "method" && !isMethod) { + throw createError( + `Method ${className}.${subroutineName} was called as a function/constructor`, + call.name.span, + ); + } + if (subroutine.type != "method" && isMethod) { + throw createError( + `${capitalize( + subroutine.name.value, + )} ${className}.${subroutineName} was called as a method`, + call.name.span, + ); + } + this.validateArgNum( + `${className}.${subroutineName}`, + subroutine.parameters.length, + call, + ); + return; + } + } + throw createError( + `Class ${className} doesn't contain a function/constructor ${subroutineName}`, + call.name.span, + ); + } else { + throw createError(`Class ${className} doesn't exist`, call.name.span); + } + } + + classifySubroutineCall(call: SubroutineCall): SubroutineCallAttributes { + let object: string | undefined; + let className = ""; + let subroutineName = ""; + + if (call.name.value.includes(".")) { + const [prefix, suffix] = call.name.value.split(".", 2); + subroutineName = suffix; + const varData = this.varData(prefix); + if (varData) { + // external method call + object = this.var(prefix); + className = varData.type; + } else { + // function / constructor call + className = prefix; + } + } else { + object = "pointer 0"; // this + className = this.className; + subroutineName = call.name.value; + } + + this.validateSubroutineCall( + className, + subroutineName, + call, + object != undefined, + ); + + return { className, subroutineName, object }; + } + + compileSubroutineCall(call: SubroutineCall) { + const attributes = this.classifySubroutineCall(call); + + if (attributes.object) { + this.write(`push ${attributes.object}`); + } + for (const param of call.parameters) { + this.compileExpression(param); + } + this.write( + `call ${attributes.className}.${attributes.subroutineName} ${ + call.parameters.length + (attributes.object ? 1 : 0) + }`, + ); + } + + compileStringLiteral(str: string) { + this.write(`push constant ${str.length}`, `call String.new 1`); + for (let i = 0; i < str.length; i++) { + this.write( + `push constant ${str.charCodeAt(i)}`, + `call String.appendChar 2`, + ); + } + } + + compileKeywordLiteral(keyword: KeywordConstant) { + switch (keyword) { + case "true": + this.write(`push constant 1`, `neg`); + break; + case "false": + this.write(`push constant 0`); + break; + case "null": + this.write(`push constant 0`); + break; + case "this": + this.write(`push pointer 0`); + } + } + + compileStatements(statements: Statement[]) { + for (const statement of statements) { + this.compileStatement(statement); + } + } + + compileStatement(statement: Statement) { + switch (statement.statementType) { + case "doStatement": + this.compileDoStatement(statement); + break; + case "ifStatement": + this.compileIf(statement); + break; + case "letStatement": + this.compileLet(statement); + break; + case "returnStatement": + this.compileReturn(statement); + break; + case "whileStatement": + this.compileWhile(statement); + } + } + + compileReturn(statement: ReturnStatement) { + if (statement.value) { + this.compileExpression(statement.value); + } else { + this.write(`push constant 0`); // return 0 + } + this.write(`return`); + } + + compileLet(statement: LetStatement) { + if (statement.arrayIndex) { + this.compileExpression(statement.arrayIndex); + this.write(`push ${this.var(statement)}`, "add"); + this.compileExpression(statement.value); + this.write("pop temp 0", "pop pointer 1", "push temp 0", "pop that 0"); + } else { + this.compileExpression(statement.value); + this.write(`pop ${this.var(statement)}`); + } + } + + compileDoStatement(statement: DoStatement) { + this.compileSubroutineCall(statement.call); + this.write(`pop temp 0`); + } + + compileIf(statement: IfStatement) { + const condTrue = this.getLabel(); + const condFalse = this.getLabel(); + + this.compileExpression(statement.condition); + this.write("not", `if-goto ${condFalse}`); + this.compileStatements(statement.body); + this.write(`goto ${condTrue}`, `label ${condFalse}`); + this.compileStatements(statement.else); + this.write(`label ${condTrue}`); + } + + compileWhile(statement: WhileStatement) { + const loop = this.getLabel(); + const exit = this.getLabel(); + + this.write(`label ${loop}`); + this.compileExpression(statement.condition); + this.write(`not`, `if-goto ${exit}`); + this.compileStatements(statement.body); + this.write(`goto ${loop}`, `label ${exit}`); } - const validator = new ValidatorListener( - this.binder.globalSymbolTable, - filename, - ); - ParseTreeWalker.DEFAULT.walk(validator, tree); - - return validator.errors.length > 0 ? validator.errors : tree; - } - compile( - tree: ProgramContext, - filename?: string, - ): string | JackCompilerError[] { - const treeOrErrors = this.validate(tree, filename); - if (Array.isArray(treeOrErrors)) { - const errors = treeOrErrors as JackCompilerError[]; - console.log("Errors in validator " + JSON.stringify(errors)); - return errors; - } - const validateTree = treeOrErrors as ProgramContext; - const vmWriter = new VMWriter(this.binder.globalSymbolTable); - ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); - return vmWriter.result; - } - - parserAndBind(src: string): ProgramContext | JackCompilerError[] { - const lexer = new JackLexer(CharStreams.fromString(src)); - lexer.removeErrorListeners(); - lexer.addErrorListener(this.errorListener); - const tokenStream = new CommonTokenStream(lexer); - const parser = new JackParser(tokenStream); - parser.removeErrorListeners(); - parser.addErrorListener(this.errorListener); - const tree = parser.program(); - if (this.errorListener.errors.length > 0) { - console.log("Errors when parsing or lexing"); - return this.errorListener.errors; - } - ParseTreeWalker.DEFAULT.walk(this.binder, tree); - if (this.binder.errors.length > 0) { - console.log("Errors in binder"); - return this.binder.errors; - } - return tree; } -} + \ No newline at end of file diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index cdad0911..ae3b6d81 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -47,9 +47,9 @@ const unaryOperationToVmCmd: Record = { export class VMWriter extends JackParserListener { public result = ""; private className = ""; - private currentLabelInd = 0; + private currentLabelIndex = 0; private localSymbolTable: LocalSymbolTable | undefined; - private afterEquals = false; + private inAssignmentRightHandSide = false; constructor(private globalSymbolTable: Record) { super(); } @@ -101,16 +101,16 @@ export class VMWriter extends JackParserListener { } this.pushSymbolOntoStack(symbol); this.result += ` add\n`; - if (this.afterEquals || ctx.parentCtx instanceof ExpressionContext) { + if (this.inAssignmentRightHandSide || ctx.parentCtx instanceof ExpressionContext) { this.result += ` pop pointer 1\n`; this.result += ` push that 0\n`; } }; override enterEquals = (ctx: EqualsContext) => { - this.afterEquals = true; + this.inAssignmentRightHandSide = true; }; override exitStatement = (ctx: StatementContext) => { - this.afterEquals = false; + this.inAssignmentRightHandSide = false; }; override enterConstant = (ctx: ConstantContext) => { if (ctx.INTEGER_LITERAL() != null) { @@ -281,6 +281,6 @@ export class VMWriter extends JackParserListener { } createLabel() { - return this.getLabel(this.currentLabelInd++); + return this.getLabel(this.currentLabelIndex++); } } From ae9be577cbe1427af000c6dc92341bfe2755df3b Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:07:54 +0200 Subject: [PATCH 53/87] WIP --- .gitignore | 1 + components/src/stores/compiler.store.ts | 2 +- simulator/package.json | 3 - .../{anltr_compiler.ts => anltr.compiler.ts} | 0 ...ompiler.test.ts => antlr.compiler.test.ts} | 2 +- simulator/src/jack/compiler.test.ts | 126 ++ simulator/src/jack/compiler.ts | 1169 ++++++++--------- simulator/src/jack/controlFlow.ts | 180 +++ .../src/jack/listener/vm.writer.listener.ts | 5 +- 9 files changed, 897 insertions(+), 591 deletions(-) rename simulator/src/jack/{anltr_compiler.ts => anltr.compiler.ts} (100%) rename simulator/src/jack/{antlr_compiler.test.ts => antlr.compiler.test.ts} (99%) create mode 100644 simulator/src/jack/compiler.test.ts create mode 100644 simulator/src/jack/controlFlow.ts diff --git a/.gitignore b/.gitignore index dbfb0494..f21da166 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ yarn-debug.log* yarn-error.log* **/.vscode/numbered-bookmars.json **/.antlr +.idea/ diff --git a/components/src/stores/compiler.store.ts b/components/src/stores/compiler.store.ts index 27e82112..7dfd9544 100644 --- a/components/src/stores/compiler.store.ts +++ b/components/src/stores/compiler.store.ts @@ -88,7 +88,7 @@ export function makeCompilerStore( (file) => state.compiled[file].valid, ); }, - + validate(state: CompilerPageState) { state.isCompiled = false; this._processCompilationResults(state, validate(state.files)); diff --git a/simulator/package.json b/simulator/package.json index bb0ce903..a645cf30 100644 --- a/simulator/package.json +++ b/simulator/package.json @@ -37,9 +37,6 @@ "scripts": { "build": "tsc", "test": "jest --verbose", - "test-w": "jest --watchAll --verbose", - "test-jack": "npm run test -- -t \"Jack\"", - "test-jack-w": "npm run test-w -- -t \"Jack\"", "gen": "cd src/languages/grammars && antlr4 -v 4.13.2 -Dlanguage=TypeScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" } } diff --git a/simulator/src/jack/anltr_compiler.ts b/simulator/src/jack/anltr.compiler.ts similarity index 100% rename from simulator/src/jack/anltr_compiler.ts rename to simulator/src/jack/anltr.compiler.ts diff --git a/simulator/src/jack/antlr_compiler.test.ts b/simulator/src/jack/antlr.compiler.test.ts similarity index 99% rename from simulator/src/jack/antlr_compiler.test.ts rename to simulator/src/jack/antlr.compiler.test.ts index edb35450..a74cd34a 100644 --- a/simulator/src/jack/antlr_compiler.test.ts +++ b/simulator/src/jack/antlr.compiler.test.ts @@ -2,7 +2,7 @@ import fs from "fs"; import { getTestResourcePath, testResourceDirs } from "./test.helper"; import path from "path"; import { ProgramContext } from "./generated/JackParser"; -import { Compiler } from "./anltr_compiler"; +import { Compiler } from "./anltr.compiler"; describe("Jack compiler", () => { test("static field", () => { testCompiler( diff --git a/simulator/src/jack/compiler.test.ts b/simulator/src/jack/compiler.test.ts new file mode 100644 index 00000000..19afc722 --- /dev/null +++ b/simulator/src/jack/compiler.test.ts @@ -0,0 +1,126 @@ +import { Programs } from "@nand2tetris/projects/samples/project_11/index.js"; +import { JACK } from "../languages/jack"; +import { Compiler, compile } from "./compiler"; + +function parse(code: string, rule: string) { + return JACK.semantics(JACK.parser.match(code, rule)); +} + +describe("compiler", () => { + it("compiles expression", () => { + const exp = parse("(2 + 3) * 5", "Expression").expression; + + const compiler = new Compiler(); + compiler.compileExpression(exp); + expect(compiler.output).toEqual([ + "push constant 2", + "push constant 3", + "add", + "push constant 5", + "call Math.multiply 2", + ]); + }); + + it("compiles function", () => { + const func = parse( + `function void main() { + var int a; + let a = 4; + return; + }`, + "SubroutineDec", + ).subroutineDec; + + const compiler = new Compiler(); + compiler.className = "Main"; + compiler.compileFunction(func); + expect(compiler.output).toEqual([ + "function Main.main 1", + "push constant 4", + "pop local 0", + "push constant 0", + "return", + ]); + }); + + it("compiles array access", () => { + const statement = parse(`let x = arr[2];`, "Statement").statement; + + const compiler = new Compiler(); + compiler.localSymbolTable = { + x: { + type: "int", + segment: "local", + index: 0, + }, + arr: { + type: "Array", + segment: "local", + index: 1, + }, + }; + compiler.compileStatement(statement); + expect(compiler.output).toEqual([ + "push constant 2", + "push local 1", + "add", + "pop pointer 1", + "push that 0", + "pop local 0", + ]); + }); + + it("compiles if-else", () => { + const statement = parse( + `if (condition) { + let x = 4; + } else { + let x = 5; + }`, + "Statement", + ).statement; + + const compiler = new Compiler(); + compiler.className = "Main"; + compiler.localSymbolTable = { + condition: { + type: "boolean", + segment: "local", + index: 0, + }, + x: { + type: "int", + segment: "local", + index: 1, + }, + }; + compiler.compileStatement(statement); + expect(compiler.output).toEqual([ + "push local 0", + "not", + "if-goto Main_1", + "push constant 4", + "pop local 1", + "goto Main_0", + "label Main_1", + "push constant 5", + "pop local 1", + "label Main_0", + ]); + }); + + it.each(Object.keys(Programs))("%s", (program) => { + const compiled = compile( + Object.fromEntries( + Object.entries(Programs[program]).map(([name, file]) => [ + name, + file.jack, + ]), + ), + ); + + for (const file of Object.keys(compiled)) { + expect(compiled[file]).toEqual(Programs[program][file].compiled); + } + }); +}); diff --git a/simulator/src/jack/compiler.ts b/simulator/src/jack/compiler.ts index f82234fb..a0c58b68 100644 --- a/simulator/src/jack/compiler.ts +++ b/simulator/src/jack/compiler.ts @@ -1,634 +1,633 @@ import { - Err, - Ok, - Result, - isErr, - } from "@davidsouther/jiffies/lib/esm/result.js"; - import { CompilationError, Span, createError } from "../languages/base.js"; - import { - ArrayAccess, - Class, - ClassVarDec, - DoStatement, - Expression, - IfStatement, - JACK, - KeywordConstant, - LetStatement, - Op, - Parameter, - ReturnStatement, - Statement, - Subroutine, - SubroutineCall, - Term, - Type, - UnaryOp, - VarDec, - Variable, - WhileStatement, - isPrimitive, - } from "../languages/jack.js"; - import { Segment } from "../languages/vm.js"; - import { - VM_BUILTINS, - makeInterface, - overridesOsCorrectly, - } from "../vm/builtins.js"; - import { validateSubroutine } from "./controlFlow.js"; - - const osClasses = new Set([ - "Sys", - "Screen", - "Output", - "Keyboard", - "String", - "Array", - "Memory", - "Math", - ]); - - function isOsClass(name: string): boolean { - return osClasses.has(name); - } - - function isError(value: unknown): value is CompilationError { - return (value as CompilationError).message != undefined; - } - - function capitalize(s: string) { - return s.charAt(0).toUpperCase() + s.slice(1); - } - - export function compile( - files: Record, - ): Record { - const classes: Record = {}; - for (const [name, content] of Object.entries(files)) { - const parsed = JACK.parse(content); - if (isErr(parsed)) { - classes[name] = Err(parsed); - } else { - const cls = Ok(parsed); - const result = validateClass(cls); - classes[name] = - cls.name.value == name - ? isErr(result) - ? Err(result) - : cls - : createError( - `Class name ${cls.name.value} doesn't match file name ${name}`, - cls.name.span, - ); - } + Err, + Ok, + Result, + isErr, +} from "@davidsouther/jiffies/lib/esm/result.js"; +import { CompilationError, Span, createError } from "../languages/base.js"; +import { + ArrayAccess, + Class, + ClassVarDec, + DoStatement, + Expression, + IfStatement, + JACK, + KeywordConstant, + LetStatement, + Op, + Parameter, + ReturnStatement, + Statement, + Subroutine, + SubroutineCall, + Term, + Type, + UnaryOp, + VarDec, + Variable, + WhileStatement, + isPrimitive, +} from "../languages/jack.js"; +import { Segment } from "../languages/vm.js"; +import { + VM_BUILTINS, + makeInterface, + overridesOsCorrectly, +} from "../vm/builtins.js"; +import { validateSubroutine } from "./controlFlow.js"; + +const osClasses = new Set([ + "Sys", + "Screen", + "Output", + "Keyboard", + "String", + "Array", + "Memory", + "Math", +]); + +function isOsClass(name: string): boolean { + return osClasses.has(name); +} + +function isError(value: unknown): value is CompilationError { + return (value as CompilationError).message != undefined; +} + +function capitalize(s: string) { + return s.charAt(0).toUpperCase() + s.slice(1); +} + +export function compile( + files: Record, +): Record { + const classes: Record = {}; + for (const [name, content] of Object.entries(files)) { + const parsed = JACK.parse(content); + if (isErr(parsed)) { + classes[name] = Err(parsed); + } else { + const cls = Ok(parsed); + const result = validateClass(cls); + classes[name] = + cls.name.value == name + ? isErr(result) + ? Err(result) + : cls + : createError( + `Class name ${cls.name.value} doesn't match file name ${name}`, + cls.name.span, + ); } - - const validClasses: Record = Object.fromEntries( - Object.entries(classes).filter(([_, parsed]) => !isError(parsed)), - ) as Record; - - const vms: Record = {}; - for (const [name, parsed] of Object.entries(classes)) { - if (isError(parsed)) { - vms[name] = parsed; - } else { - try { - const compiled = new Compiler().compile(parsed, validClasses); - if (isErr(compiled)) { - vms[name] = Err(compiled); - } else { - vms[name] = Ok(compiled); - } - } catch (e) { - vms[name] = e as CompilationError; + } + + const validClasses: Record = Object.fromEntries( + Object.entries(classes).filter(([_, parsed]) => !isError(parsed)), + ) as Record; + + const vms: Record = {}; + for (const [name, parsed] of Object.entries(classes)) { + if (isError(parsed)) { + vms[name] = parsed; + } else { + try { + const compiled = new Compiler().compile(parsed, validClasses); + if (isErr(compiled)) { + vms[name] = Err(compiled); + } else { + vms[name] = Ok(compiled); } + } catch (e) { + vms[name] = e as CompilationError; } } - return vms; } - - function validateClass(cls: Class): Result { - const subroutineNames = new Set(); - for (const subroutine of cls.subroutines) { - if (subroutineNames.has(subroutine.name.value)) { - return Err( - createError( - `Subroutine ${subroutine.name.value} already declared`, - subroutine.name.span, - ), - ); - } - subroutineNames.add(subroutine.name.value); - const result = validateSubroutine(subroutine); - if (isErr(result)) { - return result; - } - } - return Ok(); - } - - interface VariableData { - type: Type; - segment: Segment; - index: number; - } - - const ops: Record = { - "+": "add", - "-": "sub", - "*": "call Math.multiply 2", - "/": "call Math.divide 2", - "&": "and", - "|": "or", - "<": "lt", - ">": "gt", - "=": "eq", - }; - - const unaryOps: Record = { - "-": "neg", - "~": "not", - }; - - interface SubroutineCallAttributes { - className: string; - subroutineName: string; - object?: string; // object being acted upon if this is a method (undefined if function / constructor) - } - - export class Compiler { - private instructions: string[] = []; - globalSymbolTable: Record = {}; - localSymbolTable: Record = {}; - - className = ""; - private classes: Record = {}; - - private labelNum = 0; - private fieldNum = 0; - private staticNum = 0; - private localNum = 0; - - get output(): string[] { - return Array.from(this.instructions); + return vms; +} + +function validateClass(cls: Class): Result { + const subroutineNames = new Set(); + for (const subroutine of cls.subroutines) { + if (subroutineNames.has(subroutine.name.value)) { + return Err( + createError( + `Subroutine ${subroutine.name.value} already declared`, + subroutine.name.span, + ), + ); } - - varData(name: string): VariableData | undefined { - return this.localSymbolTable[name] || this.globalSymbolTable[name]; + subroutineNames.add(subroutine.name.value); + const result = validateSubroutine(subroutine); + if (isErr(result)) { + return result; } - - var(name: string): string; - var(variable: Variable): string; - var(variable: ArrayAccess): string; - var(variable: LetStatement): string; - var(arg: string | Variable | ArrayAccess | LetStatement): string { - let name: string; - let span: Span | undefined; - if (typeof arg == "string") { - name = arg; + } + return Ok(); +} + +interface VariableData { + type: Type; + segment: Segment; + index: number; +} + +const ops: Record = { + "+": "add", + "-": "sub", + "*": "call Math.multiply 2", + "/": "call Math.divide 2", + "&": "and", + "|": "or", + "<": "lt", + ">": "gt", + "=": "eq", +}; + +const unaryOps: Record = { + "-": "neg", + "~": "not", +}; + +interface SubroutineCallAttributes { + className: string; + subroutineName: string; + object?: string; // object being acted upon if this is a method (undefined if function / constructor) +} + +export class Compiler { + private instructions: string[] = []; + globalSymbolTable: Record = {}; + localSymbolTable: Record = {}; + + className = ""; + private classes: Record = {}; + + private labelNum = 0; + private fieldNum = 0; + private staticNum = 0; + private localNum = 0; + + get output(): string[] { + return Array.from(this.instructions); + } + + varData(name: string): VariableData | undefined { + return this.localSymbolTable[name] || this.globalSymbolTable[name]; + } + + var(name: string): string; + var(variable: Variable): string; + var(variable: ArrayAccess): string; + var(variable: LetStatement): string; + var(arg: string | Variable | ArrayAccess | LetStatement): string { + let name: string; + let span: Span | undefined; + if (typeof arg == "string") { + name = arg; + } else { + if (typeof arg.name == "string") { + name = arg.name; + span = arg.span; } else { - if (typeof arg.name == "string") { - name = arg.name; - span = arg.span; - } else { - name = arg.name.value; - span = arg.name.span; - } + name = arg.name.value; + span = arg.name.span; } - const data = this.varData(name); - if (!data) { - throw createError(`Undeclared variable ${name}`, span); - } - return `${data.segment} ${data.index}`; - } - - write(...lines: string[]) { - this.instructions.push(...lines); } - - getLabel() { - const label = `${this.className}_${this.labelNum}`; - this.labelNum += 1; - return label; + const data = this.varData(name); + if (!data) { + throw createError(`Undeclared variable ${name}`, span); } - - compile( - cls: Class, - other?: Record, - ): Result { - this.className = cls.name.value; - this.classes = other ?? {}; - for (const varDec of cls.varDecs) { - this.compileClassVarDec(varDec); - } - for (const subroutine of cls.subroutines) { - this.compileSubroutineDec(subroutine); - } - return Ok( - this.instructions - .map((inst) => - inst.startsWith("function") || inst.startsWith("label") - ? inst - : " ".concat(inst), - ) - .join("\n"), - ); - } - - validateType(type: string, span?: Span) { - if (isPrimitive(type) || isOsClass(type) || this.classes[type]) { - return; - } - throw createError(`Unknown type ${type}`, span); + return `${data.segment} ${data.index}`; + } + + write(...lines: string[]) { + this.instructions.push(...lines); + } + + getLabel() { + const label = `${this.className}_${this.labelNum}`; + this.labelNum += 1; + return label; + } + + compile( + cls: Class, + other?: Record, + ): Result { + this.className = cls.name.value; + this.classes = other ?? {}; + for (const varDec of cls.varDecs) { + this.compileClassVarDec(varDec); } - - validateReturnType(returnType: string, span?: Span) { - if (returnType == "void") { - return; - } - this.validateType(returnType, span); + for (const subroutine of cls.subroutines) { + this.compileSubroutineDec(subroutine); + } + return Ok( + this.instructions + .map((inst) => + inst.startsWith("function") || inst.startsWith("label") + ? inst + : " ".concat(inst), + ) + .join("\n"), + ); + } + + validateType(type: string, span?: Span) { + if (isPrimitive(type) || isOsClass(type) || this.classes[type]) { + return; } - - compileClassVarDec(dec: ClassVarDec) { - this.validateType(dec.type.value, dec.type.span); - for (const name of dec.names) { - if (dec.varType == "field") { - this.globalSymbolTable[name] = { - type: dec.type.value, - segment: "this", - index: this.fieldNum, - }; - this.fieldNum += 1; - } else { - this.globalSymbolTable[name] = { - type: dec.type.value, - segment: "static", - index: this.staticNum, - }; - this.staticNum += 1; - } - } + throw createError(`Unknown type ${type}`, span); + } + + validateReturnType(returnType: string, span?: Span) { + if (returnType == "void") { + return; } - - compileVarDec(dec: VarDec) { - this.validateType(dec.type.value, dec.type.span); - for (const name of dec.names) { - this.localSymbolTable[name] = { + this.validateType(returnType, span); + } + + compileClassVarDec(dec: ClassVarDec) { + this.validateType(dec.type.value, dec.type.span); + for (const name of dec.names) { + if (dec.varType == "field") { + this.globalSymbolTable[name] = { type: dec.type.value, - segment: "local", - index: this.localNum, + segment: "this", + index: this.fieldNum, }; - this.localNum += 1; - } - } - - registerArgs(params: Parameter[], offset = false) { - let argNum = 0; - for (const param of params) { - this.validateType(param.type.value, param.type.span); - this.localSymbolTable[param.name] = { - type: param.type.value, - segment: "argument", - index: argNum + (offset ? 1 : 0), // when compiling a method the first argument is this, so we offset the others by 1 + this.fieldNum += 1; + } else { + this.globalSymbolTable[name] = { + type: dec.type.value, + segment: "static", + index: this.staticNum, }; - argNum += 1; + this.staticNum += 1; } } - - validateSubroutineDec(subroutine: Subroutine) { - this.validateReturnType( - subroutine.returnType.value, - subroutine.returnType.span, - ); - - if (isOsClass(this.className)) { - const builtin = VM_BUILTINS[`${this.className}.${subroutine.name.value}`]; - - if (builtin && !overridesOsCorrectly(this.className, subroutine)) { - throw createError( - `OS subroutine ${this.className}.${subroutine.name.value} must follow the interface ${makeInterface(subroutine.name.value, builtin)})`, - ); - } - } + } + + compileVarDec(dec: VarDec) { + this.validateType(dec.type.value, dec.type.span); + for (const name of dec.names) { + this.localSymbolTable[name] = { + type: dec.type.value, + segment: "local", + index: this.localNum, + }; + this.localNum += 1; } - - compileSubroutineDec(subroutine: Subroutine) { - this.validateSubroutineDec(subroutine); - switch (subroutine.type) { - case "method": - this.compileMethod(subroutine); - break; - case "constructor": - this.compileConstructor(subroutine); - break; - case "function": - this.compileFunction(subroutine); - } + } + + registerArgs(params: Parameter[], offset = false) { + let argNum = 0; + for (const param of params) { + this.validateType(param.type.value, param.type.span); + this.localSymbolTable[param.name] = { + type: param.type.value, + segment: "argument", + index: argNum + (offset ? 1 : 0), // when compiling a method the first argument is this, so we offset the others by 1 + }; + argNum += 1; } - - compileSubroutineStart(subroutine: Subroutine, isMethod = false) { - this.localSymbolTable = {}; - this.localNum = 0; - this.registerArgs(subroutine.parameters, isMethod); - - const localCount = subroutine.body.varDecs - .map((dec) => dec.names.length) - .reduce((a, b) => a + b, 0); - this.write( - `function ${this.className}.${subroutine.name.value} ${localCount}`, - ); - for (const varDec of subroutine.body.varDecs) { - this.compileVarDec(varDec); + } + + validateSubroutineDec(subroutine: Subroutine) { + this.validateReturnType( + subroutine.returnType.value, + subroutine.returnType.span, + ); + + if (isOsClass(this.className)) { + const builtin = VM_BUILTINS[`${this.className}.${subroutine.name.value}`]; + + if (builtin && !overridesOsCorrectly(this.className, subroutine)) { + throw createError( + `OS subroutine ${this.className}.${subroutine.name.value} must follow the interface ${makeInterface(subroutine.name.value, builtin)})`, + ); } } - - compileFunction(subroutine: Subroutine) { - this.compileSubroutineStart(subroutine); - this.compileStatements(subroutine.body.statements); - } - - compileMethod(subroutine: Subroutine) { - this.compileSubroutineStart(subroutine, true); - this.write("push argument 0", "pop pointer 0"); - this.compileStatements(subroutine.body.statements); + } + + compileSubroutineDec(subroutine: Subroutine) { + this.validateSubroutineDec(subroutine); + switch (subroutine.type) { + case "method": + this.compileMethod(subroutine); + break; + case "constructor": + this.compileConstructor(subroutine); + break; + case "function": + this.compileFunction(subroutine); } - - compileConstructor(subroutine: Subroutine) { - this.compileSubroutineStart(subroutine); - this.write( - `push constant ${this.fieldNum}`, - "call Memory.alloc 1", - "pop pointer 0", - ); - this.compileStatements(subroutine.body.statements); + } + + compileSubroutineStart(subroutine: Subroutine, isMethod = false) { + this.localSymbolTable = {}; + this.localNum = 0; + this.registerArgs(subroutine.parameters, isMethod); + + const localCount = subroutine.body.varDecs + .map((dec) => dec.names.length) + .reduce((a, b) => a + b, 0); + this.write( + `function ${this.className}.${subroutine.name.value} ${localCount}`, + ); + for (const varDec of subroutine.body.varDecs) { + this.compileVarDec(varDec); } - - compileExpression(expression: Expression) { - this.compileTerm(expression.term); - for (const part of expression.rest) { - this.compileTerm(part.term); - this.compileOp(part.op); // postfix - } + } + + compileFunction(subroutine: Subroutine) { + this.compileSubroutineStart(subroutine); + this.compileStatements(subroutine.body.statements); + } + + compileMethod(subroutine: Subroutine) { + this.compileSubroutineStart(subroutine, true); + this.write("push argument 0", "pop pointer 0"); + this.compileStatements(subroutine.body.statements); + } + + compileConstructor(subroutine: Subroutine) { + this.compileSubroutineStart(subroutine); + this.write( + `push constant ${this.fieldNum}`, + "call Memory.alloc 1", + "pop pointer 0", + ); + this.compileStatements(subroutine.body.statements); + } + + compileExpression(expression: Expression) { + this.compileTerm(expression.term); + for (const part of expression.rest) { + this.compileTerm(part.term); + this.compileOp(part.op); // postfix } - - compileOp(op: Op) { - this.write(ops[op]); + } + + compileOp(op: Op) { + this.write(ops[op]); + } + + compileTerm(term: Term) { + switch (term.termType) { + case "numericLiteral": + this.write(`push constant ${term.value}`); + break; + case "stringLiteral": + this.compileStringLiteral(term.value); + break; + case "variable": + this.write(`push ${this.var(term)}`); + break; + case "keywordLiteral": + this.compileKeywordLiteral(term.value); + break; + case "subroutineCall": + this.compileSubroutineCall(term); + break; + case "arrayAccess": + this.compileExpression(term.index); + this.write( + `push ${this.var(term)}`, + "add", + "pop pointer 1", + "push that 0", + ); + break; + case "groupedExpression": + this.compileExpression(term.expression); + break; + case "unaryExpression": + this.compileTerm(term.term); + this.write(unaryOps[term.op]); } - - compileTerm(term: Term) { - switch (term.termType) { - case "numericLiteral": - this.write(`push constant ${term.value}`); - break; - case "stringLiteral": - this.compileStringLiteral(term.value); - break; - case "variable": - this.write(`push ${this.var(term)}`); - break; - case "keywordLiteral": - this.compileKeywordLiteral(term.value); - break; - case "subroutineCall": - this.compileSubroutineCall(term); - break; - case "arrayAccess": - this.compileExpression(term.index); - this.write( - `push ${this.var(term)}`, - "add", - "pop pointer 1", - "push that 0", - ); - break; - case "groupedExpression": - this.compileExpression(term.expression); - break; - case "unaryExpression": - this.compileTerm(term.term); - this.write(unaryOps[term.op]); - } + } + + validateArgNum(name: string, expected: number, call: SubroutineCall) { + const received = call.parameters.length; + if (expected != received) { + throw createError( + `${name} expected ${expected} arguments, got ${received}`, + call.span, + ); } - - validateArgNum(name: string, expected: number, call: SubroutineCall) { - const received = call.parameters.length; - if (expected != received) { + } + + validateSubroutineCall( + className: string, + subroutineName: string, + call: SubroutineCall, + isMethod: boolean, + ) { + const builtin = VM_BUILTINS[`${className}.${subroutineName}`]; + if (builtin) { + if (builtin.type == "method" && !isMethod) { throw createError( - `${name} expected ${expected} arguments, got ${received}`, - call.span, + `Method ${className}.${subroutineName} was called as a function/constructor`, + call.name.span, ); } - } - - validateSubroutineCall( - className: string, - subroutineName: string, - call: SubroutineCall, - isMethod: boolean, - ) { - const builtin = VM_BUILTINS[`${className}.${subroutineName}`]; - if (builtin) { - if (builtin.type == "method" && !isMethod) { - throw createError( - `Method ${className}.${subroutineName} was called as a function/constructor`, - call.name.span, - ); - } - if (builtin.type != "method" && isMethod) { - throw createError( - `${capitalize( - builtin.type, - )} ${className}.${subroutineName} was called as a method`, - call.name.span, - ); - } - this.validateArgNum( - `${className}.${subroutineName}`, - builtin.args.length, - call, - ); - return; - } else if (this.classes[className]) { - for (const subroutine of this.classes[className].subroutines) { - if (subroutine.name.value == subroutineName) { - if (subroutine.type == "method" && !isMethod) { - throw createError( - `Method ${className}.${subroutineName} was called as a function/constructor`, - call.name.span, - ); - } - if (subroutine.type != "method" && isMethod) { - throw createError( - `${capitalize( - subroutine.name.value, - )} ${className}.${subroutineName} was called as a method`, - call.name.span, - ); - } - this.validateArgNum( - `${className}.${subroutineName}`, - subroutine.parameters.length, - call, - ); - return; - } - } + if (builtin.type != "method" && isMethod) { throw createError( - `Class ${className} doesn't contain a function/constructor ${subroutineName}`, + `${capitalize( + builtin.type, + )} ${className}.${subroutineName} was called as a method`, call.name.span, ); - } else { - throw createError(`Class ${className} doesn't exist`, call.name.span); } - } - - classifySubroutineCall(call: SubroutineCall): SubroutineCallAttributes { - let object: string | undefined; - let className = ""; - let subroutineName = ""; - - if (call.name.value.includes(".")) { - const [prefix, suffix] = call.name.value.split(".", 2); - subroutineName = suffix; - const varData = this.varData(prefix); - if (varData) { - // external method call - object = this.var(prefix); - className = varData.type; - } else { - // function / constructor call - className = prefix; - } - } else { - object = "pointer 0"; // this - className = this.className; - subroutineName = call.name.value; - } - - this.validateSubroutineCall( - className, - subroutineName, + this.validateArgNum( + `${className}.${subroutineName}`, + builtin.args.length, call, - object != undefined, ); - - return { className, subroutineName, object }; - } - - compileSubroutineCall(call: SubroutineCall) { - const attributes = this.classifySubroutineCall(call); - - if (attributes.object) { - this.write(`push ${attributes.object}`); - } - for (const param of call.parameters) { - this.compileExpression(param); + return; + } else if (this.classes[className]) { + for (const subroutine of this.classes[className].subroutines) { + if (subroutine.name.value == subroutineName) { + if (subroutine.type == "method" && !isMethod) { + throw createError( + `Method ${className}.${subroutineName} was called as a function/constructor`, + call.name.span, + ); + } + if (subroutine.type != "method" && isMethod) { + throw createError( + `${capitalize( + subroutine.name.value, + )} ${className}.${subroutineName} was called as a method`, + call.name.span, + ); + } + this.validateArgNum( + `${className}.${subroutineName}`, + subroutine.parameters.length, + call, + ); + return; + } } - this.write( - `call ${attributes.className}.${attributes.subroutineName} ${ - call.parameters.length + (attributes.object ? 1 : 0) - }`, + throw createError( + `Class ${className} doesn't contain a function/constructor ${subroutineName}`, + call.name.span, ); + } else { + throw createError(`Class ${className} doesn't exist`, call.name.span); } - - compileStringLiteral(str: string) { - this.write(`push constant ${str.length}`, `call String.new 1`); - for (let i = 0; i < str.length; i++) { - this.write( - `push constant ${str.charCodeAt(i)}`, - `call String.appendChar 2`, - ); - } - } - - compileKeywordLiteral(keyword: KeywordConstant) { - switch (keyword) { - case "true": - this.write(`push constant 1`, `neg`); - break; - case "false": - this.write(`push constant 0`); - break; - case "null": - this.write(`push constant 0`); - break; - case "this": - this.write(`push pointer 0`); - } - } - - compileStatements(statements: Statement[]) { - for (const statement of statements) { - this.compileStatement(statement); - } - } - - compileStatement(statement: Statement) { - switch (statement.statementType) { - case "doStatement": - this.compileDoStatement(statement); - break; - case "ifStatement": - this.compileIf(statement); - break; - case "letStatement": - this.compileLet(statement); - break; - case "returnStatement": - this.compileReturn(statement); - break; - case "whileStatement": - this.compileWhile(statement); - } - } - - compileReturn(statement: ReturnStatement) { - if (statement.value) { - this.compileExpression(statement.value); + } + + classifySubroutineCall(call: SubroutineCall): SubroutineCallAttributes { + let object: string | undefined; + let className = ""; + let subroutineName = ""; + + if (call.name.value.includes(".")) { + const [prefix, suffix] = call.name.value.split(".", 2); + subroutineName = suffix; + const varData = this.varData(prefix); + if (varData) { + // external method call + object = this.var(prefix); + className = varData.type; } else { - this.write(`push constant 0`); // return 0 + // function / constructor call + className = prefix; } - this.write(`return`); + } else { + object = "pointer 0"; // this + className = this.className; + subroutineName = call.name.value; + } + + this.validateSubroutineCall( + className, + subroutineName, + call, + object != undefined, + ); + + return { className, subroutineName, object }; + } + + compileSubroutineCall(call: SubroutineCall) { + const attributes = this.classifySubroutineCall(call); + + if (attributes.object) { + this.write(`push ${attributes.object}`); + } + for (const param of call.parameters) { + this.compileExpression(param); + } + this.write( + `call ${attributes.className}.${attributes.subroutineName} ${ + call.parameters.length + (attributes.object ? 1 : 0) + }`, + ); + } + + compileStringLiteral(str: string) { + this.write(`push constant ${str.length}`, `call String.new 1`); + for (let i = 0; i < str.length; i++) { + this.write( + `push constant ${str.charCodeAt(i)}`, + `call String.appendChar 2`, + ); } - - compileLet(statement: LetStatement) { - if (statement.arrayIndex) { - this.compileExpression(statement.arrayIndex); - this.write(`push ${this.var(statement)}`, "add"); - this.compileExpression(statement.value); - this.write("pop temp 0", "pop pointer 1", "push temp 0", "pop that 0"); - } else { - this.compileExpression(statement.value); - this.write(`pop ${this.var(statement)}`); - } + } + + compileKeywordLiteral(keyword: KeywordConstant) { + switch (keyword) { + case "true": + this.write(`push constant 1`, `neg`); + break; + case "false": + this.write(`push constant 0`); + break; + case "null": + this.write(`push constant 0`); + break; + case "this": + this.write(`push pointer 0`); } - - compileDoStatement(statement: DoStatement) { - this.compileSubroutineCall(statement.call); - this.write(`pop temp 0`); + } + + compileStatements(statements: Statement[]) { + for (const statement of statements) { + this.compileStatement(statement); } - - compileIf(statement: IfStatement) { - const condTrue = this.getLabel(); - const condFalse = this.getLabel(); - - this.compileExpression(statement.condition); - this.write("not", `if-goto ${condFalse}`); - this.compileStatements(statement.body); - this.write(`goto ${condTrue}`, `label ${condFalse}`); - this.compileStatements(statement.else); - this.write(`label ${condTrue}`); + } + + compileStatement(statement: Statement) { + switch (statement.statementType) { + case "doStatement": + this.compileDoStatement(statement); + break; + case "ifStatement": + this.compileIf(statement); + break; + case "letStatement": + this.compileLet(statement); + break; + case "returnStatement": + this.compileReturn(statement); + break; + case "whileStatement": + this.compileWhile(statement); } - - compileWhile(statement: WhileStatement) { - const loop = this.getLabel(); - const exit = this.getLabel(); - - this.write(`label ${loop}`); - this.compileExpression(statement.condition); - this.write(`not`, `if-goto ${exit}`); - this.compileStatements(statement.body); - this.write(`goto ${loop}`, `label ${exit}`); + } + + compileReturn(statement: ReturnStatement) { + if (statement.value) { + this.compileExpression(statement.value); + } else { + this.write(`push constant 0`); // return 0 + } + this.write(`return`); + } + + compileLet(statement: LetStatement) { + if (statement.arrayIndex) { + this.compileExpression(statement.arrayIndex); + this.write(`push ${this.var(statement)}`, "add"); + this.compileExpression(statement.value); + this.write("pop temp 0", "pop pointer 1", "push temp 0", "pop that 0"); + } else { + this.compileExpression(statement.value); + this.write(`pop ${this.var(statement)}`); } } - \ No newline at end of file + + compileDoStatement(statement: DoStatement) { + this.compileSubroutineCall(statement.call); + this.write(`pop temp 0`); + } + + compileIf(statement: IfStatement) { + const condTrue = this.getLabel(); + const condFalse = this.getLabel(); + + this.compileExpression(statement.condition); + this.write("not", `if-goto ${condFalse}`); + this.compileStatements(statement.body); + this.write(`goto ${condTrue}`, `label ${condFalse}`); + this.compileStatements(statement.else); + this.write(`label ${condTrue}`); + } + + compileWhile(statement: WhileStatement) { + const loop = this.getLabel(); + const exit = this.getLabel(); + + this.write(`label ${loop}`); + this.compileExpression(statement.condition); + this.write(`not`, `if-goto ${exit}`); + this.compileStatements(statement.body); + this.write(`goto ${loop}`, `label ${exit}`); + } +} diff --git a/simulator/src/jack/controlFlow.ts b/simulator/src/jack/controlFlow.ts new file mode 100644 index 00000000..be962a06 --- /dev/null +++ b/simulator/src/jack/controlFlow.ts @@ -0,0 +1,180 @@ +import { + Err, + Ok, + Result, + isErr, + unwrap, +} from "@davidsouther/jiffies/lib/esm/result.js"; +import { CompilationError, createError } from "../languages/base.js"; +import { + IfStatement, + ReturnType, + Statement, + Subroutine, + WhileStatement, +} from "../languages/jack.js"; + +class CFGNode { + id: number; + hasReturn = false; + children: CFGNode[] = []; + + static count = 0; + + constructor() { + this.id = CFGNode.count; + CFGNode.count += 1; + } + + alwaysReturns(): boolean { + const visited: Set = new Set(); + + function checkReturn(node: CFGNode): boolean { + if (node.hasReturn) { + return true; + } else if (node.children.length === 0) { + return false; + } + visited.add(node); + for (const child of node.children) { + if (!visited.has(child) && !checkReturn(child)) { + return false; + } + } + return true; + } + + return checkReturn(this); + } + + getLeafs(): CFGNode[] { + const leafs: Set = new Set(); + const visited: Set = new Set(); + + function findLeafs(node: CFGNode) { + if (node.children.length === 0) { + leafs.add(node); + } else { + visited.add(node); + for (const child of node.children) { + if (!visited.has(child)) { + findLeafs(child); + } + } + } + } + + findLeafs(this); + return Array.from(leafs); + } +} + +function processIf( + statement: IfStatement, + returnType: ReturnType, + current: CFGNode, +): Result { + const ifStart = new CFGNode(); + current.children.push(ifStart); + current = ifStart; + const result1 = buildCFG(statement.body, returnType); + const result2 = buildCFG(statement.else, returnType); + if (isErr(result1)) { + return result1; + } + if (isErr(result2)) { + return result2; + } + const path1 = unwrap(result1); + const path2 = unwrap(result2); + current.children.push(path1, path2); + const leafs = path1.getLeafs().concat(path2.getLeafs()); + current = new CFGNode(); + for (const leaf of leafs) { + leaf.children.push(current); + } + return Ok(current); +} + +function processWhile( + statement: WhileStatement, + returnType: ReturnType, + current: CFGNode, +): Result { + const whileStart = new CFGNode(); + current.children.push(whileStart); + current = whileStart; + const result = buildCFG(statement.body, returnType); + if (isErr(result)) { + return result; + } + const body = unwrap(result); + for (const leaf of body.getLeafs()) { + leaf.children.push(current); + } + const next = new CFGNode(); + current.children.push(body, next); + current = next; + return Ok(current); +} + +function buildCFG( + statements: Statement[], + returnType: ReturnType, +): Result { + const root = new CFGNode(); + let current = root; + + let result: Result | undefined; + for (const statement of statements) { + switch (statement.statementType) { + case "letStatement": + case "doStatement": + break; + case "returnStatement": + if (returnType != "void" && statement.value == undefined) { + return Err( + createError( + `A non void subroutine must return a value`, + statement.span, + ), + ); + } + current.hasReturn = true; + break; + case "ifStatement": + result = processIf(statement, returnType, current); + if (isErr(result)) { + return result; + } + current = unwrap(result); + break; + case "whileStatement": + result = processWhile(statement, returnType, current); + if (isErr(result)) { + return result; + } + current = unwrap(result); + break; + } + } + return Ok(root); +} + +export function validateSubroutine( + subroutine: Subroutine, +): Result { + const cfg = buildCFG(subroutine.body.statements, subroutine.returnType.value); + if (isErr(cfg)) { + return cfg; + } + if (!unwrap(cfg).alwaysReturns()) { + return Err( + createError( + `Subroutine ${subroutine.name.value}: not all code paths return a value`, + subroutine.name.span, + ), + ); + } + return Ok(); +} diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index ae3b6d81..27a685ad 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -101,7 +101,10 @@ export class VMWriter extends JackParserListener { } this.pushSymbolOntoStack(symbol); this.result += ` add\n`; - if (this.inAssignmentRightHandSide || ctx.parentCtx instanceof ExpressionContext) { + if ( + this.inAssignmentRightHandSide || + ctx.parentCtx instanceof ExpressionContext + ) { this.result += ` pop pointer 1\n`; this.result += ` push that 0\n`; } From 131763512653012c4b9347eb22e03fff0fdd8234 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:38:38 +0200 Subject: [PATCH 54/87] WIP --- simulator/src/jack/README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 simulator/src/jack/README.md diff --git a/simulator/src/jack/README.md b/simulator/src/jack/README.md new file mode 100644 index 00000000..43fba9f1 --- /dev/null +++ b/simulator/src/jack/README.md @@ -0,0 +1,33 @@ +# ANTLR Jack compiler +ANTLR gives us ability to generate lexer and parser in the target programming language(typescript in this case) using grammar files for [lexer](src/languages/grammars/JackLexer.g4) and [parser](src/languages/grammars/JackParser.g4). + +After parsing is done we get a tree data structure as an output. To do anything useful with this this tree we can use the next 2 design patterns: +1) Listener +2) Visitor +You can read more about this design patterns and the difference between them on on this [blog post](https://tomassetti.me/listeners-and-visitors/). You can also check out [antlr mega tutorial from the same company](https://tomassetti.me/antlr-mega-tutorial/). + +For jack we use next listeners: +- Error listener - listens to lexer and parser errors +- Binder listener - creates global symbol table (classes and subroutines symbols) +- Validator listener - validates jack program +- VM Writer listener - generates VM code + +# Regenerate Jack Lexer and Parser files + +Next command gives us ability to regenerate parser and lexer after we've changed the grammar (.g4 files) for [lexer](src/languages/grammars/JackLexer.g4) or [parser](src/languages/grammars/JackParser.g4) + +``` +npm run gen +``` +To run this command we would need to install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md). +``` +pip install antlr4-tools +``` +Underneath the covers previous command will install Java runtime(JRE)(if you don't have java installed on your machine) and antlr4-{version}-complete.jar from maven. + +Beside generating lexer and parser files this tools include `antlr4-parse` that you can use to parser an input jack file and visualize the AST tree or view the token stream in command line. + +Small note - If you are using VSCode there is an extension to work with ANTLR grammar files. + +# Working with typescript antlr runtime +As ANTLR main target for web is Javascript it doesn't have a typescript source code in general sense. Basically typescript runtime is a collection of javascript files and `.d.ts` files to provide typescript types. If you want to find out what's going on underneath the covers go to [antlr github page](https://github.com/antlr/antlr4/tree/dev/runtime/JavaScript) and find the javascript sources. \ No newline at end of file From 06432ba3e6437f6a07cee0782a9d9542e30155cf Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:39:12 +0200 Subject: [PATCH 55/87] WIP --- simulator/README.md | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 simulator/README.md diff --git a/simulator/README.md b/simulator/README.md deleted file mode 100644 index a2369e1a..00000000 --- a/simulator/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Regenerate Jack Lexer and Parser files - -Next command gives us ability to regenerate parser and lexer after we've changed the grammar (.g4 files) for [lexer](src/languages/grammars/JackLexer.g4) or [parser](src/languages/grammars/JackParser.g4) - -``` -npm run gen -``` -To run this command we would need to install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md). Antlr 4 tools provides commands to generate lexer and parser files. Beside that it includes `antlr4-parse` that you can use to parser an input jack file and visualize the AST tree or view the token stream. More details on [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md) page. - -``` -pip install antlr4-tools -``` -Underneath the covers previous command will install Java runtime(JRE)(if you don't have java installed on your machine) and antlr4-{version}-complete.jar from maven. \ No newline at end of file From 46998c6d65b70c3bbb254a798a0e79563d564295 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:40:23 +0200 Subject: [PATCH 56/87] WIP --- simulator/src/jack/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/simulator/src/jack/README.md b/simulator/src/jack/README.md index 43fba9f1..c08c0f5f 100644 --- a/simulator/src/jack/README.md +++ b/simulator/src/jack/README.md @@ -4,7 +4,8 @@ ANTLR gives us ability to generate lexer and parser in the target programming la After parsing is done we get a tree data structure as an output. To do anything useful with this this tree we can use the next 2 design patterns: 1) Listener 2) Visitor -You can read more about this design patterns and the difference between them on on this [blog post](https://tomassetti.me/listeners-and-visitors/). You can also check out [antlr mega tutorial from the same company](https://tomassetti.me/antlr-mega-tutorial/). + +You can read more about this design patterns and the difference between them in this [blog post](https://tomassetti.me/listeners-and-visitors/). You can also check out [antlr mega tutorial from the same company](https://tomassetti.me/antlr-mega-tutorial/). For jack we use next listeners: - Error listener - listens to lexer and parser errors From 49706486f8caa98f9aaf7f974032a8ea46a4bb34 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:42:54 +0200 Subject: [PATCH 57/87] WIP --- simulator/src/jack/builtins.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulator/src/jack/builtins.ts b/simulator/src/jack/builtins.ts index 672dc2f2..3f9388c3 100644 --- a/simulator/src/jack/builtins.ts +++ b/simulator/src/jack/builtins.ts @@ -5,7 +5,7 @@ interface Range { min: number; max: number; } -export const intRange = { min: -32768, max: 32767 } as Range; +export const intRange:Range = { min: -32768, max: 32767 }; const builtInFunctionsToArgCount: Record = { "Array.dispose": 0, "Array.init": 0, From 80305093a658e27d96e599a3902ea4f55e0780f5 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:44:13 +0200 Subject: [PATCH 58/87] WIP --- simulator/src/jack/builtins.ts | 3 +++ simulator/src/jack/error.ts | 7 ++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/simulator/src/jack/builtins.ts b/simulator/src/jack/builtins.ts index 3f9388c3..74b80ce6 100644 --- a/simulator/src/jack/builtins.ts +++ b/simulator/src/jack/builtins.ts @@ -5,7 +5,9 @@ interface Range { min: number; max: number; } + export const intRange:Range = { min: -32768, max: 32767 }; + const builtInFunctionsToArgCount: Record = { "Array.dispose": 0, "Array.init": 0, @@ -58,6 +60,7 @@ const builtInFunctionsToArgCount: Record = { "Sys.halt": 0, "Sys.wait": 1, }; + const builtInClasses = [ "Array", "Keyboard", diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 9f2a3684..63ac1559 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,8 +1,5 @@ -export interface Span { - start: number; - end: number; - line: number; -} +import { Span } from "../languages/base"; + export class JackCompilerError { public span: Span; constructor( From c05caa95451364029f01669f3607fda4c9a36487 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:45:03 +0200 Subject: [PATCH 59/87] WIP --- simulator/src/jack/error.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 63ac1559..7b85042a 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,7 +1,7 @@ import { Span } from "../languages/base"; export class JackCompilerError { - public span: Span; + span: Span; constructor( line: number, startInd: number, From 074b74a47485ef99ef51adbb9d7c118841099259 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:47:35 +0200 Subject: [PATCH 60/87] WIP --- simulator/src/jack/error.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 7b85042a..bbb763fa 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -118,7 +118,6 @@ export class VoidSubroutineReturnsValueError extends JackCompilerError { endIndex, `Cannot return a value from a void subroutine`, ); - Object.setPrototypeOf(this, VoidSubroutineReturnsValueError.prototype); } } From f4d54d8e2d98dea81ee4cdc12c0b44d60d11ea4b Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:50:03 +0200 Subject: [PATCH 61/87] WIP --- simulator/src/jack/listener/binder.listener.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/binder.listener.test.ts index 996c8cc6..71d3630e 100644 --- a/simulator/src/jack/listener/binder.listener.test.ts +++ b/simulator/src/jack/listener/binder.listener.test.ts @@ -105,8 +105,8 @@ function testBinder( } catch (e) { throw new Error( `Expected error ${expectedError.name} but got '` + - errors.join(",") + - "'", + errors.join(",") + + "'", ); } } else { From c5d82430c4e92c514a9d778489169a8f47a6bd10 Mon Sep 17 00:00:00 2001 From: David Souther Date: Tue, 8 Oct 2024 23:30:41 -0400 Subject: [PATCH 62/87] Used string enum for tagged error types --- simulator/src/jack/anltr.compiler.ts | 2 +- simulator/src/jack/error.ts | 341 +++--------------- .../src/jack/listener/binder.listener.ts | 26 +- simulator/src/jack/listener/error.listener.ts | 22 +- .../jack/listener/validator.listener.test.ts | 93 ++--- .../src/jack/listener/validator.listener.ts | 168 ++------- simulator/src/jack/test.helper.ts | 3 +- 7 files changed, 154 insertions(+), 501 deletions(-) diff --git a/simulator/src/jack/anltr.compiler.ts b/simulator/src/jack/anltr.compiler.ts index f8f10262..9ef77046 100644 --- a/simulator/src/jack/anltr.compiler.ts +++ b/simulator/src/jack/anltr.compiler.ts @@ -97,7 +97,7 @@ function _do( function toCompilerError(errors: JackCompilerError[]): CompilationError { const err = errors[0]; return { - message: `Line ${err.span.line}: ${err.msg}`, + message: `Line ${err.span.line}: ${err.message}`, span: err.span, } as CompilationError; } diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index bbb763fa..71740ed6 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,283 +1,60 @@ -import { Span } from "../languages/base"; - -export class JackCompilerError { +import { Token } from "antlr4"; +import { CompilationError, Span } from "../languages/base"; + +export type JackCompilerErrorType = "ConstructorMushReturnThisError" | +"DuplicatedClassError" | +"DuplicatedSubroutineError" | +"DuplicatedVariableError" | +"FieldCantBeReferencedInFunctionError" | +"FilenameDoesntMatchClassNameError" | +"FunctionCalledAsMethodError" | +"IncorrectConstructorReturnTypeError" | +"IncorrectParamsNumberInSubroutineCallError" | +"IntLiteralIsOutOfRangeError" | +"LexerOrParserError" | +"MethodCalledAsFunctionError" | +"NonVoidFunctionNoReturnError" | +"SubroutineNotAllPathsReturnError" | +"ThisCantBeReferencedInFunctionError" | +"UndeclaredVariableError" | +"UnknownClassError" | +"UnknownSubroutineCallError" | +"UnreachableCodeError" | +"VoidSubroutineReturnsValueError" | +"WrongLiteralTypeError"; + +export interface JackCompilerError extends CompilationError { + type: JackCompilerErrorType; span: Span; - constructor( - line: number, - startInd: number, - endIndex: number, - public msg: string, - ) { - this.span = { start: startInd, end: endIndex, line: line }; - } - public toString = (): string => { - return ( - this.constructor.name + - `(${this.span.line}:${this.span.start}:${this.span.end} ${this.msg})` - ); - }; -} - -export class LexerOrParserError extends JackCompilerError {} -export class DuplicatedSubroutineError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - subroutineName: string, - ) { - super( - line, - startInd, - endIndex, - `Subroutine ${subroutineName} is already defined.`, - ); - } -} -export class DuplicatedClassError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - className: string, - ) { - super(line, startInd, endIndex, `Class ${className} is already defined.`); - } -} -export class FilenameDoesntMatchClassName extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - filename: string, - className: string, - ) { - super( - line, - startInd, - endIndex, - `Class name ${className} doesn't match file name ${filename}`, - ); - } -} - -export class DuplicatedVariableException extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - variableName: string, - ) { - super( - line, - startInd, - endIndex, - "Duplicated local variable, field, argument or static variable " + - variableName, - ); - } -} - -export class UndeclaredVariableError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - variableName: string, - ) { - super(line, startInd, endIndex, "Undeclared variable " + variableName); - } -} -export class UnknownClassError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - className: string, - ) { - super(line, startInd, endIndex, `Class ${className} doesn't exist`); - } -} - -export class NonVoidFunctionNoReturnError extends JackCompilerError { - constructor(line: number, startInd: number, endIndex: number) { - super( - line, - startInd, - endIndex, - `A non void subroutine must return a value`, - ); - } -} - -export class VoidSubroutineReturnsValueError extends JackCompilerError { - constructor(line: number, startInd: number, endIndex: number) { - super( - line, - startInd, - endIndex, - `Cannot return a value from a void subroutine`, - ); - } -} - -export class SubroutineNotAllPathsReturnError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - subroutineName: string, - ) { - super( - line, - startInd, - endIndex, - `Subroutine ${subroutineName}: not all code paths return a value`, - ); - Object.setPrototypeOf(this, SubroutineNotAllPathsReturnError.prototype); - } -} - -export class IncorrectParamsNumberInSubroutineCallError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - subroutineName: string, - expectedParamsCount: number, - actualParamsCount: number, - ) { - super( - line, - startInd, - endIndex, - `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)`, - ); - Object.setPrototypeOf( - this, - IncorrectParamsNumberInSubroutineCallError.prototype, - ); - } -} -export class UnknownSubroutineCallError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - subroutineName: string, - className?: string, - ) { - super( - line, - startInd, - endIndex, - `Can't find subroutine '${subroutineName}'${className ? ` in ${className}` : ""}`, - ); - Object.setPrototypeOf(this, UnknownSubroutineCallError.prototype); - } -} -export class MethodCalledAsFunctionError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - subroutineId: string, - ) { - super( - line, - startInd, - endIndex, - `Method ${subroutineId} was called as a function/constructor`, - ); - Object.setPrototypeOf(this, MethodCalledAsFunctionError.prototype); - } -} -export class FunctionCalledAsMethodError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - subroutineId: string, - ) { - super( - line, - startInd, - endIndex, - `Function or constructor ${subroutineId} was called as a method`, - ); - Object.setPrototypeOf(this, FunctionCalledAsMethodError.prototype); - } -} - -export class IncorrectConstructorReturnType extends JackCompilerError { - constructor(line: number, startInd: number, endIndex: number) { - super( - line, - startInd, - endIndex, - `The return type of a constructor must be of the class type`, - ); - Object.setPrototypeOf(this, IncorrectConstructorReturnType.prototype); - } -} - -export class UnreachableCodeError extends JackCompilerError { - constructor(line: number, startInd: number, endIndex: number) { - super(line, startInd, endIndex, `Unreachable code`); - Object.setPrototypeOf(this, UnreachableCodeError.prototype); - } -} - -export class ConstructorMushReturnThis extends JackCompilerError { - constructor(line: number, startInd: number, endIndex: number) { - super(line, startInd, endIndex, `A constructor must return 'this'`); - Object.setPrototypeOf(this, ConstructorMushReturnThis.prototype); - } -} - -const vowels = "aeiou"; -export class WrongLiteralTypeError extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - typeName: string, - ) { - const article = vowels.indexOf(typeName.substring(0, 1)) != -1 ? "an" : "a"; - super(line, startInd, endIndex, `${article} ${typeName} value is expected`); - Object.setPrototypeOf(this, WrongLiteralTypeError.prototype); - } -} - -export class IntLiteralIsOutOfRange extends JackCompilerError { - constructor( - line: number, - startInd: number, - endIndex: number, - value: number, - min: number, - max: number, - ) { - super( - line, - startInd, - endIndex, - `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}`, - ); - Object.setPrototypeOf(this, IntLiteralIsOutOfRange.prototype); - } -} - -export class FieldCantBeReferencedInFunction extends JackCompilerError { - constructor(line: number, startInd: number, endIndex: number) { - super(line, startInd, endIndex, `Field can't be referenced in a function`); - Object.setPrototypeOf(this, FieldCantBeReferencedInFunction.prototype); - } -} - -export class ThisCantBeReferencedInFunction extends JackCompilerError { - constructor(line: number, startInd: number, endIndex: number) { - super(line, startInd, endIndex, `this can't be referenced in a function`); - Object.setPrototypeOf(this, ThisCantBeReferencedInFunction.prototype); - } -} +}; + +export function makeJackCompilerError(type: JackCompilerErrorType, span: Span, msg?: string): JackCompilerError { + return { + type, span, message: `${type} (${span.line}:${span.start}:${span.end}${msg ? ' ' + msg : ''})` + } +} + +export const LexerOrParserError = (span: Span) => makeJackCompilerError('LexerOrParserError', span); +export const DuplicatedSubroutineError = (span: Span, subroutineName: string) => makeJackCompilerError('DuplicatedClassError', span, `Subroutine ${subroutineName} is already defined.`,); +export const DuplicatedClassError = (span: Span, className: string) => makeJackCompilerError('DuplicatedClassError', span, `Class ${className} is already defined.`); +export const FilenameDoesntMatchClassNameError = (span: Span, filename: string, className: string) => makeJackCompilerError('FilenameDoesntMatchClassNameError', span, `Class name ${className} doesn't match file name ${filename}`); +export const DuplicatedVariableError = (span: Span, variableName: string) => makeJackCompilerError('DuplicatedVariableError', span, `Duplicated local variable, field, argument or static variable ${variableName}`); +export const UndeclaredVariableError = (span: Span, variableName: string) => makeJackCompilerError('UndeclaredVariableError', span, `Undeclared variable ${variableName}`); +export const UnknownClassError = (span: Span, className: string) => makeJackCompilerError('UnknownClassError', span, `Class ${className} doesn't exist`); +export const NonVoidFunctionNoReturnError = (span: Span) => makeJackCompilerError('NonVoidFunctionNoReturnError', span, `A non void subroutine must return a value`); +export const VoidSubroutineReturnsValueError = (span: Span) => makeJackCompilerError('VoidSubroutineReturnsValueError', span, 'Cannot return a value from a void subroutine'); +export const SubroutineNotAllPathsReturnError = (span: Span, subroutineName: string) => makeJackCompilerError('SubroutineNotAllPathsReturnError', span, `Subroutine ${subroutineName}: not all code paths return a value`); +export const IncorrectParamsNumberInSubroutineCallError = (span: Span, subroutineName: string, expectedParamsCount: number, actualParamsCount: number,) => makeJackCompilerError("IncorrectParamsNumberInSubroutineCallError", span, `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)`); +export const UnknownSubroutineCallError = (span: Span, subroutineName: string, className?: string,) => makeJackCompilerError('UnknownSubroutineCallError', span, `Can't find subroutine '${subroutineName}'${className ? ` in ${className}` : ""}`); +export const MethodCalledAsFunctionError = (span: Span, subroutineId: string) => makeJackCompilerError('MethodCalledAsFunctionError', span, `Method ${subroutineId} was called as a function/constructor`); +export const FunctionCalledAsMethodError = (span: Span, subroutineId: string) => makeJackCompilerError('FunctionCalledAsMethodError', span, `Function or constructor ${subroutineId} was called as a method`); +export const IncorrectConstructorReturnTypeError = (span: Span) => makeJackCompilerError("IncorrectConstructorReturnTypeError", span, `The return type of a constructor must be of the class type`); +export const UnreachableCodeError = (span: Span) => makeJackCompilerError("UnreachableCodeError", span); +export const ConstructorMushReturnThisError = (span: Span) => makeJackCompilerError('ConstructorMushReturnThisError', span, `A constructor must return 'this'`); +const vowels = new Set("aeiou".split('')); +export const WrongLiteralTypeError = (span: Span, typeName: string) => makeJackCompilerError('WrongLiteralTypeError', span, `${vowels.has(typeName.charAt(0)) ? "an" : "a"} ${typeName} value is expected`) +export const IntLiteralIsOutOfRangeError = (span: Span, value: number, min: number, max: number,) => makeJackCompilerError('IntLiteralIsOutOfRangeError', span, `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}`,); +export const FieldCantBeReferencedInFunctionError = (span: Span) => makeJackCompilerError('FieldCantBeReferencedInFunctionError', span, `Field can't be referenced in a function`); +export const ThisCantBeReferencedInFunctionError = (span: Span) => makeJackCompilerError('ThisCantBeReferencedInFunctionError', span, `this can't be referenced in a function`); + +export const asSpan = ({line, start, stop: startEnd}: Token, stop?: Token): Span => ({ line, start, end: stop ? stop.stop : startEnd }); \ No newline at end of file diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/binder.listener.ts index 7266e142..e13348c0 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/binder.listener.ts @@ -4,7 +4,7 @@ import { SubroutineDeclarationContext, VarNameInDeclarationContext, } from "../generated/JackParser.js"; -import { DuplicatedClassError, DuplicatedSubroutineError } from "../error.js"; +import { asSpan, DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error.js"; import { builtInSymbols, builtInTypes } from "../builtins.js"; import { GenericSymbol, @@ -13,6 +13,7 @@ import { SubroutineType, } from "../symbol.js"; import JackParserListener from "../generated/JackParserListener.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; @@ -24,21 +25,20 @@ export class BinderListener extends JackParserListener { // key can be class or . public globalSymbolTable: GlobalSymbolTable = structuredClone(builtInSymbols); public className = ""; - public errors: DuplicatedSubroutineError[] = []; + // public errors: DuplicatedSubroutineError[] = []; + public errors: JackCompilerError[] = []; private subRoutineInfo: SubroutineInfo = {} as SubroutineInfo; private subroutineVarsCount = 0; private stopProcessingSubroutines = false; private subroutineId = ""; override enterClassDeclaration = (ctx: ClassDeclarationContext) => { - const id = ctx.className()!.IDENTIFIER(); + const ctxClassName = assertExists(ctx.className()); + const id = ctxClassName.IDENTIFIER(); const className = id.getText(); if (this.globalSymbolTable[className] != undefined) { - const e = new DuplicatedClassError( - ctx.className()!.start.line, - ctx.className()!.start.start, - ctx.className()!.stop!.stop + 1, - className, + const e = DuplicatedClassError( + asSpan(ctxClassName.start, ctxClassName.stop), className ); this.errors.push(e); return; @@ -64,10 +64,12 @@ export class BinderListener extends JackParserListener { const id = this.className + "." + subroutineName; if (this.globalSymbolTable[id] != undefined) { this.errors.push( - new DuplicatedSubroutineError( - nameCtx.IDENTIFIER().symbol.line, - nameCtx.start.start, - nameCtx.start.stop, + DuplicatedSubroutineError( + { + line: nameCtx.IDENTIFIER().symbol.line, + start: nameCtx.start.start, + end: nameCtx.start.stop, + }, subroutineName, ), ); diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 88af922e..1a422b12 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -18,26 +18,20 @@ export class CustomErrorListener extends ErrorListener { line: number, column: number, msg: string, - e: RecognitionException | undefined, + err: RecognitionException | undefined, ) => { - if (offendingSymbol != null || (e != null && e.offendingToken != null)) { - const t = offendingSymbol ?? (e!.offendingToken as Token); - this.errors.push(new LexerOrParserError(line, t.start, t.stop + 1, msg)); - } else if (e instanceof NoViableAltException) { + if (offendingSymbol != null || (err?.offendingToken)) { + const t = offendingSymbol ?? (err!.offendingToken as Token); + this.errors.push(LexerOrParserError({line, start: t.start, end: t.stop + 1})); + } else if (err instanceof NoViableAltException) { this.errors.push( - new LexerOrParserError( - line, - e.startToken.start, - e.startToken.stop + 1, - msg, - ), + LexerOrParserError({line, start: err.startIndex, end: err.startIndex + 1}) ); } //antlr doesn't provide a class for LexerNoViableAltException atm. Once https://github.com/antlr/antlr4/pull/4711 is release we can change it - else if (e != null && "startIndex" in e) { - const err = e as LexerNoViableAltException; + else if (err != null && "startIndex" in err) { this.errors.push( - new LexerOrParserError(line, err.startIndex, err.startIndex + 1, msg), + LexerOrParserError({line, start: err.startIndex, end: err.startIndex + 1}, msg), ); } else { console.error("Don't know how to handle this error"); diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index 86818398..d8280901 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -1,23 +1,3 @@ -import { - ConstructorMushReturnThis, - DuplicatedVariableException as DuplicatedVariableError, - FieldCantBeReferencedInFunction, - FilenameDoesntMatchClassName, - FunctionCalledAsMethodError, - IncorrectConstructorReturnType, - IncorrectParamsNumberInSubroutineCallError, - IntLiteralIsOutOfRange as IntLiteralOverflow, - MethodCalledAsFunctionError, - NonVoidFunctionNoReturnError, - SubroutineNotAllPathsReturnError, - ThisCantBeReferencedInFunction, - UndeclaredVariableError, - UnknownClassError, - UnknownSubroutineCallError, - UnreachableCodeError, - VoidSubroutineReturnsValueError, - WrongLiteralTypeError, -} from "../error"; import { CustomErrorListener } from "./error.listener"; import { ValidatorListener } from "./validator.listener"; import { @@ -36,6 +16,7 @@ import fs from "fs"; import { BinderListener } from "./binder.listener"; import path from "path"; import { ProgramContext } from "../generated/JackParser"; +import { JackCompilerErrorType } from "../error"; describe("Jack validator listener", () => { const jestConsole = console; beforeEach(() => { @@ -86,7 +67,7 @@ describe("Jack validator listener", () => { class Main { ${classBody} }`, - DuplicatedVariableError, + 'DuplicatedVariableError', ); }, ); @@ -103,7 +84,7 @@ describe("Jack validator listener", () => { return; } }`, - UndeclaredVariableError, + 'UndeclaredVariableError', ); }); @@ -118,7 +99,7 @@ describe("Jack validator listener", () => { return; } }`, - UndeclaredVariableError, + 'UndeclaredVariableError', { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 1), @@ -138,7 +119,7 @@ describe("Jack validator listener", () => { } } }`, - UndeclaredVariableError, + 'UndeclaredVariableError', ); }); @@ -154,7 +135,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError, + 'UnknownClassError', ); }); @@ -181,7 +162,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError, + 'UnknownClassError', ); }); @@ -207,7 +188,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError, + 'UnknownClassError', ); }); test("var known type", () => { @@ -229,7 +210,7 @@ describe("Jack validator listener", () => { class Main { field T t; }`, - UnknownClassError, + 'UnknownClassError', ); }); test("field known type", () => { @@ -248,7 +229,7 @@ describe("Jack validator listener", () => { class Main { static T t; }`, - UnknownClassError, + 'UnknownClassError', ); }); test("static field known type", () => { @@ -274,7 +255,7 @@ describe("Jack validator listener", () => { return; } }`, - NonVoidFunctionNoReturnError, + 'NonVoidFunctionNoReturnError', ); }); @@ -286,7 +267,7 @@ describe("Jack validator listener", () => { return 1; } }`, - VoidSubroutineReturnsValueError, + 'VoidSubroutineReturnsValueError', ); }); /** @@ -307,7 +288,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + 'SubroutineNotAllPathsReturnError', ); }); test("else missing return ", () => { @@ -324,7 +305,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + 'SubroutineNotAllPathsReturnError', ); }); @@ -340,7 +321,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + 'SubroutineNotAllPathsReturnError', ); }); @@ -356,7 +337,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + 'SubroutineNotAllPathsReturnError', ); }); @@ -378,7 +359,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + 'SubroutineNotAllPathsReturnError', ); }); test("nested if missing return 2", () => { @@ -399,7 +380,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + 'SubroutineNotAllPathsReturnError', ); }); @@ -421,7 +402,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + 'SubroutineNotAllPathsReturnError', ); }); test("should be valid", () => { @@ -451,7 +432,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownSubroutineCallError, + 'UnknownSubroutineCallError', ); }); @@ -467,7 +448,7 @@ describe("Jack validator listener", () => { return; } }`, - IncorrectParamsNumberInSubroutineCallError, + 'IncorrectParamsNumberInSubroutineCallError', { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 2), @@ -538,7 +519,7 @@ describe("Jack validator listener", () => { return; } }`, - MethodCalledAsFunctionError, + 'MethodCalledAsFunctionError', { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), @@ -558,7 +539,7 @@ describe("Jack validator listener", () => { return; } }`, - FunctionCalledAsMethodError, + 'FunctionCalledAsMethodError', { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), @@ -574,7 +555,7 @@ describe("Jack validator listener", () => { return this; } }`, - IncorrectConstructorReturnType, + 'IncorrectConstructorReturnTypeError', { Main: genericSymbol(), D: genericSymbol(), @@ -592,7 +573,7 @@ describe("Jack validator listener", () => { let a=0; } }`, - UnreachableCodeError, + 'UnreachableCodeError', { Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), @@ -607,7 +588,7 @@ describe("Jack validator listener", () => { return 1; } }`, - ConstructorMushReturnThis, + 'ConstructorMushReturnThisError', { Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), @@ -624,7 +605,7 @@ describe("Jack validator listener", () => { return; } }`, - WrongLiteralTypeError, + 'WrongLiteralTypeError', { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -642,7 +623,7 @@ describe("Jack validator listener", () => { return; } }`, - WrongLiteralTypeError, + 'WrongLiteralTypeError', { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -660,7 +641,7 @@ describe("Jack validator listener", () => { return; } }`, - WrongLiteralTypeError, + 'WrongLiteralTypeError', { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -677,7 +658,7 @@ describe("Jack validator listener", () => { return; } }`, - IntLiteralOverflow, + 'IntLiteralIsOutOfRangeError', { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -694,7 +675,7 @@ describe("Jack validator listener", () => { return; } }`, - IntLiteralOverflow, + 'IntLiteralIsOutOfRangeError', { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -711,7 +692,7 @@ describe("Jack validator listener", () => { return; } }`, - FieldCantBeReferencedInFunction, + 'FieldCantBeReferencedInFunctionError', { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -745,7 +726,7 @@ describe("Jack validator listener", () => { return; } }`, - ThisCantBeReferencedInFunction, + 'ThisCantBeReferencedInFunctionError', { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -755,7 +736,7 @@ describe("Jack validator listener", () => { test("class name doesn't match filename", () => { testValidator( `class A {}`, - FilenameDoesntMatchClassName, + 'FilenameDoesntMatchClassNameError', { A: genericSymbol(), }, @@ -792,7 +773,7 @@ function testJackDir(testFolder: string): void { } } -function testValidator( +function testValidator( src: string, expectedError?: T, globalSymbolTable: Record = {}, @@ -811,10 +792,10 @@ function testValidator( } try { expect(validator.errors.length).toBe(1); - expect(validator.errors[0]).toBeInstanceOf(expectedError); + expect(validator.errors[0].type).toBe(expectedError); } catch (e) { throw new Error( - `Expected error ${expectedError.name} but got '` + + `Expected error ${expectedError} but got '` + validator.errors.join(",") + "'", ); diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 8bff6342..27bfb2e5 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -1,26 +1,6 @@ -import { ParserRuleContext } from "antlr4"; +import { ParserRuleContext, Token } from "antlr4"; import { builtInTypes, intRange } from "../builtins.js"; -import { - ConstructorMushReturnThis, - DuplicatedVariableException, - FieldCantBeReferencedInFunction, - FilenameDoesntMatchClassName, - FunctionCalledAsMethodError, - IncorrectConstructorReturnType, - IncorrectParamsNumberInSubroutineCallError, - IntLiteralIsOutOfRange, - JackCompilerError, - MethodCalledAsFunctionError, - NonVoidFunctionNoReturnError, - SubroutineNotAllPathsReturnError, - ThisCantBeReferencedInFunction, - UndeclaredVariableError, - UnknownClassError, - UnknownSubroutineCallError, - UnreachableCodeError, - VoidSubroutineReturnsValueError, - WrongLiteralTypeError, -} from "../error.js"; +import { asSpan, ConstructorMushReturnThisError, DuplicatedVariableError, FieldCantBeReferencedInFunctionError, FilenameDoesntMatchClassNameError, FunctionCalledAsMethodError, IncorrectConstructorReturnTypeError, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRangeError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunctionError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error.js"; import { ClassDeclarationContext, ClassVarDecContext, @@ -49,6 +29,9 @@ import { SubroutineType, } from "../symbol.js"; import { CallType, getCallType } from "./common.js"; +import { Span } from "../../languages/base.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; + /* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * Validates Jack file @@ -82,15 +65,7 @@ export class ValidatorListener extends JackParserListener { ); if (this.filename != null && this.filename != this.className) { console.error("FilenameDoesntMatchClassName"); - this.errors.push( - new FilenameDoesntMatchClassName( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - this.filename, - this.className, - ), - ); + this.errors.push( FilenameDoesntMatchClassNameError(asSpan(ctx.start), this.filename, this.className,),); } ctx.localSymbolTable = this.localSymbolTable; }; @@ -120,10 +95,8 @@ export class ValidatorListener extends JackParserListener { this.className ) { this.addError( - new IncorrectConstructorReturnType( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + IncorrectConstructorReturnTypeError( + asSpan(ctx.start) ), ); } @@ -158,12 +131,7 @@ export class ValidatorListener extends JackParserListener { const type = ctx.IDENTIFIER()!.getText(); if (this.globalSymbolTable[type] == null) { this.addError( - new UnknownClassError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - type, - ), + UnknownClassError(asSpan(ctx.start), type,), ); } } @@ -182,24 +150,13 @@ export class ValidatorListener extends JackParserListener { override enterVarName = (ctx: VarNameContext) => { const symbol = this.localSymbolTable.lookup(ctx.getText()); if (symbol == undefined) { - this.addError( - new UndeclaredVariableError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - ctx.getText(), - ), - ); + this.addError(UndeclaredVariableError(asSpan(ctx.start), ctx.getText())); } else if ( this.subroutineType == SubroutineType.Function && symbol.scope == ScopeType.This ) { this.addError( - new FieldCantBeReferencedInFunction( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - ), + FieldCantBeReferencedInFunctionError(asSpan(ctx.start)), ); } }; @@ -210,24 +167,14 @@ export class ValidatorListener extends JackParserListener { this.subroutineType == SubroutineType.Function ) { this.addError( - new ThisCantBeReferencedInFunction( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - ), + ThisCantBeReferencedInFunctionError(asSpan(ctx.start)) ); } }; override enterStatement = (ctx: StatementContext) => { if (this.controlFlowGraphNode.returns == true) { - this.addError( - new UnreachableCodeError( - ctx.start.line, - ctx.start.start, - ctx.stop?.stop ?? ctx.start.stop, - ), - ); + this.addError( UnreachableCodeError( asSpan(ctx.start, ctx.stop)),); this.stopProcessingErrorsInThisScope = true; } }; @@ -283,21 +230,13 @@ export class ValidatorListener extends JackParserListener { case "int": if (constantCtx.INTEGER_LITERAL() === null) { this.addError( - new WrongLiteralTypeError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - type, - ), + WrongLiteralTypeError(asSpan(ctx.start), type,), ); } else { const value = parseInt(constantCtx.INTEGER_LITERAL()!.getText()); if (value > intRange.max) { this.addError( - new IntLiteralIsOutOfRange( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + IntLiteralIsOutOfRangeError(asSpan(ctx.start), value, intRange.min, intRange.max, @@ -309,22 +248,14 @@ export class ValidatorListener extends JackParserListener { case "boolean": if (constantCtx.booleanLiteral() === null) { this.addError( - new WrongLiteralTypeError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - type, - ), + WrongLiteralTypeError( asSpan(ctx.start), type,), ); } break; case "String": if (constantCtx.STRING_LITERAL() === null) { this.addError( - new WrongLiteralTypeError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + WrongLiteralTypeError(asSpan(ctx.start), type.toLowerCase(), ), ); @@ -349,10 +280,7 @@ export class ValidatorListener extends JackParserListener { ); if (-value < intRange.min) { this.addError( - new IntLiteralIsOutOfRange( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + IntLiteralIsOutOfRangeError(asSpan(ctx.start), value, intRange.min, intRange.max, @@ -374,10 +302,7 @@ export class ValidatorListener extends JackParserListener { const symbol = this.globalSymbolTable[subroutineIdText]; if (symbol == undefined) { this.addError( - new UnknownSubroutineCallError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + UnknownSubroutineCallError(asSpan(ctx.start), subroutineId.subroutineName().getText(), subroutineId.className()?.getText(), ), @@ -389,10 +314,7 @@ export class ValidatorListener extends JackParserListener { callType == CallType.ClassFunctionOrConstructor ) { this.addError( - new MethodCalledAsFunctionError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + MethodCalledAsFunctionError(asSpan(ctx.start), subroutineId.subroutineName().getText(), ), ); @@ -403,10 +325,7 @@ export class ValidatorListener extends JackParserListener { callType == CallType.LocalMethod ) { this.addError( - new FunctionCalledAsMethodError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + FunctionCalledAsMethodError(asSpan(ctx.start), subroutineId.subroutineName().getText(), ), ); @@ -415,13 +334,11 @@ export class ValidatorListener extends JackParserListener { const l = ctx.expressionList().expression_list().length; if (symbol.subroutineInfo!.paramsCount != l) { this.addError( - new IncorrectParamsNumberInSubroutineCallError( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + IncorrectParamsNumberInSubroutineCallError( + asSpan(ctx.start), subroutineId.getText(), symbol.subroutineInfo!.paramsCount, - l, + assertExists(symbol.subroutineInfo?.localVarsCount), ), ); } @@ -432,20 +349,12 @@ export class ValidatorListener extends JackParserListener { const returnsVoid = ctx.expression() == null; if (returnsVoid && !this.subroutineShouldReturnVoidType) { this.addError( - new NonVoidFunctionNoReturnError( - ctx.stop!.line, - ctx.stop!.start, - ctx.stop!.stop, - ), + NonVoidFunctionNoReturnError(asSpan(ctx.stop ?? ctx.start)) ); } if (!returnsVoid && this.subroutineShouldReturnVoidType) { this.addError( - new VoidSubroutineReturnsValueError( - ctx.stop!.line, - ctx.stop!.start, - ctx.stop!.stop, - ), + VoidSubroutineReturnsValueError(asSpan(ctx.start)), ); } this.controlFlowGraphNode.returns = true; @@ -457,10 +366,8 @@ export class ValidatorListener extends JackParserListener { ctx.expression()!.constant()!.THIS_LITERAL() == null ) { this.addError( - new ConstructorMushReturnThis( - ctx.stop!.line, - ctx.stop!.start, - ctx.stop!.stop, + ConstructorMushReturnThisError( + asSpan(ctx.stop ?? ctx.start), ), ); } @@ -470,10 +377,8 @@ export class ValidatorListener extends JackParserListener { override exitSubroutineBody = (ctx: SubroutineBodyContext) => { if (!this.controlFlowGraphNode.returns) { this.addError( - new SubroutineNotAllPathsReturnError( - ctx.stop!.line, - ctx.stop!.start, - ctx.stop!.stop, + SubroutineNotAllPathsReturnError( + asSpan(ctx.stop ?? ctx.start), this.subroutineName, ), ); @@ -499,12 +404,7 @@ export class ValidatorListener extends JackParserListener { ) { if (this.localSymbolTable.lookup(name)) { this.addError( - new DuplicatedVariableException( - ctx.start.line, - ctx.start.start, - ctx.start.stop, - name, - ), + DuplicatedVariableError (asSpan(ctx.start), name) ); } else { this.localSymbolTable.defineArgument(name, type, inMethod); @@ -518,10 +418,8 @@ export class ValidatorListener extends JackParserListener { ) { if (this.localSymbolTable.lookup(name)) { this.addError( - new DuplicatedVariableException( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + DuplicatedVariableError ( + asSpan(ctx.start), name, ), ); diff --git a/simulator/src/jack/test.helper.ts b/simulator/src/jack/test.helper.ts index 81d3c602..a2df8499 100644 --- a/simulator/src/jack/test.helper.ts +++ b/simulator/src/jack/test.helper.ts @@ -64,12 +64,13 @@ export function listenToTheTree( export function handleErrors(src: string, errors: JackCompilerError[]) { const msg = errors .map((e) => { - return `${e.span.line}:${e.span.start} ${e.msg}\n${src.split("\n")[e.span.line]}`; + return `${e.span.line}:${e.span.start} ${e.message}\n${src.split("\n")[e.span.line]}`; }) .join("\n"); console.error(msg); throw new Error(msg); } + export const testResourceDirs: string[] = [ "Average", "ConvertToBin", From dbf7d80ae10f537608d15472826cbe969beb5ad6 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 11 Oct 2024 19:35:28 +0200 Subject: [PATCH 63/87] Fix minor bug --- simulator/src/jack/listener/validator.listener.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 8bff6342..9a65e625 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -70,7 +70,8 @@ export class ValidatorListener extends JackParserListener { } override enterClassDeclaration = (ctx: ClassDeclarationContext) => { - const newName = ctx.className()?.getText(); + const className = ctx.className(); + const newName = className.getText(); if (this.className != "") { throw new Error("Cannot change class name"); } @@ -84,9 +85,9 @@ export class ValidatorListener extends JackParserListener { console.error("FilenameDoesntMatchClassName"); this.errors.push( new FilenameDoesntMatchClassName( - ctx.start.line, - ctx.start.start, - ctx.start.stop, + className.start.line, + className.start.start, + className.start.stop, this.filename, this.className, ), From 8681e06668838e114af8fc9d3c3ee4a3568aac7d Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:07:17 +0200 Subject: [PATCH 64/87] WIP --- simulator/src/jack/error.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index bbb763fa..a46a2027 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -134,7 +134,6 @@ export class SubroutineNotAllPathsReturnError extends JackCompilerError { endIndex, `Subroutine ${subroutineName}: not all code paths return a value`, ); - Object.setPrototypeOf(this, SubroutineNotAllPathsReturnError.prototype); } } @@ -153,10 +152,6 @@ export class IncorrectParamsNumberInSubroutineCallError extends JackCompilerErro endIndex, `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)`, ); - Object.setPrototypeOf( - this, - IncorrectParamsNumberInSubroutineCallError.prototype, - ); } } export class UnknownSubroutineCallError extends JackCompilerError { @@ -173,7 +168,6 @@ export class UnknownSubroutineCallError extends JackCompilerError { endIndex, `Can't find subroutine '${subroutineName}'${className ? ` in ${className}` : ""}`, ); - Object.setPrototypeOf(this, UnknownSubroutineCallError.prototype); } } export class MethodCalledAsFunctionError extends JackCompilerError { @@ -189,7 +183,6 @@ export class MethodCalledAsFunctionError extends JackCompilerError { endIndex, `Method ${subroutineId} was called as a function/constructor`, ); - Object.setPrototypeOf(this, MethodCalledAsFunctionError.prototype); } } export class FunctionCalledAsMethodError extends JackCompilerError { @@ -205,7 +198,6 @@ export class FunctionCalledAsMethodError extends JackCompilerError { endIndex, `Function or constructor ${subroutineId} was called as a method`, ); - Object.setPrototypeOf(this, FunctionCalledAsMethodError.prototype); } } @@ -217,21 +209,18 @@ export class IncorrectConstructorReturnType extends JackCompilerError { endIndex, `The return type of a constructor must be of the class type`, ); - Object.setPrototypeOf(this, IncorrectConstructorReturnType.prototype); } } export class UnreachableCodeError extends JackCompilerError { constructor(line: number, startInd: number, endIndex: number) { super(line, startInd, endIndex, `Unreachable code`); - Object.setPrototypeOf(this, UnreachableCodeError.prototype); } } export class ConstructorMushReturnThis extends JackCompilerError { constructor(line: number, startInd: number, endIndex: number) { super(line, startInd, endIndex, `A constructor must return 'this'`); - Object.setPrototypeOf(this, ConstructorMushReturnThis.prototype); } } @@ -245,7 +234,6 @@ export class WrongLiteralTypeError extends JackCompilerError { ) { const article = vowels.indexOf(typeName.substring(0, 1)) != -1 ? "an" : "a"; super(line, startInd, endIndex, `${article} ${typeName} value is expected`); - Object.setPrototypeOf(this, WrongLiteralTypeError.prototype); } } @@ -264,20 +252,17 @@ export class IntLiteralIsOutOfRange extends JackCompilerError { endIndex, `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}`, ); - Object.setPrototypeOf(this, IntLiteralIsOutOfRange.prototype); } } export class FieldCantBeReferencedInFunction extends JackCompilerError { constructor(line: number, startInd: number, endIndex: number) { super(line, startInd, endIndex, `Field can't be referenced in a function`); - Object.setPrototypeOf(this, FieldCantBeReferencedInFunction.prototype); } } export class ThisCantBeReferencedInFunction extends JackCompilerError { constructor(line: number, startInd: number, endIndex: number) { super(line, startInd, endIndex, `this can't be referenced in a function`); - Object.setPrototypeOf(this, ThisCantBeReferencedInFunction.prototype); } } From 6c5ec416e06605c886ed1fd7ba979edad6916180 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:22:47 +0200 Subject: [PATCH 65/87] Change tests to use FileSystem --- simulator/src/jack/antlr.compiler.test.ts | 33 +++--- .../src/jack/listener/binder.listener.test.ts | 24 ++-- .../jack/listener/validator.listener.test.ts | 108 +++++++++--------- .../src/jack/listener/validator.listener.ts | 5 - 4 files changed, 88 insertions(+), 82 deletions(-) diff --git a/simulator/src/jack/antlr.compiler.test.ts b/simulator/src/jack/antlr.compiler.test.ts index a74cd34a..55c82928 100644 --- a/simulator/src/jack/antlr.compiler.test.ts +++ b/simulator/src/jack/antlr.compiler.test.ts @@ -1,9 +1,14 @@ -import fs from "fs"; +import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; +import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import { getTestResourcePath, testResourceDirs } from "./test.helper"; import path from "path"; import { ProgramContext } from "./generated/JackParser"; import { Compiler } from "./anltr.compiler"; describe("Jack compiler", () => { + let fs: FileSystem; + beforeEach(() => { + fs = new FileSystem(new NodeFileSystemAdapter()); + }); test("static field", () => { testCompiler( `class A{ @@ -19,7 +24,7 @@ describe("Jack compiler", () => { pop static 0 push constant 0 return - `, + ` ); }); test("field", () => { @@ -40,7 +45,7 @@ describe("Jack compiler", () => { pop this 0 push constant 0 return - `, + ` ); }); @@ -910,38 +915,40 @@ describe("Jack compiler", () => { `; testCompiler(input, expected); }); - test.concurrent.each(testResourceDirs)("%s", (folder: string) => { - testFilesInFolder(folder); + test.each(testResourceDirs)("%s", async (folder: string) => { + await testFilesInFolder(fs, folder); }); }); -function testFilesInFolder(folderInTestResources: string) { +async function testFilesInFolder( + fs: FileSystem, + folderInTestResources: string +) { const testFolder = getTestResourcePath(folderInTestResources); - const files = fs - .readdirSync(testFolder) + const files = [...(await fs.readdir(testFolder))] .filter((file) => file.endsWith(".jack")) .map((file) => path.join(testFolder, file)); const trees: Record = {}; const compiler = new Compiler(); for (const f of files) { - const input = fs.readFileSync(f, { encoding: "utf8", flag: "r" }); + const input = await fs.readFile(f); const treeOrErrors = compiler.parserAndBind(input); if (Array.isArray(treeOrErrors)) { throw new Error( - `Unexpected compilation errors: ${treeOrErrors.join("\n")}`, + `Unexpected compilation errors: ${treeOrErrors.join("\n")}` ); } const tree = treeOrErrors as ProgramContext; trees[f] = tree; } for (const f of files) { - const expected = fs.readFileSync(f.replace(".jack", ".vm"), "utf8"); + const expected = await fs.readFile(f.replace(".jack", ".vm")); const res = compiler.compile(trees[f]); if (Array.isArray(res)) { throw new Error(`Unexpected compilation errors: ${res.join("\n")}`); } else { // console.log(res) expect(trimAndDeleteComments(res)).toEqual( - trimAndDeleteComments(expected), + trimAndDeleteComments(expected) ); } } @@ -970,7 +977,7 @@ function testCompiler(input: string, expected: string): void { const treeOrErrors = compiler.parserAndBind(input); if (Array.isArray(treeOrErrors)) { throw new Error( - `Unexpected compilation errors: ${treeOrErrors.join("\n")}`, + `Unexpected compilation errors: ${treeOrErrors.join("\n")}` ); } const tree = treeOrErrors as ProgramContext; diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/binder.listener.test.ts index 71d3630e..49f974df 100644 --- a/simulator/src/jack/listener/binder.listener.test.ts +++ b/simulator/src/jack/listener/binder.listener.test.ts @@ -1,4 +1,5 @@ -import fs from "fs"; +import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; +import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import path from "path"; import { DuplicatedClassError, DuplicatedSubroutineError } from "../error"; import { BinderListener } from "./binder.listener"; @@ -13,9 +14,10 @@ import { describe("Jack binder", () => { const jestConsole = console; - + let fs: FileSystem; beforeEach(() => { global.console = require("console"); + fs = new FileSystem(new NodeFileSystemAdapter()); }); afterEach(() => { @@ -49,7 +51,7 @@ describe("Jack binder", () => { }`; testBinder(input, DuplicatedClassError); }); - test("basic", () => { + test("basic", async () => { const expected = { ...builtInSymbols, Fraction: {}, @@ -58,12 +60,12 @@ describe("Jack binder", () => { "Fraction.getNumerator": createSubroutineSymbol( 0, SubroutineType.Method, - 0, + 0 ), "Fraction.getDenominator": createSubroutineSymbol( 0, SubroutineType.Method, - 0, + 0 ), "Fraction.plus": createSubroutineSymbol(1, SubroutineType.Method, 1), "Fraction.dispose": createSubroutineSymbol(0, SubroutineType.Method, 0), @@ -75,11 +77,11 @@ describe("Jack binder", () => { let globalSymbolsListener = new BinderListener(); const testFolder = getTestResourcePath("Fraction"); - const files = fs - .readdirSync(testFolder) + + const filteredFiles = [...(await fs.readdir(testFolder))] .filter((file) => file.endsWith(".jack")) .map((file) => path.join(testFolder, file)); - for (const filePath of files) { + for (const filePath of filteredFiles) { const tree = parseJackFile(filePath); globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); // console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) @@ -90,7 +92,7 @@ describe("Jack binder", () => { function testBinder( input: string, expectedError?: T, - binder = new BinderListener(), + binder = new BinderListener() ) { const tree = parseJackText(input); listenToTheTree(tree, binder); @@ -105,8 +107,8 @@ function testBinder( } catch (e) { throw new Error( `Expected error ${expectedError.name} but got '` + - errors.join(",") + - "'", + errors.join(",") + + "'" ); } } else { diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index 86818398..e6835b8e 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -18,6 +18,8 @@ import { VoidSubroutineReturnsValueError, WrongLiteralTypeError, } from "../error"; +import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; +import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import { CustomErrorListener } from "./error.listener"; import { ValidatorListener } from "./validator.listener"; import { @@ -32,14 +34,15 @@ import { parseJackText, testResourceDirs, } from "../test.helper"; -import fs from "fs"; import { BinderListener } from "./binder.listener"; import path from "path"; import { ProgramContext } from "../generated/JackParser"; describe("Jack validator listener", () => { const jestConsole = console; + let fs: FileSystem; beforeEach(() => { global.console = require("console"); + fs = new FileSystem(new NodeFileSystemAdapter()); }); afterEach(() => { @@ -48,7 +51,7 @@ describe("Jack validator listener", () => { function genericSymbol( type?: SubroutineType, - paramsCount?: number, + paramsCount?: number ): GenericSymbol { if (type != undefined && paramsCount != undefined) { return createSubroutineSymbol(paramsCount, type); @@ -86,9 +89,9 @@ describe("Jack validator listener", () => { class Main { ${classBody} }`, - DuplicatedVariableError, + DuplicatedVariableError ); - }, + } ); /** @@ -103,7 +106,7 @@ describe("Jack validator listener", () => { return; } }`, - UndeclaredVariableError, + UndeclaredVariableError ); }); @@ -123,7 +126,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 1), "Main.a": genericSymbol(SubroutineType.Function, 1), - }, + } ); }); @@ -138,7 +141,7 @@ describe("Jack validator listener", () => { } } }`, - UndeclaredVariableError, + UndeclaredVariableError ); }); @@ -154,7 +157,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError, + UnknownClassError ); }); @@ -170,7 +173,7 @@ describe("Jack validator listener", () => { { D: genericSymbol(), "D.new": genericSymbol(SubroutineType.Constructor, 0), - }, + } ); }); test("Arg Unknown class ", () => { @@ -181,7 +184,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError, + UnknownClassError ); }); @@ -195,7 +198,7 @@ describe("Jack validator listener", () => { } }`, undefined, - { D: genericSymbol() }, + { D: genericSymbol() } ); }); test("var Unknown class", () => { @@ -207,7 +210,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError, + UnknownClassError ); }); test("var known type", () => { @@ -220,7 +223,7 @@ describe("Jack validator listener", () => { } }`, undefined, - { D: genericSymbol() }, + { D: genericSymbol() } ); }); test("field Unknown class", () => { @@ -229,7 +232,7 @@ describe("Jack validator listener", () => { class Main { field T t; }`, - UnknownClassError, + UnknownClassError ); }); test("field known type", () => { @@ -239,7 +242,7 @@ describe("Jack validator listener", () => { field T t; }`, undefined, - { T: genericSymbol() }, + { T: genericSymbol() } ); }); test("static field Unknown class", () => { @@ -248,7 +251,7 @@ describe("Jack validator listener", () => { class Main { static T t; }`, - UnknownClassError, + UnknownClassError ); }); test("static field known type", () => { @@ -258,7 +261,7 @@ describe("Jack validator listener", () => { static T t; }`, undefined, - { T: genericSymbol() }, + { T: genericSymbol() } ); }); @@ -274,7 +277,7 @@ describe("Jack validator listener", () => { return; } }`, - NonVoidFunctionNoReturnError, + NonVoidFunctionNoReturnError ); }); @@ -286,7 +289,7 @@ describe("Jack validator listener", () => { return 1; } }`, - VoidSubroutineReturnsValueError, + VoidSubroutineReturnsValueError ); }); /** @@ -307,7 +310,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + SubroutineNotAllPathsReturnError ); }); test("else missing return ", () => { @@ -324,7 +327,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + SubroutineNotAllPathsReturnError ); }); @@ -340,7 +343,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + SubroutineNotAllPathsReturnError ); }); @@ -356,7 +359,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + SubroutineNotAllPathsReturnError ); }); @@ -378,7 +381,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + SubroutineNotAllPathsReturnError ); }); test("nested if missing return 2", () => { @@ -399,7 +402,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + SubroutineNotAllPathsReturnError ); }); @@ -421,7 +424,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError, + SubroutineNotAllPathsReturnError ); }); test("should be valid", () => { @@ -451,7 +454,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownSubroutineCallError, + UnknownSubroutineCallError ); }); @@ -472,7 +475,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 2), "Main.b": genericSymbol(SubroutineType.Function, 2), - }, + } ); }); @@ -499,7 +502,7 @@ describe("Jack validator listener", () => { "Main.new": genericSymbol(SubroutineType.Constructor, 0), "Main.a": genericSymbol(SubroutineType.Function, 0), "Main.b": genericSymbol(SubroutineType.Method, 0), - }, + } ); }); test("call local method ", () => { @@ -519,7 +522,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Method, 0), "Main.b": genericSymbol(SubroutineType.Method, 0), - }, + } ); }); @@ -543,7 +546,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), "Main.c": genericSymbol(SubroutineType.Method, 0), - }, + } ); }); test("function/ctor called as a method", () => { @@ -563,7 +566,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), "Main.c": genericSymbol(SubroutineType.Function, 0), - }, + } ); }); test("incorrect return type in constructor", () => { @@ -578,7 +581,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), D: genericSymbol(), - }, + } ); }); test("unreachable code", () => { @@ -596,7 +599,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), - }, + } ); }); test("A constructor must return 'this'", () => { @@ -611,7 +614,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), - }, + } ); }); test("Let statement - expected string literal ", () => { @@ -629,7 +632,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), String: genericSymbol(), - }, + } ); }); test("Let statement - expected boolean literal ", () => { @@ -646,7 +649,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - }, + } ); }); @@ -664,7 +667,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - }, + } ); }); test("integer constant value is too big", () => { @@ -681,7 +684,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - }, + } ); }); test("integer constant value is too small", () => { @@ -698,7 +701,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - }, + } ); }); test("A field can not be referenced in a function", () => { @@ -715,7 +718,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - }, + } ); }); test("A static field can be referenced in a function", () => { @@ -732,7 +735,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - }, + } ); }); test("this can't be referenced in a function", () => { @@ -749,7 +752,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - }, + } ); }); test("class name doesn't match filename", () => { @@ -759,19 +762,18 @@ describe("Jack validator listener", () => { { A: genericSymbol(), }, - "B", + "B" ); }); //validate files - test.concurrent.each(testResourceDirs)("%s", (dir: string) => { - testJackDir(getTestResourcePath(dir)); + test.each(testResourceDirs)("%s", async (dir: string) => { + await testJackDir(fs, getTestResourcePath(dir)); }); }); -function testJackDir(testFolder: string): void { - const files = fs - .readdirSync(testFolder) +async function testJackDir(fs: FileSystem, testFolder: string): Promise { + const files = [...(await fs.readdir(testFolder))] .filter((file) => file.endsWith(".jack")) .map((file) => path.join(testFolder, file)); const trees: Record = {}; @@ -786,7 +788,7 @@ function testJackDir(testFolder: string): void { const tree = trees[filepath]; const validatorListener = listenToTheTree( tree, - new ValidatorListener(globalSymbolsListener.globalSymbolTable), + new ValidatorListener(globalSymbolsListener.globalSymbolTable) ); expect(validatorListener.errors).toEqual([]); } @@ -796,7 +798,7 @@ function testValidator( src: string, expectedError?: T, globalSymbolTable: Record = {}, - filename?: string, + filename?: string ) { const errorListener = new CustomErrorListener(); const tree = parseJackText(src, errorListener); @@ -816,13 +818,13 @@ function testValidator( throw new Error( `Expected error ${expectedError.name} but got '` + validator.errors.join(",") + - "'", + "'" ); } } else { if (validator.errors.length != 0) throw new Error( - "Didn't expect any errors but got " + validator.errors.join("\n"), + "Didn't expect any errors but got " + validator.errors.join("\n") ); } } diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 9a65e625..f94c75c9 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -76,11 +76,6 @@ export class ValidatorListener extends JackParserListener { throw new Error("Cannot change class name"); } this.className = newName; - console.log( - "Filename", - this.filename != null, - this.filename != this.className, - ); if (this.filename != null && this.filename != this.className) { console.error("FilenameDoesntMatchClassName"); this.errors.push( From 98f696e3f01bd74fb5e9d909c5197d3e80a34c67 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:24:53 +0200 Subject: [PATCH 66/87] WIP --- simulator/src/jack/listener/binder.listener.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/binder.listener.test.ts index 49f974df..664c234a 100644 --- a/simulator/src/jack/listener/binder.listener.test.ts +++ b/simulator/src/jack/listener/binder.listener.test.ts @@ -1,7 +1,7 @@ import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import path from "path"; -import { DuplicatedClassError, DuplicatedSubroutineError } from "../error"; +import { DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error"; import { BinderListener } from "./binder.listener"; import { createSubroutineSymbol, SubroutineType } from "../symbol"; import { builtInSymbols } from "../builtins"; @@ -89,7 +89,7 @@ describe("Jack binder", () => { expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); }); }); -function testBinder( +function testBinder JackCompilerError>( input: string, expectedError?: T, binder = new BinderListener() From 12edbb145e55476111fb1529db25bd7069dbc948 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:32:53 +0200 Subject: [PATCH 67/87] WIP --- simulator/src/jack/anltr.compiler.ts | 20 +++++++++---------- simulator/src/jack/antlr.compiler.test.ts | 7 +++---- simulator/src/jack/listener/error.listener.ts | 2 +- ...s => global.symbol.table.listener.test.ts} | 19 +++++++++--------- ...ner.ts => global.symbol.table.listener.ts} | 2 +- .../jack/listener/validator.listener.test.ts | 16 +++++++-------- .../src/jack/listener/validator.listener.ts | 2 +- .../src/jack/listener/vm.writer.listener.ts | 2 +- simulator/src/jack/parser.test.ts | 4 ++-- simulator/src/jack/test.helper.ts | 8 ++++---- 10 files changed, 40 insertions(+), 42 deletions(-) rename simulator/src/jack/listener/{binder.listener.test.ts => global.symbol.table.listener.test.ts} (83%) rename simulator/src/jack/listener/{binder.listener.ts => global.symbol.table.listener.ts} (98%) diff --git a/simulator/src/jack/anltr.compiler.ts b/simulator/src/jack/anltr.compiler.ts index f8f10262..25f4564a 100644 --- a/simulator/src/jack/anltr.compiler.ts +++ b/simulator/src/jack/anltr.compiler.ts @@ -1,8 +1,8 @@ -import { BinderListener } from "./listener/binder.listener.js"; -import { CustomErrorListener } from "./listener/error.listener.js"; -import { ValidatorListener } from "./listener/validator.listener.js"; +import { JackGlobalSymbolTableListener } from "./listener/global.symbol.table.listener.js"; +import { JackCustomErrorListener } from "./listener/error.listener.js"; +import { JackValidatorListener } from "./listener/validator.listener.js"; import { JackCompilerError, LexerOrParserError } from "./error.js"; -import { VMWriter } from "./listener/vm.writer.listener.js"; +import { JackVMWriter } from "./listener/vm.writer.listener.js"; import JackParser, { ProgramContext } from "./generated/JackParser.js"; import { CharStreams, CommonTokenStream, ParseTreeWalker } from "antlr4"; import JackLexer from "./generated/JackLexer.js"; @@ -53,7 +53,7 @@ function _do( } const trees: Record = {}; const errors: Record = {}; - const compiler = new Compiler(); + const compiler = new JackCompiler(); for (const [name, content] of Object.entries(files)) { const treeOrErrors = compiler.parserAndBind(content); if (Array.isArray(treeOrErrors)) { @@ -102,9 +102,9 @@ function toCompilerError(errors: JackCompilerError[]): CompilationError { } as CompilationError; } -export class Compiler { - private binder = new BinderListener(); - private errorListener = new CustomErrorListener(); +export class JackCompiler { + private binder = new JackGlobalSymbolTableListener(); + private errorListener = new JackCustomErrorListener(); validate( tree: ProgramContext, filename?: string, @@ -114,7 +114,7 @@ export class Compiler { "Please populate global symbol table using parserAndBind method", ); } - const validator = new ValidatorListener( + const validator = new JackValidatorListener( this.binder.globalSymbolTable, filename, ); @@ -133,7 +133,7 @@ export class Compiler { return errors; } const validateTree = treeOrErrors as ProgramContext; - const vmWriter = new VMWriter(this.binder.globalSymbolTable); + const vmWriter = new JackVMWriter(this.binder.globalSymbolTable); ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); return vmWriter.result; } diff --git a/simulator/src/jack/antlr.compiler.test.ts b/simulator/src/jack/antlr.compiler.test.ts index 55c82928..98657304 100644 --- a/simulator/src/jack/antlr.compiler.test.ts +++ b/simulator/src/jack/antlr.compiler.test.ts @@ -3,7 +3,7 @@ import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js" import { getTestResourcePath, testResourceDirs } from "./test.helper"; import path from "path"; import { ProgramContext } from "./generated/JackParser"; -import { Compiler } from "./anltr.compiler"; +import { JackCompiler } from "./anltr.compiler"; describe("Jack compiler", () => { let fs: FileSystem; beforeEach(() => { @@ -928,7 +928,7 @@ async function testFilesInFolder( .filter((file) => file.endsWith(".jack")) .map((file) => path.join(testFolder, file)); const trees: Record = {}; - const compiler = new Compiler(); + const compiler = new JackCompiler(); for (const f of files) { const input = await fs.readFile(f); const treeOrErrors = compiler.parserAndBind(input); @@ -946,7 +946,6 @@ async function testFilesInFolder( if (Array.isArray(res)) { throw new Error(`Unexpected compilation errors: ${res.join("\n")}`); } else { - // console.log(res) expect(trimAndDeleteComments(res)).toEqual( trimAndDeleteComments(expected) ); @@ -973,7 +972,7 @@ const compose = (fn1: (a: T) => T, ...fns: Array<(a: T) => T>) => const trimAndDeleteComments = compose(trimMultiline, deleteComments); function testCompiler(input: string, expected: string): void { - const compiler = new Compiler(); + const compiler = new JackCompiler(); const treeOrErrors = compiler.parserAndBind(input); if (Array.isArray(treeOrErrors)) { throw new Error( diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 88af922e..cfd9a0ea 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -9,7 +9,7 @@ import { JackCompilerError, LexerOrParserError } from "../error.js"; interface LexerNoViableAltException { startIndex: number; } -export class CustomErrorListener extends ErrorListener { +export class JackCustomErrorListener extends ErrorListener { public errors: JackCompilerError[] = []; override syntaxError = ( diff --git a/simulator/src/jack/listener/binder.listener.test.ts b/simulator/src/jack/listener/global.symbol.table.listener.test.ts similarity index 83% rename from simulator/src/jack/listener/binder.listener.test.ts rename to simulator/src/jack/listener/global.symbol.table.listener.test.ts index 664c234a..a3c4edde 100644 --- a/simulator/src/jack/listener/binder.listener.test.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.test.ts @@ -2,7 +2,7 @@ import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import path from "path"; import { DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error"; -import { BinderListener } from "./binder.listener"; +import { JackGlobalSymbolTableListener } from "./global.symbol.table.listener"; import { createSubroutineSymbol, SubroutineType } from "../symbol"; import { builtInSymbols } from "../builtins"; import { @@ -34,22 +34,22 @@ describe("Jack binder", () => { return 1; } }`; - testBinder(input, DuplicatedSubroutineError); + testJackGlobalSymbolListener(input, DuplicatedSubroutineError); }); test("duplicated class", () => { const input = ` class A { }`; - const binder = new BinderListener(); - testBinder(input, undefined, binder); - testBinder(input, DuplicatedClassError, binder); + const binder = new JackGlobalSymbolTableListener(); + testJackGlobalSymbolListener(input, undefined, binder); + testJackGlobalSymbolListener(input, DuplicatedClassError, binder); }); test("duplicated built in class", () => { const input = ` class Math { }`; - testBinder(input, DuplicatedClassError); + testJackGlobalSymbolListener(input, DuplicatedClassError); }); test("basic", async () => { const expected = { @@ -74,7 +74,7 @@ describe("Jack binder", () => { Main: {}, "Main.main": createSubroutineSymbol(0, SubroutineType.Function, 3), }; - let globalSymbolsListener = new BinderListener(); + let globalSymbolsListener = new JackGlobalSymbolTableListener(); const testFolder = getTestResourcePath("Fraction"); @@ -84,15 +84,14 @@ describe("Jack binder", () => { for (const filePath of filteredFiles) { const tree = parseJackFile(filePath); globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); - // console.log("Symbols for " + path.basename(filePath) + ":", globalSymbolsListener.globalSymbolTable) } expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); }); }); -function testBinder JackCompilerError>( +function testJackGlobalSymbolListener JackCompilerError>( input: string, expectedError?: T, - binder = new BinderListener() + binder = new JackGlobalSymbolTableListener() ) { const tree = parseJackText(input); listenToTheTree(tree, binder); diff --git a/simulator/src/jack/listener/binder.listener.ts b/simulator/src/jack/listener/global.symbol.table.listener.ts similarity index 98% rename from simulator/src/jack/listener/binder.listener.ts rename to simulator/src/jack/listener/global.symbol.table.listener.ts index 7266e142..88b9f822 100644 --- a/simulator/src/jack/listener/binder.listener.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.ts @@ -20,7 +20,7 @@ export type Primitive = typeof primitives extends Set ? S : never; /** * Creates global symbol table that contains built-in functions and found classes and subroutines */ -export class BinderListener extends JackParserListener { +export class JackGlobalSymbolTableListener extends JackParserListener { // key can be class or . public globalSymbolTable: GlobalSymbolTable = structuredClone(builtInSymbols); public className = ""; diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index e6835b8e..67e5ae8b 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -20,8 +20,8 @@ import { } from "../error"; import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; -import { CustomErrorListener } from "./error.listener"; -import { ValidatorListener } from "./validator.listener"; +import { JackCustomErrorListener } from "./error.listener"; +import { JackValidatorListener } from "./validator.listener"; import { createSubroutineSymbol, GenericSymbol, @@ -34,7 +34,7 @@ import { parseJackText, testResourceDirs, } from "../test.helper"; -import { BinderListener } from "./binder.listener"; +import { JackGlobalSymbolTableListener } from "./global.symbol.table.listener"; import path from "path"; import { ProgramContext } from "../generated/JackParser"; describe("Jack validator listener", () => { @@ -777,7 +777,7 @@ async function testJackDir(fs: FileSystem, testFolder: string): Promise { .filter((file) => file.endsWith(".jack")) .map((file) => path.join(testFolder, file)); const trees: Record = {}; - const globalSymbolsListener: BinderListener = new BinderListener(); + const globalSymbolsListener: JackGlobalSymbolTableListener = new JackGlobalSymbolTableListener(); for (const filePath of files) { const tree = parseJackFile(filePath); trees[filePath] = tree; @@ -788,7 +788,7 @@ async function testJackDir(fs: FileSystem, testFolder: string): Promise { const tree = trees[filepath]; const validatorListener = listenToTheTree( tree, - new ValidatorListener(globalSymbolsListener.globalSymbolTable) + new JackValidatorListener(globalSymbolsListener.globalSymbolTable) ); expect(validatorListener.errors).toEqual([]); } @@ -800,12 +800,12 @@ function testValidator( globalSymbolTable: Record = {}, filename?: string ) { - const errorListener = new CustomErrorListener(); + const errorListener = new JackCustomErrorListener(); const tree = parseJackText(src, errorListener); const listener = filename != null - ? new ValidatorListener(globalSymbolTable, filename) - : new ValidatorListener(globalSymbolTable); + ? new JackValidatorListener(globalSymbolTable, filename) + : new JackValidatorListener(globalSymbolTable); const validator = listenToTheTree(tree, listener); if (expectedError) { if (validator.errors.length > 1) { diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index f94c75c9..50ad109f 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -53,7 +53,7 @@ import { CallType, getCallType } from "./common.js"; /** * Validates Jack file */ -export class ValidatorListener extends JackParserListener { +export class JackValidatorListener extends JackParserListener { private localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); private subroutineShouldReturnVoidType = false; private controlFlowGraphNode: BinaryTreeNode = new BinaryTreeNode(); diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index 27a685ad..80b1af46 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -44,7 +44,7 @@ const unaryOperationToVmCmd: Record = { /** * Transforms parse tree into VM code */ -export class VMWriter extends JackParserListener { +export class JackVMWriter extends JackParserListener { public result = ""; private className = ""; private currentLabelIndex = 0; diff --git a/simulator/src/jack/parser.test.ts b/simulator/src/jack/parser.test.ts index 3de130d1..542b7d8a 100644 --- a/simulator/src/jack/parser.test.ts +++ b/simulator/src/jack/parser.test.ts @@ -8,7 +8,7 @@ import { parseJackText, testResourceDirs, } from "./test.helper"; -import { BinderListener } from "./listener/binder.listener"; +import { JackGlobalSymbolTableListener } from "./listener/global.symbol.table.listener"; describe("Jack parser", () => { const jestConsole = console; @@ -49,7 +49,7 @@ function testJackDir(testFolder: string): void { .map((file) => path.join(testFolder, file)); for (const filePath of files) { const tree = parseJackFile(filePath); - const globalSymbolsListener = listenToTheTree(tree, new BinderListener()); + const globalSymbolsListener = listenToTheTree(tree, new JackGlobalSymbolTableListener()); const symbolsErrors = globalSymbolsListener.errors.join("\n"); try { expect(globalSymbolsListener.errors.length).toBe(0); diff --git a/simulator/src/jack/test.helper.ts b/simulator/src/jack/test.helper.ts index 81d3c602..aab62a75 100644 --- a/simulator/src/jack/test.helper.ts +++ b/simulator/src/jack/test.helper.ts @@ -1,7 +1,7 @@ import fs from "fs"; import path from "path"; import { JackCompilerError } from "./error"; -import { CustomErrorListener } from "./listener/error.listener"; +import { JackCustomErrorListener } from "./listener/error.listener"; import { CharStreams, CommonTokenStream, @@ -12,19 +12,19 @@ import JackLexer from "./generated/JackLexer"; import JackParser, { ProgramContext } from "./generated/JackParser"; export function parseJackFile(filePath: string, trace = false) { - const errorListener: CustomErrorListener = new CustomErrorListener(); + const errorListener: JackCustomErrorListener = new JackCustomErrorListener(); const f = fs.readFileSync(filePath, "utf8"); return parseJackText(f, errorListener, trace); } export function parseJackText( src: string, - errorListener?: CustomErrorListener, + errorListener?: JackCustomErrorListener, trace = false, throwOnErrors = true, ): ProgramContext { if (errorListener === undefined) { - errorListener = new CustomErrorListener(); + errorListener = new JackCustomErrorListener(); } const inputStream = CharStreams.fromString(src); const lexer = new JackLexer(inputStream); From 1dfc0ce4a545643c478d1f1d479baf8e31e9759c Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:43:09 +0200 Subject: [PATCH 68/87] Remove ! signs --- simulator/src/jack/listener/error.listener.ts | 3 +- .../listener/global.symbol.table.listener.ts | 16 +- .../src/jack/listener/validator.listener.ts | 154 +++++++++--------- .../src/jack/listener/vm.writer.listener.ts | 36 ++-- 4 files changed, 111 insertions(+), 98 deletions(-) diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index cfd9a0ea..0bf5bcec 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -6,6 +6,7 @@ import { Token, } from "antlr4"; import { JackCompilerError, LexerOrParserError } from "../error.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; interface LexerNoViableAltException { startIndex: number; } @@ -21,7 +22,7 @@ export class JackCustomErrorListener extends ErrorListener { e: RecognitionException | undefined, ) => { if (offendingSymbol != null || (e != null && e.offendingToken != null)) { - const t = offendingSymbol ?? (e!.offendingToken as Token); + const t = offendingSymbol ?? (assertExists(e).offendingToken as Token); this.errors.push(new LexerOrParserError(line, t.start, t.stop + 1, msg)); } else if (e instanceof NoViableAltException) { this.errors.push( diff --git a/simulator/src/jack/listener/global.symbol.table.listener.ts b/simulator/src/jack/listener/global.symbol.table.listener.ts index 88b9f822..93b4ffee 100644 --- a/simulator/src/jack/listener/global.symbol.table.listener.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.ts @@ -13,6 +13,7 @@ import { SubroutineType, } from "../symbol.js"; import JackParserListener from "../generated/JackParserListener.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; @@ -31,14 +32,15 @@ export class JackGlobalSymbolTableListener extends JackParserListener { private subroutineId = ""; override enterClassDeclaration = (ctx: ClassDeclarationContext) => { - const id = ctx.className()!.IDENTIFIER(); + const classNameCtx = ctx.className(); + const id = classNameCtx.IDENTIFIER(); const className = id.getText(); if (this.globalSymbolTable[className] != undefined) { const e = new DuplicatedClassError( - ctx.className()!.start.line, - ctx.className()!.start.start, - ctx.className()!.stop!.stop + 1, - className, + classNameCtx.start.line, + classNameCtx.start.start, + assertExists(classNameCtx.stop).stop + 1, + className ); this.errors.push(e); return; @@ -68,8 +70,8 @@ export class JackGlobalSymbolTableListener extends JackParserListener { nameCtx.IDENTIFIER().symbol.line, nameCtx.start.start, nameCtx.start.stop, - subroutineName, - ), + subroutineName + ) ); this.stopProcessingSubroutines = true; } else { diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 50ad109f..e47d2190 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -49,6 +49,7 @@ import { SubroutineType, } from "../symbol.js"; import { CallType, getCallType } from "./common.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; /* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * Validates Jack file @@ -64,7 +65,7 @@ export class JackValidatorListener extends JackParserListener { constructor( private globalSymbolTable: Record, private filename?: string, - public errors: JackCompilerError[] = [], + public errors: JackCompilerError[] = [] ) { super(); } @@ -84,8 +85,8 @@ export class JackValidatorListener extends JackParserListener { className.start.start, className.start.stop, this.filename, - this.className, - ), + this.className + ) ); } ctx.localSymbolTable = this.localSymbolTable; @@ -119,8 +120,8 @@ export class JackValidatorListener extends JackParserListener { new IncorrectConstructorReturnType( ctx.start.line, ctx.start.start, - ctx.start.stop, - ), + ctx.start.stop + ) ); } } else if (ctx.subroutineType().FUNCTION() != null) { @@ -132,7 +133,7 @@ export class JackValidatorListener extends JackParserListener { } }; override enterSubroutineDecWithoutType = ( - ctx: SubroutineDecWithoutTypeContext, + ctx: SubroutineDecWithoutTypeContext ) => { const returnType = ctx.subroutineReturnType(); this.subroutineShouldReturnVoidType = returnType.VOID() != null; @@ -145,21 +146,21 @@ export class JackValidatorListener extends JackParserListener { ctx, ctx.parameterName().getText(), ctx.varType().getText(), - this.subroutineType == SubroutineType.Method, + this.subroutineType == SubroutineType.Method ); }; //Var override enterVarType = (ctx: VarTypeContext) => { if (ctx.IDENTIFIER() != null) { - const type = ctx.IDENTIFIER()!.getText(); + const type = ctx.IDENTIFIER().getText(); if (this.globalSymbolTable[type] == null) { this.addError( new UnknownClassError( ctx.start.line, ctx.start.start, ctx.start.stop, - type, - ), + type + ) ); } } @@ -183,8 +184,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - ctx.getText(), - ), + ctx.getText() + ) ); } else if ( this.subroutineType == SubroutineType.Function && @@ -194,8 +195,8 @@ export class JackValidatorListener extends JackParserListener { new FieldCantBeReferencedInFunction( ctx.start.line, ctx.start.start, - ctx.start.stop, - ), + ctx.start.stop + ) ); } }; @@ -209,8 +210,8 @@ export class JackValidatorListener extends JackParserListener { new ThisCantBeReferencedInFunction( ctx.start.line, ctx.start.start, - ctx.start.stop, - ), + ctx.start.stop + ) ); } }; @@ -221,8 +222,8 @@ export class JackValidatorListener extends JackParserListener { new UnreachableCodeError( ctx.start.line, ctx.start.start, - ctx.stop?.stop ?? ctx.start.stop, - ), + ctx.stop?.stop ?? ctx.start.stop + ) ); this.stopProcessingErrorsInThisScope = true; } @@ -268,10 +269,11 @@ export class JackValidatorListener extends JackParserListener { if ( varName != null && constCtx != null && - this.localSymbolTable.lookup(ctx.varName()!.getText()) && - ctx.expression().constant()!.NULL_LITERAL() == null + this.localSymbolTable.lookup(ctx.varName().getText()) && + ctx.expression().constant().NULL_LITERAL() == null ) { - const type = this.localSymbolTable.lookup(ctx.varName()!.getText())!.type; + const symbol = this.localSymbolTable.lookup(ctx.varName().getText()); + const type = assertExists(symbol).type; if (literalTypes.indexOf(type) != -1) { const constantCtx = ctx.expression().constant()!; switch (type) { @@ -283,11 +285,11 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - type, - ), + type + ) ); } else { - const value = parseInt(constantCtx.INTEGER_LITERAL()!.getText()); + const value = parseInt(constantCtx.INTEGER_LITERAL().getText()); if (value > intRange.max) { this.addError( new IntLiteralIsOutOfRange( @@ -296,8 +298,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.stop, value, intRange.min, - intRange.max, - ), + intRange.max + ) ); } } @@ -309,8 +311,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - type, - ), + type + ) ); } break; @@ -321,8 +323,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - type.toLowerCase(), - ), + type.toLowerCase() + ) ); } break; @@ -337,11 +339,11 @@ export class JackValidatorListener extends JackParserListener { varName && unaryOp != null && unaryOp.unaryOperator().MINUS() !== null && - unaryOp!.expression().constant() != null && - unaryOp!.expression().constant()?.INTEGER_LITERAL() !== null + unaryOp.expression().constant() != null && + unaryOp.expression().constant()?.INTEGER_LITERAL() !== null ) { const value = parseInt( - unaryOp!.expression().constant()!.INTEGER_LITERAL()!.getText(), + unaryOp.expression().constant().INTEGER_LITERAL().getText() ); if (-value < intRange.min) { this.addError( @@ -351,8 +353,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.stop, value, intRange.min, - intRange.max, - ), + intRange.max + ) ); } } @@ -364,7 +366,7 @@ export class JackValidatorListener extends JackParserListener { const { callType, subroutineIdText } = getCallType( subroutineId, this.className, - this.localSymbolTable, + this.localSymbolTable ); const symbol = this.globalSymbolTable[subroutineIdText]; @@ -375,8 +377,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.start, ctx.start.stop, subroutineId.subroutineName().getText(), - subroutineId.className()?.getText(), - ), + subroutineId.className()?.getText() + ) ); } else { //method called as a function @@ -389,8 +391,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - subroutineId.subroutineName().getText(), - ), + subroutineId.subroutineName().getText() + ) ); } // function called as a method @@ -403,22 +405,22 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - subroutineId.subroutineName().getText(), - ), + subroutineId.subroutineName().getText() + ) ); } else { //check parameter count const l = ctx.expressionList().expression_list().length; - if (symbol.subroutineInfo!.paramsCount != l) { + if (assertExists(symbol.subroutineInfo).paramsCount != l) { this.addError( new IncorrectParamsNumberInSubroutineCallError( ctx.start.line, ctx.start.start, ctx.start.stop, subroutineId.getText(), - symbol.subroutineInfo!.paramsCount, - l, - ), + assertExists(symbol.subroutineInfo).paramsCount, + l + ) ); } } @@ -426,38 +428,39 @@ export class JackValidatorListener extends JackParserListener { }; override enterReturnStatement = (ctx: ReturnStatementContext) => { const returnsVoid = ctx.expression() == null; + const lastToken = assertExists(ctx.stop); if (returnsVoid && !this.subroutineShouldReturnVoidType) { this.addError( new NonVoidFunctionNoReturnError( - ctx.stop!.line, - ctx.stop!.start, - ctx.stop!.stop, - ), + lastToken.line, + lastToken.start, + lastToken.stop + ) ); } if (!returnsVoid && this.subroutineShouldReturnVoidType) { this.addError( new VoidSubroutineReturnsValueError( - ctx.stop!.line, - ctx.stop!.start, - ctx.stop!.stop, - ), + lastToken.line, + lastToken.start, + lastToken.stop + ) ); } this.controlFlowGraphNode.returns = true; if (this.subroutineType == SubroutineType.Constructor) { if ( returnsVoid || - ctx.expression()!.expression_list().length > 1 || - ctx.expression()!.constant() == null || - ctx.expression()!.constant()!.THIS_LITERAL() == null + ctx.expression().expression_list().length > 1 || + ctx.expression().constant() == null || + ctx.expression().constant().THIS_LITERAL() == null ) { this.addError( new ConstructorMushReturnThis( - ctx.stop!.line, - ctx.stop!.start, - ctx.stop!.stop, - ), + lastToken.line, + lastToken.start, + lastToken.stop + ) ); } } @@ -465,13 +468,14 @@ export class JackValidatorListener extends JackParserListener { override exitSubroutineBody = (ctx: SubroutineBodyContext) => { if (!this.controlFlowGraphNode.returns) { + const lastToken = assertExists(ctx.stop); this.addError( new SubroutineNotAllPathsReturnError( - ctx.stop!.line, - ctx.stop!.start, - ctx.stop!.stop, - this.subroutineName, - ), + lastToken.line, + lastToken.start, + lastToken.stop, + this.subroutineName + ) ); } this.subroutineType = undefined; @@ -491,7 +495,7 @@ export class JackValidatorListener extends JackParserListener { ctx: ParserRuleContext, name: string, type: string, - inMethod: boolean, + inMethod: boolean ) { if (this.localSymbolTable.lookup(name)) { this.addError( @@ -499,8 +503,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - name, - ), + name + ) ); } else { this.localSymbolTable.defineArgument(name, type, inMethod); @@ -510,7 +514,7 @@ export class JackValidatorListener extends JackParserListener { ctx: ParserRuleContext, scope: ScopeType, name: string, - type: string, + type: string ) { if (this.localSymbolTable.lookup(name)) { this.addError( @@ -518,8 +522,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - name, - ), + name + ) ); } else { this.localSymbolTable.define(scope, name, type); @@ -535,7 +539,7 @@ class BinaryTreeNode { constructor( public parent?: BinaryTreeNode, public left?: BinaryTreeNode, - public right?: BinaryTreeNode, + public right?: BinaryTreeNode ) {} public get returns(): boolean { @@ -574,13 +578,13 @@ class BinaryTreeNode { } else { res += this.left?.printBT( side == Side.LEFT ? "| " : " ", - Side.LEFT, + Side.LEFT ); if (this.right) { res += prefix; res += this.right?.printBT( side == Side.LEFT ? "|\t" : "\t", - Side.RIGHT, + Side.RIGHT ); } else { res += "\n"; diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index 80b1af46..ec0bbf04 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -1,3 +1,4 @@ +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; import { ArrayAccessContext, ClassDeclarationContext, @@ -61,7 +62,7 @@ export class JackVMWriter extends JackParserListener { if (ctx.localSymbolTable == undefined) { throw new Error("Local symbol table not found in parse tree"); } - this.className = ctx.className()!.getText(); + this.className = ctx.className().getText(); this.localSymbolTable = ctx.localSymbolTable; }; @@ -71,16 +72,18 @@ export class JackVMWriter extends JackParserListener { .subroutineName() .IDENTIFIER() .getText(); + const localSymbolTable = assertExists(this.localSymbolTable); const symbol = this.globalSymbolTable[this.className + "." + name]; if (symbol == undefined) { throw new Error( `Can't find subroutine ${name} in class ${this.className} in symbol table`, ); } - this.result += `function ${this.className}.${name} ${symbol.subroutineInfo!.localVarsCount}\n`; + const subroutineInfo = assertExists(symbol.subroutineInfo); + this.result += `function ${this.className}.${name} ${subroutineInfo.localVarsCount}\n`; if (ctx.subroutineType().CONSTRUCTOR() != null) { - this.result += ` push constant ${this.localSymbolTable!.fieldsCount()}\n`; + this.result += ` push constant ${localSymbolTable.fieldsCount()}\n`; this.result += " call Memory.alloc 1\n"; this.result += " pop pointer 0\n"; } else if (ctx.subroutineType().METHOD() != null) { @@ -91,11 +94,12 @@ export class JackVMWriter extends JackParserListener { if (ctx.symbols == null) { throw new Error("Subroutine symbols not found in parse tree"); } - this.localSymbolTable!.setSubroutineScope(ctx.symbols); + localSymbolTable.setSubroutineScope(ctx.symbols); }; override exitArrayAccess = (ctx: ArrayAccessContext) => { + const localSymbolTable = assertExists(this.localSymbolTable); const varName = ctx.varName().IDENTIFIER().getText(); - const symbol = this.localSymbolTable!.lookup(varName); + const symbol = localSymbolTable.lookup(varName); if (symbol == undefined) { throw new Error(`Can't find variable ${varName} in local symbol table`); } @@ -117,11 +121,11 @@ export class JackVMWriter extends JackParserListener { }; override enterConstant = (ctx: ConstantContext) => { if (ctx.INTEGER_LITERAL() != null) { - this.result += ` push constant ${ctx.INTEGER_LITERAL()!.getText()}\n`; + this.result += ` push constant ${ctx.INTEGER_LITERAL().getText()}\n`; } else if (ctx.booleanLiteral() != null) { - if (ctx.booleanLiteral()!.FALSE() != null) { + if (ctx.booleanLiteral().FALSE() != null) { this.result += ` push constant 0\n`; - } else if (ctx.booleanLiteral()!.TRUE()) { + } else if (ctx.booleanLiteral().TRUE()) { this.result += ` push constant 1\n`; this.result += ` neg\n`; } else { @@ -149,8 +153,9 @@ export class JackVMWriter extends JackParserListener { }; override exitExpression = (ctx: ExpressionContext) => { if (ctx.varName() != null) { - const varName = ctx.varName()!.IDENTIFIER().getText(); - const symbol = this.localSymbolTable!.lookup(varName); + const localSymbolTable = assertExists(this.localSymbolTable); + const varName = ctx.varName().IDENTIFIER().getText(); + const symbol = localSymbolTable.lookup(varName); if (symbol == undefined) { throw new Error( `Cannot find variable ${varName} in arguments or local variables`, @@ -158,13 +163,13 @@ export class JackVMWriter extends JackParserListener { } this.pushSymbolOntoStack(symbol); } else if (ctx.binaryOperator() != null) { - const binaryOp = ctx.binaryOperator()!.getText(); + const binaryOp = ctx.binaryOperator().getText(); if (binaryOperationToVmCmd[binaryOp] == undefined) { throw new Error(`Unknown binary operator ${binaryOp}`); } this.result += "\t" + binaryOperationToVmCmd[binaryOp] + "\n"; } else if (ctx.unaryOperation() != null) { - const unaryOp = ctx.unaryOperation()!.unaryOperator().getText(); + const unaryOp = ctx.unaryOperation().unaryOperator().getText(); if (unaryOperationToVmCmd[unaryOp] == null) { throw new Error(`Unknown unary operator ${unaryOp}`); } @@ -176,12 +181,13 @@ export class JackVMWriter extends JackParserListener { } override exitLetStatement = (ctx: LetStatementContext) => { if (ctx.varName() != null) { - const symbol = this.localSymbolTable!.lookup( - ctx.varName()!.IDENTIFIER().getText(), + const localSymbolTable = assertExists(this.localSymbolTable); + const symbol = localSymbolTable.lookup( + ctx.varName().IDENTIFIER().getText(), ); if (symbol == undefined) { throw new Error( - `Can't find variable ${ctx.varName()!.IDENTIFIER().getText()} in local symbol table`, + `Can't find variable ${ctx.varName().IDENTIFIER().getText()} in local symbol table`, ); } this.result += ` pop ${scopeTypeToString(symbol.scope)} ${symbol.index}\n`; From 70cbcec3601c6b0d96091adc4e1739d439f2b9e6 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:51:39 +0200 Subject: [PATCH 69/87] WIP --- components/src/stores/compiler.store.ts | 2 +- simulator/src/jack/listener/error.listener.ts | 6 +++--- simulator/src/jack/listener/global.symbol.table.listener.ts | 1 - simulator/src/jack/listener/validator.listener.ts | 1 - simulator/src/jack/listener/vm.writer.listener.ts | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/components/src/stores/compiler.store.ts b/components/src/stores/compiler.store.ts index 7dfd9544..6b397e31 100644 --- a/components/src/stores/compiler.store.ts +++ b/components/src/stores/compiler.store.ts @@ -1,5 +1,5 @@ import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; -import { compile, validate } from "@nand2tetris/simulator/jack/compiler.js"; +import { compile, validate } from "@nand2tetris/simulator/jack/anltr.compiler.js"; import { CompilationError } from "@nand2tetris/simulator/languages/base.js"; import { Dispatch, MutableRefObject, useContext, useMemo, useRef } from "react"; import { useImmerReducer } from "../react.js"; diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 0bf5bcec..9a4f3691 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -10,12 +10,12 @@ import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; interface LexerNoViableAltException { startIndex: number; } -export class JackCustomErrorListener extends ErrorListener { +export class JackCustomErrorListener extends ErrorListener { public errors: JackCompilerError[] = []; override syntaxError = ( - recognizer: Recognizer, - offendingSymbol: any, + recognizer: Recognizer, + offendingSymbol: unknown, line: number, column: number, msg: string, diff --git a/simulator/src/jack/listener/global.symbol.table.listener.ts b/simulator/src/jack/listener/global.symbol.table.listener.ts index 93b4ffee..806c12ee 100644 --- a/simulator/src/jack/listener/global.symbol.table.listener.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.ts @@ -17,7 +17,6 @@ import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; -/* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * Creates global symbol table that contains built-in functions and found classes and subroutines */ diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index e47d2190..d1ede12d 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -50,7 +50,6 @@ import { } from "../symbol.js"; import { CallType, getCallType } from "./common.js"; import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; -/* eslint-disable @typescript-eslint/no-non-null-assertion */ /** * Validates Jack file */ diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index ec0bbf04..9ac249e4 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -41,7 +41,7 @@ const unaryOperationToVmCmd: Record = { "-": "neg", "~": "not", }; -/* eslint-disable @typescript-eslint/no-non-null-assertion */ + /** * Transforms parse tree into VM code */ From 30f1b9ce16762745cd3714b3d377c5971ebb993c Mon Sep 17 00:00:00 2001 From: David Souther Date: Fri, 11 Oct 2024 15:28:10 -0400 Subject: [PATCH 70/87] Format error.ts file --- simulator/src/jack/error.ts | 246 +++++++++++++++++++++++++++++------- 1 file changed, 197 insertions(+), 49 deletions(-) diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 71740ed6..174d1885 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,60 +1,208 @@ import { Token } from "antlr4"; import { CompilationError, Span } from "../languages/base"; -export type JackCompilerErrorType = "ConstructorMushReturnThisError" | -"DuplicatedClassError" | -"DuplicatedSubroutineError" | -"DuplicatedVariableError" | -"FieldCantBeReferencedInFunctionError" | -"FilenameDoesntMatchClassNameError" | -"FunctionCalledAsMethodError" | -"IncorrectConstructorReturnTypeError" | -"IncorrectParamsNumberInSubroutineCallError" | -"IntLiteralIsOutOfRangeError" | -"LexerOrParserError" | -"MethodCalledAsFunctionError" | -"NonVoidFunctionNoReturnError" | -"SubroutineNotAllPathsReturnError" | -"ThisCantBeReferencedInFunctionError" | -"UndeclaredVariableError" | -"UnknownClassError" | -"UnknownSubroutineCallError" | -"UnreachableCodeError" | -"VoidSubroutineReturnsValueError" | -"WrongLiteralTypeError"; +/** Utility to convert an antlr Token to a nand2tetris Span */ +export const asSpan = ( + { line, start, stop: startEnd }: Token, + stop?: Token +): Span => ({ line, start, end: stop ? stop.stop : startEnd }); + +export type JackCompilerErrorType = + | "ConstructorMushReturnThisError" + | "DuplicatedClassError" + | "DuplicatedSubroutineError" + | "DuplicatedVariableError" + | "FieldCantBeReferencedInFunctionError" + | "FilenameDoesntMatchClassNameError" + | "FunctionCalledAsMethodError" + | "IncorrectConstructorReturnTypeError" + | "IncorrectParamsNumberInSubroutineCallError" + | "IntLiteralIsOutOfRangeError" + | "LexerOrParserError" + | "MethodCalledAsFunctionError" + | "NonVoidFunctionNoReturnError" + | "SubroutineNotAllPathsReturnError" + | "ThisCantBeReferencedInFunctionError" + | "UndeclaredVariableError" + | "UnknownClassError" + | "UnknownSubroutineCallError" + | "UnreachableCodeError" + | "VoidSubroutineReturnsValueError" + | "WrongLiteralTypeError"; export interface JackCompilerError extends CompilationError { type: JackCompilerErrorType; span: Span; -}; +} -export function makeJackCompilerError(type: JackCompilerErrorType, span: Span, msg?: string): JackCompilerError { +export function makeJackCompilerError( + type: JackCompilerErrorType, + span: Span, + msg?: string +): JackCompilerError { return { - type, span, message: `${type} (${span.line}:${span.start}:${span.end}${msg ? ' ' + msg : ''})` - } + type, + span, + message: `${type} (${span.line}:${span.start}:${span.end}${msg ? " " + msg : ""})`, + }; } -export const LexerOrParserError = (span: Span) => makeJackCompilerError('LexerOrParserError', span); -export const DuplicatedSubroutineError = (span: Span, subroutineName: string) => makeJackCompilerError('DuplicatedClassError', span, `Subroutine ${subroutineName} is already defined.`,); -export const DuplicatedClassError = (span: Span, className: string) => makeJackCompilerError('DuplicatedClassError', span, `Class ${className} is already defined.`); -export const FilenameDoesntMatchClassNameError = (span: Span, filename: string, className: string) => makeJackCompilerError('FilenameDoesntMatchClassNameError', span, `Class name ${className} doesn't match file name ${filename}`); -export const DuplicatedVariableError = (span: Span, variableName: string) => makeJackCompilerError('DuplicatedVariableError', span, `Duplicated local variable, field, argument or static variable ${variableName}`); -export const UndeclaredVariableError = (span: Span, variableName: string) => makeJackCompilerError('UndeclaredVariableError', span, `Undeclared variable ${variableName}`); -export const UnknownClassError = (span: Span, className: string) => makeJackCompilerError('UnknownClassError', span, `Class ${className} doesn't exist`); -export const NonVoidFunctionNoReturnError = (span: Span) => makeJackCompilerError('NonVoidFunctionNoReturnError', span, `A non void subroutine must return a value`); -export const VoidSubroutineReturnsValueError = (span: Span) => makeJackCompilerError('VoidSubroutineReturnsValueError', span, 'Cannot return a value from a void subroutine'); -export const SubroutineNotAllPathsReturnError = (span: Span, subroutineName: string) => makeJackCompilerError('SubroutineNotAllPathsReturnError', span, `Subroutine ${subroutineName}: not all code paths return a value`); -export const IncorrectParamsNumberInSubroutineCallError = (span: Span, subroutineName: string, expectedParamsCount: number, actualParamsCount: number,) => makeJackCompilerError("IncorrectParamsNumberInSubroutineCallError", span, `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)`); -export const UnknownSubroutineCallError = (span: Span, subroutineName: string, className?: string,) => makeJackCompilerError('UnknownSubroutineCallError', span, `Can't find subroutine '${subroutineName}'${className ? ` in ${className}` : ""}`); -export const MethodCalledAsFunctionError = (span: Span, subroutineId: string) => makeJackCompilerError('MethodCalledAsFunctionError', span, `Method ${subroutineId} was called as a function/constructor`); -export const FunctionCalledAsMethodError = (span: Span, subroutineId: string) => makeJackCompilerError('FunctionCalledAsMethodError', span, `Function or constructor ${subroutineId} was called as a method`); -export const IncorrectConstructorReturnTypeError = (span: Span) => makeJackCompilerError("IncorrectConstructorReturnTypeError", span, `The return type of a constructor must be of the class type`); -export const UnreachableCodeError = (span: Span) => makeJackCompilerError("UnreachableCodeError", span); -export const ConstructorMushReturnThisError = (span: Span) => makeJackCompilerError('ConstructorMushReturnThisError', span, `A constructor must return 'this'`); -const vowels = new Set("aeiou".split('')); -export const WrongLiteralTypeError = (span: Span, typeName: string) => makeJackCompilerError('WrongLiteralTypeError', span, `${vowels.has(typeName.charAt(0)) ? "an" : "a"} ${typeName} value is expected`) -export const IntLiteralIsOutOfRangeError = (span: Span, value: number, min: number, max: number,) => makeJackCompilerError('IntLiteralIsOutOfRangeError', span, `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}`,); -export const FieldCantBeReferencedInFunctionError = (span: Span) => makeJackCompilerError('FieldCantBeReferencedInFunctionError', span, `Field can't be referenced in a function`); -export const ThisCantBeReferencedInFunctionError = (span: Span) => makeJackCompilerError('ThisCantBeReferencedInFunctionError', span, `this can't be referenced in a function`); - -export const asSpan = ({line, start, stop: startEnd}: Token, stop?: Token): Span => ({ line, start, end: stop ? stop.stop : startEnd }); \ No newline at end of file +export const ConstructorMushReturnThisError = (span: Span) => + makeJackCompilerError( + "ConstructorMushReturnThisError", + span, + `A constructor must return 'this'` + ); + +export const DuplicatedClassError = (span: Span, className: string) => + makeJackCompilerError( + "DuplicatedClassError", + span, + `Class ${className} is already defined.` + ); + +export const DuplicatedSubroutineError = (span: Span, subroutineName: string) => + makeJackCompilerError( + "DuplicatedClassError", + span, + `Subroutine ${subroutineName} is already defined.` + ); + +export const DuplicatedVariableError = (span: Span, variableName: string) => + makeJackCompilerError( + "DuplicatedVariableError", + span, + `Duplicated local variable, field, argument or static variable ${variableName}` + ); + +export const FieldCantBeReferencedInFunctionError = (span: Span) => + makeJackCompilerError( + "FieldCantBeReferencedInFunctionError", + span, + `Field can't be referenced in a function` + ); + +export const FilenameDoesntMatchClassNameError = ( + span: Span, + filename: string, + className: string +) => + makeJackCompilerError( + "FilenameDoesntMatchClassNameError", + span, + `Class name ${className} doesn't match file name ${filename}` + ); + +export const FunctionCalledAsMethodError = (span: Span, subroutineId: string) => + makeJackCompilerError( + "FunctionCalledAsMethodError", + span, + `Function or constructor ${subroutineId} was called as a method` + ); + +export const IncorrectConstructorReturnTypeError = (span: Span) => + makeJackCompilerError( + "IncorrectConstructorReturnTypeError", + span, + `The return type of a constructor must be of the class type` + ); + +export const IncorrectParamsNumberInSubroutineCallError = ( + span: Span, + subroutineName: string, + expectedParamsCount: number, + actualParamsCount: number +) => + makeJackCompilerError( + "IncorrectParamsNumberInSubroutineCallError", + span, + `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)` + ); + +export const IntLiteralIsOutOfRangeError = ( + span: Span, + value: number, + min: number, + max: number +) => + makeJackCompilerError( + "IntLiteralIsOutOfRangeError", + span, + `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}` + ); + +export const LexerOrParserError = (span: Span) => + makeJackCompilerError("LexerOrParserError", span); + +export const MethodCalledAsFunctionError = (span: Span, subroutineId: string) => + makeJackCompilerError( + "MethodCalledAsFunctionError", + span, + `Method ${subroutineId} was called as a function/constructor` + ); + +export const NonVoidFunctionNoReturnError = (span: Span) => + makeJackCompilerError( + "NonVoidFunctionNoReturnError", + span, + `A non void subroutine must return a value` + ); + +export const SubroutineNotAllPathsReturnError = ( + span: Span, + subroutineName: string +) => + makeJackCompilerError( + "SubroutineNotAllPathsReturnError", + span, + `Subroutine ${subroutineName}: not all code paths return a value` + ); + +export const ThisCantBeReferencedInFunctionError = (span: Span) => + makeJackCompilerError( + "ThisCantBeReferencedInFunctionError", + span, + `this can't be referenced in a function` + ); + +export const UndeclaredVariableError = (span: Span, variableName: string) => + makeJackCompilerError( + "UndeclaredVariableError", + span, + `Undeclared variable ${variableName}` + ); + +export const UnknownClassError = (span: Span, className: string) => + makeJackCompilerError( + "UnknownClassError", + span, + `Class ${className} doesn't exist` + ); + +export const UnknownSubroutineCallError = ( + span: Span, + subroutineName: string, + className?: string +) => + makeJackCompilerError( + "UnknownSubroutineCallError", + span, + `Can't find subroutine '${subroutineName} in '${className ?? "(unknown)"}` + ); + +export const UnreachableCodeError = (span: Span) => + makeJackCompilerError("UnreachableCodeError", span); + +export const VoidSubroutineReturnsValueError = (span: Span) => + makeJackCompilerError( + "VoidSubroutineReturnsValueError", + span, + "Cannot return a value from a void subroutine" + ); + +export const WrongLiteralTypeError = (span: Span, typeName: string) => + makeJackCompilerError( + "WrongLiteralTypeError", + span, + `Value is expected to be of type ${typeName}` + ); From ce31d3a2498c1119667c2a69f29e3dfd024ead1a Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:57:24 +0200 Subject: [PATCH 71/87] WIP --- components/src/stores/compiler.store.ts | 5 +- simulator/src/jack/README.md | 25 ++-- simulator/src/jack/antlr.compiler.test.ts | 12 +- simulator/src/jack/builtins.ts | 2 +- simulator/src/jack/listener/error.listener.ts | 6 +- .../global.symbol.table.listener.test.ts | 18 ++- .../listener/global.symbol.table.listener.ts | 6 +- .../jack/listener/validator.listener.test.ts | 97 +++++++-------- .../src/jack/listener/validator.listener.ts | 110 +++++++++--------- simulator/src/jack/parser.test.ts | 5 +- 10 files changed, 153 insertions(+), 133 deletions(-) diff --git a/components/src/stores/compiler.store.ts b/components/src/stores/compiler.store.ts index 6b397e31..d098866c 100644 --- a/components/src/stores/compiler.store.ts +++ b/components/src/stores/compiler.store.ts @@ -1,5 +1,8 @@ import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; -import { compile, validate } from "@nand2tetris/simulator/jack/anltr.compiler.js"; +import { + compile, + validate, +} from "@nand2tetris/simulator/jack/anltr.compiler.js"; import { CompilationError } from "@nand2tetris/simulator/languages/base.js"; import { Dispatch, MutableRefObject, useContext, useMemo, useRef } from "react"; import { useImmerReducer } from "../react.js"; diff --git a/simulator/src/jack/README.md b/simulator/src/jack/README.md index c08c0f5f..3c0080c3 100644 --- a/simulator/src/jack/README.md +++ b/simulator/src/jack/README.md @@ -1,16 +1,19 @@ # ANTLR Jack compiler -ANTLR gives us ability to generate lexer and parser in the target programming language(typescript in this case) using grammar files for [lexer](src/languages/grammars/JackLexer.g4) and [parser](src/languages/grammars/JackParser.g4). + +ANTLR gives us ability to generate lexer and parser in the target programming language(typescript in this case) using grammar files for [lexer](src/languages/grammars/JackLexer.g4) and [parser](src/languages/grammars/JackParser.g4). After parsing is done we get a tree data structure as an output. To do anything useful with this this tree we can use the next 2 design patterns: -1) Listener -2) Visitor + +1. Listener +2. Visitor You can read more about this design patterns and the difference between them in this [blog post](https://tomassetti.me/listeners-and-visitors/). You can also check out [antlr mega tutorial from the same company](https://tomassetti.me/antlr-mega-tutorial/). For jack we use next listeners: + - Error listener - listens to lexer and parser errors - Binder listener - creates global symbol table (classes and subroutines symbols) -- Validator listener - validates jack program +- Validator listener - validates jack program - VM Writer listener - generates VM code # Regenerate Jack Lexer and Parser files @@ -20,15 +23,19 @@ Next command gives us ability to regenerate parser and lexer after we've changed ``` npm run gen ``` -To run this command we would need to install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md). + +To run this command we would need to install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md). + ``` pip install antlr4-tools ``` -Underneath the covers previous command will install Java runtime(JRE)(if you don't have java installed on your machine) and antlr4-{version}-complete.jar from maven. -Beside generating lexer and parser files this tools include `antlr4-parse` that you can use to parser an input jack file and visualize the AST tree or view the token stream in command line. +Underneath the covers previous command will install Java runtime(JRE)(if you don't have java installed on your machine) and antlr4-{version}-complete.jar from maven. + +Beside generating lexer and parser files this tools include `antlr4-parse` that you can use to parser an input jack file and visualize the AST tree or view the token stream in command line. Small note - If you are using VSCode there is an extension to work with ANTLR grammar files. -# Working with typescript antlr runtime -As ANTLR main target for web is Javascript it doesn't have a typescript source code in general sense. Basically typescript runtime is a collection of javascript files and `.d.ts` files to provide typescript types. If you want to find out what's going on underneath the covers go to [antlr github page](https://github.com/antlr/antlr4/tree/dev/runtime/JavaScript) and find the javascript sources. \ No newline at end of file +# Working with typescript antlr runtime + +As ANTLR main target for web is Javascript it doesn't have a typescript source code in general sense. Basically typescript runtime is a collection of javascript files and `.d.ts` files to provide typescript types. If you want to find out what's going on underneath the covers go to [antlr github page](https://github.com/antlr/antlr4/tree/dev/runtime/JavaScript) and find the javascript sources. diff --git a/simulator/src/jack/antlr.compiler.test.ts b/simulator/src/jack/antlr.compiler.test.ts index 98657304..6e143621 100644 --- a/simulator/src/jack/antlr.compiler.test.ts +++ b/simulator/src/jack/antlr.compiler.test.ts @@ -24,7 +24,7 @@ describe("Jack compiler", () => { pop static 0 push constant 0 return - ` + `, ); }); test("field", () => { @@ -45,7 +45,7 @@ describe("Jack compiler", () => { pop this 0 push constant 0 return - ` + `, ); }); @@ -921,7 +921,7 @@ describe("Jack compiler", () => { }); async function testFilesInFolder( fs: FileSystem, - folderInTestResources: string + folderInTestResources: string, ) { const testFolder = getTestResourcePath(folderInTestResources); const files = [...(await fs.readdir(testFolder))] @@ -934,7 +934,7 @@ async function testFilesInFolder( const treeOrErrors = compiler.parserAndBind(input); if (Array.isArray(treeOrErrors)) { throw new Error( - `Unexpected compilation errors: ${treeOrErrors.join("\n")}` + `Unexpected compilation errors: ${treeOrErrors.join("\n")}`, ); } const tree = treeOrErrors as ProgramContext; @@ -947,7 +947,7 @@ async function testFilesInFolder( throw new Error(`Unexpected compilation errors: ${res.join("\n")}`); } else { expect(trimAndDeleteComments(res)).toEqual( - trimAndDeleteComments(expected) + trimAndDeleteComments(expected), ); } } @@ -976,7 +976,7 @@ function testCompiler(input: string, expected: string): void { const treeOrErrors = compiler.parserAndBind(input); if (Array.isArray(treeOrErrors)) { throw new Error( - `Unexpected compilation errors: ${treeOrErrors.join("\n")}` + `Unexpected compilation errors: ${treeOrErrors.join("\n")}`, ); } const tree = treeOrErrors as ProgramContext; diff --git a/simulator/src/jack/builtins.ts b/simulator/src/jack/builtins.ts index 74b80ce6..33c3ed44 100644 --- a/simulator/src/jack/builtins.ts +++ b/simulator/src/jack/builtins.ts @@ -6,7 +6,7 @@ interface Range { max: number; } -export const intRange:Range = { min: -32768, max: 32767 }; +export const intRange: Range = { min: -32768, max: 32767 }; const builtInFunctionsToArgCount: Record = { "Array.dispose": 0, diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 9a4f3691..0bf5bcec 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -10,12 +10,12 @@ import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; interface LexerNoViableAltException { startIndex: number; } -export class JackCustomErrorListener extends ErrorListener { +export class JackCustomErrorListener extends ErrorListener { public errors: JackCompilerError[] = []; override syntaxError = ( - recognizer: Recognizer, - offendingSymbol: unknown, + recognizer: Recognizer, + offendingSymbol: any, line: number, column: number, msg: string, diff --git a/simulator/src/jack/listener/global.symbol.table.listener.test.ts b/simulator/src/jack/listener/global.symbol.table.listener.test.ts index a3c4edde..1caf4b72 100644 --- a/simulator/src/jack/listener/global.symbol.table.listener.test.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.test.ts @@ -1,7 +1,11 @@ import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import path from "path"; -import { DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error"; +import { + DuplicatedClassError, + DuplicatedSubroutineError, + JackCompilerError, +} from "../error"; import { JackGlobalSymbolTableListener } from "./global.symbol.table.listener"; import { createSubroutineSymbol, SubroutineType } from "../symbol"; import { builtInSymbols } from "../builtins"; @@ -60,12 +64,12 @@ describe("Jack binder", () => { "Fraction.getNumerator": createSubroutineSymbol( 0, SubroutineType.Method, - 0 + 0, ), "Fraction.getDenominator": createSubroutineSymbol( 0, SubroutineType.Method, - 0 + 0, ), "Fraction.plus": createSubroutineSymbol(1, SubroutineType.Method, 1), "Fraction.dispose": createSubroutineSymbol(0, SubroutineType.Method, 0), @@ -88,10 +92,12 @@ describe("Jack binder", () => { expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); }); }); -function testJackGlobalSymbolListener JackCompilerError>( +function testJackGlobalSymbolListener< + T extends new (...args: any[]) => JackCompilerError, +>( input: string, expectedError?: T, - binder = new JackGlobalSymbolTableListener() + binder = new JackGlobalSymbolTableListener(), ) { const tree = parseJackText(input); listenToTheTree(tree, binder); @@ -107,7 +113,7 @@ function testJackGlobalSymbolListener JackComp throw new Error( `Expected error ${expectedError.name} but got '` + errors.join(",") + - "'" + "'", ); } } else { diff --git a/simulator/src/jack/listener/global.symbol.table.listener.ts b/simulator/src/jack/listener/global.symbol.table.listener.ts index 806c12ee..3efa06ed 100644 --- a/simulator/src/jack/listener/global.symbol.table.listener.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.ts @@ -39,7 +39,7 @@ export class JackGlobalSymbolTableListener extends JackParserListener { classNameCtx.start.line, classNameCtx.start.start, assertExists(classNameCtx.stop).stop + 1, - className + className, ); this.errors.push(e); return; @@ -69,8 +69,8 @@ export class JackGlobalSymbolTableListener extends JackParserListener { nameCtx.IDENTIFIER().symbol.line, nameCtx.start.start, nameCtx.start.stop, - subroutineName - ) + subroutineName, + ), ); this.stopProcessingSubroutines = true; } else { diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index 67e5ae8b..00ced3ab 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -51,7 +51,7 @@ describe("Jack validator listener", () => { function genericSymbol( type?: SubroutineType, - paramsCount?: number + paramsCount?: number, ): GenericSymbol { if (type != undefined && paramsCount != undefined) { return createSubroutineSymbol(paramsCount, type); @@ -89,9 +89,9 @@ describe("Jack validator listener", () => { class Main { ${classBody} }`, - DuplicatedVariableError + DuplicatedVariableError, ); - } + }, ); /** @@ -106,7 +106,7 @@ describe("Jack validator listener", () => { return; } }`, - UndeclaredVariableError + UndeclaredVariableError, ); }); @@ -126,7 +126,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 1), "Main.a": genericSymbol(SubroutineType.Function, 1), - } + }, ); }); @@ -141,7 +141,7 @@ describe("Jack validator listener", () => { } } }`, - UndeclaredVariableError + UndeclaredVariableError, ); }); @@ -157,7 +157,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError + UnknownClassError, ); }); @@ -173,7 +173,7 @@ describe("Jack validator listener", () => { { D: genericSymbol(), "D.new": genericSymbol(SubroutineType.Constructor, 0), - } + }, ); }); test("Arg Unknown class ", () => { @@ -184,7 +184,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError + UnknownClassError, ); }); @@ -198,7 +198,7 @@ describe("Jack validator listener", () => { } }`, undefined, - { D: genericSymbol() } + { D: genericSymbol() }, ); }); test("var Unknown class", () => { @@ -210,7 +210,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownClassError + UnknownClassError, ); }); test("var known type", () => { @@ -223,7 +223,7 @@ describe("Jack validator listener", () => { } }`, undefined, - { D: genericSymbol() } + { D: genericSymbol() }, ); }); test("field Unknown class", () => { @@ -232,7 +232,7 @@ describe("Jack validator listener", () => { class Main { field T t; }`, - UnknownClassError + UnknownClassError, ); }); test("field known type", () => { @@ -242,7 +242,7 @@ describe("Jack validator listener", () => { field T t; }`, undefined, - { T: genericSymbol() } + { T: genericSymbol() }, ); }); test("static field Unknown class", () => { @@ -251,7 +251,7 @@ describe("Jack validator listener", () => { class Main { static T t; }`, - UnknownClassError + UnknownClassError, ); }); test("static field known type", () => { @@ -261,7 +261,7 @@ describe("Jack validator listener", () => { static T t; }`, undefined, - { T: genericSymbol() } + { T: genericSymbol() }, ); }); @@ -277,7 +277,7 @@ describe("Jack validator listener", () => { return; } }`, - NonVoidFunctionNoReturnError + NonVoidFunctionNoReturnError, ); }); @@ -289,7 +289,7 @@ describe("Jack validator listener", () => { return 1; } }`, - VoidSubroutineReturnsValueError + VoidSubroutineReturnsValueError, ); }); /** @@ -310,7 +310,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError + SubroutineNotAllPathsReturnError, ); }); test("else missing return ", () => { @@ -327,7 +327,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError + SubroutineNotAllPathsReturnError, ); }); @@ -343,7 +343,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError + SubroutineNotAllPathsReturnError, ); }); @@ -359,7 +359,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError + SubroutineNotAllPathsReturnError, ); }); @@ -381,7 +381,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError + SubroutineNotAllPathsReturnError, ); }); test("nested if missing return 2", () => { @@ -402,7 +402,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError + SubroutineNotAllPathsReturnError, ); }); @@ -424,7 +424,7 @@ describe("Jack validator listener", () => { } } }`, - SubroutineNotAllPathsReturnError + SubroutineNotAllPathsReturnError, ); }); test("should be valid", () => { @@ -454,7 +454,7 @@ describe("Jack validator listener", () => { return; } }`, - UnknownSubroutineCallError + UnknownSubroutineCallError, ); }); @@ -475,7 +475,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 2), "Main.b": genericSymbol(SubroutineType.Function, 2), - } + }, ); }); @@ -502,7 +502,7 @@ describe("Jack validator listener", () => { "Main.new": genericSymbol(SubroutineType.Constructor, 0), "Main.a": genericSymbol(SubroutineType.Function, 0), "Main.b": genericSymbol(SubroutineType.Method, 0), - } + }, ); }); test("call local method ", () => { @@ -522,7 +522,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Method, 0), "Main.b": genericSymbol(SubroutineType.Method, 0), - } + }, ); }); @@ -546,7 +546,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), "Main.c": genericSymbol(SubroutineType.Method, 0), - } + }, ); }); test("function/ctor called as a method", () => { @@ -566,7 +566,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), "Main.c": genericSymbol(SubroutineType.Function, 0), - } + }, ); }); test("incorrect return type in constructor", () => { @@ -581,7 +581,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), D: genericSymbol(), - } + }, ); }); test("unreachable code", () => { @@ -599,7 +599,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), - } + }, ); }); test("A constructor must return 'this'", () => { @@ -614,7 +614,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), - } + }, ); }); test("Let statement - expected string literal ", () => { @@ -632,7 +632,7 @@ describe("Jack validator listener", () => { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), String: genericSymbol(), - } + }, ); }); test("Let statement - expected boolean literal ", () => { @@ -649,7 +649,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - } + }, ); }); @@ -667,7 +667,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - } + }, ); }); test("integer constant value is too big", () => { @@ -684,7 +684,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - } + }, ); }); test("integer constant value is too small", () => { @@ -701,7 +701,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - } + }, ); }); test("A field can not be referenced in a function", () => { @@ -718,7 +718,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - } + }, ); }); test("A static field can be referenced in a function", () => { @@ -735,7 +735,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - } + }, ); }); test("this can't be referenced in a function", () => { @@ -752,7 +752,7 @@ describe("Jack validator listener", () => { { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), - } + }, ); }); test("class name doesn't match filename", () => { @@ -762,7 +762,7 @@ describe("Jack validator listener", () => { { A: genericSymbol(), }, - "B" + "B", ); }); @@ -777,7 +777,8 @@ async function testJackDir(fs: FileSystem, testFolder: string): Promise { .filter((file) => file.endsWith(".jack")) .map((file) => path.join(testFolder, file)); const trees: Record = {}; - const globalSymbolsListener: JackGlobalSymbolTableListener = new JackGlobalSymbolTableListener(); + const globalSymbolsListener: JackGlobalSymbolTableListener = + new JackGlobalSymbolTableListener(); for (const filePath of files) { const tree = parseJackFile(filePath); trees[filePath] = tree; @@ -788,7 +789,7 @@ async function testJackDir(fs: FileSystem, testFolder: string): Promise { const tree = trees[filepath]; const validatorListener = listenToTheTree( tree, - new JackValidatorListener(globalSymbolsListener.globalSymbolTable) + new JackValidatorListener(globalSymbolsListener.globalSymbolTable), ); expect(validatorListener.errors).toEqual([]); } @@ -798,7 +799,7 @@ function testValidator( src: string, expectedError?: T, globalSymbolTable: Record = {}, - filename?: string + filename?: string, ) { const errorListener = new JackCustomErrorListener(); const tree = parseJackText(src, errorListener); @@ -818,13 +819,13 @@ function testValidator( throw new Error( `Expected error ${expectedError.name} but got '` + validator.errors.join(",") + - "'" + "'", ); } } else { if (validator.errors.length != 0) throw new Error( - "Didn't expect any errors but got " + validator.errors.join("\n") + "Didn't expect any errors but got " + validator.errors.join("\n"), ); } } diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index d1ede12d..583eaf08 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -64,7 +64,7 @@ export class JackValidatorListener extends JackParserListener { constructor( private globalSymbolTable: Record, private filename?: string, - public errors: JackCompilerError[] = [] + public errors: JackCompilerError[] = [], ) { super(); } @@ -84,8 +84,8 @@ export class JackValidatorListener extends JackParserListener { className.start.start, className.start.stop, this.filename, - this.className - ) + this.className, + ), ); } ctx.localSymbolTable = this.localSymbolTable; @@ -119,8 +119,8 @@ export class JackValidatorListener extends JackParserListener { new IncorrectConstructorReturnType( ctx.start.line, ctx.start.start, - ctx.start.stop - ) + ctx.start.stop, + ), ); } } else if (ctx.subroutineType().FUNCTION() != null) { @@ -132,7 +132,7 @@ export class JackValidatorListener extends JackParserListener { } }; override enterSubroutineDecWithoutType = ( - ctx: SubroutineDecWithoutTypeContext + ctx: SubroutineDecWithoutTypeContext, ) => { const returnType = ctx.subroutineReturnType(); this.subroutineShouldReturnVoidType = returnType.VOID() != null; @@ -145,7 +145,7 @@ export class JackValidatorListener extends JackParserListener { ctx, ctx.parameterName().getText(), ctx.varType().getText(), - this.subroutineType == SubroutineType.Method + this.subroutineType == SubroutineType.Method, ); }; //Var @@ -158,8 +158,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - type - ) + type, + ), ); } } @@ -183,8 +183,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - ctx.getText() - ) + ctx.getText(), + ), ); } else if ( this.subroutineType == SubroutineType.Function && @@ -194,8 +194,8 @@ export class JackValidatorListener extends JackParserListener { new FieldCantBeReferencedInFunction( ctx.start.line, ctx.start.start, - ctx.start.stop - ) + ctx.start.stop, + ), ); } }; @@ -209,8 +209,8 @@ export class JackValidatorListener extends JackParserListener { new ThisCantBeReferencedInFunction( ctx.start.line, ctx.start.start, - ctx.start.stop - ) + ctx.start.stop, + ), ); } }; @@ -221,8 +221,8 @@ export class JackValidatorListener extends JackParserListener { new UnreachableCodeError( ctx.start.line, ctx.start.start, - ctx.stop?.stop ?? ctx.start.stop - ) + ctx.stop?.stop ?? ctx.start.stop, + ), ); this.stopProcessingErrorsInThisScope = true; } @@ -284,8 +284,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - type - ) + type, + ), ); } else { const value = parseInt(constantCtx.INTEGER_LITERAL().getText()); @@ -297,8 +297,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.stop, value, intRange.min, - intRange.max - ) + intRange.max, + ), ); } } @@ -310,8 +310,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - type - ) + type, + ), ); } break; @@ -322,8 +322,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - type.toLowerCase() - ) + type.toLowerCase(), + ), ); } break; @@ -342,7 +342,7 @@ export class JackValidatorListener extends JackParserListener { unaryOp.expression().constant()?.INTEGER_LITERAL() !== null ) { const value = parseInt( - unaryOp.expression().constant().INTEGER_LITERAL().getText() + unaryOp.expression().constant().INTEGER_LITERAL().getText(), ); if (-value < intRange.min) { this.addError( @@ -352,8 +352,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.stop, value, intRange.min, - intRange.max - ) + intRange.max, + ), ); } } @@ -365,7 +365,7 @@ export class JackValidatorListener extends JackParserListener { const { callType, subroutineIdText } = getCallType( subroutineId, this.className, - this.localSymbolTable + this.localSymbolTable, ); const symbol = this.globalSymbolTable[subroutineIdText]; @@ -376,8 +376,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.start, ctx.start.stop, subroutineId.subroutineName().getText(), - subroutineId.className()?.getText() - ) + subroutineId.className()?.getText(), + ), ); } else { //method called as a function @@ -390,8 +390,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - subroutineId.subroutineName().getText() - ) + subroutineId.subroutineName().getText(), + ), ); } // function called as a method @@ -404,8 +404,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - subroutineId.subroutineName().getText() - ) + subroutineId.subroutineName().getText(), + ), ); } else { //check parameter count @@ -418,8 +418,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.stop, subroutineId.getText(), assertExists(symbol.subroutineInfo).paramsCount, - l - ) + l, + ), ); } } @@ -433,8 +433,8 @@ export class JackValidatorListener extends JackParserListener { new NonVoidFunctionNoReturnError( lastToken.line, lastToken.start, - lastToken.stop - ) + lastToken.stop, + ), ); } if (!returnsVoid && this.subroutineShouldReturnVoidType) { @@ -442,8 +442,8 @@ export class JackValidatorListener extends JackParserListener { new VoidSubroutineReturnsValueError( lastToken.line, lastToken.start, - lastToken.stop - ) + lastToken.stop, + ), ); } this.controlFlowGraphNode.returns = true; @@ -458,8 +458,8 @@ export class JackValidatorListener extends JackParserListener { new ConstructorMushReturnThis( lastToken.line, lastToken.start, - lastToken.stop - ) + lastToken.stop, + ), ); } } @@ -470,11 +470,11 @@ export class JackValidatorListener extends JackParserListener { const lastToken = assertExists(ctx.stop); this.addError( new SubroutineNotAllPathsReturnError( - lastToken.line, + lastToken.line, lastToken.start, lastToken.stop, - this.subroutineName - ) + this.subroutineName, + ), ); } this.subroutineType = undefined; @@ -494,7 +494,7 @@ export class JackValidatorListener extends JackParserListener { ctx: ParserRuleContext, name: string, type: string, - inMethod: boolean + inMethod: boolean, ) { if (this.localSymbolTable.lookup(name)) { this.addError( @@ -502,8 +502,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - name - ) + name, + ), ); } else { this.localSymbolTable.defineArgument(name, type, inMethod); @@ -513,7 +513,7 @@ export class JackValidatorListener extends JackParserListener { ctx: ParserRuleContext, scope: ScopeType, name: string, - type: string + type: string, ) { if (this.localSymbolTable.lookup(name)) { this.addError( @@ -521,8 +521,8 @@ export class JackValidatorListener extends JackParserListener { ctx.start.line, ctx.start.start, ctx.start.stop, - name - ) + name, + ), ); } else { this.localSymbolTable.define(scope, name, type); @@ -538,7 +538,7 @@ class BinaryTreeNode { constructor( public parent?: BinaryTreeNode, public left?: BinaryTreeNode, - public right?: BinaryTreeNode + public right?: BinaryTreeNode, ) {} public get returns(): boolean { @@ -577,13 +577,13 @@ class BinaryTreeNode { } else { res += this.left?.printBT( side == Side.LEFT ? "| " : " ", - Side.LEFT + Side.LEFT, ); if (this.right) { res += prefix; res += this.right?.printBT( side == Side.LEFT ? "|\t" : "\t", - Side.RIGHT + Side.RIGHT, ); } else { res += "\n"; diff --git a/simulator/src/jack/parser.test.ts b/simulator/src/jack/parser.test.ts index 542b7d8a..79c6159d 100644 --- a/simulator/src/jack/parser.test.ts +++ b/simulator/src/jack/parser.test.ts @@ -49,7 +49,10 @@ function testJackDir(testFolder: string): void { .map((file) => path.join(testFolder, file)); for (const filePath of files) { const tree = parseJackFile(filePath); - const globalSymbolsListener = listenToTheTree(tree, new JackGlobalSymbolTableListener()); + const globalSymbolsListener = listenToTheTree( + tree, + new JackGlobalSymbolTableListener(), + ); const symbolsErrors = globalSymbolsListener.errors.join("\n"); try { expect(globalSymbolsListener.errors.length).toBe(0); From bf7acd04eb2c26e3c639eca3c493abc9d79500d9 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 17 Oct 2024 17:48:48 +0200 Subject: [PATCH 72/87] Fix bug in jack lexer. Fix cli for compiler --- cli/src/index.ts | 2 +- simulator/src/languages/grammars/JackLexer.g4 | 19 ++++++++----------- .../src/languages/grammars/JackParser.g4 | 12 ++++++------ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/cli/src/index.ts b/cli/src/index.ts index a541b2b2..82accdf1 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -7,7 +7,7 @@ import { testRunner } from "./testrunner.js"; import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; import * as fsCore from "fs"; -import { compile } from "@nand2tetris/simulator/jack/compiler.js"; +import { compile } from "@nand2tetris/simulator/jack/anltr.compiler.js"; yargs(hideBin(process.argv)) .usage("$0 ") diff --git a/simulator/src/languages/grammars/JackLexer.g4 b/simulator/src/languages/grammars/JackLexer.g4 index a2268f48..d0ced09a 100644 --- a/simulator/src/languages/grammars/JackLexer.g4 +++ b/simulator/src/languages/grammars/JackLexer.g4 @@ -19,7 +19,6 @@ ELSE: 'else'; WHILE: 'while'; RETURN: 'return'; - LBRACE: '{'; RBRACE: '}'; LPAREN: '('; @@ -41,22 +40,20 @@ TILDE: '~'; LESS_THAN: '<'; GREATER_THAN: '>'; -WS: [ \t\r\n]+ -> skip; -COMMENT: '/*' .*? '*/' -> skip; -LINE_COMMENT: '//' ~[\r\n]* -> skip; +WHITESPACE: [ \t\r\n\f]+ -> channel(HIDDEN); +BLOCK_COMMENT: '/*' .*? ('*/' | EOF) -> channel(HIDDEN); +LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN); INTEGER_LITERAL: [0-9]+; -TRUE: 'true'; +TRUE: 'true'; FALSE: 'false'; NULL_LITERAL: 'null'; THIS_LITERAL: 'this'; IDENTIFIER: [a-zA-Z_] [a-zA-Z0-9_]*; -STRING_LITERAL - : UnterminatedStringLiteral '"' - ; -UnterminatedStringLiteral - : '"' ~["\\\r\n]* - ; + +STRING_LITERAL: '"' (~["\r\n])* '"'; +// STRING_LITERAL: UnterminatedStringLiteral '"'; +// UnterminatedStringLiteral: '"' ~["\\\r\n]*; \ No newline at end of file diff --git a/simulator/src/languages/grammars/JackParser.g4 b/simulator/src/languages/grammars/JackParser.g4 index 04b06824..bcddbdeb 100644 --- a/simulator/src/languages/grammars/JackParser.g4 +++ b/simulator/src/languages/grammars/JackParser.g4 @@ -4,7 +4,7 @@ options { tokenVocab = JackLexer; } @header { - import { SubroutineScope, LocalSymbolTable } from "../symbol"; +import { SubroutineScope, LocalSymbolTable } from "../symbol"; } program: classDeclaration EOF; @@ -34,7 +34,6 @@ rBrace: RBRACE; varDeclaration: VAR varType varNameInDeclaration (COMMA varNameInDeclaration)* SEMICOLON; varNameInDeclaration: IDENTIFIER; -varName: IDENTIFIER; statements: statement*; statement: letStatement @@ -75,16 +74,17 @@ expression: | expression binaryOperator expression | groupedExpression; -groupedExpression: LPAREN expression RPAREN; -unaryOperation: unaryOperator expression; -arrayAccess: varName LBRACKET expression RBRACKET; - constant: INTEGER_LITERAL | STRING_LITERAL | booleanLiteral | NULL_LITERAL | THIS_LITERAL; +varName: IDENTIFIER; +arrayAccess: varName LBRACKET expression RBRACKET; +unaryOperation: unaryOperator expression; +groupedExpression: LPAREN expression RPAREN; + booleanLiteral: TRUE | FALSE; unaryOperator: TILDE | MINUS; binaryOperator: From 3e3560492bf57cc9adeddfb957bf790f8b35f984 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:45:14 +0200 Subject: [PATCH 73/87] Fix bugs --- simulator/src/jack/README.md | 2 +- simulator/src/jack/anltr.compiler.ts | 16 +- simulator/src/jack/error.ts | 6 +- simulator/src/jack/listener/error.listener.ts | 25 ++- .../global.symbol.table.listener.test.ts | 44 +++-- .../listener/global.symbol.table.listener.ts | 24 +-- .../jack/listener/validator.listener.test.ts | 4 +- .../src/jack/listener/validator.listener.ts | 158 +++++++++--------- 8 files changed, 143 insertions(+), 136 deletions(-) diff --git a/simulator/src/jack/README.md b/simulator/src/jack/README.md index 3c0080c3..5c58bba2 100644 --- a/simulator/src/jack/README.md +++ b/simulator/src/jack/README.md @@ -12,7 +12,7 @@ You can read more about this design patterns and the difference between them in For jack we use next listeners: - Error listener - listens to lexer and parser errors -- Binder listener - creates global symbol table (classes and subroutines symbols) +- Global symbol table listener - creates global symbol table (classes and subroutines symbols) - Validator listener - validates jack program - VM Writer listener - generates VM code diff --git a/simulator/src/jack/anltr.compiler.ts b/simulator/src/jack/anltr.compiler.ts index 13076465..85d147dd 100644 --- a/simulator/src/jack/anltr.compiler.ts +++ b/simulator/src/jack/anltr.compiler.ts @@ -103,19 +103,19 @@ function toCompilerError(errors: JackCompilerError[]): CompilationError { } export class JackCompiler { - private binder = new JackGlobalSymbolTableListener(); + private globalSymbolTableListener = new JackGlobalSymbolTableListener(); private errorListener = new JackCustomErrorListener(); validate( tree: ProgramContext, filename?: string, ): ProgramContext | JackCompilerError[] { - if (Object.keys(this.binder.globalSymbolTable).length == 0) { + if (Object.keys(this.globalSymbolTableListener.globalSymbolTable).length == 0) { throw new Error( "Please populate global symbol table using parserAndBind method", ); } const validator = new JackValidatorListener( - this.binder.globalSymbolTable, + this.globalSymbolTableListener.globalSymbolTable, filename, ); ParseTreeWalker.DEFAULT.walk(validator, tree); @@ -133,7 +133,7 @@ export class JackCompiler { return errors; } const validateTree = treeOrErrors as ProgramContext; - const vmWriter = new JackVMWriter(this.binder.globalSymbolTable); + const vmWriter = new JackVMWriter(this.globalSymbolTableListener.globalSymbolTable); ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); return vmWriter.result; } @@ -151,10 +151,10 @@ export class JackCompiler { console.log("Errors when parsing or lexing"); return this.errorListener.errors; } - ParseTreeWalker.DEFAULT.walk(this.binder, tree); - if (this.binder.errors.length > 0) { - console.log("Errors in binder"); - return this.binder.errors; + ParseTreeWalker.DEFAULT.walk(this.globalSymbolTableListener, tree); + if (this.globalSymbolTableListener.errors.length > 0) { + console.log("Errors when creating global symbol table"); + return this.globalSymbolTableListener.errors; } return tree; } diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 174d1885..e66efcd3 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -63,7 +63,7 @@ export const DuplicatedClassError = (span: Span, className: string) => export const DuplicatedSubroutineError = (span: Span, subroutineName: string) => makeJackCompilerError( - "DuplicatedClassError", + "DuplicatedSubroutineError", span, `Subroutine ${subroutineName} is already defined.` ); @@ -131,8 +131,8 @@ export const IntLiteralIsOutOfRangeError = ( `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}` ); -export const LexerOrParserError = (span: Span) => - makeJackCompilerError("LexerOrParserError", span); +export const LexerOrParserError = (span: Span, msg?: string) => + makeJackCompilerError("LexerOrParserError", span, msg); export const MethodCalledAsFunctionError = (span: Span, subroutineId: string) => makeJackCompilerError( diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 33f45eb1..1dbaa86e 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -5,7 +5,7 @@ import { Recognizer, Token, } from "antlr4"; -import { JackCompilerError, LexerOrParserError } from "../error.js"; +import { asSpan, JackCompilerError, LexerOrParserError } from "../error.js"; import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; interface LexerNoViableAltException { startIndex: number; @@ -19,20 +19,29 @@ export class JackCustomErrorListener extends ErrorListener { line: number, column: number, msg: string, - err: RecognitionException | undefined, + err: RecognitionException | undefined ) => { - if (offendingSymbol != null || (err?.offendingToken)) { - const t = offendingSymbol ?? (assertExists(e).offendingToken as Token); - this.errors.push(LexerOrParserError({line, start: t.start, end: t.stop + 1})); - } else if (err instanceof NoViableAltException) { + if (offendingSymbol != null || err?.offendingToken) { + const t = offendingSymbol ?? (assertExists(err).offendingToken as Token); this.errors.push( - LexerOrParserError({line, start: err.startIndex, end: err.startIndex + 1}) + LexerOrParserError({ line, start: t.start, end: t.stop + 1 }, msg) ); + } else if (err instanceof NoViableAltException) { + //TODO: RL change and fix + this.errors.push(LexerOrParserError(asSpan(err.startToken), msg)); } //antlr doesn't provide a class for LexerNoViableAltException atm. Once https://github.com/antlr/antlr4/pull/4711 is release we can change it else if (err != null && "startIndex" in err) { + const startIndex = err.startIndex as number; this.errors.push( - LexerOrParserError({line, start: err.startIndex, end: err.startIndex + 1}, msg), + LexerOrParserError( + { + line, + start: startIndex, + end: startIndex + 1, + }, + msg + ) ); } else { console.error("Don't know how to handle this error"); diff --git a/simulator/src/jack/listener/global.symbol.table.listener.test.ts b/simulator/src/jack/listener/global.symbol.table.listener.test.ts index 1caf4b72..78916f8e 100644 --- a/simulator/src/jack/listener/global.symbol.table.listener.test.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.test.ts @@ -1,22 +1,20 @@ import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import path from "path"; +import { builtInSymbols } from "../builtins"; import { - DuplicatedClassError, - DuplicatedSubroutineError, - JackCompilerError, + JackCompilerErrorType } from "../error"; -import { JackGlobalSymbolTableListener } from "./global.symbol.table.listener"; import { createSubroutineSymbol, SubroutineType } from "../symbol"; -import { builtInSymbols } from "../builtins"; import { getTestResourcePath, listenToTheTree, parseJackFile, parseJackText, } from "../test.helper"; +import { JackGlobalSymbolTableListener } from "./global.symbol.table.listener"; -describe("Jack binder", () => { +describe("Jack global symbol table listener", () => { const jestConsole = console; let fs: FileSystem; beforeEach(() => { @@ -38,22 +36,22 @@ describe("Jack binder", () => { return 1; } }`; - testJackGlobalSymbolListener(input, DuplicatedSubroutineError); + testJackGlobalSymbolListener(input, "DuplicatedSubroutineError"); }); test("duplicated class", () => { const input = ` class A { }`; - const binder = new JackGlobalSymbolTableListener(); - testJackGlobalSymbolListener(input, undefined, binder); - testJackGlobalSymbolListener(input, DuplicatedClassError, binder); + const globalSymbolTableListener = new JackGlobalSymbolTableListener(); + testJackGlobalSymbolListener(input, undefined, globalSymbolTableListener); + testJackGlobalSymbolListener(input, "DuplicatedClassError", globalSymbolTableListener); }); test("duplicated built in class", () => { const input = ` class Math { }`; - testJackGlobalSymbolListener(input, DuplicatedClassError); + testJackGlobalSymbolListener(input, "DuplicatedClassError"); }); test("basic", async () => { const expected = { @@ -64,12 +62,12 @@ describe("Jack binder", () => { "Fraction.getNumerator": createSubroutineSymbol( 0, SubroutineType.Method, - 0, + 0 ), "Fraction.getDenominator": createSubroutineSymbol( 0, SubroutineType.Method, - 0, + 0 ), "Fraction.plus": createSubroutineSymbol(1, SubroutineType.Method, 1), "Fraction.dispose": createSubroutineSymbol(0, SubroutineType.Method, 0), @@ -92,28 +90,26 @@ describe("Jack binder", () => { expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); }); }); -function testJackGlobalSymbolListener< - T extends new (...args: any[]) => JackCompilerError, ->( +function testJackGlobalSymbolListener( input: string, expectedError?: T, - binder = new JackGlobalSymbolTableListener(), + globalSymbolTableListener = new JackGlobalSymbolTableListener() ) { const tree = parseJackText(input); - listenToTheTree(tree, binder); - const errors = binder.errors; + listenToTheTree(tree, globalSymbolTableListener); + const errors = globalSymbolTableListener.errors; if (expectedError) { if (errors.length > 1) { console.error("Errors", errors); } try { - expect(errors.length).toBe(1); - expect(errors[0]).toBeInstanceOf(expectedError); + expect(globalSymbolTableListener.errors.length).toBe(1); + expect(globalSymbolTableListener.errors[0].type).toBe(expectedError); } catch (e) { throw new Error( - `Expected error ${expectedError.name} but got '` + - errors.join(",") + - "'", + `Expected error ${expectedError} but got '` + + JSON.stringify(globalSymbolTableListener.errors) + + "'" ); } } else { diff --git a/simulator/src/jack/listener/global.symbol.table.listener.ts b/simulator/src/jack/listener/global.symbol.table.listener.ts index b2f1f58a..e410ce2d 100644 --- a/simulator/src/jack/listener/global.symbol.table.listener.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.ts @@ -4,7 +4,12 @@ import { SubroutineDeclarationContext, VarNameInDeclarationContext, } from "../generated/JackParser.js"; -import { asSpan, DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error.js"; +import { + asSpan, + DuplicatedClassError, + DuplicatedSubroutineError, + JackCompilerError, +} from "../error.js"; import { builtInSymbols, builtInTypes } from "../builtins.js"; import { GenericSymbol, @@ -13,7 +18,6 @@ import { SubroutineType, } from "../symbol.js"; import JackParserListener from "../generated/JackParserListener.js"; -import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; const primitives = new Set(builtInTypes); export type Primitive = typeof primitives extends Set ? S : never; @@ -36,9 +40,7 @@ export class JackGlobalSymbolTableListener extends JackParserListener { const className = id.getText(); if (this.globalSymbolTable[className] != undefined) { //TODO: RL check on UI - const e = DuplicatedClassError( - asSpan(ctxClassName.start, ctxClassName.stop), className - ); + const e = DuplicatedClassError(asSpan(id.symbol, id.symbol), className); this.errors.push(e); return; } @@ -65,12 +67,12 @@ export class JackGlobalSymbolTableListener extends JackParserListener { this.errors.push( DuplicatedSubroutineError( { - line: nameCtx.IDENTIFIER().symbol.line, - start: nameCtx.start.start, - end: nameCtx.start.stop, - }, - subroutineName, - ), + line: nameCtx.IDENTIFIER().symbol.line, + start: nameCtx.start.start, + end: nameCtx.start.stop, + }, + subroutineName + ) ); this.stopProcessingSubroutines = true; } else { diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index 8efc4add..08b537c1 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -782,7 +782,7 @@ function testValidator( globalSymbolTable: Record = {}, filename?: string, ) { - const errorListener = new CustomErrorListener(); + const errorListener = new JackCustomErrorListener(); const tree = parseJackText(src, errorListener); const listener = filename != null @@ -799,7 +799,7 @@ function testValidator( } catch (e) { throw new Error( `Expected error ${expectedError} but got '` + - validator.errors.join(",") + + JSON.stringify(validator.errors) + "'", ); } diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index e94e1a5b..15a15acd 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -1,6 +1,28 @@ -import { ParserRuleContext, Token } from "antlr4"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; +import { ParserRuleContext } from "antlr4"; import { builtInTypes, intRange } from "../builtins.js"; -import { asSpan, ConstructorMushReturnThisError, DuplicatedVariableError, FieldCantBeReferencedInFunctionError, FilenameDoesntMatchClassNameError, FunctionCalledAsMethodError, IncorrectConstructorReturnTypeError, IncorrectParamsNumberInSubroutineCallError, IntLiteralIsOutOfRangeError, JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, SubroutineNotAllPathsReturnError, ThisCantBeReferencedInFunctionError, UndeclaredVariableError, UnknownClassError, UnknownSubroutineCallError, UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError } from "../error.js"; +import { + asSpan, + ConstructorMushReturnThisError, + DuplicatedVariableError, + FieldCantBeReferencedInFunctionError, + FilenameDoesntMatchClassNameError, + FunctionCalledAsMethodError, + IncorrectConstructorReturnTypeError, + IncorrectParamsNumberInSubroutineCallError, + IntLiteralIsOutOfRangeError, + JackCompilerError, + MethodCalledAsFunctionError, + NonVoidFunctionNoReturnError, + SubroutineNotAllPathsReturnError, + ThisCantBeReferencedInFunctionError, + UndeclaredVariableError, + UnknownClassError, + UnknownSubroutineCallError, + UnreachableCodeError, + VoidSubroutineReturnsValueError, + WrongLiteralTypeError, +} from "../error.js"; import { ClassDeclarationContext, ClassVarDecContext, @@ -29,8 +51,6 @@ import { SubroutineType, } from "../symbol.js"; import { CallType, getCallType } from "./common.js"; -import { Span } from "../../languages/base.js"; -import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; /** * Validates Jack file @@ -46,7 +66,7 @@ export class JackValidatorListener extends JackParserListener { constructor( private globalSymbolTable: Record, private filename?: string, - public errors: JackCompilerError[] = [], + public errors: JackCompilerError[] = [] ) { super(); } @@ -60,7 +80,13 @@ export class JackValidatorListener extends JackParserListener { this.className = newName; if (this.filename != null && this.filename != this.className) { console.error("FilenameDoesntMatchClassName"); - this.errors.push( FilenameDoesntMatchClassNameError(asSpan(ctx.start), this.filename, this.className,),); + this.errors.push( + FilenameDoesntMatchClassNameError( + asSpan(ctx.start), + this.filename, + this.className + ) + ); } ctx.localSymbolTable = this.localSymbolTable; }; @@ -89,11 +115,7 @@ export class JackValidatorListener extends JackParserListener { ctx.subroutineDecWithoutType().subroutineReturnType().getText() !== this.className ) { - this.addError( - IncorrectConstructorReturnTypeError( - asSpan(ctx.start) - ), - ); + this.addError(IncorrectConstructorReturnTypeError(asSpan(ctx.start))); } } else if (ctx.subroutineType().FUNCTION() != null) { this.subroutineType = SubroutineType.Function; @@ -104,7 +126,7 @@ export class JackValidatorListener extends JackParserListener { } }; override enterSubroutineDecWithoutType = ( - ctx: SubroutineDecWithoutTypeContext, + ctx: SubroutineDecWithoutTypeContext ) => { const returnType = ctx.subroutineReturnType(); this.subroutineShouldReturnVoidType = returnType.VOID() != null; @@ -117,7 +139,7 @@ export class JackValidatorListener extends JackParserListener { ctx, ctx.parameterName().getText(), ctx.varType().getText(), - this.subroutineType == SubroutineType.Method, + this.subroutineType == SubroutineType.Method ); }; //Var @@ -125,9 +147,7 @@ export class JackValidatorListener extends JackParserListener { if (ctx.IDENTIFIER() != null) { const type = ctx.IDENTIFIER().getText(); if (this.globalSymbolTable[type] == null) { - this.addError( - UnknownClassError(asSpan(ctx.start), type,), - ); + this.addError(UnknownClassError(asSpan(ctx.start), type)); } } }; @@ -150,9 +170,7 @@ export class JackValidatorListener extends JackParserListener { this.subroutineType == SubroutineType.Function && symbol.scope == ScopeType.This ) { - this.addError( - FieldCantBeReferencedInFunctionError(asSpan(ctx.start)), - ); + this.addError(FieldCantBeReferencedInFunctionError(asSpan(ctx.start))); } }; @@ -161,15 +179,13 @@ export class JackValidatorListener extends JackParserListener { ctx.THIS_LITERAL() != null && this.subroutineType == SubroutineType.Function ) { - this.addError( - ThisCantBeReferencedInFunctionError(asSpan(ctx.start)) - ); + this.addError(ThisCantBeReferencedInFunctionError(asSpan(ctx.start))); } }; override enterStatement = (ctx: StatementContext) => { if (this.controlFlowGraphNode.returns == true) { - this.addError( UnreachableCodeError( asSpan(ctx.start, ctx.stop)),); + this.addError(UnreachableCodeError(asSpan(ctx.start, ctx.stop))); this.stopProcessingErrorsInThisScope = true; } }; @@ -220,40 +236,35 @@ export class JackValidatorListener extends JackParserListener { const symbol = this.localSymbolTable.lookup(ctx.varName().getText()); const type = assertExists(symbol).type; if (literalTypes.indexOf(type) != -1) { - const constantCtx = ctx.expression().constant()!; + const constantCtx = ctx.expression().constant(); switch (type) { case "char": case "int": if (constantCtx.INTEGER_LITERAL() === null) { - this.addError( - WrongLiteralTypeError(asSpan(ctx.start), type,), - ); + this.addError(WrongLiteralTypeError(asSpan(ctx.start), type)); } else { const value = parseInt(constantCtx.INTEGER_LITERAL().getText()); if (value > intRange.max) { this.addError( - IntLiteralIsOutOfRangeError(asSpan(ctx.start), + IntLiteralIsOutOfRangeError( + asSpan(ctx.start), value, intRange.min, - intRange.max, - ), + intRange.max + ) ); } } break; case "boolean": if (constantCtx.booleanLiteral() === null) { - this.addError( - WrongLiteralTypeError( asSpan(ctx.start), type,), - ); + this.addError(WrongLiteralTypeError(asSpan(ctx.start), type)); } break; case "String": if (constantCtx.STRING_LITERAL() === null) { this.addError( - WrongLiteralTypeError(asSpan(ctx.start), - type.toLowerCase(), - ), + WrongLiteralTypeError(asSpan(ctx.start), type.toLowerCase()) ); } break; @@ -272,15 +283,16 @@ export class JackValidatorListener extends JackParserListener { unaryOp.expression().constant()?.INTEGER_LITERAL() !== null ) { const value = parseInt( - unaryOp.expression().constant().INTEGER_LITERAL().getText(), + unaryOp.expression().constant().INTEGER_LITERAL().getText() ); if (-value < intRange.min) { this.addError( - IntLiteralIsOutOfRangeError(asSpan(ctx.start), + IntLiteralIsOutOfRangeError( + asSpan(ctx.start), value, intRange.min, - intRange.max, - ), + intRange.max + ) ); } } @@ -292,16 +304,17 @@ export class JackValidatorListener extends JackParserListener { const { callType, subroutineIdText } = getCallType( subroutineId, this.className, - this.localSymbolTable, + this.localSymbolTable ); const symbol = this.globalSymbolTable[subroutineIdText]; if (symbol == undefined) { this.addError( - UnknownSubroutineCallError(asSpan(ctx.start), + UnknownSubroutineCallError( + asSpan(ctx.start), subroutineId.subroutineName().getText(), - subroutineId.className()?.getText(), - ), + subroutineId.className()?.getText() + ) ); } else { //method called as a function @@ -310,9 +323,10 @@ export class JackValidatorListener extends JackParserListener { callType == CallType.ClassFunctionOrConstructor ) { this.addError( - MethodCalledAsFunctionError(asSpan(ctx.start), - subroutineId.subroutineName().getText(), - ), + MethodCalledAsFunctionError( + asSpan(ctx.start), + subroutineId.subroutineName().getText() + ) ); } // function called as a method @@ -321,9 +335,10 @@ export class JackValidatorListener extends JackParserListener { callType == CallType.LocalMethod ) { this.addError( - FunctionCalledAsMethodError(asSpan(ctx.start), - subroutineId.subroutineName().getText(), - ), + FunctionCalledAsMethodError( + asSpan(ctx.start), + subroutineId.subroutineName().getText() + ) ); } else { //check parameter count @@ -331,11 +346,11 @@ export class JackValidatorListener extends JackParserListener { if (assertExists(symbol.subroutineInfo).paramsCount != l) { this.addError( IncorrectParamsNumberInSubroutineCallError( - asSpan(ctx.start), + asSpan(ctx.start), subroutineId.getText(), assertExists(symbol.subroutineInfo).paramsCount, - assertExists(symbol.subroutineInfo?.localVarsCount), - ), + l + ) ); } } @@ -343,16 +358,13 @@ export class JackValidatorListener extends JackParserListener { }; override enterReturnStatement = (ctx: ReturnStatementContext) => { const returnsVoid = ctx.expression() == null; - const lastToken = assertExists(ctx.stop); if (returnsVoid && !this.subroutineShouldReturnVoidType) { this.addError( NonVoidFunctionNoReturnError(asSpan(ctx.stop ?? ctx.start)) ); } if (!returnsVoid && this.subroutineShouldReturnVoidType) { - this.addError( - VoidSubroutineReturnsValueError(asSpan(ctx.start)), - ); + this.addError(VoidSubroutineReturnsValueError(asSpan(ctx.start))); } this.controlFlowGraphNode.returns = true; if (this.subroutineType == SubroutineType.Constructor) { @@ -363,9 +375,7 @@ export class JackValidatorListener extends JackParserListener { ctx.expression().constant().THIS_LITERAL() == null ) { this.addError( - ConstructorMushReturnThisError( - asSpan(ctx.stop ?? ctx.start), - ), + ConstructorMushReturnThisError(asSpan(ctx.stop ?? ctx.start)) ); } } @@ -373,14 +383,11 @@ export class JackValidatorListener extends JackParserListener { override exitSubroutineBody = (ctx: SubroutineBodyContext) => { if (!this.controlFlowGraphNode.returns) { - const lastToken = assertExists(ctx.stop); this.addError( - SubroutineNotAllPathsReturnError( - //TODO: change this and similar asSpan(ctx.stop ?? ctx.start), - this.subroutineName, - ), + this.subroutineName + ) ); } this.subroutineType = undefined; @@ -400,12 +407,10 @@ export class JackValidatorListener extends JackParserListener { ctx: ParserRuleContext, name: string, type: string, - inMethod: boolean, + inMethod: boolean ) { if (this.localSymbolTable.lookup(name)) { - this.addError( - DuplicatedVariableError (asSpan(ctx.start), name) - ); + this.addError(DuplicatedVariableError(asSpan(ctx.start), name)); } else { this.localSymbolTable.defineArgument(name, type, inMethod); } @@ -414,15 +419,10 @@ export class JackValidatorListener extends JackParserListener { ctx: ParserRuleContext, scope: ScopeType, name: string, - type: string, + type: string ) { if (this.localSymbolTable.lookup(name)) { - this.addError( - DuplicatedVariableError ( - asSpan(ctx.start), - name, - ), - ); + this.addError(DuplicatedVariableError(asSpan(ctx.start), name)); } else { this.localSymbolTable.define(scope, name, type); } @@ -437,7 +437,7 @@ class BinaryTreeNode { constructor( public parent?: BinaryTreeNode, public left?: BinaryTreeNode, - public right?: BinaryTreeNode, + public right?: BinaryTreeNode ) {} public get returns(): boolean { @@ -476,13 +476,13 @@ class BinaryTreeNode { } else { res += this.left?.printBT( side == Side.LEFT ? "| " : " ", - Side.LEFT, + Side.LEFT ); if (this.right) { res += prefix; res += this.right?.printBT( side == Side.LEFT ? "|\t" : "\t", - Side.RIGHT, + Side.RIGHT ); } else { res += "\n"; From 7604ef5c0c2e062464d48a658c05e9098385457e Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Thu, 17 Oct 2024 18:45:58 +0200 Subject: [PATCH 74/87] Generate antlr files --- simulator/src/jack/generated/JackLexer.interp | 13 +- simulator/src/jack/generated/JackLexer.tokens | 5 +- simulator/src/jack/generated/JackLexer.ts | 624 +- .../src/jack/generated/JackParser.interp | 16 +- .../src/jack/generated/JackParser.tokens | 5 +- simulator/src/jack/generated/JackParser.ts | 6748 ++++++++--------- .../src/jack/generated/JackParserListener.ts | 878 +-- 7 files changed, 3844 insertions(+), 4445 deletions(-) diff --git a/simulator/src/jack/generated/JackLexer.interp b/simulator/src/jack/generated/JackLexer.interp index f31eda73..c9f1c379 100644 --- a/simulator/src/jack/generated/JackLexer.interp +++ b/simulator/src/jack/generated/JackLexer.interp @@ -46,7 +46,6 @@ null 'this' null null -null token symbolic names: null @@ -86,8 +85,8 @@ OR TILDE LESS_THAN GREATER_THAN -WS -COMMENT +WHITESPACE +BLOCK_COMMENT LINE_COMMENT INTEGER_LITERAL TRUE @@ -96,7 +95,6 @@ NULL_LITERAL THIS_LITERAL IDENTIFIER STRING_LITERAL -UnterminatedStringLiteral rule names: CLASS @@ -135,8 +133,8 @@ OR TILDE LESS_THAN GREATER_THAN -WS -COMMENT +WHITESPACE +BLOCK_COMMENT LINE_COMMENT INTEGER_LITERAL TRUE @@ -145,7 +143,6 @@ NULL_LITERAL THIS_LITERAL IDENTIFIER STRING_LITERAL -UnterminatedStringLiteral channel names: DEFAULT_TOKEN_CHANNEL @@ -155,4 +152,4 @@ mode names: DEFAULT_MODE atn: -[4, 0, 47, 309, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 4, 36, 236, 8, 36, 11, 36, 12, 36, 237, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 246, 8, 37, 10, 37, 12, 37, 249, 9, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 260, 8, 38, 10, 38, 12, 38, 263, 9, 38, 1, 38, 1, 38, 1, 39, 4, 39, 268, 8, 39, 11, 39, 12, 39, 269, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 5, 44, 295, 8, 44, 10, 44, 12, 44, 298, 9, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 5, 46, 305, 8, 46, 10, 46, 12, 46, 308, 9, 46, 1, 247, 0, 47, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 1, 0, 6, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 314, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 1, 95, 1, 0, 0, 0, 3, 101, 1, 0, 0, 0, 5, 113, 1, 0, 0, 0, 7, 122, 1, 0, 0, 0, 9, 129, 1, 0, 0, 0, 11, 135, 1, 0, 0, 0, 13, 142, 1, 0, 0, 0, 15, 146, 1, 0, 0, 0, 17, 150, 1, 0, 0, 0, 19, 155, 1, 0, 0, 0, 21, 163, 1, 0, 0, 0, 23, 168, 1, 0, 0, 0, 25, 172, 1, 0, 0, 0, 27, 175, 1, 0, 0, 0, 29, 178, 1, 0, 0, 0, 31, 183, 1, 0, 0, 0, 33, 189, 1, 0, 0, 0, 35, 196, 1, 0, 0, 0, 37, 198, 1, 0, 0, 0, 39, 200, 1, 0, 0, 0, 41, 202, 1, 0, 0, 0, 43, 204, 1, 0, 0, 0, 45, 206, 1, 0, 0, 0, 47, 208, 1, 0, 0, 0, 49, 210, 1, 0, 0, 0, 51, 212, 1, 0, 0, 0, 53, 214, 1, 0, 0, 0, 55, 216, 1, 0, 0, 0, 57, 218, 1, 0, 0, 0, 59, 220, 1, 0, 0, 0, 61, 222, 1, 0, 0, 0, 63, 224, 1, 0, 0, 0, 65, 226, 1, 0, 0, 0, 67, 228, 1, 0, 0, 0, 69, 230, 1, 0, 0, 0, 71, 232, 1, 0, 0, 0, 73, 235, 1, 0, 0, 0, 75, 241, 1, 0, 0, 0, 77, 255, 1, 0, 0, 0, 79, 267, 1, 0, 0, 0, 81, 271, 1, 0, 0, 0, 83, 276, 1, 0, 0, 0, 85, 282, 1, 0, 0, 0, 87, 287, 1, 0, 0, 0, 89, 292, 1, 0, 0, 0, 91, 299, 1, 0, 0, 0, 93, 302, 1, 0, 0, 0, 95, 96, 5, 99, 0, 0, 96, 97, 5, 108, 0, 0, 97, 98, 5, 97, 0, 0, 98, 99, 5, 115, 0, 0, 99, 100, 5, 115, 0, 0, 100, 2, 1, 0, 0, 0, 101, 102, 5, 99, 0, 0, 102, 103, 5, 111, 0, 0, 103, 104, 5, 110, 0, 0, 104, 105, 5, 115, 0, 0, 105, 106, 5, 116, 0, 0, 106, 107, 5, 114, 0, 0, 107, 108, 5, 117, 0, 0, 108, 109, 5, 99, 0, 0, 109, 110, 5, 116, 0, 0, 110, 111, 5, 111, 0, 0, 111, 112, 5, 114, 0, 0, 112, 4, 1, 0, 0, 0, 113, 114, 5, 102, 0, 0, 114, 115, 5, 117, 0, 0, 115, 116, 5, 110, 0, 0, 116, 117, 5, 99, 0, 0, 117, 118, 5, 116, 0, 0, 118, 119, 5, 105, 0, 0, 119, 120, 5, 111, 0, 0, 120, 121, 5, 110, 0, 0, 121, 6, 1, 0, 0, 0, 122, 123, 5, 109, 0, 0, 123, 124, 5, 101, 0, 0, 124, 125, 5, 116, 0, 0, 125, 126, 5, 104, 0, 0, 126, 127, 5, 111, 0, 0, 127, 128, 5, 100, 0, 0, 128, 8, 1, 0, 0, 0, 129, 130, 5, 102, 0, 0, 130, 131, 5, 105, 0, 0, 131, 132, 5, 101, 0, 0, 132, 133, 5, 108, 0, 0, 133, 134, 5, 100, 0, 0, 134, 10, 1, 0, 0, 0, 135, 136, 5, 115, 0, 0, 136, 137, 5, 116, 0, 0, 137, 138, 5, 97, 0, 0, 138, 139, 5, 116, 0, 0, 139, 140, 5, 105, 0, 0, 140, 141, 5, 99, 0, 0, 141, 12, 1, 0, 0, 0, 142, 143, 5, 118, 0, 0, 143, 144, 5, 97, 0, 0, 144, 145, 5, 114, 0, 0, 145, 14, 1, 0, 0, 0, 146, 147, 5, 105, 0, 0, 147, 148, 5, 110, 0, 0, 148, 149, 5, 116, 0, 0, 149, 16, 1, 0, 0, 0, 150, 151, 5, 99, 0, 0, 151, 152, 5, 104, 0, 0, 152, 153, 5, 97, 0, 0, 153, 154, 5, 114, 0, 0, 154, 18, 1, 0, 0, 0, 155, 156, 5, 98, 0, 0, 156, 157, 5, 111, 0, 0, 157, 158, 5, 111, 0, 0, 158, 159, 5, 108, 0, 0, 159, 160, 5, 101, 0, 0, 160, 161, 5, 97, 0, 0, 161, 162, 5, 110, 0, 0, 162, 20, 1, 0, 0, 0, 163, 164, 5, 118, 0, 0, 164, 165, 5, 111, 0, 0, 165, 166, 5, 105, 0, 0, 166, 167, 5, 100, 0, 0, 167, 22, 1, 0, 0, 0, 168, 169, 5, 108, 0, 0, 169, 170, 5, 101, 0, 0, 170, 171, 5, 116, 0, 0, 171, 24, 1, 0, 0, 0, 172, 173, 5, 100, 0, 0, 173, 174, 5, 111, 0, 0, 174, 26, 1, 0, 0, 0, 175, 176, 5, 105, 0, 0, 176, 177, 5, 102, 0, 0, 177, 28, 1, 0, 0, 0, 178, 179, 5, 101, 0, 0, 179, 180, 5, 108, 0, 0, 180, 181, 5, 115, 0, 0, 181, 182, 5, 101, 0, 0, 182, 30, 1, 0, 0, 0, 183, 184, 5, 119, 0, 0, 184, 185, 5, 104, 0, 0, 185, 186, 5, 105, 0, 0, 186, 187, 5, 108, 0, 0, 187, 188, 5, 101, 0, 0, 188, 32, 1, 0, 0, 0, 189, 190, 5, 114, 0, 0, 190, 191, 5, 101, 0, 0, 191, 192, 5, 116, 0, 0, 192, 193, 5, 117, 0, 0, 193, 194, 5, 114, 0, 0, 194, 195, 5, 110, 0, 0, 195, 34, 1, 0, 0, 0, 196, 197, 5, 123, 0, 0, 197, 36, 1, 0, 0, 0, 198, 199, 5, 125, 0, 0, 199, 38, 1, 0, 0, 0, 200, 201, 5, 40, 0, 0, 201, 40, 1, 0, 0, 0, 202, 203, 5, 41, 0, 0, 203, 42, 1, 0, 0, 0, 204, 205, 5, 91, 0, 0, 205, 44, 1, 0, 0, 0, 206, 207, 5, 93, 0, 0, 207, 46, 1, 0, 0, 0, 208, 209, 5, 46, 0, 0, 209, 48, 1, 0, 0, 0, 210, 211, 5, 44, 0, 0, 211, 50, 1, 0, 0, 0, 212, 213, 5, 59, 0, 0, 213, 52, 1, 0, 0, 0, 214, 215, 5, 61, 0, 0, 215, 54, 1, 0, 0, 0, 216, 217, 5, 43, 0, 0, 217, 56, 1, 0, 0, 0, 218, 219, 5, 45, 0, 0, 219, 58, 1, 0, 0, 0, 220, 221, 5, 42, 0, 0, 221, 60, 1, 0, 0, 0, 222, 223, 5, 47, 0, 0, 223, 62, 1, 0, 0, 0, 224, 225, 5, 38, 0, 0, 225, 64, 1, 0, 0, 0, 226, 227, 5, 124, 0, 0, 227, 66, 1, 0, 0, 0, 228, 229, 5, 126, 0, 0, 229, 68, 1, 0, 0, 0, 230, 231, 5, 60, 0, 0, 231, 70, 1, 0, 0, 0, 232, 233, 5, 62, 0, 0, 233, 72, 1, 0, 0, 0, 234, 236, 7, 0, 0, 0, 235, 234, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 238, 1, 0, 0, 0, 238, 239, 1, 0, 0, 0, 239, 240, 6, 36, 0, 0, 240, 74, 1, 0, 0, 0, 241, 242, 5, 47, 0, 0, 242, 243, 5, 42, 0, 0, 243, 247, 1, 0, 0, 0, 244, 246, 9, 0, 0, 0, 245, 244, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 250, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 251, 5, 42, 0, 0, 251, 252, 5, 47, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 6, 37, 0, 0, 254, 76, 1, 0, 0, 0, 255, 256, 5, 47, 0, 0, 256, 257, 5, 47, 0, 0, 257, 261, 1, 0, 0, 0, 258, 260, 8, 1, 0, 0, 259, 258, 1, 0, 0, 0, 260, 263, 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 264, 1, 0, 0, 0, 263, 261, 1, 0, 0, 0, 264, 265, 6, 38, 0, 0, 265, 78, 1, 0, 0, 0, 266, 268, 7, 2, 0, 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 80, 1, 0, 0, 0, 271, 272, 5, 116, 0, 0, 272, 273, 5, 114, 0, 0, 273, 274, 5, 117, 0, 0, 274, 275, 5, 101, 0, 0, 275, 82, 1, 0, 0, 0, 276, 277, 5, 102, 0, 0, 277, 278, 5, 97, 0, 0, 278, 279, 5, 108, 0, 0, 279, 280, 5, 115, 0, 0, 280, 281, 5, 101, 0, 0, 281, 84, 1, 0, 0, 0, 282, 283, 5, 110, 0, 0, 283, 284, 5, 117, 0, 0, 284, 285, 5, 108, 0, 0, 285, 286, 5, 108, 0, 0, 286, 86, 1, 0, 0, 0, 287, 288, 5, 116, 0, 0, 288, 289, 5, 104, 0, 0, 289, 290, 5, 105, 0, 0, 290, 291, 5, 115, 0, 0, 291, 88, 1, 0, 0, 0, 292, 296, 7, 3, 0, 0, 293, 295, 7, 4, 0, 0, 294, 293, 1, 0, 0, 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 90, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299, 300, 3, 93, 46, 0, 300, 301, 5, 34, 0, 0, 301, 92, 1, 0, 0, 0, 302, 306, 5, 34, 0, 0, 303, 305, 8, 5, 0, 0, 304, 303, 1, 0, 0, 0, 305, 308, 1, 0, 0, 0, 306, 304, 1, 0, 0, 0, 306, 307, 1, 0, 0, 0, 307, 94, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 7, 0, 237, 247, 261, 269, 296, 306, 1, 6, 0, 0] \ No newline at end of file +[4, 0, 46, 308, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 4, 36, 234, 8, 36, 11, 36, 12, 36, 235, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 244, 8, 37, 10, 37, 12, 37, 247, 9, 37, 1, 37, 1, 37, 1, 37, 3, 37, 252, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 260, 8, 38, 10, 38, 12, 38, 263, 9, 38, 1, 38, 1, 38, 1, 39, 4, 39, 268, 8, 39, 11, 39, 12, 39, 269, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 5, 44, 295, 8, 44, 10, 44, 12, 44, 298, 9, 44, 1, 45, 1, 45, 5, 45, 302, 8, 45, 10, 45, 12, 45, 305, 9, 45, 1, 45, 1, 45, 1, 245, 0, 46, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 1, 0, 6, 3, 0, 9, 10, 12, 13, 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 10, 10, 13, 13, 34, 34, 314, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 1, 93, 1, 0, 0, 0, 3, 99, 1, 0, 0, 0, 5, 111, 1, 0, 0, 0, 7, 120, 1, 0, 0, 0, 9, 127, 1, 0, 0, 0, 11, 133, 1, 0, 0, 0, 13, 140, 1, 0, 0, 0, 15, 144, 1, 0, 0, 0, 17, 148, 1, 0, 0, 0, 19, 153, 1, 0, 0, 0, 21, 161, 1, 0, 0, 0, 23, 166, 1, 0, 0, 0, 25, 170, 1, 0, 0, 0, 27, 173, 1, 0, 0, 0, 29, 176, 1, 0, 0, 0, 31, 181, 1, 0, 0, 0, 33, 187, 1, 0, 0, 0, 35, 194, 1, 0, 0, 0, 37, 196, 1, 0, 0, 0, 39, 198, 1, 0, 0, 0, 41, 200, 1, 0, 0, 0, 43, 202, 1, 0, 0, 0, 45, 204, 1, 0, 0, 0, 47, 206, 1, 0, 0, 0, 49, 208, 1, 0, 0, 0, 51, 210, 1, 0, 0, 0, 53, 212, 1, 0, 0, 0, 55, 214, 1, 0, 0, 0, 57, 216, 1, 0, 0, 0, 59, 218, 1, 0, 0, 0, 61, 220, 1, 0, 0, 0, 63, 222, 1, 0, 0, 0, 65, 224, 1, 0, 0, 0, 67, 226, 1, 0, 0, 0, 69, 228, 1, 0, 0, 0, 71, 230, 1, 0, 0, 0, 73, 233, 1, 0, 0, 0, 75, 239, 1, 0, 0, 0, 77, 255, 1, 0, 0, 0, 79, 267, 1, 0, 0, 0, 81, 271, 1, 0, 0, 0, 83, 276, 1, 0, 0, 0, 85, 282, 1, 0, 0, 0, 87, 287, 1, 0, 0, 0, 89, 292, 1, 0, 0, 0, 91, 299, 1, 0, 0, 0, 93, 94, 5, 99, 0, 0, 94, 95, 5, 108, 0, 0, 95, 96, 5, 97, 0, 0, 96, 97, 5, 115, 0, 0, 97, 98, 5, 115, 0, 0, 98, 2, 1, 0, 0, 0, 99, 100, 5, 99, 0, 0, 100, 101, 5, 111, 0, 0, 101, 102, 5, 110, 0, 0, 102, 103, 5, 115, 0, 0, 103, 104, 5, 116, 0, 0, 104, 105, 5, 114, 0, 0, 105, 106, 5, 117, 0, 0, 106, 107, 5, 99, 0, 0, 107, 108, 5, 116, 0, 0, 108, 109, 5, 111, 0, 0, 109, 110, 5, 114, 0, 0, 110, 4, 1, 0, 0, 0, 111, 112, 5, 102, 0, 0, 112, 113, 5, 117, 0, 0, 113, 114, 5, 110, 0, 0, 114, 115, 5, 99, 0, 0, 115, 116, 5, 116, 0, 0, 116, 117, 5, 105, 0, 0, 117, 118, 5, 111, 0, 0, 118, 119, 5, 110, 0, 0, 119, 6, 1, 0, 0, 0, 120, 121, 5, 109, 0, 0, 121, 122, 5, 101, 0, 0, 122, 123, 5, 116, 0, 0, 123, 124, 5, 104, 0, 0, 124, 125, 5, 111, 0, 0, 125, 126, 5, 100, 0, 0, 126, 8, 1, 0, 0, 0, 127, 128, 5, 102, 0, 0, 128, 129, 5, 105, 0, 0, 129, 130, 5, 101, 0, 0, 130, 131, 5, 108, 0, 0, 131, 132, 5, 100, 0, 0, 132, 10, 1, 0, 0, 0, 133, 134, 5, 115, 0, 0, 134, 135, 5, 116, 0, 0, 135, 136, 5, 97, 0, 0, 136, 137, 5, 116, 0, 0, 137, 138, 5, 105, 0, 0, 138, 139, 5, 99, 0, 0, 139, 12, 1, 0, 0, 0, 140, 141, 5, 118, 0, 0, 141, 142, 5, 97, 0, 0, 142, 143, 5, 114, 0, 0, 143, 14, 1, 0, 0, 0, 144, 145, 5, 105, 0, 0, 145, 146, 5, 110, 0, 0, 146, 147, 5, 116, 0, 0, 147, 16, 1, 0, 0, 0, 148, 149, 5, 99, 0, 0, 149, 150, 5, 104, 0, 0, 150, 151, 5, 97, 0, 0, 151, 152, 5, 114, 0, 0, 152, 18, 1, 0, 0, 0, 153, 154, 5, 98, 0, 0, 154, 155, 5, 111, 0, 0, 155, 156, 5, 111, 0, 0, 156, 157, 5, 108, 0, 0, 157, 158, 5, 101, 0, 0, 158, 159, 5, 97, 0, 0, 159, 160, 5, 110, 0, 0, 160, 20, 1, 0, 0, 0, 161, 162, 5, 118, 0, 0, 162, 163, 5, 111, 0, 0, 163, 164, 5, 105, 0, 0, 164, 165, 5, 100, 0, 0, 165, 22, 1, 0, 0, 0, 166, 167, 5, 108, 0, 0, 167, 168, 5, 101, 0, 0, 168, 169, 5, 116, 0, 0, 169, 24, 1, 0, 0, 0, 170, 171, 5, 100, 0, 0, 171, 172, 5, 111, 0, 0, 172, 26, 1, 0, 0, 0, 173, 174, 5, 105, 0, 0, 174, 175, 5, 102, 0, 0, 175, 28, 1, 0, 0, 0, 176, 177, 5, 101, 0, 0, 177, 178, 5, 108, 0, 0, 178, 179, 5, 115, 0, 0, 179, 180, 5, 101, 0, 0, 180, 30, 1, 0, 0, 0, 181, 182, 5, 119, 0, 0, 182, 183, 5, 104, 0, 0, 183, 184, 5, 105, 0, 0, 184, 185, 5, 108, 0, 0, 185, 186, 5, 101, 0, 0, 186, 32, 1, 0, 0, 0, 187, 188, 5, 114, 0, 0, 188, 189, 5, 101, 0, 0, 189, 190, 5, 116, 0, 0, 190, 191, 5, 117, 0, 0, 191, 192, 5, 114, 0, 0, 192, 193, 5, 110, 0, 0, 193, 34, 1, 0, 0, 0, 194, 195, 5, 123, 0, 0, 195, 36, 1, 0, 0, 0, 196, 197, 5, 125, 0, 0, 197, 38, 1, 0, 0, 0, 198, 199, 5, 40, 0, 0, 199, 40, 1, 0, 0, 0, 200, 201, 5, 41, 0, 0, 201, 42, 1, 0, 0, 0, 202, 203, 5, 91, 0, 0, 203, 44, 1, 0, 0, 0, 204, 205, 5, 93, 0, 0, 205, 46, 1, 0, 0, 0, 206, 207, 5, 46, 0, 0, 207, 48, 1, 0, 0, 0, 208, 209, 5, 44, 0, 0, 209, 50, 1, 0, 0, 0, 210, 211, 5, 59, 0, 0, 211, 52, 1, 0, 0, 0, 212, 213, 5, 61, 0, 0, 213, 54, 1, 0, 0, 0, 214, 215, 5, 43, 0, 0, 215, 56, 1, 0, 0, 0, 216, 217, 5, 45, 0, 0, 217, 58, 1, 0, 0, 0, 218, 219, 5, 42, 0, 0, 219, 60, 1, 0, 0, 0, 220, 221, 5, 47, 0, 0, 221, 62, 1, 0, 0, 0, 222, 223, 5, 38, 0, 0, 223, 64, 1, 0, 0, 0, 224, 225, 5, 124, 0, 0, 225, 66, 1, 0, 0, 0, 226, 227, 5, 126, 0, 0, 227, 68, 1, 0, 0, 0, 228, 229, 5, 60, 0, 0, 229, 70, 1, 0, 0, 0, 230, 231, 5, 62, 0, 0, 231, 72, 1, 0, 0, 0, 232, 234, 7, 0, 0, 0, 233, 232, 1, 0, 0, 0, 234, 235, 1, 0, 0, 0, 235, 233, 1, 0, 0, 0, 235, 236, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, 6, 36, 0, 0, 238, 74, 1, 0, 0, 0, 239, 240, 5, 47, 0, 0, 240, 241, 5, 42, 0, 0, 241, 245, 1, 0, 0, 0, 242, 244, 9, 0, 0, 0, 243, 242, 1, 0, 0, 0, 244, 247, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 246, 251, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 249, 5, 42, 0, 0, 249, 252, 5, 47, 0, 0, 250, 252, 5, 0, 0, 1, 251, 248, 1, 0, 0, 0, 251, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 6, 37, 0, 0, 254, 76, 1, 0, 0, 0, 255, 256, 5, 47, 0, 0, 256, 257, 5, 47, 0, 0, 257, 261, 1, 0, 0, 0, 258, 260, 8, 1, 0, 0, 259, 258, 1, 0, 0, 0, 260, 263, 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 264, 1, 0, 0, 0, 263, 261, 1, 0, 0, 0, 264, 265, 6, 38, 0, 0, 265, 78, 1, 0, 0, 0, 266, 268, 7, 2, 0, 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 80, 1, 0, 0, 0, 271, 272, 5, 116, 0, 0, 272, 273, 5, 114, 0, 0, 273, 274, 5, 117, 0, 0, 274, 275, 5, 101, 0, 0, 275, 82, 1, 0, 0, 0, 276, 277, 5, 102, 0, 0, 277, 278, 5, 97, 0, 0, 278, 279, 5, 108, 0, 0, 279, 280, 5, 115, 0, 0, 280, 281, 5, 101, 0, 0, 281, 84, 1, 0, 0, 0, 282, 283, 5, 110, 0, 0, 283, 284, 5, 117, 0, 0, 284, 285, 5, 108, 0, 0, 285, 286, 5, 108, 0, 0, 286, 86, 1, 0, 0, 0, 287, 288, 5, 116, 0, 0, 288, 289, 5, 104, 0, 0, 289, 290, 5, 105, 0, 0, 290, 291, 5, 115, 0, 0, 291, 88, 1, 0, 0, 0, 292, 296, 7, 3, 0, 0, 293, 295, 7, 4, 0, 0, 294, 293, 1, 0, 0, 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 90, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299, 303, 5, 34, 0, 0, 300, 302, 8, 5, 0, 0, 301, 300, 1, 0, 0, 0, 302, 305, 1, 0, 0, 0, 303, 301, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 306, 1, 0, 0, 0, 305, 303, 1, 0, 0, 0, 306, 307, 5, 34, 0, 0, 307, 92, 1, 0, 0, 0, 8, 0, 235, 245, 251, 261, 269, 296, 303, 1, 0, 1, 0] \ No newline at end of file diff --git a/simulator/src/jack/generated/JackLexer.tokens b/simulator/src/jack/generated/JackLexer.tokens index 225dc556..7a0969b6 100644 --- a/simulator/src/jack/generated/JackLexer.tokens +++ b/simulator/src/jack/generated/JackLexer.tokens @@ -34,8 +34,8 @@ OR=33 TILDE=34 LESS_THAN=35 GREATER_THAN=36 -WS=37 -COMMENT=38 +WHITESPACE=37 +BLOCK_COMMENT=38 LINE_COMMENT=39 INTEGER_LITERAL=40 TRUE=41 @@ -44,7 +44,6 @@ NULL_LITERAL=43 THIS_LITERAL=44 IDENTIFIER=45 STRING_LITERAL=46 -UnterminatedStringLiteral=47 'class'=1 'constructor'=2 'function'=3 diff --git a/simulator/src/jack/generated/JackLexer.ts b/simulator/src/jack/generated/JackLexer.ts index c5a8dc22..20e4ea64 100644 --- a/simulator/src/jack/generated/JackLexer.ts +++ b/simulator/src/jack/generated/JackLexer.ts @@ -1,398 +1,260 @@ // Generated from JackLexer.g4 by ANTLR 4.13.2 // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { - ATN, - ATNDeserializer, - CharStream, - DecisionState, - DFA, - Lexer, - LexerATNSimulator, - PredictionContextCache, - Token, + ATN, + ATNDeserializer, + CharStream, + DecisionState, DFA, + Lexer, + LexerATNSimulator, + RuleContext, + PredictionContextCache, + Token } from "antlr4"; export default class JackLexer extends Lexer { - public static readonly CLASS = 1; - public static readonly CONSTRUCTOR = 2; - public static readonly FUNCTION = 3; - public static readonly METHOD = 4; - public static readonly FIELD = 5; - public static readonly STATIC = 6; - public static readonly VAR = 7; - public static readonly INT = 8; - public static readonly CHAR = 9; - public static readonly BOOLEAN = 10; - public static readonly VOID = 11; - public static readonly LET = 12; - public static readonly DO = 13; - public static readonly IF = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly RETURN = 17; - public static readonly LBRACE = 18; - public static readonly RBRACE = 19; - public static readonly LPAREN = 20; - public static readonly RPAREN = 21; - public static readonly LBRACKET = 22; - public static readonly RBRACKET = 23; - public static readonly DOT = 24; - public static readonly COMMA = 25; - public static readonly SEMICOLON = 26; - public static readonly EQUALS = 27; - public static readonly PLUS = 28; - public static readonly MINUS = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly AND = 32; - public static readonly OR = 33; - public static readonly TILDE = 34; - public static readonly LESS_THAN = 35; - public static readonly GREATER_THAN = 36; - public static readonly WS = 37; - public static readonly COMMENT = 38; - public static readonly LINE_COMMENT = 39; - public static readonly INTEGER_LITERAL = 40; - public static readonly TRUE = 41; - public static readonly FALSE = 42; - public static readonly NULL_LITERAL = 43; - public static readonly THIS_LITERAL = 44; - public static readonly IDENTIFIER = 45; - public static readonly STRING_LITERAL = 46; - public static readonly UnterminatedStringLiteral = 47; - public static readonly EOF = Token.EOF; + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WHITESPACE = 37; + public static readonly BLOCK_COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly TRUE = 41; + public static readonly FALSE = 42; + public static readonly NULL_LITERAL = 43; + public static readonly THIS_LITERAL = 44; + public static readonly IDENTIFIER = 45; + public static readonly STRING_LITERAL = 46; + public static readonly EOF = Token.EOF; - public static readonly channelNames: string[] = [ - "DEFAULT_TOKEN_CHANNEL", - "HIDDEN", - ]; - public static readonly literalNames: (string | null)[] = [ - null, - "'class'", - "'constructor'", - "'function'", - "'method'", - "'field'", - "'static'", - "'var'", - "'int'", - "'char'", - "'boolean'", - "'void'", - "'let'", - "'do'", - "'if'", - "'else'", - "'while'", - "'return'", - "'{'", - "'}'", - "'('", - "')'", - "'['", - "']'", - "'.'", - "','", - "';'", - "'='", - "'+'", - "'-'", - "'*'", - "'/'", - "'&'", - "'|'", - "'~'", - "'<'", - "'>'", - null, - null, - null, - null, - "'true'", - "'false'", - "'null'", - "'this'", - ]; - public static readonly symbolicNames: (string | null)[] = [ - null, - "CLASS", - "CONSTRUCTOR", - "FUNCTION", - "METHOD", - "FIELD", - "STATIC", - "VAR", - "INT", - "CHAR", - "BOOLEAN", - "VOID", - "LET", - "DO", - "IF", - "ELSE", - "WHILE", - "RETURN", - "LBRACE", - "RBRACE", - "LPAREN", - "RPAREN", - "LBRACKET", - "RBRACKET", - "DOT", - "COMMA", - "SEMICOLON", - "EQUALS", - "PLUS", - "MINUS", - "MUL", - "DIV", - "AND", - "OR", - "TILDE", - "LESS_THAN", - "GREATER_THAN", - "WS", - "COMMENT", - "LINE_COMMENT", - "INTEGER_LITERAL", - "TRUE", - "FALSE", - "NULL_LITERAL", - "THIS_LITERAL", - "IDENTIFIER", - "STRING_LITERAL", - "UnterminatedStringLiteral", - ]; - public static readonly modeNames: string[] = ["DEFAULT_MODE"]; + public static readonly channelNames: string[] = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ]; + public static readonly literalNames: (string | null)[] = [ null, "'class'", + "'constructor'", + "'function'", + "'method'", + "'field'", "'static'", + "'var'", "'int'", + "'char'", "'boolean'", + "'void'", "'let'", + "'do'", "'if'", + "'else'", "'while'", + "'return'", + "'{'", "'}'", + "'('", "')'", + "'['", "']'", + "'.'", "','", + "';'", "'='", + "'+'", "'-'", + "'*'", "'/'", + "'&'", "'|'", + "'~'", "'<'", + "'>'", null, + null, null, + null, "'true'", + "'false'", "'null'", + "'this'" ]; + public static readonly symbolicNames: (string | null)[] = [ null, "CLASS", + "CONSTRUCTOR", + "FUNCTION", + "METHOD", "FIELD", + "STATIC", "VAR", + "INT", "CHAR", + "BOOLEAN", + "VOID", "LET", + "DO", "IF", + "ELSE", "WHILE", + "RETURN", "LBRACE", + "RBRACE", "LPAREN", + "RPAREN", "LBRACKET", + "RBRACKET", + "DOT", "COMMA", + "SEMICOLON", + "EQUALS", "PLUS", + "MINUS", "MUL", + "DIV", "AND", + "OR", "TILDE", + "LESS_THAN", + "GREATER_THAN", + "WHITESPACE", + "BLOCK_COMMENT", + "LINE_COMMENT", + "INTEGER_LITERAL", + "TRUE", "FALSE", + "NULL_LITERAL", + "THIS_LITERAL", + "IDENTIFIER", + "STRING_LITERAL" ]; + public static readonly modeNames: string[] = [ "DEFAULT_MODE", ]; - public static readonly ruleNames: string[] = [ - "CLASS", - "CONSTRUCTOR", - "FUNCTION", - "METHOD", - "FIELD", - "STATIC", - "VAR", - "INT", - "CHAR", - "BOOLEAN", - "VOID", - "LET", - "DO", - "IF", - "ELSE", - "WHILE", - "RETURN", - "LBRACE", - "RBRACE", - "LPAREN", - "RPAREN", - "LBRACKET", - "RBRACKET", - "DOT", - "COMMA", - "SEMICOLON", - "EQUALS", - "PLUS", - "MINUS", - "MUL", - "DIV", - "AND", - "OR", - "TILDE", - "LESS_THAN", - "GREATER_THAN", - "WS", - "COMMENT", - "LINE_COMMENT", - "INTEGER_LITERAL", - "TRUE", - "FALSE", - "NULL_LITERAL", - "THIS_LITERAL", - "IDENTIFIER", - "STRING_LITERAL", - "UnterminatedStringLiteral", - ]; + public static readonly ruleNames: string[] = [ + "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", "VAR", + "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", + "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", + "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", + "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WHITESPACE", "BLOCK_COMMENT", + "LINE_COMMENT", "INTEGER_LITERAL", "TRUE", "FALSE", "NULL_LITERAL", "THIS_LITERAL", + "IDENTIFIER", "STRING_LITERAL", + ]; - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator( - this, - JackLexer._ATN, - JackLexer.DecisionsToDFA, - new PredictionContextCache(), - ); - } - public get grammarFileName(): string { - return "JackLexer.g4"; - } + constructor(input: CharStream) { + super(input); + this._interp = new LexerATNSimulator(this, JackLexer._ATN, JackLexer.DecisionsToDFA, new PredictionContextCache()); + } - public get literalNames(): (string | null)[] { - return JackLexer.literalNames; - } - public get symbolicNames(): (string | null)[] { - return JackLexer.symbolicNames; - } - public get ruleNames(): string[] { - return JackLexer.ruleNames; - } + public get grammarFileName(): string { return "JackLexer.g4"; } - public get serializedATN(): number[] { - return JackLexer._serializedATN; - } + public get literalNames(): (string | null)[] { return JackLexer.literalNames; } + public get symbolicNames(): (string | null)[] { return JackLexer.symbolicNames; } + public get ruleNames(): string[] { return JackLexer.ruleNames; } - public get channelNames(): string[] { - return JackLexer.channelNames; - } + public get serializedATN(): number[] { return JackLexer._serializedATN; } - public get modeNames(): string[] { - return JackLexer.modeNames; - } + public get channelNames(): string[] { return JackLexer.channelNames; } - public static readonly _serializedATN: number[] = [ - 4, 0, 47, 309, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, - 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, - 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, - 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, - 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, - 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, - 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, - 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, - 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, - 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, - 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, - 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, - 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, - 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, - 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, - 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, - 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, - 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, - 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 4, 36, 236, 8, 36, 11, 36, 12, - 36, 237, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 246, 8, 37, 10, - 37, 12, 37, 249, 9, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, - 38, 1, 38, 5, 38, 260, 8, 38, 10, 38, 12, 38, 263, 9, 38, 1, 38, 1, 38, 1, - 39, 4, 39, 268, 8, 39, 11, 39, 12, 39, 269, 1, 40, 1, 40, 1, 40, 1, 40, 1, - 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, - 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 5, 44, 295, 8, 44, 10, - 44, 12, 44, 298, 9, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 5, 46, 305, 8, - 46, 10, 46, 12, 46, 308, 9, 46, 1, 247, 0, 47, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, - 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, - 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, - 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, - 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, - 44, 89, 45, 91, 46, 93, 47, 1, 0, 6, 3, 0, 9, 10, 13, 13, 32, 32, 2, 0, 10, - 10, 13, 13, 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, - 90, 95, 95, 97, 122, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 314, 0, 1, 1, 0, - 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, - 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, - 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, - 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, - 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, - 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, - 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, - 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, - 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, - 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, - 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, - 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 1, 95, 1, 0, 0, 0, 3, 101, 1, 0, 0, - 0, 5, 113, 1, 0, 0, 0, 7, 122, 1, 0, 0, 0, 9, 129, 1, 0, 0, 0, 11, 135, 1, - 0, 0, 0, 13, 142, 1, 0, 0, 0, 15, 146, 1, 0, 0, 0, 17, 150, 1, 0, 0, 0, 19, - 155, 1, 0, 0, 0, 21, 163, 1, 0, 0, 0, 23, 168, 1, 0, 0, 0, 25, 172, 1, 0, 0, - 0, 27, 175, 1, 0, 0, 0, 29, 178, 1, 0, 0, 0, 31, 183, 1, 0, 0, 0, 33, 189, - 1, 0, 0, 0, 35, 196, 1, 0, 0, 0, 37, 198, 1, 0, 0, 0, 39, 200, 1, 0, 0, 0, - 41, 202, 1, 0, 0, 0, 43, 204, 1, 0, 0, 0, 45, 206, 1, 0, 0, 0, 47, 208, 1, - 0, 0, 0, 49, 210, 1, 0, 0, 0, 51, 212, 1, 0, 0, 0, 53, 214, 1, 0, 0, 0, 55, - 216, 1, 0, 0, 0, 57, 218, 1, 0, 0, 0, 59, 220, 1, 0, 0, 0, 61, 222, 1, 0, 0, - 0, 63, 224, 1, 0, 0, 0, 65, 226, 1, 0, 0, 0, 67, 228, 1, 0, 0, 0, 69, 230, - 1, 0, 0, 0, 71, 232, 1, 0, 0, 0, 73, 235, 1, 0, 0, 0, 75, 241, 1, 0, 0, 0, - 77, 255, 1, 0, 0, 0, 79, 267, 1, 0, 0, 0, 81, 271, 1, 0, 0, 0, 83, 276, 1, - 0, 0, 0, 85, 282, 1, 0, 0, 0, 87, 287, 1, 0, 0, 0, 89, 292, 1, 0, 0, 0, 91, - 299, 1, 0, 0, 0, 93, 302, 1, 0, 0, 0, 95, 96, 5, 99, 0, 0, 96, 97, 5, 108, - 0, 0, 97, 98, 5, 97, 0, 0, 98, 99, 5, 115, 0, 0, 99, 100, 5, 115, 0, 0, 100, - 2, 1, 0, 0, 0, 101, 102, 5, 99, 0, 0, 102, 103, 5, 111, 0, 0, 103, 104, 5, - 110, 0, 0, 104, 105, 5, 115, 0, 0, 105, 106, 5, 116, 0, 0, 106, 107, 5, 114, - 0, 0, 107, 108, 5, 117, 0, 0, 108, 109, 5, 99, 0, 0, 109, 110, 5, 116, 0, 0, - 110, 111, 5, 111, 0, 0, 111, 112, 5, 114, 0, 0, 112, 4, 1, 0, 0, 0, 113, - 114, 5, 102, 0, 0, 114, 115, 5, 117, 0, 0, 115, 116, 5, 110, 0, 0, 116, 117, - 5, 99, 0, 0, 117, 118, 5, 116, 0, 0, 118, 119, 5, 105, 0, 0, 119, 120, 5, - 111, 0, 0, 120, 121, 5, 110, 0, 0, 121, 6, 1, 0, 0, 0, 122, 123, 5, 109, 0, - 0, 123, 124, 5, 101, 0, 0, 124, 125, 5, 116, 0, 0, 125, 126, 5, 104, 0, 0, - 126, 127, 5, 111, 0, 0, 127, 128, 5, 100, 0, 0, 128, 8, 1, 0, 0, 0, 129, - 130, 5, 102, 0, 0, 130, 131, 5, 105, 0, 0, 131, 132, 5, 101, 0, 0, 132, 133, - 5, 108, 0, 0, 133, 134, 5, 100, 0, 0, 134, 10, 1, 0, 0, 0, 135, 136, 5, 115, - 0, 0, 136, 137, 5, 116, 0, 0, 137, 138, 5, 97, 0, 0, 138, 139, 5, 116, 0, 0, - 139, 140, 5, 105, 0, 0, 140, 141, 5, 99, 0, 0, 141, 12, 1, 0, 0, 0, 142, - 143, 5, 118, 0, 0, 143, 144, 5, 97, 0, 0, 144, 145, 5, 114, 0, 0, 145, 14, - 1, 0, 0, 0, 146, 147, 5, 105, 0, 0, 147, 148, 5, 110, 0, 0, 148, 149, 5, - 116, 0, 0, 149, 16, 1, 0, 0, 0, 150, 151, 5, 99, 0, 0, 151, 152, 5, 104, 0, - 0, 152, 153, 5, 97, 0, 0, 153, 154, 5, 114, 0, 0, 154, 18, 1, 0, 0, 0, 155, - 156, 5, 98, 0, 0, 156, 157, 5, 111, 0, 0, 157, 158, 5, 111, 0, 0, 158, 159, - 5, 108, 0, 0, 159, 160, 5, 101, 0, 0, 160, 161, 5, 97, 0, 0, 161, 162, 5, - 110, 0, 0, 162, 20, 1, 0, 0, 0, 163, 164, 5, 118, 0, 0, 164, 165, 5, 111, 0, - 0, 165, 166, 5, 105, 0, 0, 166, 167, 5, 100, 0, 0, 167, 22, 1, 0, 0, 0, 168, - 169, 5, 108, 0, 0, 169, 170, 5, 101, 0, 0, 170, 171, 5, 116, 0, 0, 171, 24, - 1, 0, 0, 0, 172, 173, 5, 100, 0, 0, 173, 174, 5, 111, 0, 0, 174, 26, 1, 0, - 0, 0, 175, 176, 5, 105, 0, 0, 176, 177, 5, 102, 0, 0, 177, 28, 1, 0, 0, 0, - 178, 179, 5, 101, 0, 0, 179, 180, 5, 108, 0, 0, 180, 181, 5, 115, 0, 0, 181, - 182, 5, 101, 0, 0, 182, 30, 1, 0, 0, 0, 183, 184, 5, 119, 0, 0, 184, 185, 5, - 104, 0, 0, 185, 186, 5, 105, 0, 0, 186, 187, 5, 108, 0, 0, 187, 188, 5, 101, - 0, 0, 188, 32, 1, 0, 0, 0, 189, 190, 5, 114, 0, 0, 190, 191, 5, 101, 0, 0, - 191, 192, 5, 116, 0, 0, 192, 193, 5, 117, 0, 0, 193, 194, 5, 114, 0, 0, 194, - 195, 5, 110, 0, 0, 195, 34, 1, 0, 0, 0, 196, 197, 5, 123, 0, 0, 197, 36, 1, - 0, 0, 0, 198, 199, 5, 125, 0, 0, 199, 38, 1, 0, 0, 0, 200, 201, 5, 40, 0, 0, - 201, 40, 1, 0, 0, 0, 202, 203, 5, 41, 0, 0, 203, 42, 1, 0, 0, 0, 204, 205, - 5, 91, 0, 0, 205, 44, 1, 0, 0, 0, 206, 207, 5, 93, 0, 0, 207, 46, 1, 0, 0, - 0, 208, 209, 5, 46, 0, 0, 209, 48, 1, 0, 0, 0, 210, 211, 5, 44, 0, 0, 211, - 50, 1, 0, 0, 0, 212, 213, 5, 59, 0, 0, 213, 52, 1, 0, 0, 0, 214, 215, 5, 61, - 0, 0, 215, 54, 1, 0, 0, 0, 216, 217, 5, 43, 0, 0, 217, 56, 1, 0, 0, 0, 218, - 219, 5, 45, 0, 0, 219, 58, 1, 0, 0, 0, 220, 221, 5, 42, 0, 0, 221, 60, 1, 0, - 0, 0, 222, 223, 5, 47, 0, 0, 223, 62, 1, 0, 0, 0, 224, 225, 5, 38, 0, 0, - 225, 64, 1, 0, 0, 0, 226, 227, 5, 124, 0, 0, 227, 66, 1, 0, 0, 0, 228, 229, - 5, 126, 0, 0, 229, 68, 1, 0, 0, 0, 230, 231, 5, 60, 0, 0, 231, 70, 1, 0, 0, - 0, 232, 233, 5, 62, 0, 0, 233, 72, 1, 0, 0, 0, 234, 236, 7, 0, 0, 0, 235, - 234, 1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 238, 1, 0, - 0, 0, 238, 239, 1, 0, 0, 0, 239, 240, 6, 36, 0, 0, 240, 74, 1, 0, 0, 0, 241, - 242, 5, 47, 0, 0, 242, 243, 5, 42, 0, 0, 243, 247, 1, 0, 0, 0, 244, 246, 9, - 0, 0, 0, 245, 244, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, - 247, 245, 1, 0, 0, 0, 248, 250, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 251, - 5, 42, 0, 0, 251, 252, 5, 47, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 6, 37, - 0, 0, 254, 76, 1, 0, 0, 0, 255, 256, 5, 47, 0, 0, 256, 257, 5, 47, 0, 0, - 257, 261, 1, 0, 0, 0, 258, 260, 8, 1, 0, 0, 259, 258, 1, 0, 0, 0, 260, 263, - 1, 0, 0, 0, 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 264, 1, 0, 0, - 0, 263, 261, 1, 0, 0, 0, 264, 265, 6, 38, 0, 0, 265, 78, 1, 0, 0, 0, 266, - 268, 7, 2, 0, 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 267, 1, 0, - 0, 0, 269, 270, 1, 0, 0, 0, 270, 80, 1, 0, 0, 0, 271, 272, 5, 116, 0, 0, - 272, 273, 5, 114, 0, 0, 273, 274, 5, 117, 0, 0, 274, 275, 5, 101, 0, 0, 275, - 82, 1, 0, 0, 0, 276, 277, 5, 102, 0, 0, 277, 278, 5, 97, 0, 0, 278, 279, 5, - 108, 0, 0, 279, 280, 5, 115, 0, 0, 280, 281, 5, 101, 0, 0, 281, 84, 1, 0, 0, - 0, 282, 283, 5, 110, 0, 0, 283, 284, 5, 117, 0, 0, 284, 285, 5, 108, 0, 0, - 285, 286, 5, 108, 0, 0, 286, 86, 1, 0, 0, 0, 287, 288, 5, 116, 0, 0, 288, - 289, 5, 104, 0, 0, 289, 290, 5, 105, 0, 0, 290, 291, 5, 115, 0, 0, 291, 88, - 1, 0, 0, 0, 292, 296, 7, 3, 0, 0, 293, 295, 7, 4, 0, 0, 294, 293, 1, 0, 0, - 0, 295, 298, 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, - 90, 1, 0, 0, 0, 298, 296, 1, 0, 0, 0, 299, 300, 3, 93, 46, 0, 300, 301, 5, - 34, 0, 0, 301, 92, 1, 0, 0, 0, 302, 306, 5, 34, 0, 0, 303, 305, 8, 5, 0, 0, - 304, 303, 1, 0, 0, 0, 305, 308, 1, 0, 0, 0, 306, 304, 1, 0, 0, 0, 306, 307, - 1, 0, 0, 0, 307, 94, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 7, 0, 237, 247, 261, - 269, 296, 306, 1, 6, 0, 0, - ]; + public get modeNames(): string[] { return JackLexer.modeNames; } - private static __ATN: ATN; - public static get _ATN(): ATN { - if (!JackLexer.__ATN) { - JackLexer.__ATN = new ATNDeserializer().deserialize( - JackLexer._serializedATN, - ); - } + public static readonly _serializedATN: number[] = [4,0,46,308,6,-1,2,0, + 7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9, + 7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7, + 16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23, + 2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2, + 31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38, + 7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7, + 45,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,4, + 1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,7,1,7, + 1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1, + 10,1,10,1,10,1,11,1,11,1,11,1,11,1,12,1,12,1,12,1,13,1,13,1,13,1,14,1,14, + 1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,16,1,16,1,16,1,16,1,16,1, + 16,1,16,1,17,1,17,1,18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23, + 1,23,1,24,1,24,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,1, + 30,1,31,1,31,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,36,4,36,234,8,36, + 11,36,12,36,235,1,36,1,36,1,37,1,37,1,37,1,37,5,37,244,8,37,10,37,12,37, + 247,9,37,1,37,1,37,1,37,3,37,252,8,37,1,37,1,37,1,38,1,38,1,38,1,38,5,38, + 260,8,38,10,38,12,38,263,9,38,1,38,1,38,1,39,4,39,268,8,39,11,39,12,39, + 269,1,40,1,40,1,40,1,40,1,40,1,41,1,41,1,41,1,41,1,41,1,41,1,42,1,42,1, + 42,1,42,1,42,1,43,1,43,1,43,1,43,1,43,1,44,1,44,5,44,295,8,44,10,44,12, + 44,298,9,44,1,45,1,45,5,45,302,8,45,10,45,12,45,305,9,45,1,45,1,45,1,245, + 0,46,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27, + 14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51, + 26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,71,36,73,37,75, + 38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,46,1,0,6,3,0,9,10,12,13, + 32,32,2,0,10,10,13,13,1,0,48,57,3,0,65,90,95,95,97,122,4,0,48,57,65,90, + 95,95,97,122,3,0,10,10,13,13,34,34,314,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0, + 0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17, + 1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0, + 0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39, + 1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0, + 0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61, + 1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0, + 0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83, + 1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,1,93,1,0,0, + 0,3,99,1,0,0,0,5,111,1,0,0,0,7,120,1,0,0,0,9,127,1,0,0,0,11,133,1,0,0,0, + 13,140,1,0,0,0,15,144,1,0,0,0,17,148,1,0,0,0,19,153,1,0,0,0,21,161,1,0, + 0,0,23,166,1,0,0,0,25,170,1,0,0,0,27,173,1,0,0,0,29,176,1,0,0,0,31,181, + 1,0,0,0,33,187,1,0,0,0,35,194,1,0,0,0,37,196,1,0,0,0,39,198,1,0,0,0,41, + 200,1,0,0,0,43,202,1,0,0,0,45,204,1,0,0,0,47,206,1,0,0,0,49,208,1,0,0,0, + 51,210,1,0,0,0,53,212,1,0,0,0,55,214,1,0,0,0,57,216,1,0,0,0,59,218,1,0, + 0,0,61,220,1,0,0,0,63,222,1,0,0,0,65,224,1,0,0,0,67,226,1,0,0,0,69,228, + 1,0,0,0,71,230,1,0,0,0,73,233,1,0,0,0,75,239,1,0,0,0,77,255,1,0,0,0,79, + 267,1,0,0,0,81,271,1,0,0,0,83,276,1,0,0,0,85,282,1,0,0,0,87,287,1,0,0,0, + 89,292,1,0,0,0,91,299,1,0,0,0,93,94,5,99,0,0,94,95,5,108,0,0,95,96,5,97, + 0,0,96,97,5,115,0,0,97,98,5,115,0,0,98,2,1,0,0,0,99,100,5,99,0,0,100,101, + 5,111,0,0,101,102,5,110,0,0,102,103,5,115,0,0,103,104,5,116,0,0,104,105, + 5,114,0,0,105,106,5,117,0,0,106,107,5,99,0,0,107,108,5,116,0,0,108,109, + 5,111,0,0,109,110,5,114,0,0,110,4,1,0,0,0,111,112,5,102,0,0,112,113,5,117, + 0,0,113,114,5,110,0,0,114,115,5,99,0,0,115,116,5,116,0,0,116,117,5,105, + 0,0,117,118,5,111,0,0,118,119,5,110,0,0,119,6,1,0,0,0,120,121,5,109,0,0, + 121,122,5,101,0,0,122,123,5,116,0,0,123,124,5,104,0,0,124,125,5,111,0,0, + 125,126,5,100,0,0,126,8,1,0,0,0,127,128,5,102,0,0,128,129,5,105,0,0,129, + 130,5,101,0,0,130,131,5,108,0,0,131,132,5,100,0,0,132,10,1,0,0,0,133,134, + 5,115,0,0,134,135,5,116,0,0,135,136,5,97,0,0,136,137,5,116,0,0,137,138, + 5,105,0,0,138,139,5,99,0,0,139,12,1,0,0,0,140,141,5,118,0,0,141,142,5,97, + 0,0,142,143,5,114,0,0,143,14,1,0,0,0,144,145,5,105,0,0,145,146,5,110,0, + 0,146,147,5,116,0,0,147,16,1,0,0,0,148,149,5,99,0,0,149,150,5,104,0,0,150, + 151,5,97,0,0,151,152,5,114,0,0,152,18,1,0,0,0,153,154,5,98,0,0,154,155, + 5,111,0,0,155,156,5,111,0,0,156,157,5,108,0,0,157,158,5,101,0,0,158,159, + 5,97,0,0,159,160,5,110,0,0,160,20,1,0,0,0,161,162,5,118,0,0,162,163,5,111, + 0,0,163,164,5,105,0,0,164,165,5,100,0,0,165,22,1,0,0,0,166,167,5,108,0, + 0,167,168,5,101,0,0,168,169,5,116,0,0,169,24,1,0,0,0,170,171,5,100,0,0, + 171,172,5,111,0,0,172,26,1,0,0,0,173,174,5,105,0,0,174,175,5,102,0,0,175, + 28,1,0,0,0,176,177,5,101,0,0,177,178,5,108,0,0,178,179,5,115,0,0,179,180, + 5,101,0,0,180,30,1,0,0,0,181,182,5,119,0,0,182,183,5,104,0,0,183,184,5, + 105,0,0,184,185,5,108,0,0,185,186,5,101,0,0,186,32,1,0,0,0,187,188,5,114, + 0,0,188,189,5,101,0,0,189,190,5,116,0,0,190,191,5,117,0,0,191,192,5,114, + 0,0,192,193,5,110,0,0,193,34,1,0,0,0,194,195,5,123,0,0,195,36,1,0,0,0,196, + 197,5,125,0,0,197,38,1,0,0,0,198,199,5,40,0,0,199,40,1,0,0,0,200,201,5, + 41,0,0,201,42,1,0,0,0,202,203,5,91,0,0,203,44,1,0,0,0,204,205,5,93,0,0, + 205,46,1,0,0,0,206,207,5,46,0,0,207,48,1,0,0,0,208,209,5,44,0,0,209,50, + 1,0,0,0,210,211,5,59,0,0,211,52,1,0,0,0,212,213,5,61,0,0,213,54,1,0,0,0, + 214,215,5,43,0,0,215,56,1,0,0,0,216,217,5,45,0,0,217,58,1,0,0,0,218,219, + 5,42,0,0,219,60,1,0,0,0,220,221,5,47,0,0,221,62,1,0,0,0,222,223,5,38,0, + 0,223,64,1,0,0,0,224,225,5,124,0,0,225,66,1,0,0,0,226,227,5,126,0,0,227, + 68,1,0,0,0,228,229,5,60,0,0,229,70,1,0,0,0,230,231,5,62,0,0,231,72,1,0, + 0,0,232,234,7,0,0,0,233,232,1,0,0,0,234,235,1,0,0,0,235,233,1,0,0,0,235, + 236,1,0,0,0,236,237,1,0,0,0,237,238,6,36,0,0,238,74,1,0,0,0,239,240,5,47, + 0,0,240,241,5,42,0,0,241,245,1,0,0,0,242,244,9,0,0,0,243,242,1,0,0,0,244, + 247,1,0,0,0,245,246,1,0,0,0,245,243,1,0,0,0,246,251,1,0,0,0,247,245,1,0, + 0,0,248,249,5,42,0,0,249,252,5,47,0,0,250,252,5,0,0,1,251,248,1,0,0,0,251, + 250,1,0,0,0,252,253,1,0,0,0,253,254,6,37,0,0,254,76,1,0,0,0,255,256,5,47, + 0,0,256,257,5,47,0,0,257,261,1,0,0,0,258,260,8,1,0,0,259,258,1,0,0,0,260, + 263,1,0,0,0,261,259,1,0,0,0,261,262,1,0,0,0,262,264,1,0,0,0,263,261,1,0, + 0,0,264,265,6,38,0,0,265,78,1,0,0,0,266,268,7,2,0,0,267,266,1,0,0,0,268, + 269,1,0,0,0,269,267,1,0,0,0,269,270,1,0,0,0,270,80,1,0,0,0,271,272,5,116, + 0,0,272,273,5,114,0,0,273,274,5,117,0,0,274,275,5,101,0,0,275,82,1,0,0, + 0,276,277,5,102,0,0,277,278,5,97,0,0,278,279,5,108,0,0,279,280,5,115,0, + 0,280,281,5,101,0,0,281,84,1,0,0,0,282,283,5,110,0,0,283,284,5,117,0,0, + 284,285,5,108,0,0,285,286,5,108,0,0,286,86,1,0,0,0,287,288,5,116,0,0,288, + 289,5,104,0,0,289,290,5,105,0,0,290,291,5,115,0,0,291,88,1,0,0,0,292,296, + 7,3,0,0,293,295,7,4,0,0,294,293,1,0,0,0,295,298,1,0,0,0,296,294,1,0,0,0, + 296,297,1,0,0,0,297,90,1,0,0,0,298,296,1,0,0,0,299,303,5,34,0,0,300,302, + 8,5,0,0,301,300,1,0,0,0,302,305,1,0,0,0,303,301,1,0,0,0,303,304,1,0,0,0, + 304,306,1,0,0,0,305,303,1,0,0,0,306,307,5,34,0,0,307,92,1,0,0,0,8,0,235, + 245,251,261,269,296,303,1,0,1,0]; - return JackLexer.__ATN; - } + private static __ATN: ATN; + public static get _ATN(): ATN { + if (!JackLexer.__ATN) { + JackLexer.__ATN = new ATNDeserializer().deserialize(JackLexer._serializedATN); + } - static DecisionsToDFA = JackLexer._ATN.decisionToState.map( - (ds: DecisionState, index: number) => new DFA(ds, index), - ); -} + return JackLexer.__ATN; + } + + + static DecisionsToDFA = JackLexer._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) ); +} \ No newline at end of file diff --git a/simulator/src/jack/generated/JackParser.interp b/simulator/src/jack/generated/JackParser.interp index b691bc96..6eef0a1c 100644 --- a/simulator/src/jack/generated/JackParser.interp +++ b/simulator/src/jack/generated/JackParser.interp @@ -46,7 +46,6 @@ null 'this' null null -null token symbolic names: null @@ -86,8 +85,8 @@ OR TILDE LESS_THAN GREATER_THAN -WS -COMMENT +WHITESPACE +BLOCK_COMMENT LINE_COMMENT INTEGER_LITERAL TRUE @@ -96,7 +95,6 @@ NULL_LITERAL THIS_LITERAL IDENTIFIER STRING_LITERAL -UnterminatedStringLiteral rule names: program @@ -118,7 +116,6 @@ subroutineBody rBrace varDeclaration varNameInDeclaration -varName statements statement letStatement @@ -135,14 +132,15 @@ subroutineId returnStatement expressionList expression -groupedExpression -unaryOperation -arrayAccess constant +varName +arrayAccess +unaryOperation +groupedExpression booleanLiteral unaryOperator binaryOperator atn: -[4, 1, 47, 317, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 94, 8, 1, 10, 1, 12, 1, 97, 9, 1, 1, 1, 5, 1, 100, 8, 1, 10, 1, 12, 1, 103, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 117, 8, 4, 10, 4, 12, 4, 120, 9, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 5, 12, 147, 8, 12, 10, 12, 12, 12, 150, 9, 12, 3, 12, 152, 8, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 161, 8, 15, 10, 15, 12, 15, 164, 9, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 176, 8, 17, 10, 17, 12, 17, 179, 9, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 5, 20, 188, 8, 20, 10, 20, 12, 20, 191, 9, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 198, 8, 21, 1, 22, 1, 22, 1, 22, 3, 22, 203, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 24, 1, 24, 3, 24, 213, 8, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 251, 8, 32, 1, 32, 3, 32, 254, 8, 32, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 260, 8, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 5, 34, 267, 8, 34, 10, 34, 12, 34, 270, 9, 34, 3, 34, 272, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 3, 35, 281, 8, 35, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 287, 8, 35, 10, 35, 12, 35, 290, 9, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 309, 8, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 0, 1, 70, 43, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 0, 6, 1, 0, 5, 6, 1, 0, 2, 4, 2, 0, 8, 10, 45, 45, 1, 0, 41, 42, 2, 0, 29, 29, 34, 34, 2, 0, 27, 33, 35, 36, 303, 0, 86, 1, 0, 0, 0, 2, 89, 1, 0, 0, 0, 4, 106, 1, 0, 0, 0, 6, 108, 1, 0, 0, 0, 8, 112, 1, 0, 0, 0, 10, 121, 1, 0, 0, 0, 12, 123, 1, 0, 0, 0, 14, 126, 1, 0, 0, 0, 16, 128, 1, 0, 0, 0, 18, 135, 1, 0, 0, 0, 20, 139, 1, 0, 0, 0, 22, 141, 1, 0, 0, 0, 24, 151, 1, 0, 0, 0, 26, 153, 1, 0, 0, 0, 28, 156, 1, 0, 0, 0, 30, 158, 1, 0, 0, 0, 32, 168, 1, 0, 0, 0, 34, 170, 1, 0, 0, 0, 36, 182, 1, 0, 0, 0, 38, 184, 1, 0, 0, 0, 40, 189, 1, 0, 0, 0, 42, 197, 1, 0, 0, 0, 44, 199, 1, 0, 0, 0, 46, 208, 1, 0, 0, 0, 48, 210, 1, 0, 0, 0, 50, 214, 1, 0, 0, 0, 52, 222, 1, 0, 0, 0, 54, 224, 1, 0, 0, 0, 56, 229, 1, 0, 0, 0, 58, 237, 1, 0, 0, 0, 60, 239, 1, 0, 0, 0, 62, 243, 1, 0, 0, 0, 64, 253, 1, 0, 0, 0, 66, 257, 1, 0, 0, 0, 68, 271, 1, 0, 0, 0, 70, 280, 1, 0, 0, 0, 72, 291, 1, 0, 0, 0, 74, 295, 1, 0, 0, 0, 76, 298, 1, 0, 0, 0, 78, 308, 1, 0, 0, 0, 80, 310, 1, 0, 0, 0, 82, 312, 1, 0, 0, 0, 84, 314, 1, 0, 0, 0, 86, 87, 3, 2, 1, 0, 87, 88, 5, 0, 0, 1, 88, 1, 1, 0, 0, 0, 89, 90, 5, 1, 0, 0, 90, 91, 3, 4, 2, 0, 91, 95, 5, 18, 0, 0, 92, 94, 3, 6, 3, 0, 93, 92, 1, 0, 0, 0, 94, 97, 1, 0, 0, 0, 95, 93, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 101, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 98, 100, 3, 12, 6, 0, 99, 98, 1, 0, 0, 0, 100, 103, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 101, 102, 1, 0, 0, 0, 102, 104, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 104, 105, 3, 32, 16, 0, 105, 3, 1, 0, 0, 0, 106, 107, 5, 45, 0, 0, 107, 5, 1, 0, 0, 0, 108, 109, 7, 0, 0, 0, 109, 110, 3, 8, 4, 0, 110, 111, 5, 26, 0, 0, 111, 7, 1, 0, 0, 0, 112, 113, 3, 22, 11, 0, 113, 118, 3, 10, 5, 0, 114, 115, 5, 25, 0, 0, 115, 117, 3, 10, 5, 0, 116, 114, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 9, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 121, 122, 5, 45, 0, 0, 122, 11, 1, 0, 0, 0, 123, 124, 3, 14, 7, 0, 124, 125, 3, 16, 8, 0, 125, 13, 1, 0, 0, 0, 126, 127, 7, 1, 0, 0, 127, 15, 1, 0, 0, 0, 128, 129, 3, 20, 10, 0, 129, 130, 3, 18, 9, 0, 130, 131, 5, 20, 0, 0, 131, 132, 3, 24, 12, 0, 132, 133, 5, 21, 0, 0, 133, 134, 3, 30, 15, 0, 134, 17, 1, 0, 0, 0, 135, 136, 5, 45, 0, 0, 136, 19, 1, 0, 0, 0, 137, 140, 3, 22, 11, 0, 138, 140, 5, 11, 0, 0, 139, 137, 1, 0, 0, 0, 139, 138, 1, 0, 0, 0, 140, 21, 1, 0, 0, 0, 141, 142, 7, 2, 0, 0, 142, 23, 1, 0, 0, 0, 143, 148, 3, 26, 13, 0, 144, 145, 5, 25, 0, 0, 145, 147, 3, 26, 13, 0, 146, 144, 1, 0, 0, 0, 147, 150, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 148, 149, 1, 0, 0, 0, 149, 152, 1, 0, 0, 0, 150, 148, 1, 0, 0, 0, 151, 143, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 25, 1, 0, 0, 0, 153, 154, 3, 22, 11, 0, 154, 155, 3, 28, 14, 0, 155, 27, 1, 0, 0, 0, 156, 157, 5, 45, 0, 0, 157, 29, 1, 0, 0, 0, 158, 162, 5, 18, 0, 0, 159, 161, 3, 34, 17, 0, 160, 159, 1, 0, 0, 0, 161, 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 165, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 3, 40, 20, 0, 166, 167, 3, 32, 16, 0, 167, 31, 1, 0, 0, 0, 168, 169, 5, 19, 0, 0, 169, 33, 1, 0, 0, 0, 170, 171, 5, 7, 0, 0, 171, 172, 3, 22, 11, 0, 172, 177, 3, 36, 18, 0, 173, 174, 5, 25, 0, 0, 174, 176, 3, 36, 18, 0, 175, 173, 1, 0, 0, 0, 176, 179, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 180, 1, 0, 0, 0, 179, 177, 1, 0, 0, 0, 180, 181, 5, 26, 0, 0, 181, 35, 1, 0, 0, 0, 182, 183, 5, 45, 0, 0, 183, 37, 1, 0, 0, 0, 184, 185, 5, 45, 0, 0, 185, 39, 1, 0, 0, 0, 186, 188, 3, 42, 21, 0, 187, 186, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 41, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 198, 3, 44, 22, 0, 193, 198, 3, 48, 24, 0, 194, 198, 3, 56, 28, 0, 195, 198, 3, 60, 30, 0, 196, 198, 3, 66, 33, 0, 197, 192, 1, 0, 0, 0, 197, 193, 1, 0, 0, 0, 197, 194, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 197, 196, 1, 0, 0, 0, 198, 43, 1, 0, 0, 0, 199, 202, 5, 12, 0, 0, 200, 203, 3, 38, 19, 0, 201, 203, 3, 76, 38, 0, 202, 200, 1, 0, 0, 0, 202, 201, 1, 0, 0, 0, 203, 204, 1, 0, 0, 0, 204, 205, 3, 46, 23, 0, 205, 206, 3, 70, 35, 0, 206, 207, 5, 26, 0, 0, 207, 45, 1, 0, 0, 0, 208, 209, 5, 27, 0, 0, 209, 47, 1, 0, 0, 0, 210, 212, 3, 50, 25, 0, 211, 213, 3, 54, 27, 0, 212, 211, 1, 0, 0, 0, 212, 213, 1, 0, 0, 0, 213, 49, 1, 0, 0, 0, 214, 215, 5, 14, 0, 0, 215, 216, 5, 20, 0, 0, 216, 217, 3, 52, 26, 0, 217, 218, 5, 21, 0, 0, 218, 219, 5, 18, 0, 0, 219, 220, 3, 40, 20, 0, 220, 221, 3, 32, 16, 0, 221, 51, 1, 0, 0, 0, 222, 223, 3, 70, 35, 0, 223, 53, 1, 0, 0, 0, 224, 225, 5, 15, 0, 0, 225, 226, 5, 18, 0, 0, 226, 227, 3, 40, 20, 0, 227, 228, 3, 32, 16, 0, 228, 55, 1, 0, 0, 0, 229, 230, 5, 16, 0, 0, 230, 231, 5, 20, 0, 0, 231, 232, 3, 58, 29, 0, 232, 233, 5, 21, 0, 0, 233, 234, 5, 18, 0, 0, 234, 235, 3, 40, 20, 0, 235, 236, 3, 32, 16, 0, 236, 57, 1, 0, 0, 0, 237, 238, 3, 70, 35, 0, 238, 59, 1, 0, 0, 0, 239, 240, 5, 13, 0, 0, 240, 241, 3, 62, 31, 0, 241, 242, 5, 26, 0, 0, 242, 61, 1, 0, 0, 0, 243, 244, 3, 64, 32, 0, 244, 245, 5, 20, 0, 0, 245, 246, 3, 68, 34, 0, 246, 247, 5, 21, 0, 0, 247, 63, 1, 0, 0, 0, 248, 251, 3, 4, 2, 0, 249, 251, 5, 44, 0, 0, 250, 248, 1, 0, 0, 0, 250, 249, 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 254, 5, 24, 0, 0, 253, 250, 1, 0, 0, 0, 253, 254, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 256, 3, 18, 9, 0, 256, 65, 1, 0, 0, 0, 257, 259, 5, 17, 0, 0, 258, 260, 3, 70, 35, 0, 259, 258, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 262, 5, 26, 0, 0, 262, 67, 1, 0, 0, 0, 263, 268, 3, 70, 35, 0, 264, 265, 5, 25, 0, 0, 265, 267, 3, 70, 35, 0, 266, 264, 1, 0, 0, 0, 267, 270, 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 272, 1, 0, 0, 0, 270, 268, 1, 0, 0, 0, 271, 263, 1, 0, 0, 0, 271, 272, 1, 0, 0, 0, 272, 69, 1, 0, 0, 0, 273, 274, 6, 35, -1, 0, 274, 281, 3, 78, 39, 0, 275, 281, 3, 38, 19, 0, 276, 281, 3, 62, 31, 0, 277, 281, 3, 76, 38, 0, 278, 281, 3, 74, 37, 0, 279, 281, 3, 72, 36, 0, 280, 273, 1, 0, 0, 0, 280, 275, 1, 0, 0, 0, 280, 276, 1, 0, 0, 0, 280, 277, 1, 0, 0, 0, 280, 278, 1, 0, 0, 0, 280, 279, 1, 0, 0, 0, 281, 288, 1, 0, 0, 0, 282, 283, 10, 2, 0, 0, 283, 284, 3, 84, 42, 0, 284, 285, 3, 70, 35, 3, 285, 287, 1, 0, 0, 0, 286, 282, 1, 0, 0, 0, 287, 290, 1, 0, 0, 0, 288, 286, 1, 0, 0, 0, 288, 289, 1, 0, 0, 0, 289, 71, 1, 0, 0, 0, 290, 288, 1, 0, 0, 0, 291, 292, 5, 20, 0, 0, 292, 293, 3, 70, 35, 0, 293, 294, 5, 21, 0, 0, 294, 73, 1, 0, 0, 0, 295, 296, 3, 82, 41, 0, 296, 297, 3, 70, 35, 0, 297, 75, 1, 0, 0, 0, 298, 299, 3, 38, 19, 0, 299, 300, 5, 22, 0, 0, 300, 301, 3, 70, 35, 0, 301, 302, 5, 23, 0, 0, 302, 77, 1, 0, 0, 0, 303, 309, 5, 40, 0, 0, 304, 309, 5, 46, 0, 0, 305, 309, 3, 80, 40, 0, 306, 309, 5, 43, 0, 0, 307, 309, 5, 44, 0, 0, 308, 303, 1, 0, 0, 0, 308, 304, 1, 0, 0, 0, 308, 305, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 308, 307, 1, 0, 0, 0, 309, 79, 1, 0, 0, 0, 310, 311, 7, 3, 0, 0, 311, 81, 1, 0, 0, 0, 312, 313, 7, 4, 0, 0, 313, 83, 1, 0, 0, 0, 314, 315, 7, 5, 0, 0, 315, 85, 1, 0, 0, 0, 20, 95, 101, 118, 139, 148, 151, 162, 177, 189, 197, 202, 212, 250, 253, 259, 268, 271, 280, 288, 308] \ No newline at end of file +[4, 1, 46, 317, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 94, 8, 1, 10, 1, 12, 1, 97, 9, 1, 1, 1, 5, 1, 100, 8, 1, 10, 1, 12, 1, 103, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 117, 8, 4, 10, 4, 12, 4, 120, 9, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 5, 12, 147, 8, 12, 10, 12, 12, 12, 150, 9, 12, 3, 12, 152, 8, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 161, 8, 15, 10, 15, 12, 15, 164, 9, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 176, 8, 17, 10, 17, 12, 17, 179, 9, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 5, 19, 186, 8, 19, 10, 19, 12, 19, 189, 9, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 3, 20, 196, 8, 20, 1, 21, 1, 21, 1, 21, 3, 21, 201, 8, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, 3, 23, 211, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 3, 31, 249, 8, 31, 1, 31, 3, 31, 252, 8, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 258, 8, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 5, 33, 265, 8, 33, 10, 33, 12, 33, 268, 9, 33, 3, 33, 270, 8, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 279, 8, 34, 1, 34, 1, 34, 1, 34, 1, 34, 5, 34, 285, 8, 34, 10, 34, 12, 34, 288, 9, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 3, 35, 295, 8, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 0, 1, 68, 43, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 0, 6, 1, 0, 5, 6, 1, 0, 2, 4, 2, 0, 8, 10, 45, 45, 1, 0, 41, 42, 2, 0, 29, 29, 34, 34, 2, 0, 27, 33, 35, 36, 303, 0, 86, 1, 0, 0, 0, 2, 89, 1, 0, 0, 0, 4, 106, 1, 0, 0, 0, 6, 108, 1, 0, 0, 0, 8, 112, 1, 0, 0, 0, 10, 121, 1, 0, 0, 0, 12, 123, 1, 0, 0, 0, 14, 126, 1, 0, 0, 0, 16, 128, 1, 0, 0, 0, 18, 135, 1, 0, 0, 0, 20, 139, 1, 0, 0, 0, 22, 141, 1, 0, 0, 0, 24, 151, 1, 0, 0, 0, 26, 153, 1, 0, 0, 0, 28, 156, 1, 0, 0, 0, 30, 158, 1, 0, 0, 0, 32, 168, 1, 0, 0, 0, 34, 170, 1, 0, 0, 0, 36, 182, 1, 0, 0, 0, 38, 187, 1, 0, 0, 0, 40, 195, 1, 0, 0, 0, 42, 197, 1, 0, 0, 0, 44, 206, 1, 0, 0, 0, 46, 208, 1, 0, 0, 0, 48, 212, 1, 0, 0, 0, 50, 220, 1, 0, 0, 0, 52, 222, 1, 0, 0, 0, 54, 227, 1, 0, 0, 0, 56, 235, 1, 0, 0, 0, 58, 237, 1, 0, 0, 0, 60, 241, 1, 0, 0, 0, 62, 251, 1, 0, 0, 0, 64, 255, 1, 0, 0, 0, 66, 269, 1, 0, 0, 0, 68, 278, 1, 0, 0, 0, 70, 294, 1, 0, 0, 0, 72, 296, 1, 0, 0, 0, 74, 298, 1, 0, 0, 0, 76, 303, 1, 0, 0, 0, 78, 306, 1, 0, 0, 0, 80, 310, 1, 0, 0, 0, 82, 312, 1, 0, 0, 0, 84, 314, 1, 0, 0, 0, 86, 87, 3, 2, 1, 0, 87, 88, 5, 0, 0, 1, 88, 1, 1, 0, 0, 0, 89, 90, 5, 1, 0, 0, 90, 91, 3, 4, 2, 0, 91, 95, 5, 18, 0, 0, 92, 94, 3, 6, 3, 0, 93, 92, 1, 0, 0, 0, 94, 97, 1, 0, 0, 0, 95, 93, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 101, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 98, 100, 3, 12, 6, 0, 99, 98, 1, 0, 0, 0, 100, 103, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 101, 102, 1, 0, 0, 0, 102, 104, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 104, 105, 3, 32, 16, 0, 105, 3, 1, 0, 0, 0, 106, 107, 5, 45, 0, 0, 107, 5, 1, 0, 0, 0, 108, 109, 7, 0, 0, 0, 109, 110, 3, 8, 4, 0, 110, 111, 5, 26, 0, 0, 111, 7, 1, 0, 0, 0, 112, 113, 3, 22, 11, 0, 113, 118, 3, 10, 5, 0, 114, 115, 5, 25, 0, 0, 115, 117, 3, 10, 5, 0, 116, 114, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 9, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 121, 122, 5, 45, 0, 0, 122, 11, 1, 0, 0, 0, 123, 124, 3, 14, 7, 0, 124, 125, 3, 16, 8, 0, 125, 13, 1, 0, 0, 0, 126, 127, 7, 1, 0, 0, 127, 15, 1, 0, 0, 0, 128, 129, 3, 20, 10, 0, 129, 130, 3, 18, 9, 0, 130, 131, 5, 20, 0, 0, 131, 132, 3, 24, 12, 0, 132, 133, 5, 21, 0, 0, 133, 134, 3, 30, 15, 0, 134, 17, 1, 0, 0, 0, 135, 136, 5, 45, 0, 0, 136, 19, 1, 0, 0, 0, 137, 140, 3, 22, 11, 0, 138, 140, 5, 11, 0, 0, 139, 137, 1, 0, 0, 0, 139, 138, 1, 0, 0, 0, 140, 21, 1, 0, 0, 0, 141, 142, 7, 2, 0, 0, 142, 23, 1, 0, 0, 0, 143, 148, 3, 26, 13, 0, 144, 145, 5, 25, 0, 0, 145, 147, 3, 26, 13, 0, 146, 144, 1, 0, 0, 0, 147, 150, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 148, 149, 1, 0, 0, 0, 149, 152, 1, 0, 0, 0, 150, 148, 1, 0, 0, 0, 151, 143, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 25, 1, 0, 0, 0, 153, 154, 3, 22, 11, 0, 154, 155, 3, 28, 14, 0, 155, 27, 1, 0, 0, 0, 156, 157, 5, 45, 0, 0, 157, 29, 1, 0, 0, 0, 158, 162, 5, 18, 0, 0, 159, 161, 3, 34, 17, 0, 160, 159, 1, 0, 0, 0, 161, 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 165, 1, 0, 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 3, 38, 19, 0, 166, 167, 3, 32, 16, 0, 167, 31, 1, 0, 0, 0, 168, 169, 5, 19, 0, 0, 169, 33, 1, 0, 0, 0, 170, 171, 5, 7, 0, 0, 171, 172, 3, 22, 11, 0, 172, 177, 3, 36, 18, 0, 173, 174, 5, 25, 0, 0, 174, 176, 3, 36, 18, 0, 175, 173, 1, 0, 0, 0, 176, 179, 1, 0, 0, 0, 177, 175, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 180, 1, 0, 0, 0, 179, 177, 1, 0, 0, 0, 180, 181, 5, 26, 0, 0, 181, 35, 1, 0, 0, 0, 182, 183, 5, 45, 0, 0, 183, 37, 1, 0, 0, 0, 184, 186, 3, 40, 20, 0, 185, 184, 1, 0, 0, 0, 186, 189, 1, 0, 0, 0, 187, 185, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 39, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 190, 196, 3, 42, 21, 0, 191, 196, 3, 46, 23, 0, 192, 196, 3, 54, 27, 0, 193, 196, 3, 58, 29, 0, 194, 196, 3, 64, 32, 0, 195, 190, 1, 0, 0, 0, 195, 191, 1, 0, 0, 0, 195, 192, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 195, 194, 1, 0, 0, 0, 196, 41, 1, 0, 0, 0, 197, 200, 5, 12, 0, 0, 198, 201, 3, 72, 36, 0, 199, 201, 3, 74, 37, 0, 200, 198, 1, 0, 0, 0, 200, 199, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 203, 3, 44, 22, 0, 203, 204, 3, 68, 34, 0, 204, 205, 5, 26, 0, 0, 205, 43, 1, 0, 0, 0, 206, 207, 5, 27, 0, 0, 207, 45, 1, 0, 0, 0, 208, 210, 3, 48, 24, 0, 209, 211, 3, 52, 26, 0, 210, 209, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 47, 1, 0, 0, 0, 212, 213, 5, 14, 0, 0, 213, 214, 5, 20, 0, 0, 214, 215, 3, 50, 25, 0, 215, 216, 5, 21, 0, 0, 216, 217, 5, 18, 0, 0, 217, 218, 3, 38, 19, 0, 218, 219, 3, 32, 16, 0, 219, 49, 1, 0, 0, 0, 220, 221, 3, 68, 34, 0, 221, 51, 1, 0, 0, 0, 222, 223, 5, 15, 0, 0, 223, 224, 5, 18, 0, 0, 224, 225, 3, 38, 19, 0, 225, 226, 3, 32, 16, 0, 226, 53, 1, 0, 0, 0, 227, 228, 5, 16, 0, 0, 228, 229, 5, 20, 0, 0, 229, 230, 3, 56, 28, 0, 230, 231, 5, 21, 0, 0, 231, 232, 5, 18, 0, 0, 232, 233, 3, 38, 19, 0, 233, 234, 3, 32, 16, 0, 234, 55, 1, 0, 0, 0, 235, 236, 3, 68, 34, 0, 236, 57, 1, 0, 0, 0, 237, 238, 5, 13, 0, 0, 238, 239, 3, 60, 30, 0, 239, 240, 5, 26, 0, 0, 240, 59, 1, 0, 0, 0, 241, 242, 3, 62, 31, 0, 242, 243, 5, 20, 0, 0, 243, 244, 3, 66, 33, 0, 244, 245, 5, 21, 0, 0, 245, 61, 1, 0, 0, 0, 246, 249, 3, 4, 2, 0, 247, 249, 5, 44, 0, 0, 248, 246, 1, 0, 0, 0, 248, 247, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 252, 5, 24, 0, 0, 251, 248, 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 3, 18, 9, 0, 254, 63, 1, 0, 0, 0, 255, 257, 5, 17, 0, 0, 256, 258, 3, 68, 34, 0, 257, 256, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 5, 26, 0, 0, 260, 65, 1, 0, 0, 0, 261, 266, 3, 68, 34, 0, 262, 263, 5, 25, 0, 0, 263, 265, 3, 68, 34, 0, 264, 262, 1, 0, 0, 0, 265, 268, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 267, 270, 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 269, 261, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 67, 1, 0, 0, 0, 271, 272, 6, 34, -1, 0, 272, 279, 3, 70, 35, 0, 273, 279, 3, 72, 36, 0, 274, 279, 3, 60, 30, 0, 275, 279, 3, 74, 37, 0, 276, 279, 3, 76, 38, 0, 277, 279, 3, 78, 39, 0, 278, 271, 1, 0, 0, 0, 278, 273, 1, 0, 0, 0, 278, 274, 1, 0, 0, 0, 278, 275, 1, 0, 0, 0, 278, 276, 1, 0, 0, 0, 278, 277, 1, 0, 0, 0, 279, 286, 1, 0, 0, 0, 280, 281, 10, 2, 0, 0, 281, 282, 3, 84, 42, 0, 282, 283, 3, 68, 34, 3, 283, 285, 1, 0, 0, 0, 284, 280, 1, 0, 0, 0, 285, 288, 1, 0, 0, 0, 286, 284, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 69, 1, 0, 0, 0, 288, 286, 1, 0, 0, 0, 289, 295, 5, 40, 0, 0, 290, 295, 5, 46, 0, 0, 291, 295, 3, 80, 40, 0, 292, 295, 5, 43, 0, 0, 293, 295, 5, 44, 0, 0, 294, 289, 1, 0, 0, 0, 294, 290, 1, 0, 0, 0, 294, 291, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, 294, 293, 1, 0, 0, 0, 295, 71, 1, 0, 0, 0, 296, 297, 5, 45, 0, 0, 297, 73, 1, 0, 0, 0, 298, 299, 3, 72, 36, 0, 299, 300, 5, 22, 0, 0, 300, 301, 3, 68, 34, 0, 301, 302, 5, 23, 0, 0, 302, 75, 1, 0, 0, 0, 303, 304, 3, 82, 41, 0, 304, 305, 3, 68, 34, 0, 305, 77, 1, 0, 0, 0, 306, 307, 5, 20, 0, 0, 307, 308, 3, 68, 34, 0, 308, 309, 5, 21, 0, 0, 309, 79, 1, 0, 0, 0, 310, 311, 7, 3, 0, 0, 311, 81, 1, 0, 0, 0, 312, 313, 7, 4, 0, 0, 313, 83, 1, 0, 0, 0, 314, 315, 7, 5, 0, 0, 315, 85, 1, 0, 0, 0, 20, 95, 101, 118, 139, 148, 151, 162, 177, 187, 195, 200, 210, 248, 251, 257, 266, 269, 278, 286, 294] \ No newline at end of file diff --git a/simulator/src/jack/generated/JackParser.tokens b/simulator/src/jack/generated/JackParser.tokens index 225dc556..7a0969b6 100644 --- a/simulator/src/jack/generated/JackParser.tokens +++ b/simulator/src/jack/generated/JackParser.tokens @@ -34,8 +34,8 @@ OR=33 TILDE=34 LESS_THAN=35 GREATER_THAN=36 -WS=37 -COMMENT=38 +WHITESPACE=37 +BLOCK_COMMENT=38 LINE_COMMENT=39 INTEGER_LITERAL=40 TRUE=41 @@ -44,7 +44,6 @@ NULL_LITERAL=43 THIS_LITERAL=44 IDENTIFIER=45 STRING_LITERAL=46 -UnterminatedStringLiteral=47 'class'=1 'constructor'=2 'function'=3 diff --git a/simulator/src/jack/generated/JackParser.ts b/simulator/src/jack/generated/JackParser.ts index 85b6338f..7d8fd520 100644 --- a/simulator/src/jack/generated/JackParser.ts +++ b/simulator/src/jack/generated/JackParser.ts @@ -2,3738 +2,3278 @@ // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { - ATN, - ATNDeserializer, - DecisionState, - DFA, - FailedPredicateException, - NoViableAltException, - Parser, - ParserATNSimulator, - ParserRuleContext, - PredictionContextCache, - RecognitionException, - RuleContext, - TerminalNode, - Token, - TokenStream, -} from "antlr4"; + ATN, + ATNDeserializer, DecisionState, DFA, FailedPredicateException, + RecognitionException, NoViableAltException, BailErrorStrategy, + Parser, ParserATNSimulator, + RuleContext, ParserRuleContext, PredictionMode, PredictionContextCache, + TerminalNode, RuleNode, + Token, TokenStream, + Interval, IntervalSet +} from 'antlr4'; import JackParserListener from "./JackParserListener.js"; // for running tests with parameters, TODO: discuss strategy for typed parameters in CI // eslint-disable-next-line no-unused-vars +type int = number; -import { LocalSymbolTable, SubroutineScope } from "../symbol.js"; + +import { SubroutineScope, LocalSymbolTable } from "../symbol"; export default class JackParser extends Parser { - public static readonly CLASS = 1; - public static readonly CONSTRUCTOR = 2; - public static readonly FUNCTION = 3; - public static readonly METHOD = 4; - public static readonly FIELD = 5; - public static readonly STATIC = 6; - public static readonly VAR = 7; - public static readonly INT = 8; - public static readonly CHAR = 9; - public static readonly BOOLEAN = 10; - public static readonly VOID = 11; - public static readonly LET = 12; - public static readonly DO = 13; - public static readonly IF = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly RETURN = 17; - public static readonly LBRACE = 18; - public static readonly RBRACE = 19; - public static readonly LPAREN = 20; - public static readonly RPAREN = 21; - public static readonly LBRACKET = 22; - public static readonly RBRACKET = 23; - public static readonly DOT = 24; - public static readonly COMMA = 25; - public static readonly SEMICOLON = 26; - public static readonly EQUALS = 27; - public static readonly PLUS = 28; - public static readonly MINUS = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly AND = 32; - public static readonly OR = 33; - public static readonly TILDE = 34; - public static readonly LESS_THAN = 35; - public static readonly GREATER_THAN = 36; - public static readonly WS = 37; - public static readonly COMMENT = 38; - public static readonly LINE_COMMENT = 39; - public static readonly INTEGER_LITERAL = 40; - public static readonly TRUE = 41; - public static readonly FALSE = 42; - public static readonly NULL_LITERAL = 43; - public static readonly THIS_LITERAL = 44; - public static readonly IDENTIFIER = 45; - public static readonly STRING_LITERAL = 46; - public static readonly UnterminatedStringLiteral = 47; - public static override readonly EOF = Token.EOF; - public static readonly RULE_program = 0; - public static readonly RULE_classDeclaration = 1; - public static readonly RULE_className = 2; - public static readonly RULE_classVarDec = 3; - public static readonly RULE_fieldList = 4; - public static readonly RULE_fieldName = 5; - public static readonly RULE_subroutineDeclaration = 6; - public static readonly RULE_subroutineType = 7; - public static readonly RULE_subroutineDecWithoutType = 8; - public static readonly RULE_subroutineName = 9; - public static readonly RULE_subroutineReturnType = 10; - public static readonly RULE_varType = 11; - public static readonly RULE_parameterList = 12; - public static readonly RULE_parameter = 13; - public static readonly RULE_parameterName = 14; - public static readonly RULE_subroutineBody = 15; - public static readonly RULE_rBrace = 16; - public static readonly RULE_varDeclaration = 17; - public static readonly RULE_varNameInDeclaration = 18; - public static readonly RULE_varName = 19; - public static readonly RULE_statements = 20; - public static readonly RULE_statement = 21; - public static readonly RULE_letStatement = 22; - public static readonly RULE_equals = 23; - public static readonly RULE_ifElseStatement = 24; - public static readonly RULE_ifStatement = 25; - public static readonly RULE_ifExpression = 26; - public static readonly RULE_elseStatement = 27; - public static readonly RULE_whileStatement = 28; - public static readonly RULE_whileExpression = 29; - public static readonly RULE_doStatement = 30; - public static readonly RULE_subroutineCall = 31; - public static readonly RULE_subroutineId = 32; - public static readonly RULE_returnStatement = 33; - public static readonly RULE_expressionList = 34; - public static readonly RULE_expression = 35; - public static readonly RULE_groupedExpression = 36; - public static readonly RULE_unaryOperation = 37; - public static readonly RULE_arrayAccess = 38; - public static readonly RULE_constant = 39; - public static readonly RULE_booleanLiteral = 40; - public static readonly RULE_unaryOperator = 41; - public static readonly RULE_binaryOperator = 42; - public static readonly literalNames: (string | null)[] = [ - null, - "'class'", - "'constructor'", - "'function'", - "'method'", - "'field'", - "'static'", - "'var'", - "'int'", - "'char'", - "'boolean'", - "'void'", - "'let'", - "'do'", - "'if'", - "'else'", - "'while'", - "'return'", - "'{'", - "'}'", - "'('", - "')'", - "'['", - "']'", - "'.'", - "','", - "';'", - "'='", - "'+'", - "'-'", - "'*'", - "'/'", - "'&'", - "'|'", - "'~'", - "'<'", - "'>'", - null, - null, - null, - null, - "'true'", - "'false'", - "'null'", - "'this'", - ]; - public static readonly symbolicNames: (string | null)[] = [ - null, - "CLASS", - "CONSTRUCTOR", - "FUNCTION", - "METHOD", - "FIELD", - "STATIC", - "VAR", - "INT", - "CHAR", - "BOOLEAN", - "VOID", - "LET", - "DO", - "IF", - "ELSE", - "WHILE", - "RETURN", - "LBRACE", - "RBRACE", - "LPAREN", - "RPAREN", - "LBRACKET", - "RBRACKET", - "DOT", - "COMMA", - "SEMICOLON", - "EQUALS", - "PLUS", - "MINUS", - "MUL", - "DIV", - "AND", - "OR", - "TILDE", - "LESS_THAN", - "GREATER_THAN", - "WS", - "COMMENT", - "LINE_COMMENT", - "INTEGER_LITERAL", - "TRUE", - "FALSE", - "NULL_LITERAL", - "THIS_LITERAL", - "IDENTIFIER", - "STRING_LITERAL", - "UnterminatedStringLiteral", - ]; - // tslint:disable:no-trailing-whitespace - public static readonly ruleNames: string[] = [ - "program", - "classDeclaration", - "className", - "classVarDec", - "fieldList", - "fieldName", - "subroutineDeclaration", - "subroutineType", - "subroutineDecWithoutType", - "subroutineName", - "subroutineReturnType", - "varType", - "parameterList", - "parameter", - "parameterName", - "subroutineBody", - "rBrace", - "varDeclaration", - "varNameInDeclaration", - "varName", - "statements", - "statement", - "letStatement", - "equals", - "ifElseStatement", - "ifStatement", - "ifExpression", - "elseStatement", - "whileStatement", - "whileExpression", - "doStatement", - "subroutineCall", - "subroutineId", - "returnStatement", - "expressionList", - "expression", - "groupedExpression", - "unaryOperation", - "arrayAccess", - "constant", - "booleanLiteral", - "unaryOperator", - "binaryOperator", - ]; - public get grammarFileName(): string { - return "JackParser.g4"; - } - public get literalNames(): (string | null)[] { - return JackParser.literalNames; - } - public get symbolicNames(): (string | null)[] { - return JackParser.symbolicNames; - } - public get ruleNames(): string[] { - return JackParser.ruleNames; - } - public get serializedATN(): number[] { - return JackParser._serializedATN; - } - - protected createFailedPredicateException( - predicate?: string, - message?: string, - ): FailedPredicateException { - return new FailedPredicateException(this, predicate, message); - } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator( - this, - JackParser._ATN, - JackParser.DecisionsToDFA, - new PredictionContextCache(), - ); - } - // @RuleVersion(0) - public program(): ProgramContext { - const localctx: ProgramContext = new ProgramContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 0, JackParser.RULE_program); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 86; - this.classDeclaration(); - this.state = 87; - this.match(JackParser.EOF); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public classDeclaration(): ClassDeclarationContext { - const localctx: ClassDeclarationContext = new ClassDeclarationContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 2, JackParser.RULE_classDeclaration); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 89; - this.match(JackParser.CLASS); - this.state = 90; - this.className(); - this.state = 91; - this.match(JackParser.LBRACE); - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === 5 || _la === 6) { - { - { - this.state = 92; - this.classVarDec(); - } - } - this.state = 97; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((_la & ~0x1f) === 0 && ((1 << _la) & 28) !== 0) { - { - { - this.state = 98; - this.subroutineDeclaration(); - } - } - this.state = 103; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 104; - this.rBrace(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public className(): ClassNameContext { - const localctx: ClassNameContext = new ClassNameContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 4, JackParser.RULE_className); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 106; - this.match(JackParser.IDENTIFIER); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public classVarDec(): ClassVarDecContext { - const localctx: ClassVarDecContext = new ClassVarDecContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 6, JackParser.RULE_classVarDec); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 108; - _la = this._input.LA(1); - if (!(_la === 5 || _la === 6)) { - this._errHandler.recoverInline(this); - } else { - this._errHandler.reportMatch(this); - this.consume(); - } - this.state = 109; - this.fieldList(); - this.state = 110; - this.match(JackParser.SEMICOLON); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public fieldList(): FieldListContext { - const localctx: FieldListContext = new FieldListContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 8, JackParser.RULE_fieldList); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 112; - this.varType(); - this.state = 113; - this.fieldName(); - this.state = 118; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === 25) { - { - { - this.state = 114; - this.match(JackParser.COMMA); - this.state = 115; - this.fieldName(); - } - } - this.state = 120; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public fieldName(): FieldNameContext { - const localctx: FieldNameContext = new FieldNameContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 10, JackParser.RULE_fieldName); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 121; - this.match(JackParser.IDENTIFIER); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineDeclaration(): SubroutineDeclarationContext { - const localctx: SubroutineDeclarationContext = - new SubroutineDeclarationContext(this, this._ctx, this.state); - this.enterRule(localctx, 12, JackParser.RULE_subroutineDeclaration); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 123; - this.subroutineType(); - this.state = 124; - this.subroutineDecWithoutType(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineType(): SubroutineTypeContext { - const localctx: SubroutineTypeContext = new SubroutineTypeContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 14, JackParser.RULE_subroutineType); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 126; - _la = this._input.LA(1); - if (!((_la & ~0x1f) === 0 && ((1 << _la) & 28) !== 0)) { - this._errHandler.recoverInline(this); - } else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - const localctx: SubroutineDecWithoutTypeContext = - new SubroutineDecWithoutTypeContext(this, this._ctx, this.state); - this.enterRule(localctx, 16, JackParser.RULE_subroutineDecWithoutType); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 128; - this.subroutineReturnType(); - this.state = 129; - this.subroutineName(); - this.state = 130; - this.match(JackParser.LPAREN); - this.state = 131; - this.parameterList(); - this.state = 132; - this.match(JackParser.RPAREN); - this.state = 133; - this.subroutineBody(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineName(): SubroutineNameContext { - const localctx: SubroutineNameContext = new SubroutineNameContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 18, JackParser.RULE_subroutineName); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 135; - this.match(JackParser.IDENTIFIER); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineReturnType(): SubroutineReturnTypeContext { - const localctx: SubroutineReturnTypeContext = - new SubroutineReturnTypeContext(this, this._ctx, this.state); - this.enterRule(localctx, 20, JackParser.RULE_subroutineReturnType); - try { - this.state = 139; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case 8: - case 9: - case 10: - case 45: - this.enterOuterAlt(localctx, 1); - { - this.state = 137; - this.varType(); - } - break; - case 11: - this.enterOuterAlt(localctx, 2); - { - this.state = 138; - this.match(JackParser.VOID); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public varType(): VarTypeContext { - const localctx: VarTypeContext = new VarTypeContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 22, JackParser.RULE_varType); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 141; - _la = this._input.LA(1); - if ( - !(((_la & ~0x1f) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45) - ) { - this._errHandler.recoverInline(this); - } else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public parameterList(): ParameterListContext { - const localctx: ParameterListContext = new ParameterListContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 24, JackParser.RULE_parameterList); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 151; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (((_la & ~0x1f) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45) { - { - this.state = 143; - this.parameter(); - this.state = 148; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === 25) { - { - { - this.state = 144; - this.match(JackParser.COMMA); - this.state = 145; - this.parameter(); - } - } - this.state = 150; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public parameter(): ParameterContext { - const localctx: ParameterContext = new ParameterContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 26, JackParser.RULE_parameter); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 153; - this.varType(); - this.state = 154; - this.parameterName(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public parameterName(): ParameterNameContext { - const localctx: ParameterNameContext = new ParameterNameContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 28, JackParser.RULE_parameterName); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 156; - this.match(JackParser.IDENTIFIER); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineBody(): SubroutineBodyContext { - const localctx: SubroutineBodyContext = new SubroutineBodyContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 30, JackParser.RULE_subroutineBody); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 158; - this.match(JackParser.LBRACE); - this.state = 162; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === 7) { - { - { - this.state = 159; - this.varDeclaration(); - } - } - this.state = 164; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 165; - this.statements(); - this.state = 166; - this.rBrace(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public rBrace(): RBraceContext { - const localctx: RBraceContext = new RBraceContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 32, JackParser.RULE_rBrace); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 168; - this.match(JackParser.RBRACE); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public varDeclaration(): VarDeclarationContext { - const localctx: VarDeclarationContext = new VarDeclarationContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 34, JackParser.RULE_varDeclaration); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 170; - this.match(JackParser.VAR); - this.state = 171; - this.varType(); - this.state = 172; - this.varNameInDeclaration(); - this.state = 177; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === 25) { - { - { - this.state = 173; - this.match(JackParser.COMMA); - this.state = 174; - this.varNameInDeclaration(); - } - } - this.state = 179; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 180; - this.match(JackParser.SEMICOLON); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public varNameInDeclaration(): VarNameInDeclarationContext { - const localctx: VarNameInDeclarationContext = - new VarNameInDeclarationContext(this, this._ctx, this.state); - this.enterRule(localctx, 36, JackParser.RULE_varNameInDeclaration); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 182; - this.match(JackParser.IDENTIFIER); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public varName(): VarNameContext { - const localctx: VarNameContext = new VarNameContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 38, JackParser.RULE_varName); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 184; - this.match(JackParser.IDENTIFIER); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public statements(): StatementsContext { - const localctx: StatementsContext = new StatementsContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 40, JackParser.RULE_statements); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 189; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((_la & ~0x1f) === 0 && ((1 << _la) & 225280) !== 0) { - { - { - this.state = 186; - this.statement(); - } - } - this.state = 191; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public statement(): StatementContext { - const localctx: StatementContext = new StatementContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 42, JackParser.RULE_statement); - try { - this.state = 197; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case 12: - this.enterOuterAlt(localctx, 1); - { - this.state = 192; - this.letStatement(); - } - break; - case 14: - this.enterOuterAlt(localctx, 2); - { - this.state = 193; - this.ifElseStatement(); - } - break; - case 16: - this.enterOuterAlt(localctx, 3); - { - this.state = 194; - this.whileStatement(); - } - break; - case 13: - this.enterOuterAlt(localctx, 4); - { - this.state = 195; - this.doStatement(); - } - break; - case 17: - this.enterOuterAlt(localctx, 5); - { - this.state = 196; - this.returnStatement(); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public letStatement(): LetStatementContext { - const localctx: LetStatementContext = new LetStatementContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 44, JackParser.RULE_letStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 199; - this.match(JackParser.LET); - this.state = 202; - this._errHandler.sync(this); - switch (this._interp.adaptivePredict(this._input, 10, this._ctx)) { - case 1: - { - this.state = 200; - this.varName(); - } - break; - case 2: - { - this.state = 201; - this.arrayAccess(); - } - break; - } - this.state = 204; - this.equals(); - this.state = 205; - this.expression(0); - this.state = 206; - this.match(JackParser.SEMICOLON); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public equals(): EqualsContext { - const localctx: EqualsContext = new EqualsContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 46, JackParser.RULE_equals); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 208; - this.match(JackParser.EQUALS); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public ifElseStatement(): IfElseStatementContext { - const localctx: IfElseStatementContext = new IfElseStatementContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 48, JackParser.RULE_ifElseStatement); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 210; - this.ifStatement(); - this.state = 212; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la === 15) { - { - this.state = 211; - this.elseStatement(); - } - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public ifStatement(): IfStatementContext { - const localctx: IfStatementContext = new IfStatementContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 50, JackParser.RULE_ifStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 214; - this.match(JackParser.IF); - this.state = 215; - this.match(JackParser.LPAREN); - this.state = 216; - this.ifExpression(); - this.state = 217; - this.match(JackParser.RPAREN); - this.state = 218; - this.match(JackParser.LBRACE); - this.state = 219; - this.statements(); - this.state = 220; - this.rBrace(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public ifExpression(): IfExpressionContext { - const localctx: IfExpressionContext = new IfExpressionContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 52, JackParser.RULE_ifExpression); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 222; - this.expression(0); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public elseStatement(): ElseStatementContext { - const localctx: ElseStatementContext = new ElseStatementContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 54, JackParser.RULE_elseStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 224; - this.match(JackParser.ELSE); - this.state = 225; - this.match(JackParser.LBRACE); - this.state = 226; - this.statements(); - this.state = 227; - this.rBrace(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public whileStatement(): WhileStatementContext { - const localctx: WhileStatementContext = new WhileStatementContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 56, JackParser.RULE_whileStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 229; - this.match(JackParser.WHILE); - this.state = 230; - this.match(JackParser.LPAREN); - this.state = 231; - this.whileExpression(); - this.state = 232; - this.match(JackParser.RPAREN); - this.state = 233; - this.match(JackParser.LBRACE); - this.state = 234; - this.statements(); - this.state = 235; - this.rBrace(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public whileExpression(): WhileExpressionContext { - const localctx: WhileExpressionContext = new WhileExpressionContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 58, JackParser.RULE_whileExpression); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 237; - this.expression(0); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public doStatement(): DoStatementContext { - const localctx: DoStatementContext = new DoStatementContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 60, JackParser.RULE_doStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 239; - this.match(JackParser.DO); - this.state = 240; - this.subroutineCall(); - this.state = 241; - this.match(JackParser.SEMICOLON); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineCall(): SubroutineCallContext { - const localctx: SubroutineCallContext = new SubroutineCallContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 62, JackParser.RULE_subroutineCall); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 243; - this.subroutineId(); - this.state = 244; - this.match(JackParser.LPAREN); - this.state = 245; - this.expressionList(); - this.state = 246; - this.match(JackParser.RPAREN); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineId(): SubroutineIdContext { - const localctx: SubroutineIdContext = new SubroutineIdContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 64, JackParser.RULE_subroutineId); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 253; - this._errHandler.sync(this); - switch (this._interp.adaptivePredict(this._input, 13, this._ctx)) { - case 1: - { - this.state = 250; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case 45: - { - this.state = 248; - this.className(); - } - break; - case 44: - { - this.state = 249; - this.match(JackParser.THIS_LITERAL); - } - break; - default: - throw new NoViableAltException(this); - } - this.state = 252; - this.match(JackParser.DOT); - } - break; - } - this.state = 255; - this.subroutineName(); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public returnStatement(): ReturnStatementContext { - const localctx: ReturnStatementContext = new ReturnStatementContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 66, JackParser.RULE_returnStatement); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 257; - this.match(JackParser.RETURN); - this.state = 259; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - ((_la - 20) & ~0x1f) === 0 && - ((1 << (_la - 20)) & 133186049) !== 0 - ) { - { - this.state = 258; - this.expression(0); - } - } - - this.state = 261; - this.match(JackParser.SEMICOLON); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public expressionList(): ExpressionListContext { - const localctx: ExpressionListContext = new ExpressionListContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 68, JackParser.RULE_expressionList); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 271; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ( - ((_la - 20) & ~0x1f) === 0 && - ((1 << (_la - 20)) & 133186049) !== 0 - ) { - { - this.state = 263; - this.expression(0); - this.state = 268; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la === 25) { - { - { - this.state = 264; - this.match(JackParser.COMMA); - this.state = 265; - this.expression(0); - } - } - this.state = 270; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - - public expression(): ExpressionContext; - public expression(_p: number): ExpressionContext; - // @RuleVersion(0) - public expression(_p?: number): ExpressionContext { - if (_p === undefined) { - _p = 0; - } - - const _parentctx: ParserRuleContext = this._ctx; - const _parentState: number = this.state; - let localctx: ExpressionContext = new ExpressionContext( - this, - this._ctx, - _parentState, - ); - const _startState = 70; - this.enterRecursionRule(localctx, 70, JackParser.RULE_expression, _p); - try { - let _alt: number; - this.enterOuterAlt(localctx, 1); - { - this.state = 280; - this._errHandler.sync(this); - switch (this._interp.adaptivePredict(this._input, 17, this._ctx)) { - case 1: - { - this.state = 274; - this.constant(); - } - break; - case 2: - { - this.state = 275; - this.varName(); - } - break; - case 3: - { - this.state = 276; - this.subroutineCall(); - } - break; - case 4: - { - this.state = 277; - this.arrayAccess(); - } - break; - case 5: - { - this.state = 278; - this.unaryOperation(); - } - break; - case 6: - { - this.state = 279; - this.groupedExpression(); - } - break; - } - this._ctx.stop = this._input.LT(-1); - this.state = 288; - this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 18, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - if (this._parseListeners != null) { - this.triggerExitRuleEvent(); - } - { - { - localctx = new ExpressionContext( - this, - _parentctx, - _parentState, - ); - this.pushNewRecursionContext( - localctx, - _startState, - JackParser.RULE_expression, - ); - this.state = 282; - if (!this.precpred(this._ctx, 2)) { - throw this.createFailedPredicateException( - "this.precpred(this._ctx, 2)", - ); - } - this.state = 283; - this.binaryOperator(); - this.state = 284; - this.expression(3); - } - } - } - this.state = 290; - this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 18, this._ctx); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.unrollRecursionContexts(_parentctx); - } - return localctx; - } - // @RuleVersion(0) - public groupedExpression(): GroupedExpressionContext { - const localctx: GroupedExpressionContext = new GroupedExpressionContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 72, JackParser.RULE_groupedExpression); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 291; - this.match(JackParser.LPAREN); - this.state = 292; - this.expression(0); - this.state = 293; - this.match(JackParser.RPAREN); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public unaryOperation(): UnaryOperationContext { - const localctx: UnaryOperationContext = new UnaryOperationContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 74, JackParser.RULE_unaryOperation); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 295; - this.unaryOperator(); - this.state = 296; - this.expression(0); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public arrayAccess(): ArrayAccessContext { - const localctx: ArrayAccessContext = new ArrayAccessContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 76, JackParser.RULE_arrayAccess); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 298; - this.varName(); - this.state = 299; - this.match(JackParser.LBRACKET); - this.state = 300; - this.expression(0); - this.state = 301; - this.match(JackParser.RBRACKET); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public constant(): ConstantContext { - const localctx: ConstantContext = new ConstantContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 78, JackParser.RULE_constant); - try { - this.state = 308; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case 40: - this.enterOuterAlt(localctx, 1); - { - this.state = 303; - this.match(JackParser.INTEGER_LITERAL); - } - break; - case 46: - this.enterOuterAlt(localctx, 2); - { - this.state = 304; - this.match(JackParser.STRING_LITERAL); - } - break; - case 41: - case 42: - this.enterOuterAlt(localctx, 3); - { - this.state = 305; - this.booleanLiteral(); - } - break; - case 43: - this.enterOuterAlt(localctx, 4); - { - this.state = 306; - this.match(JackParser.NULL_LITERAL); - } - break; - case 44: - this.enterOuterAlt(localctx, 5); - { - this.state = 307; - this.match(JackParser.THIS_LITERAL); - } - break; - default: - throw new NoViableAltException(this); - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public booleanLiteral(): BooleanLiteralContext { - const localctx: BooleanLiteralContext = new BooleanLiteralContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 80, JackParser.RULE_booleanLiteral); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 310; - _la = this._input.LA(1); - if (!(_la === 41 || _la === 42)) { - this._errHandler.recoverInline(this); - } else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public unaryOperator(): UnaryOperatorContext { - const localctx: UnaryOperatorContext = new UnaryOperatorContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 82, JackParser.RULE_unaryOperator); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 312; - _la = this._input.LA(1); - if (!(_la === 29 || _la === 34)) { - this._errHandler.recoverInline(this); - } else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public binaryOperator(): BinaryOperatorContext { - const localctx: BinaryOperatorContext = new BinaryOperatorContext( - this, - this._ctx, - this.state, - ); - this.enterRule(localctx, 84, JackParser.RULE_binaryOperator); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 314; - _la = this._input.LA(1); - if (!(((_la - 27) & ~0x1f) === 0 && ((1 << (_la - 27)) & 895) !== 0)) { - this._errHandler.recoverInline(this); - } else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - - public sempred( - localctx: RuleContext, - ruleIndex: number, - predIndex: number, - ): boolean { - switch (ruleIndex) { - case 35: - return this.expression_sempred( - localctx as ExpressionContext, - predIndex, - ); - } - return true; - } - private expression_sempred( - localctx: ExpressionContext, - predIndex: number, - ): boolean { - switch (predIndex) { - case 0: - return this.precpred(this._ctx, 2); - } - return true; - } - - public static readonly _serializedATN: number[] = [ - 4, 1, 47, 317, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, - 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, - 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, - 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, - 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, - 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, - 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, - 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 1, 0, 1, 0, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 94, 8, 1, 10, 1, 12, 1, 97, 9, 1, 1, 1, 5, - 1, 100, 8, 1, 10, 1, 12, 1, 103, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 117, 8, 4, 10, 4, 12, 4, 120, 9, - 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, - 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 11, 1, 11, 1, - 12, 1, 12, 1, 12, 5, 12, 147, 8, 12, 10, 12, 12, 12, 150, 9, 12, 3, 12, 152, - 8, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 161, 8, 15, - 10, 15, 12, 15, 164, 9, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, - 1, 17, 1, 17, 1, 17, 5, 17, 176, 8, 17, 10, 17, 12, 17, 179, 9, 17, 1, 17, - 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 5, 20, 188, 8, 20, 10, 20, 12, 20, - 191, 9, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 198, 8, 21, 1, 22, 1, - 22, 1, 22, 3, 22, 203, 8, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, - 24, 1, 24, 3, 24, 213, 8, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, - 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, - 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, - 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 251, 8, 32, 1, - 32, 3, 32, 254, 8, 32, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 260, 8, 33, 1, 33, - 1, 33, 1, 34, 1, 34, 1, 34, 5, 34, 267, 8, 34, 10, 34, 12, 34, 270, 9, 34, - 3, 34, 272, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 3, 35, - 281, 8, 35, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 287, 8, 35, 10, 35, 12, 35, - 290, 9, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, - 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 309, 8, 39, - 1, 40, 1, 40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 0, 1, 70, 43, 0, 2, 4, 6, - 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, - 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, - 84, 0, 6, 1, 0, 5, 6, 1, 0, 2, 4, 2, 0, 8, 10, 45, 45, 1, 0, 41, 42, 2, 0, - 29, 29, 34, 34, 2, 0, 27, 33, 35, 36, 303, 0, 86, 1, 0, 0, 0, 2, 89, 1, 0, - 0, 0, 4, 106, 1, 0, 0, 0, 6, 108, 1, 0, 0, 0, 8, 112, 1, 0, 0, 0, 10, 121, - 1, 0, 0, 0, 12, 123, 1, 0, 0, 0, 14, 126, 1, 0, 0, 0, 16, 128, 1, 0, 0, 0, - 18, 135, 1, 0, 0, 0, 20, 139, 1, 0, 0, 0, 22, 141, 1, 0, 0, 0, 24, 151, 1, - 0, 0, 0, 26, 153, 1, 0, 0, 0, 28, 156, 1, 0, 0, 0, 30, 158, 1, 0, 0, 0, 32, - 168, 1, 0, 0, 0, 34, 170, 1, 0, 0, 0, 36, 182, 1, 0, 0, 0, 38, 184, 1, 0, 0, - 0, 40, 189, 1, 0, 0, 0, 42, 197, 1, 0, 0, 0, 44, 199, 1, 0, 0, 0, 46, 208, - 1, 0, 0, 0, 48, 210, 1, 0, 0, 0, 50, 214, 1, 0, 0, 0, 52, 222, 1, 0, 0, 0, - 54, 224, 1, 0, 0, 0, 56, 229, 1, 0, 0, 0, 58, 237, 1, 0, 0, 0, 60, 239, 1, - 0, 0, 0, 62, 243, 1, 0, 0, 0, 64, 253, 1, 0, 0, 0, 66, 257, 1, 0, 0, 0, 68, - 271, 1, 0, 0, 0, 70, 280, 1, 0, 0, 0, 72, 291, 1, 0, 0, 0, 74, 295, 1, 0, 0, - 0, 76, 298, 1, 0, 0, 0, 78, 308, 1, 0, 0, 0, 80, 310, 1, 0, 0, 0, 82, 312, - 1, 0, 0, 0, 84, 314, 1, 0, 0, 0, 86, 87, 3, 2, 1, 0, 87, 88, 5, 0, 0, 1, 88, - 1, 1, 0, 0, 0, 89, 90, 5, 1, 0, 0, 90, 91, 3, 4, 2, 0, 91, 95, 5, 18, 0, 0, - 92, 94, 3, 6, 3, 0, 93, 92, 1, 0, 0, 0, 94, 97, 1, 0, 0, 0, 95, 93, 1, 0, 0, - 0, 95, 96, 1, 0, 0, 0, 96, 101, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 98, 100, 3, - 12, 6, 0, 99, 98, 1, 0, 0, 0, 100, 103, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, - 101, 102, 1, 0, 0, 0, 102, 104, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 104, 105, - 3, 32, 16, 0, 105, 3, 1, 0, 0, 0, 106, 107, 5, 45, 0, 0, 107, 5, 1, 0, 0, 0, - 108, 109, 7, 0, 0, 0, 109, 110, 3, 8, 4, 0, 110, 111, 5, 26, 0, 0, 111, 7, - 1, 0, 0, 0, 112, 113, 3, 22, 11, 0, 113, 118, 3, 10, 5, 0, 114, 115, 5, 25, - 0, 0, 115, 117, 3, 10, 5, 0, 116, 114, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, - 118, 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 9, 1, 0, 0, 0, 120, 118, 1, - 0, 0, 0, 121, 122, 5, 45, 0, 0, 122, 11, 1, 0, 0, 0, 123, 124, 3, 14, 7, 0, - 124, 125, 3, 16, 8, 0, 125, 13, 1, 0, 0, 0, 126, 127, 7, 1, 0, 0, 127, 15, - 1, 0, 0, 0, 128, 129, 3, 20, 10, 0, 129, 130, 3, 18, 9, 0, 130, 131, 5, 20, - 0, 0, 131, 132, 3, 24, 12, 0, 132, 133, 5, 21, 0, 0, 133, 134, 3, 30, 15, 0, - 134, 17, 1, 0, 0, 0, 135, 136, 5, 45, 0, 0, 136, 19, 1, 0, 0, 0, 137, 140, - 3, 22, 11, 0, 138, 140, 5, 11, 0, 0, 139, 137, 1, 0, 0, 0, 139, 138, 1, 0, - 0, 0, 140, 21, 1, 0, 0, 0, 141, 142, 7, 2, 0, 0, 142, 23, 1, 0, 0, 0, 143, - 148, 3, 26, 13, 0, 144, 145, 5, 25, 0, 0, 145, 147, 3, 26, 13, 0, 146, 144, - 1, 0, 0, 0, 147, 150, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 148, 149, 1, 0, 0, - 0, 149, 152, 1, 0, 0, 0, 150, 148, 1, 0, 0, 0, 151, 143, 1, 0, 0, 0, 151, - 152, 1, 0, 0, 0, 152, 25, 1, 0, 0, 0, 153, 154, 3, 22, 11, 0, 154, 155, 3, - 28, 14, 0, 155, 27, 1, 0, 0, 0, 156, 157, 5, 45, 0, 0, 157, 29, 1, 0, 0, 0, - 158, 162, 5, 18, 0, 0, 159, 161, 3, 34, 17, 0, 160, 159, 1, 0, 0, 0, 161, - 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 165, 1, 0, - 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 3, 40, 20, 0, 166, 167, 3, 32, 16, 0, - 167, 31, 1, 0, 0, 0, 168, 169, 5, 19, 0, 0, 169, 33, 1, 0, 0, 0, 170, 171, - 5, 7, 0, 0, 171, 172, 3, 22, 11, 0, 172, 177, 3, 36, 18, 0, 173, 174, 5, 25, - 0, 0, 174, 176, 3, 36, 18, 0, 175, 173, 1, 0, 0, 0, 176, 179, 1, 0, 0, 0, - 177, 175, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 180, 1, 0, 0, 0, 179, 177, - 1, 0, 0, 0, 180, 181, 5, 26, 0, 0, 181, 35, 1, 0, 0, 0, 182, 183, 5, 45, 0, - 0, 183, 37, 1, 0, 0, 0, 184, 185, 5, 45, 0, 0, 185, 39, 1, 0, 0, 0, 186, - 188, 3, 42, 21, 0, 187, 186, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, - 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 41, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, - 192, 198, 3, 44, 22, 0, 193, 198, 3, 48, 24, 0, 194, 198, 3, 56, 28, 0, 195, - 198, 3, 60, 30, 0, 196, 198, 3, 66, 33, 0, 197, 192, 1, 0, 0, 0, 197, 193, - 1, 0, 0, 0, 197, 194, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 197, 196, 1, 0, 0, - 0, 198, 43, 1, 0, 0, 0, 199, 202, 5, 12, 0, 0, 200, 203, 3, 38, 19, 0, 201, - 203, 3, 76, 38, 0, 202, 200, 1, 0, 0, 0, 202, 201, 1, 0, 0, 0, 203, 204, 1, - 0, 0, 0, 204, 205, 3, 46, 23, 0, 205, 206, 3, 70, 35, 0, 206, 207, 5, 26, 0, - 0, 207, 45, 1, 0, 0, 0, 208, 209, 5, 27, 0, 0, 209, 47, 1, 0, 0, 0, 210, - 212, 3, 50, 25, 0, 211, 213, 3, 54, 27, 0, 212, 211, 1, 0, 0, 0, 212, 213, - 1, 0, 0, 0, 213, 49, 1, 0, 0, 0, 214, 215, 5, 14, 0, 0, 215, 216, 5, 20, 0, - 0, 216, 217, 3, 52, 26, 0, 217, 218, 5, 21, 0, 0, 218, 219, 5, 18, 0, 0, - 219, 220, 3, 40, 20, 0, 220, 221, 3, 32, 16, 0, 221, 51, 1, 0, 0, 0, 222, - 223, 3, 70, 35, 0, 223, 53, 1, 0, 0, 0, 224, 225, 5, 15, 0, 0, 225, 226, 5, - 18, 0, 0, 226, 227, 3, 40, 20, 0, 227, 228, 3, 32, 16, 0, 228, 55, 1, 0, 0, - 0, 229, 230, 5, 16, 0, 0, 230, 231, 5, 20, 0, 0, 231, 232, 3, 58, 29, 0, - 232, 233, 5, 21, 0, 0, 233, 234, 5, 18, 0, 0, 234, 235, 3, 40, 20, 0, 235, - 236, 3, 32, 16, 0, 236, 57, 1, 0, 0, 0, 237, 238, 3, 70, 35, 0, 238, 59, 1, - 0, 0, 0, 239, 240, 5, 13, 0, 0, 240, 241, 3, 62, 31, 0, 241, 242, 5, 26, 0, - 0, 242, 61, 1, 0, 0, 0, 243, 244, 3, 64, 32, 0, 244, 245, 5, 20, 0, 0, 245, - 246, 3, 68, 34, 0, 246, 247, 5, 21, 0, 0, 247, 63, 1, 0, 0, 0, 248, 251, 3, - 4, 2, 0, 249, 251, 5, 44, 0, 0, 250, 248, 1, 0, 0, 0, 250, 249, 1, 0, 0, 0, - 251, 252, 1, 0, 0, 0, 252, 254, 5, 24, 0, 0, 253, 250, 1, 0, 0, 0, 253, 254, - 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 256, 3, 18, 9, 0, 256, 65, 1, 0, 0, - 0, 257, 259, 5, 17, 0, 0, 258, 260, 3, 70, 35, 0, 259, 258, 1, 0, 0, 0, 259, - 260, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 262, 5, 26, 0, 0, 262, 67, 1, 0, - 0, 0, 263, 268, 3, 70, 35, 0, 264, 265, 5, 25, 0, 0, 265, 267, 3, 70, 35, 0, - 266, 264, 1, 0, 0, 0, 267, 270, 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 268, 269, - 1, 0, 0, 0, 269, 272, 1, 0, 0, 0, 270, 268, 1, 0, 0, 0, 271, 263, 1, 0, 0, - 0, 271, 272, 1, 0, 0, 0, 272, 69, 1, 0, 0, 0, 273, 274, 6, 35, -1, 0, 274, - 281, 3, 78, 39, 0, 275, 281, 3, 38, 19, 0, 276, 281, 3, 62, 31, 0, 277, 281, - 3, 76, 38, 0, 278, 281, 3, 74, 37, 0, 279, 281, 3, 72, 36, 0, 280, 273, 1, - 0, 0, 0, 280, 275, 1, 0, 0, 0, 280, 276, 1, 0, 0, 0, 280, 277, 1, 0, 0, 0, - 280, 278, 1, 0, 0, 0, 280, 279, 1, 0, 0, 0, 281, 288, 1, 0, 0, 0, 282, 283, - 10, 2, 0, 0, 283, 284, 3, 84, 42, 0, 284, 285, 3, 70, 35, 3, 285, 287, 1, 0, - 0, 0, 286, 282, 1, 0, 0, 0, 287, 290, 1, 0, 0, 0, 288, 286, 1, 0, 0, 0, 288, - 289, 1, 0, 0, 0, 289, 71, 1, 0, 0, 0, 290, 288, 1, 0, 0, 0, 291, 292, 5, 20, - 0, 0, 292, 293, 3, 70, 35, 0, 293, 294, 5, 21, 0, 0, 294, 73, 1, 0, 0, 0, - 295, 296, 3, 82, 41, 0, 296, 297, 3, 70, 35, 0, 297, 75, 1, 0, 0, 0, 298, - 299, 3, 38, 19, 0, 299, 300, 5, 22, 0, 0, 300, 301, 3, 70, 35, 0, 301, 302, - 5, 23, 0, 0, 302, 77, 1, 0, 0, 0, 303, 309, 5, 40, 0, 0, 304, 309, 5, 46, 0, - 0, 305, 309, 3, 80, 40, 0, 306, 309, 5, 43, 0, 0, 307, 309, 5, 44, 0, 0, - 308, 303, 1, 0, 0, 0, 308, 304, 1, 0, 0, 0, 308, 305, 1, 0, 0, 0, 308, 306, - 1, 0, 0, 0, 308, 307, 1, 0, 0, 0, 309, 79, 1, 0, 0, 0, 310, 311, 7, 3, 0, 0, - 311, 81, 1, 0, 0, 0, 312, 313, 7, 4, 0, 0, 313, 83, 1, 0, 0, 0, 314, 315, 7, - 5, 0, 0, 315, 85, 1, 0, 0, 0, 20, 95, 101, 118, 139, 148, 151, 162, 177, - 189, 197, 202, 212, 250, 253, 259, 268, 271, 280, 288, 308, - ]; - - private static __ATN: ATN; - public static get _ATN(): ATN { - if (!JackParser.__ATN) { - JackParser.__ATN = new ATNDeserializer().deserialize( - JackParser._serializedATN, - ); - } - - return JackParser.__ATN; - } - - static DecisionsToDFA = JackParser._ATN.decisionToState.map( - (ds: DecisionState, index: number) => new DFA(ds, index), - ); + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WHITESPACE = 37; + public static readonly BLOCK_COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly TRUE = 41; + public static readonly FALSE = 42; + public static readonly NULL_LITERAL = 43; + public static readonly THIS_LITERAL = 44; + public static readonly IDENTIFIER = 45; + public static readonly STRING_LITERAL = 46; + public static override readonly EOF = Token.EOF; + public static readonly RULE_program = 0; + public static readonly RULE_classDeclaration = 1; + public static readonly RULE_className = 2; + public static readonly RULE_classVarDec = 3; + public static readonly RULE_fieldList = 4; + public static readonly RULE_fieldName = 5; + public static readonly RULE_subroutineDeclaration = 6; + public static readonly RULE_subroutineType = 7; + public static readonly RULE_subroutineDecWithoutType = 8; + public static readonly RULE_subroutineName = 9; + public static readonly RULE_subroutineReturnType = 10; + public static readonly RULE_varType = 11; + public static readonly RULE_parameterList = 12; + public static readonly RULE_parameter = 13; + public static readonly RULE_parameterName = 14; + public static readonly RULE_subroutineBody = 15; + public static readonly RULE_rBrace = 16; + public static readonly RULE_varDeclaration = 17; + public static readonly RULE_varNameInDeclaration = 18; + public static readonly RULE_statements = 19; + public static readonly RULE_statement = 20; + public static readonly RULE_letStatement = 21; + public static readonly RULE_equals = 22; + public static readonly RULE_ifElseStatement = 23; + public static readonly RULE_ifStatement = 24; + public static readonly RULE_ifExpression = 25; + public static readonly RULE_elseStatement = 26; + public static readonly RULE_whileStatement = 27; + public static readonly RULE_whileExpression = 28; + public static readonly RULE_doStatement = 29; + public static readonly RULE_subroutineCall = 30; + public static readonly RULE_subroutineId = 31; + public static readonly RULE_returnStatement = 32; + public static readonly RULE_expressionList = 33; + public static readonly RULE_expression = 34; + public static readonly RULE_constant = 35; + public static readonly RULE_varName = 36; + public static readonly RULE_arrayAccess = 37; + public static readonly RULE_unaryOperation = 38; + public static readonly RULE_groupedExpression = 39; + public static readonly RULE_booleanLiteral = 40; + public static readonly RULE_unaryOperator = 41; + public static readonly RULE_binaryOperator = 42; + public static readonly literalNames: (string | null)[] = [ null, "'class'", + "'constructor'", + "'function'", + "'method'", + "'field'", "'static'", + "'var'", "'int'", + "'char'", "'boolean'", + "'void'", "'let'", + "'do'", "'if'", + "'else'", "'while'", + "'return'", + "'{'", "'}'", + "'('", "')'", + "'['", "']'", + "'.'", "','", + "';'", "'='", + "'+'", "'-'", + "'*'", "'/'", + "'&'", "'|'", + "'~'", "'<'", + "'>'", null, + null, null, + null, "'true'", + "'false'", "'null'", + "'this'" ]; + public static readonly symbolicNames: (string | null)[] = [ null, "CLASS", + "CONSTRUCTOR", + "FUNCTION", + "METHOD", "FIELD", + "STATIC", "VAR", + "INT", "CHAR", + "BOOLEAN", + "VOID", "LET", + "DO", "IF", + "ELSE", "WHILE", + "RETURN", "LBRACE", + "RBRACE", "LPAREN", + "RPAREN", "LBRACKET", + "RBRACKET", + "DOT", "COMMA", + "SEMICOLON", + "EQUALS", "PLUS", + "MINUS", "MUL", + "DIV", "AND", + "OR", "TILDE", + "LESS_THAN", + "GREATER_THAN", + "WHITESPACE", + "BLOCK_COMMENT", + "LINE_COMMENT", + "INTEGER_LITERAL", + "TRUE", "FALSE", + "NULL_LITERAL", + "THIS_LITERAL", + "IDENTIFIER", + "STRING_LITERAL" ]; + // tslint:disable:no-trailing-whitespace + public static readonly ruleNames: string[] = [ + "program", "classDeclaration", "className", "classVarDec", "fieldList", + "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", + "subroutineName", "subroutineReturnType", "varType", "parameterList", + "parameter", "parameterName", "subroutineBody", "rBrace", "varDeclaration", + "varNameInDeclaration", "statements", "statement", "letStatement", "equals", + "ifElseStatement", "ifStatement", "ifExpression", "elseStatement", "whileStatement", + "whileExpression", "doStatement", "subroutineCall", "subroutineId", "returnStatement", + "expressionList", "expression", "constant", "varName", "arrayAccess", + "unaryOperation", "groupedExpression", "booleanLiteral", "unaryOperator", + "binaryOperator", + ]; + public get grammarFileName(): string { return "JackParser.g4"; } + public get literalNames(): (string | null)[] { return JackParser.literalNames; } + public get symbolicNames(): (string | null)[] { return JackParser.symbolicNames; } + public get ruleNames(): string[] { return JackParser.ruleNames; } + public get serializedATN(): number[] { return JackParser._serializedATN; } + + protected createFailedPredicateException(predicate?: string, message?: string): FailedPredicateException { + return new FailedPredicateException(this, predicate, message); + } + + constructor(input: TokenStream) { + super(input); + this._interp = new ParserATNSimulator(this, JackParser._ATN, JackParser.DecisionsToDFA, new PredictionContextCache()); + } + // @RuleVersion(0) + public program(): ProgramContext { + let localctx: ProgramContext = new ProgramContext(this, this._ctx, this.state); + this.enterRule(localctx, 0, JackParser.RULE_program); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 86; + this.classDeclaration(); + this.state = 87; + this.match(JackParser.EOF); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public classDeclaration(): ClassDeclarationContext { + let localctx: ClassDeclarationContext = new ClassDeclarationContext(this, this._ctx, this.state); + this.enterRule(localctx, 2, JackParser.RULE_classDeclaration); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 89; + this.match(JackParser.CLASS); + this.state = 90; + this.className(); + this.state = 91; + this.match(JackParser.LBRACE); + this.state = 95; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===5 || _la===6) { + { + { + this.state = 92; + this.classVarDec(); + } + } + this.state = 97; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 28) !== 0)) { + { + { + this.state = 98; + this.subroutineDeclaration(); + } + } + this.state = 103; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 104; + this.rBrace(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public className(): ClassNameContext { + let localctx: ClassNameContext = new ClassNameContext(this, this._ctx, this.state); + this.enterRule(localctx, 4, JackParser.RULE_className); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 106; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public classVarDec(): ClassVarDecContext { + let localctx: ClassVarDecContext = new ClassVarDecContext(this, this._ctx, this.state); + this.enterRule(localctx, 6, JackParser.RULE_classVarDec); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 108; + _la = this._input.LA(1); + if(!(_la===5 || _la===6)) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 109; + this.fieldList(); + this.state = 110; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public fieldList(): FieldListContext { + let localctx: FieldListContext = new FieldListContext(this, this._ctx, this.state); + this.enterRule(localctx, 8, JackParser.RULE_fieldList); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 112; + this.varType(); + this.state = 113; + this.fieldName(); + this.state = 118; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===25) { + { + { + this.state = 114; + this.match(JackParser.COMMA); + this.state = 115; + this.fieldName(); + } + } + this.state = 120; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public fieldName(): FieldNameContext { + let localctx: FieldNameContext = new FieldNameContext(this, this._ctx, this.state); + this.enterRule(localctx, 10, JackParser.RULE_fieldName); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 121; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineDeclaration(): SubroutineDeclarationContext { + let localctx: SubroutineDeclarationContext = new SubroutineDeclarationContext(this, this._ctx, this.state); + this.enterRule(localctx, 12, JackParser.RULE_subroutineDeclaration); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 123; + this.subroutineType(); + this.state = 124; + this.subroutineDecWithoutType(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineType(): SubroutineTypeContext { + let localctx: SubroutineTypeContext = new SubroutineTypeContext(this, this._ctx, this.state); + this.enterRule(localctx, 14, JackParser.RULE_subroutineType); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 126; + _la = this._input.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 28) !== 0))) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + let localctx: SubroutineDecWithoutTypeContext = new SubroutineDecWithoutTypeContext(this, this._ctx, this.state); + this.enterRule(localctx, 16, JackParser.RULE_subroutineDecWithoutType); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 128; + this.subroutineReturnType(); + this.state = 129; + this.subroutineName(); + this.state = 130; + this.match(JackParser.LPAREN); + this.state = 131; + this.parameterList(); + this.state = 132; + this.match(JackParser.RPAREN); + this.state = 133; + this.subroutineBody(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineName(): SubroutineNameContext { + let localctx: SubroutineNameContext = new SubroutineNameContext(this, this._ctx, this.state); + this.enterRule(localctx, 18, JackParser.RULE_subroutineName); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 135; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineReturnType(): SubroutineReturnTypeContext { + let localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this, this._ctx, this.state); + this.enterRule(localctx, 20, JackParser.RULE_subroutineReturnType); + try { + this.state = 139; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 8: + case 9: + case 10: + case 45: + this.enterOuterAlt(localctx, 1); + { + this.state = 137; + this.varType(); + } + break; + case 11: + this.enterOuterAlt(localctx, 2); + { + this.state = 138; + this.match(JackParser.VOID); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public varType(): VarTypeContext { + let localctx: VarTypeContext = new VarTypeContext(this, this._ctx, this.state); + this.enterRule(localctx, 22, JackParser.RULE_varType); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 141; + _la = this._input.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 1792) !== 0) || _la===45)) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public parameterList(): ParameterListContext { + let localctx: ParameterListContext = new ParameterListContext(this, this._ctx, this.state); + this.enterRule(localctx, 24, JackParser.RULE_parameterList); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 151; + this._errHandler.sync(this); + _la = this._input.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 1792) !== 0) || _la===45) { + { + this.state = 143; + this.parameter(); + this.state = 148; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===25) { + { + { + this.state = 144; + this.match(JackParser.COMMA); + this.state = 145; + this.parameter(); + } + } + this.state = 150; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public parameter(): ParameterContext { + let localctx: ParameterContext = new ParameterContext(this, this._ctx, this.state); + this.enterRule(localctx, 26, JackParser.RULE_parameter); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 153; + this.varType(); + this.state = 154; + this.parameterName(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public parameterName(): ParameterNameContext { + let localctx: ParameterNameContext = new ParameterNameContext(this, this._ctx, this.state); + this.enterRule(localctx, 28, JackParser.RULE_parameterName); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 156; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineBody(): SubroutineBodyContext { + let localctx: SubroutineBodyContext = new SubroutineBodyContext(this, this._ctx, this.state); + this.enterRule(localctx, 30, JackParser.RULE_subroutineBody); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 158; + this.match(JackParser.LBRACE); + this.state = 162; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===7) { + { + { + this.state = 159; + this.varDeclaration(); + } + } + this.state = 164; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 165; + this.statements(); + this.state = 166; + this.rBrace(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public rBrace(): RBraceContext { + let localctx: RBraceContext = new RBraceContext(this, this._ctx, this.state); + this.enterRule(localctx, 32, JackParser.RULE_rBrace); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 168; + this.match(JackParser.RBRACE); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public varDeclaration(): VarDeclarationContext { + let localctx: VarDeclarationContext = new VarDeclarationContext(this, this._ctx, this.state); + this.enterRule(localctx, 34, JackParser.RULE_varDeclaration); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 170; + this.match(JackParser.VAR); + this.state = 171; + this.varType(); + this.state = 172; + this.varNameInDeclaration(); + this.state = 177; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===25) { + { + { + this.state = 173; + this.match(JackParser.COMMA); + this.state = 174; + this.varNameInDeclaration(); + } + } + this.state = 179; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 180; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public varNameInDeclaration(): VarNameInDeclarationContext { + let localctx: VarNameInDeclarationContext = new VarNameInDeclarationContext(this, this._ctx, this.state); + this.enterRule(localctx, 36, JackParser.RULE_varNameInDeclaration); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 182; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public statements(): StatementsContext { + let localctx: StatementsContext = new StatementsContext(this, this._ctx, this.state); + this.enterRule(localctx, 38, JackParser.RULE_statements); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 187; + this._errHandler.sync(this); + _la = this._input.LA(1); + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 225280) !== 0)) { + { + { + this.state = 184; + this.statement(); + } + } + this.state = 189; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public statement(): StatementContext { + let localctx: StatementContext = new StatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 40, JackParser.RULE_statement); + try { + this.state = 195; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 12: + this.enterOuterAlt(localctx, 1); + { + this.state = 190; + this.letStatement(); + } + break; + case 14: + this.enterOuterAlt(localctx, 2); + { + this.state = 191; + this.ifElseStatement(); + } + break; + case 16: + this.enterOuterAlt(localctx, 3); + { + this.state = 192; + this.whileStatement(); + } + break; + case 13: + this.enterOuterAlt(localctx, 4); + { + this.state = 193; + this.doStatement(); + } + break; + case 17: + this.enterOuterAlt(localctx, 5); + { + this.state = 194; + this.returnStatement(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public letStatement(): LetStatementContext { + let localctx: LetStatementContext = new LetStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 42, JackParser.RULE_letStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 197; + this.match(JackParser.LET); + this.state = 200; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 10, this._ctx) ) { + case 1: + { + this.state = 198; + this.varName(); + } + break; + case 2: + { + this.state = 199; + this.arrayAccess(); + } + break; + } + this.state = 202; + this.equals(); + this.state = 203; + this.expression(0); + this.state = 204; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public equals(): EqualsContext { + let localctx: EqualsContext = new EqualsContext(this, this._ctx, this.state); + this.enterRule(localctx, 44, JackParser.RULE_equals); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 206; + this.match(JackParser.EQUALS); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ifElseStatement(): IfElseStatementContext { + let localctx: IfElseStatementContext = new IfElseStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 46, JackParser.RULE_ifElseStatement); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 208; + this.ifStatement(); + this.state = 210; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===15) { + { + this.state = 209; + this.elseStatement(); + } + } + + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ifStatement(): IfStatementContext { + let localctx: IfStatementContext = new IfStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 48, JackParser.RULE_ifStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 212; + this.match(JackParser.IF); + this.state = 213; + this.match(JackParser.LPAREN); + this.state = 214; + this.ifExpression(); + this.state = 215; + this.match(JackParser.RPAREN); + this.state = 216; + this.match(JackParser.LBRACE); + this.state = 217; + this.statements(); + this.state = 218; + this.rBrace(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public ifExpression(): IfExpressionContext { + let localctx: IfExpressionContext = new IfExpressionContext(this, this._ctx, this.state); + this.enterRule(localctx, 50, JackParser.RULE_ifExpression); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 220; + this.expression(0); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public elseStatement(): ElseStatementContext { + let localctx: ElseStatementContext = new ElseStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 52, JackParser.RULE_elseStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 222; + this.match(JackParser.ELSE); + this.state = 223; + this.match(JackParser.LBRACE); + this.state = 224; + this.statements(); + this.state = 225; + this.rBrace(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public whileStatement(): WhileStatementContext { + let localctx: WhileStatementContext = new WhileStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 54, JackParser.RULE_whileStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 227; + this.match(JackParser.WHILE); + this.state = 228; + this.match(JackParser.LPAREN); + this.state = 229; + this.whileExpression(); + this.state = 230; + this.match(JackParser.RPAREN); + this.state = 231; + this.match(JackParser.LBRACE); + this.state = 232; + this.statements(); + this.state = 233; + this.rBrace(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public whileExpression(): WhileExpressionContext { + let localctx: WhileExpressionContext = new WhileExpressionContext(this, this._ctx, this.state); + this.enterRule(localctx, 56, JackParser.RULE_whileExpression); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 235; + this.expression(0); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public doStatement(): DoStatementContext { + let localctx: DoStatementContext = new DoStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 58, JackParser.RULE_doStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 237; + this.match(JackParser.DO); + this.state = 238; + this.subroutineCall(); + this.state = 239; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineCall(): SubroutineCallContext { + let localctx: SubroutineCallContext = new SubroutineCallContext(this, this._ctx, this.state); + this.enterRule(localctx, 60, JackParser.RULE_subroutineCall); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 241; + this.subroutineId(); + this.state = 242; + this.match(JackParser.LPAREN); + this.state = 243; + this.expressionList(); + this.state = 244; + this.match(JackParser.RPAREN); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public subroutineId(): SubroutineIdContext { + let localctx: SubroutineIdContext = new SubroutineIdContext(this, this._ctx, this.state); + this.enterRule(localctx, 62, JackParser.RULE_subroutineId); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 251; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 13, this._ctx) ) { + case 1: + { + this.state = 248; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 45: + { + this.state = 246; + this.className(); + } + break; + case 44: + { + this.state = 247; + this.match(JackParser.THIS_LITERAL); + } + break; + default: + throw new NoViableAltException(this); + } + this.state = 250; + this.match(JackParser.DOT); + } + break; + } + this.state = 253; + this.subroutineName(); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public returnStatement(): ReturnStatementContext { + let localctx: ReturnStatementContext = new ReturnStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 64, JackParser.RULE_returnStatement); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 255; + this.match(JackParser.RETURN); + this.state = 257; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 133186049) !== 0)) { + { + this.state = 256; + this.expression(0); + } + } + + this.state = 259; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public expressionList(): ExpressionListContext { + let localctx: ExpressionListContext = new ExpressionListContext(this, this._ctx, this.state); + this.enterRule(localctx, 66, JackParser.RULE_expressionList); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 269; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 133186049) !== 0)) { + { + this.state = 261; + this.expression(0); + this.state = 266; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===25) { + { + { + this.state = 262; + this.match(JackParser.COMMA); + this.state = 263; + this.expression(0); + } + } + this.state = 268; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + } + } + + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + + public expression(): ExpressionContext; + public expression(_p: number): ExpressionContext; + // @RuleVersion(0) + public expression(_p?: number): ExpressionContext { + if (_p === undefined) { + _p = 0; + } + + let _parentctx: ParserRuleContext = this._ctx; + let _parentState: number = this.state; + let localctx: ExpressionContext = new ExpressionContext(this, this._ctx, _parentState); + let _prevctx: ExpressionContext = localctx; + let _startState: number = 68; + this.enterRecursionRule(localctx, 68, JackParser.RULE_expression, _p); + try { + let _alt: number; + this.enterOuterAlt(localctx, 1); + { + this.state = 278; + this._errHandler.sync(this); + switch ( this._interp.adaptivePredict(this._input, 17, this._ctx) ) { + case 1: + { + this.state = 272; + this.constant(); + } + break; + case 2: + { + this.state = 273; + this.varName(); + } + break; + case 3: + { + this.state = 274; + this.subroutineCall(); + } + break; + case 4: + { + this.state = 275; + this.arrayAccess(); + } + break; + case 5: + { + this.state = 276; + this.unaryOperation(); + } + break; + case 6: + { + this.state = 277; + this.groupedExpression(); + } + break; + } + this._ctx.stop = this._input.LT(-1); + this.state = 286; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 18, this._ctx); + while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners != null) { + this.triggerExitRuleEvent(); + } + _prevctx = localctx; + { + { + localctx = new ExpressionContext(this, _parentctx, _parentState); + this.pushNewRecursionContext(localctx, _startState, JackParser.RULE_expression); + this.state = 280; + if (!(this.precpred(this._ctx, 2))) { + throw this.createFailedPredicateException("this.precpred(this._ctx, 2)"); + } + this.state = 281; + this.binaryOperator(); + this.state = 282; + this.expression(3); + } + } + } + this.state = 288; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 18, this._ctx); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.unrollRecursionContexts(_parentctx); + } + return localctx; + } + // @RuleVersion(0) + public constant(): ConstantContext { + let localctx: ConstantContext = new ConstantContext(this, this._ctx, this.state); + this.enterRule(localctx, 70, JackParser.RULE_constant); + try { + this.state = 294; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 40: + this.enterOuterAlt(localctx, 1); + { + this.state = 289; + this.match(JackParser.INTEGER_LITERAL); + } + break; + case 46: + this.enterOuterAlt(localctx, 2); + { + this.state = 290; + this.match(JackParser.STRING_LITERAL); + } + break; + case 41: + case 42: + this.enterOuterAlt(localctx, 3); + { + this.state = 291; + this.booleanLiteral(); + } + break; + case 43: + this.enterOuterAlt(localctx, 4); + { + this.state = 292; + this.match(JackParser.NULL_LITERAL); + } + break; + case 44: + this.enterOuterAlt(localctx, 5); + { + this.state = 293; + this.match(JackParser.THIS_LITERAL); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public varName(): VarNameContext { + let localctx: VarNameContext = new VarNameContext(this, this._ctx, this.state); + this.enterRule(localctx, 72, JackParser.RULE_varName); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 296; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public arrayAccess(): ArrayAccessContext { + let localctx: ArrayAccessContext = new ArrayAccessContext(this, this._ctx, this.state); + this.enterRule(localctx, 74, JackParser.RULE_arrayAccess); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 298; + this.varName(); + this.state = 299; + this.match(JackParser.LBRACKET); + this.state = 300; + this.expression(0); + this.state = 301; + this.match(JackParser.RBRACKET); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public unaryOperation(): UnaryOperationContext { + let localctx: UnaryOperationContext = new UnaryOperationContext(this, this._ctx, this.state); + this.enterRule(localctx, 76, JackParser.RULE_unaryOperation); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 303; + this.unaryOperator(); + this.state = 304; + this.expression(0); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public groupedExpression(): GroupedExpressionContext { + let localctx: GroupedExpressionContext = new GroupedExpressionContext(this, this._ctx, this.state); + this.enterRule(localctx, 78, JackParser.RULE_groupedExpression); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 306; + this.match(JackParser.LPAREN); + this.state = 307; + this.expression(0); + this.state = 308; + this.match(JackParser.RPAREN); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public booleanLiteral(): BooleanLiteralContext { + let localctx: BooleanLiteralContext = new BooleanLiteralContext(this, this._ctx, this.state); + this.enterRule(localctx, 80, JackParser.RULE_booleanLiteral); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 310; + _la = this._input.LA(1); + if(!(_la===41 || _la===42)) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public unaryOperator(): UnaryOperatorContext { + let localctx: UnaryOperatorContext = new UnaryOperatorContext(this, this._ctx, this.state); + this.enterRule(localctx, 82, JackParser.RULE_unaryOperator); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 312; + _la = this._input.LA(1); + if(!(_la===29 || _la===34)) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public binaryOperator(): BinaryOperatorContext { + let localctx: BinaryOperatorContext = new BinaryOperatorContext(this, this._ctx, this.state); + this.enterRule(localctx, 84, JackParser.RULE_binaryOperator); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 314; + _la = this._input.LA(1); + if(!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & 895) !== 0))) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + + public sempred(localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { + switch (ruleIndex) { + case 34: + return this.expression_sempred(localctx as ExpressionContext, predIndex); + } + return true; + } + private expression_sempred(localctx: ExpressionContext, predIndex: number): boolean { + switch (predIndex) { + case 0: + return this.precpred(this._ctx, 2); + } + return true; + } + + public static readonly _serializedATN: number[] = [4,1,46,317,2,0,7,0,2, + 1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2, + 10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17, + 7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7, + 24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31, + 2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2, + 39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,1,0,1,0,1,0,1,1,1,1,1,1,1,1,5,1,94, + 8,1,10,1,12,1,97,9,1,1,1,5,1,100,8,1,10,1,12,1,103,9,1,1,1,1,1,1,2,1,2, + 1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,5,4,117,8,4,10,4,12,4,120,9,4,1,5,1,5,1, + 6,1,6,1,6,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,10,1,10,3,10,140, + 8,10,1,11,1,11,1,12,1,12,1,12,5,12,147,8,12,10,12,12,12,150,9,12,3,12,152, + 8,12,1,13,1,13,1,13,1,14,1,14,1,15,1,15,5,15,161,8,15,10,15,12,15,164,9, + 15,1,15,1,15,1,15,1,16,1,16,1,17,1,17,1,17,1,17,1,17,5,17,176,8,17,10,17, + 12,17,179,9,17,1,17,1,17,1,18,1,18,1,19,5,19,186,8,19,10,19,12,19,189,9, + 19,1,20,1,20,1,20,1,20,1,20,3,20,196,8,20,1,21,1,21,1,21,3,21,201,8,21, + 1,21,1,21,1,21,1,21,1,22,1,22,1,23,1,23,3,23,211,8,23,1,24,1,24,1,24,1, + 24,1,24,1,24,1,24,1,24,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,27,1,27,1,27, + 1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,29,1,29,1,29,1,29,1,30,1,30,1,30,1, + 30,1,30,1,31,1,31,3,31,249,8,31,1,31,3,31,252,8,31,1,31,1,31,1,32,1,32, + 3,32,258,8,32,1,32,1,32,1,33,1,33,1,33,5,33,265,8,33,10,33,12,33,268,9, + 33,3,33,270,8,33,1,34,1,34,1,34,1,34,1,34,1,34,1,34,3,34,279,8,34,1,34, + 1,34,1,34,1,34,5,34,285,8,34,10,34,12,34,288,9,34,1,35,1,35,1,35,1,35,1, + 35,3,35,295,8,35,1,36,1,36,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,38,1,39, + 1,39,1,39,1,39,1,40,1,40,1,41,1,41,1,42,1,42,1,42,0,1,68,43,0,2,4,6,8,10, + 12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58, + 60,62,64,66,68,70,72,74,76,78,80,82,84,0,6,1,0,5,6,1,0,2,4,2,0,8,10,45, + 45,1,0,41,42,2,0,29,29,34,34,2,0,27,33,35,36,303,0,86,1,0,0,0,2,89,1,0, + 0,0,4,106,1,0,0,0,6,108,1,0,0,0,8,112,1,0,0,0,10,121,1,0,0,0,12,123,1,0, + 0,0,14,126,1,0,0,0,16,128,1,0,0,0,18,135,1,0,0,0,20,139,1,0,0,0,22,141, + 1,0,0,0,24,151,1,0,0,0,26,153,1,0,0,0,28,156,1,0,0,0,30,158,1,0,0,0,32, + 168,1,0,0,0,34,170,1,0,0,0,36,182,1,0,0,0,38,187,1,0,0,0,40,195,1,0,0,0, + 42,197,1,0,0,0,44,206,1,0,0,0,46,208,1,0,0,0,48,212,1,0,0,0,50,220,1,0, + 0,0,52,222,1,0,0,0,54,227,1,0,0,0,56,235,1,0,0,0,58,237,1,0,0,0,60,241, + 1,0,0,0,62,251,1,0,0,0,64,255,1,0,0,0,66,269,1,0,0,0,68,278,1,0,0,0,70, + 294,1,0,0,0,72,296,1,0,0,0,74,298,1,0,0,0,76,303,1,0,0,0,78,306,1,0,0,0, + 80,310,1,0,0,0,82,312,1,0,0,0,84,314,1,0,0,0,86,87,3,2,1,0,87,88,5,0,0, + 1,88,1,1,0,0,0,89,90,5,1,0,0,90,91,3,4,2,0,91,95,5,18,0,0,92,94,3,6,3,0, + 93,92,1,0,0,0,94,97,1,0,0,0,95,93,1,0,0,0,95,96,1,0,0,0,96,101,1,0,0,0, + 97,95,1,0,0,0,98,100,3,12,6,0,99,98,1,0,0,0,100,103,1,0,0,0,101,99,1,0, + 0,0,101,102,1,0,0,0,102,104,1,0,0,0,103,101,1,0,0,0,104,105,3,32,16,0,105, + 3,1,0,0,0,106,107,5,45,0,0,107,5,1,0,0,0,108,109,7,0,0,0,109,110,3,8,4, + 0,110,111,5,26,0,0,111,7,1,0,0,0,112,113,3,22,11,0,113,118,3,10,5,0,114, + 115,5,25,0,0,115,117,3,10,5,0,116,114,1,0,0,0,117,120,1,0,0,0,118,116,1, + 0,0,0,118,119,1,0,0,0,119,9,1,0,0,0,120,118,1,0,0,0,121,122,5,45,0,0,122, + 11,1,0,0,0,123,124,3,14,7,0,124,125,3,16,8,0,125,13,1,0,0,0,126,127,7,1, + 0,0,127,15,1,0,0,0,128,129,3,20,10,0,129,130,3,18,9,0,130,131,5,20,0,0, + 131,132,3,24,12,0,132,133,5,21,0,0,133,134,3,30,15,0,134,17,1,0,0,0,135, + 136,5,45,0,0,136,19,1,0,0,0,137,140,3,22,11,0,138,140,5,11,0,0,139,137, + 1,0,0,0,139,138,1,0,0,0,140,21,1,0,0,0,141,142,7,2,0,0,142,23,1,0,0,0,143, + 148,3,26,13,0,144,145,5,25,0,0,145,147,3,26,13,0,146,144,1,0,0,0,147,150, + 1,0,0,0,148,146,1,0,0,0,148,149,1,0,0,0,149,152,1,0,0,0,150,148,1,0,0,0, + 151,143,1,0,0,0,151,152,1,0,0,0,152,25,1,0,0,0,153,154,3,22,11,0,154,155, + 3,28,14,0,155,27,1,0,0,0,156,157,5,45,0,0,157,29,1,0,0,0,158,162,5,18,0, + 0,159,161,3,34,17,0,160,159,1,0,0,0,161,164,1,0,0,0,162,160,1,0,0,0,162, + 163,1,0,0,0,163,165,1,0,0,0,164,162,1,0,0,0,165,166,3,38,19,0,166,167,3, + 32,16,0,167,31,1,0,0,0,168,169,5,19,0,0,169,33,1,0,0,0,170,171,5,7,0,0, + 171,172,3,22,11,0,172,177,3,36,18,0,173,174,5,25,0,0,174,176,3,36,18,0, + 175,173,1,0,0,0,176,179,1,0,0,0,177,175,1,0,0,0,177,178,1,0,0,0,178,180, + 1,0,0,0,179,177,1,0,0,0,180,181,5,26,0,0,181,35,1,0,0,0,182,183,5,45,0, + 0,183,37,1,0,0,0,184,186,3,40,20,0,185,184,1,0,0,0,186,189,1,0,0,0,187, + 185,1,0,0,0,187,188,1,0,0,0,188,39,1,0,0,0,189,187,1,0,0,0,190,196,3,42, + 21,0,191,196,3,46,23,0,192,196,3,54,27,0,193,196,3,58,29,0,194,196,3,64, + 32,0,195,190,1,0,0,0,195,191,1,0,0,0,195,192,1,0,0,0,195,193,1,0,0,0,195, + 194,1,0,0,0,196,41,1,0,0,0,197,200,5,12,0,0,198,201,3,72,36,0,199,201,3, + 74,37,0,200,198,1,0,0,0,200,199,1,0,0,0,201,202,1,0,0,0,202,203,3,44,22, + 0,203,204,3,68,34,0,204,205,5,26,0,0,205,43,1,0,0,0,206,207,5,27,0,0,207, + 45,1,0,0,0,208,210,3,48,24,0,209,211,3,52,26,0,210,209,1,0,0,0,210,211, + 1,0,0,0,211,47,1,0,0,0,212,213,5,14,0,0,213,214,5,20,0,0,214,215,3,50,25, + 0,215,216,5,21,0,0,216,217,5,18,0,0,217,218,3,38,19,0,218,219,3,32,16,0, + 219,49,1,0,0,0,220,221,3,68,34,0,221,51,1,0,0,0,222,223,5,15,0,0,223,224, + 5,18,0,0,224,225,3,38,19,0,225,226,3,32,16,0,226,53,1,0,0,0,227,228,5,16, + 0,0,228,229,5,20,0,0,229,230,3,56,28,0,230,231,5,21,0,0,231,232,5,18,0, + 0,232,233,3,38,19,0,233,234,3,32,16,0,234,55,1,0,0,0,235,236,3,68,34,0, + 236,57,1,0,0,0,237,238,5,13,0,0,238,239,3,60,30,0,239,240,5,26,0,0,240, + 59,1,0,0,0,241,242,3,62,31,0,242,243,5,20,0,0,243,244,3,66,33,0,244,245, + 5,21,0,0,245,61,1,0,0,0,246,249,3,4,2,0,247,249,5,44,0,0,248,246,1,0,0, + 0,248,247,1,0,0,0,249,250,1,0,0,0,250,252,5,24,0,0,251,248,1,0,0,0,251, + 252,1,0,0,0,252,253,1,0,0,0,253,254,3,18,9,0,254,63,1,0,0,0,255,257,5,17, + 0,0,256,258,3,68,34,0,257,256,1,0,0,0,257,258,1,0,0,0,258,259,1,0,0,0,259, + 260,5,26,0,0,260,65,1,0,0,0,261,266,3,68,34,0,262,263,5,25,0,0,263,265, + 3,68,34,0,264,262,1,0,0,0,265,268,1,0,0,0,266,264,1,0,0,0,266,267,1,0,0, + 0,267,270,1,0,0,0,268,266,1,0,0,0,269,261,1,0,0,0,269,270,1,0,0,0,270,67, + 1,0,0,0,271,272,6,34,-1,0,272,279,3,70,35,0,273,279,3,72,36,0,274,279,3, + 60,30,0,275,279,3,74,37,0,276,279,3,76,38,0,277,279,3,78,39,0,278,271,1, + 0,0,0,278,273,1,0,0,0,278,274,1,0,0,0,278,275,1,0,0,0,278,276,1,0,0,0,278, + 277,1,0,0,0,279,286,1,0,0,0,280,281,10,2,0,0,281,282,3,84,42,0,282,283, + 3,68,34,3,283,285,1,0,0,0,284,280,1,0,0,0,285,288,1,0,0,0,286,284,1,0,0, + 0,286,287,1,0,0,0,287,69,1,0,0,0,288,286,1,0,0,0,289,295,5,40,0,0,290,295, + 5,46,0,0,291,295,3,80,40,0,292,295,5,43,0,0,293,295,5,44,0,0,294,289,1, + 0,0,0,294,290,1,0,0,0,294,291,1,0,0,0,294,292,1,0,0,0,294,293,1,0,0,0,295, + 71,1,0,0,0,296,297,5,45,0,0,297,73,1,0,0,0,298,299,3,72,36,0,299,300,5, + 22,0,0,300,301,3,68,34,0,301,302,5,23,0,0,302,75,1,0,0,0,303,304,3,82,41, + 0,304,305,3,68,34,0,305,77,1,0,0,0,306,307,5,20,0,0,307,308,3,68,34,0,308, + 309,5,21,0,0,309,79,1,0,0,0,310,311,7,3,0,0,311,81,1,0,0,0,312,313,7,4, + 0,0,313,83,1,0,0,0,314,315,7,5,0,0,315,85,1,0,0,0,20,95,101,118,139,148, + 151,162,177,187,195,200,210,248,251,257,266,269,278,286,294]; + + private static __ATN: ATN; + public static get _ATN(): ATN { + if (!JackParser.__ATN) { + JackParser.__ATN = new ATNDeserializer().deserialize(JackParser._serializedATN); + } + + return JackParser.__ATN; + } + + + static DecisionsToDFA = JackParser._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) ); + } export class ProgramContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public classDeclaration(): ClassDeclarationContext { - return this.getTypedRuleContext( - ClassDeclarationContext, - 0, - ) as ClassDeclarationContext; - } - public EOF(): TerminalNode { - return this.getToken(JackParser.EOF, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_program; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterProgram) { - listener.enterProgram(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitProgram) { - listener.exitProgram(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public classDeclaration(): ClassDeclarationContext { + return this.getTypedRuleContext(ClassDeclarationContext, 0) as ClassDeclarationContext; + } + public EOF(): TerminalNode { + return this.getToken(JackParser.EOF, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_program; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterProgram) { + listener.enterProgram(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitProgram) { + listener.exitProgram(this); + } + } } + export class ClassDeclarationContext extends ParserRuleContext { - public localSymbolTable: LocalSymbolTable | undefined; - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public CLASS(): TerminalNode { - return this.getToken(JackParser.CLASS, 0); - } - public className(): ClassNameContext { - return this.getTypedRuleContext(ClassNameContext, 0) as ClassNameContext; - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public classVarDec_list(): ClassVarDecContext[] { - return this.getTypedRuleContexts( - ClassVarDecContext, - ) as ClassVarDecContext[]; - } - public classVarDec(i: number): ClassVarDecContext { - return this.getTypedRuleContext( - ClassVarDecContext, - i, - ) as ClassVarDecContext; - } - public subroutineDeclaration_list(): SubroutineDeclarationContext[] { - return this.getTypedRuleContexts( - SubroutineDeclarationContext, - ) as SubroutineDeclarationContext[]; - } - public subroutineDeclaration(i: number): SubroutineDeclarationContext { - return this.getTypedRuleContext( - SubroutineDeclarationContext, - i, - ) as SubroutineDeclarationContext; - } - public get ruleIndex(): number { - return JackParser.RULE_classDeclaration; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterClassDeclaration) { - listener.enterClassDeclaration(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitClassDeclaration) { - listener.exitClassDeclaration(this); - } - } + public localSymbolTable: LocalSymbolTable | undefined; + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public CLASS(): TerminalNode { + return this.getToken(JackParser.CLASS, 0); + } + public className(): ClassNameContext { + return this.getTypedRuleContext(ClassNameContext, 0) as ClassNameContext; + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public classVarDec_list(): ClassVarDecContext[] { + return this.getTypedRuleContexts(ClassVarDecContext) as ClassVarDecContext[]; + } + public classVarDec(i: number): ClassVarDecContext { + return this.getTypedRuleContext(ClassVarDecContext, i) as ClassVarDecContext; + } + public subroutineDeclaration_list(): SubroutineDeclarationContext[] { + return this.getTypedRuleContexts(SubroutineDeclarationContext) as SubroutineDeclarationContext[]; + } + public subroutineDeclaration(i: number): SubroutineDeclarationContext { + return this.getTypedRuleContext(SubroutineDeclarationContext, i) as SubroutineDeclarationContext; + } + public get ruleIndex(): number { + return JackParser.RULE_classDeclaration; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterClassDeclaration) { + listener.enterClassDeclaration(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitClassDeclaration) { + listener.exitClassDeclaration(this); + } + } } + export class ClassNameContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_className; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterClassName) { - listener.enterClassName(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitClassName) { - listener.exitClassName(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_className; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterClassName) { + listener.enterClassName(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitClassName) { + listener.exitClassName(this); + } + } } + export class ClassVarDecContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public fieldList(): FieldListContext { - return this.getTypedRuleContext(FieldListContext, 0) as FieldListContext; - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public STATIC(): TerminalNode { - return this.getToken(JackParser.STATIC, 0); - } - public FIELD(): TerminalNode { - return this.getToken(JackParser.FIELD, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_classVarDec; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterClassVarDec) { - listener.enterClassVarDec(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitClassVarDec) { - listener.exitClassVarDec(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public fieldList(): FieldListContext { + return this.getTypedRuleContext(FieldListContext, 0) as FieldListContext; + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public STATIC(): TerminalNode { + return this.getToken(JackParser.STATIC, 0); + } + public FIELD(): TerminalNode { + return this.getToken(JackParser.FIELD, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_classVarDec; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterClassVarDec) { + listener.enterClassVarDec(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitClassVarDec) { + listener.exitClassVarDec(this); + } + } } + export class FieldListContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public varType(): VarTypeContext { - return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; - } - public fieldName_list(): FieldNameContext[] { - return this.getTypedRuleContexts(FieldNameContext) as FieldNameContext[]; - } - public fieldName(i: number): FieldNameContext { - return this.getTypedRuleContext(FieldNameContext, i) as FieldNameContext; - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(JackParser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(JackParser.COMMA, i); - } - public get ruleIndex(): number { - return JackParser.RULE_fieldList; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterFieldList) { - listener.enterFieldList(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitFieldList) { - listener.exitFieldList(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public varType(): VarTypeContext { + return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; + } + public fieldName_list(): FieldNameContext[] { + return this.getTypedRuleContexts(FieldNameContext) as FieldNameContext[]; + } + public fieldName(i: number): FieldNameContext { + return this.getTypedRuleContext(FieldNameContext, i) as FieldNameContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(JackParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(JackParser.COMMA, i); + } + public get ruleIndex(): number { + return JackParser.RULE_fieldList; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterFieldList) { + listener.enterFieldList(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitFieldList) { + listener.exitFieldList(this); + } + } } + export class FieldNameContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_fieldName; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterFieldName) { - listener.enterFieldName(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitFieldName) { - listener.exitFieldName(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_fieldName; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterFieldName) { + listener.enterFieldName(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitFieldName) { + listener.exitFieldName(this); + } + } } + export class SubroutineDeclarationContext extends ParserRuleContext { - public symbols: SubroutineScope | undefined; - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public subroutineType(): SubroutineTypeContext { - return this.getTypedRuleContext( - SubroutineTypeContext, - 0, - ) as SubroutineTypeContext; - } - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - return this.getTypedRuleContext( - SubroutineDecWithoutTypeContext, - 0, - ) as SubroutineDecWithoutTypeContext; - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineDeclaration; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineDeclaration) { - listener.enterSubroutineDeclaration(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineDeclaration) { - listener.exitSubroutineDeclaration(this); - } - } + public symbols: SubroutineScope | undefined; + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public subroutineType(): SubroutineTypeContext { + return this.getTypedRuleContext(SubroutineTypeContext, 0) as SubroutineTypeContext; + } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + return this.getTypedRuleContext(SubroutineDecWithoutTypeContext, 0) as SubroutineDecWithoutTypeContext; + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineDeclaration; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineDeclaration) { + listener.enterSubroutineDeclaration(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineDeclaration) { + listener.exitSubroutineDeclaration(this); + } + } } + export class SubroutineTypeContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public CONSTRUCTOR(): TerminalNode { - return this.getToken(JackParser.CONSTRUCTOR, 0); - } - public METHOD(): TerminalNode { - return this.getToken(JackParser.METHOD, 0); - } - public FUNCTION(): TerminalNode { - return this.getToken(JackParser.FUNCTION, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineType; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineType) { - listener.enterSubroutineType(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineType) { - listener.exitSubroutineType(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public CONSTRUCTOR(): TerminalNode { + return this.getToken(JackParser.CONSTRUCTOR, 0); + } + public METHOD(): TerminalNode { + return this.getToken(JackParser.METHOD, 0); + } + public FUNCTION(): TerminalNode { + return this.getToken(JackParser.FUNCTION, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineType; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineType) { + listener.enterSubroutineType(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineType) { + listener.exitSubroutineType(this); + } + } } + export class SubroutineDecWithoutTypeContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public subroutineReturnType(): SubroutineReturnTypeContext { - return this.getTypedRuleContext( - SubroutineReturnTypeContext, - 0, - ) as SubroutineReturnTypeContext; - } - public subroutineName(): SubroutineNameContext { - return this.getTypedRuleContext( - SubroutineNameContext, - 0, - ) as SubroutineNameContext; - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public parameterList(): ParameterListContext { - return this.getTypedRuleContext( - ParameterListContext, - 0, - ) as ParameterListContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public subroutineBody(): SubroutineBodyContext { - return this.getTypedRuleContext( - SubroutineBodyContext, - 0, - ) as SubroutineBodyContext; - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineDecWithoutType; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineDecWithoutType) { - listener.enterSubroutineDecWithoutType(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineDecWithoutType) { - listener.exitSubroutineDecWithoutType(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public subroutineReturnType(): SubroutineReturnTypeContext { + return this.getTypedRuleContext(SubroutineReturnTypeContext, 0) as SubroutineReturnTypeContext; + } + public subroutineName(): SubroutineNameContext { + return this.getTypedRuleContext(SubroutineNameContext, 0) as SubroutineNameContext; + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public parameterList(): ParameterListContext { + return this.getTypedRuleContext(ParameterListContext, 0) as ParameterListContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public subroutineBody(): SubroutineBodyContext { + return this.getTypedRuleContext(SubroutineBodyContext, 0) as SubroutineBodyContext; + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineDecWithoutType; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineDecWithoutType) { + listener.enterSubroutineDecWithoutType(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineDecWithoutType) { + listener.exitSubroutineDecWithoutType(this); + } + } } + export class SubroutineNameContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineName; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineName) { - listener.enterSubroutineName(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineName) { - listener.exitSubroutineName(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineName; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineName) { + listener.enterSubroutineName(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineName) { + listener.exitSubroutineName(this); + } + } } + export class SubroutineReturnTypeContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public varType(): VarTypeContext { - return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; - } - public VOID(): TerminalNode { - return this.getToken(JackParser.VOID, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineReturnType; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineReturnType) { - listener.enterSubroutineReturnType(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineReturnType) { - listener.exitSubroutineReturnType(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public varType(): VarTypeContext { + return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; + } + public VOID(): TerminalNode { + return this.getToken(JackParser.VOID, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineReturnType; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineReturnType) { + listener.enterSubroutineReturnType(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineReturnType) { + listener.exitSubroutineReturnType(this); + } + } } + export class VarTypeContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public INT(): TerminalNode { - return this.getToken(JackParser.INT, 0); - } - public CHAR(): TerminalNode { - return this.getToken(JackParser.CHAR, 0); - } - public BOOLEAN(): TerminalNode { - return this.getToken(JackParser.BOOLEAN, 0); - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_varType; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterVarType) { - listener.enterVarType(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitVarType) { - listener.exitVarType(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public INT(): TerminalNode { + return this.getToken(JackParser.INT, 0); + } + public CHAR(): TerminalNode { + return this.getToken(JackParser.CHAR, 0); + } + public BOOLEAN(): TerminalNode { + return this.getToken(JackParser.BOOLEAN, 0); + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_varType; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterVarType) { + listener.enterVarType(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitVarType) { + listener.exitVarType(this); + } + } } + export class ParameterListContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public parameter_list(): ParameterContext[] { - return this.getTypedRuleContexts(ParameterContext) as ParameterContext[]; - } - public parameter(i: number): ParameterContext { - return this.getTypedRuleContext(ParameterContext, i) as ParameterContext; - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(JackParser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(JackParser.COMMA, i); - } - public get ruleIndex(): number { - return JackParser.RULE_parameterList; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterParameterList) { - listener.enterParameterList(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitParameterList) { - listener.exitParameterList(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public parameter_list(): ParameterContext[] { + return this.getTypedRuleContexts(ParameterContext) as ParameterContext[]; + } + public parameter(i: number): ParameterContext { + return this.getTypedRuleContext(ParameterContext, i) as ParameterContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(JackParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(JackParser.COMMA, i); + } + public get ruleIndex(): number { + return JackParser.RULE_parameterList; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterParameterList) { + listener.enterParameterList(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitParameterList) { + listener.exitParameterList(this); + } + } } + export class ParameterContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public varType(): VarTypeContext { - return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; - } - public parameterName(): ParameterNameContext { - return this.getTypedRuleContext( - ParameterNameContext, - 0, - ) as ParameterNameContext; - } - public get ruleIndex(): number { - return JackParser.RULE_parameter; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterParameter) { - listener.enterParameter(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitParameter) { - listener.exitParameter(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public varType(): VarTypeContext { + return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; + } + public parameterName(): ParameterNameContext { + return this.getTypedRuleContext(ParameterNameContext, 0) as ParameterNameContext; + } + public get ruleIndex(): number { + return JackParser.RULE_parameter; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterParameter) { + listener.enterParameter(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitParameter) { + listener.exitParameter(this); + } + } } + export class ParameterNameContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_parameterName; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterParameterName) { - listener.enterParameterName(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitParameterName) { - listener.exitParameterName(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_parameterName; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterParameterName) { + listener.enterParameterName(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitParameterName) { + listener.exitParameterName(this); + } + } } + export class SubroutineBodyContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public statements(): StatementsContext { - return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public varDeclaration_list(): VarDeclarationContext[] { - return this.getTypedRuleContexts( - VarDeclarationContext, - ) as VarDeclarationContext[]; - } - public varDeclaration(i: number): VarDeclarationContext { - return this.getTypedRuleContext( - VarDeclarationContext, - i, - ) as VarDeclarationContext; - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineBody; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineBody) { - listener.enterSubroutineBody(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineBody) { - listener.exitSubroutineBody(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public statements(): StatementsContext { + return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public varDeclaration_list(): VarDeclarationContext[] { + return this.getTypedRuleContexts(VarDeclarationContext) as VarDeclarationContext[]; + } + public varDeclaration(i: number): VarDeclarationContext { + return this.getTypedRuleContext(VarDeclarationContext, i) as VarDeclarationContext; + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineBody; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineBody) { + listener.enterSubroutineBody(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineBody) { + listener.exitSubroutineBody(this); + } + } } + export class RBraceContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public RBRACE(): TerminalNode { - return this.getToken(JackParser.RBRACE, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_rBrace; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterRBrace) { - listener.enterRBrace(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitRBrace) { - listener.exitRBrace(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public RBRACE(): TerminalNode { + return this.getToken(JackParser.RBRACE, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_rBrace; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterRBrace) { + listener.enterRBrace(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitRBrace) { + listener.exitRBrace(this); + } + } } + export class VarDeclarationContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public VAR(): TerminalNode { - return this.getToken(JackParser.VAR, 0); - } - public varType(): VarTypeContext { - return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; - } - public varNameInDeclaration_list(): VarNameInDeclarationContext[] { - return this.getTypedRuleContexts( - VarNameInDeclarationContext, - ) as VarNameInDeclarationContext[]; - } - public varNameInDeclaration(i: number): VarNameInDeclarationContext { - return this.getTypedRuleContext( - VarNameInDeclarationContext, - i, - ) as VarNameInDeclarationContext; - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(JackParser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(JackParser.COMMA, i); - } - public get ruleIndex(): number { - return JackParser.RULE_varDeclaration; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterVarDeclaration) { - listener.enterVarDeclaration(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitVarDeclaration) { - listener.exitVarDeclaration(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public VAR(): TerminalNode { + return this.getToken(JackParser.VAR, 0); + } + public varType(): VarTypeContext { + return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; + } + public varNameInDeclaration_list(): VarNameInDeclarationContext[] { + return this.getTypedRuleContexts(VarNameInDeclarationContext) as VarNameInDeclarationContext[]; + } + public varNameInDeclaration(i: number): VarNameInDeclarationContext { + return this.getTypedRuleContext(VarNameInDeclarationContext, i) as VarNameInDeclarationContext; + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(JackParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(JackParser.COMMA, i); + } + public get ruleIndex(): number { + return JackParser.RULE_varDeclaration; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterVarDeclaration) { + listener.enterVarDeclaration(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitVarDeclaration) { + listener.exitVarDeclaration(this); + } + } } + export class VarNameInDeclarationContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_varNameInDeclaration; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterVarNameInDeclaration) { - listener.enterVarNameInDeclaration(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitVarNameInDeclaration) { - listener.exitVarNameInDeclaration(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_varNameInDeclaration; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterVarNameInDeclaration) { + listener.enterVarNameInDeclaration(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitVarNameInDeclaration) { + listener.exitVarNameInDeclaration(this); + } + } } -export class VarNameContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_varName; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterVarName) { - listener.enterVarName(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitVarName) { - listener.exitVarName(this); - } - } -} export class StatementsContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public statement_list(): StatementContext[] { - return this.getTypedRuleContexts(StatementContext) as StatementContext[]; - } - public statement(i: number): StatementContext { - return this.getTypedRuleContext(StatementContext, i) as StatementContext; - } - public get ruleIndex(): number { - return JackParser.RULE_statements; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterStatements) { - listener.enterStatements(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitStatements) { - listener.exitStatements(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public statement_list(): StatementContext[] { + return this.getTypedRuleContexts(StatementContext) as StatementContext[]; + } + public statement(i: number): StatementContext { + return this.getTypedRuleContext(StatementContext, i) as StatementContext; + } + public get ruleIndex(): number { + return JackParser.RULE_statements; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterStatements) { + listener.enterStatements(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitStatements) { + listener.exitStatements(this); + } + } } + export class StatementContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public letStatement(): LetStatementContext { - return this.getTypedRuleContext( - LetStatementContext, - 0, - ) as LetStatementContext; - } - public ifElseStatement(): IfElseStatementContext { - return this.getTypedRuleContext( - IfElseStatementContext, - 0, - ) as IfElseStatementContext; - } - public whileStatement(): WhileStatementContext { - return this.getTypedRuleContext( - WhileStatementContext, - 0, - ) as WhileStatementContext; - } - public doStatement(): DoStatementContext { - return this.getTypedRuleContext( - DoStatementContext, - 0, - ) as DoStatementContext; - } - public returnStatement(): ReturnStatementContext { - return this.getTypedRuleContext( - ReturnStatementContext, - 0, - ) as ReturnStatementContext; - } - public get ruleIndex(): number { - return JackParser.RULE_statement; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterStatement) { - listener.enterStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitStatement) { - listener.exitStatement(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public letStatement(): LetStatementContext { + return this.getTypedRuleContext(LetStatementContext, 0) as LetStatementContext; + } + public ifElseStatement(): IfElseStatementContext { + return this.getTypedRuleContext(IfElseStatementContext, 0) as IfElseStatementContext; + } + public whileStatement(): WhileStatementContext { + return this.getTypedRuleContext(WhileStatementContext, 0) as WhileStatementContext; + } + public doStatement(): DoStatementContext { + return this.getTypedRuleContext(DoStatementContext, 0) as DoStatementContext; + } + public returnStatement(): ReturnStatementContext { + return this.getTypedRuleContext(ReturnStatementContext, 0) as ReturnStatementContext; + } + public get ruleIndex(): number { + return JackParser.RULE_statement; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterStatement) { + listener.enterStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitStatement) { + listener.exitStatement(this); + } + } } + export class LetStatementContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public LET(): TerminalNode { - return this.getToken(JackParser.LET, 0); - } - public equals(): EqualsContext { - return this.getTypedRuleContext(EqualsContext, 0) as EqualsContext; - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public varName(): VarNameContext { - return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; - } - public arrayAccess(): ArrayAccessContext { - return this.getTypedRuleContext( - ArrayAccessContext, - 0, - ) as ArrayAccessContext; - } - public get ruleIndex(): number { - return JackParser.RULE_letStatement; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterLetStatement) { - listener.enterLetStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitLetStatement) { - listener.exitLetStatement(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public LET(): TerminalNode { + return this.getToken(JackParser.LET, 0); + } + public equals(): EqualsContext { + return this.getTypedRuleContext(EqualsContext, 0) as EqualsContext; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public varName(): VarNameContext { + return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; + } + public arrayAccess(): ArrayAccessContext { + return this.getTypedRuleContext(ArrayAccessContext, 0) as ArrayAccessContext; + } + public get ruleIndex(): number { + return JackParser.RULE_letStatement; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterLetStatement) { + listener.enterLetStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitLetStatement) { + listener.exitLetStatement(this); + } + } } + export class EqualsContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public EQUALS(): TerminalNode { - return this.getToken(JackParser.EQUALS, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_equals; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterEquals) { - listener.enterEquals(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitEquals) { - listener.exitEquals(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public EQUALS(): TerminalNode { + return this.getToken(JackParser.EQUALS, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_equals; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterEquals) { + listener.enterEquals(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitEquals) { + listener.exitEquals(this); + } + } } + export class IfElseStatementContext extends ParserRuleContext { - public endLabel = ""; - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public ifStatement(): IfStatementContext { - return this.getTypedRuleContext( - IfStatementContext, - 0, - ) as IfStatementContext; - } - public elseStatement(): ElseStatementContext { - return this.getTypedRuleContext( - ElseStatementContext, - 0, - ) as ElseStatementContext; - } - public get ruleIndex(): number { - return JackParser.RULE_ifElseStatement; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterIfElseStatement) { - listener.enterIfElseStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitIfElseStatement) { - listener.exitIfElseStatement(this); - } - } + public endLabel: string = ""; + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public ifStatement(): IfStatementContext { + return this.getTypedRuleContext(IfStatementContext, 0) as IfStatementContext; + } + public elseStatement(): ElseStatementContext { + return this.getTypedRuleContext(ElseStatementContext, 0) as ElseStatementContext; + } + public get ruleIndex(): number { + return JackParser.RULE_ifElseStatement; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterIfElseStatement) { + listener.enterIfElseStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitIfElseStatement) { + listener.exitIfElseStatement(this); + } + } } + export class IfStatementContext extends ParserRuleContext { - public endLabel = ""; - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public IF(): TerminalNode { - return this.getToken(JackParser.IF, 0); - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public ifExpression(): IfExpressionContext { - return this.getTypedRuleContext( - IfExpressionContext, - 0, - ) as IfExpressionContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public statements(): StatementsContext { - return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public get ruleIndex(): number { - return JackParser.RULE_ifStatement; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterIfStatement) { - listener.enterIfStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitIfStatement) { - listener.exitIfStatement(this); - } - } + public endLabel: string = ""; + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IF(): TerminalNode { + return this.getToken(JackParser.IF, 0); + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public ifExpression(): IfExpressionContext { + return this.getTypedRuleContext(IfExpressionContext, 0) as IfExpressionContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public statements(): StatementsContext { + return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public get ruleIndex(): number { + return JackParser.RULE_ifStatement; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterIfStatement) { + listener.enterIfStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitIfStatement) { + listener.exitIfStatement(this); + } + } } + export class IfExpressionContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public get ruleIndex(): number { - return JackParser.RULE_ifExpression; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterIfExpression) { - listener.enterIfExpression(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitIfExpression) { - listener.exitIfExpression(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return JackParser.RULE_ifExpression; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterIfExpression) { + listener.enterIfExpression(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitIfExpression) { + listener.exitIfExpression(this); + } + } } + export class ElseStatementContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public ELSE(): TerminalNode { - return this.getToken(JackParser.ELSE, 0); - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public statements(): StatementsContext { - return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public get ruleIndex(): number { - return JackParser.RULE_elseStatement; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterElseStatement) { - listener.enterElseStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitElseStatement) { - listener.exitElseStatement(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public ELSE(): TerminalNode { + return this.getToken(JackParser.ELSE, 0); + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public statements(): StatementsContext { + return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public get ruleIndex(): number { + return JackParser.RULE_elseStatement; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterElseStatement) { + listener.enterElseStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitElseStatement) { + listener.exitElseStatement(this); + } + } } + export class WhileStatementContext extends ParserRuleContext { - public startLabel = ""; - endLabel = ""; - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public WHILE(): TerminalNode { - return this.getToken(JackParser.WHILE, 0); - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public whileExpression(): WhileExpressionContext { - return this.getTypedRuleContext( - WhileExpressionContext, - 0, - ) as WhileExpressionContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public statements(): StatementsContext { - return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public get ruleIndex(): number { - return JackParser.RULE_whileStatement; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterWhileStatement) { - listener.enterWhileStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitWhileStatement) { - listener.exitWhileStatement(this); - } - } + public startLabel: string = "";endLabel:string="";; + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public WHILE(): TerminalNode { + return this.getToken(JackParser.WHILE, 0); + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public whileExpression(): WhileExpressionContext { + return this.getTypedRuleContext(WhileExpressionContext, 0) as WhileExpressionContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public LBRACE(): TerminalNode { + return this.getToken(JackParser.LBRACE, 0); + } + public statements(): StatementsContext { + return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; + } + public rBrace(): RBraceContext { + return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; + } + public get ruleIndex(): number { + return JackParser.RULE_whileStatement; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterWhileStatement) { + listener.enterWhileStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitWhileStatement) { + listener.exitWhileStatement(this); + } + } } + export class WhileExpressionContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public get ruleIndex(): number { - return JackParser.RULE_whileExpression; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterWhileExpression) { - listener.enterWhileExpression(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitWhileExpression) { - listener.exitWhileExpression(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return JackParser.RULE_whileExpression; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterWhileExpression) { + listener.enterWhileExpression(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitWhileExpression) { + listener.exitWhileExpression(this); + } + } } + export class DoStatementContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public DO(): TerminalNode { - return this.getToken(JackParser.DO, 0); - } - public subroutineCall(): SubroutineCallContext { - return this.getTypedRuleContext( - SubroutineCallContext, - 0, - ) as SubroutineCallContext; - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_doStatement; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterDoStatement) { - listener.enterDoStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitDoStatement) { - listener.exitDoStatement(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public DO(): TerminalNode { + return this.getToken(JackParser.DO, 0); + } + public subroutineCall(): SubroutineCallContext { + return this.getTypedRuleContext(SubroutineCallContext, 0) as SubroutineCallContext; + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_doStatement; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterDoStatement) { + listener.enterDoStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitDoStatement) { + listener.exitDoStatement(this); + } + } } + export class SubroutineCallContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public subroutineId(): SubroutineIdContext { - return this.getTypedRuleContext( - SubroutineIdContext, - 0, - ) as SubroutineIdContext; - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public expressionList(): ExpressionListContext { - return this.getTypedRuleContext( - ExpressionListContext, - 0, - ) as ExpressionListContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineCall; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineCall) { - listener.enterSubroutineCall(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineCall) { - listener.exitSubroutineCall(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public subroutineId(): SubroutineIdContext { + return this.getTypedRuleContext(SubroutineIdContext, 0) as SubroutineIdContext; + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public expressionList(): ExpressionListContext { + return this.getTypedRuleContext(ExpressionListContext, 0) as ExpressionListContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineCall; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineCall) { + listener.enterSubroutineCall(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineCall) { + listener.exitSubroutineCall(this); + } + } } + export class SubroutineIdContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public subroutineName(): SubroutineNameContext { - return this.getTypedRuleContext( - SubroutineNameContext, - 0, - ) as SubroutineNameContext; - } - public DOT(): TerminalNode { - return this.getToken(JackParser.DOT, 0); - } - public className(): ClassNameContext { - return this.getTypedRuleContext(ClassNameContext, 0) as ClassNameContext; - } - public THIS_LITERAL(): TerminalNode { - return this.getToken(JackParser.THIS_LITERAL, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineId; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterSubroutineId) { - listener.enterSubroutineId(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitSubroutineId) { - listener.exitSubroutineId(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public subroutineName(): SubroutineNameContext { + return this.getTypedRuleContext(SubroutineNameContext, 0) as SubroutineNameContext; + } + public DOT(): TerminalNode { + return this.getToken(JackParser.DOT, 0); + } + public className(): ClassNameContext { + return this.getTypedRuleContext(ClassNameContext, 0) as ClassNameContext; + } + public THIS_LITERAL(): TerminalNode { + return this.getToken(JackParser.THIS_LITERAL, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_subroutineId; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineId) { + listener.enterSubroutineId(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineId) { + listener.exitSubroutineId(this); + } + } } + export class ReturnStatementContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public RETURN(): TerminalNode { - return this.getToken(JackParser.RETURN, 0); - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public get ruleIndex(): number { - return JackParser.RULE_returnStatement; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterReturnStatement) { - listener.enterReturnStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitReturnStatement) { - listener.exitReturnStatement(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public RETURN(): TerminalNode { + return this.getToken(JackParser.RETURN, 0); + } + public SEMICOLON(): TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0); + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return JackParser.RULE_returnStatement; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterReturnStatement) { + listener.enterReturnStatement(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitReturnStatement) { + listener.exitReturnStatement(this); + } + } } + export class ExpressionListContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public expression_list(): ExpressionContext[] { - return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; - } - public expression(i: number): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(JackParser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(JackParser.COMMA, i); - } - public get ruleIndex(): number { - return JackParser.RULE_expressionList; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterExpressionList) { - listener.enterExpressionList(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitExpressionList) { - listener.exitExpressionList(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public expression_list(): ExpressionContext[] { + return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; + } + public expression(i: number): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; + } + public COMMA_list(): TerminalNode[] { + return this.getTokens(JackParser.COMMA); + } + public COMMA(i: number): TerminalNode { + return this.getToken(JackParser.COMMA, i); + } + public get ruleIndex(): number { + return JackParser.RULE_expressionList; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterExpressionList) { + listener.enterExpressionList(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitExpressionList) { + listener.exitExpressionList(this); + } + } } + export class ExpressionContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public constant(): ConstantContext { - return this.getTypedRuleContext(ConstantContext, 0) as ConstantContext; - } - public varName(): VarNameContext { - return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; - } - public subroutineCall(): SubroutineCallContext { - return this.getTypedRuleContext( - SubroutineCallContext, - 0, - ) as SubroutineCallContext; - } - public arrayAccess(): ArrayAccessContext { - return this.getTypedRuleContext( - ArrayAccessContext, - 0, - ) as ArrayAccessContext; - } - public unaryOperation(): UnaryOperationContext { - return this.getTypedRuleContext( - UnaryOperationContext, - 0, - ) as UnaryOperationContext; - } - public groupedExpression(): GroupedExpressionContext { - return this.getTypedRuleContext( - GroupedExpressionContext, - 0, - ) as GroupedExpressionContext; - } - public expression_list(): ExpressionContext[] { - return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; - } - public expression(i: number): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; - } - public binaryOperator(): BinaryOperatorContext { - return this.getTypedRuleContext( - BinaryOperatorContext, - 0, - ) as BinaryOperatorContext; - } - public get ruleIndex(): number { - return JackParser.RULE_expression; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterExpression) { - listener.enterExpression(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitExpression) { - listener.exitExpression(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public constant(): ConstantContext { + return this.getTypedRuleContext(ConstantContext, 0) as ConstantContext; + } + public varName(): VarNameContext { + return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; + } + public subroutineCall(): SubroutineCallContext { + return this.getTypedRuleContext(SubroutineCallContext, 0) as SubroutineCallContext; + } + public arrayAccess(): ArrayAccessContext { + return this.getTypedRuleContext(ArrayAccessContext, 0) as ArrayAccessContext; + } + public unaryOperation(): UnaryOperationContext { + return this.getTypedRuleContext(UnaryOperationContext, 0) as UnaryOperationContext; + } + public groupedExpression(): GroupedExpressionContext { + return this.getTypedRuleContext(GroupedExpressionContext, 0) as GroupedExpressionContext; + } + public expression_list(): ExpressionContext[] { + return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; + } + public expression(i: number): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; + } + public binaryOperator(): BinaryOperatorContext { + return this.getTypedRuleContext(BinaryOperatorContext, 0) as BinaryOperatorContext; + } + public get ruleIndex(): number { + return JackParser.RULE_expression; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterExpression) { + listener.enterExpression(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitExpression) { + listener.exitExpression(this); + } + } } -export class GroupedExpressionContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_groupedExpression; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterGroupedExpression) { - listener.enterGroupedExpression(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitGroupedExpression) { - listener.exitGroupedExpression(this); - } - } + +export class ConstantContext extends ParserRuleContext { + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public INTEGER_LITERAL(): TerminalNode { + return this.getToken(JackParser.INTEGER_LITERAL, 0); + } + public STRING_LITERAL(): TerminalNode { + return this.getToken(JackParser.STRING_LITERAL, 0); + } + public booleanLiteral(): BooleanLiteralContext { + return this.getTypedRuleContext(BooleanLiteralContext, 0) as BooleanLiteralContext; + } + public NULL_LITERAL(): TerminalNode { + return this.getToken(JackParser.NULL_LITERAL, 0); + } + public THIS_LITERAL(): TerminalNode { + return this.getToken(JackParser.THIS_LITERAL, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_constant; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterConstant) { + listener.enterConstant(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitConstant) { + listener.exitConstant(this); + } + } } -export class UnaryOperationContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public unaryOperator(): UnaryOperatorContext { - return this.getTypedRuleContext( - UnaryOperatorContext, - 0, - ) as UnaryOperatorContext; - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public get ruleIndex(): number { - return JackParser.RULE_unaryOperation; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterUnaryOperation) { - listener.enterUnaryOperation(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitUnaryOperation) { - listener.exitUnaryOperation(this); - } - } + +export class VarNameContext extends ParserRuleContext { + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public IDENTIFIER(): TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_varName; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterVarName) { + listener.enterVarName(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitVarName) { + listener.exitVarName(this); + } + } } + export class ArrayAccessContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public varName(): VarNameContext { - return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; - } - public LBRACKET(): TerminalNode { - return this.getToken(JackParser.LBRACKET, 0); - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public RBRACKET(): TerminalNode { - return this.getToken(JackParser.RBRACKET, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_arrayAccess; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterArrayAccess) { - listener.enterArrayAccess(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitArrayAccess) { - listener.exitArrayAccess(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public varName(): VarNameContext { + return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; + } + public LBRACKET(): TerminalNode { + return this.getToken(JackParser.LBRACKET, 0); + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public RBRACKET(): TerminalNode { + return this.getToken(JackParser.RBRACKET, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_arrayAccess; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterArrayAccess) { + listener.enterArrayAccess(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitArrayAccess) { + listener.exitArrayAccess(this); + } + } } -export class ConstantContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public INTEGER_LITERAL(): TerminalNode { - return this.getToken(JackParser.INTEGER_LITERAL, 0); - } - public STRING_LITERAL(): TerminalNode { - return this.getToken(JackParser.STRING_LITERAL, 0); - } - public booleanLiteral(): BooleanLiteralContext { - return this.getTypedRuleContext( - BooleanLiteralContext, - 0, - ) as BooleanLiteralContext; - } - public NULL_LITERAL(): TerminalNode { - return this.getToken(JackParser.NULL_LITERAL, 0); - } - public THIS_LITERAL(): TerminalNode { - return this.getToken(JackParser.THIS_LITERAL, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_constant; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterConstant) { - listener.enterConstant(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitConstant) { - listener.exitConstant(this); - } - } + +export class UnaryOperationContext extends ParserRuleContext { + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public unaryOperator(): UnaryOperatorContext { + return this.getTypedRuleContext(UnaryOperatorContext, 0) as UnaryOperatorContext; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return JackParser.RULE_unaryOperation; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterUnaryOperation) { + listener.enterUnaryOperation(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitUnaryOperation) { + listener.exitUnaryOperation(this); + } + } +} + + +export class GroupedExpressionContext extends ParserRuleContext { + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public LPAREN(): TerminalNode { + return this.getToken(JackParser.LPAREN, 0); + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public RPAREN(): TerminalNode { + return this.getToken(JackParser.RPAREN, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_groupedExpression; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterGroupedExpression) { + listener.enterGroupedExpression(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitGroupedExpression) { + listener.exitGroupedExpression(this); + } + } } + export class BooleanLiteralContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public TRUE(): TerminalNode { - return this.getToken(JackParser.TRUE, 0); - } - public FALSE(): TerminalNode { - return this.getToken(JackParser.FALSE, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_booleanLiteral; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterBooleanLiteral) { - listener.enterBooleanLiteral(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitBooleanLiteral) { - listener.exitBooleanLiteral(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public TRUE(): TerminalNode { + return this.getToken(JackParser.TRUE, 0); + } + public FALSE(): TerminalNode { + return this.getToken(JackParser.FALSE, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_booleanLiteral; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterBooleanLiteral) { + listener.enterBooleanLiteral(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitBooleanLiteral) { + listener.exitBooleanLiteral(this); + } + } } + export class UnaryOperatorContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public TILDE(): TerminalNode { - return this.getToken(JackParser.TILDE, 0); - } - public MINUS(): TerminalNode { - return this.getToken(JackParser.MINUS, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_unaryOperator; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterUnaryOperator) { - listener.enterUnaryOperator(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitUnaryOperator) { - listener.exitUnaryOperator(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public TILDE(): TerminalNode { + return this.getToken(JackParser.TILDE, 0); + } + public MINUS(): TerminalNode { + return this.getToken(JackParser.MINUS, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_unaryOperator; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterUnaryOperator) { + listener.enterUnaryOperator(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitUnaryOperator) { + listener.exitUnaryOperator(this); + } + } } + export class BinaryOperatorContext extends ParserRuleContext { - constructor( - parser?: JackParser, - parent?: ParserRuleContext, - invokingState?: number, - ) { - super(parent, invokingState); - this.parser = parser; - } - public PLUS(): TerminalNode { - return this.getToken(JackParser.PLUS, 0); - } - public MINUS(): TerminalNode { - return this.getToken(JackParser.MINUS, 0); - } - public MUL(): TerminalNode { - return this.getToken(JackParser.MUL, 0); - } - public DIV(): TerminalNode { - return this.getToken(JackParser.DIV, 0); - } - public AND(): TerminalNode { - return this.getToken(JackParser.AND, 0); - } - public OR(): TerminalNode { - return this.getToken(JackParser.OR, 0); - } - public LESS_THAN(): TerminalNode { - return this.getToken(JackParser.LESS_THAN, 0); - } - public GREATER_THAN(): TerminalNode { - return this.getToken(JackParser.GREATER_THAN, 0); - } - public EQUALS(): TerminalNode { - return this.getToken(JackParser.EQUALS, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_binaryOperator; - } - public enterRule(listener: JackParserListener): void { - if (listener.enterBinaryOperator) { - listener.enterBinaryOperator(this); - } - } - public exitRule(listener: JackParserListener): void { - if (listener.exitBinaryOperator) { - listener.exitBinaryOperator(this); - } - } + constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public PLUS(): TerminalNode { + return this.getToken(JackParser.PLUS, 0); + } + public MINUS(): TerminalNode { + return this.getToken(JackParser.MINUS, 0); + } + public MUL(): TerminalNode { + return this.getToken(JackParser.MUL, 0); + } + public DIV(): TerminalNode { + return this.getToken(JackParser.DIV, 0); + } + public AND(): TerminalNode { + return this.getToken(JackParser.AND, 0); + } + public OR(): TerminalNode { + return this.getToken(JackParser.OR, 0); + } + public LESS_THAN(): TerminalNode { + return this.getToken(JackParser.LESS_THAN, 0); + } + public GREATER_THAN(): TerminalNode { + return this.getToken(JackParser.GREATER_THAN, 0); + } + public EQUALS(): TerminalNode { + return this.getToken(JackParser.EQUALS, 0); + } + public get ruleIndex(): number { + return JackParser.RULE_binaryOperator; + } + public enterRule(listener: JackParserListener): void { + if(listener.enterBinaryOperator) { + listener.enterBinaryOperator(this); + } + } + public exitRule(listener: JackParserListener): void { + if(listener.exitBinaryOperator) { + listener.exitBinaryOperator(this); + } + } } diff --git a/simulator/src/jack/generated/JackParserListener.ts b/simulator/src/jack/generated/JackParserListener.ts index 67718c1e..754b2077 100644 --- a/simulator/src/jack/generated/JackParserListener.ts +++ b/simulator/src/jack/generated/JackParserListener.ts @@ -1,6 +1,10 @@ // Generated from JackParser.g4 by ANTLR 4.13.2 -import { ParseTreeListener } from "antlr4"; +import {ParseTreeListener} from "antlr4"; + + +import { SubroutineScope, LocalSymbolTable } from "../symbol"; + import { ProgramContext } from "./JackParser.js"; import { ClassDeclarationContext } from "./JackParser.js"; @@ -21,7 +25,6 @@ import { SubroutineBodyContext } from "./JackParser.js"; import { RBraceContext } from "./JackParser.js"; import { VarDeclarationContext } from "./JackParser.js"; import { VarNameInDeclarationContext } from "./JackParser.js"; -import { VarNameContext } from "./JackParser.js"; import { StatementsContext } from "./JackParser.js"; import { StatementContext } from "./JackParser.js"; import { LetStatementContext } from "./JackParser.js"; @@ -38,449 +41,450 @@ import { SubroutineIdContext } from "./JackParser.js"; import { ReturnStatementContext } from "./JackParser.js"; import { ExpressionListContext } from "./JackParser.js"; import { ExpressionContext } from "./JackParser.js"; -import { GroupedExpressionContext } from "./JackParser.js"; -import { UnaryOperationContext } from "./JackParser.js"; -import { ArrayAccessContext } from "./JackParser.js"; import { ConstantContext } from "./JackParser.js"; +import { VarNameContext } from "./JackParser.js"; +import { ArrayAccessContext } from "./JackParser.js"; +import { UnaryOperationContext } from "./JackParser.js"; +import { GroupedExpressionContext } from "./JackParser.js"; import { BooleanLiteralContext } from "./JackParser.js"; import { UnaryOperatorContext } from "./JackParser.js"; import { BinaryOperatorContext } from "./JackParser.js"; + /** * This interface defines a complete listener for a parse tree produced by * `JackParser`. */ export default class JackParserListener extends ParseTreeListener { - /** - * Enter a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - */ - enterProgram?: (ctx: ProgramContext) => void; - /** - * Exit a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - */ - exitProgram?: (ctx: ProgramContext) => void; - /** - * Enter a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - */ - enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - */ - exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - */ - enterClassName?: (ctx: ClassNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - */ - exitClassName?: (ctx: ClassNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - */ - enterClassVarDec?: (ctx: ClassVarDecContext) => void; - /** - * Exit a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - */ - exitClassVarDec?: (ctx: ClassVarDecContext) => void; - /** - * Enter a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - */ - enterFieldList?: (ctx: FieldListContext) => void; - /** - * Exit a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - */ - exitFieldList?: (ctx: FieldListContext) => void; - /** - * Enter a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - */ - enterFieldName?: (ctx: FieldNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - */ - exitFieldName?: (ctx: FieldNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - */ - enterSubroutineType?: (ctx: SubroutineTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - */ - exitSubroutineType?: (ctx: SubroutineTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - */ - enterSubroutineDecWithoutType?: ( - ctx: SubroutineDecWithoutTypeContext, - ) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - */ - exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - */ - enterSubroutineName?: (ctx: SubroutineNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - */ - exitSubroutineName?: (ctx: SubroutineNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - */ - enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - */ - exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - */ - enterVarType?: (ctx: VarTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - */ - exitVarType?: (ctx: VarTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - */ - enterParameterList?: (ctx: ParameterListContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - */ - exitParameterList?: (ctx: ParameterListContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - */ - enterParameter?: (ctx: ParameterContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - */ - exitParameter?: (ctx: ParameterContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - */ - enterParameterName?: (ctx: ParameterNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - */ - exitParameterName?: (ctx: ParameterNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - */ - enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - */ - exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; - /** - * Enter a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - */ - enterRBrace?: (ctx: RBraceContext) => void; - /** - * Exit a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - */ - exitRBrace?: (ctx: RBraceContext) => void; - /** - * Enter a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - */ - enterVarDeclaration?: (ctx: VarDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - */ - exitVarDeclaration?: (ctx: VarDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - */ - enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - */ - exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - */ - enterVarName?: (ctx: VarNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - */ - exitVarName?: (ctx: VarNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - */ - enterStatements?: (ctx: StatementsContext) => void; - /** - * Exit a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - */ - exitStatements?: (ctx: StatementsContext) => void; - /** - * Enter a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - */ - enterStatement?: (ctx: StatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - */ - exitStatement?: (ctx: StatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - */ - enterLetStatement?: (ctx: LetStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - */ - exitLetStatement?: (ctx: LetStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.equals`. - * @param ctx the parse tree - */ - enterEquals?: (ctx: EqualsContext) => void; - /** - * Exit a parse tree produced by `JackParser.equals`. - * @param ctx the parse tree - */ - exitEquals?: (ctx: EqualsContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - */ - enterIfElseStatement?: (ctx: IfElseStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - */ - exitIfElseStatement?: (ctx: IfElseStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - */ - enterIfStatement?: (ctx: IfStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - */ - exitIfStatement?: (ctx: IfStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifExpression`. - * @param ctx the parse tree - */ - enterIfExpression?: (ctx: IfExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifExpression`. - * @param ctx the parse tree - */ - exitIfExpression?: (ctx: IfExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - */ - enterElseStatement?: (ctx: ElseStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - */ - exitElseStatement?: (ctx: ElseStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - */ - enterWhileStatement?: (ctx: WhileStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - */ - exitWhileStatement?: (ctx: WhileStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.whileExpression`. - * @param ctx the parse tree - */ - enterWhileExpression?: (ctx: WhileExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.whileExpression`. - * @param ctx the parse tree - */ - exitWhileExpression?: (ctx: WhileExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - */ - enterDoStatement?: (ctx: DoStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - */ - exitDoStatement?: (ctx: DoStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - */ - enterSubroutineCall?: (ctx: SubroutineCallContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - */ - exitSubroutineCall?: (ctx: SubroutineCallContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - */ - enterSubroutineId?: (ctx: SubroutineIdContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - */ - exitSubroutineId?: (ctx: SubroutineIdContext) => void; - /** - * Enter a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - */ - enterReturnStatement?: (ctx: ReturnStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - */ - exitReturnStatement?: (ctx: ReturnStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - */ - enterExpressionList?: (ctx: ExpressionListContext) => void; - /** - * Exit a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - */ - exitExpressionList?: (ctx: ExpressionListContext) => void; - /** - * Enter a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - */ - enterExpression?: (ctx: ExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - */ - exitExpression?: (ctx: ExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - */ - enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - */ - exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - */ - enterUnaryOperation?: (ctx: UnaryOperationContext) => void; - /** - * Exit a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - */ - exitUnaryOperation?: (ctx: UnaryOperationContext) => void; - /** - * Enter a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - */ - enterArrayAccess?: (ctx: ArrayAccessContext) => void; - /** - * Exit a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - */ - exitArrayAccess?: (ctx: ArrayAccessContext) => void; - /** - * Enter a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - */ - enterConstant?: (ctx: ConstantContext) => void; - /** - * Exit a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - */ - exitConstant?: (ctx: ConstantContext) => void; - /** - * Enter a parse tree produced by `JackParser.booleanLiteral`. - * @param ctx the parse tree - */ - enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; - /** - * Exit a parse tree produced by `JackParser.booleanLiteral`. - * @param ctx the parse tree - */ - exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; - /** - * Enter a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - */ - enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; - /** - * Exit a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - */ - exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; - /** - * Enter a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - */ - enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; - /** - * Exit a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - */ - exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; + /** + * Enter a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + enterProgram?: (ctx: ProgramContext) => void; + /** + * Exit a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + exitProgram?: (ctx: ProgramContext) => void; + /** + * Enter a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + enterClassName?: (ctx: ClassNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + exitClassName?: (ctx: ClassNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + enterClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Exit a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + exitClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Enter a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + enterFieldList?: (ctx: FieldListContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + exitFieldList?: (ctx: FieldListContext) => void; + /** + * Enter a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + enterFieldName?: (ctx: FieldNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + exitFieldName?: (ctx: FieldNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineDeclaration`. + * @param ctx the parse tree + */ + enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDeclaration`. + * @param ctx the parse tree + */ + exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + enterSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + exitSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + enterSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + enterSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + exitSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + enterVarType?: (ctx: VarTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + exitVarType?: (ctx: VarTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + enterParameterList?: (ctx: ParameterListContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + exitParameterList?: (ctx: ParameterListContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + enterParameter?: (ctx: ParameterContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + exitParameter?: (ctx: ParameterContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + enterParameterName?: (ctx: ParameterNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + exitParameterName?: (ctx: ParameterNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Enter a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + enterRBrace?: (ctx: RBraceContext) => void; + /** + * Exit a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + exitRBrace?: (ctx: RBraceContext) => void; + /** + * Enter a parse tree produced by `JackParser.varDeclaration`. + * @param ctx the parse tree + */ + enterVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varDeclaration`. + * @param ctx the parse tree + */ + exitVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + enterStatements?: (ctx: StatementsContext) => void; + /** + * Exit a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + exitStatements?: (ctx: StatementsContext) => void; + /** + * Enter a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + enterStatement?: (ctx: StatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + exitStatement?: (ctx: StatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + enterLetStatement?: (ctx: LetStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + exitLetStatement?: (ctx: LetStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.equals`. + * @param ctx the parse tree + */ + enterEquals?: (ctx: EqualsContext) => void; + /** + * Exit a parse tree produced by `JackParser.equals`. + * @param ctx the parse tree + */ + exitEquals?: (ctx: EqualsContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + enterIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + exitIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + enterIfStatement?: (ctx: IfStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + exitIfStatement?: (ctx: IfStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifExpression`. + * @param ctx the parse tree + */ + enterIfExpression?: (ctx: IfExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifExpression`. + * @param ctx the parse tree + */ + exitIfExpression?: (ctx: IfExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + enterElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + exitElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + enterWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + exitWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.whileExpression`. + * @param ctx the parse tree + */ + enterWhileExpression?: (ctx: WhileExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileExpression`. + * @param ctx the parse tree + */ + exitWhileExpression?: (ctx: WhileExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + enterDoStatement?: (ctx: DoStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + exitDoStatement?: (ctx: DoStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + enterSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + exitSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + enterSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + exitSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Enter a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + enterReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + exitReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + enterExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Exit a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + exitExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Enter a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + enterExpression?: (ctx: ExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + exitExpression?: (ctx: ExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + enterConstant?: (ctx: ConstantContext) => void; + /** + * Exit a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + exitConstant?: (ctx: ConstantContext) => void; + /** + * Enter a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + enterVarName?: (ctx: VarNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + exitVarName?: (ctx: VarNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + enterArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Exit a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + exitArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Enter a parse tree produced by `JackParser.unaryOperation`. + * @param ctx the parse tree + */ + enterUnaryOperation?: (ctx: UnaryOperationContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperation`. + * @param ctx the parse tree + */ + exitUnaryOperation?: (ctx: UnaryOperationContext) => void; + /** + * Enter a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.booleanLiteral`. + * @param ctx the parse tree + */ + enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Exit a parse tree produced by `JackParser.booleanLiteral`. + * @param ctx the parse tree + */ + exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Enter a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Enter a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; } + From 773cf3d9157877ea8d99a9a4500b081ac74d25e4 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 20 Oct 2024 10:54:20 +0200 Subject: [PATCH 75/87] Migrate to antlr4ng --- package-lock.json | 24 +- simulator/package.json | 7 +- simulator/src/jack/anltr.compiler.ts | 28 +- simulator/src/jack/error.ts | 52 +- simulator/src/jack/generated/JackLexer.ts | 468 +- simulator/src/jack/generated/JackParser.ts | 6166 ++++++++--------- .../src/jack/generated/JackParserListener.ts | 871 +-- simulator/src/jack/listener/common.ts | 18 +- simulator/src/jack/listener/error.listener.ts | 98 +- ....listener.ts => global.symbol.listener.ts} | 63 +- .../global.symbol.table.listener.test.ts | 119 - .../jack/listener/validator.listener.test.ts | 824 --- .../src/jack/listener/validator.listener.ts | 322 +- .../src/jack/listener/vm.writer.listener.ts | 123 +- simulator/src/jack/parser.test.ts | 4 +- simulator/src/jack/simulator.code-workspace | 11 + simulator/src/jack/symbol.ts | 1 + simulator/src/jack/test.helper.ts | 26 +- 18 files changed, 4151 insertions(+), 5074 deletions(-) rename simulator/src/jack/listener/{global.symbol.table.listener.ts => global.symbol.listener.ts} (63%) delete mode 100644 simulator/src/jack/listener/global.symbol.table.listener.test.ts delete mode 100644 simulator/src/jack/listener/validator.listener.test.ts create mode 100644 simulator/src/jack/simulator.code-workspace diff --git a/package-lock.json b/package-lock.json index 8b4d34ef..004e3b20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5341,13 +5341,22 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/antlr4": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.2.tgz", - "integrity": "sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==", + "node_modules/antlr4ng": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/antlr4ng/-/antlr4ng-3.0.7.tgz", + "integrity": "sha512-e9VzrS6fErCUTmkZX2eKEMCsmYY87gVhmHkzmOXtUDgvwGhivUvtiHqlOByDx4Nd1PIQ0lMlhflOWEz6cGXqKA==", "license": "BSD-3-Clause", - "engines": { - "node": ">=16" + "peerDependencies": { + "antlr4ng-cli": "^2.0.0" + } + }, + "node_modules/antlr4ng-cli": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/antlr4ng-cli/-/antlr4ng-cli-2.0.0.tgz", + "integrity": "sha512-oAt5OSSYhRQn1PgahtpAP4Vp3BApCoCqlzX7Q8ZUWWls4hX59ryYuu0t7Hwrnfk796OxP/vgIJaqxdltd/oEvQ==", + "license": "BSD-3-Clause", + "bin": { + "antlr4ng": "index.js" } }, "node_modules/any-promise": { @@ -22624,13 +22633,14 @@ "@nand2tetris/projects": "^1.0.0", "@nand2tetris/runner": "^1.0.0", "@types/node": "^20.14.2", - "antlr4": "^4.13.2", + "antlr4ng": "^3.0.7", "ohm-js": "^17.1.0", "rxjs": "^7.8.1" }, "devDependencies": { "@babel/preset-typescript": "^7.24.7", "@types/jest": "^29.5.12", + "antlr4ng-cli": "^2.0.0", "babel-jest": "^29.7.0", "jest": "^29.7.0", "jest-ts-webcompat-resolver": "^1.0.0", diff --git a/simulator/package.json b/simulator/package.json index a645cf30..3982e502 100644 --- a/simulator/package.json +++ b/simulator/package.json @@ -22,13 +22,14 @@ "@nand2tetris/projects": "^1.0.0", "@nand2tetris/runner": "^1.0.0", "@types/node": "^20.14.2", - "antlr4": "^4.13.2", + "antlr4ng": "^3.0.7", "ohm-js": "^17.1.0", "rxjs": "^7.8.1" }, "devDependencies": { "@babel/preset-typescript": "^7.24.7", "@types/jest": "^29.5.12", + "antlr4ng-cli": "^2.0.0", "babel-jest": "^29.7.0", "jest": "^29.7.0", "jest-ts-webcompat-resolver": "^1.0.0", @@ -37,6 +38,8 @@ "scripts": { "build": "tsc", "test": "jest --verbose", - "gen": "cd src/languages/grammars && antlr4 -v 4.13.2 -Dlanguage=TypeScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" + "test-jack": "npm run test -- -t \"Jack\"", + "test-jack-w": "npm run test-w -- -t \"Jack\"", + "gen": "cd src/languages/grammars && antlr4ng -Dlanguage=TypeScript JackLexer.g4 JackParser.g4 -o ../../jack/generated" } } diff --git a/simulator/src/jack/anltr.compiler.ts b/simulator/src/jack/anltr.compiler.ts index 85d147dd..894af679 100644 --- a/simulator/src/jack/anltr.compiler.ts +++ b/simulator/src/jack/anltr.compiler.ts @@ -1,11 +1,13 @@ -import { JackGlobalSymbolTableListener } from "./listener/global.symbol.table.listener.js"; -import { JackCustomErrorListener } from "./listener/error.listener.js"; -import { JackValidatorListener } from "./listener/validator.listener.js"; + +import { GlobalSymbolTableListener } from "./listener/global.symbol.listener.js"; +import { CustomErrorListener } from "./listener/error.listener.js"; +import { ValidatorListener } from "./listener/validator.listener.js"; import { JackCompilerError, LexerOrParserError } from "./error.js"; -import { JackVMWriter } from "./listener/vm.writer.listener.js"; -import JackParser, { ProgramContext } from "./generated/JackParser.js"; -import { CharStreams, CommonTokenStream, ParseTreeWalker } from "antlr4"; -import JackLexer from "./generated/JackLexer.js"; +import { VMWriter } from "./listener/vm.writer.listener.js"; +import { GlobalSymbolTable } from "./symbol.js"; +import { JackParser, ProgramContext } from "./generated/JackParser.js"; +import { JackLexer } from "./generated/JackLexer.js"; +import { CharStream, CommonTokenStream, ParseTreeWalker } from "antlr4ng"; import { CompilationError } from "../languages/base.js"; export function compile( @@ -97,14 +99,14 @@ function _do( function toCompilerError(errors: JackCompilerError[]): CompilationError { const err = errors[0]; return { - message: `Line ${err.span.line}: ${err.message}`, + message: `Line ${err.span.line}: ${err.msg}`, span: err.span, } as CompilationError; } export class JackCompiler { - private globalSymbolTableListener = new JackGlobalSymbolTableListener(); - private errorListener = new JackCustomErrorListener(); + private globalSymbolTableListener = new GlobalSymbolTableListener(); + private errorListener = new CustomErrorListener(); validate( tree: ProgramContext, filename?: string, @@ -114,7 +116,7 @@ export class JackCompiler { "Please populate global symbol table using parserAndBind method", ); } - const validator = new JackValidatorListener( + const validator = new ValidatorListener( this.globalSymbolTableListener.globalSymbolTable, filename, ); @@ -133,13 +135,13 @@ export class JackCompiler { return errors; } const validateTree = treeOrErrors as ProgramContext; - const vmWriter = new JackVMWriter(this.globalSymbolTableListener.globalSymbolTable); + const vmWriter = new VMWriter(this.globalSymbolTableListener.globalSymbolTable); ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); return vmWriter.result; } parserAndBind(src: string): ProgramContext | JackCompilerError[] { - const lexer = new JackLexer(CharStreams.fromString(src)); + const lexer = new JackLexer(CharStream.fromString(src)); lexer.removeErrorListeners(); lexer.addErrorListener(this.errorListener); const tokenStream = new CommonTokenStream(lexer); diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index e66efcd3..da4cd76b 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,11 +1,31 @@ -import { Token } from "antlr4"; -import { CompilationError, Span } from "../languages/base"; +import { ParserRuleContext, TerminalNode } from "antlr4ng"; +import { assertExists } from "./listener/common"; -/** Utility to convert an antlr Token to a nand2tetris Span */ -export const asSpan = ( - { line, start, stop: startEnd }: Token, - stop?: Token -): Span => ({ line, start, end: stop ? stop.stop : startEnd }); +export interface Span { + start: number; + end: number; + line: number; +} +export const terminalNodeToSpan = (node: TerminalNode): Span => { + const s = node.getSymbol(); + return { + line: s.line, + start: s.start, + end: s.stop + 1, + }; +}; + +export const ruleContextToSpan = (ctx: ParserRuleContext): Span => { + const start = assertExists( + ctx.start, + " Cannot find start token when creating an error" + ); + return { + line: start.line, + start: start.start, + end: ctx.stop ? ctx.stop.stop + 1 : start.stop, + }; +}; export type JackCompilerErrorType = | "ConstructorMushReturnThisError" @@ -30,20 +50,21 @@ export type JackCompilerErrorType = | "VoidSubroutineReturnsValueError" | "WrongLiteralTypeError"; -export interface JackCompilerError extends CompilationError { +export interface JackCompilerError { type: JackCompilerErrorType; span: Span; + msg: string; } export function makeJackCompilerError( type: JackCompilerErrorType, span: Span, - msg?: string + msg: string ): JackCompilerError { return { type, span, - message: `${type} (${span.line}:${span.start}:${span.end}${msg ? " " + msg : ""})`, + msg, }; } @@ -116,8 +137,7 @@ export const IncorrectParamsNumberInSubroutineCallError = ( makeJackCompilerError( "IncorrectParamsNumberInSubroutineCallError", span, - `Subroutine ${subroutineName} (declared to accept ${expectedParamsCount} parameter(s)) called with ${actualParamsCount} parameter(s)` - ); + `Expected ${expectedParamsCount} arguments, but got ${actualParamsCount}`); export const IntLiteralIsOutOfRangeError = ( span: Span, @@ -131,7 +151,7 @@ export const IntLiteralIsOutOfRangeError = ( `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}` ); -export const LexerOrParserError = (span: Span, msg?: string) => +export const LexerOrParserError = (span: Span, msg: string) => makeJackCompilerError("LexerOrParserError", span, msg); export const MethodCalledAsFunctionError = (span: Span, subroutineId: string) => @@ -191,7 +211,7 @@ export const UnknownSubroutineCallError = ( ); export const UnreachableCodeError = (span: Span) => - makeJackCompilerError("UnreachableCodeError", span); + makeJackCompilerError("UnreachableCodeError", span, `Unreachable code`); export const VoidSubroutineReturnsValueError = (span: Span) => makeJackCompilerError( @@ -200,9 +220,9 @@ export const VoidSubroutineReturnsValueError = (span: Span) => "Cannot return a value from a void subroutine" ); -export const WrongLiteralTypeError = (span: Span, typeName: string) => +export const WrongLiteralTypeError = (span: Span, expectedTypeName: string, actualTypeName:string) => makeJackCompilerError( "WrongLiteralTypeError", span, - `Value is expected to be of type ${typeName}` + `Cannot assign ${actualTypeName} type to ${expectedTypeName}` ); diff --git a/simulator/src/jack/generated/JackLexer.ts b/simulator/src/jack/generated/JackLexer.ts index 20e4ea64..27c7f43a 100644 --- a/simulator/src/jack/generated/JackLexer.ts +++ b/simulator/src/jack/generated/JackLexer.ts @@ -1,260 +1,238 @@ -// Generated from JackLexer.g4 by ANTLR 4.13.2 -// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols -import { - ATN, - ATNDeserializer, - CharStream, - DecisionState, DFA, - Lexer, - LexerATNSimulator, - RuleContext, - PredictionContextCache, - Token -} from "antlr4"; -export default class JackLexer extends Lexer { - public static readonly CLASS = 1; - public static readonly CONSTRUCTOR = 2; - public static readonly FUNCTION = 3; - public static readonly METHOD = 4; - public static readonly FIELD = 5; - public static readonly STATIC = 6; - public static readonly VAR = 7; - public static readonly INT = 8; - public static readonly CHAR = 9; - public static readonly BOOLEAN = 10; - public static readonly VOID = 11; - public static readonly LET = 12; - public static readonly DO = 13; - public static readonly IF = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly RETURN = 17; - public static readonly LBRACE = 18; - public static readonly RBRACE = 19; - public static readonly LPAREN = 20; - public static readonly RPAREN = 21; - public static readonly LBRACKET = 22; - public static readonly RBRACKET = 23; - public static readonly DOT = 24; - public static readonly COMMA = 25; - public static readonly SEMICOLON = 26; - public static readonly EQUALS = 27; - public static readonly PLUS = 28; - public static readonly MINUS = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly AND = 32; - public static readonly OR = 33; - public static readonly TILDE = 34; - public static readonly LESS_THAN = 35; - public static readonly GREATER_THAN = 36; - public static readonly WHITESPACE = 37; - public static readonly BLOCK_COMMENT = 38; - public static readonly LINE_COMMENT = 39; - public static readonly INTEGER_LITERAL = 40; - public static readonly TRUE = 41; - public static readonly FALSE = 42; - public static readonly NULL_LITERAL = 43; - public static readonly THIS_LITERAL = 44; - public static readonly IDENTIFIER = 45; - public static readonly STRING_LITERAL = 46; - public static readonly EOF = Token.EOF; +// Generated from JackLexer.g4 by ANTLR 4.13.1 - public static readonly channelNames: string[] = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ]; - public static readonly literalNames: (string | null)[] = [ null, "'class'", - "'constructor'", - "'function'", - "'method'", - "'field'", "'static'", - "'var'", "'int'", - "'char'", "'boolean'", - "'void'", "'let'", - "'do'", "'if'", - "'else'", "'while'", - "'return'", - "'{'", "'}'", - "'('", "')'", - "'['", "']'", - "'.'", "','", - "';'", "'='", - "'+'", "'-'", - "'*'", "'/'", - "'&'", "'|'", - "'~'", "'<'", - "'>'", null, - null, null, - null, "'true'", - "'false'", "'null'", - "'this'" ]; - public static readonly symbolicNames: (string | null)[] = [ null, "CLASS", - "CONSTRUCTOR", - "FUNCTION", - "METHOD", "FIELD", - "STATIC", "VAR", - "INT", "CHAR", - "BOOLEAN", - "VOID", "LET", - "DO", "IF", - "ELSE", "WHILE", - "RETURN", "LBRACE", - "RBRACE", "LPAREN", - "RPAREN", "LBRACKET", - "RBRACKET", - "DOT", "COMMA", - "SEMICOLON", - "EQUALS", "PLUS", - "MINUS", "MUL", - "DIV", "AND", - "OR", "TILDE", - "LESS_THAN", - "GREATER_THAN", - "WHITESPACE", - "BLOCK_COMMENT", - "LINE_COMMENT", - "INTEGER_LITERAL", - "TRUE", "FALSE", - "NULL_LITERAL", - "THIS_LITERAL", - "IDENTIFIER", - "STRING_LITERAL" ]; - public static readonly modeNames: string[] = [ "DEFAULT_MODE", ]; +import * as antlr from "antlr4ng"; +import { Token } from "antlr4ng"; - public static readonly ruleNames: string[] = [ - "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", "VAR", - "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", "WHILE", - "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", "RBRACKET", - "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", "MUL", "DIV", - "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", "WHITESPACE", "BLOCK_COMMENT", - "LINE_COMMENT", "INTEGER_LITERAL", "TRUE", "FALSE", "NULL_LITERAL", "THIS_LITERAL", - "IDENTIFIER", "STRING_LITERAL", - ]; +export class JackLexer extends antlr.Lexer { + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WHITESPACE = 37; + public static readonly BLOCK_COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly TRUE = 41; + public static readonly FALSE = 42; + public static readonly NULL_LITERAL = 43; + public static readonly THIS_LITERAL = 44; + public static readonly IDENTIFIER = 45; + public static readonly STRING_LITERAL = 46; - constructor(input: CharStream) { - super(input); - this._interp = new LexerATNSimulator(this, JackLexer._ATN, JackLexer.DecisionsToDFA, new PredictionContextCache()); - } + public static readonly channelNames = [ + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + ]; - public get grammarFileName(): string { return "JackLexer.g4"; } + public static readonly literalNames = [ + null, "'class'", "'constructor'", "'function'", "'method'", "'field'", + "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", + "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", + "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", + "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", null, null, null, null, + "'true'", "'false'", "'null'", "'this'" + ]; - public get literalNames(): (string | null)[] { return JackLexer.literalNames; } - public get symbolicNames(): (string | null)[] { return JackLexer.symbolicNames; } - public get ruleNames(): string[] { return JackLexer.ruleNames; } + public static readonly symbolicNames = [ + null, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", + "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", + "WHILE", "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", + "RBRACKET", "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", + "MUL", "DIV", "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", + "WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT", "INTEGER_LITERAL", + "TRUE", "FALSE", "NULL_LITERAL", "THIS_LITERAL", "IDENTIFIER", "STRING_LITERAL" + ]; - public get serializedATN(): number[] { return JackLexer._serializedATN; } + public static readonly modeNames = [ + "DEFAULT_MODE", + ]; - public get channelNames(): string[] { return JackLexer.channelNames; } + public static readonly ruleNames = [ + "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", + "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", + "WHILE", "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", + "RBRACKET", "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", + "MUL", "DIV", "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", + "WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT", "INTEGER_LITERAL", + "TRUE", "FALSE", "NULL_LITERAL", "THIS_LITERAL", "IDENTIFIER", "STRING_LITERAL", + ]; - public get modeNames(): string[] { return JackLexer.modeNames; } - public static readonly _serializedATN: number[] = [4,0,46,308,6,-1,2,0, - 7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9, - 7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7, - 16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23, - 2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2, - 31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38, - 7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7, - 45,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,4, - 1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,7,1,7, - 1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1, - 10,1,10,1,10,1,11,1,11,1,11,1,11,1,12,1,12,1,12,1,13,1,13,1,13,1,14,1,14, - 1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,16,1,16,1,16,1,16,1,16,1, - 16,1,16,1,17,1,17,1,18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23, - 1,23,1,24,1,24,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,1, - 30,1,31,1,31,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,36,4,36,234,8,36, - 11,36,12,36,235,1,36,1,36,1,37,1,37,1,37,1,37,5,37,244,8,37,10,37,12,37, - 247,9,37,1,37,1,37,1,37,3,37,252,8,37,1,37,1,37,1,38,1,38,1,38,1,38,5,38, - 260,8,38,10,38,12,38,263,9,38,1,38,1,38,1,39,4,39,268,8,39,11,39,12,39, - 269,1,40,1,40,1,40,1,40,1,40,1,41,1,41,1,41,1,41,1,41,1,41,1,42,1,42,1, - 42,1,42,1,42,1,43,1,43,1,43,1,43,1,43,1,44,1,44,5,44,295,8,44,10,44,12, - 44,298,9,44,1,45,1,45,5,45,302,8,45,10,45,12,45,305,9,45,1,45,1,45,1,245, - 0,46,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27, - 14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51, - 26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,71,36,73,37,75, - 38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,46,1,0,6,3,0,9,10,12,13, - 32,32,2,0,10,10,13,13,1,0,48,57,3,0,65,90,95,95,97,122,4,0,48,57,65,90, - 95,95,97,122,3,0,10,10,13,13,34,34,314,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0, - 0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17, - 1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0, - 0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39, - 1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0, - 0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61, - 1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0, - 0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83, - 1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,1,93,1,0,0, - 0,3,99,1,0,0,0,5,111,1,0,0,0,7,120,1,0,0,0,9,127,1,0,0,0,11,133,1,0,0,0, - 13,140,1,0,0,0,15,144,1,0,0,0,17,148,1,0,0,0,19,153,1,0,0,0,21,161,1,0, - 0,0,23,166,1,0,0,0,25,170,1,0,0,0,27,173,1,0,0,0,29,176,1,0,0,0,31,181, - 1,0,0,0,33,187,1,0,0,0,35,194,1,0,0,0,37,196,1,0,0,0,39,198,1,0,0,0,41, - 200,1,0,0,0,43,202,1,0,0,0,45,204,1,0,0,0,47,206,1,0,0,0,49,208,1,0,0,0, - 51,210,1,0,0,0,53,212,1,0,0,0,55,214,1,0,0,0,57,216,1,0,0,0,59,218,1,0, - 0,0,61,220,1,0,0,0,63,222,1,0,0,0,65,224,1,0,0,0,67,226,1,0,0,0,69,228, - 1,0,0,0,71,230,1,0,0,0,73,233,1,0,0,0,75,239,1,0,0,0,77,255,1,0,0,0,79, - 267,1,0,0,0,81,271,1,0,0,0,83,276,1,0,0,0,85,282,1,0,0,0,87,287,1,0,0,0, - 89,292,1,0,0,0,91,299,1,0,0,0,93,94,5,99,0,0,94,95,5,108,0,0,95,96,5,97, - 0,0,96,97,5,115,0,0,97,98,5,115,0,0,98,2,1,0,0,0,99,100,5,99,0,0,100,101, - 5,111,0,0,101,102,5,110,0,0,102,103,5,115,0,0,103,104,5,116,0,0,104,105, - 5,114,0,0,105,106,5,117,0,0,106,107,5,99,0,0,107,108,5,116,0,0,108,109, - 5,111,0,0,109,110,5,114,0,0,110,4,1,0,0,0,111,112,5,102,0,0,112,113,5,117, - 0,0,113,114,5,110,0,0,114,115,5,99,0,0,115,116,5,116,0,0,116,117,5,105, - 0,0,117,118,5,111,0,0,118,119,5,110,0,0,119,6,1,0,0,0,120,121,5,109,0,0, - 121,122,5,101,0,0,122,123,5,116,0,0,123,124,5,104,0,0,124,125,5,111,0,0, - 125,126,5,100,0,0,126,8,1,0,0,0,127,128,5,102,0,0,128,129,5,105,0,0,129, - 130,5,101,0,0,130,131,5,108,0,0,131,132,5,100,0,0,132,10,1,0,0,0,133,134, - 5,115,0,0,134,135,5,116,0,0,135,136,5,97,0,0,136,137,5,116,0,0,137,138, - 5,105,0,0,138,139,5,99,0,0,139,12,1,0,0,0,140,141,5,118,0,0,141,142,5,97, - 0,0,142,143,5,114,0,0,143,14,1,0,0,0,144,145,5,105,0,0,145,146,5,110,0, - 0,146,147,5,116,0,0,147,16,1,0,0,0,148,149,5,99,0,0,149,150,5,104,0,0,150, - 151,5,97,0,0,151,152,5,114,0,0,152,18,1,0,0,0,153,154,5,98,0,0,154,155, - 5,111,0,0,155,156,5,111,0,0,156,157,5,108,0,0,157,158,5,101,0,0,158,159, - 5,97,0,0,159,160,5,110,0,0,160,20,1,0,0,0,161,162,5,118,0,0,162,163,5,111, - 0,0,163,164,5,105,0,0,164,165,5,100,0,0,165,22,1,0,0,0,166,167,5,108,0, - 0,167,168,5,101,0,0,168,169,5,116,0,0,169,24,1,0,0,0,170,171,5,100,0,0, - 171,172,5,111,0,0,172,26,1,0,0,0,173,174,5,105,0,0,174,175,5,102,0,0,175, - 28,1,0,0,0,176,177,5,101,0,0,177,178,5,108,0,0,178,179,5,115,0,0,179,180, - 5,101,0,0,180,30,1,0,0,0,181,182,5,119,0,0,182,183,5,104,0,0,183,184,5, - 105,0,0,184,185,5,108,0,0,185,186,5,101,0,0,186,32,1,0,0,0,187,188,5,114, - 0,0,188,189,5,101,0,0,189,190,5,116,0,0,190,191,5,117,0,0,191,192,5,114, - 0,0,192,193,5,110,0,0,193,34,1,0,0,0,194,195,5,123,0,0,195,36,1,0,0,0,196, - 197,5,125,0,0,197,38,1,0,0,0,198,199,5,40,0,0,199,40,1,0,0,0,200,201,5, - 41,0,0,201,42,1,0,0,0,202,203,5,91,0,0,203,44,1,0,0,0,204,205,5,93,0,0, - 205,46,1,0,0,0,206,207,5,46,0,0,207,48,1,0,0,0,208,209,5,44,0,0,209,50, - 1,0,0,0,210,211,5,59,0,0,211,52,1,0,0,0,212,213,5,61,0,0,213,54,1,0,0,0, - 214,215,5,43,0,0,215,56,1,0,0,0,216,217,5,45,0,0,217,58,1,0,0,0,218,219, - 5,42,0,0,219,60,1,0,0,0,220,221,5,47,0,0,221,62,1,0,0,0,222,223,5,38,0, - 0,223,64,1,0,0,0,224,225,5,124,0,0,225,66,1,0,0,0,226,227,5,126,0,0,227, - 68,1,0,0,0,228,229,5,60,0,0,229,70,1,0,0,0,230,231,5,62,0,0,231,72,1,0, - 0,0,232,234,7,0,0,0,233,232,1,0,0,0,234,235,1,0,0,0,235,233,1,0,0,0,235, - 236,1,0,0,0,236,237,1,0,0,0,237,238,6,36,0,0,238,74,1,0,0,0,239,240,5,47, - 0,0,240,241,5,42,0,0,241,245,1,0,0,0,242,244,9,0,0,0,243,242,1,0,0,0,244, - 247,1,0,0,0,245,246,1,0,0,0,245,243,1,0,0,0,246,251,1,0,0,0,247,245,1,0, - 0,0,248,249,5,42,0,0,249,252,5,47,0,0,250,252,5,0,0,1,251,248,1,0,0,0,251, - 250,1,0,0,0,252,253,1,0,0,0,253,254,6,37,0,0,254,76,1,0,0,0,255,256,5,47, - 0,0,256,257,5,47,0,0,257,261,1,0,0,0,258,260,8,1,0,0,259,258,1,0,0,0,260, - 263,1,0,0,0,261,259,1,0,0,0,261,262,1,0,0,0,262,264,1,0,0,0,263,261,1,0, - 0,0,264,265,6,38,0,0,265,78,1,0,0,0,266,268,7,2,0,0,267,266,1,0,0,0,268, - 269,1,0,0,0,269,267,1,0,0,0,269,270,1,0,0,0,270,80,1,0,0,0,271,272,5,116, - 0,0,272,273,5,114,0,0,273,274,5,117,0,0,274,275,5,101,0,0,275,82,1,0,0, - 0,276,277,5,102,0,0,277,278,5,97,0,0,278,279,5,108,0,0,279,280,5,115,0, - 0,280,281,5,101,0,0,281,84,1,0,0,0,282,283,5,110,0,0,283,284,5,117,0,0, - 284,285,5,108,0,0,285,286,5,108,0,0,286,86,1,0,0,0,287,288,5,116,0,0,288, - 289,5,104,0,0,289,290,5,105,0,0,290,291,5,115,0,0,291,88,1,0,0,0,292,296, - 7,3,0,0,293,295,7,4,0,0,294,293,1,0,0,0,295,298,1,0,0,0,296,294,1,0,0,0, - 296,297,1,0,0,0,297,90,1,0,0,0,298,296,1,0,0,0,299,303,5,34,0,0,300,302, - 8,5,0,0,301,300,1,0,0,0,302,305,1,0,0,0,303,301,1,0,0,0,303,304,1,0,0,0, - 304,306,1,0,0,0,305,303,1,0,0,0,306,307,5,34,0,0,307,92,1,0,0,0,8,0,235, - 245,251,261,269,296,303,1,0,1,0]; + public constructor(input: antlr.CharStream) { + super(input); + this.interpreter = new antlr.LexerATNSimulator(this, JackLexer._ATN, JackLexer.decisionsToDFA, new antlr.PredictionContextCache()); + } - private static __ATN: ATN; - public static get _ATN(): ATN { - if (!JackLexer.__ATN) { - JackLexer.__ATN = new ATNDeserializer().deserialize(JackLexer._serializedATN); - } + public get grammarFileName(): string { return "JackLexer.g4"; } - return JackLexer.__ATN; - } + public get literalNames(): (string | null)[] { return JackLexer.literalNames; } + public get symbolicNames(): (string | null)[] { return JackLexer.symbolicNames; } + public get ruleNames(): string[] { return JackLexer.ruleNames; } + public get serializedATN(): number[] { return JackLexer._serializedATN; } - static DecisionsToDFA = JackLexer._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) ); + public get channelNames(): string[] { return JackLexer.channelNames; } + + public get modeNames(): string[] { return JackLexer.modeNames; } + + public static readonly _serializedATN: number[] = [ + 4,0,46,308,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5, + 2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2, + 13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7, + 19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2, + 26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7, + 32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2, + 39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7, + 45,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1, + 3,1,3,1,3,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1, + 6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1, + 9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,11,1,11,1,11,1,11,1, + 12,1,12,1,12,1,13,1,13,1,13,1,14,1,14,1,14,1,14,1,14,1,15,1,15,1, + 15,1,15,1,15,1,15,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1, + 18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,24,1, + 24,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,1,30,1, + 31,1,31,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,36,4,36,234,8, + 36,11,36,12,36,235,1,36,1,36,1,37,1,37,1,37,1,37,5,37,244,8,37,10, + 37,12,37,247,9,37,1,37,1,37,1,37,3,37,252,8,37,1,37,1,37,1,38,1, + 38,1,38,1,38,5,38,260,8,38,10,38,12,38,263,9,38,1,38,1,38,1,39,4, + 39,268,8,39,11,39,12,39,269,1,40,1,40,1,40,1,40,1,40,1,41,1,41,1, + 41,1,41,1,41,1,41,1,42,1,42,1,42,1,42,1,42,1,43,1,43,1,43,1,43,1, + 43,1,44,1,44,5,44,295,8,44,10,44,12,44,298,9,44,1,45,1,45,5,45,302, + 8,45,10,45,12,45,305,9,45,1,45,1,45,1,245,0,46,1,1,3,2,5,3,7,4,9, + 5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27,14,29,15,31,16, + 33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27, + 55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,71,36,73,37,75,38, + 77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,46,1,0,6,3,0,9,10,12, + 13,32,32,2,0,10,10,13,13,1,0,48,57,3,0,65,90,95,95,97,122,4,0,48, + 57,65,90,95,95,97,122,3,0,10,10,13,13,34,34,314,0,1,1,0,0,0,0,3, + 1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1, + 0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1, + 0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1, + 0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1, + 0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1, + 0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1, + 0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1, + 0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1, + 0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,1,93,1, + 0,0,0,3,99,1,0,0,0,5,111,1,0,0,0,7,120,1,0,0,0,9,127,1,0,0,0,11, + 133,1,0,0,0,13,140,1,0,0,0,15,144,1,0,0,0,17,148,1,0,0,0,19,153, + 1,0,0,0,21,161,1,0,0,0,23,166,1,0,0,0,25,170,1,0,0,0,27,173,1,0, + 0,0,29,176,1,0,0,0,31,181,1,0,0,0,33,187,1,0,0,0,35,194,1,0,0,0, + 37,196,1,0,0,0,39,198,1,0,0,0,41,200,1,0,0,0,43,202,1,0,0,0,45,204, + 1,0,0,0,47,206,1,0,0,0,49,208,1,0,0,0,51,210,1,0,0,0,53,212,1,0, + 0,0,55,214,1,0,0,0,57,216,1,0,0,0,59,218,1,0,0,0,61,220,1,0,0,0, + 63,222,1,0,0,0,65,224,1,0,0,0,67,226,1,0,0,0,69,228,1,0,0,0,71,230, + 1,0,0,0,73,233,1,0,0,0,75,239,1,0,0,0,77,255,1,0,0,0,79,267,1,0, + 0,0,81,271,1,0,0,0,83,276,1,0,0,0,85,282,1,0,0,0,87,287,1,0,0,0, + 89,292,1,0,0,0,91,299,1,0,0,0,93,94,5,99,0,0,94,95,5,108,0,0,95, + 96,5,97,0,0,96,97,5,115,0,0,97,98,5,115,0,0,98,2,1,0,0,0,99,100, + 5,99,0,0,100,101,5,111,0,0,101,102,5,110,0,0,102,103,5,115,0,0,103, + 104,5,116,0,0,104,105,5,114,0,0,105,106,5,117,0,0,106,107,5,99,0, + 0,107,108,5,116,0,0,108,109,5,111,0,0,109,110,5,114,0,0,110,4,1, + 0,0,0,111,112,5,102,0,0,112,113,5,117,0,0,113,114,5,110,0,0,114, + 115,5,99,0,0,115,116,5,116,0,0,116,117,5,105,0,0,117,118,5,111,0, + 0,118,119,5,110,0,0,119,6,1,0,0,0,120,121,5,109,0,0,121,122,5,101, + 0,0,122,123,5,116,0,0,123,124,5,104,0,0,124,125,5,111,0,0,125,126, + 5,100,0,0,126,8,1,0,0,0,127,128,5,102,0,0,128,129,5,105,0,0,129, + 130,5,101,0,0,130,131,5,108,0,0,131,132,5,100,0,0,132,10,1,0,0,0, + 133,134,5,115,0,0,134,135,5,116,0,0,135,136,5,97,0,0,136,137,5,116, + 0,0,137,138,5,105,0,0,138,139,5,99,0,0,139,12,1,0,0,0,140,141,5, + 118,0,0,141,142,5,97,0,0,142,143,5,114,0,0,143,14,1,0,0,0,144,145, + 5,105,0,0,145,146,5,110,0,0,146,147,5,116,0,0,147,16,1,0,0,0,148, + 149,5,99,0,0,149,150,5,104,0,0,150,151,5,97,0,0,151,152,5,114,0, + 0,152,18,1,0,0,0,153,154,5,98,0,0,154,155,5,111,0,0,155,156,5,111, + 0,0,156,157,5,108,0,0,157,158,5,101,0,0,158,159,5,97,0,0,159,160, + 5,110,0,0,160,20,1,0,0,0,161,162,5,118,0,0,162,163,5,111,0,0,163, + 164,5,105,0,0,164,165,5,100,0,0,165,22,1,0,0,0,166,167,5,108,0,0, + 167,168,5,101,0,0,168,169,5,116,0,0,169,24,1,0,0,0,170,171,5,100, + 0,0,171,172,5,111,0,0,172,26,1,0,0,0,173,174,5,105,0,0,174,175,5, + 102,0,0,175,28,1,0,0,0,176,177,5,101,0,0,177,178,5,108,0,0,178,179, + 5,115,0,0,179,180,5,101,0,0,180,30,1,0,0,0,181,182,5,119,0,0,182, + 183,5,104,0,0,183,184,5,105,0,0,184,185,5,108,0,0,185,186,5,101, + 0,0,186,32,1,0,0,0,187,188,5,114,0,0,188,189,5,101,0,0,189,190,5, + 116,0,0,190,191,5,117,0,0,191,192,5,114,0,0,192,193,5,110,0,0,193, + 34,1,0,0,0,194,195,5,123,0,0,195,36,1,0,0,0,196,197,5,125,0,0,197, + 38,1,0,0,0,198,199,5,40,0,0,199,40,1,0,0,0,200,201,5,41,0,0,201, + 42,1,0,0,0,202,203,5,91,0,0,203,44,1,0,0,0,204,205,5,93,0,0,205, + 46,1,0,0,0,206,207,5,46,0,0,207,48,1,0,0,0,208,209,5,44,0,0,209, + 50,1,0,0,0,210,211,5,59,0,0,211,52,1,0,0,0,212,213,5,61,0,0,213, + 54,1,0,0,0,214,215,5,43,0,0,215,56,1,0,0,0,216,217,5,45,0,0,217, + 58,1,0,0,0,218,219,5,42,0,0,219,60,1,0,0,0,220,221,5,47,0,0,221, + 62,1,0,0,0,222,223,5,38,0,0,223,64,1,0,0,0,224,225,5,124,0,0,225, + 66,1,0,0,0,226,227,5,126,0,0,227,68,1,0,0,0,228,229,5,60,0,0,229, + 70,1,0,0,0,230,231,5,62,0,0,231,72,1,0,0,0,232,234,7,0,0,0,233,232, + 1,0,0,0,234,235,1,0,0,0,235,233,1,0,0,0,235,236,1,0,0,0,236,237, + 1,0,0,0,237,238,6,36,0,0,238,74,1,0,0,0,239,240,5,47,0,0,240,241, + 5,42,0,0,241,245,1,0,0,0,242,244,9,0,0,0,243,242,1,0,0,0,244,247, + 1,0,0,0,245,246,1,0,0,0,245,243,1,0,0,0,246,251,1,0,0,0,247,245, + 1,0,0,0,248,249,5,42,0,0,249,252,5,47,0,0,250,252,5,0,0,1,251,248, + 1,0,0,0,251,250,1,0,0,0,252,253,1,0,0,0,253,254,6,37,0,0,254,76, + 1,0,0,0,255,256,5,47,0,0,256,257,5,47,0,0,257,261,1,0,0,0,258,260, + 8,1,0,0,259,258,1,0,0,0,260,263,1,0,0,0,261,259,1,0,0,0,261,262, + 1,0,0,0,262,264,1,0,0,0,263,261,1,0,0,0,264,265,6,38,0,0,265,78, + 1,0,0,0,266,268,7,2,0,0,267,266,1,0,0,0,268,269,1,0,0,0,269,267, + 1,0,0,0,269,270,1,0,0,0,270,80,1,0,0,0,271,272,5,116,0,0,272,273, + 5,114,0,0,273,274,5,117,0,0,274,275,5,101,0,0,275,82,1,0,0,0,276, + 277,5,102,0,0,277,278,5,97,0,0,278,279,5,108,0,0,279,280,5,115,0, + 0,280,281,5,101,0,0,281,84,1,0,0,0,282,283,5,110,0,0,283,284,5,117, + 0,0,284,285,5,108,0,0,285,286,5,108,0,0,286,86,1,0,0,0,287,288,5, + 116,0,0,288,289,5,104,0,0,289,290,5,105,0,0,290,291,5,115,0,0,291, + 88,1,0,0,0,292,296,7,3,0,0,293,295,7,4,0,0,294,293,1,0,0,0,295,298, + 1,0,0,0,296,294,1,0,0,0,296,297,1,0,0,0,297,90,1,0,0,0,298,296,1, + 0,0,0,299,303,5,34,0,0,300,302,8,5,0,0,301,300,1,0,0,0,302,305,1, + 0,0,0,303,301,1,0,0,0,303,304,1,0,0,0,304,306,1,0,0,0,305,303,1, + 0,0,0,306,307,5,34,0,0,307,92,1,0,0,0,8,0,235,245,251,261,269,296, + 303,1,0,1,0 + ]; + + private static __ATN: antlr.ATN; + public static get _ATN(): antlr.ATN { + if (!JackLexer.__ATN) { + JackLexer.__ATN = new antlr.ATNDeserializer().deserialize(JackLexer._serializedATN); + } + + return JackLexer.__ATN; + } + + + private static readonly vocabulary = new antlr.Vocabulary(JackLexer.literalNames, JackLexer.symbolicNames, []); + + public override get vocabulary(): antlr.Vocabulary { + return JackLexer.vocabulary; + } + + private static readonly decisionsToDFA = JackLexer._ATN.decisionToState.map( (ds: antlr.DecisionState, index: number) => new antlr.DFA(ds, index) ); } \ No newline at end of file diff --git a/simulator/src/jack/generated/JackParser.ts b/simulator/src/jack/generated/JackParser.ts index 7d8fd520..e2d0283b 100644 --- a/simulator/src/jack/generated/JackParser.ts +++ b/simulator/src/jack/generated/JackParser.ts @@ -1,17 +1,9 @@ -// Generated from JackParser.g4 by ANTLR 4.13.2 -// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols - -import { - ATN, - ATNDeserializer, DecisionState, DFA, FailedPredicateException, - RecognitionException, NoViableAltException, BailErrorStrategy, - Parser, ParserATNSimulator, - RuleContext, ParserRuleContext, PredictionMode, PredictionContextCache, - TerminalNode, RuleNode, - Token, TokenStream, - Interval, IntervalSet -} from 'antlr4'; -import JackParserListener from "./JackParserListener.js"; +// Generated from JackParser.g4 by ANTLR 4.13.1 + +import * as antlr from "antlr4ng"; +import { Token } from "antlr4ng"; + +import { JackParserListener } from "./JackParserListener.js"; // for running tests with parameters, TODO: discuss strategy for typed parameters in CI // eslint-disable-next-line no-unused-vars type int = number; @@ -19,3261 +11,3151 @@ type int = number; import { SubroutineScope, LocalSymbolTable } from "../symbol"; -export default class JackParser extends Parser { - public static readonly CLASS = 1; - public static readonly CONSTRUCTOR = 2; - public static readonly FUNCTION = 3; - public static readonly METHOD = 4; - public static readonly FIELD = 5; - public static readonly STATIC = 6; - public static readonly VAR = 7; - public static readonly INT = 8; - public static readonly CHAR = 9; - public static readonly BOOLEAN = 10; - public static readonly VOID = 11; - public static readonly LET = 12; - public static readonly DO = 13; - public static readonly IF = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly RETURN = 17; - public static readonly LBRACE = 18; - public static readonly RBRACE = 19; - public static readonly LPAREN = 20; - public static readonly RPAREN = 21; - public static readonly LBRACKET = 22; - public static readonly RBRACKET = 23; - public static readonly DOT = 24; - public static readonly COMMA = 25; - public static readonly SEMICOLON = 26; - public static readonly EQUALS = 27; - public static readonly PLUS = 28; - public static readonly MINUS = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly AND = 32; - public static readonly OR = 33; - public static readonly TILDE = 34; - public static readonly LESS_THAN = 35; - public static readonly GREATER_THAN = 36; - public static readonly WHITESPACE = 37; - public static readonly BLOCK_COMMENT = 38; - public static readonly LINE_COMMENT = 39; - public static readonly INTEGER_LITERAL = 40; - public static readonly TRUE = 41; - public static readonly FALSE = 42; - public static readonly NULL_LITERAL = 43; - public static readonly THIS_LITERAL = 44; - public static readonly IDENTIFIER = 45; - public static readonly STRING_LITERAL = 46; - public static override readonly EOF = Token.EOF; - public static readonly RULE_program = 0; - public static readonly RULE_classDeclaration = 1; - public static readonly RULE_className = 2; - public static readonly RULE_classVarDec = 3; - public static readonly RULE_fieldList = 4; - public static readonly RULE_fieldName = 5; - public static readonly RULE_subroutineDeclaration = 6; - public static readonly RULE_subroutineType = 7; - public static readonly RULE_subroutineDecWithoutType = 8; - public static readonly RULE_subroutineName = 9; - public static readonly RULE_subroutineReturnType = 10; - public static readonly RULE_varType = 11; - public static readonly RULE_parameterList = 12; - public static readonly RULE_parameter = 13; - public static readonly RULE_parameterName = 14; - public static readonly RULE_subroutineBody = 15; - public static readonly RULE_rBrace = 16; - public static readonly RULE_varDeclaration = 17; - public static readonly RULE_varNameInDeclaration = 18; - public static readonly RULE_statements = 19; - public static readonly RULE_statement = 20; - public static readonly RULE_letStatement = 21; - public static readonly RULE_equals = 22; - public static readonly RULE_ifElseStatement = 23; - public static readonly RULE_ifStatement = 24; - public static readonly RULE_ifExpression = 25; - public static readonly RULE_elseStatement = 26; - public static readonly RULE_whileStatement = 27; - public static readonly RULE_whileExpression = 28; - public static readonly RULE_doStatement = 29; - public static readonly RULE_subroutineCall = 30; - public static readonly RULE_subroutineId = 31; - public static readonly RULE_returnStatement = 32; - public static readonly RULE_expressionList = 33; - public static readonly RULE_expression = 34; - public static readonly RULE_constant = 35; - public static readonly RULE_varName = 36; - public static readonly RULE_arrayAccess = 37; - public static readonly RULE_unaryOperation = 38; - public static readonly RULE_groupedExpression = 39; - public static readonly RULE_booleanLiteral = 40; - public static readonly RULE_unaryOperator = 41; - public static readonly RULE_binaryOperator = 42; - public static readonly literalNames: (string | null)[] = [ null, "'class'", - "'constructor'", - "'function'", - "'method'", - "'field'", "'static'", - "'var'", "'int'", - "'char'", "'boolean'", - "'void'", "'let'", - "'do'", "'if'", - "'else'", "'while'", - "'return'", - "'{'", "'}'", - "'('", "')'", - "'['", "']'", - "'.'", "','", - "';'", "'='", - "'+'", "'-'", - "'*'", "'/'", - "'&'", "'|'", - "'~'", "'<'", - "'>'", null, - null, null, - null, "'true'", - "'false'", "'null'", - "'this'" ]; - public static readonly symbolicNames: (string | null)[] = [ null, "CLASS", - "CONSTRUCTOR", - "FUNCTION", - "METHOD", "FIELD", - "STATIC", "VAR", - "INT", "CHAR", - "BOOLEAN", - "VOID", "LET", - "DO", "IF", - "ELSE", "WHILE", - "RETURN", "LBRACE", - "RBRACE", "LPAREN", - "RPAREN", "LBRACKET", - "RBRACKET", - "DOT", "COMMA", - "SEMICOLON", - "EQUALS", "PLUS", - "MINUS", "MUL", - "DIV", "AND", - "OR", "TILDE", - "LESS_THAN", - "GREATER_THAN", - "WHITESPACE", - "BLOCK_COMMENT", - "LINE_COMMENT", - "INTEGER_LITERAL", - "TRUE", "FALSE", - "NULL_LITERAL", - "THIS_LITERAL", - "IDENTIFIER", - "STRING_LITERAL" ]; - // tslint:disable:no-trailing-whitespace - public static readonly ruleNames: string[] = [ - "program", "classDeclaration", "className", "classVarDec", "fieldList", - "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", - "subroutineName", "subroutineReturnType", "varType", "parameterList", - "parameter", "parameterName", "subroutineBody", "rBrace", "varDeclaration", - "varNameInDeclaration", "statements", "statement", "letStatement", "equals", - "ifElseStatement", "ifStatement", "ifExpression", "elseStatement", "whileStatement", - "whileExpression", "doStatement", "subroutineCall", "subroutineId", "returnStatement", - "expressionList", "expression", "constant", "varName", "arrayAccess", - "unaryOperation", "groupedExpression", "booleanLiteral", "unaryOperator", - "binaryOperator", - ]; - public get grammarFileName(): string { return "JackParser.g4"; } - public get literalNames(): (string | null)[] { return JackParser.literalNames; } - public get symbolicNames(): (string | null)[] { return JackParser.symbolicNames; } - public get ruleNames(): string[] { return JackParser.ruleNames; } - public get serializedATN(): number[] { return JackParser._serializedATN; } - - protected createFailedPredicateException(predicate?: string, message?: string): FailedPredicateException { - return new FailedPredicateException(this, predicate, message); - } - - constructor(input: TokenStream) { - super(input); - this._interp = new ParserATNSimulator(this, JackParser._ATN, JackParser.DecisionsToDFA, new PredictionContextCache()); - } - // @RuleVersion(0) - public program(): ProgramContext { - let localctx: ProgramContext = new ProgramContext(this, this._ctx, this.state); - this.enterRule(localctx, 0, JackParser.RULE_program); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 86; - this.classDeclaration(); - this.state = 87; - this.match(JackParser.EOF); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public classDeclaration(): ClassDeclarationContext { - let localctx: ClassDeclarationContext = new ClassDeclarationContext(this, this._ctx, this.state); - this.enterRule(localctx, 2, JackParser.RULE_classDeclaration); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 89; - this.match(JackParser.CLASS); - this.state = 90; - this.className(); - this.state = 91; - this.match(JackParser.LBRACE); - this.state = 95; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la===5 || _la===6) { - { - { - this.state = 92; - this.classVarDec(); - } - } - this.state = 97; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 101; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 28) !== 0)) { - { - { - this.state = 98; - this.subroutineDeclaration(); - } - } - this.state = 103; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 104; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public className(): ClassNameContext { - let localctx: ClassNameContext = new ClassNameContext(this, this._ctx, this.state); - this.enterRule(localctx, 4, JackParser.RULE_className); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 106; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public classVarDec(): ClassVarDecContext { - let localctx: ClassVarDecContext = new ClassVarDecContext(this, this._ctx, this.state); - this.enterRule(localctx, 6, JackParser.RULE_classVarDec); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 108; - _la = this._input.LA(1); - if(!(_la===5 || _la===6)) { - this._errHandler.recoverInline(this); - } - else { - this._errHandler.reportMatch(this); - this.consume(); - } - this.state = 109; - this.fieldList(); - this.state = 110; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public fieldList(): FieldListContext { - let localctx: FieldListContext = new FieldListContext(this, this._ctx, this.state); - this.enterRule(localctx, 8, JackParser.RULE_fieldList); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 112; - this.varType(); - this.state = 113; - this.fieldName(); - this.state = 118; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la===25) { - { - { - this.state = 114; - this.match(JackParser.COMMA); - this.state = 115; - this.fieldName(); - } - } - this.state = 120; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public fieldName(): FieldNameContext { - let localctx: FieldNameContext = new FieldNameContext(this, this._ctx, this.state); - this.enterRule(localctx, 10, JackParser.RULE_fieldName); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 121; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineDeclaration(): SubroutineDeclarationContext { - let localctx: SubroutineDeclarationContext = new SubroutineDeclarationContext(this, this._ctx, this.state); - this.enterRule(localctx, 12, JackParser.RULE_subroutineDeclaration); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 123; - this.subroutineType(); - this.state = 124; - this.subroutineDecWithoutType(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineType(): SubroutineTypeContext { - let localctx: SubroutineTypeContext = new SubroutineTypeContext(this, this._ctx, this.state); - this.enterRule(localctx, 14, JackParser.RULE_subroutineType); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 126; - _la = this._input.LA(1); - if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 28) !== 0))) { - this._errHandler.recoverInline(this); - } - else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - let localctx: SubroutineDecWithoutTypeContext = new SubroutineDecWithoutTypeContext(this, this._ctx, this.state); - this.enterRule(localctx, 16, JackParser.RULE_subroutineDecWithoutType); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 128; - this.subroutineReturnType(); - this.state = 129; - this.subroutineName(); - this.state = 130; - this.match(JackParser.LPAREN); - this.state = 131; - this.parameterList(); - this.state = 132; - this.match(JackParser.RPAREN); - this.state = 133; - this.subroutineBody(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineName(): SubroutineNameContext { - let localctx: SubroutineNameContext = new SubroutineNameContext(this, this._ctx, this.state); - this.enterRule(localctx, 18, JackParser.RULE_subroutineName); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 135; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineReturnType(): SubroutineReturnTypeContext { - let localctx: SubroutineReturnTypeContext = new SubroutineReturnTypeContext(this, this._ctx, this.state); - this.enterRule(localctx, 20, JackParser.RULE_subroutineReturnType); - try { - this.state = 139; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case 8: - case 9: - case 10: - case 45: - this.enterOuterAlt(localctx, 1); - { - this.state = 137; - this.varType(); - } - break; - case 11: - this.enterOuterAlt(localctx, 2); - { - this.state = 138; - this.match(JackParser.VOID); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public varType(): VarTypeContext { - let localctx: VarTypeContext = new VarTypeContext(this, this._ctx, this.state); - this.enterRule(localctx, 22, JackParser.RULE_varType); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 141; - _la = this._input.LA(1); - if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 1792) !== 0) || _la===45)) { - this._errHandler.recoverInline(this); - } - else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public parameterList(): ParameterListContext { - let localctx: ParameterListContext = new ParameterListContext(this, this._ctx, this.state); - this.enterRule(localctx, 24, JackParser.RULE_parameterList); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 151; - this._errHandler.sync(this); - _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 1792) !== 0) || _la===45) { - { - this.state = 143; - this.parameter(); - this.state = 148; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la===25) { - { - { - this.state = 144; - this.match(JackParser.COMMA); - this.state = 145; - this.parameter(); - } - } - this.state = 150; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public parameter(): ParameterContext { - let localctx: ParameterContext = new ParameterContext(this, this._ctx, this.state); - this.enterRule(localctx, 26, JackParser.RULE_parameter); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 153; - this.varType(); - this.state = 154; - this.parameterName(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public parameterName(): ParameterNameContext { - let localctx: ParameterNameContext = new ParameterNameContext(this, this._ctx, this.state); - this.enterRule(localctx, 28, JackParser.RULE_parameterName); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 156; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineBody(): SubroutineBodyContext { - let localctx: SubroutineBodyContext = new SubroutineBodyContext(this, this._ctx, this.state); - this.enterRule(localctx, 30, JackParser.RULE_subroutineBody); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 158; - this.match(JackParser.LBRACE); - this.state = 162; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la===7) { - { - { - this.state = 159; - this.varDeclaration(); - } - } - this.state = 164; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 165; - this.statements(); - this.state = 166; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public rBrace(): RBraceContext { - let localctx: RBraceContext = new RBraceContext(this, this._ctx, this.state); - this.enterRule(localctx, 32, JackParser.RULE_rBrace); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 168; - this.match(JackParser.RBRACE); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public varDeclaration(): VarDeclarationContext { - let localctx: VarDeclarationContext = new VarDeclarationContext(this, this._ctx, this.state); - this.enterRule(localctx, 34, JackParser.RULE_varDeclaration); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 170; - this.match(JackParser.VAR); - this.state = 171; - this.varType(); - this.state = 172; - this.varNameInDeclaration(); - this.state = 177; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la===25) { - { - { - this.state = 173; - this.match(JackParser.COMMA); - this.state = 174; - this.varNameInDeclaration(); - } - } - this.state = 179; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - this.state = 180; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public varNameInDeclaration(): VarNameInDeclarationContext { - let localctx: VarNameInDeclarationContext = new VarNameInDeclarationContext(this, this._ctx, this.state); - this.enterRule(localctx, 36, JackParser.RULE_varNameInDeclaration); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 182; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public statements(): StatementsContext { - let localctx: StatementsContext = new StatementsContext(this, this._ctx, this.state); - this.enterRule(localctx, 38, JackParser.RULE_statements); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 187; - this._errHandler.sync(this); - _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 225280) !== 0)) { - { - { - this.state = 184; - this.statement(); - } - } - this.state = 189; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public statement(): StatementContext { - let localctx: StatementContext = new StatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 40, JackParser.RULE_statement); - try { - this.state = 195; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case 12: - this.enterOuterAlt(localctx, 1); - { - this.state = 190; - this.letStatement(); - } - break; - case 14: - this.enterOuterAlt(localctx, 2); - { - this.state = 191; - this.ifElseStatement(); - } - break; - case 16: - this.enterOuterAlt(localctx, 3); - { - this.state = 192; - this.whileStatement(); - } - break; - case 13: - this.enterOuterAlt(localctx, 4); - { - this.state = 193; - this.doStatement(); - } - break; - case 17: - this.enterOuterAlt(localctx, 5); - { - this.state = 194; - this.returnStatement(); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public letStatement(): LetStatementContext { - let localctx: LetStatementContext = new LetStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 42, JackParser.RULE_letStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 197; - this.match(JackParser.LET); - this.state = 200; - this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 10, this._ctx) ) { - case 1: - { - this.state = 198; - this.varName(); - } - break; - case 2: - { - this.state = 199; - this.arrayAccess(); - } - break; - } - this.state = 202; - this.equals(); - this.state = 203; - this.expression(0); - this.state = 204; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public equals(): EqualsContext { - let localctx: EqualsContext = new EqualsContext(this, this._ctx, this.state); - this.enterRule(localctx, 44, JackParser.RULE_equals); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 206; - this.match(JackParser.EQUALS); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public ifElseStatement(): IfElseStatementContext { - let localctx: IfElseStatementContext = new IfElseStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 46, JackParser.RULE_ifElseStatement); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 208; - this.ifStatement(); - this.state = 210; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (_la===15) { - { - this.state = 209; - this.elseStatement(); - } - } - - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public ifStatement(): IfStatementContext { - let localctx: IfStatementContext = new IfStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 48, JackParser.RULE_ifStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 212; - this.match(JackParser.IF); - this.state = 213; - this.match(JackParser.LPAREN); - this.state = 214; - this.ifExpression(); - this.state = 215; - this.match(JackParser.RPAREN); - this.state = 216; - this.match(JackParser.LBRACE); - this.state = 217; - this.statements(); - this.state = 218; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public ifExpression(): IfExpressionContext { - let localctx: IfExpressionContext = new IfExpressionContext(this, this._ctx, this.state); - this.enterRule(localctx, 50, JackParser.RULE_ifExpression); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 220; - this.expression(0); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public elseStatement(): ElseStatementContext { - let localctx: ElseStatementContext = new ElseStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 52, JackParser.RULE_elseStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 222; - this.match(JackParser.ELSE); - this.state = 223; - this.match(JackParser.LBRACE); - this.state = 224; - this.statements(); - this.state = 225; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public whileStatement(): WhileStatementContext { - let localctx: WhileStatementContext = new WhileStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 54, JackParser.RULE_whileStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 227; - this.match(JackParser.WHILE); - this.state = 228; - this.match(JackParser.LPAREN); - this.state = 229; - this.whileExpression(); - this.state = 230; - this.match(JackParser.RPAREN); - this.state = 231; - this.match(JackParser.LBRACE); - this.state = 232; - this.statements(); - this.state = 233; - this.rBrace(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public whileExpression(): WhileExpressionContext { - let localctx: WhileExpressionContext = new WhileExpressionContext(this, this._ctx, this.state); - this.enterRule(localctx, 56, JackParser.RULE_whileExpression); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 235; - this.expression(0); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public doStatement(): DoStatementContext { - let localctx: DoStatementContext = new DoStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 58, JackParser.RULE_doStatement); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 237; - this.match(JackParser.DO); - this.state = 238; - this.subroutineCall(); - this.state = 239; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineCall(): SubroutineCallContext { - let localctx: SubroutineCallContext = new SubroutineCallContext(this, this._ctx, this.state); - this.enterRule(localctx, 60, JackParser.RULE_subroutineCall); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 241; - this.subroutineId(); - this.state = 242; - this.match(JackParser.LPAREN); - this.state = 243; - this.expressionList(); - this.state = 244; - this.match(JackParser.RPAREN); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public subroutineId(): SubroutineIdContext { - let localctx: SubroutineIdContext = new SubroutineIdContext(this, this._ctx, this.state); - this.enterRule(localctx, 62, JackParser.RULE_subroutineId); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 251; - this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 13, this._ctx) ) { - case 1: - { - this.state = 248; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case 45: - { - this.state = 246; - this.className(); - } - break; - case 44: - { - this.state = 247; - this.match(JackParser.THIS_LITERAL); - } - break; - default: - throw new NoViableAltException(this); - } - this.state = 250; - this.match(JackParser.DOT); - } - break; - } - this.state = 253; - this.subroutineName(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public returnStatement(): ReturnStatementContext { - let localctx: ReturnStatementContext = new ReturnStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 64, JackParser.RULE_returnStatement); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 255; - this.match(JackParser.RETURN); - this.state = 257; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 133186049) !== 0)) { - { - this.state = 256; - this.expression(0); - } - } - - this.state = 259; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public expressionList(): ExpressionListContext { - let localctx: ExpressionListContext = new ExpressionListContext(this, this._ctx, this.state); - this.enterRule(localctx, 66, JackParser.RULE_expressionList); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 269; - this._errHandler.sync(this); - _la = this._input.LA(1); - if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 133186049) !== 0)) { - { - this.state = 261; - this.expression(0); - this.state = 266; - this._errHandler.sync(this); - _la = this._input.LA(1); - while (_la===25) { - { - { - this.state = 262; - this.match(JackParser.COMMA); - this.state = 263; - this.expression(0); - } - } - this.state = 268; - this._errHandler.sync(this); - _la = this._input.LA(1); - } - } - } - - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - - public expression(): ExpressionContext; - public expression(_p: number): ExpressionContext; - // @RuleVersion(0) - public expression(_p?: number): ExpressionContext { - if (_p === undefined) { - _p = 0; - } - - let _parentctx: ParserRuleContext = this._ctx; - let _parentState: number = this.state; - let localctx: ExpressionContext = new ExpressionContext(this, this._ctx, _parentState); - let _prevctx: ExpressionContext = localctx; - let _startState: number = 68; - this.enterRecursionRule(localctx, 68, JackParser.RULE_expression, _p); - try { - let _alt: number; - this.enterOuterAlt(localctx, 1); - { - this.state = 278; - this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 17, this._ctx) ) { - case 1: - { - this.state = 272; - this.constant(); - } - break; - case 2: - { - this.state = 273; - this.varName(); - } - break; - case 3: - { - this.state = 274; - this.subroutineCall(); - } - break; - case 4: - { - this.state = 275; - this.arrayAccess(); - } - break; - case 5: - { - this.state = 276; - this.unaryOperation(); - } - break; - case 6: - { - this.state = 277; - this.groupedExpression(); - } - break; - } - this._ctx.stop = this._input.LT(-1); - this.state = 286; - this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 18, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - if (this._parseListeners != null) { - this.triggerExitRuleEvent(); - } - _prevctx = localctx; - { - { - localctx = new ExpressionContext(this, _parentctx, _parentState); - this.pushNewRecursionContext(localctx, _startState, JackParser.RULE_expression); - this.state = 280; - if (!(this.precpred(this._ctx, 2))) { - throw this.createFailedPredicateException("this.precpred(this._ctx, 2)"); - } - this.state = 281; - this.binaryOperator(); - this.state = 282; - this.expression(3); - } - } - } - this.state = 288; - this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 18, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.unrollRecursionContexts(_parentctx); - } - return localctx; - } - // @RuleVersion(0) - public constant(): ConstantContext { - let localctx: ConstantContext = new ConstantContext(this, this._ctx, this.state); - this.enterRule(localctx, 70, JackParser.RULE_constant); - try { - this.state = 294; - this._errHandler.sync(this); - switch (this._input.LA(1)) { - case 40: - this.enterOuterAlt(localctx, 1); - { - this.state = 289; - this.match(JackParser.INTEGER_LITERAL); - } - break; - case 46: - this.enterOuterAlt(localctx, 2); - { - this.state = 290; - this.match(JackParser.STRING_LITERAL); - } - break; - case 41: - case 42: - this.enterOuterAlt(localctx, 3); - { - this.state = 291; - this.booleanLiteral(); - } - break; - case 43: - this.enterOuterAlt(localctx, 4); - { - this.state = 292; - this.match(JackParser.NULL_LITERAL); - } - break; - case 44: - this.enterOuterAlt(localctx, 5); - { - this.state = 293; - this.match(JackParser.THIS_LITERAL); - } - break; - default: - throw new NoViableAltException(this); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public varName(): VarNameContext { - let localctx: VarNameContext = new VarNameContext(this, this._ctx, this.state); - this.enterRule(localctx, 72, JackParser.RULE_varName); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 296; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public arrayAccess(): ArrayAccessContext { - let localctx: ArrayAccessContext = new ArrayAccessContext(this, this._ctx, this.state); - this.enterRule(localctx, 74, JackParser.RULE_arrayAccess); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 298; - this.varName(); - this.state = 299; - this.match(JackParser.LBRACKET); - this.state = 300; - this.expression(0); - this.state = 301; - this.match(JackParser.RBRACKET); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public unaryOperation(): UnaryOperationContext { - let localctx: UnaryOperationContext = new UnaryOperationContext(this, this._ctx, this.state); - this.enterRule(localctx, 76, JackParser.RULE_unaryOperation); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 303; - this.unaryOperator(); - this.state = 304; - this.expression(0); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public groupedExpression(): GroupedExpressionContext { - let localctx: GroupedExpressionContext = new GroupedExpressionContext(this, this._ctx, this.state); - this.enterRule(localctx, 78, JackParser.RULE_groupedExpression); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 306; - this.match(JackParser.LPAREN); - this.state = 307; - this.expression(0); - this.state = 308; - this.match(JackParser.RPAREN); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public booleanLiteral(): BooleanLiteralContext { - let localctx: BooleanLiteralContext = new BooleanLiteralContext(this, this._ctx, this.state); - this.enterRule(localctx, 80, JackParser.RULE_booleanLiteral); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 310; - _la = this._input.LA(1); - if(!(_la===41 || _la===42)) { - this._errHandler.recoverInline(this); - } - else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public unaryOperator(): UnaryOperatorContext { - let localctx: UnaryOperatorContext = new UnaryOperatorContext(this, this._ctx, this.state); - this.enterRule(localctx, 82, JackParser.RULE_unaryOperator); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 312; - _la = this._input.LA(1); - if(!(_la===29 || _la===34)) { - this._errHandler.recoverInline(this); - } - else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public binaryOperator(): BinaryOperatorContext { - let localctx: BinaryOperatorContext = new BinaryOperatorContext(this, this._ctx, this.state); - this.enterRule(localctx, 84, JackParser.RULE_binaryOperator); - let _la: number; - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 314; - _la = this._input.LA(1); - if(!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & 895) !== 0))) { - this._errHandler.recoverInline(this); - } - else { - this._errHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - - public sempred(localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 34: - return this.expression_sempred(localctx as ExpressionContext, predIndex); - } - return true; - } - private expression_sempred(localctx: ExpressionContext, predIndex: number): boolean { - switch (predIndex) { - case 0: - return this.precpred(this._ctx, 2); - } - return true; - } - - public static readonly _serializedATN: number[] = [4,1,46,317,2,0,7,0,2, - 1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2, - 10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17, - 7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7, - 24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31, - 2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2, - 39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,1,0,1,0,1,0,1,1,1,1,1,1,1,1,5,1,94, - 8,1,10,1,12,1,97,9,1,1,1,5,1,100,8,1,10,1,12,1,103,9,1,1,1,1,1,1,2,1,2, - 1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,5,4,117,8,4,10,4,12,4,120,9,4,1,5,1,5,1, - 6,1,6,1,6,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,10,1,10,3,10,140, - 8,10,1,11,1,11,1,12,1,12,1,12,5,12,147,8,12,10,12,12,12,150,9,12,3,12,152, - 8,12,1,13,1,13,1,13,1,14,1,14,1,15,1,15,5,15,161,8,15,10,15,12,15,164,9, - 15,1,15,1,15,1,15,1,16,1,16,1,17,1,17,1,17,1,17,1,17,5,17,176,8,17,10,17, - 12,17,179,9,17,1,17,1,17,1,18,1,18,1,19,5,19,186,8,19,10,19,12,19,189,9, - 19,1,20,1,20,1,20,1,20,1,20,3,20,196,8,20,1,21,1,21,1,21,3,21,201,8,21, - 1,21,1,21,1,21,1,21,1,22,1,22,1,23,1,23,3,23,211,8,23,1,24,1,24,1,24,1, - 24,1,24,1,24,1,24,1,24,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,27,1,27,1,27, - 1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,29,1,29,1,29,1,29,1,30,1,30,1,30,1, - 30,1,30,1,31,1,31,3,31,249,8,31,1,31,3,31,252,8,31,1,31,1,31,1,32,1,32, - 3,32,258,8,32,1,32,1,32,1,33,1,33,1,33,5,33,265,8,33,10,33,12,33,268,9, - 33,3,33,270,8,33,1,34,1,34,1,34,1,34,1,34,1,34,1,34,3,34,279,8,34,1,34, - 1,34,1,34,1,34,5,34,285,8,34,10,34,12,34,288,9,34,1,35,1,35,1,35,1,35,1, - 35,3,35,295,8,35,1,36,1,36,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,38,1,39, - 1,39,1,39,1,39,1,40,1,40,1,41,1,41,1,42,1,42,1,42,0,1,68,43,0,2,4,6,8,10, - 12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58, - 60,62,64,66,68,70,72,74,76,78,80,82,84,0,6,1,0,5,6,1,0,2,4,2,0,8,10,45, - 45,1,0,41,42,2,0,29,29,34,34,2,0,27,33,35,36,303,0,86,1,0,0,0,2,89,1,0, - 0,0,4,106,1,0,0,0,6,108,1,0,0,0,8,112,1,0,0,0,10,121,1,0,0,0,12,123,1,0, - 0,0,14,126,1,0,0,0,16,128,1,0,0,0,18,135,1,0,0,0,20,139,1,0,0,0,22,141, - 1,0,0,0,24,151,1,0,0,0,26,153,1,0,0,0,28,156,1,0,0,0,30,158,1,0,0,0,32, - 168,1,0,0,0,34,170,1,0,0,0,36,182,1,0,0,0,38,187,1,0,0,0,40,195,1,0,0,0, - 42,197,1,0,0,0,44,206,1,0,0,0,46,208,1,0,0,0,48,212,1,0,0,0,50,220,1,0, - 0,0,52,222,1,0,0,0,54,227,1,0,0,0,56,235,1,0,0,0,58,237,1,0,0,0,60,241, - 1,0,0,0,62,251,1,0,0,0,64,255,1,0,0,0,66,269,1,0,0,0,68,278,1,0,0,0,70, - 294,1,0,0,0,72,296,1,0,0,0,74,298,1,0,0,0,76,303,1,0,0,0,78,306,1,0,0,0, - 80,310,1,0,0,0,82,312,1,0,0,0,84,314,1,0,0,0,86,87,3,2,1,0,87,88,5,0,0, - 1,88,1,1,0,0,0,89,90,5,1,0,0,90,91,3,4,2,0,91,95,5,18,0,0,92,94,3,6,3,0, - 93,92,1,0,0,0,94,97,1,0,0,0,95,93,1,0,0,0,95,96,1,0,0,0,96,101,1,0,0,0, - 97,95,1,0,0,0,98,100,3,12,6,0,99,98,1,0,0,0,100,103,1,0,0,0,101,99,1,0, - 0,0,101,102,1,0,0,0,102,104,1,0,0,0,103,101,1,0,0,0,104,105,3,32,16,0,105, - 3,1,0,0,0,106,107,5,45,0,0,107,5,1,0,0,0,108,109,7,0,0,0,109,110,3,8,4, - 0,110,111,5,26,0,0,111,7,1,0,0,0,112,113,3,22,11,0,113,118,3,10,5,0,114, - 115,5,25,0,0,115,117,3,10,5,0,116,114,1,0,0,0,117,120,1,0,0,0,118,116,1, - 0,0,0,118,119,1,0,0,0,119,9,1,0,0,0,120,118,1,0,0,0,121,122,5,45,0,0,122, - 11,1,0,0,0,123,124,3,14,7,0,124,125,3,16,8,0,125,13,1,0,0,0,126,127,7,1, - 0,0,127,15,1,0,0,0,128,129,3,20,10,0,129,130,3,18,9,0,130,131,5,20,0,0, - 131,132,3,24,12,0,132,133,5,21,0,0,133,134,3,30,15,0,134,17,1,0,0,0,135, - 136,5,45,0,0,136,19,1,0,0,0,137,140,3,22,11,0,138,140,5,11,0,0,139,137, - 1,0,0,0,139,138,1,0,0,0,140,21,1,0,0,0,141,142,7,2,0,0,142,23,1,0,0,0,143, - 148,3,26,13,0,144,145,5,25,0,0,145,147,3,26,13,0,146,144,1,0,0,0,147,150, - 1,0,0,0,148,146,1,0,0,0,148,149,1,0,0,0,149,152,1,0,0,0,150,148,1,0,0,0, - 151,143,1,0,0,0,151,152,1,0,0,0,152,25,1,0,0,0,153,154,3,22,11,0,154,155, - 3,28,14,0,155,27,1,0,0,0,156,157,5,45,0,0,157,29,1,0,0,0,158,162,5,18,0, - 0,159,161,3,34,17,0,160,159,1,0,0,0,161,164,1,0,0,0,162,160,1,0,0,0,162, - 163,1,0,0,0,163,165,1,0,0,0,164,162,1,0,0,0,165,166,3,38,19,0,166,167,3, - 32,16,0,167,31,1,0,0,0,168,169,5,19,0,0,169,33,1,0,0,0,170,171,5,7,0,0, - 171,172,3,22,11,0,172,177,3,36,18,0,173,174,5,25,0,0,174,176,3,36,18,0, - 175,173,1,0,0,0,176,179,1,0,0,0,177,175,1,0,0,0,177,178,1,0,0,0,178,180, - 1,0,0,0,179,177,1,0,0,0,180,181,5,26,0,0,181,35,1,0,0,0,182,183,5,45,0, - 0,183,37,1,0,0,0,184,186,3,40,20,0,185,184,1,0,0,0,186,189,1,0,0,0,187, - 185,1,0,0,0,187,188,1,0,0,0,188,39,1,0,0,0,189,187,1,0,0,0,190,196,3,42, - 21,0,191,196,3,46,23,0,192,196,3,54,27,0,193,196,3,58,29,0,194,196,3,64, - 32,0,195,190,1,0,0,0,195,191,1,0,0,0,195,192,1,0,0,0,195,193,1,0,0,0,195, - 194,1,0,0,0,196,41,1,0,0,0,197,200,5,12,0,0,198,201,3,72,36,0,199,201,3, - 74,37,0,200,198,1,0,0,0,200,199,1,0,0,0,201,202,1,0,0,0,202,203,3,44,22, - 0,203,204,3,68,34,0,204,205,5,26,0,0,205,43,1,0,0,0,206,207,5,27,0,0,207, - 45,1,0,0,0,208,210,3,48,24,0,209,211,3,52,26,0,210,209,1,0,0,0,210,211, - 1,0,0,0,211,47,1,0,0,0,212,213,5,14,0,0,213,214,5,20,0,0,214,215,3,50,25, - 0,215,216,5,21,0,0,216,217,5,18,0,0,217,218,3,38,19,0,218,219,3,32,16,0, - 219,49,1,0,0,0,220,221,3,68,34,0,221,51,1,0,0,0,222,223,5,15,0,0,223,224, - 5,18,0,0,224,225,3,38,19,0,225,226,3,32,16,0,226,53,1,0,0,0,227,228,5,16, - 0,0,228,229,5,20,0,0,229,230,3,56,28,0,230,231,5,21,0,0,231,232,5,18,0, - 0,232,233,3,38,19,0,233,234,3,32,16,0,234,55,1,0,0,0,235,236,3,68,34,0, - 236,57,1,0,0,0,237,238,5,13,0,0,238,239,3,60,30,0,239,240,5,26,0,0,240, - 59,1,0,0,0,241,242,3,62,31,0,242,243,5,20,0,0,243,244,3,66,33,0,244,245, - 5,21,0,0,245,61,1,0,0,0,246,249,3,4,2,0,247,249,5,44,0,0,248,246,1,0,0, - 0,248,247,1,0,0,0,249,250,1,0,0,0,250,252,5,24,0,0,251,248,1,0,0,0,251, - 252,1,0,0,0,252,253,1,0,0,0,253,254,3,18,9,0,254,63,1,0,0,0,255,257,5,17, - 0,0,256,258,3,68,34,0,257,256,1,0,0,0,257,258,1,0,0,0,258,259,1,0,0,0,259, - 260,5,26,0,0,260,65,1,0,0,0,261,266,3,68,34,0,262,263,5,25,0,0,263,265, - 3,68,34,0,264,262,1,0,0,0,265,268,1,0,0,0,266,264,1,0,0,0,266,267,1,0,0, - 0,267,270,1,0,0,0,268,266,1,0,0,0,269,261,1,0,0,0,269,270,1,0,0,0,270,67, - 1,0,0,0,271,272,6,34,-1,0,272,279,3,70,35,0,273,279,3,72,36,0,274,279,3, - 60,30,0,275,279,3,74,37,0,276,279,3,76,38,0,277,279,3,78,39,0,278,271,1, - 0,0,0,278,273,1,0,0,0,278,274,1,0,0,0,278,275,1,0,0,0,278,276,1,0,0,0,278, - 277,1,0,0,0,279,286,1,0,0,0,280,281,10,2,0,0,281,282,3,84,42,0,282,283, - 3,68,34,3,283,285,1,0,0,0,284,280,1,0,0,0,285,288,1,0,0,0,286,284,1,0,0, - 0,286,287,1,0,0,0,287,69,1,0,0,0,288,286,1,0,0,0,289,295,5,40,0,0,290,295, - 5,46,0,0,291,295,3,80,40,0,292,295,5,43,0,0,293,295,5,44,0,0,294,289,1, - 0,0,0,294,290,1,0,0,0,294,291,1,0,0,0,294,292,1,0,0,0,294,293,1,0,0,0,295, - 71,1,0,0,0,296,297,5,45,0,0,297,73,1,0,0,0,298,299,3,72,36,0,299,300,5, - 22,0,0,300,301,3,68,34,0,301,302,5,23,0,0,302,75,1,0,0,0,303,304,3,82,41, - 0,304,305,3,68,34,0,305,77,1,0,0,0,306,307,5,20,0,0,307,308,3,68,34,0,308, - 309,5,21,0,0,309,79,1,0,0,0,310,311,7,3,0,0,311,81,1,0,0,0,312,313,7,4, - 0,0,313,83,1,0,0,0,314,315,7,5,0,0,315,85,1,0,0,0,20,95,101,118,139,148, - 151,162,177,187,195,200,210,248,251,257,266,269,278,286,294]; - - private static __ATN: ATN; - public static get _ATN(): ATN { - if (!JackParser.__ATN) { - JackParser.__ATN = new ATNDeserializer().deserialize(JackParser._serializedATN); - } - - return JackParser.__ATN; - } - - - static DecisionsToDFA = JackParser._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) ); +export class JackParser extends antlr.Parser { + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WHITESPACE = 37; + public static readonly BLOCK_COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly TRUE = 41; + public static readonly FALSE = 42; + public static readonly NULL_LITERAL = 43; + public static readonly THIS_LITERAL = 44; + public static readonly IDENTIFIER = 45; + public static readonly STRING_LITERAL = 46; + public static readonly RULE_program = 0; + public static readonly RULE_classDeclaration = 1; + public static readonly RULE_className = 2; + public static readonly RULE_classVarDec = 3; + public static readonly RULE_fieldList = 4; + public static readonly RULE_fieldName = 5; + public static readonly RULE_subroutineDeclaration = 6; + public static readonly RULE_subroutineType = 7; + public static readonly RULE_subroutineDecWithoutType = 8; + public static readonly RULE_subroutineName = 9; + public static readonly RULE_subroutineReturnType = 10; + public static readonly RULE_varType = 11; + public static readonly RULE_parameterList = 12; + public static readonly RULE_parameter = 13; + public static readonly RULE_parameterName = 14; + public static readonly RULE_subroutineBody = 15; + public static readonly RULE_rBrace = 16; + public static readonly RULE_varDeclaration = 17; + public static readonly RULE_varNameInDeclaration = 18; + public static readonly RULE_statements = 19; + public static readonly RULE_statement = 20; + public static readonly RULE_letStatement = 21; + public static readonly RULE_equals = 22; + public static readonly RULE_ifElseStatement = 23; + public static readonly RULE_ifStatement = 24; + public static readonly RULE_ifExpression = 25; + public static readonly RULE_elseStatement = 26; + public static readonly RULE_whileStatement = 27; + public static readonly RULE_whileExpression = 28; + public static readonly RULE_doStatement = 29; + public static readonly RULE_subroutineCall = 30; + public static readonly RULE_subroutineId = 31; + public static readonly RULE_returnStatement = 32; + public static readonly RULE_expressionList = 33; + public static readonly RULE_expression = 34; + public static readonly RULE_constant = 35; + public static readonly RULE_varName = 36; + public static readonly RULE_arrayAccess = 37; + public static readonly RULE_unaryOperation = 38; + public static readonly RULE_groupedExpression = 39; + public static readonly RULE_booleanLiteral = 40; + public static readonly RULE_unaryOperator = 41; + public static readonly RULE_binaryOperator = 42; + + public static readonly literalNames = [ + null, "'class'", "'constructor'", "'function'", "'method'", "'field'", + "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", + "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", + "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", + "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", null, null, null, null, + "'true'", "'false'", "'null'", "'this'" + ]; + + public static readonly symbolicNames = [ + null, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", + "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", + "WHILE", "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", + "RBRACKET", "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", + "MUL", "DIV", "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", + "WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT", "INTEGER_LITERAL", + "TRUE", "FALSE", "NULL_LITERAL", "THIS_LITERAL", "IDENTIFIER", "STRING_LITERAL" + ]; + public static readonly ruleNames = [ + "program", "classDeclaration", "className", "classVarDec", "fieldList", + "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", + "subroutineName", "subroutineReturnType", "varType", "parameterList", + "parameter", "parameterName", "subroutineBody", "rBrace", "varDeclaration", + "varNameInDeclaration", "statements", "statement", "letStatement", + "equals", "ifElseStatement", "ifStatement", "ifExpression", "elseStatement", + "whileStatement", "whileExpression", "doStatement", "subroutineCall", + "subroutineId", "returnStatement", "expressionList", "expression", + "constant", "varName", "arrayAccess", "unaryOperation", "groupedExpression", + "booleanLiteral", "unaryOperator", "binaryOperator", + ]; + + public get grammarFileName(): string { return "JackParser.g4"; } + public get literalNames(): (string | null)[] { return JackParser.literalNames; } + public get symbolicNames(): (string | null)[] { return JackParser.symbolicNames; } + public get ruleNames(): string[] { return JackParser.ruleNames; } + public get serializedATN(): number[] { return JackParser._serializedATN; } + + protected createFailedPredicateException(predicate?: string, message?: string): antlr.FailedPredicateException { + return new antlr.FailedPredicateException(this, predicate, message); + } + + public constructor(input: antlr.TokenStream) { + super(input); + this.interpreter = new antlr.ParserATNSimulator(this, JackParser._ATN, JackParser.decisionsToDFA, new antlr.PredictionContextCache()); + } + public program(): ProgramContext { + let localContext = new ProgramContext(this.context, this.state); + this.enterRule(localContext, 0, JackParser.RULE_program); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 86; + this.classDeclaration(); + this.state = 87; + this.match(JackParser.EOF); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public classDeclaration(): ClassDeclarationContext { + let localContext = new ClassDeclarationContext(this.context, this.state); + this.enterRule(localContext, 2, JackParser.RULE_classDeclaration); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 89; + this.match(JackParser.CLASS); + this.state = 90; + this.className(); + this.state = 91; + this.match(JackParser.LBRACE); + this.state = 95; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 5 || _la === 6) { + { + { + this.state = 92; + this.classVarDec(); + } + } + this.state = 97; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 101; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 28) !== 0)) { + { + { + this.state = 98; + this.subroutineDeclaration(); + } + } + this.state = 103; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 104; + this.rBrace(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public className(): ClassNameContext { + let localContext = new ClassNameContext(this.context, this.state); + this.enterRule(localContext, 4, JackParser.RULE_className); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 106; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public classVarDec(): ClassVarDecContext { + let localContext = new ClassVarDecContext(this.context, this.state); + this.enterRule(localContext, 6, JackParser.RULE_classVarDec); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 108; + _la = this.tokenStream.LA(1); + if(!(_la === 5 || _la === 6)) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 109; + this.fieldList(); + this.state = 110; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public fieldList(): FieldListContext { + let localContext = new FieldListContext(this.context, this.state); + this.enterRule(localContext, 8, JackParser.RULE_fieldList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 112; + this.varType(); + this.state = 113; + this.fieldName(); + this.state = 118; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 25) { + { + { + this.state = 114; + this.match(JackParser.COMMA); + this.state = 115; + this.fieldName(); + } + } + this.state = 120; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public fieldName(): FieldNameContext { + let localContext = new FieldNameContext(this.context, this.state); + this.enterRule(localContext, 10, JackParser.RULE_fieldName); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 121; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public subroutineDeclaration(): SubroutineDeclarationContext { + let localContext = new SubroutineDeclarationContext(this.context, this.state); + this.enterRule(localContext, 12, JackParser.RULE_subroutineDeclaration); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 123; + this.subroutineType(); + this.state = 124; + this.subroutineDecWithoutType(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public subroutineType(): SubroutineTypeContext { + let localContext = new SubroutineTypeContext(this.context, this.state); + this.enterRule(localContext, 14, JackParser.RULE_subroutineType); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 126; + _la = this.tokenStream.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 28) !== 0))) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + let localContext = new SubroutineDecWithoutTypeContext(this.context, this.state); + this.enterRule(localContext, 16, JackParser.RULE_subroutineDecWithoutType); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 128; + this.subroutineReturnType(); + this.state = 129; + this.subroutineName(); + this.state = 130; + this.match(JackParser.LPAREN); + this.state = 131; + this.parameterList(); + this.state = 132; + this.match(JackParser.RPAREN); + this.state = 133; + this.subroutineBody(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public subroutineName(): SubroutineNameContext { + let localContext = new SubroutineNameContext(this.context, this.state); + this.enterRule(localContext, 18, JackParser.RULE_subroutineName); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 135; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public subroutineReturnType(): SubroutineReturnTypeContext { + let localContext = new SubroutineReturnTypeContext(this.context, this.state); + this.enterRule(localContext, 20, JackParser.RULE_subroutineReturnType); + try { + this.state = 139; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case JackParser.INT: + case JackParser.CHAR: + case JackParser.BOOLEAN: + case JackParser.IDENTIFIER: + this.enterOuterAlt(localContext, 1); + { + this.state = 137; + this.varType(); + } + break; + case JackParser.VOID: + this.enterOuterAlt(localContext, 2); + { + this.state = 138; + this.match(JackParser.VOID); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public varType(): VarTypeContext { + let localContext = new VarTypeContext(this.context, this.state); + this.enterRule(localContext, 22, JackParser.RULE_varType); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 141; + _la = this.tokenStream.LA(1); + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45)) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public parameterList(): ParameterListContext { + let localContext = new ParameterListContext(this.context, this.state); + this.enterRule(localContext, 24, JackParser.RULE_parameterList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 151; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45) { + { + this.state = 143; + this.parameter(); + this.state = 148; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 25) { + { + { + this.state = 144; + this.match(JackParser.COMMA); + this.state = 145; + this.parameter(); + } + } + this.state = 150; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public parameter(): ParameterContext { + let localContext = new ParameterContext(this.context, this.state); + this.enterRule(localContext, 26, JackParser.RULE_parameter); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 153; + this.varType(); + this.state = 154; + this.parameterName(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public parameterName(): ParameterNameContext { + let localContext = new ParameterNameContext(this.context, this.state); + this.enterRule(localContext, 28, JackParser.RULE_parameterName); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 156; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public subroutineBody(): SubroutineBodyContext { + let localContext = new SubroutineBodyContext(this.context, this.state); + this.enterRule(localContext, 30, JackParser.RULE_subroutineBody); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 158; + this.match(JackParser.LBRACE); + this.state = 162; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 7) { + { + { + this.state = 159; + this.varDeclaration(); + } + } + this.state = 164; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 165; + this.statements(); + this.state = 166; + this.rBrace(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public rBrace(): RBraceContext { + let localContext = new RBraceContext(this.context, this.state); + this.enterRule(localContext, 32, JackParser.RULE_rBrace); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 168; + this.match(JackParser.RBRACE); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public varDeclaration(): VarDeclarationContext { + let localContext = new VarDeclarationContext(this.context, this.state); + this.enterRule(localContext, 34, JackParser.RULE_varDeclaration); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 170; + this.match(JackParser.VAR); + this.state = 171; + this.varType(); + this.state = 172; + this.varNameInDeclaration(); + this.state = 177; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 25) { + { + { + this.state = 173; + this.match(JackParser.COMMA); + this.state = 174; + this.varNameInDeclaration(); + } + } + this.state = 179; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 180; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public varNameInDeclaration(): VarNameInDeclarationContext { + let localContext = new VarNameInDeclarationContext(this.context, this.state); + this.enterRule(localContext, 36, JackParser.RULE_varNameInDeclaration); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 182; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public statements(): StatementsContext { + let localContext = new StatementsContext(this.context, this.state); + this.enterRule(localContext, 38, JackParser.RULE_statements); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 187; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 225280) !== 0)) { + { + { + this.state = 184; + this.statement(); + } + } + this.state = 189; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public statement(): StatementContext { + let localContext = new StatementContext(this.context, this.state); + this.enterRule(localContext, 40, JackParser.RULE_statement); + try { + this.state = 195; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case JackParser.LET: + this.enterOuterAlt(localContext, 1); + { + this.state = 190; + this.letStatement(); + } + break; + case JackParser.IF: + this.enterOuterAlt(localContext, 2); + { + this.state = 191; + this.ifElseStatement(); + } + break; + case JackParser.WHILE: + this.enterOuterAlt(localContext, 3); + { + this.state = 192; + this.whileStatement(); + } + break; + case JackParser.DO: + this.enterOuterAlt(localContext, 4); + { + this.state = 193; + this.doStatement(); + } + break; + case JackParser.RETURN: + this.enterOuterAlt(localContext, 5); + { + this.state = 194; + this.returnStatement(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public letStatement(): LetStatementContext { + let localContext = new LetStatementContext(this.context, this.state); + this.enterRule(localContext, 42, JackParser.RULE_letStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 197; + this.match(JackParser.LET); + this.state = 200; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 10, this.context) ) { + case 1: + { + this.state = 198; + this.varName(); + } + break; + case 2: + { + this.state = 199; + this.arrayAccess(); + } + break; + } + this.state = 202; + this.equals(); + this.state = 203; + this.expression(0); + this.state = 204; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public equals(): EqualsContext { + let localContext = new EqualsContext(this.context, this.state); + this.enterRule(localContext, 44, JackParser.RULE_equals); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 206; + this.match(JackParser.EQUALS); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public ifElseStatement(): IfElseStatementContext { + let localContext = new IfElseStatementContext(this.context, this.state); + this.enterRule(localContext, 46, JackParser.RULE_ifElseStatement); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 208; + this.ifStatement(); + this.state = 210; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 15) { + { + this.state = 209; + this.elseStatement(); + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public ifStatement(): IfStatementContext { + let localContext = new IfStatementContext(this.context, this.state); + this.enterRule(localContext, 48, JackParser.RULE_ifStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 212; + this.match(JackParser.IF); + this.state = 213; + this.match(JackParser.LPAREN); + this.state = 214; + this.ifExpression(); + this.state = 215; + this.match(JackParser.RPAREN); + this.state = 216; + this.match(JackParser.LBRACE); + this.state = 217; + this.statements(); + this.state = 218; + this.rBrace(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public ifExpression(): IfExpressionContext { + let localContext = new IfExpressionContext(this.context, this.state); + this.enterRule(localContext, 50, JackParser.RULE_ifExpression); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 220; + this.expression(0); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public elseStatement(): ElseStatementContext { + let localContext = new ElseStatementContext(this.context, this.state); + this.enterRule(localContext, 52, JackParser.RULE_elseStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 222; + this.match(JackParser.ELSE); + this.state = 223; + this.match(JackParser.LBRACE); + this.state = 224; + this.statements(); + this.state = 225; + this.rBrace(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public whileStatement(): WhileStatementContext { + let localContext = new WhileStatementContext(this.context, this.state); + this.enterRule(localContext, 54, JackParser.RULE_whileStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 227; + this.match(JackParser.WHILE); + this.state = 228; + this.match(JackParser.LPAREN); + this.state = 229; + this.whileExpression(); + this.state = 230; + this.match(JackParser.RPAREN); + this.state = 231; + this.match(JackParser.LBRACE); + this.state = 232; + this.statements(); + this.state = 233; + this.rBrace(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public whileExpression(): WhileExpressionContext { + let localContext = new WhileExpressionContext(this.context, this.state); + this.enterRule(localContext, 56, JackParser.RULE_whileExpression); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 235; + this.expression(0); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public doStatement(): DoStatementContext { + let localContext = new DoStatementContext(this.context, this.state); + this.enterRule(localContext, 58, JackParser.RULE_doStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 237; + this.match(JackParser.DO); + this.state = 238; + this.subroutineCall(); + this.state = 239; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public subroutineCall(): SubroutineCallContext { + let localContext = new SubroutineCallContext(this.context, this.state); + this.enterRule(localContext, 60, JackParser.RULE_subroutineCall); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 241; + this.subroutineId(); + this.state = 242; + this.match(JackParser.LPAREN); + this.state = 243; + this.expressionList(); + this.state = 244; + this.match(JackParser.RPAREN); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public subroutineId(): SubroutineIdContext { + let localContext = new SubroutineIdContext(this.context, this.state); + this.enterRule(localContext, 62, JackParser.RULE_subroutineId); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 251; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 13, this.context) ) { + case 1: + { + this.state = 248; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case JackParser.IDENTIFIER: + { + this.state = 246; + this.className(); + } + break; + case JackParser.THIS_LITERAL: + { + this.state = 247; + this.match(JackParser.THIS_LITERAL); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + this.state = 250; + this.match(JackParser.DOT); + } + break; + } + this.state = 253; + this.subroutineName(); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public returnStatement(): ReturnStatementContext { + let localContext = new ReturnStatementContext(this.context, this.state); + this.enterRule(localContext, 64, JackParser.RULE_returnStatement); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 255; + this.match(JackParser.RETURN); + this.state = 257; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 133186049) !== 0)) { + { + this.state = 256; + this.expression(0); + } + } + + this.state = 259; + this.match(JackParser.SEMICOLON); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public expressionList(): ExpressionListContext { + let localContext = new ExpressionListContext(this.context, this.state); + this.enterRule(localContext, 66, JackParser.RULE_expressionList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 269; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 133186049) !== 0)) { + { + this.state = 261; + this.expression(0); + this.state = 266; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 25) { + { + { + this.state = 262; + this.match(JackParser.COMMA); + this.state = 263; + this.expression(0); + } + } + this.state = 268; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + + public expression(): ExpressionContext; + public expression(_p: number): ExpressionContext; + public expression(_p?: number): ExpressionContext { + if (_p === undefined) { + _p = 0; + } + + let parentContext = this.context; + let parentState = this.state; + let localContext = new ExpressionContext(this.context, parentState); + let previousContext = localContext; + let _startState = 68; + this.enterRecursionRule(localContext, 68, JackParser.RULE_expression, _p); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 278; + this.errorHandler.sync(this); + switch (this.interpreter.adaptivePredict(this.tokenStream, 17, this.context) ) { + case 1: + { + this.state = 272; + this.constant(); + } + break; + case 2: + { + this.state = 273; + this.varName(); + } + break; + case 3: + { + this.state = 274; + this.subroutineCall(); + } + break; + case 4: + { + this.state = 275; + this.arrayAccess(); + } + break; + case 5: + { + this.state = 276; + this.unaryOperation(); + } + break; + case 6: + { + this.state = 277; + this.groupedExpression(); + } + break; + } + this.context!.stop = this.tokenStream.LT(-1); + this.state = 286; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 18, this.context); + while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { + if (alternative === 1) { + if (this.parseListeners != null) { + this.triggerExitRuleEvent(); + } + previousContext = localContext; + { + { + localContext = new ExpressionContext(parentContext, parentState); + this.pushNewRecursionContext(localContext, _startState, JackParser.RULE_expression); + this.state = 280; + if (!(this.precpred(this.context, 2))) { + throw this.createFailedPredicateException("this.precpred(this.context, 2)"); + } + this.state = 281; + this.binaryOperator(); + this.state = 282; + this.expression(3); + } + } + } + this.state = 288; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict(this.tokenStream, 18, this.context); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.unrollRecursionContexts(parentContext); + } + return localContext; + } + public constant(): ConstantContext { + let localContext = new ConstantContext(this.context, this.state); + this.enterRule(localContext, 70, JackParser.RULE_constant); + try { + this.state = 294; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case JackParser.INTEGER_LITERAL: + this.enterOuterAlt(localContext, 1); + { + this.state = 289; + this.match(JackParser.INTEGER_LITERAL); + } + break; + case JackParser.STRING_LITERAL: + this.enterOuterAlt(localContext, 2); + { + this.state = 290; + this.match(JackParser.STRING_LITERAL); + } + break; + case JackParser.TRUE: + case JackParser.FALSE: + this.enterOuterAlt(localContext, 3); + { + this.state = 291; + this.booleanLiteral(); + } + break; + case JackParser.NULL_LITERAL: + this.enterOuterAlt(localContext, 4); + { + this.state = 292; + this.match(JackParser.NULL_LITERAL); + } + break; + case JackParser.THIS_LITERAL: + this.enterOuterAlt(localContext, 5); + { + this.state = 293; + this.match(JackParser.THIS_LITERAL); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public varName(): VarNameContext { + let localContext = new VarNameContext(this.context, this.state); + this.enterRule(localContext, 72, JackParser.RULE_varName); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 296; + this.match(JackParser.IDENTIFIER); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public arrayAccess(): ArrayAccessContext { + let localContext = new ArrayAccessContext(this.context, this.state); + this.enterRule(localContext, 74, JackParser.RULE_arrayAccess); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 298; + this.varName(); + this.state = 299; + this.match(JackParser.LBRACKET); + this.state = 300; + this.expression(0); + this.state = 301; + this.match(JackParser.RBRACKET); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public unaryOperation(): UnaryOperationContext { + let localContext = new UnaryOperationContext(this.context, this.state); + this.enterRule(localContext, 76, JackParser.RULE_unaryOperation); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 303; + this.unaryOperator(); + this.state = 304; + this.expression(0); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public groupedExpression(): GroupedExpressionContext { + let localContext = new GroupedExpressionContext(this.context, this.state); + this.enterRule(localContext, 78, JackParser.RULE_groupedExpression); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 306; + this.match(JackParser.LPAREN); + this.state = 307; + this.expression(0); + this.state = 308; + this.match(JackParser.RPAREN); + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public booleanLiteral(): BooleanLiteralContext { + let localContext = new BooleanLiteralContext(this.context, this.state); + this.enterRule(localContext, 80, JackParser.RULE_booleanLiteral); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 310; + _la = this.tokenStream.LA(1); + if(!(_la === 41 || _la === 42)) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public unaryOperator(): UnaryOperatorContext { + let localContext = new UnaryOperatorContext(this.context, this.state); + this.enterRule(localContext, 82, JackParser.RULE_unaryOperator); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 312; + _la = this.tokenStream.LA(1); + if(!(_la === 29 || _la === 34)) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + public binaryOperator(): BinaryOperatorContext { + let localContext = new BinaryOperatorContext(this.context, this.state); + this.enterRule(localContext, 84, JackParser.RULE_binaryOperator); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 314; + _la = this.tokenStream.LA(1); + if(!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & 895) !== 0))) { + this.errorHandler.recoverInline(this); + } + else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } + catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localContext; + } + + public override sempred(localContext: antlr.ParserRuleContext | null, ruleIndex: number, predIndex: number): boolean { + switch (ruleIndex) { + case 34: + return this.expression_sempred(localContext as ExpressionContext, predIndex); + } + return true; + } + private expression_sempred(localContext: ExpressionContext | null, predIndex: number): boolean { + switch (predIndex) { + case 0: + return this.precpred(this.context, 2); + } + return true; + } + + public static readonly _serializedATN: number[] = [ + 4,1,46,317,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7, + 6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13, + 2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20, + 7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26, + 2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33, + 7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39, + 2,40,7,40,2,41,7,41,2,42,7,42,1,0,1,0,1,0,1,1,1,1,1,1,1,1,5,1,94, + 8,1,10,1,12,1,97,9,1,1,1,5,1,100,8,1,10,1,12,1,103,9,1,1,1,1,1,1, + 2,1,2,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,5,4,117,8,4,10,4,12,4,120, + 9,4,1,5,1,5,1,6,1,6,1,6,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9, + 1,9,1,10,1,10,3,10,140,8,10,1,11,1,11,1,12,1,12,1,12,5,12,147,8, + 12,10,12,12,12,150,9,12,3,12,152,8,12,1,13,1,13,1,13,1,14,1,14,1, + 15,1,15,5,15,161,8,15,10,15,12,15,164,9,15,1,15,1,15,1,15,1,16,1, + 16,1,17,1,17,1,17,1,17,1,17,5,17,176,8,17,10,17,12,17,179,9,17,1, + 17,1,17,1,18,1,18,1,19,5,19,186,8,19,10,19,12,19,189,9,19,1,20,1, + 20,1,20,1,20,1,20,3,20,196,8,20,1,21,1,21,1,21,3,21,201,8,21,1,21, + 1,21,1,21,1,21,1,22,1,22,1,23,1,23,3,23,211,8,23,1,24,1,24,1,24, + 1,24,1,24,1,24,1,24,1,24,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,27, + 1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,29,1,29,1,29,1,29, + 1,30,1,30,1,30,1,30,1,30,1,31,1,31,3,31,249,8,31,1,31,3,31,252,8, + 31,1,31,1,31,1,32,1,32,3,32,258,8,32,1,32,1,32,1,33,1,33,1,33,5, + 33,265,8,33,10,33,12,33,268,9,33,3,33,270,8,33,1,34,1,34,1,34,1, + 34,1,34,1,34,1,34,3,34,279,8,34,1,34,1,34,1,34,1,34,5,34,285,8,34, + 10,34,12,34,288,9,34,1,35,1,35,1,35,1,35,1,35,3,35,295,8,35,1,36, + 1,36,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,38,1,39,1,39,1,39,1,39, + 1,40,1,40,1,41,1,41,1,42,1,42,1,42,0,1,68,43,0,2,4,6,8,10,12,14, + 16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58, + 60,62,64,66,68,70,72,74,76,78,80,82,84,0,6,1,0,5,6,1,0,2,4,2,0,8, + 10,45,45,1,0,41,42,2,0,29,29,34,34,2,0,27,33,35,36,303,0,86,1,0, + 0,0,2,89,1,0,0,0,4,106,1,0,0,0,6,108,1,0,0,0,8,112,1,0,0,0,10,121, + 1,0,0,0,12,123,1,0,0,0,14,126,1,0,0,0,16,128,1,0,0,0,18,135,1,0, + 0,0,20,139,1,0,0,0,22,141,1,0,0,0,24,151,1,0,0,0,26,153,1,0,0,0, + 28,156,1,0,0,0,30,158,1,0,0,0,32,168,1,0,0,0,34,170,1,0,0,0,36,182, + 1,0,0,0,38,187,1,0,0,0,40,195,1,0,0,0,42,197,1,0,0,0,44,206,1,0, + 0,0,46,208,1,0,0,0,48,212,1,0,0,0,50,220,1,0,0,0,52,222,1,0,0,0, + 54,227,1,0,0,0,56,235,1,0,0,0,58,237,1,0,0,0,60,241,1,0,0,0,62,251, + 1,0,0,0,64,255,1,0,0,0,66,269,1,0,0,0,68,278,1,0,0,0,70,294,1,0, + 0,0,72,296,1,0,0,0,74,298,1,0,0,0,76,303,1,0,0,0,78,306,1,0,0,0, + 80,310,1,0,0,0,82,312,1,0,0,0,84,314,1,0,0,0,86,87,3,2,1,0,87,88, + 5,0,0,1,88,1,1,0,0,0,89,90,5,1,0,0,90,91,3,4,2,0,91,95,5,18,0,0, + 92,94,3,6,3,0,93,92,1,0,0,0,94,97,1,0,0,0,95,93,1,0,0,0,95,96,1, + 0,0,0,96,101,1,0,0,0,97,95,1,0,0,0,98,100,3,12,6,0,99,98,1,0,0,0, + 100,103,1,0,0,0,101,99,1,0,0,0,101,102,1,0,0,0,102,104,1,0,0,0,103, + 101,1,0,0,0,104,105,3,32,16,0,105,3,1,0,0,0,106,107,5,45,0,0,107, + 5,1,0,0,0,108,109,7,0,0,0,109,110,3,8,4,0,110,111,5,26,0,0,111,7, + 1,0,0,0,112,113,3,22,11,0,113,118,3,10,5,0,114,115,5,25,0,0,115, + 117,3,10,5,0,116,114,1,0,0,0,117,120,1,0,0,0,118,116,1,0,0,0,118, + 119,1,0,0,0,119,9,1,0,0,0,120,118,1,0,0,0,121,122,5,45,0,0,122,11, + 1,0,0,0,123,124,3,14,7,0,124,125,3,16,8,0,125,13,1,0,0,0,126,127, + 7,1,0,0,127,15,1,0,0,0,128,129,3,20,10,0,129,130,3,18,9,0,130,131, + 5,20,0,0,131,132,3,24,12,0,132,133,5,21,0,0,133,134,3,30,15,0,134, + 17,1,0,0,0,135,136,5,45,0,0,136,19,1,0,0,0,137,140,3,22,11,0,138, + 140,5,11,0,0,139,137,1,0,0,0,139,138,1,0,0,0,140,21,1,0,0,0,141, + 142,7,2,0,0,142,23,1,0,0,0,143,148,3,26,13,0,144,145,5,25,0,0,145, + 147,3,26,13,0,146,144,1,0,0,0,147,150,1,0,0,0,148,146,1,0,0,0,148, + 149,1,0,0,0,149,152,1,0,0,0,150,148,1,0,0,0,151,143,1,0,0,0,151, + 152,1,0,0,0,152,25,1,0,0,0,153,154,3,22,11,0,154,155,3,28,14,0,155, + 27,1,0,0,0,156,157,5,45,0,0,157,29,1,0,0,0,158,162,5,18,0,0,159, + 161,3,34,17,0,160,159,1,0,0,0,161,164,1,0,0,0,162,160,1,0,0,0,162, + 163,1,0,0,0,163,165,1,0,0,0,164,162,1,0,0,0,165,166,3,38,19,0,166, + 167,3,32,16,0,167,31,1,0,0,0,168,169,5,19,0,0,169,33,1,0,0,0,170, + 171,5,7,0,0,171,172,3,22,11,0,172,177,3,36,18,0,173,174,5,25,0,0, + 174,176,3,36,18,0,175,173,1,0,0,0,176,179,1,0,0,0,177,175,1,0,0, + 0,177,178,1,0,0,0,178,180,1,0,0,0,179,177,1,0,0,0,180,181,5,26,0, + 0,181,35,1,0,0,0,182,183,5,45,0,0,183,37,1,0,0,0,184,186,3,40,20, + 0,185,184,1,0,0,0,186,189,1,0,0,0,187,185,1,0,0,0,187,188,1,0,0, + 0,188,39,1,0,0,0,189,187,1,0,0,0,190,196,3,42,21,0,191,196,3,46, + 23,0,192,196,3,54,27,0,193,196,3,58,29,0,194,196,3,64,32,0,195,190, + 1,0,0,0,195,191,1,0,0,0,195,192,1,0,0,0,195,193,1,0,0,0,195,194, + 1,0,0,0,196,41,1,0,0,0,197,200,5,12,0,0,198,201,3,72,36,0,199,201, + 3,74,37,0,200,198,1,0,0,0,200,199,1,0,0,0,201,202,1,0,0,0,202,203, + 3,44,22,0,203,204,3,68,34,0,204,205,5,26,0,0,205,43,1,0,0,0,206, + 207,5,27,0,0,207,45,1,0,0,0,208,210,3,48,24,0,209,211,3,52,26,0, + 210,209,1,0,0,0,210,211,1,0,0,0,211,47,1,0,0,0,212,213,5,14,0,0, + 213,214,5,20,0,0,214,215,3,50,25,0,215,216,5,21,0,0,216,217,5,18, + 0,0,217,218,3,38,19,0,218,219,3,32,16,0,219,49,1,0,0,0,220,221,3, + 68,34,0,221,51,1,0,0,0,222,223,5,15,0,0,223,224,5,18,0,0,224,225, + 3,38,19,0,225,226,3,32,16,0,226,53,1,0,0,0,227,228,5,16,0,0,228, + 229,5,20,0,0,229,230,3,56,28,0,230,231,5,21,0,0,231,232,5,18,0,0, + 232,233,3,38,19,0,233,234,3,32,16,0,234,55,1,0,0,0,235,236,3,68, + 34,0,236,57,1,0,0,0,237,238,5,13,0,0,238,239,3,60,30,0,239,240,5, + 26,0,0,240,59,1,0,0,0,241,242,3,62,31,0,242,243,5,20,0,0,243,244, + 3,66,33,0,244,245,5,21,0,0,245,61,1,0,0,0,246,249,3,4,2,0,247,249, + 5,44,0,0,248,246,1,0,0,0,248,247,1,0,0,0,249,250,1,0,0,0,250,252, + 5,24,0,0,251,248,1,0,0,0,251,252,1,0,0,0,252,253,1,0,0,0,253,254, + 3,18,9,0,254,63,1,0,0,0,255,257,5,17,0,0,256,258,3,68,34,0,257,256, + 1,0,0,0,257,258,1,0,0,0,258,259,1,0,0,0,259,260,5,26,0,0,260,65, + 1,0,0,0,261,266,3,68,34,0,262,263,5,25,0,0,263,265,3,68,34,0,264, + 262,1,0,0,0,265,268,1,0,0,0,266,264,1,0,0,0,266,267,1,0,0,0,267, + 270,1,0,0,0,268,266,1,0,0,0,269,261,1,0,0,0,269,270,1,0,0,0,270, + 67,1,0,0,0,271,272,6,34,-1,0,272,279,3,70,35,0,273,279,3,72,36,0, + 274,279,3,60,30,0,275,279,3,74,37,0,276,279,3,76,38,0,277,279,3, + 78,39,0,278,271,1,0,0,0,278,273,1,0,0,0,278,274,1,0,0,0,278,275, + 1,0,0,0,278,276,1,0,0,0,278,277,1,0,0,0,279,286,1,0,0,0,280,281, + 10,2,0,0,281,282,3,84,42,0,282,283,3,68,34,3,283,285,1,0,0,0,284, + 280,1,0,0,0,285,288,1,0,0,0,286,284,1,0,0,0,286,287,1,0,0,0,287, + 69,1,0,0,0,288,286,1,0,0,0,289,295,5,40,0,0,290,295,5,46,0,0,291, + 295,3,80,40,0,292,295,5,43,0,0,293,295,5,44,0,0,294,289,1,0,0,0, + 294,290,1,0,0,0,294,291,1,0,0,0,294,292,1,0,0,0,294,293,1,0,0,0, + 295,71,1,0,0,0,296,297,5,45,0,0,297,73,1,0,0,0,298,299,3,72,36,0, + 299,300,5,22,0,0,300,301,3,68,34,0,301,302,5,23,0,0,302,75,1,0,0, + 0,303,304,3,82,41,0,304,305,3,68,34,0,305,77,1,0,0,0,306,307,5,20, + 0,0,307,308,3,68,34,0,308,309,5,21,0,0,309,79,1,0,0,0,310,311,7, + 3,0,0,311,81,1,0,0,0,312,313,7,4,0,0,313,83,1,0,0,0,314,315,7,5, + 0,0,315,85,1,0,0,0,20,95,101,118,139,148,151,162,177,187,195,200, + 210,248,251,257,266,269,278,286,294 + ]; + + private static __ATN: antlr.ATN; + public static get _ATN(): antlr.ATN { + if (!JackParser.__ATN) { + JackParser.__ATN = new antlr.ATNDeserializer().deserialize(JackParser._serializedATN); + } + + return JackParser.__ATN; + } + + + private static readonly vocabulary = new antlr.Vocabulary(JackParser.literalNames, JackParser.symbolicNames, []); + + public override get vocabulary(): antlr.Vocabulary { + return JackParser.vocabulary; + } + + private static readonly decisionsToDFA = JackParser._ATN.decisionToState.map( (ds: antlr.DecisionState, index: number) => new antlr.DFA(ds, index) ); } -export class ProgramContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public classDeclaration(): ClassDeclarationContext { - return this.getTypedRuleContext(ClassDeclarationContext, 0) as ClassDeclarationContext; - } - public EOF(): TerminalNode { - return this.getToken(JackParser.EOF, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_program; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterProgram) { - listener.enterProgram(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitProgram) { - listener.exitProgram(this); - } - } +export class ProgramContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public classDeclaration(): ClassDeclarationContext { + return this.getRuleContext(0, ClassDeclarationContext)!; + } + public EOF(): antlr.TerminalNode { + return this.getToken(JackParser.EOF, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_program; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterProgram) { + listener.enterProgram(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitProgram) { + listener.exitProgram(this); + } + } } -export class ClassDeclarationContext extends ParserRuleContext { - public localSymbolTable: LocalSymbolTable | undefined; - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public CLASS(): TerminalNode { - return this.getToken(JackParser.CLASS, 0); - } - public className(): ClassNameContext { - return this.getTypedRuleContext(ClassNameContext, 0) as ClassNameContext; - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public classVarDec_list(): ClassVarDecContext[] { - return this.getTypedRuleContexts(ClassVarDecContext) as ClassVarDecContext[]; - } - public classVarDec(i: number): ClassVarDecContext { - return this.getTypedRuleContext(ClassVarDecContext, i) as ClassVarDecContext; - } - public subroutineDeclaration_list(): SubroutineDeclarationContext[] { - return this.getTypedRuleContexts(SubroutineDeclarationContext) as SubroutineDeclarationContext[]; - } - public subroutineDeclaration(i: number): SubroutineDeclarationContext { - return this.getTypedRuleContext(SubroutineDeclarationContext, i) as SubroutineDeclarationContext; - } - public get ruleIndex(): number { - return JackParser.RULE_classDeclaration; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterClassDeclaration) { - listener.enterClassDeclaration(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitClassDeclaration) { - listener.exitClassDeclaration(this); - } - } +export class ClassDeclarationContext extends antlr.ParserRuleContext { + public localSymbolTable: LocalSymbolTable | undefined; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public CLASS(): antlr.TerminalNode { + return this.getToken(JackParser.CLASS, 0)!; + } + public className(): ClassNameContext { + return this.getRuleContext(0, ClassNameContext)!; + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public classVarDec(): ClassVarDecContext[]; + public classVarDec(i: number): ClassVarDecContext | null; + public classVarDec(i?: number): ClassVarDecContext[] | ClassVarDecContext | null { + if (i === undefined) { + return this.getRuleContexts(ClassVarDecContext); + } + + return this.getRuleContext(i, ClassVarDecContext); + } + public subroutineDeclaration(): SubroutineDeclarationContext[]; + public subroutineDeclaration(i: number): SubroutineDeclarationContext | null; + public subroutineDeclaration(i?: number): SubroutineDeclarationContext[] | SubroutineDeclarationContext | null { + if (i === undefined) { + return this.getRuleContexts(SubroutineDeclarationContext); + } + + return this.getRuleContext(i, SubroutineDeclarationContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_classDeclaration; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterClassDeclaration) { + listener.enterClassDeclaration(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitClassDeclaration) { + listener.exitClassDeclaration(this); + } + } } -export class ClassNameContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_className; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterClassName) { - listener.enterClassName(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitClassName) { - listener.exitClassName(this); - } - } +export class ClassNameContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_className; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterClassName) { + listener.enterClassName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitClassName) { + listener.exitClassName(this); + } + } } -export class ClassVarDecContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public fieldList(): FieldListContext { - return this.getTypedRuleContext(FieldListContext, 0) as FieldListContext; - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public STATIC(): TerminalNode { - return this.getToken(JackParser.STATIC, 0); - } - public FIELD(): TerminalNode { - return this.getToken(JackParser.FIELD, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_classVarDec; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterClassVarDec) { - listener.enterClassVarDec(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitClassVarDec) { - listener.exitClassVarDec(this); - } - } +export class ClassVarDecContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public fieldList(): FieldListContext { + return this.getRuleContext(0, FieldListContext)!; + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public STATIC(): antlr.TerminalNode | null { + return this.getToken(JackParser.STATIC, 0); + } + public FIELD(): antlr.TerminalNode | null { + return this.getToken(JackParser.FIELD, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_classVarDec; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterClassVarDec) { + listener.enterClassVarDec(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitClassVarDec) { + listener.exitClassVarDec(this); + } + } } -export class FieldListContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public varType(): VarTypeContext { - return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; - } - public fieldName_list(): FieldNameContext[] { - return this.getTypedRuleContexts(FieldNameContext) as FieldNameContext[]; - } - public fieldName(i: number): FieldNameContext { - return this.getTypedRuleContext(FieldNameContext, i) as FieldNameContext; - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(JackParser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(JackParser.COMMA, i); - } - public get ruleIndex(): number { - return JackParser.RULE_fieldList; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterFieldList) { - listener.enterFieldList(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitFieldList) { - listener.exitFieldList(this); - } - } +export class FieldListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext)!; + } + public fieldName(): FieldNameContext[]; + public fieldName(i: number): FieldNameContext | null; + public fieldName(i?: number): FieldNameContext[] | FieldNameContext | null { + if (i === undefined) { + return this.getRuleContexts(FieldNameContext); + } + + return this.getRuleContext(i, FieldNameContext); + } + public COMMA(): antlr.TerminalNode[]; + public COMMA(i: number): antlr.TerminalNode | null; + public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public override get ruleIndex(): number { + return JackParser.RULE_fieldList; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterFieldList) { + listener.enterFieldList(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitFieldList) { + listener.exitFieldList(this); + } + } } -export class FieldNameContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_fieldName; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterFieldName) { - listener.enterFieldName(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitFieldName) { - listener.exitFieldName(this); - } - } +export class FieldNameContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_fieldName; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterFieldName) { + listener.enterFieldName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitFieldName) { + listener.exitFieldName(this); + } + } } -export class SubroutineDeclarationContext extends ParserRuleContext { - public symbols: SubroutineScope | undefined; - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public subroutineType(): SubroutineTypeContext { - return this.getTypedRuleContext(SubroutineTypeContext, 0) as SubroutineTypeContext; - } - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - return this.getTypedRuleContext(SubroutineDecWithoutTypeContext, 0) as SubroutineDecWithoutTypeContext; - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineDeclaration; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineDeclaration) { - listener.enterSubroutineDeclaration(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineDeclaration) { - listener.exitSubroutineDeclaration(this); - } - } +export class SubroutineDeclarationContext extends antlr.ParserRuleContext { + public symbols: SubroutineScope | undefined; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public subroutineType(): SubroutineTypeContext { + return this.getRuleContext(0, SubroutineTypeContext)!; + } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + return this.getRuleContext(0, SubroutineDecWithoutTypeContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineDeclaration; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineDeclaration) { + listener.enterSubroutineDeclaration(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineDeclaration) { + listener.exitSubroutineDeclaration(this); + } + } } -export class SubroutineTypeContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public CONSTRUCTOR(): TerminalNode { - return this.getToken(JackParser.CONSTRUCTOR, 0); - } - public METHOD(): TerminalNode { - return this.getToken(JackParser.METHOD, 0); - } - public FUNCTION(): TerminalNode { - return this.getToken(JackParser.FUNCTION, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineType; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineType) { - listener.enterSubroutineType(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineType) { - listener.exitSubroutineType(this); - } - } +export class SubroutineTypeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public CONSTRUCTOR(): antlr.TerminalNode | null { + return this.getToken(JackParser.CONSTRUCTOR, 0); + } + public METHOD(): antlr.TerminalNode | null { + return this.getToken(JackParser.METHOD, 0); + } + public FUNCTION(): antlr.TerminalNode | null { + return this.getToken(JackParser.FUNCTION, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineType; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineType) { + listener.enterSubroutineType(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineType) { + listener.exitSubroutineType(this); + } + } } -export class SubroutineDecWithoutTypeContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public subroutineReturnType(): SubroutineReturnTypeContext { - return this.getTypedRuleContext(SubroutineReturnTypeContext, 0) as SubroutineReturnTypeContext; - } - public subroutineName(): SubroutineNameContext { - return this.getTypedRuleContext(SubroutineNameContext, 0) as SubroutineNameContext; - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public parameterList(): ParameterListContext { - return this.getTypedRuleContext(ParameterListContext, 0) as ParameterListContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public subroutineBody(): SubroutineBodyContext { - return this.getTypedRuleContext(SubroutineBodyContext, 0) as SubroutineBodyContext; - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineDecWithoutType; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineDecWithoutType) { - listener.enterSubroutineDecWithoutType(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineDecWithoutType) { - listener.exitSubroutineDecWithoutType(this); - } - } +export class SubroutineDecWithoutTypeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public subroutineReturnType(): SubroutineReturnTypeContext { + return this.getRuleContext(0, SubroutineReturnTypeContext)!; + } + public subroutineName(): SubroutineNameContext { + return this.getRuleContext(0, SubroutineNameContext)!; + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public parameterList(): ParameterListContext { + return this.getRuleContext(0, ParameterListContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public subroutineBody(): SubroutineBodyContext { + return this.getRuleContext(0, SubroutineBodyContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineDecWithoutType; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineDecWithoutType) { + listener.enterSubroutineDecWithoutType(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineDecWithoutType) { + listener.exitSubroutineDecWithoutType(this); + } + } } -export class SubroutineNameContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineName; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineName) { - listener.enterSubroutineName(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineName) { - listener.exitSubroutineName(this); - } - } +export class SubroutineNameContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineName; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineName) { + listener.enterSubroutineName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineName) { + listener.exitSubroutineName(this); + } + } } -export class SubroutineReturnTypeContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public varType(): VarTypeContext { - return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; - } - public VOID(): TerminalNode { - return this.getToken(JackParser.VOID, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineReturnType; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineReturnType) { - listener.enterSubroutineReturnType(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineReturnType) { - listener.exitSubroutineReturnType(this); - } - } +export class SubroutineReturnTypeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public varType(): VarTypeContext | null { + return this.getRuleContext(0, VarTypeContext); + } + public VOID(): antlr.TerminalNode | null { + return this.getToken(JackParser.VOID, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineReturnType; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineReturnType) { + listener.enterSubroutineReturnType(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineReturnType) { + listener.exitSubroutineReturnType(this); + } + } } -export class VarTypeContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public INT(): TerminalNode { - return this.getToken(JackParser.INT, 0); - } - public CHAR(): TerminalNode { - return this.getToken(JackParser.CHAR, 0); - } - public BOOLEAN(): TerminalNode { - return this.getToken(JackParser.BOOLEAN, 0); - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_varType; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterVarType) { - listener.enterVarType(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitVarType) { - listener.exitVarType(this); - } - } +export class VarTypeContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public INT(): antlr.TerminalNode | null { + return this.getToken(JackParser.INT, 0); + } + public CHAR(): antlr.TerminalNode | null { + return this.getToken(JackParser.CHAR, 0); + } + public BOOLEAN(): antlr.TerminalNode | null { + return this.getToken(JackParser.BOOLEAN, 0); + } + public IDENTIFIER(): antlr.TerminalNode | null { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_varType; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterVarType) { + listener.enterVarType(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitVarType) { + listener.exitVarType(this); + } + } } -export class ParameterListContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public parameter_list(): ParameterContext[] { - return this.getTypedRuleContexts(ParameterContext) as ParameterContext[]; - } - public parameter(i: number): ParameterContext { - return this.getTypedRuleContext(ParameterContext, i) as ParameterContext; - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(JackParser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(JackParser.COMMA, i); - } - public get ruleIndex(): number { - return JackParser.RULE_parameterList; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterParameterList) { - listener.enterParameterList(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitParameterList) { - listener.exitParameterList(this); - } - } +export class ParameterListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public parameter(): ParameterContext[]; + public parameter(i: number): ParameterContext | null; + public parameter(i?: number): ParameterContext[] | ParameterContext | null { + if (i === undefined) { + return this.getRuleContexts(ParameterContext); + } + + return this.getRuleContext(i, ParameterContext); + } + public COMMA(): antlr.TerminalNode[]; + public COMMA(i: number): antlr.TerminalNode | null; + public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public override get ruleIndex(): number { + return JackParser.RULE_parameterList; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterParameterList) { + listener.enterParameterList(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitParameterList) { + listener.exitParameterList(this); + } + } } -export class ParameterContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public varType(): VarTypeContext { - return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; - } - public parameterName(): ParameterNameContext { - return this.getTypedRuleContext(ParameterNameContext, 0) as ParameterNameContext; - } - public get ruleIndex(): number { - return JackParser.RULE_parameter; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterParameter) { - listener.enterParameter(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitParameter) { - listener.exitParameter(this); - } - } +export class ParameterContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext)!; + } + public parameterName(): ParameterNameContext { + return this.getRuleContext(0, ParameterNameContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_parameter; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterParameter) { + listener.enterParameter(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitParameter) { + listener.exitParameter(this); + } + } } -export class ParameterNameContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_parameterName; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterParameterName) { - listener.enterParameterName(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitParameterName) { - listener.exitParameterName(this); - } - } +export class ParameterNameContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_parameterName; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterParameterName) { + listener.enterParameterName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitParameterName) { + listener.exitParameterName(this); + } + } } -export class SubroutineBodyContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public statements(): StatementsContext { - return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public varDeclaration_list(): VarDeclarationContext[] { - return this.getTypedRuleContexts(VarDeclarationContext) as VarDeclarationContext[]; - } - public varDeclaration(i: number): VarDeclarationContext { - return this.getTypedRuleContext(VarDeclarationContext, i) as VarDeclarationContext; - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineBody; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineBody) { - listener.enterSubroutineBody(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineBody) { - listener.exitSubroutineBody(this); - } - } +export class SubroutineBodyContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public varDeclaration(): VarDeclarationContext[]; + public varDeclaration(i: number): VarDeclarationContext | null; + public varDeclaration(i?: number): VarDeclarationContext[] | VarDeclarationContext | null { + if (i === undefined) { + return this.getRuleContexts(VarDeclarationContext); + } + + return this.getRuleContext(i, VarDeclarationContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineBody; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineBody) { + listener.enterSubroutineBody(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineBody) { + listener.exitSubroutineBody(this); + } + } } -export class RBraceContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public RBRACE(): TerminalNode { - return this.getToken(JackParser.RBRACE, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_rBrace; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterRBrace) { - listener.enterRBrace(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitRBrace) { - listener.exitRBrace(this); - } - } +export class RBraceContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public RBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.RBRACE, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_rBrace; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterRBrace) { + listener.enterRBrace(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitRBrace) { + listener.exitRBrace(this); + } + } } -export class VarDeclarationContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public VAR(): TerminalNode { - return this.getToken(JackParser.VAR, 0); - } - public varType(): VarTypeContext { - return this.getTypedRuleContext(VarTypeContext, 0) as VarTypeContext; - } - public varNameInDeclaration_list(): VarNameInDeclarationContext[] { - return this.getTypedRuleContexts(VarNameInDeclarationContext) as VarNameInDeclarationContext[]; - } - public varNameInDeclaration(i: number): VarNameInDeclarationContext { - return this.getTypedRuleContext(VarNameInDeclarationContext, i) as VarNameInDeclarationContext; - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(JackParser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(JackParser.COMMA, i); - } - public get ruleIndex(): number { - return JackParser.RULE_varDeclaration; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterVarDeclaration) { - listener.enterVarDeclaration(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitVarDeclaration) { - listener.exitVarDeclaration(this); - } - } +export class VarDeclarationContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public VAR(): antlr.TerminalNode { + return this.getToken(JackParser.VAR, 0)!; + } + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext)!; + } + public varNameInDeclaration(): VarNameInDeclarationContext[]; + public varNameInDeclaration(i: number): VarNameInDeclarationContext | null; + public varNameInDeclaration(i?: number): VarNameInDeclarationContext[] | VarNameInDeclarationContext | null { + if (i === undefined) { + return this.getRuleContexts(VarNameInDeclarationContext); + } + + return this.getRuleContext(i, VarNameInDeclarationContext); + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public COMMA(): antlr.TerminalNode[]; + public COMMA(i: number): antlr.TerminalNode | null; + public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public override get ruleIndex(): number { + return JackParser.RULE_varDeclaration; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterVarDeclaration) { + listener.enterVarDeclaration(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitVarDeclaration) { + listener.exitVarDeclaration(this); + } + } } -export class VarNameInDeclarationContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_varNameInDeclaration; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterVarNameInDeclaration) { - listener.enterVarNameInDeclaration(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitVarNameInDeclaration) { - listener.exitVarNameInDeclaration(this); - } - } +export class VarNameInDeclarationContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_varNameInDeclaration; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterVarNameInDeclaration) { + listener.enterVarNameInDeclaration(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitVarNameInDeclaration) { + listener.exitVarNameInDeclaration(this); + } + } } -export class StatementsContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public statement_list(): StatementContext[] { - return this.getTypedRuleContexts(StatementContext) as StatementContext[]; - } - public statement(i: number): StatementContext { - return this.getTypedRuleContext(StatementContext, i) as StatementContext; - } - public get ruleIndex(): number { - return JackParser.RULE_statements; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterStatements) { - listener.enterStatements(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitStatements) { - listener.exitStatements(this); - } - } +export class StatementsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public statement(): StatementContext[]; + public statement(i: number): StatementContext | null; + public statement(i?: number): StatementContext[] | StatementContext | null { + if (i === undefined) { + return this.getRuleContexts(StatementContext); + } + + return this.getRuleContext(i, StatementContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_statements; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterStatements) { + listener.enterStatements(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitStatements) { + listener.exitStatements(this); + } + } } -export class StatementContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public letStatement(): LetStatementContext { - return this.getTypedRuleContext(LetStatementContext, 0) as LetStatementContext; - } - public ifElseStatement(): IfElseStatementContext { - return this.getTypedRuleContext(IfElseStatementContext, 0) as IfElseStatementContext; - } - public whileStatement(): WhileStatementContext { - return this.getTypedRuleContext(WhileStatementContext, 0) as WhileStatementContext; - } - public doStatement(): DoStatementContext { - return this.getTypedRuleContext(DoStatementContext, 0) as DoStatementContext; - } - public returnStatement(): ReturnStatementContext { - return this.getTypedRuleContext(ReturnStatementContext, 0) as ReturnStatementContext; - } - public get ruleIndex(): number { - return JackParser.RULE_statement; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterStatement) { - listener.enterStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitStatement) { - listener.exitStatement(this); - } - } +export class StatementContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public letStatement(): LetStatementContext | null { + return this.getRuleContext(0, LetStatementContext); + } + public ifElseStatement(): IfElseStatementContext | null { + return this.getRuleContext(0, IfElseStatementContext); + } + public whileStatement(): WhileStatementContext | null { + return this.getRuleContext(0, WhileStatementContext); + } + public doStatement(): DoStatementContext | null { + return this.getRuleContext(0, DoStatementContext); + } + public returnStatement(): ReturnStatementContext | null { + return this.getRuleContext(0, ReturnStatementContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_statement; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterStatement) { + listener.enterStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitStatement) { + listener.exitStatement(this); + } + } } -export class LetStatementContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public LET(): TerminalNode { - return this.getToken(JackParser.LET, 0); - } - public equals(): EqualsContext { - return this.getTypedRuleContext(EqualsContext, 0) as EqualsContext; - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public varName(): VarNameContext { - return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; - } - public arrayAccess(): ArrayAccessContext { - return this.getTypedRuleContext(ArrayAccessContext, 0) as ArrayAccessContext; - } - public get ruleIndex(): number { - return JackParser.RULE_letStatement; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterLetStatement) { - listener.enterLetStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitLetStatement) { - listener.exitLetStatement(this); - } - } +export class LetStatementContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public LET(): antlr.TerminalNode { + return this.getToken(JackParser.LET, 0)!; + } + public equals(): EqualsContext { + return this.getRuleContext(0, EqualsContext)!; + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public varName(): VarNameContext | null { + return this.getRuleContext(0, VarNameContext); + } + public arrayAccess(): ArrayAccessContext | null { + return this.getRuleContext(0, ArrayAccessContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_letStatement; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterLetStatement) { + listener.enterLetStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitLetStatement) { + listener.exitLetStatement(this); + } + } } -export class EqualsContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public EQUALS(): TerminalNode { - return this.getToken(JackParser.EQUALS, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_equals; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterEquals) { - listener.enterEquals(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitEquals) { - listener.exitEquals(this); - } - } +export class EqualsContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public EQUALS(): antlr.TerminalNode { + return this.getToken(JackParser.EQUALS, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_equals; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterEquals) { + listener.enterEquals(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitEquals) { + listener.exitEquals(this); + } + } } -export class IfElseStatementContext extends ParserRuleContext { - public endLabel: string = ""; - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public ifStatement(): IfStatementContext { - return this.getTypedRuleContext(IfStatementContext, 0) as IfStatementContext; - } - public elseStatement(): ElseStatementContext { - return this.getTypedRuleContext(ElseStatementContext, 0) as ElseStatementContext; - } - public get ruleIndex(): number { - return JackParser.RULE_ifElseStatement; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterIfElseStatement) { - listener.enterIfElseStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitIfElseStatement) { - listener.exitIfElseStatement(this); - } - } +export class IfElseStatementContext extends antlr.ParserRuleContext { + public endLabel: string = ""; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public ifStatement(): IfStatementContext { + return this.getRuleContext(0, IfStatementContext)!; + } + public elseStatement(): ElseStatementContext | null { + return this.getRuleContext(0, ElseStatementContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_ifElseStatement; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterIfElseStatement) { + listener.enterIfElseStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitIfElseStatement) { + listener.exitIfElseStatement(this); + } + } } -export class IfStatementContext extends ParserRuleContext { - public endLabel: string = ""; - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public IF(): TerminalNode { - return this.getToken(JackParser.IF, 0); - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public ifExpression(): IfExpressionContext { - return this.getTypedRuleContext(IfExpressionContext, 0) as IfExpressionContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public statements(): StatementsContext { - return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public get ruleIndex(): number { - return JackParser.RULE_ifStatement; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterIfStatement) { - listener.enterIfStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitIfStatement) { - listener.exitIfStatement(this); - } - } +export class IfStatementContext extends antlr.ParserRuleContext { + public endLabel: string = ""; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IF(): antlr.TerminalNode { + return this.getToken(JackParser.IF, 0)!; + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public ifExpression(): IfExpressionContext { + return this.getRuleContext(0, IfExpressionContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_ifStatement; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterIfStatement) { + listener.enterIfStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitIfStatement) { + listener.exitIfStatement(this); + } + } } -export class IfExpressionContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public get ruleIndex(): number { - return JackParser.RULE_ifExpression; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterIfExpression) { - listener.enterIfExpression(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitIfExpression) { - listener.exitIfExpression(this); - } - } +export class IfExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_ifExpression; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterIfExpression) { + listener.enterIfExpression(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitIfExpression) { + listener.exitIfExpression(this); + } + } } -export class ElseStatementContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public ELSE(): TerminalNode { - return this.getToken(JackParser.ELSE, 0); - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public statements(): StatementsContext { - return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public get ruleIndex(): number { - return JackParser.RULE_elseStatement; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterElseStatement) { - listener.enterElseStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitElseStatement) { - listener.exitElseStatement(this); - } - } +export class ElseStatementContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public ELSE(): antlr.TerminalNode { + return this.getToken(JackParser.ELSE, 0)!; + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_elseStatement; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterElseStatement) { + listener.enterElseStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitElseStatement) { + listener.exitElseStatement(this); + } + } } -export class WhileStatementContext extends ParserRuleContext { - public startLabel: string = "";endLabel:string="";; - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public WHILE(): TerminalNode { - return this.getToken(JackParser.WHILE, 0); - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public whileExpression(): WhileExpressionContext { - return this.getTypedRuleContext(WhileExpressionContext, 0) as WhileExpressionContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public LBRACE(): TerminalNode { - return this.getToken(JackParser.LBRACE, 0); - } - public statements(): StatementsContext { - return this.getTypedRuleContext(StatementsContext, 0) as StatementsContext; - } - public rBrace(): RBraceContext { - return this.getTypedRuleContext(RBraceContext, 0) as RBraceContext; - } - public get ruleIndex(): number { - return JackParser.RULE_whileStatement; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterWhileStatement) { - listener.enterWhileStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitWhileStatement) { - listener.exitWhileStatement(this); - } - } +export class WhileStatementContext extends antlr.ParserRuleContext { + public startLabel: string = "";endLabel:string="";; + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public WHILE(): antlr.TerminalNode { + return this.getToken(JackParser.WHILE, 0)!; + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public whileExpression(): WhileExpressionContext { + return this.getRuleContext(0, WhileExpressionContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_whileStatement; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterWhileStatement) { + listener.enterWhileStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitWhileStatement) { + listener.exitWhileStatement(this); + } + } } -export class WhileExpressionContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public get ruleIndex(): number { - return JackParser.RULE_whileExpression; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterWhileExpression) { - listener.enterWhileExpression(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitWhileExpression) { - listener.exitWhileExpression(this); - } - } +export class WhileExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_whileExpression; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterWhileExpression) { + listener.enterWhileExpression(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitWhileExpression) { + listener.exitWhileExpression(this); + } + } } -export class DoStatementContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public DO(): TerminalNode { - return this.getToken(JackParser.DO, 0); - } - public subroutineCall(): SubroutineCallContext { - return this.getTypedRuleContext(SubroutineCallContext, 0) as SubroutineCallContext; - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_doStatement; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterDoStatement) { - listener.enterDoStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitDoStatement) { - listener.exitDoStatement(this); - } - } +export class DoStatementContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public DO(): antlr.TerminalNode { + return this.getToken(JackParser.DO, 0)!; + } + public subroutineCall(): SubroutineCallContext { + return this.getRuleContext(0, SubroutineCallContext)!; + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_doStatement; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterDoStatement) { + listener.enterDoStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitDoStatement) { + listener.exitDoStatement(this); + } + } } -export class SubroutineCallContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public subroutineId(): SubroutineIdContext { - return this.getTypedRuleContext(SubroutineIdContext, 0) as SubroutineIdContext; - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public expressionList(): ExpressionListContext { - return this.getTypedRuleContext(ExpressionListContext, 0) as ExpressionListContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineCall; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineCall) { - listener.enterSubroutineCall(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineCall) { - listener.exitSubroutineCall(this); - } - } +export class SubroutineCallContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public subroutineId(): SubroutineIdContext { + return this.getRuleContext(0, SubroutineIdContext)!; + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public expressionList(): ExpressionListContext { + return this.getRuleContext(0, ExpressionListContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineCall; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineCall) { + listener.enterSubroutineCall(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineCall) { + listener.exitSubroutineCall(this); + } + } } -export class SubroutineIdContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public subroutineName(): SubroutineNameContext { - return this.getTypedRuleContext(SubroutineNameContext, 0) as SubroutineNameContext; - } - public DOT(): TerminalNode { - return this.getToken(JackParser.DOT, 0); - } - public className(): ClassNameContext { - return this.getTypedRuleContext(ClassNameContext, 0) as ClassNameContext; - } - public THIS_LITERAL(): TerminalNode { - return this.getToken(JackParser.THIS_LITERAL, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_subroutineId; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineId) { - listener.enterSubroutineId(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineId) { - listener.exitSubroutineId(this); - } - } +export class SubroutineIdContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public subroutineName(): SubroutineNameContext { + return this.getRuleContext(0, SubroutineNameContext)!; + } + public DOT(): antlr.TerminalNode | null { + return this.getToken(JackParser.DOT, 0); + } + public className(): ClassNameContext | null { + return this.getRuleContext(0, ClassNameContext); + } + public THIS_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.THIS_LITERAL, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineId; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterSubroutineId) { + listener.enterSubroutineId(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitSubroutineId) { + listener.exitSubroutineId(this); + } + } } -export class ReturnStatementContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public RETURN(): TerminalNode { - return this.getToken(JackParser.RETURN, 0); - } - public SEMICOLON(): TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0); - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public get ruleIndex(): number { - return JackParser.RULE_returnStatement; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterReturnStatement) { - listener.enterReturnStatement(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitReturnStatement) { - listener.exitReturnStatement(this); - } - } +export class ReturnStatementContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public RETURN(): antlr.TerminalNode { + return this.getToken(JackParser.RETURN, 0)!; + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public expression(): ExpressionContext | null { + return this.getRuleContext(0, ExpressionContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_returnStatement; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterReturnStatement) { + listener.enterReturnStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitReturnStatement) { + listener.exitReturnStatement(this); + } + } } -export class ExpressionListContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public expression_list(): ExpressionContext[] { - return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; - } - public expression(i: number): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(JackParser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(JackParser.COMMA, i); - } - public get ruleIndex(): number { - return JackParser.RULE_expressionList; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterExpressionList) { - listener.enterExpressionList(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitExpressionList) { - listener.exitExpressionList(this); - } - } +export class ExpressionListContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public expression(): ExpressionContext[]; + public expression(i: number): ExpressionContext | null; + public expression(i?: number): ExpressionContext[] | ExpressionContext | null { + if (i === undefined) { + return this.getRuleContexts(ExpressionContext); + } + + return this.getRuleContext(i, ExpressionContext); + } + public COMMA(): antlr.TerminalNode[]; + public COMMA(i: number): antlr.TerminalNode | null; + public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public override get ruleIndex(): number { + return JackParser.RULE_expressionList; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterExpressionList) { + listener.enterExpressionList(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitExpressionList) { + listener.exitExpressionList(this); + } + } } -export class ExpressionContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public constant(): ConstantContext { - return this.getTypedRuleContext(ConstantContext, 0) as ConstantContext; - } - public varName(): VarNameContext { - return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; - } - public subroutineCall(): SubroutineCallContext { - return this.getTypedRuleContext(SubroutineCallContext, 0) as SubroutineCallContext; - } - public arrayAccess(): ArrayAccessContext { - return this.getTypedRuleContext(ArrayAccessContext, 0) as ArrayAccessContext; - } - public unaryOperation(): UnaryOperationContext { - return this.getTypedRuleContext(UnaryOperationContext, 0) as UnaryOperationContext; - } - public groupedExpression(): GroupedExpressionContext { - return this.getTypedRuleContext(GroupedExpressionContext, 0) as GroupedExpressionContext; - } - public expression_list(): ExpressionContext[] { - return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; - } - public expression(i: number): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; - } - public binaryOperator(): BinaryOperatorContext { - return this.getTypedRuleContext(BinaryOperatorContext, 0) as BinaryOperatorContext; - } - public get ruleIndex(): number { - return JackParser.RULE_expression; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterExpression) { - listener.enterExpression(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitExpression) { - listener.exitExpression(this); - } - } +export class ExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public constant(): ConstantContext | null { + return this.getRuleContext(0, ConstantContext); + } + public varName(): VarNameContext | null { + return this.getRuleContext(0, VarNameContext); + } + public subroutineCall(): SubroutineCallContext | null { + return this.getRuleContext(0, SubroutineCallContext); + } + public arrayAccess(): ArrayAccessContext | null { + return this.getRuleContext(0, ArrayAccessContext); + } + public unaryOperation(): UnaryOperationContext | null { + return this.getRuleContext(0, UnaryOperationContext); + } + public groupedExpression(): GroupedExpressionContext | null { + return this.getRuleContext(0, GroupedExpressionContext); + } + public expression(): ExpressionContext[]; + public expression(i: number): ExpressionContext | null; + public expression(i?: number): ExpressionContext[] | ExpressionContext | null { + if (i === undefined) { + return this.getRuleContexts(ExpressionContext); + } + + return this.getRuleContext(i, ExpressionContext); + } + public binaryOperator(): BinaryOperatorContext | null { + return this.getRuleContext(0, BinaryOperatorContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_expression; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterExpression) { + listener.enterExpression(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitExpression) { + listener.exitExpression(this); + } + } } -export class ConstantContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public INTEGER_LITERAL(): TerminalNode { - return this.getToken(JackParser.INTEGER_LITERAL, 0); - } - public STRING_LITERAL(): TerminalNode { - return this.getToken(JackParser.STRING_LITERAL, 0); - } - public booleanLiteral(): BooleanLiteralContext { - return this.getTypedRuleContext(BooleanLiteralContext, 0) as BooleanLiteralContext; - } - public NULL_LITERAL(): TerminalNode { - return this.getToken(JackParser.NULL_LITERAL, 0); - } - public THIS_LITERAL(): TerminalNode { - return this.getToken(JackParser.THIS_LITERAL, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_constant; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterConstant) { - listener.enterConstant(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitConstant) { - listener.exitConstant(this); - } - } +export class ConstantContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public INTEGER_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.INTEGER_LITERAL, 0); + } + public STRING_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.STRING_LITERAL, 0); + } + public booleanLiteral(): BooleanLiteralContext | null { + return this.getRuleContext(0, BooleanLiteralContext); + } + public NULL_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.NULL_LITERAL, 0); + } + public THIS_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.THIS_LITERAL, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_constant; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterConstant) { + listener.enterConstant(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitConstant) { + listener.exitConstant(this); + } + } } -export class VarNameContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public IDENTIFIER(): TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_varName; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterVarName) { - listener.enterVarName(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitVarName) { - listener.exitVarName(this); - } - } +export class VarNameContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_varName; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterVarName) { + listener.enterVarName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitVarName) { + listener.exitVarName(this); + } + } } -export class ArrayAccessContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public varName(): VarNameContext { - return this.getTypedRuleContext(VarNameContext, 0) as VarNameContext; - } - public LBRACKET(): TerminalNode { - return this.getToken(JackParser.LBRACKET, 0); - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public RBRACKET(): TerminalNode { - return this.getToken(JackParser.RBRACKET, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_arrayAccess; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterArrayAccess) { - listener.enterArrayAccess(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitArrayAccess) { - listener.exitArrayAccess(this); - } - } +export class ArrayAccessContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public varName(): VarNameContext { + return this.getRuleContext(0, VarNameContext)!; + } + public LBRACKET(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACKET, 0)!; + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public RBRACKET(): antlr.TerminalNode { + return this.getToken(JackParser.RBRACKET, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_arrayAccess; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterArrayAccess) { + listener.enterArrayAccess(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitArrayAccess) { + listener.exitArrayAccess(this); + } + } } -export class UnaryOperationContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public unaryOperator(): UnaryOperatorContext { - return this.getTypedRuleContext(UnaryOperatorContext, 0) as UnaryOperatorContext; - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public get ruleIndex(): number { - return JackParser.RULE_unaryOperation; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterUnaryOperation) { - listener.enterUnaryOperation(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitUnaryOperation) { - listener.exitUnaryOperation(this); - } - } +export class UnaryOperationContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public unaryOperator(): UnaryOperatorContext { + return this.getRuleContext(0, UnaryOperatorContext)!; + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_unaryOperation; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterUnaryOperation) { + listener.enterUnaryOperation(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitUnaryOperation) { + listener.exitUnaryOperation(this); + } + } } -export class GroupedExpressionContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public LPAREN(): TerminalNode { - return this.getToken(JackParser.LPAREN, 0); - } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; - } - public RPAREN(): TerminalNode { - return this.getToken(JackParser.RPAREN, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_groupedExpression; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterGroupedExpression) { - listener.enterGroupedExpression(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitGroupedExpression) { - listener.exitGroupedExpression(this); - } - } +export class GroupedExpressionContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_groupedExpression; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterGroupedExpression) { + listener.enterGroupedExpression(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitGroupedExpression) { + listener.exitGroupedExpression(this); + } + } } -export class BooleanLiteralContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public TRUE(): TerminalNode { - return this.getToken(JackParser.TRUE, 0); - } - public FALSE(): TerminalNode { - return this.getToken(JackParser.FALSE, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_booleanLiteral; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterBooleanLiteral) { - listener.enterBooleanLiteral(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitBooleanLiteral) { - listener.exitBooleanLiteral(this); - } - } +export class BooleanLiteralContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public TRUE(): antlr.TerminalNode | null { + return this.getToken(JackParser.TRUE, 0); + } + public FALSE(): antlr.TerminalNode | null { + return this.getToken(JackParser.FALSE, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_booleanLiteral; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterBooleanLiteral) { + listener.enterBooleanLiteral(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitBooleanLiteral) { + listener.exitBooleanLiteral(this); + } + } } -export class UnaryOperatorContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public TILDE(): TerminalNode { - return this.getToken(JackParser.TILDE, 0); - } - public MINUS(): TerminalNode { - return this.getToken(JackParser.MINUS, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_unaryOperator; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterUnaryOperator) { - listener.enterUnaryOperator(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitUnaryOperator) { - listener.exitUnaryOperator(this); - } - } +export class UnaryOperatorContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public TILDE(): antlr.TerminalNode | null { + return this.getToken(JackParser.TILDE, 0); + } + public MINUS(): antlr.TerminalNode | null { + return this.getToken(JackParser.MINUS, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_unaryOperator; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterUnaryOperator) { + listener.enterUnaryOperator(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitUnaryOperator) { + listener.exitUnaryOperator(this); + } + } } -export class BinaryOperatorContext extends ParserRuleContext { - constructor(parser?: JackParser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public PLUS(): TerminalNode { - return this.getToken(JackParser.PLUS, 0); - } - public MINUS(): TerminalNode { - return this.getToken(JackParser.MINUS, 0); - } - public MUL(): TerminalNode { - return this.getToken(JackParser.MUL, 0); - } - public DIV(): TerminalNode { - return this.getToken(JackParser.DIV, 0); - } - public AND(): TerminalNode { - return this.getToken(JackParser.AND, 0); - } - public OR(): TerminalNode { - return this.getToken(JackParser.OR, 0); - } - public LESS_THAN(): TerminalNode { - return this.getToken(JackParser.LESS_THAN, 0); - } - public GREATER_THAN(): TerminalNode { - return this.getToken(JackParser.GREATER_THAN, 0); - } - public EQUALS(): TerminalNode { - return this.getToken(JackParser.EQUALS, 0); - } - public get ruleIndex(): number { - return JackParser.RULE_binaryOperator; - } - public enterRule(listener: JackParserListener): void { - if(listener.enterBinaryOperator) { - listener.enterBinaryOperator(this); - } - } - public exitRule(listener: JackParserListener): void { - if(listener.exitBinaryOperator) { - listener.exitBinaryOperator(this); - } - } +export class BinaryOperatorContext extends antlr.ParserRuleContext { + public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { + super(parent, invokingState); + } + public PLUS(): antlr.TerminalNode | null { + return this.getToken(JackParser.PLUS, 0); + } + public MINUS(): antlr.TerminalNode | null { + return this.getToken(JackParser.MINUS, 0); + } + public MUL(): antlr.TerminalNode | null { + return this.getToken(JackParser.MUL, 0); + } + public DIV(): antlr.TerminalNode | null { + return this.getToken(JackParser.DIV, 0); + } + public AND(): antlr.TerminalNode | null { + return this.getToken(JackParser.AND, 0); + } + public OR(): antlr.TerminalNode | null { + return this.getToken(JackParser.OR, 0); + } + public LESS_THAN(): antlr.TerminalNode | null { + return this.getToken(JackParser.LESS_THAN, 0); + } + public GREATER_THAN(): antlr.TerminalNode | null { + return this.getToken(JackParser.GREATER_THAN, 0); + } + public EQUALS(): antlr.TerminalNode | null { + return this.getToken(JackParser.EQUALS, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_binaryOperator; + } + public override enterRule(listener: JackParserListener): void { + if(listener.enterBinaryOperator) { + listener.enterBinaryOperator(this); + } + } + public override exitRule(listener: JackParserListener): void { + if(listener.exitBinaryOperator) { + listener.exitBinaryOperator(this); + } + } } diff --git a/simulator/src/jack/generated/JackParserListener.ts b/simulator/src/jack/generated/JackParserListener.ts index 754b2077..88885ae0 100644 --- a/simulator/src/jack/generated/JackParserListener.ts +++ b/simulator/src/jack/generated/JackParserListener.ts @@ -1,6 +1,6 @@ -// Generated from JackParser.g4 by ANTLR 4.13.2 +// Generated from JackParser.g4 by ANTLR 4.13.1 -import {ParseTreeListener} from "antlr4"; +import { ErrorNode, ParseTreeListener, ParserRuleContext, TerminalNode } from "antlr4ng"; import { SubroutineScope, LocalSymbolTable } from "../symbol"; @@ -55,436 +55,441 @@ import { BinaryOperatorContext } from "./JackParser.js"; * This interface defines a complete listener for a parse tree produced by * `JackParser`. */ -export default class JackParserListener extends ParseTreeListener { - /** - * Enter a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - */ - enterProgram?: (ctx: ProgramContext) => void; - /** - * Exit a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - */ - exitProgram?: (ctx: ProgramContext) => void; - /** - * Enter a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - */ - enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - */ - exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - */ - enterClassName?: (ctx: ClassNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - */ - exitClassName?: (ctx: ClassNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - */ - enterClassVarDec?: (ctx: ClassVarDecContext) => void; - /** - * Exit a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - */ - exitClassVarDec?: (ctx: ClassVarDecContext) => void; - /** - * Enter a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - */ - enterFieldList?: (ctx: FieldListContext) => void; - /** - * Exit a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - */ - exitFieldList?: (ctx: FieldListContext) => void; - /** - * Enter a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - */ - enterFieldName?: (ctx: FieldNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - */ - exitFieldName?: (ctx: FieldNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - */ - enterSubroutineType?: (ctx: SubroutineTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - */ - exitSubroutineType?: (ctx: SubroutineTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - */ - enterSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - */ - exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - */ - enterSubroutineName?: (ctx: SubroutineNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - */ - exitSubroutineName?: (ctx: SubroutineNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - */ - enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - */ - exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - */ - enterVarType?: (ctx: VarTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - */ - exitVarType?: (ctx: VarTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - */ - enterParameterList?: (ctx: ParameterListContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - */ - exitParameterList?: (ctx: ParameterListContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - */ - enterParameter?: (ctx: ParameterContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - */ - exitParameter?: (ctx: ParameterContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - */ - enterParameterName?: (ctx: ParameterNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - */ - exitParameterName?: (ctx: ParameterNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - */ - enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - */ - exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; - /** - * Enter a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - */ - enterRBrace?: (ctx: RBraceContext) => void; - /** - * Exit a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - */ - exitRBrace?: (ctx: RBraceContext) => void; - /** - * Enter a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - */ - enterVarDeclaration?: (ctx: VarDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - */ - exitVarDeclaration?: (ctx: VarDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - */ - enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - */ - exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - */ - enterStatements?: (ctx: StatementsContext) => void; - /** - * Exit a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - */ - exitStatements?: (ctx: StatementsContext) => void; - /** - * Enter a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - */ - enterStatement?: (ctx: StatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - */ - exitStatement?: (ctx: StatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - */ - enterLetStatement?: (ctx: LetStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - */ - exitLetStatement?: (ctx: LetStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.equals`. - * @param ctx the parse tree - */ - enterEquals?: (ctx: EqualsContext) => void; - /** - * Exit a parse tree produced by `JackParser.equals`. - * @param ctx the parse tree - */ - exitEquals?: (ctx: EqualsContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - */ - enterIfElseStatement?: (ctx: IfElseStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - */ - exitIfElseStatement?: (ctx: IfElseStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - */ - enterIfStatement?: (ctx: IfStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - */ - exitIfStatement?: (ctx: IfStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifExpression`. - * @param ctx the parse tree - */ - enterIfExpression?: (ctx: IfExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifExpression`. - * @param ctx the parse tree - */ - exitIfExpression?: (ctx: IfExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - */ - enterElseStatement?: (ctx: ElseStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - */ - exitElseStatement?: (ctx: ElseStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - */ - enterWhileStatement?: (ctx: WhileStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - */ - exitWhileStatement?: (ctx: WhileStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.whileExpression`. - * @param ctx the parse tree - */ - enterWhileExpression?: (ctx: WhileExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.whileExpression`. - * @param ctx the parse tree - */ - exitWhileExpression?: (ctx: WhileExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - */ - enterDoStatement?: (ctx: DoStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - */ - exitDoStatement?: (ctx: DoStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - */ - enterSubroutineCall?: (ctx: SubroutineCallContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - */ - exitSubroutineCall?: (ctx: SubroutineCallContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - */ - enterSubroutineId?: (ctx: SubroutineIdContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - */ - exitSubroutineId?: (ctx: SubroutineIdContext) => void; - /** - * Enter a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - */ - enterReturnStatement?: (ctx: ReturnStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - */ - exitReturnStatement?: (ctx: ReturnStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - */ - enterExpressionList?: (ctx: ExpressionListContext) => void; - /** - * Exit a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - */ - exitExpressionList?: (ctx: ExpressionListContext) => void; - /** - * Enter a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - */ - enterExpression?: (ctx: ExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - */ - exitExpression?: (ctx: ExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - */ - enterConstant?: (ctx: ConstantContext) => void; - /** - * Exit a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - */ - exitConstant?: (ctx: ConstantContext) => void; - /** - * Enter a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - */ - enterVarName?: (ctx: VarNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - */ - exitVarName?: (ctx: VarNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - */ - enterArrayAccess?: (ctx: ArrayAccessContext) => void; - /** - * Exit a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - */ - exitArrayAccess?: (ctx: ArrayAccessContext) => void; - /** - * Enter a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - */ - enterUnaryOperation?: (ctx: UnaryOperationContext) => void; - /** - * Exit a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - */ - exitUnaryOperation?: (ctx: UnaryOperationContext) => void; - /** - * Enter a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - */ - enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - */ - exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.booleanLiteral`. - * @param ctx the parse tree - */ - enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; - /** - * Exit a parse tree produced by `JackParser.booleanLiteral`. - * @param ctx the parse tree - */ - exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; - /** - * Enter a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - */ - enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; - /** - * Exit a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - */ - exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; - /** - * Enter a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - */ - enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; - /** - * Exit a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - */ - exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; +export class JackParserListener implements ParseTreeListener { + /** + * Enter a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + enterProgram?: (ctx: ProgramContext) => void; + /** + * Exit a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + exitProgram?: (ctx: ProgramContext) => void; + /** + * Enter a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + enterClassName?: (ctx: ClassNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + exitClassName?: (ctx: ClassNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + enterClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Exit a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + exitClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Enter a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + enterFieldList?: (ctx: FieldListContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + exitFieldList?: (ctx: FieldListContext) => void; + /** + * Enter a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + enterFieldName?: (ctx: FieldNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + exitFieldName?: (ctx: FieldNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineDeclaration`. + * @param ctx the parse tree + */ + enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDeclaration`. + * @param ctx the parse tree + */ + exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + enterSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + exitSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + enterSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + enterSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + exitSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + enterVarType?: (ctx: VarTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + exitVarType?: (ctx: VarTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + enterParameterList?: (ctx: ParameterListContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + exitParameterList?: (ctx: ParameterListContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + enterParameter?: (ctx: ParameterContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + exitParameter?: (ctx: ParameterContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + enterParameterName?: (ctx: ParameterNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + exitParameterName?: (ctx: ParameterNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Enter a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + enterRBrace?: (ctx: RBraceContext) => void; + /** + * Exit a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + exitRBrace?: (ctx: RBraceContext) => void; + /** + * Enter a parse tree produced by `JackParser.varDeclaration`. + * @param ctx the parse tree + */ + enterVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varDeclaration`. + * @param ctx the parse tree + */ + exitVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + enterStatements?: (ctx: StatementsContext) => void; + /** + * Exit a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + exitStatements?: (ctx: StatementsContext) => void; + /** + * Enter a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + enterStatement?: (ctx: StatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + exitStatement?: (ctx: StatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + enterLetStatement?: (ctx: LetStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + exitLetStatement?: (ctx: LetStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.equals`. + * @param ctx the parse tree + */ + enterEquals?: (ctx: EqualsContext) => void; + /** + * Exit a parse tree produced by `JackParser.equals`. + * @param ctx the parse tree + */ + exitEquals?: (ctx: EqualsContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + enterIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + exitIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + enterIfStatement?: (ctx: IfStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + exitIfStatement?: (ctx: IfStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifExpression`. + * @param ctx the parse tree + */ + enterIfExpression?: (ctx: IfExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifExpression`. + * @param ctx the parse tree + */ + exitIfExpression?: (ctx: IfExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + enterElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + exitElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + enterWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + exitWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.whileExpression`. + * @param ctx the parse tree + */ + enterWhileExpression?: (ctx: WhileExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileExpression`. + * @param ctx the parse tree + */ + exitWhileExpression?: (ctx: WhileExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + enterDoStatement?: (ctx: DoStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + exitDoStatement?: (ctx: DoStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + enterSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + exitSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + enterSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + exitSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Enter a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + enterReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + exitReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + enterExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Exit a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + exitExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Enter a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + enterExpression?: (ctx: ExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + exitExpression?: (ctx: ExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + enterConstant?: (ctx: ConstantContext) => void; + /** + * Exit a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + exitConstant?: (ctx: ConstantContext) => void; + /** + * Enter a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + enterVarName?: (ctx: VarNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + exitVarName?: (ctx: VarNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + enterArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Exit a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + exitArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Enter a parse tree produced by `JackParser.unaryOperation`. + * @param ctx the parse tree + */ + enterUnaryOperation?: (ctx: UnaryOperationContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperation`. + * @param ctx the parse tree + */ + exitUnaryOperation?: (ctx: UnaryOperationContext) => void; + /** + * Enter a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.booleanLiteral`. + * @param ctx the parse tree + */ + enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Exit a parse tree produced by `JackParser.booleanLiteral`. + * @param ctx the parse tree + */ + exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Enter a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Enter a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; + + visitTerminal(node: TerminalNode): void {} + visitErrorNode(node: ErrorNode): void {} + enterEveryRule(node: ParserRuleContext): void {} + exitEveryRule(node: ParserRuleContext): void {} } diff --git a/simulator/src/jack/listener/common.ts b/simulator/src/jack/listener/common.ts index dd472da6..8063468f 100644 --- a/simulator/src/jack/listener/common.ts +++ b/simulator/src/jack/listener/common.ts @@ -1,5 +1,5 @@ -import { SubroutineIdContext } from "../generated/JackParser.js"; -import { LocalSymbolTable, VariableSymbol } from "../symbol.js"; +import { SubroutineIdContext } from "../generated/JackParser"; +import { LocalSymbolTable, VariableSymbol } from "../symbol"; export interface CallTypeResult { callType: CallType; @@ -15,14 +15,14 @@ export enum CallType { export function getCallType( subroutineId: SubroutineIdContext, className: string, - localSymbolTable: LocalSymbolTable, + localSymbolTable: LocalSymbolTable ): CallTypeResult { if (subroutineId.DOT() == undefined) { //local method return { callType: CallType.LocalMethod, subroutineIdText: - className + "." + subroutineId.subroutineName().getText(), + className + "." + (subroutineId.subroutineName()?.getText() ?? ""), } as CallTypeResult; } else { // var method @@ -43,3 +43,13 @@ export function getCallType( } } } + +export function assertExists( + val: T | undefined | null, + message?: string +): T { + if (val == null) { + throw new Error(message ?? "Cannot be null or undefined"); + } + return val; +} diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 1dbaa86e..dfdf603d 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -1,51 +1,85 @@ import { - ErrorListener, + ANTLRErrorListener, + ATNConfigSet, + ATNSimulator, + BitSet, + DFA, + LexerNoViableAltException, NoViableAltException, + Parser, RecognitionException, Recognizer, Token, -} from "antlr4"; -import { asSpan, JackCompilerError, LexerOrParserError } from "../error.js"; -import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; -interface LexerNoViableAltException { - startIndex: number; -} -export class JackCustomErrorListener extends ErrorListener { - public errors: JackCompilerError[] = []; +} from "antlr4ng"; +import { + JackCompilerError, + LexerOrParserError +} from "../error"; +import { assertExists } from "./common"; - override syntaxError = ( - recognizer: Recognizer, - offendingSymbol: any, +export class CustomErrorListener implements ANTLRErrorListener { + public errors: JackCompilerError[] = []; + syntaxError( + _recognizer: Recognizer, + offendingSymbol: S | null, line: number, - column: number, + _charPositionInLine: number, msg: string, - err: RecognitionException | undefined - ) => { - if (offendingSymbol != null || err?.offendingToken) { - const t = offendingSymbol ?? (assertExists(err).offendingToken as Token); + e: RecognitionException | null + ): void { + if (offendingSymbol != null || (e != null && e.offendingToken != null)) { + const t = offendingSymbol ?? (e?.offendingToken as Token); this.errors.push( - LexerOrParserError({ line, start: t.start, end: t.stop + 1 }, msg) + LexerOrParserError({ line: line, start: t.start, end: t.stop + 1 }, msg) + ); + } else if (e instanceof NoViableAltException) { + //theoretically we can't get this exception + const token = assertExists( + e.startToken ?? e.offendingToken, + "Cant find start token for NoViableAltException" ); - } else if (err instanceof NoViableAltException) { - //TODO: RL change and fix - this.errors.push(LexerOrParserError(asSpan(err.startToken), msg)); - } - //antlr doesn't provide a class for LexerNoViableAltException atm. Once https://github.com/antlr/antlr4/pull/4711 is release we can change it - else if (err != null && "startIndex" in err) { - const startIndex = err.startIndex as number; this.errors.push( LexerOrParserError( - { - line, - start: startIndex, - end: startIndex + 1, - }, + { line: token.line, start: token.start, end: token.stop }, + msg + ) + ); + } else if (e instanceof LexerNoViableAltException) { + this.errors.push( + LexerOrParserError( + { line: line, start: e.startIndex, end: e.startIndex + 1 }, msg ) ); } else { console.error("Don't know how to handle this error"); - throw new Error("Don't know how to handle this error"); + throw new Error("Don't know how to handle this error "); } - }; + } + + reportAmbiguity( + _recognizer: Parser, + _dfa: DFA, + _startIndex: number, + _stopIndex: number, + _exact: boolean, + _ambigAlts: BitSet | undefined, + _configs: ATNConfigSet + ): void {} + reportAttemptingFullContext( + _recognizer: Parser, + _dfa: DFA, + _startIndex: number, + _stopIndex: number, + _conflictingAlts: BitSet | undefined, + _configs: ATNConfigSet + ): void {} + reportContextSensitivity( + _recognizer: Parser, + _dfa: DFA, + _startIndex: number, + _stopIndex: number, + _prediction: number, + _configs: ATNConfigSet + ): void {} } diff --git a/simulator/src/jack/listener/global.symbol.table.listener.ts b/simulator/src/jack/listener/global.symbol.listener.ts similarity index 63% rename from simulator/src/jack/listener/global.symbol.table.listener.ts rename to simulator/src/jack/listener/global.symbol.listener.ts index e410ce2d..1f0d000d 100644 --- a/simulator/src/jack/listener/global.symbol.table.listener.ts +++ b/simulator/src/jack/listener/global.symbol.listener.ts @@ -1,30 +1,22 @@ import { ClassDeclarationContext, - SubroutineBodyContext, SubroutineDeclarationContext, VarNameInDeclarationContext, -} from "../generated/JackParser.js"; -import { - asSpan, - DuplicatedClassError, - DuplicatedSubroutineError, - JackCompilerError, -} from "../error.js"; -import { builtInSymbols, builtInTypes } from "../builtins.js"; +} from "../generated/JackParser"; +import { ruleContextToSpan, DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error"; import { GenericSymbol, GlobalSymbolTable, SubroutineInfo, SubroutineType, -} from "../symbol.js"; -import JackParserListener from "../generated/JackParserListener.js"; +} from "../symbol"; +import { builtInSymbols } from "../builtins"; +import { JackParserListener } from "../generated/JackParserListener"; -const primitives = new Set(builtInTypes); -export type Primitive = typeof primitives extends Set ? S : never; /** * Creates global symbol table that contains built-in functions and found classes and subroutines */ -export class JackGlobalSymbolTableListener extends JackParserListener { +export class GlobalSymbolTableListener extends JackParserListener { // key can be class or . public globalSymbolTable: GlobalSymbolTable = structuredClone(builtInSymbols); public className = ""; @@ -33,18 +25,32 @@ export class JackGlobalSymbolTableListener extends JackParserListener { private subroutineVarsCount = 0; private stopProcessingSubroutines = false; private subroutineId = ""; - + public filename = ""; override enterClassDeclaration = (ctx: ClassDeclarationContext) => { const classNameCtx = ctx.className(); const id = classNameCtx.IDENTIFIER(); const className = id.getText(); if (this.globalSymbolTable[className] != undefined) { - //TODO: RL check on UI - const e = DuplicatedClassError(asSpan(id.symbol, id.symbol), className); + if (classNameCtx.stop == null || classNameCtx.stop?.stop == null) + throw new Error("Stop token should not be null"); + if (classNameCtx.start == null) { + throw new Error("Start token should not be null"); + } + const e = DuplicatedClassError( + ruleContextToSpan(classNameCtx), + className + ); this.errors.push(e); return; } - this.globalSymbolTable[className] = {} as GenericSymbol; + this.globalSymbolTable[className] = { + filename: this.filename, + start: { line: id.symbol.line, character: id.symbol.column }, + end: { + line: id.symbol.line, + character: id.symbol.column + id.getText().length, + }, + } as GenericSymbol; this.className = className; }; @@ -64,35 +70,34 @@ export class JackGlobalSymbolTableListener extends JackParserListener { const subroutineName = nameCtx.IDENTIFIER().getText(); const id = this.className + "." + subroutineName; if (this.globalSymbolTable[id] != undefined) { + if (nameCtx.start == null) { + throw new Error("Start token should not be null"); + } this.errors.push( - DuplicatedSubroutineError( - { - line: nameCtx.IDENTIFIER().symbol.line, - start: nameCtx.start.start, - end: nameCtx.start.stop, - }, + DuplicatedSubroutineError( + ruleContextToSpan(nameCtx), subroutineName ) ); this.stopProcessingSubroutines = true; } else { this.subroutineId = id; - const paramsCount = subroutineWithoutTypeCtx + const params = subroutineWithoutTypeCtx .parameterList() - .parameter_list().length; + .parameter() this.subRoutineInfo = { type: subroutineType, - paramsCount: paramsCount, + paramsCount: params.length, }; this.subroutineVarsCount = 0; this.stopProcessingSubroutines = false; } }; - override enterVarNameInDeclaration = (ctx: VarNameInDeclarationContext) => { + override enterVarNameInDeclaration = (_ctx: VarNameInDeclarationContext) => { if (this.stopProcessingSubroutines) return; this.subroutineVarsCount++; }; - override exitSubroutineBody = (ctx: SubroutineBodyContext) => { + override exitSubroutineDeclaration = (_ctx: SubroutineDeclarationContext) => { if (this.stopProcessingSubroutines) return; this.subRoutineInfo.localVarsCount = this.subroutineVarsCount; this.globalSymbolTable[this.subroutineId] = { diff --git a/simulator/src/jack/listener/global.symbol.table.listener.test.ts b/simulator/src/jack/listener/global.symbol.table.listener.test.ts deleted file mode 100644 index 78916f8e..00000000 --- a/simulator/src/jack/listener/global.symbol.table.listener.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; -import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; -import path from "path"; -import { builtInSymbols } from "../builtins"; -import { - JackCompilerErrorType -} from "../error"; -import { createSubroutineSymbol, SubroutineType } from "../symbol"; -import { - getTestResourcePath, - listenToTheTree, - parseJackFile, - parseJackText, -} from "../test.helper"; -import { JackGlobalSymbolTableListener } from "./global.symbol.table.listener"; - -describe("Jack global symbol table listener", () => { - const jestConsole = console; - let fs: FileSystem; - beforeEach(() => { - global.console = require("console"); - fs = new FileSystem(new NodeFileSystemAdapter()); - }); - - afterEach(() => { - global.console = jestConsole; - }); - - test("should fail on duplicated subroutine", () => { - const input = ` - class A { - function void f(){ - return; - } - function int f(){ - return 1; - } - }`; - testJackGlobalSymbolListener(input, "DuplicatedSubroutineError"); - }); - - test("duplicated class", () => { - const input = ` - class A { - }`; - const globalSymbolTableListener = new JackGlobalSymbolTableListener(); - testJackGlobalSymbolListener(input, undefined, globalSymbolTableListener); - testJackGlobalSymbolListener(input, "DuplicatedClassError", globalSymbolTableListener); - }); - test("duplicated built in class", () => { - const input = ` - class Math { - }`; - testJackGlobalSymbolListener(input, "DuplicatedClassError"); - }); - test("basic", async () => { - const expected = { - ...builtInSymbols, - Fraction: {}, - "Fraction.new": createSubroutineSymbol(2, SubroutineType.Constructor, 0), - "Fraction.reduce": createSubroutineSymbol(0, SubroutineType.Method, 1), - "Fraction.getNumerator": createSubroutineSymbol( - 0, - SubroutineType.Method, - 0 - ), - "Fraction.getDenominator": createSubroutineSymbol( - 0, - SubroutineType.Method, - 0 - ), - "Fraction.plus": createSubroutineSymbol(1, SubroutineType.Method, 1), - "Fraction.dispose": createSubroutineSymbol(0, SubroutineType.Method, 0), - "Fraction.print": createSubroutineSymbol(0, SubroutineType.Method, 0), - "Fraction.gcd": createSubroutineSymbol(2, SubroutineType.Function, 1), - Main: {}, - "Main.main": createSubroutineSymbol(0, SubroutineType.Function, 3), - }; - let globalSymbolsListener = new JackGlobalSymbolTableListener(); - - const testFolder = getTestResourcePath("Fraction"); - - const filteredFiles = [...(await fs.readdir(testFolder))] - .filter((file) => file.endsWith(".jack")) - .map((file) => path.join(testFolder, file)); - for (const filePath of filteredFiles) { - const tree = parseJackFile(filePath); - globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); - } - expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); - }); -}); -function testJackGlobalSymbolListener( - input: string, - expectedError?: T, - globalSymbolTableListener = new JackGlobalSymbolTableListener() -) { - const tree = parseJackText(input); - listenToTheTree(tree, globalSymbolTableListener); - const errors = globalSymbolTableListener.errors; - if (expectedError) { - if (errors.length > 1) { - console.error("Errors", errors); - } - try { - expect(globalSymbolTableListener.errors.length).toBe(1); - expect(globalSymbolTableListener.errors[0].type).toBe(expectedError); - } catch (e) { - throw new Error( - `Expected error ${expectedError} but got '` + - JSON.stringify(globalSymbolTableListener.errors) + - "'" - ); - } - } else { - if (errors.length != 0) - throw new Error("Didn't expect any errors but got " + errors.join("\n")); - } -} diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts deleted file mode 100644 index 08b537c1..00000000 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ /dev/null @@ -1,824 +0,0 @@ -import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; -import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; -import { JackCustomErrorListener } from "./error.listener"; -import { JackValidatorListener } from "./validator.listener"; -import { - createSubroutineSymbol, - GenericSymbol, - SubroutineType, -} from "../symbol"; -import { - getTestResourcePath, - listenToTheTree, - parseJackFile, - parseJackText, - testResourceDirs, -} from "../test.helper"; -import { JackGlobalSymbolTableListener } from "./global.symbol.table.listener"; -import path from "path"; -import { ProgramContext } from "../generated/JackParser"; -import { JackCompilerErrorType } from "../error"; -describe("Jack validator listener", () => { - const jestConsole = console; - let fs: FileSystem; - beforeEach(() => { - global.console = require("console"); - fs = new FileSystem(new NodeFileSystemAdapter()); - }); - - afterEach(() => { - global.console = jestConsole; - }); - - function genericSymbol( - type?: SubroutineType, - paramsCount?: number, - ): GenericSymbol { - if (type != undefined && paramsCount != undefined) { - return createSubroutineSymbol(paramsCount, type); - } else { - return {} as GenericSymbol; - } - } - - const duplicateVarClassBodies = [ - ["static", " static int a, a;"], - ["field", " field int a, a;"], - ["static and field", " static int a; field boolean a;"], - ["function args", " function void a(int a, int a){return;}"], - [ - "function var", - ` function void a(){ - var boolean a, a; - return; - }`, - ], - [ - "function var with different types", - ` function void a(){ - var boolean a; - var int a; - return; - }`, - ], - ]; - test.concurrent.each(duplicateVarClassBodies)( - "duplicated %s", - (testName, classBody) => { - testValidator( - ` - class Main { - ${classBody} - }`, - 'DuplicatedVariableError', - ); - }, - ); - - /** - * Undeclared var - */ - test("let - undeclared variable ", () => { - testValidator( - ` - class Main { - function void a(){ - let b=1; - return; - } - }`, - 'UndeclaredVariableError', - ); - }); - - test("call function - undeclared variable ", () => { - testValidator( - `class Main { - function void b(int a){ - return; - } - function void a(){ - do Main.b(a); - return; - } - }`, - 'UndeclaredVariableError', - { - Main: genericSymbol(), - "Main.b": genericSymbol(SubroutineType.Function, 1), - "Main.a": genericSymbol(SubroutineType.Function, 1), - }, - ); - }); - - test("if - undeclared variable ", () => { - testValidator( - `class Main { - function void a(){ - if(a=0){ - return; - }else { - return; - } - } - }`, - 'UndeclaredVariableError', - ); - }); - - /** - * Unknown class - */ - test("Unknown class for subroutine return type ", () => { - testValidator( - ` - class Main { - function void b(int a){ - var D d; - return; - } - }`, - 'UnknownClassError', - ); - }); - - test("Known type for subroutine return type ", () => { - testValidator( - ` - class Main { - function D b(int a){ - return D.new(); - } - }`, - undefined, - { - D: genericSymbol(), - "D.new": genericSymbol(SubroutineType.Constructor, 0), - }, - ); - }); - test("Arg Unknown class ", () => { - testValidator( - ` - class Main { - function void b(D a){ - return; - } - }`, - 'UnknownClassError', - ); - }); - - test("Arg known type ", () => { - testValidator( - ` - - class Main { - function void b(D a){ - return; - } - }`, - undefined, - { D: genericSymbol() }, - ); - }); - test("var Unknown class", () => { - testValidator( - ` - class Main { - function void b(){ - var D d; - return; - } - }`, - 'UnknownClassError', - ); - }); - test("var known type", () => { - testValidator( - ` - class Main { - function void b(){ - var D d; - return; - } - }`, - undefined, - { D: genericSymbol() }, - ); - }); - test("field Unknown class", () => { - testValidator( - ` - class Main { - field T t; - }`, - 'UnknownClassError', - ); - }); - test("field known type", () => { - testValidator( - ` - class Main { - field T t; - }`, - undefined, - { T: genericSymbol() }, - ); - }); - test("static field Unknown class", () => { - testValidator( - ` - class Main { - static T t; - }`, - 'UnknownClassError', - ); - }); - test("static field known type", () => { - testValidator( - ` - class Main { - static T t; - }`, - undefined, - { T: genericSymbol() }, - ); - }); - - /** - * Incorrect return type - */ - - test("non void subroutine must return a value", () => { - testValidator( - ` - class Main { - function int a(){ - return; - } - }`, - 'NonVoidFunctionNoReturnError', - ); - }); - - test("void subroutine must return not return a value", () => { - testValidator( - ` - class Main { - function void a(){ - return 1; - } - }`, - 'VoidSubroutineReturnsValueError', - ); - }); - /** - * `Subroutine ${subroutine.name.value}: not all code paths return a value` - */ - - test("if missing return", () => { - testValidator( - ` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - - }else{ - return; - } - } - }`, - 'SubroutineNotAllPathsReturnError', - ); - }); - test("else missing return ", () => { - testValidator( - ` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - return; - }else{ - - } - } - }`, - 'SubroutineNotAllPathsReturnError', - ); - }); - - test("while missing return", () => { - testValidator( - ` - class Main { - function int a(){ - var int a; - let a=0; - while(a<10){ - - } - } - }`, - 'SubroutineNotAllPathsReturnError', - ); - }); - - test(" missing return after while", () => { - testValidator( - ` - class Main { - function int a(){ - var int a; - let a=0; - while(a<10){ - return 0; - } - } - }`, - 'SubroutineNotAllPathsReturnError', - ); - }); - - test("nested if missing return", () => { - testValidator( - ` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - if(a=1){ - return; - }else { - - } - }else{ - return; - } - } - }`, - 'SubroutineNotAllPathsReturnError', - ); - }); - test("nested if missing return 2", () => { - testValidator( - ` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - if(a=1){ - - }else { - return; - } - }else{ - return; - } - } - }`, - 'SubroutineNotAllPathsReturnError', - ); - }); - - test("nested if missing return 3", () => { - testValidator( - ` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - if(a=1){ - return; - }else { - return; - } - }else{ - - } - } - }`, - 'SubroutineNotAllPathsReturnError', - ); - }); - test("should be valid", () => { - testValidator(` - class Main { - function void a(){ - var int a; - let a=0; - if(a=0){ - if(a=1){ - }else { - } - } - return; - } - }`); - }); - /** - * Validate function call - */ - test("calling undefined subroutine", () => { - testValidator( - ` - class Main { - function void b(){ - do Main.c(); - return; - } - }`, - 'UnknownSubroutineCallError', - ); - }); - - test("incorrect number of parameters when calling a function", () => { - testValidator( - ` - class Main { - function void a(int a, int b){ - return; - } - function void b(){ - do Main.a(1); - return; - } - }`, - 'IncorrectParamsNumberInSubroutineCallError', - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 2), - "Main.b": genericSymbol(SubroutineType.Function, 2), - }, - ); - }); - - test("call var method ", () => { - testValidator( - ` - class Main { - constructor Main new(){ - return this; - } - function void a(){ - var Main m; - let m = Main.new(); - do m.b(); - return; - } - method void b(){ - return; - } - }`, - undefined, - { - Main: genericSymbol(), - "Main.new": genericSymbol(SubroutineType.Constructor, 0), - "Main.a": genericSymbol(SubroutineType.Function, 0), - "Main.b": genericSymbol(SubroutineType.Method, 0), - }, - ); - }); - test("call local method ", () => { - testValidator( - ` - class Main { - method void a(){ - do b(); - return; - } - method void b(){ - return; - } - }`, - undefined, - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Method, 0), - "Main.b": genericSymbol(SubroutineType.Method, 0), - }, - ); - }); - - /** - * - `Method ${className}.${subroutineName} was called as a function/constructor` - */ - test("method called as a function/constructor", () => { - testValidator( - ` - class Main { - function void b(){ - do Main.c(); - return; - } - method void c(){ - return; - } - }`, - 'MethodCalledAsFunctionError', - { - Main: genericSymbol(), - "Main.b": genericSymbol(SubroutineType.Function, 0), - "Main.c": genericSymbol(SubroutineType.Method, 0), - }, - ); - }); - test("function/ctor called as a method", () => { - testValidator( - ` - class Main { - function void b(){ - do c(); - return; - } - function void c(){ - return; - } - }`, - 'FunctionCalledAsMethodError', - { - Main: genericSymbol(), - "Main.b": genericSymbol(SubroutineType.Function, 0), - "Main.c": genericSymbol(SubroutineType.Function, 0), - }, - ); - }); - test("incorrect return type in constructor", () => { - testValidator( - ` - class Main { - constructor D new(){ - return this; - } - }`, - 'IncorrectConstructorReturnTypeError', - { - Main: genericSymbol(), - D: genericSymbol(), - }, - ); - }); - test("unreachable code", () => { - testValidator( - ` - class Main { - constructor Main new(){ - return this; - let a=0; - let a=0; - let a=0; - } - }`, - 'UnreachableCodeError', - { - Main: genericSymbol(), - "Main.new": genericSymbol(SubroutineType.Constructor, 0), - }, - ); - }); - test("A constructor must return 'this'", () => { - testValidator( - ` - class Main { - constructor Main new(){ - return 1; - } - }`, - 'ConstructorMushReturnThisError', - { - Main: genericSymbol(), - "Main.new": genericSymbol(SubroutineType.Constructor, 0), - }, - ); - }); - test("Let statement - expected string literal ", () => { - testValidator( - ` - class Main { - function void a(){ - var String foo; - let foo = 1; - return; - } - }`, - 'WrongLiteralTypeError', - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - String: genericSymbol(), - }, - ); - }); - test("Let statement - expected boolean literal ", () => { - testValidator( - ` - class Main { - function void a(){ - var boolean foo; - let foo = 1; - return; - } - }`, - 'WrongLiteralTypeError', - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }, - ); - }); - - test("Let statement - expected int literal ", () => { - testValidator( - ` - class Main { - function void a(){ - var int foo; - let foo = "asb"; - return; - } - }`, - 'WrongLiteralTypeError', - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }, - ); - }); - test("integer constant value is too big", () => { - testValidator( - ` - class Main { - function void a(){ - var int foo; - let foo = 33000; - return; - } - }`, - 'IntLiteralIsOutOfRangeError', - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }, - ); - }); - test("integer constant value is too small", () => { - testValidator( - ` - class Main { - function void a(){ - var int foo; - let foo = -33000; - return; - } - }`, - 'IntLiteralIsOutOfRangeError', - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }, - ); - }); - test("A field can not be referenced in a function", () => { - testValidator( - ` - class Main { - field int a; - function void a(){ - let a = 1; - return; - } - }`, - 'FieldCantBeReferencedInFunctionError', - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }, - ); - }); - test("A static field can be referenced in a function", () => { - testValidator( - ` - class Main { - static int a; - function void a(){ - let a = 1; - return; - } - }`, - undefined, - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }, - ); - }); - test("this can't be referenced in a function", () => { - testValidator( - ` - class Main { - function void a(){ - var Main m; - let m = this; - return; - } - }`, - 'ThisCantBeReferencedInFunctionError', - { - Main: genericSymbol(), - "Main.a": genericSymbol(SubroutineType.Function, 0), - }, - ); - }); - test("class name doesn't match filename", () => { - testValidator( - `class A {}`, - 'FilenameDoesntMatchClassNameError', - { - A: genericSymbol(), - }, - "B", - ); - }); - - //validate files - test.each(testResourceDirs)("%s", async (dir: string) => { - await testJackDir(fs, getTestResourcePath(dir)); - }); -}); - -async function testJackDir(fs: FileSystem, testFolder: string): Promise { - const files = [...(await fs.readdir(testFolder))] - .filter((file) => file.endsWith(".jack")) - .map((file) => path.join(testFolder, file)); - const trees: Record = {}; - const globalSymbolsListener: JackGlobalSymbolTableListener = - new JackGlobalSymbolTableListener(); - for (const filePath of files) { - const tree = parseJackFile(filePath); - trees[filePath] = tree; - listenToTheTree(tree, globalSymbolsListener); - expect(globalSymbolsListener.errors).toEqual([]); - } - for (const filepath of Object.keys(trees)) { - const tree = trees[filepath]; - const validatorListener = listenToTheTree( - tree, - new JackValidatorListener(globalSymbolsListener.globalSymbolTable), - ); - expect(validatorListener.errors).toEqual([]); - } -} - -function testValidator( - src: string, - expectedError?: T, - globalSymbolTable: Record = {}, - filename?: string, -) { - const errorListener = new JackCustomErrorListener(); - const tree = parseJackText(src, errorListener); - const listener = - filename != null - ? new JackValidatorListener(globalSymbolTable, filename) - : new JackValidatorListener(globalSymbolTable); - const validator = listenToTheTree(tree, listener); - if (expectedError) { - if (validator.errors.length > 1) { - console.error("Errors", validator.errors); - } - try { - expect(validator.errors.length).toBe(1); - expect(validator.errors[0].type).toBe(expectedError); - } catch (e) { - throw new Error( - `Expected error ${expectedError} but got '` + - JSON.stringify(validator.errors) + - "'", - ); - } - } else { - if (validator.errors.length != 0) - throw new Error( - "Didn't expect any errors but got " + validator.errors.join("\n"), - ); - } -} - -/** - * TODO: - * Ideas for improvement - - * - Show "Expected class name, subroutine name, field, parameter or local or static variable name" instead of "expecting IDENTIFIER" - * - Show "Expected subroutine return type followed by a subroutine name" instead of "expecting IDENTIFIER" - * - Expected subroutine name in call - * - a numeric value is illegal here when using non numeric vars - * - validate function call - when using literal in call validate the type - * add validation for assigning from void function call - * add rule to forbid var use before assignment - */ diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 15a15acd..2f6696d6 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -1,8 +1,6 @@ -import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; -import { ParserRuleContext } from "antlr4"; -import { builtInTypes, intRange } from "../builtins.js"; +import { TerminalNode } from "antlr4ng"; +import { builtInTypes, intRange } from "../builtins"; import { - asSpan, ConstructorMushReturnThisError, DuplicatedVariableError, FieldCantBeReferencedInFunctionError, @@ -14,7 +12,9 @@ import { JackCompilerError, MethodCalledAsFunctionError, NonVoidFunctionNoReturnError, + ruleContextToSpan, SubroutineNotAllPathsReturnError, + terminalNodeToSpan, ThisCantBeReferencedInFunctionError, UndeclaredVariableError, UnknownClassError, @@ -22,40 +22,40 @@ import { UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError, -} from "../error.js"; +} from "../error"; import { ClassDeclarationContext, ClassVarDecContext, ConstantContext, ElseStatementContext, + FieldNameContext, IfStatementContext, LetStatementContext, ParameterContext, RBraceContext, ReturnStatementContext, StatementContext, - SubroutineBodyContext, SubroutineCallContext, SubroutineDeclarationContext, SubroutineDecWithoutTypeContext, VarDeclarationContext, VarNameContext, + VarNameInDeclarationContext, VarTypeContext, - WhileStatementContext, -} from "../generated/JackParser.js"; -import JackParserListener from "../generated/JackParserListener.js"; + WhileStatementContext +} from "../generated/JackParser"; +import { JackParserListener } from "../generated/JackParserListener"; import { GenericSymbol, LocalSymbolTable, ScopeType, SubroutineType, -} from "../symbol.js"; -import { CallType, getCallType } from "./common.js"; - +} from "../symbol"; +import { assertExists, CallType, getCallType } from "./common"; /** * Validates Jack file */ -export class JackValidatorListener extends JackParserListener { +export class ValidatorListener extends JackParserListener { private localSymbolTable: LocalSymbolTable = new LocalSymbolTable(); private subroutineShouldReturnVoidType = false; private controlFlowGraphNode: BinaryTreeNode = new BinaryTreeNode(); @@ -79,10 +79,12 @@ export class JackValidatorListener extends JackParserListener { } this.className = newName; if (this.filename != null && this.filename != this.className) { - console.error("FilenameDoesntMatchClassName"); + if (className.start == null) { + throw new Error("Start token should not be null"); + } this.errors.push( FilenameDoesntMatchClassNameError( - asSpan(ctx.start), + ruleContextToSpan(ctx.className()), this.filename, this.className ) @@ -103,9 +105,14 @@ export class JackValidatorListener extends JackParserListener { const type = ctx.fieldList().varType().getText(); ctx .fieldList() - .fieldName_list() - .forEach((field) => { - this.localSymbolTableAdd(ctx, scope, field.getText(), type); + .fieldName() + .forEach((field: FieldNameContext) => { + this.localSymbolTableAdd( + field.IDENTIFIER(), + scope, + field.getText(), + type + ); }); }; override enterSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { @@ -115,7 +122,13 @@ export class JackValidatorListener extends JackParserListener { ctx.subroutineDecWithoutType().subroutineReturnType().getText() !== this.className ) { - this.addError(IncorrectConstructorReturnTypeError(asSpan(ctx.start))); + this.addError( + IncorrectConstructorReturnTypeError( + ruleContextToSpan( + ctx.subroutineDecWithoutType().subroutineReturnType() + ) + ) + ); } } else if (ctx.subroutineType().FUNCTION() != null) { this.subroutineType = SubroutineType.Function; @@ -135,28 +148,42 @@ export class JackValidatorListener extends JackParserListener { }; override enterParameter = (ctx: ParameterContext) => { - this.defineArgument( - ctx, - ctx.parameterName().getText(), - ctx.varType().getText(), - this.subroutineType == SubroutineType.Method - ); + const name = ctx.parameterName().getText(); + if (this.localSymbolTable.lookup(name)) { + this.addError( + DuplicatedVariableError(ruleContextToSpan(ctx.parameterName()), name) + ); + } else { + this.localSymbolTable.defineArgument( + name, + ctx.varType().getText(), + this.subroutineType == SubroutineType.Method + ); + } }; //Var override enterVarType = (ctx: VarTypeContext) => { - if (ctx.IDENTIFIER() != null) { - const type = ctx.IDENTIFIER().getText(); + const id = ctx.IDENTIFIER(); + if (id != null) { + const type = id.getText() ?? ""; if (this.globalSymbolTable[type] == null) { - this.addError(UnknownClassError(asSpan(ctx.start), type)); + this.addError(UnknownClassError(terminalNodeToSpan(id), type)); } } }; override enterVarDeclaration = (ctx: VarDeclarationContext) => { const type = ctx.varType().getText(); - ctx.varNameInDeclaration_list().forEach((name) => { - this.localSymbolTableAdd(ctx, ScopeType.Local, name.getText(), type); - }); + ctx + .varNameInDeclaration() + .forEach((nameCtx: VarNameInDeclarationContext) => { + this.localSymbolTableAdd( + nameCtx.IDENTIFIER(), + ScopeType.Local, + nameCtx.getText(), + type + ); + }); }; /** @@ -165,130 +192,146 @@ export class JackValidatorListener extends JackParserListener { override enterVarName = (ctx: VarNameContext) => { const symbol = this.localSymbolTable.lookup(ctx.getText()); if (symbol == undefined) { - this.addError(UndeclaredVariableError(asSpan(ctx.start), ctx.getText())); + this.addError( + UndeclaredVariableError( + terminalNodeToSpan(ctx.IDENTIFIER()), + ctx.getText() + ) + ); } else if ( this.subroutineType == SubroutineType.Function && symbol.scope == ScopeType.This ) { - this.addError(FieldCantBeReferencedInFunctionError(asSpan(ctx.start))); + this.addError( + FieldCantBeReferencedInFunctionError( + terminalNodeToSpan(ctx.IDENTIFIER()) + ) + ); } }; override enterConstant = (ctx: ConstantContext) => { - if ( - ctx.THIS_LITERAL() != null && - this.subroutineType == SubroutineType.Function - ) { - this.addError(ThisCantBeReferencedInFunctionError(asSpan(ctx.start))); + const thisLiteral = ctx.THIS_LITERAL(); + if (thisLiteral != null && this.subroutineType == SubroutineType.Function) { + this.addError( + ThisCantBeReferencedInFunctionError(terminalNodeToSpan(thisLiteral)) + ); } }; override enterStatement = (ctx: StatementContext) => { if (this.controlFlowGraphNode.returns == true) { - this.addError(UnreachableCodeError(asSpan(ctx.start, ctx.stop))); + this.addError(UnreachableCodeError(ruleContextToSpan(ctx))); this.stopProcessingErrorsInThisScope = true; } }; - override enterRBrace = (ctx: RBraceContext) => { + override enterRBrace = (_ctx: RBraceContext) => { this.stopProcessingErrorsInThisScope = false; }; /** * Control flow */ - override enterWhileStatement = (ctx: WhileStatementContext) => { + override enterWhileStatement = (_ctx: WhileStatementContext) => { this.controlFlowGraphNode = this.controlFlowGraphNode.left = new BinaryTreeNode(this.controlFlowGraphNode); }; - override exitWhileStatement = (ctx: WhileStatementContext) => { + override exitWhileStatement = (_ctx: WhileStatementContext) => { if (this.controlFlowGraphNode?.parent != null) { this.controlFlowGraphNode = this.controlFlowGraphNode.parent; } }; - override enterIfStatement = (ctx: IfStatementContext) => { + override enterIfStatement = (_ctx: IfStatementContext) => { this.controlFlowGraphNode = this.controlFlowGraphNode.left = new BinaryTreeNode(this.controlFlowGraphNode); }; - override exitIfStatement = (ctx: IfStatementContext) => { + override exitIfStatement = (_ctx: IfStatementContext) => { if (this.controlFlowGraphNode?.parent != null) { this.controlFlowGraphNode = this.controlFlowGraphNode.parent; } }; - override enterElseStatement = (ctx: ElseStatementContext) => { + override enterElseStatement = (_ctx: ElseStatementContext) => { this.controlFlowGraphNode = this.controlFlowGraphNode.right = new BinaryTreeNode(this.controlFlowGraphNode); }; - override exitElseStatement = (ctx: ElseStatementContext) => { + override exitElseStatement = (_ctx: ElseStatementContext) => { if (this.controlFlowGraphNode?.parent != null) { this.controlFlowGraphNode = this.controlFlowGraphNode.parent; } }; override enterLetStatement = (ctx: LetStatementContext) => { - const varName = ctx.varName(); - const constCtx = ctx.expression().constant(); + const varName = ctx.varName()?.getText(); + const constCtx = ctx.expression()?.constant(); //corresponding literal type check if ( varName != null && constCtx != null && - this.localSymbolTable.lookup(ctx.varName().getText()) && - ctx.expression().constant().NULL_LITERAL() == null + this.localSymbolTable.lookup(varName) && + constCtx.NULL_LITERAL() == null ) { - const symbol = this.localSymbolTable.lookup(ctx.varName().getText()); - const type = assertExists(symbol).type; - if (literalTypes.indexOf(type) != -1) { - const constantCtx = ctx.expression().constant(); - switch (type) { - case "char": - case "int": - if (constantCtx.INTEGER_LITERAL() === null) { - this.addError(WrongLiteralTypeError(asSpan(ctx.start), type)); - } else { - const value = parseInt(constantCtx.INTEGER_LITERAL().getText()); - if (value > intRange.max) { - this.addError( - IntLiteralIsOutOfRangeError( - asSpan(ctx.start), - value, - intRange.min, - intRange.max - ) - ); - } - } - break; - case "boolean": - if (constantCtx.booleanLiteral() === null) { - this.addError(WrongLiteralTypeError(asSpan(ctx.start), type)); - } - break; - case "String": - if (constantCtx.STRING_LITERAL() === null) { - this.addError( - WrongLiteralTypeError(asSpan(ctx.start), type.toLowerCase()) - ); - } - break; - default: - throw new Error(`Unknown literal type ${type}`); + const symbol = this.localSymbolTable.lookup(varName); + if (symbol != null && literalTypes.indexOf(symbol.type) != -1) { + let expectedLiteralType = symbol.type; + if (expectedLiteralType === "char") { + expectedLiteralType = "int"; + } + const constantCtx = ctx.expression()?.constant(); + let actualType = ""; + if (constantCtx?.INTEGER_LITERAL() != null) { + actualType = "int"; + const intLiteral = constantCtx?.INTEGER_LITERAL(); + const value = constantCtx?.INTEGER_LITERAL()?.getText(); + if ( + constCtx != null && + intLiteral != null && + value != null && + parseInt(value) > intRange.max + ) { + this.addError( + IntLiteralIsOutOfRangeError( + terminalNodeToSpan(intLiteral), + parseInt(value), + intRange.min, + intRange.max + ) + ); + } + } else if (constCtx?.STRING_LITERAL() != null) { + actualType = "String"; + } else if (constCtx?.booleanLiteral() != null) { + actualType = "boolean"; + } else { + throw new Error(`Unknown literal type ${expectedLiteralType}`); + } + if (actualType != expectedLiteralType) { + this.addError( + WrongLiteralTypeError( + ruleContextToSpan(constantCtx ?? ctx), + symbol.type, + actualType + ) + ); } } } //int min value check - const unaryOp = ctx.expression().unaryOperation(); + const unaryOp = ctx.expression()?.unaryOperation(); if ( varName && unaryOp != null && unaryOp.unaryOperator().MINUS() !== null && - unaryOp.expression().constant() != null && - unaryOp.expression().constant()?.INTEGER_LITERAL() !== null + unaryOp.expression()?.constant() != null && + unaryOp.expression()?.constant()?.INTEGER_LITERAL() !== null ) { const value = parseInt( - unaryOp.expression().constant().INTEGER_LITERAL().getText() + unaryOp.expression()?.constant()?.INTEGER_LITERAL()?.getText() ?? "0" ); if (-value < intRange.min) { this.addError( IntLiteralIsOutOfRangeError( - asSpan(ctx.start), + terminalNodeToSpan( + assertExists(unaryOp.expression()?.constant()?.INTEGER_LITERAL()) + ), value, intRange.min, intRange.max @@ -311,7 +354,7 @@ export class JackValidatorListener extends JackParserListener { if (symbol == undefined) { this.addError( UnknownSubroutineCallError( - asSpan(ctx.start), + ruleContextToSpan(subroutineId.subroutineName()), subroutineId.subroutineName().getText(), subroutineId.className()?.getText() ) @@ -324,7 +367,7 @@ export class JackValidatorListener extends JackParserListener { ) { this.addError( MethodCalledAsFunctionError( - asSpan(ctx.start), + ruleContextToSpan(subroutineId.subroutineName()), subroutineId.subroutineName().getText() ) ); @@ -336,22 +379,41 @@ export class JackValidatorListener extends JackParserListener { ) { this.addError( FunctionCalledAsMethodError( - asSpan(ctx.start), + ruleContextToSpan(subroutineId.subroutineName()), subroutineId.subroutineName().getText() ) ); } else { //check parameter count - const l = ctx.expressionList().expression_list().length; - if (assertExists(symbol.subroutineInfo).paramsCount != l) { - this.addError( - IncorrectParamsNumberInSubroutineCallError( - asSpan(ctx.start), - subroutineId.getText(), - assertExists(symbol.subroutineInfo).paramsCount, - l - ) - ); + const l = ctx.expressionList()?.expression().length; + if (symbol.subroutineInfo?.paramsCount != l) { + if (symbol.subroutineInfo == null) + throw new Error("Subroutine info cannot be null"); + if ( + ctx.expressionList() != null && + ctx.expressionList().start != null + ) { + this.addError( + IncorrectParamsNumberInSubroutineCallError( + ruleContextToSpan(ctx.expressionList()), + subroutineId.getText(), + assertExists(symbol.subroutineInfo).paramsCount, + l + ) + ); + } else { + const start = ctx.LPAREN().symbol; + const stop = ctx.RPAREN().symbol; + + this.addError( + IncorrectParamsNumberInSubroutineCallError( + { line: start.line, start: start.start, end: stop.stop + 1 }, + subroutineId.getText(), + symbol.subroutineInfo?.paramsCount ?? 0, + l + ) + ); + } } } } @@ -359,70 +421,56 @@ export class JackValidatorListener extends JackParserListener { override enterReturnStatement = (ctx: ReturnStatementContext) => { const returnsVoid = ctx.expression() == null; if (returnsVoid && !this.subroutineShouldReturnVoidType) { - this.addError( - NonVoidFunctionNoReturnError(asSpan(ctx.stop ?? ctx.start)) - ); + this.addError(NonVoidFunctionNoReturnError(ruleContextToSpan(ctx))); } if (!returnsVoid && this.subroutineShouldReturnVoidType) { - this.addError(VoidSubroutineReturnsValueError(asSpan(ctx.start))); + this.addError(VoidSubroutineReturnsValueError(ruleContextToSpan(ctx))); } this.controlFlowGraphNode.returns = true; if (this.subroutineType == SubroutineType.Constructor) { if ( returnsVoid || - ctx.expression().expression_list().length > 1 || - ctx.expression().constant() == null || - ctx.expression().constant().THIS_LITERAL() == null + (ctx.expression()?.expression().length ?? 0) > 1 || + ctx.expression()?.constant() == null || + ctx.expression()?.constant()?.THIS_LITERAL() == null ) { - this.addError( - ConstructorMushReturnThisError(asSpan(ctx.stop ?? ctx.start)) - ); + this.addError(ConstructorMushReturnThisError(ruleContextToSpan(ctx))); } } }; - override exitSubroutineBody = (ctx: SubroutineBodyContext) => { + override exitSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { if (!this.controlFlowGraphNode.returns) { this.addError( + //TODO: add exact place that doesn't return SubroutineNotAllPathsReturnError( - asSpan(ctx.stop ?? ctx.start), + ruleContextToSpan(ctx.subroutineType()), this.subroutineName ) ); } this.subroutineType = undefined; - }; - override exitSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { ctx.symbols = this.localSymbolTable.popStack(); }; - override exitClassDeclaration = (ctx: ClassDeclarationContext) => { + override exitClassDeclaration = (_ctx: ClassDeclarationContext) => { while (this.controlFlowGraphNode?.parent != undefined) { this.controlFlowGraphNode = this.controlFlowGraphNode.parent; } }; //Utils - defineArgument( - ctx: ParserRuleContext, - name: string, - type: string, - inMethod: boolean - ) { - if (this.localSymbolTable.lookup(name)) { - this.addError(DuplicatedVariableError(asSpan(ctx.start), name)); - } else { - this.localSymbolTable.defineArgument(name, type, inMethod); - } - } + localSymbolTableAdd( - ctx: ParserRuleContext, + identifierCtx: TerminalNode, scope: ScopeType, name: string, type: string ) { if (this.localSymbolTable.lookup(name)) { - this.addError(DuplicatedVariableError(asSpan(ctx.start), name)); + this.addError( + DuplicatedVariableError(terminalNodeToSpan(identifierCtx), name) + ); } else { this.localSymbolTable.define(scope, name, type); } @@ -466,12 +514,12 @@ class BinaryTreeNode { printBT(prefix = "", side: Side = Side.LEFT) { let res = ""; if (this._returns) { - res += this.pad(prefix, side); + res += this.#pad(side); res += " " + this._returns + "\n"; return res; } else { if (this.right == undefined && this.left == undefined) { - res += this.pad(prefix, side); + res += this.#pad(side); res += " " + false + "\n"; } else { res += this.left?.printBT( @@ -491,7 +539,7 @@ class BinaryTreeNode { } return res; } - pad(prefix: string, side: Side): string { + #pad(side: Side): string { return side == Side.LEFT ? "├──" : "└──"; } } diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index 9ac249e4..d8f80989 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -1,29 +1,26 @@ -import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; +import { JackParserListener } from "../generated/JackParserListener"; import { ArrayAccessContext, ClassDeclarationContext, ConstantContext, - EqualsContext, ExpressionContext, IfElseStatementContext, IfExpressionContext, IfStatementContext, LetStatementContext, ReturnStatementContext, - StatementContext, SubroutineCallContext, SubroutineDeclarationContext, WhileExpressionContext, WhileStatementContext, -} from "../generated/JackParser.js"; -import JackParserListener from "../generated/JackParserListener.js"; +} from "../generated/JackParser"; import { GenericSymbol, LocalSymbolTable, scopeTypeToString, VariableSymbol, -} from "../symbol.js"; -import { CallType, getCallType } from "./common.js"; +} from "../symbol"; +import { assertExists, CallType, getCallType } from "./common"; const binaryOperationToVmCmd: Record = { "+": "add", @@ -41,16 +38,15 @@ const unaryOperationToVmCmd: Record = { "-": "neg", "~": "not", }; - /** * Transforms parse tree into VM code */ -export class JackVMWriter extends JackParserListener { +export class VMWriter extends JackParserListener { public result = ""; private className = ""; - private currentLabelIndex = 0; - private localSymbolTable: LocalSymbolTable | undefined; - private inAssignmentRightHandSide = false; + private currentLabelInd = 0; + private _localSymbolTable: LocalSymbolTable | undefined; + private afterEquals = false; constructor(private globalSymbolTable: Record) { super(); } @@ -62,9 +58,17 @@ export class JackVMWriter extends JackParserListener { if (ctx.localSymbolTable == undefined) { throw new Error("Local symbol table not found in parse tree"); } + if (ctx.className() == null) { + throw new Error("Class name not found in parse tree"); + } this.className = ctx.className().getText(); - this.localSymbolTable = ctx.localSymbolTable; + this._localSymbolTable = ctx.localSymbolTable; }; + get localSymbolTable() { + if (this._localSymbolTable == null) + throw new Error("Local symbol table is not initialized"); + return this._localSymbolTable; + } override enterSubroutineDeclaration = (ctx: SubroutineDeclarationContext) => { const name = ctx @@ -72,18 +76,21 @@ export class JackVMWriter extends JackParserListener { .subroutineName() .IDENTIFIER() .getText(); - const localSymbolTable = assertExists(this.localSymbolTable); const symbol = this.globalSymbolTable[this.className + "." + name]; if (symbol == undefined) { throw new Error( - `Can't find subroutine ${name} in class ${this.className} in symbol table`, + `Can't find subroutine ${name} in class ${this.className} in symbol table` + ); + } + if (symbol.subroutineInfo == null) { + throw new Error( + `Subroutine info not found for subroutine ${name} in class ${this.className}` ); } - const subroutineInfo = assertExists(symbol.subroutineInfo); - this.result += `function ${this.className}.${name} ${subroutineInfo.localVarsCount}\n`; + this.result += `function ${this.className}.${name} ${symbol.subroutineInfo.localVarsCount}\n`; if (ctx.subroutineType().CONSTRUCTOR() != null) { - this.result += ` push constant ${localSymbolTable.fieldsCount()}\n`; + this.result += ` push constant ${this.localSymbolTable.fieldsCount()}\n`; this.result += " call Memory.alloc 1\n"; this.result += " pop pointer 0\n"; } else if (ctx.subroutineType().METHOD() != null) { @@ -94,38 +101,34 @@ export class JackVMWriter extends JackParserListener { if (ctx.symbols == null) { throw new Error("Subroutine symbols not found in parse tree"); } - localSymbolTable.setSubroutineScope(ctx.symbols); + this.localSymbolTable.setSubroutineScope(ctx.symbols); }; override exitArrayAccess = (ctx: ArrayAccessContext) => { - const localSymbolTable = assertExists(this.localSymbolTable); const varName = ctx.varName().IDENTIFIER().getText(); - const symbol = localSymbolTable.lookup(varName); + const symbol = this.localSymbolTable.lookup(varName); if (symbol == undefined) { throw new Error(`Can't find variable ${varName} in local symbol table`); } this.pushSymbolOntoStack(symbol); this.result += ` add\n`; - if ( - this.inAssignmentRightHandSide || - ctx.parentCtx instanceof ExpressionContext - ) { + if (this.afterEquals || ctx.parent instanceof ExpressionContext) { this.result += ` pop pointer 1\n`; this.result += ` push that 0\n`; } }; - override enterEquals = (ctx: EqualsContext) => { - this.inAssignmentRightHandSide = true; + override enterEquals = () => { + this.afterEquals = true; }; - override exitStatement = (ctx: StatementContext) => { - this.inAssignmentRightHandSide = false; + override exitStatement = () => { + this.afterEquals = false; }; override enterConstant = (ctx: ConstantContext) => { if (ctx.INTEGER_LITERAL() != null) { - this.result += ` push constant ${ctx.INTEGER_LITERAL().getText()}\n`; + this.result += ` push constant ${ctx.INTEGER_LITERAL()?.getText()}\n`; } else if (ctx.booleanLiteral() != null) { - if (ctx.booleanLiteral().FALSE() != null) { + if (ctx.booleanLiteral()?.FALSE() != null) { this.result += ` push constant 0\n`; - } else if (ctx.booleanLiteral().TRUE()) { + } else if (ctx.booleanLiteral()?.TRUE()) { this.result += ` push constant 1\n`; this.result += ` neg\n`; } else { @@ -134,11 +137,12 @@ export class JackVMWriter extends JackParserListener { } else if (ctx.THIS_LITERAL() != null) { this.result += ` push pointer 0\n`; } else if (ctx.STRING_LITERAL() != null) { - const str = ctx - .STRING_LITERAL()! - .getText() + const maybeStr = ctx + .STRING_LITERAL() + ?.getText() //cutoff "" .slice(1, -1); + const str = assertExists(maybeStr, "String literal cannot be null"); this.result += ` push constant ${str.length}\n`; this.result += ` call String.new 1\n`; for (const char of str) { @@ -153,23 +157,32 @@ export class JackVMWriter extends JackParserListener { }; override exitExpression = (ctx: ExpressionContext) => { if (ctx.varName() != null) { - const localSymbolTable = assertExists(this.localSymbolTable); - const varName = ctx.varName().IDENTIFIER().getText(); - const symbol = localSymbolTable.lookup(varName); + const varNameCtx = assertExists( + ctx.varName(), + "Variable name cannot be null" + ); + const varName = varNameCtx.IDENTIFIER().getText(); + const symbol = this.localSymbolTable.lookup(varName); if (symbol == undefined) { throw new Error( - `Cannot find variable ${varName} in arguments or local variables`, + `Cannot find variable ${varName} in arguments or local variables` ); } this.pushSymbolOntoStack(symbol); } else if (ctx.binaryOperator() != null) { - const binaryOp = ctx.binaryOperator().getText(); + const binaryOp = assertExists( + ctx.binaryOperator(), + "Binary operator cannot be null" + ).getText(); if (binaryOperationToVmCmd[binaryOp] == undefined) { throw new Error(`Unknown binary operator ${binaryOp}`); } this.result += "\t" + binaryOperationToVmCmd[binaryOp] + "\n"; } else if (ctx.unaryOperation() != null) { - const unaryOp = ctx.unaryOperation().unaryOperator().getText(); + const unaryOp = assertExists( + ctx.unaryOperation()?.unaryOperator(), + "Unary operation cannot be null" + ).getText(); if (unaryOperationToVmCmd[unaryOp] == null) { throw new Error(`Unknown unary operator ${unaryOp}`); } @@ -181,13 +194,13 @@ export class JackVMWriter extends JackParserListener { } override exitLetStatement = (ctx: LetStatementContext) => { if (ctx.varName() != null) { - const localSymbolTable = assertExists(this.localSymbolTable); - const symbol = localSymbolTable.lookup( - ctx.varName().IDENTIFIER().getText(), + const varNameCtx = assertExists(ctx.varName(), "Var name cannot be null"); + const symbol = this.localSymbolTable.lookup( + varNameCtx.IDENTIFIER().getText() ); if (symbol == undefined) { throw new Error( - `Can't find variable ${ctx.varName().IDENTIFIER().getText()} in local symbol table`, + `Can't find variable ${ctx.varName()?.IDENTIFIER().getText()} in local symbol table` ); } this.result += ` pop ${scopeTypeToString(symbol.scope)} ${symbol.index}\n`; @@ -205,7 +218,7 @@ export class JackVMWriter extends JackParserListener { ctx.endLabel = this.createLabel(); }; override exitIfStatement = (ctx: IfStatementContext) => { - const parent = ctx.parentCtx as IfElseStatementContext; + const parent = ctx.parent as IfElseStatementContext; if (parent.elseStatement() != null) { parent.endLabel = this.createLabel(); this.result += ` goto ${parent.endLabel}\n`; @@ -213,7 +226,7 @@ export class JackVMWriter extends JackParserListener { this.result += ` label ${ctx.endLabel}\n`; }; override exitIfExpression = (ctx: IfExpressionContext) => { - const parent = ctx.parentCtx as IfStatementContext; + const parent = ctx.parent as IfStatementContext; this.ifNotGoto(parent.endLabel); }; override exitIfElseStatement = (ctx: IfElseStatementContext) => { @@ -228,7 +241,7 @@ export class JackVMWriter extends JackParserListener { this.result += ` label ${ctx.startLabel} \n`; }; override exitWhileExpression = (ctx: WhileExpressionContext) => { - const parent = ctx.parentCtx as WhileStatementContext; + const parent = ctx.parent as WhileStatementContext; this.ifNotGoto(parent.endLabel); }; @@ -241,10 +254,12 @@ export class JackVMWriter extends JackParserListener { const { callType, symbol } = getCallType( ctx.subroutineId(), this.className, - this.localSymbolTable!, + this.localSymbolTable ); if (callType === CallType.VarMethod) { - this.pushSymbolOntoStack(symbol!); + if (symbol == null) + throw new Error("Symbol not found when calling a method"); + this.pushSymbolOntoStack(symbol); } else if (callType === CallType.LocalMethod) { this.result += ` push pointer 0\n`; } @@ -255,17 +270,17 @@ export class JackVMWriter extends JackParserListener { const { callType, subroutineIdText } = getCallType( ctx.subroutineId(), this.className, - this.localSymbolTable!, + this.localSymbolTable ); switch (callType) { case CallType.ClassFunctionOrConstructor: { - const argsCount = ctx.expressionList().expression_list().length; + const argsCount = ctx.expressionList().expression().length; this.result += ` call ${ctx.subroutineId().getText()} ${argsCount}\n`; break; } case CallType.LocalMethod: case CallType.VarMethod: { - const expressionsCount = ctx.expressionList().expression_list().length; + const expressionsCount = ctx.expressionList().expression().length; this.result += ` call ${subroutineIdText} ${expressionsCount + 1}\n`; break; } @@ -290,6 +305,6 @@ export class JackVMWriter extends JackParserListener { } createLabel() { - return this.getLabel(this.currentLabelIndex++); + return this.getLabel(this.currentLabelInd++); } } diff --git a/simulator/src/jack/parser.test.ts b/simulator/src/jack/parser.test.ts index 79c6159d..0ef7b328 100644 --- a/simulator/src/jack/parser.test.ts +++ b/simulator/src/jack/parser.test.ts @@ -8,7 +8,7 @@ import { parseJackText, testResourceDirs, } from "./test.helper"; -import { JackGlobalSymbolTableListener } from "./listener/global.symbol.table.listener"; +import { GlobalSymbolTableListener } from "./listener/global.symbol.listener"; describe("Jack parser", () => { const jestConsole = console; @@ -51,7 +51,7 @@ function testJackDir(testFolder: string): void { const tree = parseJackFile(filePath); const globalSymbolsListener = listenToTheTree( tree, - new JackGlobalSymbolTableListener(), + new GlobalSymbolTableListener(), ); const symbolsErrors = globalSymbolsListener.errors.join("\n"); try { diff --git a/simulator/src/jack/simulator.code-workspace b/simulator/src/jack/simulator.code-workspace new file mode 100644 index 00000000..ce26be06 --- /dev/null +++ b/simulator/src/jack/simulator.code-workspace @@ -0,0 +1,11 @@ +{ + "folders": [ + { + "path": "../.." + }, + { + "path": "../../../../nand2tetris-jack-lsp/jack-compiler" + } + ], + "settings": {} +} \ No newline at end of file diff --git a/simulator/src/jack/symbol.ts b/simulator/src/jack/symbol.ts index b514485b..6bacd114 100644 --- a/simulator/src/jack/symbol.ts +++ b/simulator/src/jack/symbol.ts @@ -11,6 +11,7 @@ export interface SubroutineInfo { type: SubroutineType; localVarsCount?: number; } + export type GlobalSymbolTable = Record; /** * Symbol that represents class or a subroutine diff --git a/simulator/src/jack/test.helper.ts b/simulator/src/jack/test.helper.ts index 7e4086b0..5263bbbf 100644 --- a/simulator/src/jack/test.helper.ts +++ b/simulator/src/jack/test.helper.ts @@ -1,32 +1,28 @@ import fs from "fs"; import path from "path"; import { JackCompilerError } from "./error"; -import { JackCustomErrorListener } from "./listener/error.listener"; -import { - CharStreams, - CommonTokenStream, - ParseTreeListener, - ParseTreeWalker, -} from "antlr4"; -import JackLexer from "./generated/JackLexer"; -import JackParser, { ProgramContext } from "./generated/JackParser"; +import { CustomErrorListener } from "./listener/error.listener"; +import { JackParser, ProgramContext } from "./generated/JackParser"; +import { CharStream, CommonTokenStream, ParseTreeListener, ParseTreeWalker } from "antlr4ng"; +import { JackLexer } from "./generated/JackLexer"; + export function parseJackFile(filePath: string, trace = false) { - const errorListener: JackCustomErrorListener = new JackCustomErrorListener(); + const errorListener = new CustomErrorListener(); const f = fs.readFileSync(filePath, "utf8"); return parseJackText(f, errorListener, trace); } export function parseJackText( src: string, - errorListener?: JackCustomErrorListener, + errorListener?: CustomErrorListener, trace = false, throwOnErrors = true, ): ProgramContext { if (errorListener === undefined) { - errorListener = new JackCustomErrorListener(); + errorListener = new CustomErrorListener(); } - const inputStream = CharStreams.fromString(src); + const inputStream = CharStream.fromString(src); const lexer = new JackLexer(inputStream); if (errorListener) { lexer.removeErrorListeners(); @@ -41,7 +37,7 @@ export function parseJackText( } const tree = parser.program(); - expect(tokenStream.tokens.length).toBeGreaterThan(0); + expect(tokenStream.getTokens().length).toBeGreaterThan(0); if (errorListener.errors.length > 0) { console.error("Parser or lexer errors found"); handleErrors(src, errorListener.errors); @@ -64,7 +60,7 @@ export function listenToTheTree( export function handleErrors(src: string, errors: JackCompilerError[]) { const msg = errors .map((e) => { - return `${e.span.line}:${e.span.start} ${e.message}\n${src.split("\n")[e.span.line]}`; + return `${e.span.line}:${e.span.start} ${e.msg}\n${src.split("\n")[e.span.line]}`; }) .join("\n"); console.error(msg); From 7c154b97daaa50da70727de3de970f336c4362c7 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 20 Oct 2024 11:00:16 +0200 Subject: [PATCH 76/87] WIP --- simulator/src/jack/anltr.compiler.ts | 5 ++--- simulator/src/jack/error.ts | 2 +- simulator/src/jack/generated/JackParser.ts | 2 +- simulator/src/jack/generated/JackParserListener.ts | 2 +- simulator/src/jack/listener/common.ts | 4 ++-- simulator/src/jack/listener/error.listener.ts | 4 ++-- .../src/jack/listener/global.symbol.listener.ts | 10 +++++----- simulator/src/jack/listener/validator.listener.ts | 12 ++++++------ simulator/src/jack/listener/vm.writer.listener.ts | 8 ++++---- 9 files changed, 24 insertions(+), 25 deletions(-) diff --git a/simulator/src/jack/anltr.compiler.ts b/simulator/src/jack/anltr.compiler.ts index 894af679..dbcf52c8 100644 --- a/simulator/src/jack/anltr.compiler.ts +++ b/simulator/src/jack/anltr.compiler.ts @@ -2,9 +2,8 @@ import { GlobalSymbolTableListener } from "./listener/global.symbol.listener.js"; import { CustomErrorListener } from "./listener/error.listener.js"; import { ValidatorListener } from "./listener/validator.listener.js"; -import { JackCompilerError, LexerOrParserError } from "./error.js"; +import { JackCompilerError } from "./error.js"; import { VMWriter } from "./listener/vm.writer.listener.js"; -import { GlobalSymbolTable } from "./symbol.js"; import { JackParser, ProgramContext } from "./generated/JackParser.js"; import { JackLexer } from "./generated/JackLexer.js"; import { CharStream, CommonTokenStream, ParseTreeWalker } from "antlr4ng"; @@ -46,7 +45,7 @@ function _do( files: Record, cmd: Command, ): Record { - if (files instanceof LexerOrParserError) { + if (files.type == "LexerOrParserError") { throw new Error("Expected tree but got a lexer or parser error"); } const result: Record = {}; diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index da4cd76b..d01db93f 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,5 +1,5 @@ import { ParserRuleContext, TerminalNode } from "antlr4ng"; -import { assertExists } from "./listener/common"; +import { assertExists } from "./listener/common.js"; export interface Span { start: number; diff --git a/simulator/src/jack/generated/JackParser.ts b/simulator/src/jack/generated/JackParser.ts index e2d0283b..f5ac7517 100644 --- a/simulator/src/jack/generated/JackParser.ts +++ b/simulator/src/jack/generated/JackParser.ts @@ -9,7 +9,7 @@ import { JackParserListener } from "./JackParserListener.js"; type int = number; -import { SubroutineScope, LocalSymbolTable } from "../symbol"; +import { SubroutineScope, LocalSymbolTable } from "../symbol.js"; export class JackParser extends antlr.Parser { diff --git a/simulator/src/jack/generated/JackParserListener.ts b/simulator/src/jack/generated/JackParserListener.ts index 88885ae0..cbdfb388 100644 --- a/simulator/src/jack/generated/JackParserListener.ts +++ b/simulator/src/jack/generated/JackParserListener.ts @@ -3,7 +3,7 @@ import { ErrorNode, ParseTreeListener, ParserRuleContext, TerminalNode } from "antlr4ng"; -import { SubroutineScope, LocalSymbolTable } from "../symbol"; +import { SubroutineScope, LocalSymbolTable } from "../symbol.js"; import { ProgramContext } from "./JackParser.js"; diff --git a/simulator/src/jack/listener/common.ts b/simulator/src/jack/listener/common.ts index 8063468f..ae8fe870 100644 --- a/simulator/src/jack/listener/common.ts +++ b/simulator/src/jack/listener/common.ts @@ -1,5 +1,5 @@ -import { SubroutineIdContext } from "../generated/JackParser"; -import { LocalSymbolTable, VariableSymbol } from "../symbol"; +import { SubroutineIdContext } from "../generated/JackParser.js"; +import { LocalSymbolTable, VariableSymbol } from "../symbol.js"; export interface CallTypeResult { callType: CallType; diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index dfdf603d..4c50870d 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -14,8 +14,8 @@ import { import { JackCompilerError, LexerOrParserError -} from "../error"; -import { assertExists } from "./common"; +} from "../error.js"; +import { assertExists } from "./common.js"; export class CustomErrorListener implements ANTLRErrorListener { public errors: JackCompilerError[] = []; diff --git a/simulator/src/jack/listener/global.symbol.listener.ts b/simulator/src/jack/listener/global.symbol.listener.ts index 1f0d000d..8a1bf5f8 100644 --- a/simulator/src/jack/listener/global.symbol.listener.ts +++ b/simulator/src/jack/listener/global.symbol.listener.ts @@ -2,16 +2,16 @@ import { ClassDeclarationContext, SubroutineDeclarationContext, VarNameInDeclarationContext, -} from "../generated/JackParser"; -import { ruleContextToSpan, DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error"; +} from "../generated/JackParser.js"; +import { ruleContextToSpan, DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error.js"; import { GenericSymbol, GlobalSymbolTable, SubroutineInfo, SubroutineType, -} from "../symbol"; -import { builtInSymbols } from "../builtins"; -import { JackParserListener } from "../generated/JackParserListener"; +} from "../symbol.js"; +import { builtInSymbols } from "../builtins.js"; +import { JackParserListener } from "../generated/JackParserListener.js"; /** * Creates global symbol table that contains built-in functions and found classes and subroutines diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 2f6696d6..774ef378 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -1,5 +1,5 @@ import { TerminalNode } from "antlr4ng"; -import { builtInTypes, intRange } from "../builtins"; +import { builtInTypes, intRange } from "../builtins.js"; import { ConstructorMushReturnThisError, DuplicatedVariableError, @@ -22,7 +22,7 @@ import { UnreachableCodeError, VoidSubroutineReturnsValueError, WrongLiteralTypeError, -} from "../error"; +} from "../error.js"; import { ClassDeclarationContext, ClassVarDecContext, @@ -43,15 +43,15 @@ import { VarNameInDeclarationContext, VarTypeContext, WhileStatementContext -} from "../generated/JackParser"; -import { JackParserListener } from "../generated/JackParserListener"; +} from "../generated/JackParser.js"; +import { JackParserListener } from "../generated/JackParserListener.js"; import { GenericSymbol, LocalSymbolTable, ScopeType, SubroutineType, -} from "../symbol"; -import { assertExists, CallType, getCallType } from "./common"; +} from "../symbol.js"; +import { assertExists, CallType, getCallType } from "./common.js"; /** * Validates Jack file */ diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index d8f80989..b1632816 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -1,4 +1,4 @@ -import { JackParserListener } from "../generated/JackParserListener"; +import { JackParserListener } from "../generated/JackParserListener.js"; import { ArrayAccessContext, ClassDeclarationContext, @@ -13,14 +13,14 @@ import { SubroutineDeclarationContext, WhileExpressionContext, WhileStatementContext, -} from "../generated/JackParser"; +} from "../generated/JackParser.js"; import { GenericSymbol, LocalSymbolTable, scopeTypeToString, VariableSymbol, -} from "../symbol"; -import { assertExists, CallType, getCallType } from "./common"; +} from "../symbol.js"; +import { assertExists, CallType, getCallType } from "./common.js"; const binaryOperationToVmCmd: Record = { "+": "add", From 4bcce0ab9632a5df64421eca3634109e5ca77893 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 20 Oct 2024 11:02:33 +0200 Subject: [PATCH 77/87] WIP --- simulator/src/jack/simulator.code-workspace | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 simulator/src/jack/simulator.code-workspace diff --git a/simulator/src/jack/simulator.code-workspace b/simulator/src/jack/simulator.code-workspace deleted file mode 100644 index ce26be06..00000000 --- a/simulator/src/jack/simulator.code-workspace +++ /dev/null @@ -1,11 +0,0 @@ -{ - "folders": [ - { - "path": "../.." - }, - { - "path": "../../../../nand2tetris-jack-lsp/jack-compiler" - } - ], - "settings": {} -} \ No newline at end of file From 8b71fdb2aa68474efffe0a699ad55dc9bbd86fa0 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 20 Oct 2024 11:05:11 +0200 Subject: [PATCH 78/87] WIP --- simulator/src/jack/README.md | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/simulator/src/jack/README.md b/simulator/src/jack/README.md index 5c58bba2..e361c257 100644 --- a/simulator/src/jack/README.md +++ b/simulator/src/jack/README.md @@ -22,20 +22,4 @@ Next command gives us ability to regenerate parser and lexer after we've changed ``` npm run gen -``` - -To run this command we would need to install [antlr-tools](https://github.com/antlr/antlr4-tools/blob/master/README.md). - -``` -pip install antlr4-tools -``` - -Underneath the covers previous command will install Java runtime(JRE)(if you don't have java installed on your machine) and antlr4-{version}-complete.jar from maven. - -Beside generating lexer and parser files this tools include `antlr4-parse` that you can use to parser an input jack file and visualize the AST tree or view the token stream in command line. - -Small note - If you are using VSCode there is an extension to work with ANTLR grammar files. - -# Working with typescript antlr runtime - -As ANTLR main target for web is Javascript it doesn't have a typescript source code in general sense. Basically typescript runtime is a collection of javascript files and `.d.ts` files to provide typescript types. If you want to find out what's going on underneath the covers go to [antlr github page](https://github.com/antlr/antlr4/tree/dev/runtime/JavaScript) and find the javascript sources. +``` \ No newline at end of file From b573d00a145b3620f01328a5c6500d23b3769de0 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 20 Oct 2024 11:05:46 +0200 Subject: [PATCH 79/87] WIP --- simulator/src/jack/README.md | 2 +- simulator/src/jack/anltr.compiler.ts | 9 +- simulator/src/jack/error.ts | 59 +- simulator/src/jack/generated/JackLexer.ts | 609 +- simulator/src/jack/generated/JackParser.ts | 6197 +++++++++-------- .../src/jack/generated/JackParserListener.ts | 881 +-- simulator/src/jack/listener/common.ts | 4 +- simulator/src/jack/listener/error.listener.ts | 28 +- .../jack/listener/global.symbol.listener.ts | 18 +- .../src/jack/listener/validator.listener.ts | 86 +- .../src/jack/listener/vm.writer.listener.ts | 20 +- simulator/src/jack/test.helper.ts | 8 +- 12 files changed, 4154 insertions(+), 3767 deletions(-) diff --git a/simulator/src/jack/README.md b/simulator/src/jack/README.md index e361c257..dbf3739c 100644 --- a/simulator/src/jack/README.md +++ b/simulator/src/jack/README.md @@ -22,4 +22,4 @@ Next command gives us ability to regenerate parser and lexer after we've changed ``` npm run gen -``` \ No newline at end of file +``` diff --git a/simulator/src/jack/anltr.compiler.ts b/simulator/src/jack/anltr.compiler.ts index dbcf52c8..e79554cf 100644 --- a/simulator/src/jack/anltr.compiler.ts +++ b/simulator/src/jack/anltr.compiler.ts @@ -1,4 +1,3 @@ - import { GlobalSymbolTableListener } from "./listener/global.symbol.listener.js"; import { CustomErrorListener } from "./listener/error.listener.js"; import { ValidatorListener } from "./listener/validator.listener.js"; @@ -110,7 +109,9 @@ export class JackCompiler { tree: ProgramContext, filename?: string, ): ProgramContext | JackCompilerError[] { - if (Object.keys(this.globalSymbolTableListener.globalSymbolTable).length == 0) { + if ( + Object.keys(this.globalSymbolTableListener.globalSymbolTable).length == 0 + ) { throw new Error( "Please populate global symbol table using parserAndBind method", ); @@ -134,7 +135,9 @@ export class JackCompiler { return errors; } const validateTree = treeOrErrors as ProgramContext; - const vmWriter = new VMWriter(this.globalSymbolTableListener.globalSymbolTable); + const vmWriter = new VMWriter( + this.globalSymbolTableListener.globalSymbolTable, + ); ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); return vmWriter.result; } diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index d01db93f..ca623f72 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -18,7 +18,7 @@ export const terminalNodeToSpan = (node: TerminalNode): Span => { export const ruleContextToSpan = (ctx: ParserRuleContext): Span => { const start = assertExists( ctx.start, - " Cannot find start token when creating an error" + " Cannot find start token when creating an error", ); return { line: start.line, @@ -59,7 +59,7 @@ export interface JackCompilerError { export function makeJackCompilerError( type: JackCompilerErrorType, span: Span, - msg: string + msg: string, ): JackCompilerError { return { type, @@ -72,83 +72,84 @@ export const ConstructorMushReturnThisError = (span: Span) => makeJackCompilerError( "ConstructorMushReturnThisError", span, - `A constructor must return 'this'` + `A constructor must return 'this'`, ); export const DuplicatedClassError = (span: Span, className: string) => makeJackCompilerError( "DuplicatedClassError", span, - `Class ${className} is already defined.` + `Class ${className} is already defined.`, ); export const DuplicatedSubroutineError = (span: Span, subroutineName: string) => makeJackCompilerError( "DuplicatedSubroutineError", span, - `Subroutine ${subroutineName} is already defined.` + `Subroutine ${subroutineName} is already defined.`, ); export const DuplicatedVariableError = (span: Span, variableName: string) => makeJackCompilerError( "DuplicatedVariableError", span, - `Duplicated local variable, field, argument or static variable ${variableName}` + `Duplicated local variable, field, argument or static variable ${variableName}`, ); export const FieldCantBeReferencedInFunctionError = (span: Span) => makeJackCompilerError( "FieldCantBeReferencedInFunctionError", span, - `Field can't be referenced in a function` + `Field can't be referenced in a function`, ); export const FilenameDoesntMatchClassNameError = ( span: Span, filename: string, - className: string + className: string, ) => makeJackCompilerError( "FilenameDoesntMatchClassNameError", span, - `Class name ${className} doesn't match file name ${filename}` + `Class name ${className} doesn't match file name ${filename}`, ); export const FunctionCalledAsMethodError = (span: Span, subroutineId: string) => makeJackCompilerError( "FunctionCalledAsMethodError", span, - `Function or constructor ${subroutineId} was called as a method` + `Function or constructor ${subroutineId} was called as a method`, ); export const IncorrectConstructorReturnTypeError = (span: Span) => makeJackCompilerError( "IncorrectConstructorReturnTypeError", span, - `The return type of a constructor must be of the class type` + `The return type of a constructor must be of the class type`, ); export const IncorrectParamsNumberInSubroutineCallError = ( span: Span, subroutineName: string, expectedParamsCount: number, - actualParamsCount: number + actualParamsCount: number, ) => makeJackCompilerError( "IncorrectParamsNumberInSubroutineCallError", span, - `Expected ${expectedParamsCount} arguments, but got ${actualParamsCount}`); + `Expected ${expectedParamsCount} arguments, but got ${actualParamsCount}`, + ); export const IntLiteralIsOutOfRangeError = ( span: Span, value: number, min: number, - max: number + max: number, ) => makeJackCompilerError( "IntLiteralIsOutOfRangeError", span, - `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}` + `Integer constant(${value}) is out of range. Min value is ${min} and max value is ${max}`, ); export const LexerOrParserError = (span: Span, msg: string) => @@ -158,56 +159,56 @@ export const MethodCalledAsFunctionError = (span: Span, subroutineId: string) => makeJackCompilerError( "MethodCalledAsFunctionError", span, - `Method ${subroutineId} was called as a function/constructor` + `Method ${subroutineId} was called as a function/constructor`, ); export const NonVoidFunctionNoReturnError = (span: Span) => makeJackCompilerError( "NonVoidFunctionNoReturnError", span, - `A non void subroutine must return a value` + `A non void subroutine must return a value`, ); export const SubroutineNotAllPathsReturnError = ( span: Span, - subroutineName: string + subroutineName: string, ) => makeJackCompilerError( "SubroutineNotAllPathsReturnError", span, - `Subroutine ${subroutineName}: not all code paths return a value` + `Subroutine ${subroutineName}: not all code paths return a value`, ); export const ThisCantBeReferencedInFunctionError = (span: Span) => makeJackCompilerError( "ThisCantBeReferencedInFunctionError", span, - `this can't be referenced in a function` + `this can't be referenced in a function`, ); export const UndeclaredVariableError = (span: Span, variableName: string) => makeJackCompilerError( "UndeclaredVariableError", span, - `Undeclared variable ${variableName}` + `Undeclared variable ${variableName}`, ); export const UnknownClassError = (span: Span, className: string) => makeJackCompilerError( "UnknownClassError", span, - `Class ${className} doesn't exist` + `Class ${className} doesn't exist`, ); export const UnknownSubroutineCallError = ( span: Span, subroutineName: string, - className?: string + className?: string, ) => makeJackCompilerError( "UnknownSubroutineCallError", span, - `Can't find subroutine '${subroutineName} in '${className ?? "(unknown)"}` + `Can't find subroutine '${subroutineName} in '${className ?? "(unknown)"}`, ); export const UnreachableCodeError = (span: Span) => @@ -217,12 +218,16 @@ export const VoidSubroutineReturnsValueError = (span: Span) => makeJackCompilerError( "VoidSubroutineReturnsValueError", span, - "Cannot return a value from a void subroutine" + "Cannot return a value from a void subroutine", ); -export const WrongLiteralTypeError = (span: Span, expectedTypeName: string, actualTypeName:string) => +export const WrongLiteralTypeError = ( + span: Span, + expectedTypeName: string, + actualTypeName: string, +) => makeJackCompilerError( "WrongLiteralTypeError", span, - `Cannot assign ${actualTypeName} type to ${expectedTypeName}` + `Cannot assign ${actualTypeName} type to ${expectedTypeName}`, ); diff --git a/simulator/src/jack/generated/JackLexer.ts b/simulator/src/jack/generated/JackLexer.ts index 27c7f43a..c0f50d70 100644 --- a/simulator/src/jack/generated/JackLexer.ts +++ b/simulator/src/jack/generated/JackLexer.ts @@ -3,236 +3,393 @@ import * as antlr from "antlr4ng"; import { Token } from "antlr4ng"; - export class JackLexer extends antlr.Lexer { - public static readonly CLASS = 1; - public static readonly CONSTRUCTOR = 2; - public static readonly FUNCTION = 3; - public static readonly METHOD = 4; - public static readonly FIELD = 5; - public static readonly STATIC = 6; - public static readonly VAR = 7; - public static readonly INT = 8; - public static readonly CHAR = 9; - public static readonly BOOLEAN = 10; - public static readonly VOID = 11; - public static readonly LET = 12; - public static readonly DO = 13; - public static readonly IF = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly RETURN = 17; - public static readonly LBRACE = 18; - public static readonly RBRACE = 19; - public static readonly LPAREN = 20; - public static readonly RPAREN = 21; - public static readonly LBRACKET = 22; - public static readonly RBRACKET = 23; - public static readonly DOT = 24; - public static readonly COMMA = 25; - public static readonly SEMICOLON = 26; - public static readonly EQUALS = 27; - public static readonly PLUS = 28; - public static readonly MINUS = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly AND = 32; - public static readonly OR = 33; - public static readonly TILDE = 34; - public static readonly LESS_THAN = 35; - public static readonly GREATER_THAN = 36; - public static readonly WHITESPACE = 37; - public static readonly BLOCK_COMMENT = 38; - public static readonly LINE_COMMENT = 39; - public static readonly INTEGER_LITERAL = 40; - public static readonly TRUE = 41; - public static readonly FALSE = 42; - public static readonly NULL_LITERAL = 43; - public static readonly THIS_LITERAL = 44; - public static readonly IDENTIFIER = 45; - public static readonly STRING_LITERAL = 46; - - public static readonly channelNames = [ - "DEFAULT_TOKEN_CHANNEL", "HIDDEN" - ]; - - public static readonly literalNames = [ - null, "'class'", "'constructor'", "'function'", "'method'", "'field'", - "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", - "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", - "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", - "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", null, null, null, null, - "'true'", "'false'", "'null'", "'this'" - ]; - - public static readonly symbolicNames = [ - null, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", - "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", - "WHILE", "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", - "RBRACKET", "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", - "MUL", "DIV", "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", - "WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT", "INTEGER_LITERAL", - "TRUE", "FALSE", "NULL_LITERAL", "THIS_LITERAL", "IDENTIFIER", "STRING_LITERAL" - ]; - - public static readonly modeNames = [ - "DEFAULT_MODE", - ]; - - public static readonly ruleNames = [ - "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", - "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", - "WHILE", "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", - "RBRACKET", "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", - "MUL", "DIV", "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", - "WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT", "INTEGER_LITERAL", - "TRUE", "FALSE", "NULL_LITERAL", "THIS_LITERAL", "IDENTIFIER", "STRING_LITERAL", - ]; - - - public constructor(input: antlr.CharStream) { - super(input); - this.interpreter = new antlr.LexerATNSimulator(this, JackLexer._ATN, JackLexer.decisionsToDFA, new antlr.PredictionContextCache()); - } + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WHITESPACE = 37; + public static readonly BLOCK_COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly TRUE = 41; + public static readonly FALSE = 42; + public static readonly NULL_LITERAL = 43; + public static readonly THIS_LITERAL = 44; + public static readonly IDENTIFIER = 45; + public static readonly STRING_LITERAL = 46; - public get grammarFileName(): string { return "JackLexer.g4"; } - - public get literalNames(): (string | null)[] { return JackLexer.literalNames; } - public get symbolicNames(): (string | null)[] { return JackLexer.symbolicNames; } - public get ruleNames(): string[] { return JackLexer.ruleNames; } - - public get serializedATN(): number[] { return JackLexer._serializedATN; } - - public get channelNames(): string[] { return JackLexer.channelNames; } - - public get modeNames(): string[] { return JackLexer.modeNames; } - - public static readonly _serializedATN: number[] = [ - 4,0,46,308,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5, - 2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2, - 13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7, - 19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2, - 26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7, - 32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2, - 39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7, - 45,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1, - 3,1,3,1,3,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1, - 6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1, - 9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,11,1,11,1,11,1,11,1, - 12,1,12,1,12,1,13,1,13,1,13,1,14,1,14,1,14,1,14,1,14,1,15,1,15,1, - 15,1,15,1,15,1,15,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1, - 18,1,18,1,19,1,19,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,24,1, - 24,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,1,30,1, - 31,1,31,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,36,4,36,234,8, - 36,11,36,12,36,235,1,36,1,36,1,37,1,37,1,37,1,37,5,37,244,8,37,10, - 37,12,37,247,9,37,1,37,1,37,1,37,3,37,252,8,37,1,37,1,37,1,38,1, - 38,1,38,1,38,5,38,260,8,38,10,38,12,38,263,9,38,1,38,1,38,1,39,4, - 39,268,8,39,11,39,12,39,269,1,40,1,40,1,40,1,40,1,40,1,41,1,41,1, - 41,1,41,1,41,1,41,1,42,1,42,1,42,1,42,1,42,1,43,1,43,1,43,1,43,1, - 43,1,44,1,44,5,44,295,8,44,10,44,12,44,298,9,44,1,45,1,45,5,45,302, - 8,45,10,45,12,45,305,9,45,1,45,1,45,1,245,0,46,1,1,3,2,5,3,7,4,9, - 5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27,14,29,15,31,16, - 33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27, - 55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,71,36,73,37,75,38, - 77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,46,1,0,6,3,0,9,10,12, - 13,32,32,2,0,10,10,13,13,1,0,48,57,3,0,65,90,95,95,97,122,4,0,48, - 57,65,90,95,95,97,122,3,0,10,10,13,13,34,34,314,0,1,1,0,0,0,0,3, - 1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1, - 0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1, - 0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1, - 0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1, - 0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1, - 0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1, - 0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1, - 0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1, - 0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0,1,93,1, - 0,0,0,3,99,1,0,0,0,5,111,1,0,0,0,7,120,1,0,0,0,9,127,1,0,0,0,11, - 133,1,0,0,0,13,140,1,0,0,0,15,144,1,0,0,0,17,148,1,0,0,0,19,153, - 1,0,0,0,21,161,1,0,0,0,23,166,1,0,0,0,25,170,1,0,0,0,27,173,1,0, - 0,0,29,176,1,0,0,0,31,181,1,0,0,0,33,187,1,0,0,0,35,194,1,0,0,0, - 37,196,1,0,0,0,39,198,1,0,0,0,41,200,1,0,0,0,43,202,1,0,0,0,45,204, - 1,0,0,0,47,206,1,0,0,0,49,208,1,0,0,0,51,210,1,0,0,0,53,212,1,0, - 0,0,55,214,1,0,0,0,57,216,1,0,0,0,59,218,1,0,0,0,61,220,1,0,0,0, - 63,222,1,0,0,0,65,224,1,0,0,0,67,226,1,0,0,0,69,228,1,0,0,0,71,230, - 1,0,0,0,73,233,1,0,0,0,75,239,1,0,0,0,77,255,1,0,0,0,79,267,1,0, - 0,0,81,271,1,0,0,0,83,276,1,0,0,0,85,282,1,0,0,0,87,287,1,0,0,0, - 89,292,1,0,0,0,91,299,1,0,0,0,93,94,5,99,0,0,94,95,5,108,0,0,95, - 96,5,97,0,0,96,97,5,115,0,0,97,98,5,115,0,0,98,2,1,0,0,0,99,100, - 5,99,0,0,100,101,5,111,0,0,101,102,5,110,0,0,102,103,5,115,0,0,103, - 104,5,116,0,0,104,105,5,114,0,0,105,106,5,117,0,0,106,107,5,99,0, - 0,107,108,5,116,0,0,108,109,5,111,0,0,109,110,5,114,0,0,110,4,1, - 0,0,0,111,112,5,102,0,0,112,113,5,117,0,0,113,114,5,110,0,0,114, - 115,5,99,0,0,115,116,5,116,0,0,116,117,5,105,0,0,117,118,5,111,0, - 0,118,119,5,110,0,0,119,6,1,0,0,0,120,121,5,109,0,0,121,122,5,101, - 0,0,122,123,5,116,0,0,123,124,5,104,0,0,124,125,5,111,0,0,125,126, - 5,100,0,0,126,8,1,0,0,0,127,128,5,102,0,0,128,129,5,105,0,0,129, - 130,5,101,0,0,130,131,5,108,0,0,131,132,5,100,0,0,132,10,1,0,0,0, - 133,134,5,115,0,0,134,135,5,116,0,0,135,136,5,97,0,0,136,137,5,116, - 0,0,137,138,5,105,0,0,138,139,5,99,0,0,139,12,1,0,0,0,140,141,5, - 118,0,0,141,142,5,97,0,0,142,143,5,114,0,0,143,14,1,0,0,0,144,145, - 5,105,0,0,145,146,5,110,0,0,146,147,5,116,0,0,147,16,1,0,0,0,148, - 149,5,99,0,0,149,150,5,104,0,0,150,151,5,97,0,0,151,152,5,114,0, - 0,152,18,1,0,0,0,153,154,5,98,0,0,154,155,5,111,0,0,155,156,5,111, - 0,0,156,157,5,108,0,0,157,158,5,101,0,0,158,159,5,97,0,0,159,160, - 5,110,0,0,160,20,1,0,0,0,161,162,5,118,0,0,162,163,5,111,0,0,163, - 164,5,105,0,0,164,165,5,100,0,0,165,22,1,0,0,0,166,167,5,108,0,0, - 167,168,5,101,0,0,168,169,5,116,0,0,169,24,1,0,0,0,170,171,5,100, - 0,0,171,172,5,111,0,0,172,26,1,0,0,0,173,174,5,105,0,0,174,175,5, - 102,0,0,175,28,1,0,0,0,176,177,5,101,0,0,177,178,5,108,0,0,178,179, - 5,115,0,0,179,180,5,101,0,0,180,30,1,0,0,0,181,182,5,119,0,0,182, - 183,5,104,0,0,183,184,5,105,0,0,184,185,5,108,0,0,185,186,5,101, - 0,0,186,32,1,0,0,0,187,188,5,114,0,0,188,189,5,101,0,0,189,190,5, - 116,0,0,190,191,5,117,0,0,191,192,5,114,0,0,192,193,5,110,0,0,193, - 34,1,0,0,0,194,195,5,123,0,0,195,36,1,0,0,0,196,197,5,125,0,0,197, - 38,1,0,0,0,198,199,5,40,0,0,199,40,1,0,0,0,200,201,5,41,0,0,201, - 42,1,0,0,0,202,203,5,91,0,0,203,44,1,0,0,0,204,205,5,93,0,0,205, - 46,1,0,0,0,206,207,5,46,0,0,207,48,1,0,0,0,208,209,5,44,0,0,209, - 50,1,0,0,0,210,211,5,59,0,0,211,52,1,0,0,0,212,213,5,61,0,0,213, - 54,1,0,0,0,214,215,5,43,0,0,215,56,1,0,0,0,216,217,5,45,0,0,217, - 58,1,0,0,0,218,219,5,42,0,0,219,60,1,0,0,0,220,221,5,47,0,0,221, - 62,1,0,0,0,222,223,5,38,0,0,223,64,1,0,0,0,224,225,5,124,0,0,225, - 66,1,0,0,0,226,227,5,126,0,0,227,68,1,0,0,0,228,229,5,60,0,0,229, - 70,1,0,0,0,230,231,5,62,0,0,231,72,1,0,0,0,232,234,7,0,0,0,233,232, - 1,0,0,0,234,235,1,0,0,0,235,233,1,0,0,0,235,236,1,0,0,0,236,237, - 1,0,0,0,237,238,6,36,0,0,238,74,1,0,0,0,239,240,5,47,0,0,240,241, - 5,42,0,0,241,245,1,0,0,0,242,244,9,0,0,0,243,242,1,0,0,0,244,247, - 1,0,0,0,245,246,1,0,0,0,245,243,1,0,0,0,246,251,1,0,0,0,247,245, - 1,0,0,0,248,249,5,42,0,0,249,252,5,47,0,0,250,252,5,0,0,1,251,248, - 1,0,0,0,251,250,1,0,0,0,252,253,1,0,0,0,253,254,6,37,0,0,254,76, - 1,0,0,0,255,256,5,47,0,0,256,257,5,47,0,0,257,261,1,0,0,0,258,260, - 8,1,0,0,259,258,1,0,0,0,260,263,1,0,0,0,261,259,1,0,0,0,261,262, - 1,0,0,0,262,264,1,0,0,0,263,261,1,0,0,0,264,265,6,38,0,0,265,78, - 1,0,0,0,266,268,7,2,0,0,267,266,1,0,0,0,268,269,1,0,0,0,269,267, - 1,0,0,0,269,270,1,0,0,0,270,80,1,0,0,0,271,272,5,116,0,0,272,273, - 5,114,0,0,273,274,5,117,0,0,274,275,5,101,0,0,275,82,1,0,0,0,276, - 277,5,102,0,0,277,278,5,97,0,0,278,279,5,108,0,0,279,280,5,115,0, - 0,280,281,5,101,0,0,281,84,1,0,0,0,282,283,5,110,0,0,283,284,5,117, - 0,0,284,285,5,108,0,0,285,286,5,108,0,0,286,86,1,0,0,0,287,288,5, - 116,0,0,288,289,5,104,0,0,289,290,5,105,0,0,290,291,5,115,0,0,291, - 88,1,0,0,0,292,296,7,3,0,0,293,295,7,4,0,0,294,293,1,0,0,0,295,298, - 1,0,0,0,296,294,1,0,0,0,296,297,1,0,0,0,297,90,1,0,0,0,298,296,1, - 0,0,0,299,303,5,34,0,0,300,302,8,5,0,0,301,300,1,0,0,0,302,305,1, - 0,0,0,303,301,1,0,0,0,303,304,1,0,0,0,304,306,1,0,0,0,305,303,1, - 0,0,0,306,307,5,34,0,0,307,92,1,0,0,0,8,0,235,245,251,261,269,296, - 303,1,0,1,0 - ]; - - private static __ATN: antlr.ATN; - public static get _ATN(): antlr.ATN { - if (!JackLexer.__ATN) { - JackLexer.__ATN = new antlr.ATNDeserializer().deserialize(JackLexer._serializedATN); - } - - return JackLexer.__ATN; - } + public static readonly channelNames = ["DEFAULT_TOKEN_CHANNEL", "HIDDEN"]; + + public static readonly literalNames = [ + null, + "'class'", + "'constructor'", + "'function'", + "'method'", + "'field'", + "'static'", + "'var'", + "'int'", + "'char'", + "'boolean'", + "'void'", + "'let'", + "'do'", + "'if'", + "'else'", + "'while'", + "'return'", + "'{'", + "'}'", + "'('", + "')'", + "'['", + "']'", + "'.'", + "','", + "';'", + "'='", + "'+'", + "'-'", + "'*'", + "'/'", + "'&'", + "'|'", + "'~'", + "'<'", + "'>'", + null, + null, + null, + null, + "'true'", + "'false'", + "'null'", + "'this'", + ]; + + public static readonly symbolicNames = [ + null, + "CLASS", + "CONSTRUCTOR", + "FUNCTION", + "METHOD", + "FIELD", + "STATIC", + "VAR", + "INT", + "CHAR", + "BOOLEAN", + "VOID", + "LET", + "DO", + "IF", + "ELSE", + "WHILE", + "RETURN", + "LBRACE", + "RBRACE", + "LPAREN", + "RPAREN", + "LBRACKET", + "RBRACKET", + "DOT", + "COMMA", + "SEMICOLON", + "EQUALS", + "PLUS", + "MINUS", + "MUL", + "DIV", + "AND", + "OR", + "TILDE", + "LESS_THAN", + "GREATER_THAN", + "WHITESPACE", + "BLOCK_COMMENT", + "LINE_COMMENT", + "INTEGER_LITERAL", + "TRUE", + "FALSE", + "NULL_LITERAL", + "THIS_LITERAL", + "IDENTIFIER", + "STRING_LITERAL", + ]; + + public static readonly modeNames = ["DEFAULT_MODE"]; + + public static readonly ruleNames = [ + "CLASS", + "CONSTRUCTOR", + "FUNCTION", + "METHOD", + "FIELD", + "STATIC", + "VAR", + "INT", + "CHAR", + "BOOLEAN", + "VOID", + "LET", + "DO", + "IF", + "ELSE", + "WHILE", + "RETURN", + "LBRACE", + "RBRACE", + "LPAREN", + "RPAREN", + "LBRACKET", + "RBRACKET", + "DOT", + "COMMA", + "SEMICOLON", + "EQUALS", + "PLUS", + "MINUS", + "MUL", + "DIV", + "AND", + "OR", + "TILDE", + "LESS_THAN", + "GREATER_THAN", + "WHITESPACE", + "BLOCK_COMMENT", + "LINE_COMMENT", + "INTEGER_LITERAL", + "TRUE", + "FALSE", + "NULL_LITERAL", + "THIS_LITERAL", + "IDENTIFIER", + "STRING_LITERAL", + ]; + + public constructor(input: antlr.CharStream) { + super(input); + this.interpreter = new antlr.LexerATNSimulator( + this, + JackLexer._ATN, + JackLexer.decisionsToDFA, + new antlr.PredictionContextCache(), + ); + } + public get grammarFileName(): string { + return "JackLexer.g4"; + } - private static readonly vocabulary = new antlr.Vocabulary(JackLexer.literalNames, JackLexer.symbolicNames, []); + public get literalNames(): (string | null)[] { + return JackLexer.literalNames; + } + public get symbolicNames(): (string | null)[] { + return JackLexer.symbolicNames; + } + public get ruleNames(): string[] { + return JackLexer.ruleNames; + } - public override get vocabulary(): antlr.Vocabulary { - return JackLexer.vocabulary; + public get serializedATN(): number[] { + return JackLexer._serializedATN; + } + + public get channelNames(): string[] { + return JackLexer.channelNames; + } + + public get modeNames(): string[] { + return JackLexer.modeNames; + } + + public static readonly _serializedATN: number[] = [ + 4, 0, 46, 308, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, + 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, + 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, + 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, + 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, + 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, + 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, + 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, + 43, 2, 44, 7, 44, 2, 45, 7, 45, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, + 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, + 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, + 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, + 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, + 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, + 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, + 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, + 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, + 1, 23, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 28, 1, 28, + 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, + 1, 34, 1, 35, 1, 35, 1, 36, 4, 36, 234, 8, 36, 11, 36, 12, 36, 235, 1, 36, + 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 244, 8, 37, 10, 37, 12, 37, 247, + 9, 37, 1, 37, 1, 37, 1, 37, 3, 37, 252, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, + 1, 38, 1, 38, 5, 38, 260, 8, 38, 10, 38, 12, 38, 263, 9, 38, 1, 38, 1, 38, + 1, 39, 4, 39, 268, 8, 39, 11, 39, 12, 39, 269, 1, 40, 1, 40, 1, 40, 1, 40, + 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, + 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 5, 44, 295, 8, 44, + 10, 44, 12, 44, 298, 9, 44, 1, 45, 1, 45, 5, 45, 302, 8, 45, 10, 45, 12, 45, + 305, 9, 45, 1, 45, 1, 45, 1, 245, 0, 46, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, + 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, + 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, + 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, + 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, + 89, 45, 91, 46, 1, 0, 6, 3, 0, 9, 10, 12, 13, 32, 32, 2, 0, 10, 10, 13, 13, + 1, 0, 48, 57, 3, 0, 65, 90, 95, 95, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, + 97, 122, 3, 0, 10, 10, 13, 13, 34, 34, 314, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, + 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, + 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, + 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, + 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, + 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, + 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, + 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, + 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, + 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, + 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, + 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, + 1, 93, 1, 0, 0, 0, 3, 99, 1, 0, 0, 0, 5, 111, 1, 0, 0, 0, 7, 120, 1, 0, 0, + 0, 9, 127, 1, 0, 0, 0, 11, 133, 1, 0, 0, 0, 13, 140, 1, 0, 0, 0, 15, 144, 1, + 0, 0, 0, 17, 148, 1, 0, 0, 0, 19, 153, 1, 0, 0, 0, 21, 161, 1, 0, 0, 0, 23, + 166, 1, 0, 0, 0, 25, 170, 1, 0, 0, 0, 27, 173, 1, 0, 0, 0, 29, 176, 1, 0, 0, + 0, 31, 181, 1, 0, 0, 0, 33, 187, 1, 0, 0, 0, 35, 194, 1, 0, 0, 0, 37, 196, + 1, 0, 0, 0, 39, 198, 1, 0, 0, 0, 41, 200, 1, 0, 0, 0, 43, 202, 1, 0, 0, 0, + 45, 204, 1, 0, 0, 0, 47, 206, 1, 0, 0, 0, 49, 208, 1, 0, 0, 0, 51, 210, 1, + 0, 0, 0, 53, 212, 1, 0, 0, 0, 55, 214, 1, 0, 0, 0, 57, 216, 1, 0, 0, 0, 59, + 218, 1, 0, 0, 0, 61, 220, 1, 0, 0, 0, 63, 222, 1, 0, 0, 0, 65, 224, 1, 0, 0, + 0, 67, 226, 1, 0, 0, 0, 69, 228, 1, 0, 0, 0, 71, 230, 1, 0, 0, 0, 73, 233, + 1, 0, 0, 0, 75, 239, 1, 0, 0, 0, 77, 255, 1, 0, 0, 0, 79, 267, 1, 0, 0, 0, + 81, 271, 1, 0, 0, 0, 83, 276, 1, 0, 0, 0, 85, 282, 1, 0, 0, 0, 87, 287, 1, + 0, 0, 0, 89, 292, 1, 0, 0, 0, 91, 299, 1, 0, 0, 0, 93, 94, 5, 99, 0, 0, 94, + 95, 5, 108, 0, 0, 95, 96, 5, 97, 0, 0, 96, 97, 5, 115, 0, 0, 97, 98, 5, 115, + 0, 0, 98, 2, 1, 0, 0, 0, 99, 100, 5, 99, 0, 0, 100, 101, 5, 111, 0, 0, 101, + 102, 5, 110, 0, 0, 102, 103, 5, 115, 0, 0, 103, 104, 5, 116, 0, 0, 104, 105, + 5, 114, 0, 0, 105, 106, 5, 117, 0, 0, 106, 107, 5, 99, 0, 0, 107, 108, 5, + 116, 0, 0, 108, 109, 5, 111, 0, 0, 109, 110, 5, 114, 0, 0, 110, 4, 1, 0, 0, + 0, 111, 112, 5, 102, 0, 0, 112, 113, 5, 117, 0, 0, 113, 114, 5, 110, 0, 0, + 114, 115, 5, 99, 0, 0, 115, 116, 5, 116, 0, 0, 116, 117, 5, 105, 0, 0, 117, + 118, 5, 111, 0, 0, 118, 119, 5, 110, 0, 0, 119, 6, 1, 0, 0, 0, 120, 121, 5, + 109, 0, 0, 121, 122, 5, 101, 0, 0, 122, 123, 5, 116, 0, 0, 123, 124, 5, 104, + 0, 0, 124, 125, 5, 111, 0, 0, 125, 126, 5, 100, 0, 0, 126, 8, 1, 0, 0, 0, + 127, 128, 5, 102, 0, 0, 128, 129, 5, 105, 0, 0, 129, 130, 5, 101, 0, 0, 130, + 131, 5, 108, 0, 0, 131, 132, 5, 100, 0, 0, 132, 10, 1, 0, 0, 0, 133, 134, 5, + 115, 0, 0, 134, 135, 5, 116, 0, 0, 135, 136, 5, 97, 0, 0, 136, 137, 5, 116, + 0, 0, 137, 138, 5, 105, 0, 0, 138, 139, 5, 99, 0, 0, 139, 12, 1, 0, 0, 0, + 140, 141, 5, 118, 0, 0, 141, 142, 5, 97, 0, 0, 142, 143, 5, 114, 0, 0, 143, + 14, 1, 0, 0, 0, 144, 145, 5, 105, 0, 0, 145, 146, 5, 110, 0, 0, 146, 147, 5, + 116, 0, 0, 147, 16, 1, 0, 0, 0, 148, 149, 5, 99, 0, 0, 149, 150, 5, 104, 0, + 0, 150, 151, 5, 97, 0, 0, 151, 152, 5, 114, 0, 0, 152, 18, 1, 0, 0, 0, 153, + 154, 5, 98, 0, 0, 154, 155, 5, 111, 0, 0, 155, 156, 5, 111, 0, 0, 156, 157, + 5, 108, 0, 0, 157, 158, 5, 101, 0, 0, 158, 159, 5, 97, 0, 0, 159, 160, 5, + 110, 0, 0, 160, 20, 1, 0, 0, 0, 161, 162, 5, 118, 0, 0, 162, 163, 5, 111, 0, + 0, 163, 164, 5, 105, 0, 0, 164, 165, 5, 100, 0, 0, 165, 22, 1, 0, 0, 0, 166, + 167, 5, 108, 0, 0, 167, 168, 5, 101, 0, 0, 168, 169, 5, 116, 0, 0, 169, 24, + 1, 0, 0, 0, 170, 171, 5, 100, 0, 0, 171, 172, 5, 111, 0, 0, 172, 26, 1, 0, + 0, 0, 173, 174, 5, 105, 0, 0, 174, 175, 5, 102, 0, 0, 175, 28, 1, 0, 0, 0, + 176, 177, 5, 101, 0, 0, 177, 178, 5, 108, 0, 0, 178, 179, 5, 115, 0, 0, 179, + 180, 5, 101, 0, 0, 180, 30, 1, 0, 0, 0, 181, 182, 5, 119, 0, 0, 182, 183, 5, + 104, 0, 0, 183, 184, 5, 105, 0, 0, 184, 185, 5, 108, 0, 0, 185, 186, 5, 101, + 0, 0, 186, 32, 1, 0, 0, 0, 187, 188, 5, 114, 0, 0, 188, 189, 5, 101, 0, 0, + 189, 190, 5, 116, 0, 0, 190, 191, 5, 117, 0, 0, 191, 192, 5, 114, 0, 0, 192, + 193, 5, 110, 0, 0, 193, 34, 1, 0, 0, 0, 194, 195, 5, 123, 0, 0, 195, 36, 1, + 0, 0, 0, 196, 197, 5, 125, 0, 0, 197, 38, 1, 0, 0, 0, 198, 199, 5, 40, 0, 0, + 199, 40, 1, 0, 0, 0, 200, 201, 5, 41, 0, 0, 201, 42, 1, 0, 0, 0, 202, 203, + 5, 91, 0, 0, 203, 44, 1, 0, 0, 0, 204, 205, 5, 93, 0, 0, 205, 46, 1, 0, 0, + 0, 206, 207, 5, 46, 0, 0, 207, 48, 1, 0, 0, 0, 208, 209, 5, 44, 0, 0, 209, + 50, 1, 0, 0, 0, 210, 211, 5, 59, 0, 0, 211, 52, 1, 0, 0, 0, 212, 213, 5, 61, + 0, 0, 213, 54, 1, 0, 0, 0, 214, 215, 5, 43, 0, 0, 215, 56, 1, 0, 0, 0, 216, + 217, 5, 45, 0, 0, 217, 58, 1, 0, 0, 0, 218, 219, 5, 42, 0, 0, 219, 60, 1, 0, + 0, 0, 220, 221, 5, 47, 0, 0, 221, 62, 1, 0, 0, 0, 222, 223, 5, 38, 0, 0, + 223, 64, 1, 0, 0, 0, 224, 225, 5, 124, 0, 0, 225, 66, 1, 0, 0, 0, 226, 227, + 5, 126, 0, 0, 227, 68, 1, 0, 0, 0, 228, 229, 5, 60, 0, 0, 229, 70, 1, 0, 0, + 0, 230, 231, 5, 62, 0, 0, 231, 72, 1, 0, 0, 0, 232, 234, 7, 0, 0, 0, 233, + 232, 1, 0, 0, 0, 234, 235, 1, 0, 0, 0, 235, 233, 1, 0, 0, 0, 235, 236, 1, 0, + 0, 0, 236, 237, 1, 0, 0, 0, 237, 238, 6, 36, 0, 0, 238, 74, 1, 0, 0, 0, 239, + 240, 5, 47, 0, 0, 240, 241, 5, 42, 0, 0, 241, 245, 1, 0, 0, 0, 242, 244, 9, + 0, 0, 0, 243, 242, 1, 0, 0, 0, 244, 247, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, + 245, 243, 1, 0, 0, 0, 246, 251, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 248, 249, + 5, 42, 0, 0, 249, 252, 5, 47, 0, 0, 250, 252, 5, 0, 0, 1, 251, 248, 1, 0, 0, + 0, 251, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 6, 37, 0, 0, 254, + 76, 1, 0, 0, 0, 255, 256, 5, 47, 0, 0, 256, 257, 5, 47, 0, 0, 257, 261, 1, + 0, 0, 0, 258, 260, 8, 1, 0, 0, 259, 258, 1, 0, 0, 0, 260, 263, 1, 0, 0, 0, + 261, 259, 1, 0, 0, 0, 261, 262, 1, 0, 0, 0, 262, 264, 1, 0, 0, 0, 263, 261, + 1, 0, 0, 0, 264, 265, 6, 38, 0, 0, 265, 78, 1, 0, 0, 0, 266, 268, 7, 2, 0, + 0, 267, 266, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 269, + 270, 1, 0, 0, 0, 270, 80, 1, 0, 0, 0, 271, 272, 5, 116, 0, 0, 272, 273, 5, + 114, 0, 0, 273, 274, 5, 117, 0, 0, 274, 275, 5, 101, 0, 0, 275, 82, 1, 0, 0, + 0, 276, 277, 5, 102, 0, 0, 277, 278, 5, 97, 0, 0, 278, 279, 5, 108, 0, 0, + 279, 280, 5, 115, 0, 0, 280, 281, 5, 101, 0, 0, 281, 84, 1, 0, 0, 0, 282, + 283, 5, 110, 0, 0, 283, 284, 5, 117, 0, 0, 284, 285, 5, 108, 0, 0, 285, 286, + 5, 108, 0, 0, 286, 86, 1, 0, 0, 0, 287, 288, 5, 116, 0, 0, 288, 289, 5, 104, + 0, 0, 289, 290, 5, 105, 0, 0, 290, 291, 5, 115, 0, 0, 291, 88, 1, 0, 0, 0, + 292, 296, 7, 3, 0, 0, 293, 295, 7, 4, 0, 0, 294, 293, 1, 0, 0, 0, 295, 298, + 1, 0, 0, 0, 296, 294, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 90, 1, 0, 0, 0, + 298, 296, 1, 0, 0, 0, 299, 303, 5, 34, 0, 0, 300, 302, 8, 5, 0, 0, 301, 300, + 1, 0, 0, 0, 302, 305, 1, 0, 0, 0, 303, 301, 1, 0, 0, 0, 303, 304, 1, 0, 0, + 0, 304, 306, 1, 0, 0, 0, 305, 303, 1, 0, 0, 0, 306, 307, 5, 34, 0, 0, 307, + 92, 1, 0, 0, 0, 8, 0, 235, 245, 251, 261, 269, 296, 303, 1, 0, 1, 0, + ]; + + private static __ATN: antlr.ATN; + public static get _ATN(): antlr.ATN { + if (!JackLexer.__ATN) { + JackLexer.__ATN = new antlr.ATNDeserializer().deserialize( + JackLexer._serializedATN, + ); } - private static readonly decisionsToDFA = JackLexer._ATN.decisionToState.map( (ds: antlr.DecisionState, index: number) => new antlr.DFA(ds, index) ); -} \ No newline at end of file + return JackLexer.__ATN; + } + + private static readonly vocabulary = new antlr.Vocabulary( + JackLexer.literalNames, + JackLexer.symbolicNames, + [], + ); + + public override get vocabulary(): antlr.Vocabulary { + return JackLexer.vocabulary; + } + + private static readonly decisionsToDFA = JackLexer._ATN.decisionToState.map( + (ds: antlr.DecisionState, index: number) => new antlr.DFA(ds, index), + ); +} diff --git a/simulator/src/jack/generated/JackParser.ts b/simulator/src/jack/generated/JackParser.ts index f5ac7517..83b10646 100644 --- a/simulator/src/jack/generated/JackParser.ts +++ b/simulator/src/jack/generated/JackParser.ts @@ -8,3154 +8,3369 @@ import { JackParserListener } from "./JackParserListener.js"; // eslint-disable-next-line no-unused-vars type int = number; - import { SubroutineScope, LocalSymbolTable } from "../symbol.js"; - export class JackParser extends antlr.Parser { - public static readonly CLASS = 1; - public static readonly CONSTRUCTOR = 2; - public static readonly FUNCTION = 3; - public static readonly METHOD = 4; - public static readonly FIELD = 5; - public static readonly STATIC = 6; - public static readonly VAR = 7; - public static readonly INT = 8; - public static readonly CHAR = 9; - public static readonly BOOLEAN = 10; - public static readonly VOID = 11; - public static readonly LET = 12; - public static readonly DO = 13; - public static readonly IF = 14; - public static readonly ELSE = 15; - public static readonly WHILE = 16; - public static readonly RETURN = 17; - public static readonly LBRACE = 18; - public static readonly RBRACE = 19; - public static readonly LPAREN = 20; - public static readonly RPAREN = 21; - public static readonly LBRACKET = 22; - public static readonly RBRACKET = 23; - public static readonly DOT = 24; - public static readonly COMMA = 25; - public static readonly SEMICOLON = 26; - public static readonly EQUALS = 27; - public static readonly PLUS = 28; - public static readonly MINUS = 29; - public static readonly MUL = 30; - public static readonly DIV = 31; - public static readonly AND = 32; - public static readonly OR = 33; - public static readonly TILDE = 34; - public static readonly LESS_THAN = 35; - public static readonly GREATER_THAN = 36; - public static readonly WHITESPACE = 37; - public static readonly BLOCK_COMMENT = 38; - public static readonly LINE_COMMENT = 39; - public static readonly INTEGER_LITERAL = 40; - public static readonly TRUE = 41; - public static readonly FALSE = 42; - public static readonly NULL_LITERAL = 43; - public static readonly THIS_LITERAL = 44; - public static readonly IDENTIFIER = 45; - public static readonly STRING_LITERAL = 46; - public static readonly RULE_program = 0; - public static readonly RULE_classDeclaration = 1; - public static readonly RULE_className = 2; - public static readonly RULE_classVarDec = 3; - public static readonly RULE_fieldList = 4; - public static readonly RULE_fieldName = 5; - public static readonly RULE_subroutineDeclaration = 6; - public static readonly RULE_subroutineType = 7; - public static readonly RULE_subroutineDecWithoutType = 8; - public static readonly RULE_subroutineName = 9; - public static readonly RULE_subroutineReturnType = 10; - public static readonly RULE_varType = 11; - public static readonly RULE_parameterList = 12; - public static readonly RULE_parameter = 13; - public static readonly RULE_parameterName = 14; - public static readonly RULE_subroutineBody = 15; - public static readonly RULE_rBrace = 16; - public static readonly RULE_varDeclaration = 17; - public static readonly RULE_varNameInDeclaration = 18; - public static readonly RULE_statements = 19; - public static readonly RULE_statement = 20; - public static readonly RULE_letStatement = 21; - public static readonly RULE_equals = 22; - public static readonly RULE_ifElseStatement = 23; - public static readonly RULE_ifStatement = 24; - public static readonly RULE_ifExpression = 25; - public static readonly RULE_elseStatement = 26; - public static readonly RULE_whileStatement = 27; - public static readonly RULE_whileExpression = 28; - public static readonly RULE_doStatement = 29; - public static readonly RULE_subroutineCall = 30; - public static readonly RULE_subroutineId = 31; - public static readonly RULE_returnStatement = 32; - public static readonly RULE_expressionList = 33; - public static readonly RULE_expression = 34; - public static readonly RULE_constant = 35; - public static readonly RULE_varName = 36; - public static readonly RULE_arrayAccess = 37; - public static readonly RULE_unaryOperation = 38; - public static readonly RULE_groupedExpression = 39; - public static readonly RULE_booleanLiteral = 40; - public static readonly RULE_unaryOperator = 41; - public static readonly RULE_binaryOperator = 42; - - public static readonly literalNames = [ - null, "'class'", "'constructor'", "'function'", "'method'", "'field'", - "'static'", "'var'", "'int'", "'char'", "'boolean'", "'void'", "'let'", - "'do'", "'if'", "'else'", "'while'", "'return'", "'{'", "'}'", "'('", - "')'", "'['", "']'", "'.'", "','", "';'", "'='", "'+'", "'-'", "'*'", - "'/'", "'&'", "'|'", "'~'", "'<'", "'>'", null, null, null, null, - "'true'", "'false'", "'null'", "'this'" - ]; - - public static readonly symbolicNames = [ - null, "CLASS", "CONSTRUCTOR", "FUNCTION", "METHOD", "FIELD", "STATIC", - "VAR", "INT", "CHAR", "BOOLEAN", "VOID", "LET", "DO", "IF", "ELSE", - "WHILE", "RETURN", "LBRACE", "RBRACE", "LPAREN", "RPAREN", "LBRACKET", - "RBRACKET", "DOT", "COMMA", "SEMICOLON", "EQUALS", "PLUS", "MINUS", - "MUL", "DIV", "AND", "OR", "TILDE", "LESS_THAN", "GREATER_THAN", - "WHITESPACE", "BLOCK_COMMENT", "LINE_COMMENT", "INTEGER_LITERAL", - "TRUE", "FALSE", "NULL_LITERAL", "THIS_LITERAL", "IDENTIFIER", "STRING_LITERAL" - ]; - public static readonly ruleNames = [ - "program", "classDeclaration", "className", "classVarDec", "fieldList", - "fieldName", "subroutineDeclaration", "subroutineType", "subroutineDecWithoutType", - "subroutineName", "subroutineReturnType", "varType", "parameterList", - "parameter", "parameterName", "subroutineBody", "rBrace", "varDeclaration", - "varNameInDeclaration", "statements", "statement", "letStatement", - "equals", "ifElseStatement", "ifStatement", "ifExpression", "elseStatement", - "whileStatement", "whileExpression", "doStatement", "subroutineCall", - "subroutineId", "returnStatement", "expressionList", "expression", - "constant", "varName", "arrayAccess", "unaryOperation", "groupedExpression", - "booleanLiteral", "unaryOperator", "binaryOperator", - ]; - - public get grammarFileName(): string { return "JackParser.g4"; } - public get literalNames(): (string | null)[] { return JackParser.literalNames; } - public get symbolicNames(): (string | null)[] { return JackParser.symbolicNames; } - public get ruleNames(): string[] { return JackParser.ruleNames; } - public get serializedATN(): number[] { return JackParser._serializedATN; } - - protected createFailedPredicateException(predicate?: string, message?: string): antlr.FailedPredicateException { - return new antlr.FailedPredicateException(this, predicate, message); - } - - public constructor(input: antlr.TokenStream) { - super(input); - this.interpreter = new antlr.ParserATNSimulator(this, JackParser._ATN, JackParser.decisionsToDFA, new antlr.PredictionContextCache()); - } - public program(): ProgramContext { - let localContext = new ProgramContext(this.context, this.state); - this.enterRule(localContext, 0, JackParser.RULE_program); - try { - this.enterOuterAlt(localContext, 1); + public static readonly CLASS = 1; + public static readonly CONSTRUCTOR = 2; + public static readonly FUNCTION = 3; + public static readonly METHOD = 4; + public static readonly FIELD = 5; + public static readonly STATIC = 6; + public static readonly VAR = 7; + public static readonly INT = 8; + public static readonly CHAR = 9; + public static readonly BOOLEAN = 10; + public static readonly VOID = 11; + public static readonly LET = 12; + public static readonly DO = 13; + public static readonly IF = 14; + public static readonly ELSE = 15; + public static readonly WHILE = 16; + public static readonly RETURN = 17; + public static readonly LBRACE = 18; + public static readonly RBRACE = 19; + public static readonly LPAREN = 20; + public static readonly RPAREN = 21; + public static readonly LBRACKET = 22; + public static readonly RBRACKET = 23; + public static readonly DOT = 24; + public static readonly COMMA = 25; + public static readonly SEMICOLON = 26; + public static readonly EQUALS = 27; + public static readonly PLUS = 28; + public static readonly MINUS = 29; + public static readonly MUL = 30; + public static readonly DIV = 31; + public static readonly AND = 32; + public static readonly OR = 33; + public static readonly TILDE = 34; + public static readonly LESS_THAN = 35; + public static readonly GREATER_THAN = 36; + public static readonly WHITESPACE = 37; + public static readonly BLOCK_COMMENT = 38; + public static readonly LINE_COMMENT = 39; + public static readonly INTEGER_LITERAL = 40; + public static readonly TRUE = 41; + public static readonly FALSE = 42; + public static readonly NULL_LITERAL = 43; + public static readonly THIS_LITERAL = 44; + public static readonly IDENTIFIER = 45; + public static readonly STRING_LITERAL = 46; + public static readonly RULE_program = 0; + public static readonly RULE_classDeclaration = 1; + public static readonly RULE_className = 2; + public static readonly RULE_classVarDec = 3; + public static readonly RULE_fieldList = 4; + public static readonly RULE_fieldName = 5; + public static readonly RULE_subroutineDeclaration = 6; + public static readonly RULE_subroutineType = 7; + public static readonly RULE_subroutineDecWithoutType = 8; + public static readonly RULE_subroutineName = 9; + public static readonly RULE_subroutineReturnType = 10; + public static readonly RULE_varType = 11; + public static readonly RULE_parameterList = 12; + public static readonly RULE_parameter = 13; + public static readonly RULE_parameterName = 14; + public static readonly RULE_subroutineBody = 15; + public static readonly RULE_rBrace = 16; + public static readonly RULE_varDeclaration = 17; + public static readonly RULE_varNameInDeclaration = 18; + public static readonly RULE_statements = 19; + public static readonly RULE_statement = 20; + public static readonly RULE_letStatement = 21; + public static readonly RULE_equals = 22; + public static readonly RULE_ifElseStatement = 23; + public static readonly RULE_ifStatement = 24; + public static readonly RULE_ifExpression = 25; + public static readonly RULE_elseStatement = 26; + public static readonly RULE_whileStatement = 27; + public static readonly RULE_whileExpression = 28; + public static readonly RULE_doStatement = 29; + public static readonly RULE_subroutineCall = 30; + public static readonly RULE_subroutineId = 31; + public static readonly RULE_returnStatement = 32; + public static readonly RULE_expressionList = 33; + public static readonly RULE_expression = 34; + public static readonly RULE_constant = 35; + public static readonly RULE_varName = 36; + public static readonly RULE_arrayAccess = 37; + public static readonly RULE_unaryOperation = 38; + public static readonly RULE_groupedExpression = 39; + public static readonly RULE_booleanLiteral = 40; + public static readonly RULE_unaryOperator = 41; + public static readonly RULE_binaryOperator = 42; + + public static readonly literalNames = [ + null, + "'class'", + "'constructor'", + "'function'", + "'method'", + "'field'", + "'static'", + "'var'", + "'int'", + "'char'", + "'boolean'", + "'void'", + "'let'", + "'do'", + "'if'", + "'else'", + "'while'", + "'return'", + "'{'", + "'}'", + "'('", + "')'", + "'['", + "']'", + "'.'", + "','", + "';'", + "'='", + "'+'", + "'-'", + "'*'", + "'/'", + "'&'", + "'|'", + "'~'", + "'<'", + "'>'", + null, + null, + null, + null, + "'true'", + "'false'", + "'null'", + "'this'", + ]; + + public static readonly symbolicNames = [ + null, + "CLASS", + "CONSTRUCTOR", + "FUNCTION", + "METHOD", + "FIELD", + "STATIC", + "VAR", + "INT", + "CHAR", + "BOOLEAN", + "VOID", + "LET", + "DO", + "IF", + "ELSE", + "WHILE", + "RETURN", + "LBRACE", + "RBRACE", + "LPAREN", + "RPAREN", + "LBRACKET", + "RBRACKET", + "DOT", + "COMMA", + "SEMICOLON", + "EQUALS", + "PLUS", + "MINUS", + "MUL", + "DIV", + "AND", + "OR", + "TILDE", + "LESS_THAN", + "GREATER_THAN", + "WHITESPACE", + "BLOCK_COMMENT", + "LINE_COMMENT", + "INTEGER_LITERAL", + "TRUE", + "FALSE", + "NULL_LITERAL", + "THIS_LITERAL", + "IDENTIFIER", + "STRING_LITERAL", + ]; + public static readonly ruleNames = [ + "program", + "classDeclaration", + "className", + "classVarDec", + "fieldList", + "fieldName", + "subroutineDeclaration", + "subroutineType", + "subroutineDecWithoutType", + "subroutineName", + "subroutineReturnType", + "varType", + "parameterList", + "parameter", + "parameterName", + "subroutineBody", + "rBrace", + "varDeclaration", + "varNameInDeclaration", + "statements", + "statement", + "letStatement", + "equals", + "ifElseStatement", + "ifStatement", + "ifExpression", + "elseStatement", + "whileStatement", + "whileExpression", + "doStatement", + "subroutineCall", + "subroutineId", + "returnStatement", + "expressionList", + "expression", + "constant", + "varName", + "arrayAccess", + "unaryOperation", + "groupedExpression", + "booleanLiteral", + "unaryOperator", + "binaryOperator", + ]; + + public get grammarFileName(): string { + return "JackParser.g4"; + } + public get literalNames(): (string | null)[] { + return JackParser.literalNames; + } + public get symbolicNames(): (string | null)[] { + return JackParser.symbolicNames; + } + public get ruleNames(): string[] { + return JackParser.ruleNames; + } + public get serializedATN(): number[] { + return JackParser._serializedATN; + } + + protected createFailedPredicateException( + predicate?: string, + message?: string, + ): antlr.FailedPredicateException { + return new antlr.FailedPredicateException(this, predicate, message); + } + + public constructor(input: antlr.TokenStream) { + super(input); + this.interpreter = new antlr.ParserATNSimulator( + this, + JackParser._ATN, + JackParser.decisionsToDFA, + new antlr.PredictionContextCache(), + ); + } + public program(): ProgramContext { + let localContext = new ProgramContext(this.context, this.state); + this.enterRule(localContext, 0, JackParser.RULE_program); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 86; + this.classDeclaration(); + this.state = 87; + this.match(JackParser.EOF); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public classDeclaration(): ClassDeclarationContext { + let localContext = new ClassDeclarationContext(this.context, this.state); + this.enterRule(localContext, 2, JackParser.RULE_classDeclaration); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 89; + this.match(JackParser.CLASS); + this.state = 90; + this.className(); + this.state = 91; + this.match(JackParser.LBRACE); + this.state = 95; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 5 || _la === 6) { + { { - this.state = 86; - this.classDeclaration(); - this.state = 87; - this.match(JackParser.EOF); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public classDeclaration(): ClassDeclarationContext { - let localContext = new ClassDeclarationContext(this.context, this.state); - this.enterRule(localContext, 2, JackParser.RULE_classDeclaration); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); + this.state = 92; + this.classVarDec(); + } + } + this.state = 97; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 101; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while ((_la & ~0x1f) === 0 && ((1 << _la) & 28) !== 0) { + { { - this.state = 89; - this.match(JackParser.CLASS); - this.state = 90; - this.className(); - this.state = 91; - this.match(JackParser.LBRACE); - this.state = 95; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - while (_la === 5 || _la === 6) { - { - { - this.state = 92; - this.classVarDec(); - } - } - this.state = 97; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - } - this.state = 101; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 28) !== 0)) { - { - { - this.state = 98; - this.subroutineDeclaration(); - } - } - this.state = 103; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - } - this.state = 104; - this.rBrace(); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public className(): ClassNameContext { - let localContext = new ClassNameContext(this.context, this.state); - this.enterRule(localContext, 4, JackParser.RULE_className); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 106; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public classVarDec(): ClassVarDecContext { - let localContext = new ClassVarDecContext(this.context, this.state); - this.enterRule(localContext, 6, JackParser.RULE_classVarDec); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 108; - _la = this.tokenStream.LA(1); - if(!(_la === 5 || _la === 6)) { - this.errorHandler.recoverInline(this); - } - else { - this.errorHandler.reportMatch(this); - this.consume(); - } - this.state = 109; - this.fieldList(); - this.state = 110; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public fieldList(): FieldListContext { - let localContext = new FieldListContext(this.context, this.state); - this.enterRule(localContext, 8, JackParser.RULE_fieldList); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); + this.state = 98; + this.subroutineDeclaration(); + } + } + this.state = 103; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 104; + this.rBrace(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public className(): ClassNameContext { + let localContext = new ClassNameContext(this.context, this.state); + this.enterRule(localContext, 4, JackParser.RULE_className); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 106; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public classVarDec(): ClassVarDecContext { + let localContext = new ClassVarDecContext(this.context, this.state); + this.enterRule(localContext, 6, JackParser.RULE_classVarDec); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 108; + _la = this.tokenStream.LA(1); + if (!(_la === 5 || _la === 6)) { + this.errorHandler.recoverInline(this); + } else { + this.errorHandler.reportMatch(this); + this.consume(); + } + this.state = 109; + this.fieldList(); + this.state = 110; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public fieldList(): FieldListContext { + let localContext = new FieldListContext(this.context, this.state); + this.enterRule(localContext, 8, JackParser.RULE_fieldList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 112; + this.varType(); + this.state = 113; + this.fieldName(); + this.state = 118; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 25) { + { { - this.state = 112; + this.state = 114; + this.match(JackParser.COMMA); + this.state = 115; + this.fieldName(); + } + } + this.state = 120; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public fieldName(): FieldNameContext { + let localContext = new FieldNameContext(this.context, this.state); + this.enterRule(localContext, 10, JackParser.RULE_fieldName); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 121; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public subroutineDeclaration(): SubroutineDeclarationContext { + let localContext = new SubroutineDeclarationContext( + this.context, + this.state, + ); + this.enterRule(localContext, 12, JackParser.RULE_subroutineDeclaration); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 123; + this.subroutineType(); + this.state = 124; + this.subroutineDecWithoutType(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public subroutineType(): SubroutineTypeContext { + let localContext = new SubroutineTypeContext(this.context, this.state); + this.enterRule(localContext, 14, JackParser.RULE_subroutineType); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 126; + _la = this.tokenStream.LA(1); + if (!((_la & ~0x1f) === 0 && ((1 << _la) & 28) !== 0)) { + this.errorHandler.recoverInline(this); + } else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + let localContext = new SubroutineDecWithoutTypeContext( + this.context, + this.state, + ); + this.enterRule(localContext, 16, JackParser.RULE_subroutineDecWithoutType); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 128; + this.subroutineReturnType(); + this.state = 129; + this.subroutineName(); + this.state = 130; + this.match(JackParser.LPAREN); + this.state = 131; + this.parameterList(); + this.state = 132; + this.match(JackParser.RPAREN); + this.state = 133; + this.subroutineBody(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public subroutineName(): SubroutineNameContext { + let localContext = new SubroutineNameContext(this.context, this.state); + this.enterRule(localContext, 18, JackParser.RULE_subroutineName); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 135; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public subroutineReturnType(): SubroutineReturnTypeContext { + let localContext = new SubroutineReturnTypeContext( + this.context, + this.state, + ); + this.enterRule(localContext, 20, JackParser.RULE_subroutineReturnType); + try { + this.state = 139; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case JackParser.INT: + case JackParser.CHAR: + case JackParser.BOOLEAN: + case JackParser.IDENTIFIER: + this.enterOuterAlt(localContext, 1); + { + this.state = 137; this.varType(); - this.state = 113; - this.fieldName(); - this.state = 118; + } + break; + case JackParser.VOID: + this.enterOuterAlt(localContext, 2); + { + this.state = 138; + this.match(JackParser.VOID); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public varType(): VarTypeContext { + let localContext = new VarTypeContext(this.context, this.state); + this.enterRule(localContext, 22, JackParser.RULE_varType); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 141; + _la = this.tokenStream.LA(1); + if ( + !(((_la & ~0x1f) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45) + ) { + this.errorHandler.recoverInline(this); + } else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public parameterList(): ParameterListContext { + let localContext = new ParameterListContext(this.context, this.state); + this.enterRule(localContext, 24, JackParser.RULE_parameterList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 151; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (((_la & ~0x1f) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45) { + { + this.state = 143; + this.parameter(); + this.state = 148; this.errorHandler.sync(this); _la = this.tokenStream.LA(1); while (_la === 25) { + { { - { - this.state = 114; - this.match(JackParser.COMMA); - this.state = 115; - this.fieldName(); + this.state = 144; + this.match(JackParser.COMMA); + this.state = 145; + this.parameter(); } - } - this.state = 120; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - } - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public fieldName(): FieldNameContext { - let localContext = new FieldNameContext(this.context, this.state); - this.enterRule(localContext, 10, JackParser.RULE_fieldName); - try { - this.enterOuterAlt(localContext, 1); + } + this.state = 150; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public parameter(): ParameterContext { + let localContext = new ParameterContext(this.context, this.state); + this.enterRule(localContext, 26, JackParser.RULE_parameter); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 153; + this.varType(); + this.state = 154; + this.parameterName(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public parameterName(): ParameterNameContext { + let localContext = new ParameterNameContext(this.context, this.state); + this.enterRule(localContext, 28, JackParser.RULE_parameterName); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 156; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public subroutineBody(): SubroutineBodyContext { + let localContext = new SubroutineBodyContext(this.context, this.state); + this.enterRule(localContext, 30, JackParser.RULE_subroutineBody); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 158; + this.match(JackParser.LBRACE); + this.state = 162; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 7) { + { { - this.state = 121; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public subroutineDeclaration(): SubroutineDeclarationContext { - let localContext = new SubroutineDeclarationContext(this.context, this.state); - this.enterRule(localContext, 12, JackParser.RULE_subroutineDeclaration); - try { - this.enterOuterAlt(localContext, 1); + this.state = 159; + this.varDeclaration(); + } + } + this.state = 164; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 165; + this.statements(); + this.state = 166; + this.rBrace(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public rBrace(): RBraceContext { + let localContext = new RBraceContext(this.context, this.state); + this.enterRule(localContext, 32, JackParser.RULE_rBrace); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 168; + this.match(JackParser.RBRACE); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public varDeclaration(): VarDeclarationContext { + let localContext = new VarDeclarationContext(this.context, this.state); + this.enterRule(localContext, 34, JackParser.RULE_varDeclaration); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 170; + this.match(JackParser.VAR); + this.state = 171; + this.varType(); + this.state = 172; + this.varNameInDeclaration(); + this.state = 177; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 25) { + { { - this.state = 123; - this.subroutineType(); - this.state = 124; - this.subroutineDecWithoutType(); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public subroutineType(): SubroutineTypeContext { - let localContext = new SubroutineTypeContext(this.context, this.state); - this.enterRule(localContext, 14, JackParser.RULE_subroutineType); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); + this.state = 173; + this.match(JackParser.COMMA); + this.state = 174; + this.varNameInDeclaration(); + } + } + this.state = 179; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + this.state = 180; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public varNameInDeclaration(): VarNameInDeclarationContext { + let localContext = new VarNameInDeclarationContext( + this.context, + this.state, + ); + this.enterRule(localContext, 36, JackParser.RULE_varNameInDeclaration); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 182; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public statements(): StatementsContext { + let localContext = new StatementsContext(this.context, this.state); + this.enterRule(localContext, 38, JackParser.RULE_statements); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 187; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while ((_la & ~0x1f) === 0 && ((1 << _la) & 225280) !== 0) { + { { - this.state = 126; - _la = this.tokenStream.LA(1); - if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 28) !== 0))) { - this.errorHandler.recoverInline(this); - } - else { - this.errorHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - let localContext = new SubroutineDecWithoutTypeContext(this.context, this.state); - this.enterRule(localContext, 16, JackParser.RULE_subroutineDecWithoutType); - try { - this.enterOuterAlt(localContext, 1); + this.state = 184; + this.statement(); + } + } + this.state = 189; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public statement(): StatementContext { + let localContext = new StatementContext(this.context, this.state); + this.enterRule(localContext, 40, JackParser.RULE_statement); + try { + this.state = 195; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case JackParser.LET: + this.enterOuterAlt(localContext, 1); + { + this.state = 190; + this.letStatement(); + } + break; + case JackParser.IF: + this.enterOuterAlt(localContext, 2); + { + this.state = 191; + this.ifElseStatement(); + } + break; + case JackParser.WHILE: + this.enterOuterAlt(localContext, 3); + { + this.state = 192; + this.whileStatement(); + } + break; + case JackParser.DO: + this.enterOuterAlt(localContext, 4); + { + this.state = 193; + this.doStatement(); + } + break; + case JackParser.RETURN: + this.enterOuterAlt(localContext, 5); + { + this.state = 194; + this.returnStatement(); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public letStatement(): LetStatementContext { + let localContext = new LetStatementContext(this.context, this.state); + this.enterRule(localContext, 42, JackParser.RULE_letStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 197; + this.match(JackParser.LET); + this.state = 200; + this.errorHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this.tokenStream, 10, this.context) + ) { + case 1: { - this.state = 128; - this.subroutineReturnType(); - this.state = 129; - this.subroutineName(); - this.state = 130; - this.match(JackParser.LPAREN); - this.state = 131; - this.parameterList(); - this.state = 132; - this.match(JackParser.RPAREN); - this.state = 133; - this.subroutineBody(); + this.state = 198; + this.varName(); } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public subroutineName(): SubroutineNameContext { - let localContext = new SubroutineNameContext(this.context, this.state); - this.enterRule(localContext, 18, JackParser.RULE_subroutineName); - try { - this.enterOuterAlt(localContext, 1); + break; + case 2: { - this.state = 135; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public subroutineReturnType(): SubroutineReturnTypeContext { - let localContext = new SubroutineReturnTypeContext(this.context, this.state); - this.enterRule(localContext, 20, JackParser.RULE_subroutineReturnType); - try { - this.state = 139; - this.errorHandler.sync(this); - switch (this.tokenStream.LA(1)) { - case JackParser.INT: - case JackParser.CHAR: - case JackParser.BOOLEAN: - case JackParser.IDENTIFIER: - this.enterOuterAlt(localContext, 1); - { - this.state = 137; - this.varType(); - } - break; - case JackParser.VOID: - this.enterOuterAlt(localContext, 2); - { - this.state = 138; - this.match(JackParser.VOID); - } - break; - default: - throw new antlr.NoViableAltException(this); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public varType(): VarTypeContext { - let localContext = new VarTypeContext(this.context, this.state); - this.enterRule(localContext, 22, JackParser.RULE_varType); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); + this.state = 199; + this.arrayAccess(); + } + break; + } + this.state = 202; + this.equals(); + this.state = 203; + this.expression(0); + this.state = 204; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public equals(): EqualsContext { + let localContext = new EqualsContext(this.context, this.state); + this.enterRule(localContext, 44, JackParser.RULE_equals); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 206; + this.match(JackParser.EQUALS); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public ifElseStatement(): IfElseStatementContext { + let localContext = new IfElseStatementContext(this.context, this.state); + this.enterRule(localContext, 46, JackParser.RULE_ifElseStatement); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 208; + this.ifStatement(); + this.state = 210; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if (_la === 15) { + { + this.state = 209; + this.elseStatement(); + } + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public ifStatement(): IfStatementContext { + let localContext = new IfStatementContext(this.context, this.state); + this.enterRule(localContext, 48, JackParser.RULE_ifStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 212; + this.match(JackParser.IF); + this.state = 213; + this.match(JackParser.LPAREN); + this.state = 214; + this.ifExpression(); + this.state = 215; + this.match(JackParser.RPAREN); + this.state = 216; + this.match(JackParser.LBRACE); + this.state = 217; + this.statements(); + this.state = 218; + this.rBrace(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public ifExpression(): IfExpressionContext { + let localContext = new IfExpressionContext(this.context, this.state); + this.enterRule(localContext, 50, JackParser.RULE_ifExpression); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 220; + this.expression(0); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public elseStatement(): ElseStatementContext { + let localContext = new ElseStatementContext(this.context, this.state); + this.enterRule(localContext, 52, JackParser.RULE_elseStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 222; + this.match(JackParser.ELSE); + this.state = 223; + this.match(JackParser.LBRACE); + this.state = 224; + this.statements(); + this.state = 225; + this.rBrace(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public whileStatement(): WhileStatementContext { + let localContext = new WhileStatementContext(this.context, this.state); + this.enterRule(localContext, 54, JackParser.RULE_whileStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 227; + this.match(JackParser.WHILE); + this.state = 228; + this.match(JackParser.LPAREN); + this.state = 229; + this.whileExpression(); + this.state = 230; + this.match(JackParser.RPAREN); + this.state = 231; + this.match(JackParser.LBRACE); + this.state = 232; + this.statements(); + this.state = 233; + this.rBrace(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public whileExpression(): WhileExpressionContext { + let localContext = new WhileExpressionContext(this.context, this.state); + this.enterRule(localContext, 56, JackParser.RULE_whileExpression); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 235; + this.expression(0); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public doStatement(): DoStatementContext { + let localContext = new DoStatementContext(this.context, this.state); + this.enterRule(localContext, 58, JackParser.RULE_doStatement); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 237; + this.match(JackParser.DO); + this.state = 238; + this.subroutineCall(); + this.state = 239; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public subroutineCall(): SubroutineCallContext { + let localContext = new SubroutineCallContext(this.context, this.state); + this.enterRule(localContext, 60, JackParser.RULE_subroutineCall); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 241; + this.subroutineId(); + this.state = 242; + this.match(JackParser.LPAREN); + this.state = 243; + this.expressionList(); + this.state = 244; + this.match(JackParser.RPAREN); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public subroutineId(): SubroutineIdContext { + let localContext = new SubroutineIdContext(this.context, this.state); + this.enterRule(localContext, 62, JackParser.RULE_subroutineId); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 251; + this.errorHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this.tokenStream, 13, this.context) + ) { + case 1: { - this.state = 141; - _la = this.tokenStream.LA(1); - if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45)) { - this.errorHandler.recoverInline(this); - } - else { - this.errorHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public parameterList(): ParameterListContext { - let localContext = new ParameterListContext(this.context, this.state); - this.enterRule(localContext, 24, JackParser.RULE_parameterList); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 151; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 1792) !== 0) || _la === 45) { - { - this.state = 143; - this.parameter(); - this.state = 148; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - while (_la === 25) { - { - { - this.state = 144; - this.match(JackParser.COMMA); - this.state = 145; - this.parameter(); - } - } - this.state = 150; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - } - } - } - - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public parameter(): ParameterContext { - let localContext = new ParameterContext(this.context, this.state); - this.enterRule(localContext, 26, JackParser.RULE_parameter); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 153; - this.varType(); - this.state = 154; - this.parameterName(); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public parameterName(): ParameterNameContext { - let localContext = new ParameterNameContext(this.context, this.state); - this.enterRule(localContext, 28, JackParser.RULE_parameterName); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 156; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public subroutineBody(): SubroutineBodyContext { - let localContext = new SubroutineBodyContext(this.context, this.state); - this.enterRule(localContext, 30, JackParser.RULE_subroutineBody); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 158; - this.match(JackParser.LBRACE); - this.state = 162; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - while (_la === 7) { - { - { - this.state = 159; - this.varDeclaration(); - } - } - this.state = 164; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - } - this.state = 165; - this.statements(); - this.state = 166; - this.rBrace(); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public rBrace(): RBraceContext { - let localContext = new RBraceContext(this.context, this.state); - this.enterRule(localContext, 32, JackParser.RULE_rBrace); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 168; - this.match(JackParser.RBRACE); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public varDeclaration(): VarDeclarationContext { - let localContext = new VarDeclarationContext(this.context, this.state); - this.enterRule(localContext, 34, JackParser.RULE_varDeclaration); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 170; - this.match(JackParser.VAR); - this.state = 171; - this.varType(); - this.state = 172; - this.varNameInDeclaration(); - this.state = 177; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - while (_la === 25) { - { - { - this.state = 173; - this.match(JackParser.COMMA); - this.state = 174; - this.varNameInDeclaration(); - } - } - this.state = 179; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - } - this.state = 180; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public varNameInDeclaration(): VarNameInDeclarationContext { - let localContext = new VarNameInDeclarationContext(this.context, this.state); - this.enterRule(localContext, 36, JackParser.RULE_varNameInDeclaration); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 182; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public statements(): StatementsContext { - let localContext = new StatementsContext(this.context, this.state); - this.enterRule(localContext, 38, JackParser.RULE_statements); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 187; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 225280) !== 0)) { - { - { - this.state = 184; - this.statement(); - } - } - this.state = 189; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - } - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public statement(): StatementContext { - let localContext = new StatementContext(this.context, this.state); - this.enterRule(localContext, 40, JackParser.RULE_statement); - try { - this.state = 195; - this.errorHandler.sync(this); - switch (this.tokenStream.LA(1)) { - case JackParser.LET: - this.enterOuterAlt(localContext, 1); - { - this.state = 190; - this.letStatement(); - } - break; - case JackParser.IF: - this.enterOuterAlt(localContext, 2); - { - this.state = 191; - this.ifElseStatement(); - } - break; - case JackParser.WHILE: - this.enterOuterAlt(localContext, 3); - { - this.state = 192; - this.whileStatement(); - } - break; - case JackParser.DO: - this.enterOuterAlt(localContext, 4); - { - this.state = 193; - this.doStatement(); - } - break; - case JackParser.RETURN: - this.enterOuterAlt(localContext, 5); - { - this.state = 194; - this.returnStatement(); - } - break; - default: - throw new antlr.NoViableAltException(this); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public letStatement(): LetStatementContext { - let localContext = new LetStatementContext(this.context, this.state); - this.enterRule(localContext, 42, JackParser.RULE_letStatement); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 197; - this.match(JackParser.LET); - this.state = 200; - this.errorHandler.sync(this); - switch (this.interpreter.adaptivePredict(this.tokenStream, 10, this.context) ) { - case 1: - { - this.state = 198; - this.varName(); - } - break; - case 2: - { - this.state = 199; - this.arrayAccess(); - } - break; - } - this.state = 202; - this.equals(); - this.state = 203; - this.expression(0); - this.state = 204; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public equals(): EqualsContext { - let localContext = new EqualsContext(this.context, this.state); - this.enterRule(localContext, 44, JackParser.RULE_equals); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 206; - this.match(JackParser.EQUALS); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public ifElseStatement(): IfElseStatementContext { - let localContext = new IfElseStatementContext(this.context, this.state); - this.enterRule(localContext, 46, JackParser.RULE_ifElseStatement); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 208; - this.ifStatement(); - this.state = 210; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - if (_la === 15) { - { - this.state = 209; - this.elseStatement(); - } - } - - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public ifStatement(): IfStatementContext { - let localContext = new IfStatementContext(this.context, this.state); - this.enterRule(localContext, 48, JackParser.RULE_ifStatement); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 212; - this.match(JackParser.IF); - this.state = 213; - this.match(JackParser.LPAREN); - this.state = 214; - this.ifExpression(); - this.state = 215; - this.match(JackParser.RPAREN); - this.state = 216; - this.match(JackParser.LBRACE); - this.state = 217; - this.statements(); - this.state = 218; - this.rBrace(); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public ifExpression(): IfExpressionContext { - let localContext = new IfExpressionContext(this.context, this.state); - this.enterRule(localContext, 50, JackParser.RULE_ifExpression); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 220; - this.expression(0); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public elseStatement(): ElseStatementContext { - let localContext = new ElseStatementContext(this.context, this.state); - this.enterRule(localContext, 52, JackParser.RULE_elseStatement); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 222; - this.match(JackParser.ELSE); - this.state = 223; - this.match(JackParser.LBRACE); - this.state = 224; - this.statements(); - this.state = 225; - this.rBrace(); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public whileStatement(): WhileStatementContext { - let localContext = new WhileStatementContext(this.context, this.state); - this.enterRule(localContext, 54, JackParser.RULE_whileStatement); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 227; - this.match(JackParser.WHILE); - this.state = 228; - this.match(JackParser.LPAREN); - this.state = 229; - this.whileExpression(); - this.state = 230; - this.match(JackParser.RPAREN); - this.state = 231; - this.match(JackParser.LBRACE); - this.state = 232; - this.statements(); - this.state = 233; - this.rBrace(); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public whileExpression(): WhileExpressionContext { - let localContext = new WhileExpressionContext(this.context, this.state); - this.enterRule(localContext, 56, JackParser.RULE_whileExpression); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 235; - this.expression(0); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public doStatement(): DoStatementContext { - let localContext = new DoStatementContext(this.context, this.state); - this.enterRule(localContext, 58, JackParser.RULE_doStatement); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 237; - this.match(JackParser.DO); - this.state = 238; - this.subroutineCall(); - this.state = 239; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public subroutineCall(): SubroutineCallContext { - let localContext = new SubroutineCallContext(this.context, this.state); - this.enterRule(localContext, 60, JackParser.RULE_subroutineCall); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 241; - this.subroutineId(); - this.state = 242; - this.match(JackParser.LPAREN); - this.state = 243; - this.expressionList(); - this.state = 244; - this.match(JackParser.RPAREN); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public subroutineId(): SubroutineIdContext { - let localContext = new SubroutineIdContext(this.context, this.state); - this.enterRule(localContext, 62, JackParser.RULE_subroutineId); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 251; - this.errorHandler.sync(this); - switch (this.interpreter.adaptivePredict(this.tokenStream, 13, this.context) ) { - case 1: - { - this.state = 248; - this.errorHandler.sync(this); - switch (this.tokenStream.LA(1)) { + this.state = 248; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { case JackParser.IDENTIFIER: - { + { this.state = 246; this.className(); - } - break; + } + break; case JackParser.THIS_LITERAL: - { + { this.state = 247; this.match(JackParser.THIS_LITERAL); - } - break; + } + break; default: - throw new antlr.NoViableAltException(this); - } - this.state = 250; - this.match(JackParser.DOT); - } - break; - } - this.state = 253; - this.subroutineName(); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public returnStatement(): ReturnStatementContext { - let localContext = new ReturnStatementContext(this.context, this.state); - this.enterRule(localContext, 64, JackParser.RULE_returnStatement); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 255; - this.match(JackParser.RETURN); - this.state = 257; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 133186049) !== 0)) { - { - this.state = 256; - this.expression(0); - } - } - - this.state = 259; - this.match(JackParser.SEMICOLON); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public expressionList(): ExpressionListContext { - let localContext = new ExpressionListContext(this.context, this.state); - this.enterRule(localContext, 66, JackParser.RULE_expressionList); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 269; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - if (((((_la - 20)) & ~0x1F) === 0 && ((1 << (_la - 20)) & 133186049) !== 0)) { - { - this.state = 261; - this.expression(0); - this.state = 266; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - while (_la === 25) { - { - { - this.state = 262; - this.match(JackParser.COMMA); - this.state = 263; - this.expression(0); - } - } - this.state = 268; - this.errorHandler.sync(this); - _la = this.tokenStream.LA(1); - } - } - } - - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - - public expression(): ExpressionContext; - public expression(_p: number): ExpressionContext; - public expression(_p?: number): ExpressionContext { - if (_p === undefined) { - _p = 0; - } - - let parentContext = this.context; - let parentState = this.state; - let localContext = new ExpressionContext(this.context, parentState); - let previousContext = localContext; - let _startState = 68; - this.enterRecursionRule(localContext, 68, JackParser.RULE_expression, _p); - try { - let alternative: number; - this.enterOuterAlt(localContext, 1); - { - this.state = 278; - this.errorHandler.sync(this); - switch (this.interpreter.adaptivePredict(this.tokenStream, 17, this.context) ) { - case 1: - { - this.state = 272; - this.constant(); - } - break; - case 2: - { - this.state = 273; - this.varName(); - } - break; - case 3: - { - this.state = 274; - this.subroutineCall(); - } - break; - case 4: - { - this.state = 275; - this.arrayAccess(); - } - break; - case 5: - { - this.state = 276; - this.unaryOperation(); - } - break; - case 6: - { - this.state = 277; - this.groupedExpression(); - } - break; - } - this.context!.stop = this.tokenStream.LT(-1); - this.state = 286; - this.errorHandler.sync(this); - alternative = this.interpreter.adaptivePredict(this.tokenStream, 18, this.context); - while (alternative !== 2 && alternative !== antlr.ATN.INVALID_ALT_NUMBER) { - if (alternative === 1) { - if (this.parseListeners != null) { - this.triggerExitRuleEvent(); - } - previousContext = localContext; - { - { - localContext = new ExpressionContext(parentContext, parentState); - this.pushNewRecursionContext(localContext, _startState, JackParser.RULE_expression); - this.state = 280; - if (!(this.precpred(this.context, 2))) { - throw this.createFailedPredicateException("this.precpred(this.context, 2)"); - } - this.state = 281; - this.binaryOperator(); - this.state = 282; - this.expression(3); - } - } - } - this.state = 288; - this.errorHandler.sync(this); - alternative = this.interpreter.adaptivePredict(this.tokenStream, 18, this.context); - } - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.unrollRecursionContexts(parentContext); - } - return localContext; - } - public constant(): ConstantContext { - let localContext = new ConstantContext(this.context, this.state); - this.enterRule(localContext, 70, JackParser.RULE_constant); - try { - this.state = 294; - this.errorHandler.sync(this); - switch (this.tokenStream.LA(1)) { - case JackParser.INTEGER_LITERAL: - this.enterOuterAlt(localContext, 1); - { - this.state = 289; - this.match(JackParser.INTEGER_LITERAL); - } - break; - case JackParser.STRING_LITERAL: - this.enterOuterAlt(localContext, 2); - { - this.state = 290; - this.match(JackParser.STRING_LITERAL); - } - break; - case JackParser.TRUE: - case JackParser.FALSE: - this.enterOuterAlt(localContext, 3); - { - this.state = 291; - this.booleanLiteral(); - } - break; - case JackParser.NULL_LITERAL: - this.enterOuterAlt(localContext, 4); - { - this.state = 292; - this.match(JackParser.NULL_LITERAL); - } - break; - case JackParser.THIS_LITERAL: - this.enterOuterAlt(localContext, 5); - { - this.state = 293; - this.match(JackParser.THIS_LITERAL); - } - break; - default: - throw new antlr.NoViableAltException(this); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public varName(): VarNameContext { - let localContext = new VarNameContext(this.context, this.state); - this.enterRule(localContext, 72, JackParser.RULE_varName); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 296; - this.match(JackParser.IDENTIFIER); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public arrayAccess(): ArrayAccessContext { - let localContext = new ArrayAccessContext(this.context, this.state); - this.enterRule(localContext, 74, JackParser.RULE_arrayAccess); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 298; - this.varName(); - this.state = 299; - this.match(JackParser.LBRACKET); - this.state = 300; + throw new antlr.NoViableAltException(this); + } + this.state = 250; + this.match(JackParser.DOT); + } + break; + } + this.state = 253; + this.subroutineName(); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public returnStatement(): ReturnStatementContext { + let localContext = new ReturnStatementContext(this.context, this.state); + this.enterRule(localContext, 64, JackParser.RULE_returnStatement); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 255; + this.match(JackParser.RETURN); + this.state = 257; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if ( + ((_la - 20) & ~0x1f) === 0 && + ((1 << (_la - 20)) & 133186049) !== 0 + ) { + { + this.state = 256; this.expression(0); - this.state = 301; - this.match(JackParser.RBRACKET); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public unaryOperation(): UnaryOperationContext { - let localContext = new UnaryOperationContext(this.context, this.state); - this.enterRule(localContext, 76, JackParser.RULE_unaryOperation); - try { - this.enterOuterAlt(localContext, 1); - { - this.state = 303; - this.unaryOperator(); - this.state = 304; + } + } + + this.state = 259; + this.match(JackParser.SEMICOLON); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public expressionList(): ExpressionListContext { + let localContext = new ExpressionListContext(this.context, this.state); + this.enterRule(localContext, 66, JackParser.RULE_expressionList); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 269; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + if ( + ((_la - 20) & ~0x1f) === 0 && + ((1 << (_la - 20)) & 133186049) !== 0 + ) { + { + this.state = 261; this.expression(0); - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public groupedExpression(): GroupedExpressionContext { - let localContext = new GroupedExpressionContext(this.context, this.state); - this.enterRule(localContext, 78, JackParser.RULE_groupedExpression); - try { - this.enterOuterAlt(localContext, 1); + this.state = 266; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + while (_la === 25) { + { + { + this.state = 262; + this.match(JackParser.COMMA); + this.state = 263; + this.expression(0); + } + } + this.state = 268; + this.errorHandler.sync(this); + _la = this.tokenStream.LA(1); + } + } + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + + public expression(): ExpressionContext; + public expression(_p: number): ExpressionContext; + public expression(_p?: number): ExpressionContext { + if (_p === undefined) { + _p = 0; + } + + let parentContext = this.context; + let parentState = this.state; + let localContext = new ExpressionContext(this.context, parentState); + let previousContext = localContext; + let _startState = 68; + this.enterRecursionRule(localContext, 68, JackParser.RULE_expression, _p); + try { + let alternative: number; + this.enterOuterAlt(localContext, 1); + { + this.state = 278; + this.errorHandler.sync(this); + switch ( + this.interpreter.adaptivePredict(this.tokenStream, 17, this.context) + ) { + case 1: { - this.state = 306; - this.match(JackParser.LPAREN); - this.state = 307; - this.expression(0); - this.state = 308; - this.match(JackParser.RPAREN); + this.state = 272; + this.constant(); } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public booleanLiteral(): BooleanLiteralContext { - let localContext = new BooleanLiteralContext(this.context, this.state); - this.enterRule(localContext, 80, JackParser.RULE_booleanLiteral); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); + break; + case 2: { - this.state = 310; - _la = this.tokenStream.LA(1); - if(!(_la === 41 || _la === 42)) { - this.errorHandler.recoverInline(this); - } - else { - this.errorHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; + this.state = 273; + this.varName(); } - } - finally { - this.exitRule(); - } - return localContext; - } - public unaryOperator(): UnaryOperatorContext { - let localContext = new UnaryOperatorContext(this.context, this.state); - this.enterRule(localContext, 82, JackParser.RULE_unaryOperator); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); + break; + case 3: { - this.state = 312; - _la = this.tokenStream.LA(1); - if(!(_la === 29 || _la === 34)) { - this.errorHandler.recoverInline(this); + this.state = 274; + this.subroutineCall(); } - else { - this.errorHandler.reportMatch(this); - this.consume(); - } - } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - public binaryOperator(): BinaryOperatorContext { - let localContext = new BinaryOperatorContext(this.context, this.state); - this.enterRule(localContext, 84, JackParser.RULE_binaryOperator); - let _la: number; - try { - this.enterOuterAlt(localContext, 1); + break; + case 4: { - this.state = 314; - _la = this.tokenStream.LA(1); - if(!(((((_la - 27)) & ~0x1F) === 0 && ((1 << (_la - 27)) & 895) !== 0))) { - this.errorHandler.recoverInline(this); - } - else { - this.errorHandler.reportMatch(this); - this.consume(); + this.state = 275; + this.arrayAccess(); } + break; + case 5: + { + this.state = 276; + this.unaryOperation(); } - } - catch (re) { - if (re instanceof antlr.RecognitionException) { - this.errorHandler.reportError(this, re); - this.errorHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localContext; - } - - public override sempred(localContext: antlr.ParserRuleContext | null, ruleIndex: number, predIndex: number): boolean { - switch (ruleIndex) { - case 34: - return this.expression_sempred(localContext as ExpressionContext, predIndex); - } - return true; - } - private expression_sempred(localContext: ExpressionContext | null, predIndex: number): boolean { - switch (predIndex) { - case 0: - return this.precpred(this.context, 2); - } - return true; - } - - public static readonly _serializedATN: number[] = [ - 4,1,46,317,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7, - 6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13, - 2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20, - 7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26, - 2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33, - 7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39, - 2,40,7,40,2,41,7,41,2,42,7,42,1,0,1,0,1,0,1,1,1,1,1,1,1,1,5,1,94, - 8,1,10,1,12,1,97,9,1,1,1,5,1,100,8,1,10,1,12,1,103,9,1,1,1,1,1,1, - 2,1,2,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,5,4,117,8,4,10,4,12,4,120, - 9,4,1,5,1,5,1,6,1,6,1,6,1,7,1,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9, - 1,9,1,10,1,10,3,10,140,8,10,1,11,1,11,1,12,1,12,1,12,5,12,147,8, - 12,10,12,12,12,150,9,12,3,12,152,8,12,1,13,1,13,1,13,1,14,1,14,1, - 15,1,15,5,15,161,8,15,10,15,12,15,164,9,15,1,15,1,15,1,15,1,16,1, - 16,1,17,1,17,1,17,1,17,1,17,5,17,176,8,17,10,17,12,17,179,9,17,1, - 17,1,17,1,18,1,18,1,19,5,19,186,8,19,10,19,12,19,189,9,19,1,20,1, - 20,1,20,1,20,1,20,3,20,196,8,20,1,21,1,21,1,21,3,21,201,8,21,1,21, - 1,21,1,21,1,21,1,22,1,22,1,23,1,23,3,23,211,8,23,1,24,1,24,1,24, - 1,24,1,24,1,24,1,24,1,24,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,27, - 1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,29,1,29,1,29,1,29, - 1,30,1,30,1,30,1,30,1,30,1,31,1,31,3,31,249,8,31,1,31,3,31,252,8, - 31,1,31,1,31,1,32,1,32,3,32,258,8,32,1,32,1,32,1,33,1,33,1,33,5, - 33,265,8,33,10,33,12,33,268,9,33,3,33,270,8,33,1,34,1,34,1,34,1, - 34,1,34,1,34,1,34,3,34,279,8,34,1,34,1,34,1,34,1,34,5,34,285,8,34, - 10,34,12,34,288,9,34,1,35,1,35,1,35,1,35,1,35,3,35,295,8,35,1,36, - 1,36,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,38,1,39,1,39,1,39,1,39, - 1,40,1,40,1,41,1,41,1,42,1,42,1,42,0,1,68,43,0,2,4,6,8,10,12,14, - 16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58, - 60,62,64,66,68,70,72,74,76,78,80,82,84,0,6,1,0,5,6,1,0,2,4,2,0,8, - 10,45,45,1,0,41,42,2,0,29,29,34,34,2,0,27,33,35,36,303,0,86,1,0, - 0,0,2,89,1,0,0,0,4,106,1,0,0,0,6,108,1,0,0,0,8,112,1,0,0,0,10,121, - 1,0,0,0,12,123,1,0,0,0,14,126,1,0,0,0,16,128,1,0,0,0,18,135,1,0, - 0,0,20,139,1,0,0,0,22,141,1,0,0,0,24,151,1,0,0,0,26,153,1,0,0,0, - 28,156,1,0,0,0,30,158,1,0,0,0,32,168,1,0,0,0,34,170,1,0,0,0,36,182, - 1,0,0,0,38,187,1,0,0,0,40,195,1,0,0,0,42,197,1,0,0,0,44,206,1,0, - 0,0,46,208,1,0,0,0,48,212,1,0,0,0,50,220,1,0,0,0,52,222,1,0,0,0, - 54,227,1,0,0,0,56,235,1,0,0,0,58,237,1,0,0,0,60,241,1,0,0,0,62,251, - 1,0,0,0,64,255,1,0,0,0,66,269,1,0,0,0,68,278,1,0,0,0,70,294,1,0, - 0,0,72,296,1,0,0,0,74,298,1,0,0,0,76,303,1,0,0,0,78,306,1,0,0,0, - 80,310,1,0,0,0,82,312,1,0,0,0,84,314,1,0,0,0,86,87,3,2,1,0,87,88, - 5,0,0,1,88,1,1,0,0,0,89,90,5,1,0,0,90,91,3,4,2,0,91,95,5,18,0,0, - 92,94,3,6,3,0,93,92,1,0,0,0,94,97,1,0,0,0,95,93,1,0,0,0,95,96,1, - 0,0,0,96,101,1,0,0,0,97,95,1,0,0,0,98,100,3,12,6,0,99,98,1,0,0,0, - 100,103,1,0,0,0,101,99,1,0,0,0,101,102,1,0,0,0,102,104,1,0,0,0,103, - 101,1,0,0,0,104,105,3,32,16,0,105,3,1,0,0,0,106,107,5,45,0,0,107, - 5,1,0,0,0,108,109,7,0,0,0,109,110,3,8,4,0,110,111,5,26,0,0,111,7, - 1,0,0,0,112,113,3,22,11,0,113,118,3,10,5,0,114,115,5,25,0,0,115, - 117,3,10,5,0,116,114,1,0,0,0,117,120,1,0,0,0,118,116,1,0,0,0,118, - 119,1,0,0,0,119,9,1,0,0,0,120,118,1,0,0,0,121,122,5,45,0,0,122,11, - 1,0,0,0,123,124,3,14,7,0,124,125,3,16,8,0,125,13,1,0,0,0,126,127, - 7,1,0,0,127,15,1,0,0,0,128,129,3,20,10,0,129,130,3,18,9,0,130,131, - 5,20,0,0,131,132,3,24,12,0,132,133,5,21,0,0,133,134,3,30,15,0,134, - 17,1,0,0,0,135,136,5,45,0,0,136,19,1,0,0,0,137,140,3,22,11,0,138, - 140,5,11,0,0,139,137,1,0,0,0,139,138,1,0,0,0,140,21,1,0,0,0,141, - 142,7,2,0,0,142,23,1,0,0,0,143,148,3,26,13,0,144,145,5,25,0,0,145, - 147,3,26,13,0,146,144,1,0,0,0,147,150,1,0,0,0,148,146,1,0,0,0,148, - 149,1,0,0,0,149,152,1,0,0,0,150,148,1,0,0,0,151,143,1,0,0,0,151, - 152,1,0,0,0,152,25,1,0,0,0,153,154,3,22,11,0,154,155,3,28,14,0,155, - 27,1,0,0,0,156,157,5,45,0,0,157,29,1,0,0,0,158,162,5,18,0,0,159, - 161,3,34,17,0,160,159,1,0,0,0,161,164,1,0,0,0,162,160,1,0,0,0,162, - 163,1,0,0,0,163,165,1,0,0,0,164,162,1,0,0,0,165,166,3,38,19,0,166, - 167,3,32,16,0,167,31,1,0,0,0,168,169,5,19,0,0,169,33,1,0,0,0,170, - 171,5,7,0,0,171,172,3,22,11,0,172,177,3,36,18,0,173,174,5,25,0,0, - 174,176,3,36,18,0,175,173,1,0,0,0,176,179,1,0,0,0,177,175,1,0,0, - 0,177,178,1,0,0,0,178,180,1,0,0,0,179,177,1,0,0,0,180,181,5,26,0, - 0,181,35,1,0,0,0,182,183,5,45,0,0,183,37,1,0,0,0,184,186,3,40,20, - 0,185,184,1,0,0,0,186,189,1,0,0,0,187,185,1,0,0,0,187,188,1,0,0, - 0,188,39,1,0,0,0,189,187,1,0,0,0,190,196,3,42,21,0,191,196,3,46, - 23,0,192,196,3,54,27,0,193,196,3,58,29,0,194,196,3,64,32,0,195,190, - 1,0,0,0,195,191,1,0,0,0,195,192,1,0,0,0,195,193,1,0,0,0,195,194, - 1,0,0,0,196,41,1,0,0,0,197,200,5,12,0,0,198,201,3,72,36,0,199,201, - 3,74,37,0,200,198,1,0,0,0,200,199,1,0,0,0,201,202,1,0,0,0,202,203, - 3,44,22,0,203,204,3,68,34,0,204,205,5,26,0,0,205,43,1,0,0,0,206, - 207,5,27,0,0,207,45,1,0,0,0,208,210,3,48,24,0,209,211,3,52,26,0, - 210,209,1,0,0,0,210,211,1,0,0,0,211,47,1,0,0,0,212,213,5,14,0,0, - 213,214,5,20,0,0,214,215,3,50,25,0,215,216,5,21,0,0,216,217,5,18, - 0,0,217,218,3,38,19,0,218,219,3,32,16,0,219,49,1,0,0,0,220,221,3, - 68,34,0,221,51,1,0,0,0,222,223,5,15,0,0,223,224,5,18,0,0,224,225, - 3,38,19,0,225,226,3,32,16,0,226,53,1,0,0,0,227,228,5,16,0,0,228, - 229,5,20,0,0,229,230,3,56,28,0,230,231,5,21,0,0,231,232,5,18,0,0, - 232,233,3,38,19,0,233,234,3,32,16,0,234,55,1,0,0,0,235,236,3,68, - 34,0,236,57,1,0,0,0,237,238,5,13,0,0,238,239,3,60,30,0,239,240,5, - 26,0,0,240,59,1,0,0,0,241,242,3,62,31,0,242,243,5,20,0,0,243,244, - 3,66,33,0,244,245,5,21,0,0,245,61,1,0,0,0,246,249,3,4,2,0,247,249, - 5,44,0,0,248,246,1,0,0,0,248,247,1,0,0,0,249,250,1,0,0,0,250,252, - 5,24,0,0,251,248,1,0,0,0,251,252,1,0,0,0,252,253,1,0,0,0,253,254, - 3,18,9,0,254,63,1,0,0,0,255,257,5,17,0,0,256,258,3,68,34,0,257,256, - 1,0,0,0,257,258,1,0,0,0,258,259,1,0,0,0,259,260,5,26,0,0,260,65, - 1,0,0,0,261,266,3,68,34,0,262,263,5,25,0,0,263,265,3,68,34,0,264, - 262,1,0,0,0,265,268,1,0,0,0,266,264,1,0,0,0,266,267,1,0,0,0,267, - 270,1,0,0,0,268,266,1,0,0,0,269,261,1,0,0,0,269,270,1,0,0,0,270, - 67,1,0,0,0,271,272,6,34,-1,0,272,279,3,70,35,0,273,279,3,72,36,0, - 274,279,3,60,30,0,275,279,3,74,37,0,276,279,3,76,38,0,277,279,3, - 78,39,0,278,271,1,0,0,0,278,273,1,0,0,0,278,274,1,0,0,0,278,275, - 1,0,0,0,278,276,1,0,0,0,278,277,1,0,0,0,279,286,1,0,0,0,280,281, - 10,2,0,0,281,282,3,84,42,0,282,283,3,68,34,3,283,285,1,0,0,0,284, - 280,1,0,0,0,285,288,1,0,0,0,286,284,1,0,0,0,286,287,1,0,0,0,287, - 69,1,0,0,0,288,286,1,0,0,0,289,295,5,40,0,0,290,295,5,46,0,0,291, - 295,3,80,40,0,292,295,5,43,0,0,293,295,5,44,0,0,294,289,1,0,0,0, - 294,290,1,0,0,0,294,291,1,0,0,0,294,292,1,0,0,0,294,293,1,0,0,0, - 295,71,1,0,0,0,296,297,5,45,0,0,297,73,1,0,0,0,298,299,3,72,36,0, - 299,300,5,22,0,0,300,301,3,68,34,0,301,302,5,23,0,0,302,75,1,0,0, - 0,303,304,3,82,41,0,304,305,3,68,34,0,305,77,1,0,0,0,306,307,5,20, - 0,0,307,308,3,68,34,0,308,309,5,21,0,0,309,79,1,0,0,0,310,311,7, - 3,0,0,311,81,1,0,0,0,312,313,7,4,0,0,313,83,1,0,0,0,314,315,7,5, - 0,0,315,85,1,0,0,0,20,95,101,118,139,148,151,162,177,187,195,200, - 210,248,251,257,266,269,278,286,294 - ]; - - private static __ATN: antlr.ATN; - public static get _ATN(): antlr.ATN { - if (!JackParser.__ATN) { - JackParser.__ATN = new antlr.ATNDeserializer().deserialize(JackParser._serializedATN); - } - - return JackParser.__ATN; - } - - - private static readonly vocabulary = new antlr.Vocabulary(JackParser.literalNames, JackParser.symbolicNames, []); - - public override get vocabulary(): antlr.Vocabulary { - return JackParser.vocabulary; - } - - private static readonly decisionsToDFA = JackParser._ATN.decisionToState.map( (ds: antlr.DecisionState, index: number) => new antlr.DFA(ds, index) ); + break; + case 6: + { + this.state = 277; + this.groupedExpression(); + } + break; + } + this.context!.stop = this.tokenStream.LT(-1); + this.state = 286; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict( + this.tokenStream, + 18, + this.context, + ); + while ( + alternative !== 2 && + alternative !== antlr.ATN.INVALID_ALT_NUMBER + ) { + if (alternative === 1) { + if (this.parseListeners != null) { + this.triggerExitRuleEvent(); + } + previousContext = localContext; + { + { + localContext = new ExpressionContext( + parentContext, + parentState, + ); + this.pushNewRecursionContext( + localContext, + _startState, + JackParser.RULE_expression, + ); + this.state = 280; + if (!this.precpred(this.context, 2)) { + throw this.createFailedPredicateException( + "this.precpred(this.context, 2)", + ); + } + this.state = 281; + this.binaryOperator(); + this.state = 282; + this.expression(3); + } + } + } + this.state = 288; + this.errorHandler.sync(this); + alternative = this.interpreter.adaptivePredict( + this.tokenStream, + 18, + this.context, + ); + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.unrollRecursionContexts(parentContext); + } + return localContext; + } + public constant(): ConstantContext { + let localContext = new ConstantContext(this.context, this.state); + this.enterRule(localContext, 70, JackParser.RULE_constant); + try { + this.state = 294; + this.errorHandler.sync(this); + switch (this.tokenStream.LA(1)) { + case JackParser.INTEGER_LITERAL: + this.enterOuterAlt(localContext, 1); + { + this.state = 289; + this.match(JackParser.INTEGER_LITERAL); + } + break; + case JackParser.STRING_LITERAL: + this.enterOuterAlt(localContext, 2); + { + this.state = 290; + this.match(JackParser.STRING_LITERAL); + } + break; + case JackParser.TRUE: + case JackParser.FALSE: + this.enterOuterAlt(localContext, 3); + { + this.state = 291; + this.booleanLiteral(); + } + break; + case JackParser.NULL_LITERAL: + this.enterOuterAlt(localContext, 4); + { + this.state = 292; + this.match(JackParser.NULL_LITERAL); + } + break; + case JackParser.THIS_LITERAL: + this.enterOuterAlt(localContext, 5); + { + this.state = 293; + this.match(JackParser.THIS_LITERAL); + } + break; + default: + throw new antlr.NoViableAltException(this); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public varName(): VarNameContext { + let localContext = new VarNameContext(this.context, this.state); + this.enterRule(localContext, 72, JackParser.RULE_varName); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 296; + this.match(JackParser.IDENTIFIER); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public arrayAccess(): ArrayAccessContext { + let localContext = new ArrayAccessContext(this.context, this.state); + this.enterRule(localContext, 74, JackParser.RULE_arrayAccess); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 298; + this.varName(); + this.state = 299; + this.match(JackParser.LBRACKET); + this.state = 300; + this.expression(0); + this.state = 301; + this.match(JackParser.RBRACKET); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public unaryOperation(): UnaryOperationContext { + let localContext = new UnaryOperationContext(this.context, this.state); + this.enterRule(localContext, 76, JackParser.RULE_unaryOperation); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 303; + this.unaryOperator(); + this.state = 304; + this.expression(0); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public groupedExpression(): GroupedExpressionContext { + let localContext = new GroupedExpressionContext(this.context, this.state); + this.enterRule(localContext, 78, JackParser.RULE_groupedExpression); + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 306; + this.match(JackParser.LPAREN); + this.state = 307; + this.expression(0); + this.state = 308; + this.match(JackParser.RPAREN); + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public booleanLiteral(): BooleanLiteralContext { + let localContext = new BooleanLiteralContext(this.context, this.state); + this.enterRule(localContext, 80, JackParser.RULE_booleanLiteral); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 310; + _la = this.tokenStream.LA(1); + if (!(_la === 41 || _la === 42)) { + this.errorHandler.recoverInline(this); + } else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public unaryOperator(): UnaryOperatorContext { + let localContext = new UnaryOperatorContext(this.context, this.state); + this.enterRule(localContext, 82, JackParser.RULE_unaryOperator); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 312; + _la = this.tokenStream.LA(1); + if (!(_la === 29 || _la === 34)) { + this.errorHandler.recoverInline(this); + } else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + public binaryOperator(): BinaryOperatorContext { + let localContext = new BinaryOperatorContext(this.context, this.state); + this.enterRule(localContext, 84, JackParser.RULE_binaryOperator); + let _la: number; + try { + this.enterOuterAlt(localContext, 1); + { + this.state = 314; + _la = this.tokenStream.LA(1); + if (!(((_la - 27) & ~0x1f) === 0 && ((1 << (_la - 27)) & 895) !== 0)) { + this.errorHandler.recoverInline(this); + } else { + this.errorHandler.reportMatch(this); + this.consume(); + } + } + } catch (re) { + if (re instanceof antlr.RecognitionException) { + this.errorHandler.reportError(this, re); + this.errorHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localContext; + } + + public override sempred( + localContext: antlr.ParserRuleContext | null, + ruleIndex: number, + predIndex: number, + ): boolean { + switch (ruleIndex) { + case 34: + return this.expression_sempred( + localContext as ExpressionContext, + predIndex, + ); + } + return true; + } + private expression_sempred( + localContext: ExpressionContext | null, + predIndex: number, + ): boolean { + switch (predIndex) { + case 0: + return this.precpred(this.context, 2); + } + return true; + } + + public static readonly _serializedATN: number[] = [ + 4, 1, 46, 317, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, + 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, + 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, + 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, + 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, + 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, + 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, + 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 1, 0, 1, 0, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 94, 8, 1, 10, 1, 12, 1, 97, 9, 1, 1, 1, 5, + 1, 100, 8, 1, 10, 1, 12, 1, 103, 9, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 117, 8, 4, 10, 4, 12, 4, 120, 9, + 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, + 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 3, 10, 140, 8, 10, 1, 11, 1, 11, 1, + 12, 1, 12, 1, 12, 5, 12, 147, 8, 12, 10, 12, 12, 12, 150, 9, 12, 3, 12, 152, + 8, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 161, 8, 15, + 10, 15, 12, 15, 164, 9, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, + 1, 17, 1, 17, 1, 17, 5, 17, 176, 8, 17, 10, 17, 12, 17, 179, 9, 17, 1, 17, + 1, 17, 1, 18, 1, 18, 1, 19, 5, 19, 186, 8, 19, 10, 19, 12, 19, 189, 9, 19, + 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 3, 20, 196, 8, 20, 1, 21, 1, 21, 1, 21, + 3, 21, 201, 8, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 23, 1, 23, + 3, 23, 211, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, + 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, + 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, + 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 3, 31, 249, 8, 31, 1, 31, 3, 31, + 252, 8, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 258, 8, 32, 1, 32, 1, 32, 1, + 33, 1, 33, 1, 33, 5, 33, 265, 8, 33, 10, 33, 12, 33, 268, 9, 33, 3, 33, 270, + 8, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 279, 8, 34, + 1, 34, 1, 34, 1, 34, 1, 34, 5, 34, 285, 8, 34, 10, 34, 12, 34, 288, 9, 34, + 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 3, 35, 295, 8, 35, 1, 36, 1, 36, 1, 37, + 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, + 1, 40, 1, 40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 0, 1, 68, 43, 0, 2, 4, 6, + 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, + 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, + 84, 0, 6, 1, 0, 5, 6, 1, 0, 2, 4, 2, 0, 8, 10, 45, 45, 1, 0, 41, 42, 2, 0, + 29, 29, 34, 34, 2, 0, 27, 33, 35, 36, 303, 0, 86, 1, 0, 0, 0, 2, 89, 1, 0, + 0, 0, 4, 106, 1, 0, 0, 0, 6, 108, 1, 0, 0, 0, 8, 112, 1, 0, 0, 0, 10, 121, + 1, 0, 0, 0, 12, 123, 1, 0, 0, 0, 14, 126, 1, 0, 0, 0, 16, 128, 1, 0, 0, 0, + 18, 135, 1, 0, 0, 0, 20, 139, 1, 0, 0, 0, 22, 141, 1, 0, 0, 0, 24, 151, 1, + 0, 0, 0, 26, 153, 1, 0, 0, 0, 28, 156, 1, 0, 0, 0, 30, 158, 1, 0, 0, 0, 32, + 168, 1, 0, 0, 0, 34, 170, 1, 0, 0, 0, 36, 182, 1, 0, 0, 0, 38, 187, 1, 0, 0, + 0, 40, 195, 1, 0, 0, 0, 42, 197, 1, 0, 0, 0, 44, 206, 1, 0, 0, 0, 46, 208, + 1, 0, 0, 0, 48, 212, 1, 0, 0, 0, 50, 220, 1, 0, 0, 0, 52, 222, 1, 0, 0, 0, + 54, 227, 1, 0, 0, 0, 56, 235, 1, 0, 0, 0, 58, 237, 1, 0, 0, 0, 60, 241, 1, + 0, 0, 0, 62, 251, 1, 0, 0, 0, 64, 255, 1, 0, 0, 0, 66, 269, 1, 0, 0, 0, 68, + 278, 1, 0, 0, 0, 70, 294, 1, 0, 0, 0, 72, 296, 1, 0, 0, 0, 74, 298, 1, 0, 0, + 0, 76, 303, 1, 0, 0, 0, 78, 306, 1, 0, 0, 0, 80, 310, 1, 0, 0, 0, 82, 312, + 1, 0, 0, 0, 84, 314, 1, 0, 0, 0, 86, 87, 3, 2, 1, 0, 87, 88, 5, 0, 0, 1, 88, + 1, 1, 0, 0, 0, 89, 90, 5, 1, 0, 0, 90, 91, 3, 4, 2, 0, 91, 95, 5, 18, 0, 0, + 92, 94, 3, 6, 3, 0, 93, 92, 1, 0, 0, 0, 94, 97, 1, 0, 0, 0, 95, 93, 1, 0, 0, + 0, 95, 96, 1, 0, 0, 0, 96, 101, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 98, 100, 3, + 12, 6, 0, 99, 98, 1, 0, 0, 0, 100, 103, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, + 101, 102, 1, 0, 0, 0, 102, 104, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 104, 105, + 3, 32, 16, 0, 105, 3, 1, 0, 0, 0, 106, 107, 5, 45, 0, 0, 107, 5, 1, 0, 0, 0, + 108, 109, 7, 0, 0, 0, 109, 110, 3, 8, 4, 0, 110, 111, 5, 26, 0, 0, 111, 7, + 1, 0, 0, 0, 112, 113, 3, 22, 11, 0, 113, 118, 3, 10, 5, 0, 114, 115, 5, 25, + 0, 0, 115, 117, 3, 10, 5, 0, 116, 114, 1, 0, 0, 0, 117, 120, 1, 0, 0, 0, + 118, 116, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 9, 1, 0, 0, 0, 120, 118, 1, + 0, 0, 0, 121, 122, 5, 45, 0, 0, 122, 11, 1, 0, 0, 0, 123, 124, 3, 14, 7, 0, + 124, 125, 3, 16, 8, 0, 125, 13, 1, 0, 0, 0, 126, 127, 7, 1, 0, 0, 127, 15, + 1, 0, 0, 0, 128, 129, 3, 20, 10, 0, 129, 130, 3, 18, 9, 0, 130, 131, 5, 20, + 0, 0, 131, 132, 3, 24, 12, 0, 132, 133, 5, 21, 0, 0, 133, 134, 3, 30, 15, 0, + 134, 17, 1, 0, 0, 0, 135, 136, 5, 45, 0, 0, 136, 19, 1, 0, 0, 0, 137, 140, + 3, 22, 11, 0, 138, 140, 5, 11, 0, 0, 139, 137, 1, 0, 0, 0, 139, 138, 1, 0, + 0, 0, 140, 21, 1, 0, 0, 0, 141, 142, 7, 2, 0, 0, 142, 23, 1, 0, 0, 0, 143, + 148, 3, 26, 13, 0, 144, 145, 5, 25, 0, 0, 145, 147, 3, 26, 13, 0, 146, 144, + 1, 0, 0, 0, 147, 150, 1, 0, 0, 0, 148, 146, 1, 0, 0, 0, 148, 149, 1, 0, 0, + 0, 149, 152, 1, 0, 0, 0, 150, 148, 1, 0, 0, 0, 151, 143, 1, 0, 0, 0, 151, + 152, 1, 0, 0, 0, 152, 25, 1, 0, 0, 0, 153, 154, 3, 22, 11, 0, 154, 155, 3, + 28, 14, 0, 155, 27, 1, 0, 0, 0, 156, 157, 5, 45, 0, 0, 157, 29, 1, 0, 0, 0, + 158, 162, 5, 18, 0, 0, 159, 161, 3, 34, 17, 0, 160, 159, 1, 0, 0, 0, 161, + 164, 1, 0, 0, 0, 162, 160, 1, 0, 0, 0, 162, 163, 1, 0, 0, 0, 163, 165, 1, 0, + 0, 0, 164, 162, 1, 0, 0, 0, 165, 166, 3, 38, 19, 0, 166, 167, 3, 32, 16, 0, + 167, 31, 1, 0, 0, 0, 168, 169, 5, 19, 0, 0, 169, 33, 1, 0, 0, 0, 170, 171, + 5, 7, 0, 0, 171, 172, 3, 22, 11, 0, 172, 177, 3, 36, 18, 0, 173, 174, 5, 25, + 0, 0, 174, 176, 3, 36, 18, 0, 175, 173, 1, 0, 0, 0, 176, 179, 1, 0, 0, 0, + 177, 175, 1, 0, 0, 0, 177, 178, 1, 0, 0, 0, 178, 180, 1, 0, 0, 0, 179, 177, + 1, 0, 0, 0, 180, 181, 5, 26, 0, 0, 181, 35, 1, 0, 0, 0, 182, 183, 5, 45, 0, + 0, 183, 37, 1, 0, 0, 0, 184, 186, 3, 40, 20, 0, 185, 184, 1, 0, 0, 0, 186, + 189, 1, 0, 0, 0, 187, 185, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 39, 1, 0, + 0, 0, 189, 187, 1, 0, 0, 0, 190, 196, 3, 42, 21, 0, 191, 196, 3, 46, 23, 0, + 192, 196, 3, 54, 27, 0, 193, 196, 3, 58, 29, 0, 194, 196, 3, 64, 32, 0, 195, + 190, 1, 0, 0, 0, 195, 191, 1, 0, 0, 0, 195, 192, 1, 0, 0, 0, 195, 193, 1, 0, + 0, 0, 195, 194, 1, 0, 0, 0, 196, 41, 1, 0, 0, 0, 197, 200, 5, 12, 0, 0, 198, + 201, 3, 72, 36, 0, 199, 201, 3, 74, 37, 0, 200, 198, 1, 0, 0, 0, 200, 199, + 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 203, 3, 44, 22, 0, 203, 204, 3, 68, + 34, 0, 204, 205, 5, 26, 0, 0, 205, 43, 1, 0, 0, 0, 206, 207, 5, 27, 0, 0, + 207, 45, 1, 0, 0, 0, 208, 210, 3, 48, 24, 0, 209, 211, 3, 52, 26, 0, 210, + 209, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 47, 1, 0, 0, 0, 212, 213, 5, 14, + 0, 0, 213, 214, 5, 20, 0, 0, 214, 215, 3, 50, 25, 0, 215, 216, 5, 21, 0, 0, + 216, 217, 5, 18, 0, 0, 217, 218, 3, 38, 19, 0, 218, 219, 3, 32, 16, 0, 219, + 49, 1, 0, 0, 0, 220, 221, 3, 68, 34, 0, 221, 51, 1, 0, 0, 0, 222, 223, 5, + 15, 0, 0, 223, 224, 5, 18, 0, 0, 224, 225, 3, 38, 19, 0, 225, 226, 3, 32, + 16, 0, 226, 53, 1, 0, 0, 0, 227, 228, 5, 16, 0, 0, 228, 229, 5, 20, 0, 0, + 229, 230, 3, 56, 28, 0, 230, 231, 5, 21, 0, 0, 231, 232, 5, 18, 0, 0, 232, + 233, 3, 38, 19, 0, 233, 234, 3, 32, 16, 0, 234, 55, 1, 0, 0, 0, 235, 236, 3, + 68, 34, 0, 236, 57, 1, 0, 0, 0, 237, 238, 5, 13, 0, 0, 238, 239, 3, 60, 30, + 0, 239, 240, 5, 26, 0, 0, 240, 59, 1, 0, 0, 0, 241, 242, 3, 62, 31, 0, 242, + 243, 5, 20, 0, 0, 243, 244, 3, 66, 33, 0, 244, 245, 5, 21, 0, 0, 245, 61, 1, + 0, 0, 0, 246, 249, 3, 4, 2, 0, 247, 249, 5, 44, 0, 0, 248, 246, 1, 0, 0, 0, + 248, 247, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 252, 5, 24, 0, 0, 251, 248, + 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 3, 18, 9, + 0, 254, 63, 1, 0, 0, 0, 255, 257, 5, 17, 0, 0, 256, 258, 3, 68, 34, 0, 257, + 256, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 5, + 26, 0, 0, 260, 65, 1, 0, 0, 0, 261, 266, 3, 68, 34, 0, 262, 263, 5, 25, 0, + 0, 263, 265, 3, 68, 34, 0, 264, 262, 1, 0, 0, 0, 265, 268, 1, 0, 0, 0, 266, + 264, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 267, 270, 1, 0, 0, 0, 268, 266, 1, 0, + 0, 0, 269, 261, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 67, 1, 0, 0, 0, 271, + 272, 6, 34, -1, 0, 272, 279, 3, 70, 35, 0, 273, 279, 3, 72, 36, 0, 274, 279, + 3, 60, 30, 0, 275, 279, 3, 74, 37, 0, 276, 279, 3, 76, 38, 0, 277, 279, 3, + 78, 39, 0, 278, 271, 1, 0, 0, 0, 278, 273, 1, 0, 0, 0, 278, 274, 1, 0, 0, 0, + 278, 275, 1, 0, 0, 0, 278, 276, 1, 0, 0, 0, 278, 277, 1, 0, 0, 0, 279, 286, + 1, 0, 0, 0, 280, 281, 10, 2, 0, 0, 281, 282, 3, 84, 42, 0, 282, 283, 3, 68, + 34, 3, 283, 285, 1, 0, 0, 0, 284, 280, 1, 0, 0, 0, 285, 288, 1, 0, 0, 0, + 286, 284, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 69, 1, 0, 0, 0, 288, 286, + 1, 0, 0, 0, 289, 295, 5, 40, 0, 0, 290, 295, 5, 46, 0, 0, 291, 295, 3, 80, + 40, 0, 292, 295, 5, 43, 0, 0, 293, 295, 5, 44, 0, 0, 294, 289, 1, 0, 0, 0, + 294, 290, 1, 0, 0, 0, 294, 291, 1, 0, 0, 0, 294, 292, 1, 0, 0, 0, 294, 293, + 1, 0, 0, 0, 295, 71, 1, 0, 0, 0, 296, 297, 5, 45, 0, 0, 297, 73, 1, 0, 0, 0, + 298, 299, 3, 72, 36, 0, 299, 300, 5, 22, 0, 0, 300, 301, 3, 68, 34, 0, 301, + 302, 5, 23, 0, 0, 302, 75, 1, 0, 0, 0, 303, 304, 3, 82, 41, 0, 304, 305, 3, + 68, 34, 0, 305, 77, 1, 0, 0, 0, 306, 307, 5, 20, 0, 0, 307, 308, 3, 68, 34, + 0, 308, 309, 5, 21, 0, 0, 309, 79, 1, 0, 0, 0, 310, 311, 7, 3, 0, 0, 311, + 81, 1, 0, 0, 0, 312, 313, 7, 4, 0, 0, 313, 83, 1, 0, 0, 0, 314, 315, 7, 5, + 0, 0, 315, 85, 1, 0, 0, 0, 20, 95, 101, 118, 139, 148, 151, 162, 177, 187, + 195, 200, 210, 248, 251, 257, 266, 269, 278, 286, 294, + ]; + + private static __ATN: antlr.ATN; + public static get _ATN(): antlr.ATN { + if (!JackParser.__ATN) { + JackParser.__ATN = new antlr.ATNDeserializer().deserialize( + JackParser._serializedATN, + ); + } + + return JackParser.__ATN; + } + + private static readonly vocabulary = new antlr.Vocabulary( + JackParser.literalNames, + JackParser.symbolicNames, + [], + ); + + public override get vocabulary(): antlr.Vocabulary { + return JackParser.vocabulary; + } + + private static readonly decisionsToDFA = JackParser._ATN.decisionToState.map( + (ds: antlr.DecisionState, index: number) => new antlr.DFA(ds, index), + ); } export class ProgramContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public classDeclaration(): ClassDeclarationContext { - return this.getRuleContext(0, ClassDeclarationContext)!; - } - public EOF(): antlr.TerminalNode { - return this.getToken(JackParser.EOF, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_program; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterProgram) { - listener.enterProgram(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitProgram) { - listener.exitProgram(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public classDeclaration(): ClassDeclarationContext { + return this.getRuleContext(0, ClassDeclarationContext)!; + } + public EOF(): antlr.TerminalNode { + return this.getToken(JackParser.EOF, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_program; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterProgram) { + listener.enterProgram(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitProgram) { + listener.exitProgram(this); + } + } } - export class ClassDeclarationContext extends antlr.ParserRuleContext { - public localSymbolTable: LocalSymbolTable | undefined; - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public CLASS(): antlr.TerminalNode { - return this.getToken(JackParser.CLASS, 0)!; - } - public className(): ClassNameContext { - return this.getRuleContext(0, ClassNameContext)!; - } - public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; - } - public classVarDec(): ClassVarDecContext[]; - public classVarDec(i: number): ClassVarDecContext | null; - public classVarDec(i?: number): ClassVarDecContext[] | ClassVarDecContext | null { - if (i === undefined) { - return this.getRuleContexts(ClassVarDecContext); - } - - return this.getRuleContext(i, ClassVarDecContext); - } - public subroutineDeclaration(): SubroutineDeclarationContext[]; - public subroutineDeclaration(i: number): SubroutineDeclarationContext | null; - public subroutineDeclaration(i?: number): SubroutineDeclarationContext[] | SubroutineDeclarationContext | null { - if (i === undefined) { - return this.getRuleContexts(SubroutineDeclarationContext); - } - - return this.getRuleContext(i, SubroutineDeclarationContext); - } - public override get ruleIndex(): number { - return JackParser.RULE_classDeclaration; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterClassDeclaration) { - listener.enterClassDeclaration(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitClassDeclaration) { - listener.exitClassDeclaration(this); - } - } + public localSymbolTable: LocalSymbolTable | undefined; + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public CLASS(): antlr.TerminalNode { + return this.getToken(JackParser.CLASS, 0)!; + } + public className(): ClassNameContext { + return this.getRuleContext(0, ClassNameContext)!; + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public classVarDec(): ClassVarDecContext[]; + public classVarDec(i: number): ClassVarDecContext | null; + public classVarDec( + i?: number, + ): ClassVarDecContext[] | ClassVarDecContext | null { + if (i === undefined) { + return this.getRuleContexts(ClassVarDecContext); + } + + return this.getRuleContext(i, ClassVarDecContext); + } + public subroutineDeclaration(): SubroutineDeclarationContext[]; + public subroutineDeclaration(i: number): SubroutineDeclarationContext | null; + public subroutineDeclaration( + i?: number, + ): SubroutineDeclarationContext[] | SubroutineDeclarationContext | null { + if (i === undefined) { + return this.getRuleContexts(SubroutineDeclarationContext); + } + + return this.getRuleContext(i, SubroutineDeclarationContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_classDeclaration; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterClassDeclaration) { + listener.enterClassDeclaration(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitClassDeclaration) { + listener.exitClassDeclaration(this); + } + } } - export class ClassNameContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_className; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterClassName) { - listener.enterClassName(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitClassName) { - listener.exitClassName(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_className; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterClassName) { + listener.enterClassName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitClassName) { + listener.exitClassName(this); + } + } } - export class ClassVarDecContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public fieldList(): FieldListContext { - return this.getRuleContext(0, FieldListContext)!; - } - public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; - } - public STATIC(): antlr.TerminalNode | null { - return this.getToken(JackParser.STATIC, 0); - } - public FIELD(): antlr.TerminalNode | null { - return this.getToken(JackParser.FIELD, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_classVarDec; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterClassVarDec) { - listener.enterClassVarDec(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitClassVarDec) { - listener.exitClassVarDec(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public fieldList(): FieldListContext { + return this.getRuleContext(0, FieldListContext)!; + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public STATIC(): antlr.TerminalNode | null { + return this.getToken(JackParser.STATIC, 0); + } + public FIELD(): antlr.TerminalNode | null { + return this.getToken(JackParser.FIELD, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_classVarDec; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterClassVarDec) { + listener.enterClassVarDec(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitClassVarDec) { + listener.exitClassVarDec(this); + } + } } - export class FieldListContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext)!; - } - public fieldName(): FieldNameContext[]; - public fieldName(i: number): FieldNameContext | null; - public fieldName(i?: number): FieldNameContext[] | FieldNameContext | null { - if (i === undefined) { - return this.getRuleContexts(FieldNameContext); - } - - return this.getRuleContext(i, FieldNameContext); - } - public COMMA(): antlr.TerminalNode[]; - public COMMA(i: number): antlr.TerminalNode | null; - public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.COMMA); - } else { - return this.getToken(JackParser.COMMA, i); - } - } - public override get ruleIndex(): number { - return JackParser.RULE_fieldList; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterFieldList) { - listener.enterFieldList(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitFieldList) { - listener.exitFieldList(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext)!; + } + public fieldName(): FieldNameContext[]; + public fieldName(i: number): FieldNameContext | null; + public fieldName(i?: number): FieldNameContext[] | FieldNameContext | null { + if (i === undefined) { + return this.getRuleContexts(FieldNameContext); + } + + return this.getRuleContext(i, FieldNameContext); + } + public COMMA(): antlr.TerminalNode[]; + public COMMA(i: number): antlr.TerminalNode | null; + public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public override get ruleIndex(): number { + return JackParser.RULE_fieldList; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterFieldList) { + listener.enterFieldList(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitFieldList) { + listener.exitFieldList(this); + } + } } - export class FieldNameContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_fieldName; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterFieldName) { - listener.enterFieldName(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitFieldName) { - listener.exitFieldName(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_fieldName; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterFieldName) { + listener.enterFieldName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitFieldName) { + listener.exitFieldName(this); + } + } } - export class SubroutineDeclarationContext extends antlr.ParserRuleContext { - public symbols: SubroutineScope | undefined; - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public subroutineType(): SubroutineTypeContext { - return this.getRuleContext(0, SubroutineTypeContext)!; - } - public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - return this.getRuleContext(0, SubroutineDecWithoutTypeContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_subroutineDeclaration; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineDeclaration) { - listener.enterSubroutineDeclaration(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineDeclaration) { - listener.exitSubroutineDeclaration(this); - } - } + public symbols: SubroutineScope | undefined; + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public subroutineType(): SubroutineTypeContext { + return this.getRuleContext(0, SubroutineTypeContext)!; + } + public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { + return this.getRuleContext(0, SubroutineDecWithoutTypeContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineDeclaration; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineDeclaration) { + listener.enterSubroutineDeclaration(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineDeclaration) { + listener.exitSubroutineDeclaration(this); + } + } } - export class SubroutineTypeContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public CONSTRUCTOR(): antlr.TerminalNode | null { - return this.getToken(JackParser.CONSTRUCTOR, 0); - } - public METHOD(): antlr.TerminalNode | null { - return this.getToken(JackParser.METHOD, 0); - } - public FUNCTION(): antlr.TerminalNode | null { - return this.getToken(JackParser.FUNCTION, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_subroutineType; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineType) { - listener.enterSubroutineType(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineType) { - listener.exitSubroutineType(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public CONSTRUCTOR(): antlr.TerminalNode | null { + return this.getToken(JackParser.CONSTRUCTOR, 0); + } + public METHOD(): antlr.TerminalNode | null { + return this.getToken(JackParser.METHOD, 0); + } + public FUNCTION(): antlr.TerminalNode | null { + return this.getToken(JackParser.FUNCTION, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineType; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineType) { + listener.enterSubroutineType(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineType) { + listener.exitSubroutineType(this); + } + } } - export class SubroutineDecWithoutTypeContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public subroutineReturnType(): SubroutineReturnTypeContext { - return this.getRuleContext(0, SubroutineReturnTypeContext)!; - } - public subroutineName(): SubroutineNameContext { - return this.getRuleContext(0, SubroutineNameContext)!; - } - public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; - } - public parameterList(): ParameterListContext { - return this.getRuleContext(0, ParameterListContext)!; - } - public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; - } - public subroutineBody(): SubroutineBodyContext { - return this.getRuleContext(0, SubroutineBodyContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_subroutineDecWithoutType; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineDecWithoutType) { - listener.enterSubroutineDecWithoutType(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineDecWithoutType) { - listener.exitSubroutineDecWithoutType(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public subroutineReturnType(): SubroutineReturnTypeContext { + return this.getRuleContext(0, SubroutineReturnTypeContext)!; + } + public subroutineName(): SubroutineNameContext { + return this.getRuleContext(0, SubroutineNameContext)!; + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public parameterList(): ParameterListContext { + return this.getRuleContext(0, ParameterListContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public subroutineBody(): SubroutineBodyContext { + return this.getRuleContext(0, SubroutineBodyContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineDecWithoutType; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineDecWithoutType) { + listener.enterSubroutineDecWithoutType(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineDecWithoutType) { + listener.exitSubroutineDecWithoutType(this); + } + } } - export class SubroutineNameContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_subroutineName; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineName) { - listener.enterSubroutineName(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineName) { - listener.exitSubroutineName(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineName; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineName) { + listener.enterSubroutineName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineName) { + listener.exitSubroutineName(this); + } + } } - export class SubroutineReturnTypeContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public varType(): VarTypeContext | null { - return this.getRuleContext(0, VarTypeContext); - } - public VOID(): antlr.TerminalNode | null { - return this.getToken(JackParser.VOID, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_subroutineReturnType; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineReturnType) { - listener.enterSubroutineReturnType(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineReturnType) { - listener.exitSubroutineReturnType(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public varType(): VarTypeContext | null { + return this.getRuleContext(0, VarTypeContext); + } + public VOID(): antlr.TerminalNode | null { + return this.getToken(JackParser.VOID, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineReturnType; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineReturnType) { + listener.enterSubroutineReturnType(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineReturnType) { + listener.exitSubroutineReturnType(this); + } + } } - export class VarTypeContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public INT(): antlr.TerminalNode | null { - return this.getToken(JackParser.INT, 0); - } - public CHAR(): antlr.TerminalNode | null { - return this.getToken(JackParser.CHAR, 0); - } - public BOOLEAN(): antlr.TerminalNode | null { - return this.getToken(JackParser.BOOLEAN, 0); - } - public IDENTIFIER(): antlr.TerminalNode | null { - return this.getToken(JackParser.IDENTIFIER, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_varType; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterVarType) { - listener.enterVarType(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitVarType) { - listener.exitVarType(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public INT(): antlr.TerminalNode | null { + return this.getToken(JackParser.INT, 0); + } + public CHAR(): antlr.TerminalNode | null { + return this.getToken(JackParser.CHAR, 0); + } + public BOOLEAN(): antlr.TerminalNode | null { + return this.getToken(JackParser.BOOLEAN, 0); + } + public IDENTIFIER(): antlr.TerminalNode | null { + return this.getToken(JackParser.IDENTIFIER, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_varType; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterVarType) { + listener.enterVarType(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitVarType) { + listener.exitVarType(this); + } + } } - export class ParameterListContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public parameter(): ParameterContext[]; - public parameter(i: number): ParameterContext | null; - public parameter(i?: number): ParameterContext[] | ParameterContext | null { - if (i === undefined) { - return this.getRuleContexts(ParameterContext); - } - - return this.getRuleContext(i, ParameterContext); - } - public COMMA(): antlr.TerminalNode[]; - public COMMA(i: number): antlr.TerminalNode | null; - public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.COMMA); - } else { - return this.getToken(JackParser.COMMA, i); - } - } - public override get ruleIndex(): number { - return JackParser.RULE_parameterList; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterParameterList) { - listener.enterParameterList(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitParameterList) { - listener.exitParameterList(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public parameter(): ParameterContext[]; + public parameter(i: number): ParameterContext | null; + public parameter(i?: number): ParameterContext[] | ParameterContext | null { + if (i === undefined) { + return this.getRuleContexts(ParameterContext); + } + + return this.getRuleContext(i, ParameterContext); + } + public COMMA(): antlr.TerminalNode[]; + public COMMA(i: number): antlr.TerminalNode | null; + public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public override get ruleIndex(): number { + return JackParser.RULE_parameterList; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterParameterList) { + listener.enterParameterList(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitParameterList) { + listener.exitParameterList(this); + } + } } - export class ParameterContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext)!; - } - public parameterName(): ParameterNameContext { - return this.getRuleContext(0, ParameterNameContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_parameter; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterParameter) { - listener.enterParameter(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitParameter) { - listener.exitParameter(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext)!; + } + public parameterName(): ParameterNameContext { + return this.getRuleContext(0, ParameterNameContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_parameter; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterParameter) { + listener.enterParameter(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitParameter) { + listener.exitParameter(this); + } + } } - export class ParameterNameContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_parameterName; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterParameterName) { - listener.enterParameterName(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitParameterName) { - listener.exitParameterName(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_parameterName; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterParameterName) { + listener.enterParameterName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitParameterName) { + listener.exitParameterName(this); + } + } } - export class SubroutineBodyContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; - } - public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext)!; - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; - } - public varDeclaration(): VarDeclarationContext[]; - public varDeclaration(i: number): VarDeclarationContext | null; - public varDeclaration(i?: number): VarDeclarationContext[] | VarDeclarationContext | null { - if (i === undefined) { - return this.getRuleContexts(VarDeclarationContext); - } - - return this.getRuleContext(i, VarDeclarationContext); - } - public override get ruleIndex(): number { - return JackParser.RULE_subroutineBody; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineBody) { - listener.enterSubroutineBody(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineBody) { - listener.exitSubroutineBody(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public varDeclaration(): VarDeclarationContext[]; + public varDeclaration(i: number): VarDeclarationContext | null; + public varDeclaration( + i?: number, + ): VarDeclarationContext[] | VarDeclarationContext | null { + if (i === undefined) { + return this.getRuleContexts(VarDeclarationContext); + } + + return this.getRuleContext(i, VarDeclarationContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineBody; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineBody) { + listener.enterSubroutineBody(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineBody) { + listener.exitSubroutineBody(this); + } + } } - export class RBraceContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public RBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.RBRACE, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_rBrace; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterRBrace) { - listener.enterRBrace(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitRBrace) { - listener.exitRBrace(this); - } - } -} - - -export class VarDeclarationContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public VAR(): antlr.TerminalNode { - return this.getToken(JackParser.VAR, 0)!; - } - public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext)!; - } - public varNameInDeclaration(): VarNameInDeclarationContext[]; - public varNameInDeclaration(i: number): VarNameInDeclarationContext | null; - public varNameInDeclaration(i?: number): VarNameInDeclarationContext[] | VarNameInDeclarationContext | null { - if (i === undefined) { - return this.getRuleContexts(VarNameInDeclarationContext); - } - - return this.getRuleContext(i, VarNameInDeclarationContext); - } - public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; - } - public COMMA(): antlr.TerminalNode[]; - public COMMA(i: number): antlr.TerminalNode | null; - public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.COMMA); - } else { - return this.getToken(JackParser.COMMA, i); - } - } - public override get ruleIndex(): number { - return JackParser.RULE_varDeclaration; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterVarDeclaration) { - listener.enterVarDeclaration(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitVarDeclaration) { - listener.exitVarDeclaration(this); - } - } -} - - -export class VarNameInDeclarationContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_varNameInDeclaration; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterVarNameInDeclaration) { - listener.enterVarNameInDeclaration(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitVarNameInDeclaration) { - listener.exitVarNameInDeclaration(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public RBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.RBRACE, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_rBrace; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterRBrace) { + listener.enterRBrace(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitRBrace) { + listener.exitRBrace(this); + } + } } - - -export class StatementsContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public statement(): StatementContext[]; - public statement(i: number): StatementContext | null; - public statement(i?: number): StatementContext[] | StatementContext | null { - if (i === undefined) { - return this.getRuleContexts(StatementContext); - } - - return this.getRuleContext(i, StatementContext); - } - public override get ruleIndex(): number { - return JackParser.RULE_statements; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterStatements) { - listener.enterStatements(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitStatements) { - listener.exitStatements(this); - } - } + +export class VarDeclarationContext extends antlr.ParserRuleContext { + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public VAR(): antlr.TerminalNode { + return this.getToken(JackParser.VAR, 0)!; + } + public varType(): VarTypeContext { + return this.getRuleContext(0, VarTypeContext)!; + } + public varNameInDeclaration(): VarNameInDeclarationContext[]; + public varNameInDeclaration(i: number): VarNameInDeclarationContext | null; + public varNameInDeclaration( + i?: number, + ): VarNameInDeclarationContext[] | VarNameInDeclarationContext | null { + if (i === undefined) { + return this.getRuleContexts(VarNameInDeclarationContext); + } + + return this.getRuleContext(i, VarNameInDeclarationContext); + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public COMMA(): antlr.TerminalNode[]; + public COMMA(i: number): antlr.TerminalNode | null; + public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public override get ruleIndex(): number { + return JackParser.RULE_varDeclaration; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterVarDeclaration) { + listener.enterVarDeclaration(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitVarDeclaration) { + listener.exitVarDeclaration(this); + } + } } +export class VarNameInDeclarationContext extends antlr.ParserRuleContext { + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_varNameInDeclaration; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterVarNameInDeclaration) { + listener.enterVarNameInDeclaration(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitVarNameInDeclaration) { + listener.exitVarNameInDeclaration(this); + } + } +} -export class StatementContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public letStatement(): LetStatementContext | null { - return this.getRuleContext(0, LetStatementContext); - } - public ifElseStatement(): IfElseStatementContext | null { - return this.getRuleContext(0, IfElseStatementContext); - } - public whileStatement(): WhileStatementContext | null { - return this.getRuleContext(0, WhileStatementContext); - } - public doStatement(): DoStatementContext | null { - return this.getRuleContext(0, DoStatementContext); - } - public returnStatement(): ReturnStatementContext | null { - return this.getRuleContext(0, ReturnStatementContext); - } - public override get ruleIndex(): number { - return JackParser.RULE_statement; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterStatement) { - listener.enterStatement(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitStatement) { - listener.exitStatement(this); - } - } +export class StatementsContext extends antlr.ParserRuleContext { + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public statement(): StatementContext[]; + public statement(i: number): StatementContext | null; + public statement(i?: number): StatementContext[] | StatementContext | null { + if (i === undefined) { + return this.getRuleContexts(StatementContext); + } + + return this.getRuleContext(i, StatementContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_statements; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterStatements) { + listener.enterStatements(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitStatements) { + listener.exitStatements(this); + } + } } +export class StatementContext extends antlr.ParserRuleContext { + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public letStatement(): LetStatementContext | null { + return this.getRuleContext(0, LetStatementContext); + } + public ifElseStatement(): IfElseStatementContext | null { + return this.getRuleContext(0, IfElseStatementContext); + } + public whileStatement(): WhileStatementContext | null { + return this.getRuleContext(0, WhileStatementContext); + } + public doStatement(): DoStatementContext | null { + return this.getRuleContext(0, DoStatementContext); + } + public returnStatement(): ReturnStatementContext | null { + return this.getRuleContext(0, ReturnStatementContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_statement; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterStatement) { + listener.enterStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitStatement) { + listener.exitStatement(this); + } + } +} export class LetStatementContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public LET(): antlr.TerminalNode { - return this.getToken(JackParser.LET, 0)!; - } - public equals(): EqualsContext { - return this.getRuleContext(0, EqualsContext)!; - } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; - } - public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; - } - public varName(): VarNameContext | null { - return this.getRuleContext(0, VarNameContext); - } - public arrayAccess(): ArrayAccessContext | null { - return this.getRuleContext(0, ArrayAccessContext); - } - public override get ruleIndex(): number { - return JackParser.RULE_letStatement; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterLetStatement) { - listener.enterLetStatement(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitLetStatement) { - listener.exitLetStatement(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public LET(): antlr.TerminalNode { + return this.getToken(JackParser.LET, 0)!; + } + public equals(): EqualsContext { + return this.getRuleContext(0, EqualsContext)!; + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public varName(): VarNameContext | null { + return this.getRuleContext(0, VarNameContext); + } + public arrayAccess(): ArrayAccessContext | null { + return this.getRuleContext(0, ArrayAccessContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_letStatement; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterLetStatement) { + listener.enterLetStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitLetStatement) { + listener.exitLetStatement(this); + } + } } - export class EqualsContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public EQUALS(): antlr.TerminalNode { - return this.getToken(JackParser.EQUALS, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_equals; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterEquals) { - listener.enterEquals(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitEquals) { - listener.exitEquals(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public EQUALS(): antlr.TerminalNode { + return this.getToken(JackParser.EQUALS, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_equals; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterEquals) { + listener.enterEquals(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitEquals) { + listener.exitEquals(this); + } + } } - export class IfElseStatementContext extends antlr.ParserRuleContext { - public endLabel: string = ""; - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public ifStatement(): IfStatementContext { - return this.getRuleContext(0, IfStatementContext)!; - } - public elseStatement(): ElseStatementContext | null { - return this.getRuleContext(0, ElseStatementContext); - } - public override get ruleIndex(): number { - return JackParser.RULE_ifElseStatement; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterIfElseStatement) { - listener.enterIfElseStatement(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitIfElseStatement) { - listener.exitIfElseStatement(this); - } - } + public endLabel: string = ""; + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public ifStatement(): IfStatementContext { + return this.getRuleContext(0, IfStatementContext)!; + } + public elseStatement(): ElseStatementContext | null { + return this.getRuleContext(0, ElseStatementContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_ifElseStatement; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterIfElseStatement) { + listener.enterIfElseStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitIfElseStatement) { + listener.exitIfElseStatement(this); + } + } } - export class IfStatementContext extends antlr.ParserRuleContext { - public endLabel: string = ""; - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public IF(): antlr.TerminalNode { - return this.getToken(JackParser.IF, 0)!; - } - public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; - } - public ifExpression(): IfExpressionContext { - return this.getRuleContext(0, IfExpressionContext)!; - } - public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; - } - public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; - } - public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext)!; - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_ifStatement; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterIfStatement) { - listener.enterIfStatement(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitIfStatement) { - listener.exitIfStatement(this); - } - } + public endLabel: string = ""; + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public IF(): antlr.TerminalNode { + return this.getToken(JackParser.IF, 0)!; + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public ifExpression(): IfExpressionContext { + return this.getRuleContext(0, IfExpressionContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_ifStatement; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterIfStatement) { + listener.enterIfStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitIfStatement) { + listener.exitIfStatement(this); + } + } } - export class IfExpressionContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_ifExpression; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterIfExpression) { - listener.enterIfExpression(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitIfExpression) { - listener.exitIfExpression(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_ifExpression; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterIfExpression) { + listener.enterIfExpression(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitIfExpression) { + listener.exitIfExpression(this); + } + } } - export class ElseStatementContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public ELSE(): antlr.TerminalNode { - return this.getToken(JackParser.ELSE, 0)!; - } - public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; - } - public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext)!; - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_elseStatement; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterElseStatement) { - listener.enterElseStatement(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitElseStatement) { - listener.exitElseStatement(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public ELSE(): antlr.TerminalNode { + return this.getToken(JackParser.ELSE, 0)!; + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_elseStatement; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterElseStatement) { + listener.enterElseStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitElseStatement) { + listener.exitElseStatement(this); + } + } } - export class WhileStatementContext extends antlr.ParserRuleContext { - public startLabel: string = "";endLabel:string="";; - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public WHILE(): antlr.TerminalNode { - return this.getToken(JackParser.WHILE, 0)!; - } - public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; - } - public whileExpression(): WhileExpressionContext { - return this.getRuleContext(0, WhileExpressionContext)!; - } - public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; - } - public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; - } - public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext)!; - } - public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_whileStatement; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterWhileStatement) { - listener.enterWhileStatement(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitWhileStatement) { - listener.exitWhileStatement(this); - } - } + public startLabel: string = ""; + endLabel: string = ""; + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public WHILE(): antlr.TerminalNode { + return this.getToken(JackParser.WHILE, 0)!; + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public whileExpression(): WhileExpressionContext { + return this.getRuleContext(0, WhileExpressionContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public LBRACE(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACE, 0)!; + } + public statements(): StatementsContext { + return this.getRuleContext(0, StatementsContext)!; + } + public rBrace(): RBraceContext { + return this.getRuleContext(0, RBraceContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_whileStatement; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterWhileStatement) { + listener.enterWhileStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitWhileStatement) { + listener.exitWhileStatement(this); + } + } } - export class WhileExpressionContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_whileExpression; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterWhileExpression) { - listener.enterWhileExpression(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitWhileExpression) { - listener.exitWhileExpression(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_whileExpression; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterWhileExpression) { + listener.enterWhileExpression(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitWhileExpression) { + listener.exitWhileExpression(this); + } + } } - export class DoStatementContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public DO(): antlr.TerminalNode { - return this.getToken(JackParser.DO, 0)!; - } - public subroutineCall(): SubroutineCallContext { - return this.getRuleContext(0, SubroutineCallContext)!; - } - public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_doStatement; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterDoStatement) { - listener.enterDoStatement(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitDoStatement) { - listener.exitDoStatement(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public DO(): antlr.TerminalNode { + return this.getToken(JackParser.DO, 0)!; + } + public subroutineCall(): SubroutineCallContext { + return this.getRuleContext(0, SubroutineCallContext)!; + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_doStatement; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterDoStatement) { + listener.enterDoStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitDoStatement) { + listener.exitDoStatement(this); + } + } } - export class SubroutineCallContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public subroutineId(): SubroutineIdContext { - return this.getRuleContext(0, SubroutineIdContext)!; - } - public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; - } - public expressionList(): ExpressionListContext { - return this.getRuleContext(0, ExpressionListContext)!; - } - public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_subroutineCall; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineCall) { - listener.enterSubroutineCall(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineCall) { - listener.exitSubroutineCall(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public subroutineId(): SubroutineIdContext { + return this.getRuleContext(0, SubroutineIdContext)!; + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public expressionList(): ExpressionListContext { + return this.getRuleContext(0, ExpressionListContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineCall; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineCall) { + listener.enterSubroutineCall(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineCall) { + listener.exitSubroutineCall(this); + } + } } - export class SubroutineIdContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public subroutineName(): SubroutineNameContext { - return this.getRuleContext(0, SubroutineNameContext)!; - } - public DOT(): antlr.TerminalNode | null { - return this.getToken(JackParser.DOT, 0); - } - public className(): ClassNameContext | null { - return this.getRuleContext(0, ClassNameContext); - } - public THIS_LITERAL(): antlr.TerminalNode | null { - return this.getToken(JackParser.THIS_LITERAL, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_subroutineId; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterSubroutineId) { - listener.enterSubroutineId(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitSubroutineId) { - listener.exitSubroutineId(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public subroutineName(): SubroutineNameContext { + return this.getRuleContext(0, SubroutineNameContext)!; + } + public DOT(): antlr.TerminalNode | null { + return this.getToken(JackParser.DOT, 0); + } + public className(): ClassNameContext | null { + return this.getRuleContext(0, ClassNameContext); + } + public THIS_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.THIS_LITERAL, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_subroutineId; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterSubroutineId) { + listener.enterSubroutineId(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitSubroutineId) { + listener.exitSubroutineId(this); + } + } } - export class ReturnStatementContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public RETURN(): antlr.TerminalNode { - return this.getToken(JackParser.RETURN, 0)!; - } - public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; - } - public expression(): ExpressionContext | null { - return this.getRuleContext(0, ExpressionContext); - } - public override get ruleIndex(): number { - return JackParser.RULE_returnStatement; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterReturnStatement) { - listener.enterReturnStatement(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitReturnStatement) { - listener.exitReturnStatement(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public RETURN(): antlr.TerminalNode { + return this.getToken(JackParser.RETURN, 0)!; + } + public SEMICOLON(): antlr.TerminalNode { + return this.getToken(JackParser.SEMICOLON, 0)!; + } + public expression(): ExpressionContext | null { + return this.getRuleContext(0, ExpressionContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_returnStatement; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterReturnStatement) { + listener.enterReturnStatement(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitReturnStatement) { + listener.exitReturnStatement(this); + } + } } - export class ExpressionListContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public expression(): ExpressionContext[]; - public expression(i: number): ExpressionContext | null; - public expression(i?: number): ExpressionContext[] | ExpressionContext | null { - if (i === undefined) { - return this.getRuleContexts(ExpressionContext); - } - - return this.getRuleContext(i, ExpressionContext); - } - public COMMA(): antlr.TerminalNode[]; - public COMMA(i: number): antlr.TerminalNode | null; - public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { - if (i === undefined) { - return this.getTokens(JackParser.COMMA); - } else { - return this.getToken(JackParser.COMMA, i); - } - } - public override get ruleIndex(): number { - return JackParser.RULE_expressionList; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterExpressionList) { - listener.enterExpressionList(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitExpressionList) { - listener.exitExpressionList(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public expression(): ExpressionContext[]; + public expression(i: number): ExpressionContext | null; + public expression( + i?: number, + ): ExpressionContext[] | ExpressionContext | null { + if (i === undefined) { + return this.getRuleContexts(ExpressionContext); + } + + return this.getRuleContext(i, ExpressionContext); + } + public COMMA(): antlr.TerminalNode[]; + public COMMA(i: number): antlr.TerminalNode | null; + public COMMA(i?: number): antlr.TerminalNode | null | antlr.TerminalNode[] { + if (i === undefined) { + return this.getTokens(JackParser.COMMA); + } else { + return this.getToken(JackParser.COMMA, i); + } + } + public override get ruleIndex(): number { + return JackParser.RULE_expressionList; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterExpressionList) { + listener.enterExpressionList(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitExpressionList) { + listener.exitExpressionList(this); + } + } } - export class ExpressionContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public constant(): ConstantContext | null { - return this.getRuleContext(0, ConstantContext); - } - public varName(): VarNameContext | null { - return this.getRuleContext(0, VarNameContext); - } - public subroutineCall(): SubroutineCallContext | null { - return this.getRuleContext(0, SubroutineCallContext); - } - public arrayAccess(): ArrayAccessContext | null { - return this.getRuleContext(0, ArrayAccessContext); - } - public unaryOperation(): UnaryOperationContext | null { - return this.getRuleContext(0, UnaryOperationContext); - } - public groupedExpression(): GroupedExpressionContext | null { - return this.getRuleContext(0, GroupedExpressionContext); - } - public expression(): ExpressionContext[]; - public expression(i: number): ExpressionContext | null; - public expression(i?: number): ExpressionContext[] | ExpressionContext | null { - if (i === undefined) { - return this.getRuleContexts(ExpressionContext); - } - - return this.getRuleContext(i, ExpressionContext); - } - public binaryOperator(): BinaryOperatorContext | null { - return this.getRuleContext(0, BinaryOperatorContext); - } - public override get ruleIndex(): number { - return JackParser.RULE_expression; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterExpression) { - listener.enterExpression(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitExpression) { - listener.exitExpression(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public constant(): ConstantContext | null { + return this.getRuleContext(0, ConstantContext); + } + public varName(): VarNameContext | null { + return this.getRuleContext(0, VarNameContext); + } + public subroutineCall(): SubroutineCallContext | null { + return this.getRuleContext(0, SubroutineCallContext); + } + public arrayAccess(): ArrayAccessContext | null { + return this.getRuleContext(0, ArrayAccessContext); + } + public unaryOperation(): UnaryOperationContext | null { + return this.getRuleContext(0, UnaryOperationContext); + } + public groupedExpression(): GroupedExpressionContext | null { + return this.getRuleContext(0, GroupedExpressionContext); + } + public expression(): ExpressionContext[]; + public expression(i: number): ExpressionContext | null; + public expression( + i?: number, + ): ExpressionContext[] | ExpressionContext | null { + if (i === undefined) { + return this.getRuleContexts(ExpressionContext); + } + + return this.getRuleContext(i, ExpressionContext); + } + public binaryOperator(): BinaryOperatorContext | null { + return this.getRuleContext(0, BinaryOperatorContext); + } + public override get ruleIndex(): number { + return JackParser.RULE_expression; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterExpression) { + listener.enterExpression(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitExpression) { + listener.exitExpression(this); + } + } } - export class ConstantContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public INTEGER_LITERAL(): antlr.TerminalNode | null { - return this.getToken(JackParser.INTEGER_LITERAL, 0); - } - public STRING_LITERAL(): antlr.TerminalNode | null { - return this.getToken(JackParser.STRING_LITERAL, 0); - } - public booleanLiteral(): BooleanLiteralContext | null { - return this.getRuleContext(0, BooleanLiteralContext); - } - public NULL_LITERAL(): antlr.TerminalNode | null { - return this.getToken(JackParser.NULL_LITERAL, 0); - } - public THIS_LITERAL(): antlr.TerminalNode | null { - return this.getToken(JackParser.THIS_LITERAL, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_constant; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterConstant) { - listener.enterConstant(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitConstant) { - listener.exitConstant(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public INTEGER_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.INTEGER_LITERAL, 0); + } + public STRING_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.STRING_LITERAL, 0); + } + public booleanLiteral(): BooleanLiteralContext | null { + return this.getRuleContext(0, BooleanLiteralContext); + } + public NULL_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.NULL_LITERAL, 0); + } + public THIS_LITERAL(): antlr.TerminalNode | null { + return this.getToken(JackParser.THIS_LITERAL, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_constant; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterConstant) { + listener.enterConstant(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitConstant) { + listener.exitConstant(this); + } + } } - export class VarNameContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_varName; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterVarName) { - listener.enterVarName(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitVarName) { - listener.exitVarName(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public IDENTIFIER(): antlr.TerminalNode { + return this.getToken(JackParser.IDENTIFIER, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_varName; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterVarName) { + listener.enterVarName(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitVarName) { + listener.exitVarName(this); + } + } } - export class ArrayAccessContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public varName(): VarNameContext { - return this.getRuleContext(0, VarNameContext)!; - } - public LBRACKET(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACKET, 0)!; - } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; - } - public RBRACKET(): antlr.TerminalNode { - return this.getToken(JackParser.RBRACKET, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_arrayAccess; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterArrayAccess) { - listener.enterArrayAccess(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitArrayAccess) { - listener.exitArrayAccess(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public varName(): VarNameContext { + return this.getRuleContext(0, VarNameContext)!; + } + public LBRACKET(): antlr.TerminalNode { + return this.getToken(JackParser.LBRACKET, 0)!; + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public RBRACKET(): antlr.TerminalNode { + return this.getToken(JackParser.RBRACKET, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_arrayAccess; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterArrayAccess) { + listener.enterArrayAccess(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitArrayAccess) { + listener.exitArrayAccess(this); + } + } } - export class UnaryOperationContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public unaryOperator(): UnaryOperatorContext { - return this.getRuleContext(0, UnaryOperatorContext)!; - } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_unaryOperation; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterUnaryOperation) { - listener.enterUnaryOperation(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitUnaryOperation) { - listener.exitUnaryOperation(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public unaryOperator(): UnaryOperatorContext { + return this.getRuleContext(0, UnaryOperatorContext)!; + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_unaryOperation; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterUnaryOperation) { + listener.enterUnaryOperation(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitUnaryOperation) { + listener.exitUnaryOperation(this); + } + } } - export class GroupedExpressionContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; - } - public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; - } - public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; - } - public override get ruleIndex(): number { - return JackParser.RULE_groupedExpression; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterGroupedExpression) { - listener.enterGroupedExpression(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitGroupedExpression) { - listener.exitGroupedExpression(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public LPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.LPAREN, 0)!; + } + public expression(): ExpressionContext { + return this.getRuleContext(0, ExpressionContext)!; + } + public RPAREN(): antlr.TerminalNode { + return this.getToken(JackParser.RPAREN, 0)!; + } + public override get ruleIndex(): number { + return JackParser.RULE_groupedExpression; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterGroupedExpression) { + listener.enterGroupedExpression(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitGroupedExpression) { + listener.exitGroupedExpression(this); + } + } } - export class BooleanLiteralContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public TRUE(): antlr.TerminalNode | null { - return this.getToken(JackParser.TRUE, 0); - } - public FALSE(): antlr.TerminalNode | null { - return this.getToken(JackParser.FALSE, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_booleanLiteral; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterBooleanLiteral) { - listener.enterBooleanLiteral(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitBooleanLiteral) { - listener.exitBooleanLiteral(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public TRUE(): antlr.TerminalNode | null { + return this.getToken(JackParser.TRUE, 0); + } + public FALSE(): antlr.TerminalNode | null { + return this.getToken(JackParser.FALSE, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_booleanLiteral; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterBooleanLiteral) { + listener.enterBooleanLiteral(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitBooleanLiteral) { + listener.exitBooleanLiteral(this); + } + } } - export class UnaryOperatorContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public TILDE(): antlr.TerminalNode | null { - return this.getToken(JackParser.TILDE, 0); - } - public MINUS(): antlr.TerminalNode | null { - return this.getToken(JackParser.MINUS, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_unaryOperator; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterUnaryOperator) { - listener.enterUnaryOperator(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitUnaryOperator) { - listener.exitUnaryOperator(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public TILDE(): antlr.TerminalNode | null { + return this.getToken(JackParser.TILDE, 0); + } + public MINUS(): antlr.TerminalNode | null { + return this.getToken(JackParser.MINUS, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_unaryOperator; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterUnaryOperator) { + listener.enterUnaryOperator(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitUnaryOperator) { + listener.exitUnaryOperator(this); + } + } } - export class BinaryOperatorContext extends antlr.ParserRuleContext { - public constructor(parent: antlr.ParserRuleContext | null, invokingState: number) { - super(parent, invokingState); - } - public PLUS(): antlr.TerminalNode | null { - return this.getToken(JackParser.PLUS, 0); - } - public MINUS(): antlr.TerminalNode | null { - return this.getToken(JackParser.MINUS, 0); - } - public MUL(): antlr.TerminalNode | null { - return this.getToken(JackParser.MUL, 0); - } - public DIV(): antlr.TerminalNode | null { - return this.getToken(JackParser.DIV, 0); - } - public AND(): antlr.TerminalNode | null { - return this.getToken(JackParser.AND, 0); - } - public OR(): antlr.TerminalNode | null { - return this.getToken(JackParser.OR, 0); - } - public LESS_THAN(): antlr.TerminalNode | null { - return this.getToken(JackParser.LESS_THAN, 0); - } - public GREATER_THAN(): antlr.TerminalNode | null { - return this.getToken(JackParser.GREATER_THAN, 0); - } - public EQUALS(): antlr.TerminalNode | null { - return this.getToken(JackParser.EQUALS, 0); - } - public override get ruleIndex(): number { - return JackParser.RULE_binaryOperator; - } - public override enterRule(listener: JackParserListener): void { - if(listener.enterBinaryOperator) { - listener.enterBinaryOperator(this); - } - } - public override exitRule(listener: JackParserListener): void { - if(listener.exitBinaryOperator) { - listener.exitBinaryOperator(this); - } - } + public constructor( + parent: antlr.ParserRuleContext | null, + invokingState: number, + ) { + super(parent, invokingState); + } + public PLUS(): antlr.TerminalNode | null { + return this.getToken(JackParser.PLUS, 0); + } + public MINUS(): antlr.TerminalNode | null { + return this.getToken(JackParser.MINUS, 0); + } + public MUL(): antlr.TerminalNode | null { + return this.getToken(JackParser.MUL, 0); + } + public DIV(): antlr.TerminalNode | null { + return this.getToken(JackParser.DIV, 0); + } + public AND(): antlr.TerminalNode | null { + return this.getToken(JackParser.AND, 0); + } + public OR(): antlr.TerminalNode | null { + return this.getToken(JackParser.OR, 0); + } + public LESS_THAN(): antlr.TerminalNode | null { + return this.getToken(JackParser.LESS_THAN, 0); + } + public GREATER_THAN(): antlr.TerminalNode | null { + return this.getToken(JackParser.GREATER_THAN, 0); + } + public EQUALS(): antlr.TerminalNode | null { + return this.getToken(JackParser.EQUALS, 0); + } + public override get ruleIndex(): number { + return JackParser.RULE_binaryOperator; + } + public override enterRule(listener: JackParserListener): void { + if (listener.enterBinaryOperator) { + listener.enterBinaryOperator(this); + } + } + public override exitRule(listener: JackParserListener): void { + if (listener.exitBinaryOperator) { + listener.exitBinaryOperator(this); + } + } } diff --git a/simulator/src/jack/generated/JackParserListener.ts b/simulator/src/jack/generated/JackParserListener.ts index cbdfb388..cebcc430 100644 --- a/simulator/src/jack/generated/JackParserListener.ts +++ b/simulator/src/jack/generated/JackParserListener.ts @@ -1,11 +1,14 @@ // Generated from JackParser.g4 by ANTLR 4.13.1 -import { ErrorNode, ParseTreeListener, ParserRuleContext, TerminalNode } from "antlr4ng"; - +import { + ErrorNode, + ParseTreeListener, + ParserRuleContext, + TerminalNode, +} from "antlr4ng"; import { SubroutineScope, LocalSymbolTable } from "../symbol.js"; - import { ProgramContext } from "./JackParser.js"; import { ClassDeclarationContext } from "./JackParser.js"; import { ClassNameContext } from "./JackParser.js"; @@ -50,446 +53,446 @@ import { BooleanLiteralContext } from "./JackParser.js"; import { UnaryOperatorContext } from "./JackParser.js"; import { BinaryOperatorContext } from "./JackParser.js"; - /** * This interface defines a complete listener for a parse tree produced by * `JackParser`. */ export class JackParserListener implements ParseTreeListener { - /** - * Enter a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - */ - enterProgram?: (ctx: ProgramContext) => void; - /** - * Exit a parse tree produced by `JackParser.program`. - * @param ctx the parse tree - */ - exitProgram?: (ctx: ProgramContext) => void; - /** - * Enter a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - */ - enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.classDeclaration`. - * @param ctx the parse tree - */ - exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - */ - enterClassName?: (ctx: ClassNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.className`. - * @param ctx the parse tree - */ - exitClassName?: (ctx: ClassNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - */ - enterClassVarDec?: (ctx: ClassVarDecContext) => void; - /** - * Exit a parse tree produced by `JackParser.classVarDec`. - * @param ctx the parse tree - */ - exitClassVarDec?: (ctx: ClassVarDecContext) => void; - /** - * Enter a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - */ - enterFieldList?: (ctx: FieldListContext) => void; - /** - * Exit a parse tree produced by `JackParser.fieldList`. - * @param ctx the parse tree - */ - exitFieldList?: (ctx: FieldListContext) => void; - /** - * Enter a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - */ - enterFieldName?: (ctx: FieldNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.fieldName`. - * @param ctx the parse tree - */ - exitFieldName?: (ctx: FieldNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineDeclaration`. - * @param ctx the parse tree - */ - exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - */ - enterSubroutineType?: (ctx: SubroutineTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineType`. - * @param ctx the parse tree - */ - exitSubroutineType?: (ctx: SubroutineTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - */ - enterSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. - * @param ctx the parse tree - */ - exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - */ - enterSubroutineName?: (ctx: SubroutineNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineName`. - * @param ctx the parse tree - */ - exitSubroutineName?: (ctx: SubroutineNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - */ - enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineReturnType`. - * @param ctx the parse tree - */ - exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - */ - enterVarType?: (ctx: VarTypeContext) => void; - /** - * Exit a parse tree produced by `JackParser.varType`. - * @param ctx the parse tree - */ - exitVarType?: (ctx: VarTypeContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - */ - enterParameterList?: (ctx: ParameterListContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameterList`. - * @param ctx the parse tree - */ - exitParameterList?: (ctx: ParameterListContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - */ - enterParameter?: (ctx: ParameterContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameter`. - * @param ctx the parse tree - */ - exitParameter?: (ctx: ParameterContext) => void; - /** - * Enter a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - */ - enterParameterName?: (ctx: ParameterNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.parameterName`. - * @param ctx the parse tree - */ - exitParameterName?: (ctx: ParameterNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - */ - enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineBody`. - * @param ctx the parse tree - */ - exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; - /** - * Enter a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - */ - enterRBrace?: (ctx: RBraceContext) => void; - /** - * Exit a parse tree produced by `JackParser.rBrace`. - * @param ctx the parse tree - */ - exitRBrace?: (ctx: RBraceContext) => void; - /** - * Enter a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - */ - enterVarDeclaration?: (ctx: VarDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.varDeclaration`. - * @param ctx the parse tree - */ - exitVarDeclaration?: (ctx: VarDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - */ - enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; - /** - * Exit a parse tree produced by `JackParser.varNameInDeclaration`. - * @param ctx the parse tree - */ - exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; - /** - * Enter a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - */ - enterStatements?: (ctx: StatementsContext) => void; - /** - * Exit a parse tree produced by `JackParser.statements`. - * @param ctx the parse tree - */ - exitStatements?: (ctx: StatementsContext) => void; - /** - * Enter a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - */ - enterStatement?: (ctx: StatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.statement`. - * @param ctx the parse tree - */ - exitStatement?: (ctx: StatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - */ - enterLetStatement?: (ctx: LetStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.letStatement`. - * @param ctx the parse tree - */ - exitLetStatement?: (ctx: LetStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.equals`. - * @param ctx the parse tree - */ - enterEquals?: (ctx: EqualsContext) => void; - /** - * Exit a parse tree produced by `JackParser.equals`. - * @param ctx the parse tree - */ - exitEquals?: (ctx: EqualsContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - */ - enterIfElseStatement?: (ctx: IfElseStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifElseStatement`. - * @param ctx the parse tree - */ - exitIfElseStatement?: (ctx: IfElseStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - */ - enterIfStatement?: (ctx: IfStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifStatement`. - * @param ctx the parse tree - */ - exitIfStatement?: (ctx: IfStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.ifExpression`. - * @param ctx the parse tree - */ - enterIfExpression?: (ctx: IfExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.ifExpression`. - * @param ctx the parse tree - */ - exitIfExpression?: (ctx: IfExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - */ - enterElseStatement?: (ctx: ElseStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.elseStatement`. - * @param ctx the parse tree - */ - exitElseStatement?: (ctx: ElseStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - */ - enterWhileStatement?: (ctx: WhileStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.whileStatement`. - * @param ctx the parse tree - */ - exitWhileStatement?: (ctx: WhileStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.whileExpression`. - * @param ctx the parse tree - */ - enterWhileExpression?: (ctx: WhileExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.whileExpression`. - * @param ctx the parse tree - */ - exitWhileExpression?: (ctx: WhileExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - */ - enterDoStatement?: (ctx: DoStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.doStatement`. - * @param ctx the parse tree - */ - exitDoStatement?: (ctx: DoStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - */ - enterSubroutineCall?: (ctx: SubroutineCallContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineCall`. - * @param ctx the parse tree - */ - exitSubroutineCall?: (ctx: SubroutineCallContext) => void; - /** - * Enter a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - */ - enterSubroutineId?: (ctx: SubroutineIdContext) => void; - /** - * Exit a parse tree produced by `JackParser.subroutineId`. - * @param ctx the parse tree - */ - exitSubroutineId?: (ctx: SubroutineIdContext) => void; - /** - * Enter a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - */ - enterReturnStatement?: (ctx: ReturnStatementContext) => void; - /** - * Exit a parse tree produced by `JackParser.returnStatement`. - * @param ctx the parse tree - */ - exitReturnStatement?: (ctx: ReturnStatementContext) => void; - /** - * Enter a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - */ - enterExpressionList?: (ctx: ExpressionListContext) => void; - /** - * Exit a parse tree produced by `JackParser.expressionList`. - * @param ctx the parse tree - */ - exitExpressionList?: (ctx: ExpressionListContext) => void; - /** - * Enter a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - */ - enterExpression?: (ctx: ExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.expression`. - * @param ctx the parse tree - */ - exitExpression?: (ctx: ExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - */ - enterConstant?: (ctx: ConstantContext) => void; - /** - * Exit a parse tree produced by `JackParser.constant`. - * @param ctx the parse tree - */ - exitConstant?: (ctx: ConstantContext) => void; - /** - * Enter a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - */ - enterVarName?: (ctx: VarNameContext) => void; - /** - * Exit a parse tree produced by `JackParser.varName`. - * @param ctx the parse tree - */ - exitVarName?: (ctx: VarNameContext) => void; - /** - * Enter a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - */ - enterArrayAccess?: (ctx: ArrayAccessContext) => void; - /** - * Exit a parse tree produced by `JackParser.arrayAccess`. - * @param ctx the parse tree - */ - exitArrayAccess?: (ctx: ArrayAccessContext) => void; - /** - * Enter a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - */ - enterUnaryOperation?: (ctx: UnaryOperationContext) => void; - /** - * Exit a parse tree produced by `JackParser.unaryOperation`. - * @param ctx the parse tree - */ - exitUnaryOperation?: (ctx: UnaryOperationContext) => void; - /** - * Enter a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - */ - enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; - /** - * Exit a parse tree produced by `JackParser.groupedExpression`. - * @param ctx the parse tree - */ - exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; - /** - * Enter a parse tree produced by `JackParser.booleanLiteral`. - * @param ctx the parse tree - */ - enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; - /** - * Exit a parse tree produced by `JackParser.booleanLiteral`. - * @param ctx the parse tree - */ - exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; - /** - * Enter a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - */ - enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; - /** - * Exit a parse tree produced by `JackParser.unaryOperator`. - * @param ctx the parse tree - */ - exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; - /** - * Enter a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - */ - enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; - /** - * Exit a parse tree produced by `JackParser.binaryOperator`. - * @param ctx the parse tree - */ - exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; + /** + * Enter a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + enterProgram?: (ctx: ProgramContext) => void; + /** + * Exit a parse tree produced by `JackParser.program`. + * @param ctx the parse tree + */ + exitProgram?: (ctx: ProgramContext) => void; + /** + * Enter a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + enterClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.classDeclaration`. + * @param ctx the parse tree + */ + exitClassDeclaration?: (ctx: ClassDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + enterClassName?: (ctx: ClassNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.className`. + * @param ctx the parse tree + */ + exitClassName?: (ctx: ClassNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + enterClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Exit a parse tree produced by `JackParser.classVarDec`. + * @param ctx the parse tree + */ + exitClassVarDec?: (ctx: ClassVarDecContext) => void; + /** + * Enter a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + enterFieldList?: (ctx: FieldListContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldList`. + * @param ctx the parse tree + */ + exitFieldList?: (ctx: FieldListContext) => void; + /** + * Enter a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + enterFieldName?: (ctx: FieldNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.fieldName`. + * @param ctx the parse tree + */ + exitFieldName?: (ctx: FieldNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineDeclaration`. + * @param ctx the parse tree + */ + enterSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDeclaration`. + * @param ctx the parse tree + */ + exitSubroutineDeclaration?: (ctx: SubroutineDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + enterSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineType`. + * @param ctx the parse tree + */ + exitSubroutineType?: (ctx: SubroutineTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + enterSubroutineDecWithoutType?: ( + ctx: SubroutineDecWithoutTypeContext, + ) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineDecWithoutType`. + * @param ctx the parse tree + */ + exitSubroutineDecWithoutType?: (ctx: SubroutineDecWithoutTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + enterSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineName`. + * @param ctx the parse tree + */ + exitSubroutineName?: (ctx: SubroutineNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + enterSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineReturnType`. + * @param ctx the parse tree + */ + exitSubroutineReturnType?: (ctx: SubroutineReturnTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + enterVarType?: (ctx: VarTypeContext) => void; + /** + * Exit a parse tree produced by `JackParser.varType`. + * @param ctx the parse tree + */ + exitVarType?: (ctx: VarTypeContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + enterParameterList?: (ctx: ParameterListContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterList`. + * @param ctx the parse tree + */ + exitParameterList?: (ctx: ParameterListContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + enterParameter?: (ctx: ParameterContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameter`. + * @param ctx the parse tree + */ + exitParameter?: (ctx: ParameterContext) => void; + /** + * Enter a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + enterParameterName?: (ctx: ParameterNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.parameterName`. + * @param ctx the parse tree + */ + exitParameterName?: (ctx: ParameterNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + enterSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineBody`. + * @param ctx the parse tree + */ + exitSubroutineBody?: (ctx: SubroutineBodyContext) => void; + /** + * Enter a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + enterRBrace?: (ctx: RBraceContext) => void; + /** + * Exit a parse tree produced by `JackParser.rBrace`. + * @param ctx the parse tree + */ + exitRBrace?: (ctx: RBraceContext) => void; + /** + * Enter a parse tree produced by `JackParser.varDeclaration`. + * @param ctx the parse tree + */ + enterVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varDeclaration`. + * @param ctx the parse tree + */ + exitVarDeclaration?: (ctx: VarDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + enterVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Exit a parse tree produced by `JackParser.varNameInDeclaration`. + * @param ctx the parse tree + */ + exitVarNameInDeclaration?: (ctx: VarNameInDeclarationContext) => void; + /** + * Enter a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + enterStatements?: (ctx: StatementsContext) => void; + /** + * Exit a parse tree produced by `JackParser.statements`. + * @param ctx the parse tree + */ + exitStatements?: (ctx: StatementsContext) => void; + /** + * Enter a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + enterStatement?: (ctx: StatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.statement`. + * @param ctx the parse tree + */ + exitStatement?: (ctx: StatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + enterLetStatement?: (ctx: LetStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.letStatement`. + * @param ctx the parse tree + */ + exitLetStatement?: (ctx: LetStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.equals`. + * @param ctx the parse tree + */ + enterEquals?: (ctx: EqualsContext) => void; + /** + * Exit a parse tree produced by `JackParser.equals`. + * @param ctx the parse tree + */ + exitEquals?: (ctx: EqualsContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + enterIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifElseStatement`. + * @param ctx the parse tree + */ + exitIfElseStatement?: (ctx: IfElseStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + enterIfStatement?: (ctx: IfStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifStatement`. + * @param ctx the parse tree + */ + exitIfStatement?: (ctx: IfStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.ifExpression`. + * @param ctx the parse tree + */ + enterIfExpression?: (ctx: IfExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.ifExpression`. + * @param ctx the parse tree + */ + exitIfExpression?: (ctx: IfExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + enterElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.elseStatement`. + * @param ctx the parse tree + */ + exitElseStatement?: (ctx: ElseStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + enterWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileStatement`. + * @param ctx the parse tree + */ + exitWhileStatement?: (ctx: WhileStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.whileExpression`. + * @param ctx the parse tree + */ + enterWhileExpression?: (ctx: WhileExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.whileExpression`. + * @param ctx the parse tree + */ + exitWhileExpression?: (ctx: WhileExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + enterDoStatement?: (ctx: DoStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.doStatement`. + * @param ctx the parse tree + */ + exitDoStatement?: (ctx: DoStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + enterSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineCall`. + * @param ctx the parse tree + */ + exitSubroutineCall?: (ctx: SubroutineCallContext) => void; + /** + * Enter a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + enterSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Exit a parse tree produced by `JackParser.subroutineId`. + * @param ctx the parse tree + */ + exitSubroutineId?: (ctx: SubroutineIdContext) => void; + /** + * Enter a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + enterReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Exit a parse tree produced by `JackParser.returnStatement`. + * @param ctx the parse tree + */ + exitReturnStatement?: (ctx: ReturnStatementContext) => void; + /** + * Enter a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + enterExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Exit a parse tree produced by `JackParser.expressionList`. + * @param ctx the parse tree + */ + exitExpressionList?: (ctx: ExpressionListContext) => void; + /** + * Enter a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + enterExpression?: (ctx: ExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.expression`. + * @param ctx the parse tree + */ + exitExpression?: (ctx: ExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + enterConstant?: (ctx: ConstantContext) => void; + /** + * Exit a parse tree produced by `JackParser.constant`. + * @param ctx the parse tree + */ + exitConstant?: (ctx: ConstantContext) => void; + /** + * Enter a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + enterVarName?: (ctx: VarNameContext) => void; + /** + * Exit a parse tree produced by `JackParser.varName`. + * @param ctx the parse tree + */ + exitVarName?: (ctx: VarNameContext) => void; + /** + * Enter a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + enterArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Exit a parse tree produced by `JackParser.arrayAccess`. + * @param ctx the parse tree + */ + exitArrayAccess?: (ctx: ArrayAccessContext) => void; + /** + * Enter a parse tree produced by `JackParser.unaryOperation`. + * @param ctx the parse tree + */ + enterUnaryOperation?: (ctx: UnaryOperationContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperation`. + * @param ctx the parse tree + */ + exitUnaryOperation?: (ctx: UnaryOperationContext) => void; + /** + * Enter a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + enterGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Exit a parse tree produced by `JackParser.groupedExpression`. + * @param ctx the parse tree + */ + exitGroupedExpression?: (ctx: GroupedExpressionContext) => void; + /** + * Enter a parse tree produced by `JackParser.booleanLiteral`. + * @param ctx the parse tree + */ + enterBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Exit a parse tree produced by `JackParser.booleanLiteral`. + * @param ctx the parse tree + */ + exitBooleanLiteral?: (ctx: BooleanLiteralContext) => void; + /** + * Enter a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + enterUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.unaryOperator`. + * @param ctx the parse tree + */ + exitUnaryOperator?: (ctx: UnaryOperatorContext) => void; + /** + * Enter a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + enterBinaryOperator?: (ctx: BinaryOperatorContext) => void; + /** + * Exit a parse tree produced by `JackParser.binaryOperator`. + * @param ctx the parse tree + */ + exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; - visitTerminal(node: TerminalNode): void {} - visitErrorNode(node: ErrorNode): void {} - enterEveryRule(node: ParserRuleContext): void {} - exitEveryRule(node: ParserRuleContext): void {} + visitTerminal(node: TerminalNode): void {} + visitErrorNode(node: ErrorNode): void {} + enterEveryRule(node: ParserRuleContext): void {} + exitEveryRule(node: ParserRuleContext): void {} } - diff --git a/simulator/src/jack/listener/common.ts b/simulator/src/jack/listener/common.ts index ae8fe870..b29b6550 100644 --- a/simulator/src/jack/listener/common.ts +++ b/simulator/src/jack/listener/common.ts @@ -15,7 +15,7 @@ export enum CallType { export function getCallType( subroutineId: SubroutineIdContext, className: string, - localSymbolTable: LocalSymbolTable + localSymbolTable: LocalSymbolTable, ): CallTypeResult { if (subroutineId.DOT() == undefined) { //local method @@ -46,7 +46,7 @@ export function getCallType( export function assertExists( val: T | undefined | null, - message?: string + message?: string, ): T { if (val == null) { throw new Error(message ?? "Cannot be null or undefined"); diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index 4c50870d..ff03f587 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -11,10 +11,7 @@ import { Recognizer, Token, } from "antlr4ng"; -import { - JackCompilerError, - LexerOrParserError -} from "../error.js"; +import { JackCompilerError, LexerOrParserError } from "../error.js"; import { assertExists } from "./common.js"; export class CustomErrorListener implements ANTLRErrorListener { @@ -25,31 +22,34 @@ export class CustomErrorListener implements ANTLRErrorListener { line: number, _charPositionInLine: number, msg: string, - e: RecognitionException | null + e: RecognitionException | null, ): void { if (offendingSymbol != null || (e != null && e.offendingToken != null)) { const t = offendingSymbol ?? (e?.offendingToken as Token); this.errors.push( - LexerOrParserError({ line: line, start: t.start, end: t.stop + 1 }, msg) + LexerOrParserError( + { line: line, start: t.start, end: t.stop + 1 }, + msg, + ), ); } else if (e instanceof NoViableAltException) { //theoretically we can't get this exception const token = assertExists( e.startToken ?? e.offendingToken, - "Cant find start token for NoViableAltException" + "Cant find start token for NoViableAltException", ); this.errors.push( LexerOrParserError( { line: token.line, start: token.start, end: token.stop }, - msg - ) + msg, + ), ); } else if (e instanceof LexerNoViableAltException) { this.errors.push( LexerOrParserError( { line: line, start: e.startIndex, end: e.startIndex + 1 }, - msg - ) + msg, + ), ); } else { console.error("Don't know how to handle this error"); @@ -64,7 +64,7 @@ export class CustomErrorListener implements ANTLRErrorListener { _stopIndex: number, _exact: boolean, _ambigAlts: BitSet | undefined, - _configs: ATNConfigSet + _configs: ATNConfigSet, ): void {} reportAttemptingFullContext( _recognizer: Parser, @@ -72,7 +72,7 @@ export class CustomErrorListener implements ANTLRErrorListener { _startIndex: number, _stopIndex: number, _conflictingAlts: BitSet | undefined, - _configs: ATNConfigSet + _configs: ATNConfigSet, ): void {} reportContextSensitivity( _recognizer: Parser, @@ -80,6 +80,6 @@ export class CustomErrorListener implements ANTLRErrorListener { _startIndex: number, _stopIndex: number, _prediction: number, - _configs: ATNConfigSet + _configs: ATNConfigSet, ): void {} } diff --git a/simulator/src/jack/listener/global.symbol.listener.ts b/simulator/src/jack/listener/global.symbol.listener.ts index 8a1bf5f8..aa42d387 100644 --- a/simulator/src/jack/listener/global.symbol.listener.ts +++ b/simulator/src/jack/listener/global.symbol.listener.ts @@ -3,7 +3,12 @@ import { SubroutineDeclarationContext, VarNameInDeclarationContext, } from "../generated/JackParser.js"; -import { ruleContextToSpan, DuplicatedClassError, DuplicatedSubroutineError, JackCompilerError } from "../error.js"; +import { + ruleContextToSpan, + DuplicatedClassError, + DuplicatedSubroutineError, + JackCompilerError, +} from "../error.js"; import { GenericSymbol, GlobalSymbolTable, @@ -38,7 +43,7 @@ export class GlobalSymbolTableListener extends JackParserListener { } const e = DuplicatedClassError( ruleContextToSpan(classNameCtx), - className + className, ); this.errors.push(e); return; @@ -74,17 +79,12 @@ export class GlobalSymbolTableListener extends JackParserListener { throw new Error("Start token should not be null"); } this.errors.push( - DuplicatedSubroutineError( - ruleContextToSpan(nameCtx), - subroutineName - ) + DuplicatedSubroutineError(ruleContextToSpan(nameCtx), subroutineName), ); this.stopProcessingSubroutines = true; } else { this.subroutineId = id; - const params = subroutineWithoutTypeCtx - .parameterList() - .parameter() + const params = subroutineWithoutTypeCtx.parameterList().parameter(); this.subRoutineInfo = { type: subroutineType, paramsCount: params.length, diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 774ef378..72b59039 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -42,7 +42,7 @@ import { VarNameContext, VarNameInDeclarationContext, VarTypeContext, - WhileStatementContext + WhileStatementContext, } from "../generated/JackParser.js"; import { JackParserListener } from "../generated/JackParserListener.js"; import { @@ -66,7 +66,7 @@ export class ValidatorListener extends JackParserListener { constructor( private globalSymbolTable: Record, private filename?: string, - public errors: JackCompilerError[] = [] + public errors: JackCompilerError[] = [], ) { super(); } @@ -86,8 +86,8 @@ export class ValidatorListener extends JackParserListener { FilenameDoesntMatchClassNameError( ruleContextToSpan(ctx.className()), this.filename, - this.className - ) + this.className, + ), ); } ctx.localSymbolTable = this.localSymbolTable; @@ -111,7 +111,7 @@ export class ValidatorListener extends JackParserListener { field.IDENTIFIER(), scope, field.getText(), - type + type, ); }); }; @@ -125,9 +125,9 @@ export class ValidatorListener extends JackParserListener { this.addError( IncorrectConstructorReturnTypeError( ruleContextToSpan( - ctx.subroutineDecWithoutType().subroutineReturnType() - ) - ) + ctx.subroutineDecWithoutType().subroutineReturnType(), + ), + ), ); } } else if (ctx.subroutineType().FUNCTION() != null) { @@ -139,7 +139,7 @@ export class ValidatorListener extends JackParserListener { } }; override enterSubroutineDecWithoutType = ( - ctx: SubroutineDecWithoutTypeContext + ctx: SubroutineDecWithoutTypeContext, ) => { const returnType = ctx.subroutineReturnType(); this.subroutineShouldReturnVoidType = returnType.VOID() != null; @@ -151,13 +151,13 @@ export class ValidatorListener extends JackParserListener { const name = ctx.parameterName().getText(); if (this.localSymbolTable.lookup(name)) { this.addError( - DuplicatedVariableError(ruleContextToSpan(ctx.parameterName()), name) + DuplicatedVariableError(ruleContextToSpan(ctx.parameterName()), name), ); } else { this.localSymbolTable.defineArgument( name, ctx.varType().getText(), - this.subroutineType == SubroutineType.Method + this.subroutineType == SubroutineType.Method, ); } }; @@ -181,7 +181,7 @@ export class ValidatorListener extends JackParserListener { nameCtx.IDENTIFIER(), ScopeType.Local, nameCtx.getText(), - type + type, ); }); }; @@ -195,8 +195,8 @@ export class ValidatorListener extends JackParserListener { this.addError( UndeclaredVariableError( terminalNodeToSpan(ctx.IDENTIFIER()), - ctx.getText() - ) + ctx.getText(), + ), ); } else if ( this.subroutineType == SubroutineType.Function && @@ -204,8 +204,8 @@ export class ValidatorListener extends JackParserListener { ) { this.addError( FieldCantBeReferencedInFunctionError( - terminalNodeToSpan(ctx.IDENTIFIER()) - ) + terminalNodeToSpan(ctx.IDENTIFIER()), + ), ); } }; @@ -214,7 +214,7 @@ export class ValidatorListener extends JackParserListener { const thisLiteral = ctx.THIS_LITERAL(); if (thisLiteral != null && this.subroutineType == SubroutineType.Function) { this.addError( - ThisCantBeReferencedInFunctionError(terminalNodeToSpan(thisLiteral)) + ThisCantBeReferencedInFunctionError(terminalNodeToSpan(thisLiteral)), ); } }; @@ -292,8 +292,8 @@ export class ValidatorListener extends JackParserListener { terminalNodeToSpan(intLiteral), parseInt(value), intRange.min, - intRange.max - ) + intRange.max, + ), ); } } else if (constCtx?.STRING_LITERAL() != null) { @@ -308,8 +308,8 @@ export class ValidatorListener extends JackParserListener { WrongLiteralTypeError( ruleContextToSpan(constantCtx ?? ctx), symbol.type, - actualType - ) + actualType, + ), ); } } @@ -324,18 +324,18 @@ export class ValidatorListener extends JackParserListener { unaryOp.expression()?.constant()?.INTEGER_LITERAL() !== null ) { const value = parseInt( - unaryOp.expression()?.constant()?.INTEGER_LITERAL()?.getText() ?? "0" + unaryOp.expression()?.constant()?.INTEGER_LITERAL()?.getText() ?? "0", ); if (-value < intRange.min) { this.addError( IntLiteralIsOutOfRangeError( terminalNodeToSpan( - assertExists(unaryOp.expression()?.constant()?.INTEGER_LITERAL()) + assertExists(unaryOp.expression()?.constant()?.INTEGER_LITERAL()), ), value, intRange.min, - intRange.max - ) + intRange.max, + ), ); } } @@ -347,7 +347,7 @@ export class ValidatorListener extends JackParserListener { const { callType, subroutineIdText } = getCallType( subroutineId, this.className, - this.localSymbolTable + this.localSymbolTable, ); const symbol = this.globalSymbolTable[subroutineIdText]; @@ -356,8 +356,8 @@ export class ValidatorListener extends JackParserListener { UnknownSubroutineCallError( ruleContextToSpan(subroutineId.subroutineName()), subroutineId.subroutineName().getText(), - subroutineId.className()?.getText() - ) + subroutineId.className()?.getText(), + ), ); } else { //method called as a function @@ -368,8 +368,8 @@ export class ValidatorListener extends JackParserListener { this.addError( MethodCalledAsFunctionError( ruleContextToSpan(subroutineId.subroutineName()), - subroutineId.subroutineName().getText() - ) + subroutineId.subroutineName().getText(), + ), ); } // function called as a method @@ -380,8 +380,8 @@ export class ValidatorListener extends JackParserListener { this.addError( FunctionCalledAsMethodError( ruleContextToSpan(subroutineId.subroutineName()), - subroutineId.subroutineName().getText() - ) + subroutineId.subroutineName().getText(), + ), ); } else { //check parameter count @@ -398,8 +398,8 @@ export class ValidatorListener extends JackParserListener { ruleContextToSpan(ctx.expressionList()), subroutineId.getText(), assertExists(symbol.subroutineInfo).paramsCount, - l - ) + l, + ), ); } else { const start = ctx.LPAREN().symbol; @@ -410,8 +410,8 @@ export class ValidatorListener extends JackParserListener { { line: start.line, start: start.start, end: stop.stop + 1 }, subroutineId.getText(), symbol.subroutineInfo?.paramsCount ?? 0, - l - ) + l, + ), ); } } @@ -445,8 +445,8 @@ export class ValidatorListener extends JackParserListener { //TODO: add exact place that doesn't return SubroutineNotAllPathsReturnError( ruleContextToSpan(ctx.subroutineType()), - this.subroutineName - ) + this.subroutineName, + ), ); } this.subroutineType = undefined; @@ -465,11 +465,11 @@ export class ValidatorListener extends JackParserListener { identifierCtx: TerminalNode, scope: ScopeType, name: string, - type: string + type: string, ) { if (this.localSymbolTable.lookup(name)) { this.addError( - DuplicatedVariableError(terminalNodeToSpan(identifierCtx), name) + DuplicatedVariableError(terminalNodeToSpan(identifierCtx), name), ); } else { this.localSymbolTable.define(scope, name, type); @@ -485,7 +485,7 @@ class BinaryTreeNode { constructor( public parent?: BinaryTreeNode, public left?: BinaryTreeNode, - public right?: BinaryTreeNode + public right?: BinaryTreeNode, ) {} public get returns(): boolean { @@ -524,13 +524,13 @@ class BinaryTreeNode { } else { res += this.left?.printBT( side == Side.LEFT ? "| " : " ", - Side.LEFT + Side.LEFT, ); if (this.right) { res += prefix; res += this.right?.printBT( side == Side.LEFT ? "|\t" : "\t", - Side.RIGHT + Side.RIGHT, ); } else { res += "\n"; diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index b1632816..e4d0edf4 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -79,12 +79,12 @@ export class VMWriter extends JackParserListener { const symbol = this.globalSymbolTable[this.className + "." + name]; if (symbol == undefined) { throw new Error( - `Can't find subroutine ${name} in class ${this.className} in symbol table` + `Can't find subroutine ${name} in class ${this.className} in symbol table`, ); } if (symbol.subroutineInfo == null) { throw new Error( - `Subroutine info not found for subroutine ${name} in class ${this.className}` + `Subroutine info not found for subroutine ${name} in class ${this.className}`, ); } this.result += `function ${this.className}.${name} ${symbol.subroutineInfo.localVarsCount}\n`; @@ -159,20 +159,20 @@ export class VMWriter extends JackParserListener { if (ctx.varName() != null) { const varNameCtx = assertExists( ctx.varName(), - "Variable name cannot be null" + "Variable name cannot be null", ); const varName = varNameCtx.IDENTIFIER().getText(); const symbol = this.localSymbolTable.lookup(varName); if (symbol == undefined) { throw new Error( - `Cannot find variable ${varName} in arguments or local variables` + `Cannot find variable ${varName} in arguments or local variables`, ); } this.pushSymbolOntoStack(symbol); } else if (ctx.binaryOperator() != null) { const binaryOp = assertExists( ctx.binaryOperator(), - "Binary operator cannot be null" + "Binary operator cannot be null", ).getText(); if (binaryOperationToVmCmd[binaryOp] == undefined) { throw new Error(`Unknown binary operator ${binaryOp}`); @@ -181,7 +181,7 @@ export class VMWriter extends JackParserListener { } else if (ctx.unaryOperation() != null) { const unaryOp = assertExists( ctx.unaryOperation()?.unaryOperator(), - "Unary operation cannot be null" + "Unary operation cannot be null", ).getText(); if (unaryOperationToVmCmd[unaryOp] == null) { throw new Error(`Unknown unary operator ${unaryOp}`); @@ -196,11 +196,11 @@ export class VMWriter extends JackParserListener { if (ctx.varName() != null) { const varNameCtx = assertExists(ctx.varName(), "Var name cannot be null"); const symbol = this.localSymbolTable.lookup( - varNameCtx.IDENTIFIER().getText() + varNameCtx.IDENTIFIER().getText(), ); if (symbol == undefined) { throw new Error( - `Can't find variable ${ctx.varName()?.IDENTIFIER().getText()} in local symbol table` + `Can't find variable ${ctx.varName()?.IDENTIFIER().getText()} in local symbol table`, ); } this.result += ` pop ${scopeTypeToString(symbol.scope)} ${symbol.index}\n`; @@ -254,7 +254,7 @@ export class VMWriter extends JackParserListener { const { callType, symbol } = getCallType( ctx.subroutineId(), this.className, - this.localSymbolTable + this.localSymbolTable, ); if (callType === CallType.VarMethod) { if (symbol == null) @@ -270,7 +270,7 @@ export class VMWriter extends JackParserListener { const { callType, subroutineIdText } = getCallType( ctx.subroutineId(), this.className, - this.localSymbolTable + this.localSymbolTable, ); switch (callType) { case CallType.ClassFunctionOrConstructor: { diff --git a/simulator/src/jack/test.helper.ts b/simulator/src/jack/test.helper.ts index 5263bbbf..44cef7ae 100644 --- a/simulator/src/jack/test.helper.ts +++ b/simulator/src/jack/test.helper.ts @@ -3,10 +3,14 @@ import path from "path"; import { JackCompilerError } from "./error"; import { CustomErrorListener } from "./listener/error.listener"; import { JackParser, ProgramContext } from "./generated/JackParser"; -import { CharStream, CommonTokenStream, ParseTreeListener, ParseTreeWalker } from "antlr4ng"; +import { + CharStream, + CommonTokenStream, + ParseTreeListener, + ParseTreeWalker, +} from "antlr4ng"; import { JackLexer } from "./generated/JackLexer"; - export function parseJackFile(filePath: string, trace = false) { const errorListener = new CustomErrorListener(); const f = fs.readFileSync(filePath, "utf8"); From 79241239434c09ceedce800538686f95dbc3f03f Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 20 Oct 2024 11:12:26 +0200 Subject: [PATCH 80/87] WIP --- .../jack/listener/global.symbol.listener.ts | 13 +- .../global.symbol.table.listener.test.ts | 119 +++ .../jack/listener/validator.listener.test.ts | 824 ++++++++++++++++++ 3 files changed, 946 insertions(+), 10 deletions(-) create mode 100644 simulator/src/jack/listener/global.symbol.table.listener.test.ts create mode 100644 simulator/src/jack/listener/validator.listener.test.ts diff --git a/simulator/src/jack/listener/global.symbol.listener.ts b/simulator/src/jack/listener/global.symbol.listener.ts index aa42d387..f08bc52f 100644 --- a/simulator/src/jack/listener/global.symbol.listener.ts +++ b/simulator/src/jack/listener/global.symbol.listener.ts @@ -43,19 +43,12 @@ export class GlobalSymbolTableListener extends JackParserListener { } const e = DuplicatedClassError( ruleContextToSpan(classNameCtx), - className, + className ); this.errors.push(e); return; } - this.globalSymbolTable[className] = { - filename: this.filename, - start: { line: id.symbol.line, character: id.symbol.column }, - end: { - line: id.symbol.line, - character: id.symbol.column + id.getText().length, - }, - } as GenericSymbol; + this.globalSymbolTable[className] = {} as GenericSymbol; this.className = className; }; @@ -79,7 +72,7 @@ export class GlobalSymbolTableListener extends JackParserListener { throw new Error("Start token should not be null"); } this.errors.push( - DuplicatedSubroutineError(ruleContextToSpan(nameCtx), subroutineName), + DuplicatedSubroutineError(ruleContextToSpan(nameCtx), subroutineName) ); this.stopProcessingSubroutines = true; } else { diff --git a/simulator/src/jack/listener/global.symbol.table.listener.test.ts b/simulator/src/jack/listener/global.symbol.table.listener.test.ts new file mode 100644 index 00000000..85a80e5a --- /dev/null +++ b/simulator/src/jack/listener/global.symbol.table.listener.test.ts @@ -0,0 +1,119 @@ +import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; +import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; +import path from "path"; +import { builtInSymbols } from "../builtins"; +import { + JackCompilerErrorType +} from "../error"; +import { createSubroutineSymbol, SubroutineType } from "../symbol"; +import { + getTestResourcePath, + listenToTheTree, + parseJackFile, + parseJackText, +} from "../test.helper"; +import { GlobalSymbolTableListener } from "./global.symbol.listener"; + +describe("Jack global symbol table listener", () => { + const jestConsole = console; + let fs: FileSystem; + beforeEach(() => { + global.console = require("console"); + fs = new FileSystem(new NodeFileSystemAdapter()); + }); + + afterEach(() => { + global.console = jestConsole; + }); + + test("should fail on duplicated subroutine", () => { + const input = ` + class A { + function void f(){ + return; + } + function int f(){ + return 1; + } + }`; + testJackGlobalSymbolListener(input, "DuplicatedSubroutineError"); + }); + + test("duplicated class", () => { + const input = ` + class A { + }`; + const globalSymbolTableListener = new GlobalSymbolTableListener(); + testJackGlobalSymbolListener(input, undefined, globalSymbolTableListener); + testJackGlobalSymbolListener(input, "DuplicatedClassError", globalSymbolTableListener); + }); + test("duplicated built in class", () => { + const input = ` + class Math { + }`; + testJackGlobalSymbolListener(input, "DuplicatedClassError"); + }); + test("basic", async () => { + const expected = { + ...builtInSymbols, + Fraction: {}, + "Fraction.new": createSubroutineSymbol(2, SubroutineType.Constructor, 0), + "Fraction.reduce": createSubroutineSymbol(0, SubroutineType.Method, 1), + "Fraction.getNumerator": createSubroutineSymbol( + 0, + SubroutineType.Method, + 0 + ), + "Fraction.getDenominator": createSubroutineSymbol( + 0, + SubroutineType.Method, + 0 + ), + "Fraction.plus": createSubroutineSymbol(1, SubroutineType.Method, 1), + "Fraction.dispose": createSubroutineSymbol(0, SubroutineType.Method, 0), + "Fraction.print": createSubroutineSymbol(0, SubroutineType.Method, 0), + "Fraction.gcd": createSubroutineSymbol(2, SubroutineType.Function, 1), + Main: {}, + "Main.main": createSubroutineSymbol(0, SubroutineType.Function, 3), + }; + let globalSymbolsListener = new GlobalSymbolTableListener(); + + const testFolder = getTestResourcePath("Fraction"); + + const filteredFiles = [...(await fs.readdir(testFolder))] + .filter((file) => file.endsWith(".jack")) + .map((file) => path.join(testFolder, file)); + for (const filePath of filteredFiles) { + const tree = parseJackFile(filePath); + globalSymbolsListener = listenToTheTree(tree, globalSymbolsListener); + } + expect(globalSymbolsListener.globalSymbolTable).toEqual(expected); + }); +}); +function testJackGlobalSymbolListener( + input: string, + expectedError?: T, + globalSymbolTableListener = new GlobalSymbolTableListener() +) { + const tree = parseJackText(input); + listenToTheTree(tree, globalSymbolTableListener); + const errors = globalSymbolTableListener.errors; + if (expectedError) { + if (errors.length > 1) { + console.error("Errors", errors); + } + try { + expect(globalSymbolTableListener.errors.length).toBe(1); + expect(globalSymbolTableListener.errors[0].type).toBe(expectedError); + } catch (e) { + throw new Error( + `Expected error ${expectedError} but got '` + + JSON.stringify(globalSymbolTableListener.errors) + + "'" + ); + } + } else { + if (errors.length != 0) + throw new Error("Didn't expect any errors but got " + errors.join("\n")); + } +} diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts new file mode 100644 index 00000000..f5f95ed6 --- /dev/null +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -0,0 +1,824 @@ +import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; +import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; +import { + createSubroutineSymbol, + GenericSymbol, + SubroutineType, +} from "../symbol"; +import { + getTestResourcePath, + listenToTheTree, + parseJackFile, + parseJackText, + testResourceDirs, +} from "../test.helper"; +import path from "path"; +import { ProgramContext } from "../generated/JackParser"; +import { JackCompilerErrorType } from "../error"; +import { GlobalSymbolTableListener } from "./global.symbol.listener"; +import { ValidatorListener } from "./validator.listener"; +import { CustomErrorListener } from "./error.listener"; +describe("Jack validator listener", () => { + const jestConsole = console; + let fs: FileSystem; + beforeEach(() => { + global.console = require("console"); + fs = new FileSystem(new NodeFileSystemAdapter()); + }); + + afterEach(() => { + global.console = jestConsole; + }); + + function genericSymbol( + type?: SubroutineType, + paramsCount?: number, + ): GenericSymbol { + if (type != undefined && paramsCount != undefined) { + return createSubroutineSymbol(paramsCount, type); + } else { + return {} as GenericSymbol; + } + } + + const duplicateVarClassBodies = [ + ["static", " static int a, a;"], + ["field", " field int a, a;"], + ["static and field", " static int a; field boolean a;"], + ["function args", " function void a(int a, int a){return;}"], + [ + "function var", + ` function void a(){ + var boolean a, a; + return; + }`, + ], + [ + "function var with different types", + ` function void a(){ + var boolean a; + var int a; + return; + }`, + ], + ]; + test.concurrent.each(duplicateVarClassBodies)( + "duplicated %s", + (testName, classBody) => { + testValidator( + ` + class Main { + ${classBody} + }`, + 'DuplicatedVariableError', + ); + }, + ); + + /** + * Undeclared var + */ + test("let - undeclared variable ", () => { + testValidator( + ` + class Main { + function void a(){ + let b=1; + return; + } + }`, + 'UndeclaredVariableError', + ); + }); + + test("call function - undeclared variable ", () => { + testValidator( + `class Main { + function void b(int a){ + return; + } + function void a(){ + do Main.b(a); + return; + } + }`, + 'UndeclaredVariableError', + { + Main: genericSymbol(), + "Main.b": genericSymbol(SubroutineType.Function, 1), + "Main.a": genericSymbol(SubroutineType.Function, 1), + }, + ); + }); + + test("if - undeclared variable ", () => { + testValidator( + `class Main { + function void a(){ + if(a=0){ + return; + }else { + return; + } + } + }`, + 'UndeclaredVariableError', + ); + }); + + /** + * Unknown class + */ + test("Unknown class for subroutine return type ", () => { + testValidator( + ` + class Main { + function void b(int a){ + var D d; + return; + } + }`, + 'UnknownClassError', + ); + }); + + test("Known type for subroutine return type ", () => { + testValidator( + ` + class Main { + function D b(int a){ + return D.new(); + } + }`, + undefined, + { + D: genericSymbol(), + "D.new": genericSymbol(SubroutineType.Constructor, 0), + }, + ); + }); + test("Arg Unknown class ", () => { + testValidator( + ` + class Main { + function void b(D a){ + return; + } + }`, + 'UnknownClassError', + ); + }); + + test("Arg known type ", () => { + testValidator( + ` + + class Main { + function void b(D a){ + return; + } + }`, + undefined, + { D: genericSymbol() }, + ); + }); + test("var Unknown class", () => { + testValidator( + ` + class Main { + function void b(){ + var D d; + return; + } + }`, + 'UnknownClassError', + ); + }); + test("var known type", () => { + testValidator( + ` + class Main { + function void b(){ + var D d; + return; + } + }`, + undefined, + { D: genericSymbol() }, + ); + }); + test("field Unknown class", () => { + testValidator( + ` + class Main { + field T t; + }`, + 'UnknownClassError', + ); + }); + test("field known type", () => { + testValidator( + ` + class Main { + field T t; + }`, + undefined, + { T: genericSymbol() }, + ); + }); + test("static field Unknown class", () => { + testValidator( + ` + class Main { + static T t; + }`, + 'UnknownClassError', + ); + }); + test("static field known type", () => { + testValidator( + ` + class Main { + static T t; + }`, + undefined, + { T: genericSymbol() }, + ); + }); + + /** + * Incorrect return type + */ + + test("non void subroutine must return a value", () => { + testValidator( + ` + class Main { + function int a(){ + return; + } + }`, + 'NonVoidFunctionNoReturnError', + ); + }); + + test("void subroutine must return not return a value", () => { + testValidator( + ` + class Main { + function void a(){ + return 1; + } + }`, + 'VoidSubroutineReturnsValueError', + ); + }); + /** + * `Subroutine ${subroutine.name.value}: not all code paths return a value` + */ + + test("if missing return", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + + }else{ + return; + } + } + }`, + 'SubroutineNotAllPathsReturnError', + ); + }); + test("else missing return ", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + return; + }else{ + + } + } + }`, + 'SubroutineNotAllPathsReturnError', + ); + }); + + test("while missing return", () => { + testValidator( + ` + class Main { + function int a(){ + var int a; + let a=0; + while(a<10){ + + } + } + }`, + 'SubroutineNotAllPathsReturnError', + ); + }); + + test(" missing return after while", () => { + testValidator( + ` + class Main { + function int a(){ + var int a; + let a=0; + while(a<10){ + return 0; + } + } + }`, + 'SubroutineNotAllPathsReturnError', + ); + }); + + test("nested if missing return", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + return; + }else { + + } + }else{ + return; + } + } + }`, + 'SubroutineNotAllPathsReturnError', + ); + }); + test("nested if missing return 2", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + + }else { + return; + } + }else{ + return; + } + } + }`, + 'SubroutineNotAllPathsReturnError', + ); + }); + + test("nested if missing return 3", () => { + testValidator( + ` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + return; + }else { + return; + } + }else{ + + } + } + }`, + 'SubroutineNotAllPathsReturnError', + ); + }); + test("should be valid", () => { + testValidator(` + class Main { + function void a(){ + var int a; + let a=0; + if(a=0){ + if(a=1){ + }else { + } + } + return; + } + }`); + }); + /** + * Validate function call + */ + test("calling undefined subroutine", () => { + testValidator( + ` + class Main { + function void b(){ + do Main.c(); + return; + } + }`, + 'UnknownSubroutineCallError', + ); + }); + + test("incorrect number of parameters when calling a function", () => { + testValidator( + ` + class Main { + function void a(int a, int b){ + return; + } + function void b(){ + do Main.a(1); + return; + } + }`, + 'IncorrectParamsNumberInSubroutineCallError', + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 2), + "Main.b": genericSymbol(SubroutineType.Function, 2), + }, + ); + }); + + test("call var method ", () => { + testValidator( + ` + class Main { + constructor Main new(){ + return this; + } + function void a(){ + var Main m; + let m = Main.new(); + do m.b(); + return; + } + method void b(){ + return; + } + }`, + undefined, + { + Main: genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + "Main.a": genericSymbol(SubroutineType.Function, 0), + "Main.b": genericSymbol(SubroutineType.Method, 0), + }, + ); + }); + test("call local method ", () => { + testValidator( + ` + class Main { + method void a(){ + do b(); + return; + } + method void b(){ + return; + } + }`, + undefined, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Method, 0), + "Main.b": genericSymbol(SubroutineType.Method, 0), + }, + ); + }); + + /** + * - `Method ${className}.${subroutineName} was called as a function/constructor` + */ + test("method called as a function/constructor", () => { + testValidator( + ` + class Main { + function void b(){ + do Main.c(); + return; + } + method void c(){ + return; + } + }`, + 'MethodCalledAsFunctionError', + { + Main: genericSymbol(), + "Main.b": genericSymbol(SubroutineType.Function, 0), + "Main.c": genericSymbol(SubroutineType.Method, 0), + }, + ); + }); + test("function/ctor called as a method", () => { + testValidator( + ` + class Main { + function void b(){ + do c(); + return; + } + function void c(){ + return; + } + }`, + 'FunctionCalledAsMethodError', + { + Main: genericSymbol(), + "Main.b": genericSymbol(SubroutineType.Function, 0), + "Main.c": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("incorrect return type in constructor", () => { + testValidator( + ` + class Main { + constructor D new(){ + return this; + } + }`, + 'IncorrectConstructorReturnTypeError', + { + Main: genericSymbol(), + D: genericSymbol(), + }, + ); + }); + test("unreachable code", () => { + testValidator( + ` + class Main { + constructor Main new(){ + return this; + let a=0; + let a=0; + let a=0; + } + }`, + 'UnreachableCodeError', + { + Main: genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + }, + ); + }); + test("A constructor must return 'this'", () => { + testValidator( + ` + class Main { + constructor Main new(){ + return 1; + } + }`, + 'ConstructorMushReturnThisError', + { + Main: genericSymbol(), + "Main.new": genericSymbol(SubroutineType.Constructor, 0), + }, + ); + }); + test("Let statement - expected string literal ", () => { + testValidator( + ` + class Main { + function void a(){ + var String foo; + let foo = 1; + return; + } + }`, + 'WrongLiteralTypeError', + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + String: genericSymbol(), + }, + ); + }); + test("Let statement - expected boolean literal ", () => { + testValidator( + ` + class Main { + function void a(){ + var boolean foo; + let foo = 1; + return; + } + }`, + 'WrongLiteralTypeError', + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + + test("Let statement - expected int literal ", () => { + testValidator( + ` + class Main { + function void a(){ + var int foo; + let foo = "asb"; + return; + } + }`, + 'WrongLiteralTypeError', + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("integer constant value is too big", () => { + testValidator( + ` + class Main { + function void a(){ + var int foo; + let foo = 33000; + return; + } + }`, + 'IntLiteralIsOutOfRangeError', + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("integer constant value is too small", () => { + testValidator( + ` + class Main { + function void a(){ + var int foo; + let foo = -33000; + return; + } + }`, + 'IntLiteralIsOutOfRangeError', + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("A field can not be referenced in a function", () => { + testValidator( + ` + class Main { + field int a; + function void a(){ + let a = 1; + return; + } + }`, + 'FieldCantBeReferencedInFunctionError', + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("A static field can be referenced in a function", () => { + testValidator( + ` + class Main { + static int a; + function void a(){ + let a = 1; + return; + } + }`, + undefined, + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("this can't be referenced in a function", () => { + testValidator( + ` + class Main { + function void a(){ + var Main m; + let m = this; + return; + } + }`, + 'ThisCantBeReferencedInFunctionError', + { + Main: genericSymbol(), + "Main.a": genericSymbol(SubroutineType.Function, 0), + }, + ); + }); + test("class name doesn't match filename", () => { + testValidator( + `class A {}`, + 'FilenameDoesntMatchClassNameError', + { + A: genericSymbol(), + }, + "B", + ); + }); + + //validate files + test.each(testResourceDirs)("%s", async (dir: string) => { + await testJackDir(fs, getTestResourcePath(dir)); + }); +}); + +async function testJackDir(fs: FileSystem, testFolder: string): Promise { + const files = [...(await fs.readdir(testFolder))] + .filter((file) => file.endsWith(".jack")) + .map((file) => path.join(testFolder, file)); + const trees: Record = {}; + const globalSymbolsListener: GlobalSymbolTableListener = + new GlobalSymbolTableListener(); + for (const filePath of files) { + const tree = parseJackFile(filePath); + trees[filePath] = tree; + listenToTheTree(tree, globalSymbolsListener); + expect(globalSymbolsListener.errors).toEqual([]); + } + for (const filepath of Object.keys(trees)) { + const tree = trees[filepath]; + const validatorListener = listenToTheTree( + tree, + new ValidatorListener(globalSymbolsListener.globalSymbolTable), + ); + expect(validatorListener.errors).toEqual([]); + } +} + +function testValidator( + src: string, + expectedError?: T, + globalSymbolTable: Record = {}, + filename?: string, +) { + const errorListener = new CustomErrorListener(); + const tree = parseJackText(src, errorListener); + const listener = + filename != null + ? new ValidatorListener(globalSymbolTable, filename) + : new ValidatorListener(globalSymbolTable); + const validator = listenToTheTree(tree, listener); + if (expectedError) { + if (validator.errors.length > 1) { + console.error("Errors", validator.errors); + } + try { + expect(validator.errors.length).toBe(1); + expect(validator.errors[0].type).toBe(expectedError); + } catch (e) { + throw new Error( + `Expected error ${expectedError} but got '` + + JSON.stringify(validator.errors) + + "'", + ); + } + } else { + if (validator.errors.length != 0) + throw new Error( + "Didn't expect any errors but got " + validator.errors.join("\n"), + ); + } +} + +/** + * TODO: + * Ideas for improvement - + * - Show "Expected class name, subroutine name, field, parameter or local or static variable name" instead of "expecting IDENTIFIER" + * - Show "Expected subroutine return type followed by a subroutine name" instead of "expecting IDENTIFIER" + * - Expected subroutine name in call + * - a numeric value is illegal here when using non numeric vars + * - validate function call - when using literal in call validate the type + * add validation for assigning from void function call + * add rule to forbid var use before assignment + */ From 8afba76f3f3497a85c9b3f748bbd608c8e68b79c Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 20 Oct 2024 12:10:22 +0200 Subject: [PATCH 81/87] WIP --- .../jack/listener/global.symbol.listener.ts | 4 +- .../global.symbol.table.listener.test.ts | 18 ++--- .../jack/listener/validator.listener.test.ts | 66 +++++++++---------- 3 files changed, 45 insertions(+), 43 deletions(-) diff --git a/simulator/src/jack/listener/global.symbol.listener.ts b/simulator/src/jack/listener/global.symbol.listener.ts index f08bc52f..172b83f0 100644 --- a/simulator/src/jack/listener/global.symbol.listener.ts +++ b/simulator/src/jack/listener/global.symbol.listener.ts @@ -43,7 +43,7 @@ export class GlobalSymbolTableListener extends JackParserListener { } const e = DuplicatedClassError( ruleContextToSpan(classNameCtx), - className + className, ); this.errors.push(e); return; @@ -72,7 +72,7 @@ export class GlobalSymbolTableListener extends JackParserListener { throw new Error("Start token should not be null"); } this.errors.push( - DuplicatedSubroutineError(ruleContextToSpan(nameCtx), subroutineName) + DuplicatedSubroutineError(ruleContextToSpan(nameCtx), subroutineName), ); this.stopProcessingSubroutines = true; } else { diff --git a/simulator/src/jack/listener/global.symbol.table.listener.test.ts b/simulator/src/jack/listener/global.symbol.table.listener.test.ts index 85a80e5a..99c1ab4f 100644 --- a/simulator/src/jack/listener/global.symbol.table.listener.test.ts +++ b/simulator/src/jack/listener/global.symbol.table.listener.test.ts @@ -2,9 +2,7 @@ import { FileSystem } from "@davidsouther/jiffies/lib/esm/fs.js"; import { NodeFileSystemAdapter } from "@davidsouther/jiffies/lib/esm/fs_node.js"; import path from "path"; import { builtInSymbols } from "../builtins"; -import { - JackCompilerErrorType -} from "../error"; +import { JackCompilerErrorType } from "../error"; import { createSubroutineSymbol, SubroutineType } from "../symbol"; import { getTestResourcePath, @@ -45,7 +43,11 @@ describe("Jack global symbol table listener", () => { }`; const globalSymbolTableListener = new GlobalSymbolTableListener(); testJackGlobalSymbolListener(input, undefined, globalSymbolTableListener); - testJackGlobalSymbolListener(input, "DuplicatedClassError", globalSymbolTableListener); + testJackGlobalSymbolListener( + input, + "DuplicatedClassError", + globalSymbolTableListener, + ); }); test("duplicated built in class", () => { const input = ` @@ -62,12 +64,12 @@ describe("Jack global symbol table listener", () => { "Fraction.getNumerator": createSubroutineSymbol( 0, SubroutineType.Method, - 0 + 0, ), "Fraction.getDenominator": createSubroutineSymbol( 0, SubroutineType.Method, - 0 + 0, ), "Fraction.plus": createSubroutineSymbol(1, SubroutineType.Method, 1), "Fraction.dispose": createSubroutineSymbol(0, SubroutineType.Method, 0), @@ -93,7 +95,7 @@ describe("Jack global symbol table listener", () => { function testJackGlobalSymbolListener( input: string, expectedError?: T, - globalSymbolTableListener = new GlobalSymbolTableListener() + globalSymbolTableListener = new GlobalSymbolTableListener(), ) { const tree = parseJackText(input); listenToTheTree(tree, globalSymbolTableListener); @@ -109,7 +111,7 @@ function testJackGlobalSymbolListener( throw new Error( `Expected error ${expectedError} but got '` + JSON.stringify(globalSymbolTableListener.errors) + - "'" + "'", ); } } else { diff --git a/simulator/src/jack/listener/validator.listener.test.ts b/simulator/src/jack/listener/validator.listener.test.ts index f5f95ed6..810c5827 100644 --- a/simulator/src/jack/listener/validator.listener.test.ts +++ b/simulator/src/jack/listener/validator.listener.test.ts @@ -70,7 +70,7 @@ describe("Jack validator listener", () => { class Main { ${classBody} }`, - 'DuplicatedVariableError', + "DuplicatedVariableError", ); }, ); @@ -87,7 +87,7 @@ describe("Jack validator listener", () => { return; } }`, - 'UndeclaredVariableError', + "UndeclaredVariableError", ); }); @@ -102,7 +102,7 @@ describe("Jack validator listener", () => { return; } }`, - 'UndeclaredVariableError', + "UndeclaredVariableError", { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 1), @@ -122,7 +122,7 @@ describe("Jack validator listener", () => { } } }`, - 'UndeclaredVariableError', + "UndeclaredVariableError", ); }); @@ -138,7 +138,7 @@ describe("Jack validator listener", () => { return; } }`, - 'UnknownClassError', + "UnknownClassError", ); }); @@ -165,7 +165,7 @@ describe("Jack validator listener", () => { return; } }`, - 'UnknownClassError', + "UnknownClassError", ); }); @@ -191,7 +191,7 @@ describe("Jack validator listener", () => { return; } }`, - 'UnknownClassError', + "UnknownClassError", ); }); test("var known type", () => { @@ -213,7 +213,7 @@ describe("Jack validator listener", () => { class Main { field T t; }`, - 'UnknownClassError', + "UnknownClassError", ); }); test("field known type", () => { @@ -232,7 +232,7 @@ describe("Jack validator listener", () => { class Main { static T t; }`, - 'UnknownClassError', + "UnknownClassError", ); }); test("static field known type", () => { @@ -258,7 +258,7 @@ describe("Jack validator listener", () => { return; } }`, - 'NonVoidFunctionNoReturnError', + "NonVoidFunctionNoReturnError", ); }); @@ -270,7 +270,7 @@ describe("Jack validator listener", () => { return 1; } }`, - 'VoidSubroutineReturnsValueError', + "VoidSubroutineReturnsValueError", ); }); /** @@ -291,7 +291,7 @@ describe("Jack validator listener", () => { } } }`, - 'SubroutineNotAllPathsReturnError', + "SubroutineNotAllPathsReturnError", ); }); test("else missing return ", () => { @@ -308,7 +308,7 @@ describe("Jack validator listener", () => { } } }`, - 'SubroutineNotAllPathsReturnError', + "SubroutineNotAllPathsReturnError", ); }); @@ -324,7 +324,7 @@ describe("Jack validator listener", () => { } } }`, - 'SubroutineNotAllPathsReturnError', + "SubroutineNotAllPathsReturnError", ); }); @@ -340,7 +340,7 @@ describe("Jack validator listener", () => { } } }`, - 'SubroutineNotAllPathsReturnError', + "SubroutineNotAllPathsReturnError", ); }); @@ -362,7 +362,7 @@ describe("Jack validator listener", () => { } } }`, - 'SubroutineNotAllPathsReturnError', + "SubroutineNotAllPathsReturnError", ); }); test("nested if missing return 2", () => { @@ -383,7 +383,7 @@ describe("Jack validator listener", () => { } } }`, - 'SubroutineNotAllPathsReturnError', + "SubroutineNotAllPathsReturnError", ); }); @@ -405,7 +405,7 @@ describe("Jack validator listener", () => { } } }`, - 'SubroutineNotAllPathsReturnError', + "SubroutineNotAllPathsReturnError", ); }); test("should be valid", () => { @@ -435,7 +435,7 @@ describe("Jack validator listener", () => { return; } }`, - 'UnknownSubroutineCallError', + "UnknownSubroutineCallError", ); }); @@ -451,7 +451,7 @@ describe("Jack validator listener", () => { return; } }`, - 'IncorrectParamsNumberInSubroutineCallError', + "IncorrectParamsNumberInSubroutineCallError", { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 2), @@ -522,7 +522,7 @@ describe("Jack validator listener", () => { return; } }`, - 'MethodCalledAsFunctionError', + "MethodCalledAsFunctionError", { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), @@ -542,7 +542,7 @@ describe("Jack validator listener", () => { return; } }`, - 'FunctionCalledAsMethodError', + "FunctionCalledAsMethodError", { Main: genericSymbol(), "Main.b": genericSymbol(SubroutineType.Function, 0), @@ -558,7 +558,7 @@ describe("Jack validator listener", () => { return this; } }`, - 'IncorrectConstructorReturnTypeError', + "IncorrectConstructorReturnTypeError", { Main: genericSymbol(), D: genericSymbol(), @@ -576,7 +576,7 @@ describe("Jack validator listener", () => { let a=0; } }`, - 'UnreachableCodeError', + "UnreachableCodeError", { Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), @@ -591,7 +591,7 @@ describe("Jack validator listener", () => { return 1; } }`, - 'ConstructorMushReturnThisError', + "ConstructorMushReturnThisError", { Main: genericSymbol(), "Main.new": genericSymbol(SubroutineType.Constructor, 0), @@ -608,7 +608,7 @@ describe("Jack validator listener", () => { return; } }`, - 'WrongLiteralTypeError', + "WrongLiteralTypeError", { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -626,7 +626,7 @@ describe("Jack validator listener", () => { return; } }`, - 'WrongLiteralTypeError', + "WrongLiteralTypeError", { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -644,7 +644,7 @@ describe("Jack validator listener", () => { return; } }`, - 'WrongLiteralTypeError', + "WrongLiteralTypeError", { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -661,7 +661,7 @@ describe("Jack validator listener", () => { return; } }`, - 'IntLiteralIsOutOfRangeError', + "IntLiteralIsOutOfRangeError", { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -678,7 +678,7 @@ describe("Jack validator listener", () => { return; } }`, - 'IntLiteralIsOutOfRangeError', + "IntLiteralIsOutOfRangeError", { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -695,7 +695,7 @@ describe("Jack validator listener", () => { return; } }`, - 'FieldCantBeReferencedInFunctionError', + "FieldCantBeReferencedInFunctionError", { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -729,7 +729,7 @@ describe("Jack validator listener", () => { return; } }`, - 'ThisCantBeReferencedInFunctionError', + "ThisCantBeReferencedInFunctionError", { Main: genericSymbol(), "Main.a": genericSymbol(SubroutineType.Function, 0), @@ -739,7 +739,7 @@ describe("Jack validator listener", () => { test("class name doesn't match filename", () => { testValidator( `class A {}`, - 'FilenameDoesntMatchClassNameError', + "FilenameDoesntMatchClassNameError", { A: genericSymbol(), }, From 2dbf34dbd59788465249ebbafc7a7fdc7d4016b7 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Sun, 20 Oct 2024 12:25:05 +0200 Subject: [PATCH 82/87] Fix formatting and lint errors --- simulator/src/jack/error.ts | 2 +- simulator/src/jack/generated/JackLexer.ts | 1 - simulator/src/jack/generated/JackParser.ts | 266 +++++++++--------- .../src/jack/generated/JackParserListener.ts | 108 +++---- simulator/src/jack/listener/common.ts | 10 - simulator/src/jack/listener/error.listener.ts | 14 +- .../src/jack/listener/validator.listener.ts | 3 +- .../src/jack/listener/vm.writer.listener.ts | 3 +- 8 files changed, 204 insertions(+), 203 deletions(-) diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index ca623f72..983720db 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,5 +1,5 @@ +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert"; import { ParserRuleContext, TerminalNode } from "antlr4ng"; -import { assertExists } from "./listener/common.js"; export interface Span { start: number; diff --git a/simulator/src/jack/generated/JackLexer.ts b/simulator/src/jack/generated/JackLexer.ts index c0f50d70..e59c8633 100644 --- a/simulator/src/jack/generated/JackLexer.ts +++ b/simulator/src/jack/generated/JackLexer.ts @@ -1,7 +1,6 @@ // Generated from JackLexer.g4 by ANTLR 4.13.1 import * as antlr from "antlr4ng"; -import { Token } from "antlr4ng"; export class JackLexer extends antlr.Lexer { public static readonly CLASS = 1; diff --git a/simulator/src/jack/generated/JackParser.ts b/simulator/src/jack/generated/JackParser.ts index 83b10646..7038ddac 100644 --- a/simulator/src/jack/generated/JackParser.ts +++ b/simulator/src/jack/generated/JackParser.ts @@ -1,14 +1,10 @@ // Generated from JackParser.g4 by ANTLR 4.13.1 import * as antlr from "antlr4ng"; -import { Token } from "antlr4ng"; - -import { JackParserListener } from "./JackParserListener.js"; -// for running tests with parameters, TODO: discuss strategy for typed parameters in CI -// eslint-disable-next-line no-unused-vars -type int = number; import { SubroutineScope, LocalSymbolTable } from "../symbol.js"; +import { JackParserListener } from "./JackParserListener.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; export class JackParser extends antlr.Parser { public static readonly CLASS = 1; @@ -277,7 +273,7 @@ export class JackParser extends antlr.Parser { ); } public program(): ProgramContext { - let localContext = new ProgramContext(this.context, this.state); + const localContext = new ProgramContext(this.context, this.state); this.enterRule(localContext, 0, JackParser.RULE_program); try { this.enterOuterAlt(localContext, 1); @@ -300,7 +296,7 @@ export class JackParser extends antlr.Parser { return localContext; } public classDeclaration(): ClassDeclarationContext { - let localContext = new ClassDeclarationContext(this.context, this.state); + const localContext = new ClassDeclarationContext(this.context, this.state); this.enterRule(localContext, 2, JackParser.RULE_classDeclaration); let _la: number; try { @@ -356,7 +352,7 @@ export class JackParser extends antlr.Parser { return localContext; } public className(): ClassNameContext { - let localContext = new ClassNameContext(this.context, this.state); + const localContext = new ClassNameContext(this.context, this.state); this.enterRule(localContext, 4, JackParser.RULE_className); try { this.enterOuterAlt(localContext, 1); @@ -377,7 +373,7 @@ export class JackParser extends antlr.Parser { return localContext; } public classVarDec(): ClassVarDecContext { - let localContext = new ClassVarDecContext(this.context, this.state); + const localContext = new ClassVarDecContext(this.context, this.state); this.enterRule(localContext, 6, JackParser.RULE_classVarDec); let _la: number; try { @@ -409,7 +405,7 @@ export class JackParser extends antlr.Parser { return localContext; } public fieldList(): FieldListContext { - let localContext = new FieldListContext(this.context, this.state); + const localContext = new FieldListContext(this.context, this.state); this.enterRule(localContext, 8, JackParser.RULE_fieldList); let _la: number; try { @@ -449,7 +445,7 @@ export class JackParser extends antlr.Parser { return localContext; } public fieldName(): FieldNameContext { - let localContext = new FieldNameContext(this.context, this.state); + const localContext = new FieldNameContext(this.context, this.state); this.enterRule(localContext, 10, JackParser.RULE_fieldName); try { this.enterOuterAlt(localContext, 1); @@ -470,7 +466,7 @@ export class JackParser extends antlr.Parser { return localContext; } public subroutineDeclaration(): SubroutineDeclarationContext { - let localContext = new SubroutineDeclarationContext( + const localContext = new SubroutineDeclarationContext( this.context, this.state, ); @@ -496,7 +492,7 @@ export class JackParser extends antlr.Parser { return localContext; } public subroutineType(): SubroutineTypeContext { - let localContext = new SubroutineTypeContext(this.context, this.state); + const localContext = new SubroutineTypeContext(this.context, this.state); this.enterRule(localContext, 14, JackParser.RULE_subroutineType); let _la: number; try { @@ -524,7 +520,7 @@ export class JackParser extends antlr.Parser { return localContext; } public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - let localContext = new SubroutineDecWithoutTypeContext( + const localContext = new SubroutineDecWithoutTypeContext( this.context, this.state, ); @@ -558,7 +554,7 @@ export class JackParser extends antlr.Parser { return localContext; } public subroutineName(): SubroutineNameContext { - let localContext = new SubroutineNameContext(this.context, this.state); + const localContext = new SubroutineNameContext(this.context, this.state); this.enterRule(localContext, 18, JackParser.RULE_subroutineName); try { this.enterOuterAlt(localContext, 1); @@ -579,7 +575,7 @@ export class JackParser extends antlr.Parser { return localContext; } public subroutineReturnType(): SubroutineReturnTypeContext { - let localContext = new SubroutineReturnTypeContext( + const localContext = new SubroutineReturnTypeContext( this.context, this.state, ); @@ -621,7 +617,7 @@ export class JackParser extends antlr.Parser { return localContext; } public varType(): VarTypeContext { - let localContext = new VarTypeContext(this.context, this.state); + const localContext = new VarTypeContext(this.context, this.state); this.enterRule(localContext, 22, JackParser.RULE_varType); let _la: number; try { @@ -651,7 +647,7 @@ export class JackParser extends antlr.Parser { return localContext; } public parameterList(): ParameterListContext { - let localContext = new ParameterListContext(this.context, this.state); + const localContext = new ParameterListContext(this.context, this.state); this.enterRule(localContext, 24, JackParser.RULE_parameterList); let _la: number; try { @@ -696,7 +692,7 @@ export class JackParser extends antlr.Parser { return localContext; } public parameter(): ParameterContext { - let localContext = new ParameterContext(this.context, this.state); + const localContext = new ParameterContext(this.context, this.state); this.enterRule(localContext, 26, JackParser.RULE_parameter); try { this.enterOuterAlt(localContext, 1); @@ -719,7 +715,7 @@ export class JackParser extends antlr.Parser { return localContext; } public parameterName(): ParameterNameContext { - let localContext = new ParameterNameContext(this.context, this.state); + const localContext = new ParameterNameContext(this.context, this.state); this.enterRule(localContext, 28, JackParser.RULE_parameterName); try { this.enterOuterAlt(localContext, 1); @@ -740,7 +736,7 @@ export class JackParser extends antlr.Parser { return localContext; } public subroutineBody(): SubroutineBodyContext { - let localContext = new SubroutineBodyContext(this.context, this.state); + const localContext = new SubroutineBodyContext(this.context, this.state); this.enterRule(localContext, 30, JackParser.RULE_subroutineBody); let _la: number; try { @@ -780,7 +776,7 @@ export class JackParser extends antlr.Parser { return localContext; } public rBrace(): RBraceContext { - let localContext = new RBraceContext(this.context, this.state); + const localContext = new RBraceContext(this.context, this.state); this.enterRule(localContext, 32, JackParser.RULE_rBrace); try { this.enterOuterAlt(localContext, 1); @@ -801,7 +797,7 @@ export class JackParser extends antlr.Parser { return localContext; } public varDeclaration(): VarDeclarationContext { - let localContext = new VarDeclarationContext(this.context, this.state); + const localContext = new VarDeclarationContext(this.context, this.state); this.enterRule(localContext, 34, JackParser.RULE_varDeclaration); let _la: number; try { @@ -845,7 +841,7 @@ export class JackParser extends antlr.Parser { return localContext; } public varNameInDeclaration(): VarNameInDeclarationContext { - let localContext = new VarNameInDeclarationContext( + const localContext = new VarNameInDeclarationContext( this.context, this.state, ); @@ -869,7 +865,7 @@ export class JackParser extends antlr.Parser { return localContext; } public statements(): StatementsContext { - let localContext = new StatementsContext(this.context, this.state); + const localContext = new StatementsContext(this.context, this.state); this.enterRule(localContext, 38, JackParser.RULE_statements); let _la: number; try { @@ -903,7 +899,7 @@ export class JackParser extends antlr.Parser { return localContext; } public statement(): StatementContext { - let localContext = new StatementContext(this.context, this.state); + const localContext = new StatementContext(this.context, this.state); this.enterRule(localContext, 40, JackParser.RULE_statement); try { this.state = 195; @@ -960,7 +956,7 @@ export class JackParser extends antlr.Parser { return localContext; } public letStatement(): LetStatementContext { - let localContext = new LetStatementContext(this.context, this.state); + const localContext = new LetStatementContext(this.context, this.state); this.enterRule(localContext, 42, JackParser.RULE_letStatement); try { this.enterOuterAlt(localContext, 1); @@ -1005,7 +1001,7 @@ export class JackParser extends antlr.Parser { return localContext; } public equals(): EqualsContext { - let localContext = new EqualsContext(this.context, this.state); + const localContext = new EqualsContext(this.context, this.state); this.enterRule(localContext, 44, JackParser.RULE_equals); try { this.enterOuterAlt(localContext, 1); @@ -1026,7 +1022,7 @@ export class JackParser extends antlr.Parser { return localContext; } public ifElseStatement(): IfElseStatementContext { - let localContext = new IfElseStatementContext(this.context, this.state); + const localContext = new IfElseStatementContext(this.context, this.state); this.enterRule(localContext, 46, JackParser.RULE_ifElseStatement); let _la: number; try { @@ -1057,7 +1053,7 @@ export class JackParser extends antlr.Parser { return localContext; } public ifStatement(): IfStatementContext { - let localContext = new IfStatementContext(this.context, this.state); + const localContext = new IfStatementContext(this.context, this.state); this.enterRule(localContext, 48, JackParser.RULE_ifStatement); try { this.enterOuterAlt(localContext, 1); @@ -1090,7 +1086,7 @@ export class JackParser extends antlr.Parser { return localContext; } public ifExpression(): IfExpressionContext { - let localContext = new IfExpressionContext(this.context, this.state); + const localContext = new IfExpressionContext(this.context, this.state); this.enterRule(localContext, 50, JackParser.RULE_ifExpression); try { this.enterOuterAlt(localContext, 1); @@ -1111,7 +1107,7 @@ export class JackParser extends antlr.Parser { return localContext; } public elseStatement(): ElseStatementContext { - let localContext = new ElseStatementContext(this.context, this.state); + const localContext = new ElseStatementContext(this.context, this.state); this.enterRule(localContext, 52, JackParser.RULE_elseStatement); try { this.enterOuterAlt(localContext, 1); @@ -1138,7 +1134,7 @@ export class JackParser extends antlr.Parser { return localContext; } public whileStatement(): WhileStatementContext { - let localContext = new WhileStatementContext(this.context, this.state); + const localContext = new WhileStatementContext(this.context, this.state); this.enterRule(localContext, 54, JackParser.RULE_whileStatement); try { this.enterOuterAlt(localContext, 1); @@ -1171,7 +1167,7 @@ export class JackParser extends antlr.Parser { return localContext; } public whileExpression(): WhileExpressionContext { - let localContext = new WhileExpressionContext(this.context, this.state); + const localContext = new WhileExpressionContext(this.context, this.state); this.enterRule(localContext, 56, JackParser.RULE_whileExpression); try { this.enterOuterAlt(localContext, 1); @@ -1192,7 +1188,7 @@ export class JackParser extends antlr.Parser { return localContext; } public doStatement(): DoStatementContext { - let localContext = new DoStatementContext(this.context, this.state); + const localContext = new DoStatementContext(this.context, this.state); this.enterRule(localContext, 58, JackParser.RULE_doStatement); try { this.enterOuterAlt(localContext, 1); @@ -1217,7 +1213,7 @@ export class JackParser extends antlr.Parser { return localContext; } public subroutineCall(): SubroutineCallContext { - let localContext = new SubroutineCallContext(this.context, this.state); + const localContext = new SubroutineCallContext(this.context, this.state); this.enterRule(localContext, 60, JackParser.RULE_subroutineCall); try { this.enterOuterAlt(localContext, 1); @@ -1244,7 +1240,7 @@ export class JackParser extends antlr.Parser { return localContext; } public subroutineId(): SubroutineIdContext { - let localContext = new SubroutineIdContext(this.context, this.state); + const localContext = new SubroutineIdContext(this.context, this.state); this.enterRule(localContext, 62, JackParser.RULE_subroutineId); try { this.enterOuterAlt(localContext, 1); @@ -1295,7 +1291,7 @@ export class JackParser extends antlr.Parser { return localContext; } public returnStatement(): ReturnStatementContext { - let localContext = new ReturnStatementContext(this.context, this.state); + const localContext = new ReturnStatementContext(this.context, this.state); this.enterRule(localContext, 64, JackParser.RULE_returnStatement); let _la: number; try { @@ -1332,7 +1328,7 @@ export class JackParser extends antlr.Parser { return localContext; } public expressionList(): ExpressionListContext { - let localContext = new ExpressionListContext(this.context, this.state); + const localContext = new ExpressionListContext(this.context, this.state); this.enterRule(localContext, 66, JackParser.RULE_expressionList); let _la: number; try { @@ -1387,11 +1383,10 @@ export class JackParser extends antlr.Parser { _p = 0; } - let parentContext = this.context; - let parentState = this.state; + const parentContext = this.context; + const parentState = this.state; let localContext = new ExpressionContext(this.context, parentState); - let previousContext = localContext; - let _startState = 68; + const _startState = 68; this.enterRecursionRule(localContext, 68, JackParser.RULE_expression, _p); try { let alternative: number; @@ -1439,7 +1434,7 @@ export class JackParser extends antlr.Parser { } break; } - this.context!.stop = this.tokenStream.LT(-1); + assertExists(this.context).stop = this.tokenStream.LT(-1); this.state = 286; this.errorHandler.sync(this); alternative = this.interpreter.adaptivePredict( @@ -1455,7 +1450,6 @@ export class JackParser extends antlr.Parser { if (this.parseListeners != null) { this.triggerExitRuleEvent(); } - previousContext = localContext; { { localContext = new ExpressionContext( @@ -1502,7 +1496,7 @@ export class JackParser extends antlr.Parser { return localContext; } public constant(): ConstantContext { - let localContext = new ConstantContext(this.context, this.state); + const localContext = new ConstantContext(this.context, this.state); this.enterRule(localContext, 70, JackParser.RULE_constant); try { this.state = 294; @@ -1560,7 +1554,7 @@ export class JackParser extends antlr.Parser { return localContext; } public varName(): VarNameContext { - let localContext = new VarNameContext(this.context, this.state); + const localContext = new VarNameContext(this.context, this.state); this.enterRule(localContext, 72, JackParser.RULE_varName); try { this.enterOuterAlt(localContext, 1); @@ -1581,7 +1575,7 @@ export class JackParser extends antlr.Parser { return localContext; } public arrayAccess(): ArrayAccessContext { - let localContext = new ArrayAccessContext(this.context, this.state); + const localContext = new ArrayAccessContext(this.context, this.state); this.enterRule(localContext, 74, JackParser.RULE_arrayAccess); try { this.enterOuterAlt(localContext, 1); @@ -1608,7 +1602,7 @@ export class JackParser extends antlr.Parser { return localContext; } public unaryOperation(): UnaryOperationContext { - let localContext = new UnaryOperationContext(this.context, this.state); + const localContext = new UnaryOperationContext(this.context, this.state); this.enterRule(localContext, 76, JackParser.RULE_unaryOperation); try { this.enterOuterAlt(localContext, 1); @@ -1631,7 +1625,7 @@ export class JackParser extends antlr.Parser { return localContext; } public groupedExpression(): GroupedExpressionContext { - let localContext = new GroupedExpressionContext(this.context, this.state); + const localContext = new GroupedExpressionContext(this.context, this.state); this.enterRule(localContext, 78, JackParser.RULE_groupedExpression); try { this.enterOuterAlt(localContext, 1); @@ -1656,7 +1650,7 @@ export class JackParser extends antlr.Parser { return localContext; } public booleanLiteral(): BooleanLiteralContext { - let localContext = new BooleanLiteralContext(this.context, this.state); + const localContext = new BooleanLiteralContext(this.context, this.state); this.enterRule(localContext, 80, JackParser.RULE_booleanLiteral); let _la: number; try { @@ -1684,7 +1678,7 @@ export class JackParser extends antlr.Parser { return localContext; } public unaryOperator(): UnaryOperatorContext { - let localContext = new UnaryOperatorContext(this.context, this.state); + const localContext = new UnaryOperatorContext(this.context, this.state); this.enterRule(localContext, 82, JackParser.RULE_unaryOperator); let _la: number; try { @@ -1712,7 +1706,7 @@ export class JackParser extends antlr.Parser { return localContext; } public binaryOperator(): BinaryOperatorContext { - let localContext = new BinaryOperatorContext(this.context, this.state); + const localContext = new BinaryOperatorContext(this.context, this.state); this.enterRule(localContext, 84, JackParser.RULE_binaryOperator); let _la: number; try { @@ -1927,10 +1921,10 @@ export class ProgramContext extends antlr.ParserRuleContext { super(parent, invokingState); } public classDeclaration(): ClassDeclarationContext { - return this.getRuleContext(0, ClassDeclarationContext)!; + return assertExists(this.getRuleContext(0, ClassDeclarationContext)); } public EOF(): antlr.TerminalNode { - return this.getToken(JackParser.EOF, 0)!; + return assertExists(this.getToken(JackParser.EOF, 0)); } public override get ruleIndex(): number { return JackParser.RULE_program; @@ -1956,16 +1950,16 @@ export class ClassDeclarationContext extends antlr.ParserRuleContext { super(parent, invokingState); } public CLASS(): antlr.TerminalNode { - return this.getToken(JackParser.CLASS, 0)!; + return assertExists(this.getToken(JackParser.CLASS, 0)); } public className(): ClassNameContext { - return this.getRuleContext(0, ClassNameContext)!; + return assertExists(this.getRuleContext(0, ClassNameContext)); } public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; + return assertExists(this.getToken(JackParser.LBRACE, 0)); } public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; + return assertExists(this.getRuleContext(0, RBraceContext)); } public classVarDec(): ClassVarDecContext[]; public classVarDec(i: number): ClassVarDecContext | null; @@ -2012,7 +2006,7 @@ export class ClassNameContext extends antlr.ParserRuleContext { super(parent, invokingState); } public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; + return assertExists(this.getToken(JackParser.IDENTIFIER, 0)); } public override get ruleIndex(): number { return JackParser.RULE_className; @@ -2037,10 +2031,10 @@ export class ClassVarDecContext extends antlr.ParserRuleContext { super(parent, invokingState); } public fieldList(): FieldListContext { - return this.getRuleContext(0, FieldListContext)!; + return assertExists(this.getRuleContext(0, FieldListContext)); } public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; + return assertExists(this.getToken(JackParser.SEMICOLON, 0)); } public STATIC(): antlr.TerminalNode | null { return this.getToken(JackParser.STATIC, 0); @@ -2071,7 +2065,7 @@ export class FieldListContext extends antlr.ParserRuleContext { super(parent, invokingState); } public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext)!; + return assertExists(this.getRuleContext(0, VarTypeContext)); } public fieldName(): FieldNameContext[]; public fieldName(i: number): FieldNameContext | null; @@ -2114,7 +2108,7 @@ export class FieldNameContext extends antlr.ParserRuleContext { super(parent, invokingState); } public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; + return assertExists(this.getToken(JackParser.IDENTIFIER, 0)); } public override get ruleIndex(): number { return JackParser.RULE_fieldName; @@ -2140,10 +2134,12 @@ export class SubroutineDeclarationContext extends antlr.ParserRuleContext { super(parent, invokingState); } public subroutineType(): SubroutineTypeContext { - return this.getRuleContext(0, SubroutineTypeContext)!; + return assertExists(this.getRuleContext(0, SubroutineTypeContext)); } public subroutineDecWithoutType(): SubroutineDecWithoutTypeContext { - return this.getRuleContext(0, SubroutineDecWithoutTypeContext)!; + return assertExists( + this.getRuleContext(0, SubroutineDecWithoutTypeContext), + ); } public override get ruleIndex(): number { return JackParser.RULE_subroutineDeclaration; @@ -2199,22 +2195,22 @@ export class SubroutineDecWithoutTypeContext extends antlr.ParserRuleContext { super(parent, invokingState); } public subroutineReturnType(): SubroutineReturnTypeContext { - return this.getRuleContext(0, SubroutineReturnTypeContext)!; + return assertExists(this.getRuleContext(0, SubroutineReturnTypeContext)); } public subroutineName(): SubroutineNameContext { - return this.getRuleContext(0, SubroutineNameContext)!; + return assertExists(this.getRuleContext(0, SubroutineNameContext)); } public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; + return assertExists(this.getToken(JackParser.LPAREN, 0)); } public parameterList(): ParameterListContext { - return this.getRuleContext(0, ParameterListContext)!; + return assertExists(this.getRuleContext(0, ParameterListContext)); } public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; + return assertExists(this.getToken(JackParser.RPAREN, 0)); } public subroutineBody(): SubroutineBodyContext { - return this.getRuleContext(0, SubroutineBodyContext)!; + return assertExists(this.getRuleContext(0, SubroutineBodyContext)); } public override get ruleIndex(): number { return JackParser.RULE_subroutineDecWithoutType; @@ -2239,7 +2235,7 @@ export class SubroutineNameContext extends antlr.ParserRuleContext { super(parent, invokingState); } public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; + return assertExists(this.getToken(JackParser.IDENTIFIER, 0)); } public override get ruleIndex(): number { return JackParser.RULE_subroutineName; @@ -2366,10 +2362,10 @@ export class ParameterContext extends antlr.ParserRuleContext { super(parent, invokingState); } public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext)!; + return assertExists(this.getRuleContext(0, VarTypeContext)); } public parameterName(): ParameterNameContext { - return this.getRuleContext(0, ParameterNameContext)!; + return assertExists(this.getRuleContext(0, ParameterNameContext)); } public override get ruleIndex(): number { return JackParser.RULE_parameter; @@ -2394,7 +2390,7 @@ export class ParameterNameContext extends antlr.ParserRuleContext { super(parent, invokingState); } public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; + return assertExists(this.getToken(JackParser.IDENTIFIER, 0)); } public override get ruleIndex(): number { return JackParser.RULE_parameterName; @@ -2419,13 +2415,13 @@ export class SubroutineBodyContext extends antlr.ParserRuleContext { super(parent, invokingState); } public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; + return assertExists(this.getToken(JackParser.LBRACE, 0)); } public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext)!; + return assertExists(this.getRuleContext(0, StatementsContext)); } public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; + return assertExists(this.getRuleContext(0, RBraceContext)); } public varDeclaration(): VarDeclarationContext[]; public varDeclaration(i: number): VarDeclarationContext | null; @@ -2461,7 +2457,7 @@ export class RBraceContext extends antlr.ParserRuleContext { super(parent, invokingState); } public RBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.RBRACE, 0)!; + return assertExists(this.getToken(JackParser.RBRACE, 0)); } public override get ruleIndex(): number { return JackParser.RULE_rBrace; @@ -2486,10 +2482,10 @@ export class VarDeclarationContext extends antlr.ParserRuleContext { super(parent, invokingState); } public VAR(): antlr.TerminalNode { - return this.getToken(JackParser.VAR, 0)!; + return assertExists(this.getToken(JackParser.VAR, 0)); } public varType(): VarTypeContext { - return this.getRuleContext(0, VarTypeContext)!; + return assertExists(this.getRuleContext(0, VarTypeContext)); } public varNameInDeclaration(): VarNameInDeclarationContext[]; public varNameInDeclaration(i: number): VarNameInDeclarationContext | null; @@ -2503,7 +2499,7 @@ export class VarDeclarationContext extends antlr.ParserRuleContext { return this.getRuleContext(i, VarNameInDeclarationContext); } public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; + return assertExists(this.getToken(JackParser.SEMICOLON, 0)); } public COMMA(): antlr.TerminalNode[]; public COMMA(i: number): antlr.TerminalNode | null; @@ -2537,7 +2533,7 @@ export class VarNameInDeclarationContext extends antlr.ParserRuleContext { super(parent, invokingState); } public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; + return assertExists(this.getToken(JackParser.IDENTIFIER, 0)); } public override get ruleIndex(): number { return JackParser.RULE_varNameInDeclaration; @@ -2630,16 +2626,16 @@ export class LetStatementContext extends antlr.ParserRuleContext { super(parent, invokingState); } public LET(): antlr.TerminalNode { - return this.getToken(JackParser.LET, 0)!; + return assertExists(this.getToken(JackParser.LET, 0)); } public equals(): EqualsContext { - return this.getRuleContext(0, EqualsContext)!; + return assertExists(this.getRuleContext(0, EqualsContext)); } public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; + return assertExists(this.getRuleContext(0, ExpressionContext)); } public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; + return assertExists(this.getToken(JackParser.SEMICOLON, 0)); } public varName(): VarNameContext | null { return this.getRuleContext(0, VarNameContext); @@ -2670,7 +2666,7 @@ export class EqualsContext extends antlr.ParserRuleContext { super(parent, invokingState); } public EQUALS(): antlr.TerminalNode { - return this.getToken(JackParser.EQUALS, 0)!; + return assertExists(this.getToken(JackParser.EQUALS, 0)); } public override get ruleIndex(): number { return JackParser.RULE_equals; @@ -2688,7 +2684,7 @@ export class EqualsContext extends antlr.ParserRuleContext { } export class IfElseStatementContext extends antlr.ParserRuleContext { - public endLabel: string = ""; + public endLabel = ""; public constructor( parent: antlr.ParserRuleContext | null, invokingState: number, @@ -2696,7 +2692,7 @@ export class IfElseStatementContext extends antlr.ParserRuleContext { super(parent, invokingState); } public ifStatement(): IfStatementContext { - return this.getRuleContext(0, IfStatementContext)!; + return assertExists(this.getRuleContext(0, IfStatementContext)); } public elseStatement(): ElseStatementContext | null { return this.getRuleContext(0, ElseStatementContext); @@ -2717,7 +2713,7 @@ export class IfElseStatementContext extends antlr.ParserRuleContext { } export class IfStatementContext extends antlr.ParserRuleContext { - public endLabel: string = ""; + public endLabel = ""; public constructor( parent: antlr.ParserRuleContext | null, invokingState: number, @@ -2725,25 +2721,25 @@ export class IfStatementContext extends antlr.ParserRuleContext { super(parent, invokingState); } public IF(): antlr.TerminalNode { - return this.getToken(JackParser.IF, 0)!; + return assertExists(this.getToken(JackParser.IF, 0)); } public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; + return assertExists(this.getToken(JackParser.LPAREN, 0)); } public ifExpression(): IfExpressionContext { - return this.getRuleContext(0, IfExpressionContext)!; + return assertExists(this.getRuleContext(0, IfExpressionContext)); } public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; + return assertExists(this.getToken(JackParser.RPAREN, 0)); } public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; + return assertExists(this.getToken(JackParser.LBRACE, 0)); } public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext)!; + return assertExists(this.getRuleContext(0, StatementsContext)); } public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; + return assertExists(this.getRuleContext(0, RBraceContext)); } public override get ruleIndex(): number { return JackParser.RULE_ifStatement; @@ -2768,7 +2764,7 @@ export class IfExpressionContext extends antlr.ParserRuleContext { super(parent, invokingState); } public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; + return assertExists(this.getRuleContext(0, ExpressionContext)); } public override get ruleIndex(): number { return JackParser.RULE_ifExpression; @@ -2793,16 +2789,16 @@ export class ElseStatementContext extends antlr.ParserRuleContext { super(parent, invokingState); } public ELSE(): antlr.TerminalNode { - return this.getToken(JackParser.ELSE, 0)!; + return assertExists(this.getToken(JackParser.ELSE, 0)); } public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; + return assertExists(this.getToken(JackParser.LBRACE, 0)); } public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext)!; + return assertExists(this.getRuleContext(0, StatementsContext)); } public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; + return assertExists(this.getRuleContext(0, RBraceContext)); } public override get ruleIndex(): number { return JackParser.RULE_elseStatement; @@ -2820,8 +2816,8 @@ export class ElseStatementContext extends antlr.ParserRuleContext { } export class WhileStatementContext extends antlr.ParserRuleContext { - public startLabel: string = ""; - endLabel: string = ""; + public startLabel = ""; + endLabel = ""; public constructor( parent: antlr.ParserRuleContext | null, invokingState: number, @@ -2829,25 +2825,25 @@ export class WhileStatementContext extends antlr.ParserRuleContext { super(parent, invokingState); } public WHILE(): antlr.TerminalNode { - return this.getToken(JackParser.WHILE, 0)!; + return assertExists(this.getToken(JackParser.WHILE, 0)); } public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; + return assertExists(this.getToken(JackParser.LPAREN, 0)); } public whileExpression(): WhileExpressionContext { - return this.getRuleContext(0, WhileExpressionContext)!; + return assertExists(this.getRuleContext(0, WhileExpressionContext)); } public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; + return assertExists(this.getToken(JackParser.RPAREN, 0)); } public LBRACE(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACE, 0)!; + return assertExists(this.getToken(JackParser.LBRACE, 0)); } public statements(): StatementsContext { - return this.getRuleContext(0, StatementsContext)!; + return assertExists(this.getRuleContext(0, StatementsContext)); } public rBrace(): RBraceContext { - return this.getRuleContext(0, RBraceContext)!; + return assertExists(this.getRuleContext(0, RBraceContext)); } public override get ruleIndex(): number { return JackParser.RULE_whileStatement; @@ -2872,7 +2868,7 @@ export class WhileExpressionContext extends antlr.ParserRuleContext { super(parent, invokingState); } public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; + return assertExists(this.getRuleContext(0, ExpressionContext)); } public override get ruleIndex(): number { return JackParser.RULE_whileExpression; @@ -2897,13 +2893,13 @@ export class DoStatementContext extends antlr.ParserRuleContext { super(parent, invokingState); } public DO(): antlr.TerminalNode { - return this.getToken(JackParser.DO, 0)!; + return assertExists(this.getToken(JackParser.DO, 0)); } public subroutineCall(): SubroutineCallContext { - return this.getRuleContext(0, SubroutineCallContext)!; + return assertExists(this.getRuleContext(0, SubroutineCallContext)); } public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; + return assertExists(this.getToken(JackParser.SEMICOLON, 0)); } public override get ruleIndex(): number { return JackParser.RULE_doStatement; @@ -2928,16 +2924,16 @@ export class SubroutineCallContext extends antlr.ParserRuleContext { super(parent, invokingState); } public subroutineId(): SubroutineIdContext { - return this.getRuleContext(0, SubroutineIdContext)!; + return assertExists(this.getRuleContext(0, SubroutineIdContext)); } public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; + return assertExists(this.getToken(JackParser.LPAREN, 0)); } public expressionList(): ExpressionListContext { - return this.getRuleContext(0, ExpressionListContext)!; + return assertExists(this.getRuleContext(0, ExpressionListContext)); } public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; + return assertExists(this.getToken(JackParser.RPAREN, 0)); } public override get ruleIndex(): number { return JackParser.RULE_subroutineCall; @@ -2962,7 +2958,7 @@ export class SubroutineIdContext extends antlr.ParserRuleContext { super(parent, invokingState); } public subroutineName(): SubroutineNameContext { - return this.getRuleContext(0, SubroutineNameContext)!; + return assertExists(this.getRuleContext(0, SubroutineNameContext)); } public DOT(): antlr.TerminalNode | null { return this.getToken(JackParser.DOT, 0); @@ -2996,10 +2992,10 @@ export class ReturnStatementContext extends antlr.ParserRuleContext { super(parent, invokingState); } public RETURN(): antlr.TerminalNode { - return this.getToken(JackParser.RETURN, 0)!; + return assertExists(this.getToken(JackParser.RETURN, 0)); } public SEMICOLON(): antlr.TerminalNode { - return this.getToken(JackParser.SEMICOLON, 0)!; + return assertExists(this.getToken(JackParser.SEMICOLON, 0)); } public expression(): ExpressionContext | null { return this.getRuleContext(0, ExpressionContext); @@ -3160,7 +3156,7 @@ export class VarNameContext extends antlr.ParserRuleContext { super(parent, invokingState); } public IDENTIFIER(): antlr.TerminalNode { - return this.getToken(JackParser.IDENTIFIER, 0)!; + return assertExists(this.getToken(JackParser.IDENTIFIER, 0)); } public override get ruleIndex(): number { return JackParser.RULE_varName; @@ -3185,16 +3181,16 @@ export class ArrayAccessContext extends antlr.ParserRuleContext { super(parent, invokingState); } public varName(): VarNameContext { - return this.getRuleContext(0, VarNameContext)!; + return assertExists(this.getRuleContext(0, VarNameContext)); } public LBRACKET(): antlr.TerminalNode { - return this.getToken(JackParser.LBRACKET, 0)!; + return assertExists(this.getToken(JackParser.LBRACKET, 0)); } public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; + return assertExists(this.getRuleContext(0, ExpressionContext)); } public RBRACKET(): antlr.TerminalNode { - return this.getToken(JackParser.RBRACKET, 0)!; + return assertExists(this.getToken(JackParser.RBRACKET, 0)); } public override get ruleIndex(): number { return JackParser.RULE_arrayAccess; @@ -3219,10 +3215,10 @@ export class UnaryOperationContext extends antlr.ParserRuleContext { super(parent, invokingState); } public unaryOperator(): UnaryOperatorContext { - return this.getRuleContext(0, UnaryOperatorContext)!; + return assertExists(this.getRuleContext(0, UnaryOperatorContext)); } public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; + return assertExists(this.getRuleContext(0, ExpressionContext)); } public override get ruleIndex(): number { return JackParser.RULE_unaryOperation; @@ -3247,13 +3243,13 @@ export class GroupedExpressionContext extends antlr.ParserRuleContext { super(parent, invokingState); } public LPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.LPAREN, 0)!; + return assertExists(this.getToken(JackParser.LPAREN, 0)); } public expression(): ExpressionContext { - return this.getRuleContext(0, ExpressionContext)!; + return assertExists(this.getRuleContext(0, ExpressionContext)); } public RPAREN(): antlr.TerminalNode { - return this.getToken(JackParser.RPAREN, 0)!; + return assertExists(this.getToken(JackParser.RPAREN, 0)); } public override get ruleIndex(): number { return JackParser.RULE_groupedExpression; diff --git a/simulator/src/jack/generated/JackParserListener.ts b/simulator/src/jack/generated/JackParserListener.ts index cebcc430..b6875bd3 100644 --- a/simulator/src/jack/generated/JackParserListener.ts +++ b/simulator/src/jack/generated/JackParserListener.ts @@ -2,56 +2,56 @@ import { ErrorNode, - ParseTreeListener, ParserRuleContext, + ParseTreeListener, TerminalNode, } from "antlr4ng"; -import { SubroutineScope, LocalSymbolTable } from "../symbol.js"; - -import { ProgramContext } from "./JackParser.js"; -import { ClassDeclarationContext } from "./JackParser.js"; -import { ClassNameContext } from "./JackParser.js"; -import { ClassVarDecContext } from "./JackParser.js"; -import { FieldListContext } from "./JackParser.js"; -import { FieldNameContext } from "./JackParser.js"; -import { SubroutineDeclarationContext } from "./JackParser.js"; -import { SubroutineTypeContext } from "./JackParser.js"; -import { SubroutineDecWithoutTypeContext } from "./JackParser.js"; -import { SubroutineNameContext } from "./JackParser.js"; -import { SubroutineReturnTypeContext } from "./JackParser.js"; -import { VarTypeContext } from "./JackParser.js"; -import { ParameterListContext } from "./JackParser.js"; -import { ParameterContext } from "./JackParser.js"; -import { ParameterNameContext } from "./JackParser.js"; -import { SubroutineBodyContext } from "./JackParser.js"; -import { RBraceContext } from "./JackParser.js"; -import { VarDeclarationContext } from "./JackParser.js"; -import { VarNameInDeclarationContext } from "./JackParser.js"; -import { StatementsContext } from "./JackParser.js"; -import { StatementContext } from "./JackParser.js"; -import { LetStatementContext } from "./JackParser.js"; -import { EqualsContext } from "./JackParser.js"; -import { IfElseStatementContext } from "./JackParser.js"; -import { IfStatementContext } from "./JackParser.js"; -import { IfExpressionContext } from "./JackParser.js"; -import { ElseStatementContext } from "./JackParser.js"; -import { WhileStatementContext } from "./JackParser.js"; -import { WhileExpressionContext } from "./JackParser.js"; -import { DoStatementContext } from "./JackParser.js"; -import { SubroutineCallContext } from "./JackParser.js"; -import { SubroutineIdContext } from "./JackParser.js"; -import { ReturnStatementContext } from "./JackParser.js"; -import { ExpressionListContext } from "./JackParser.js"; -import { ExpressionContext } from "./JackParser.js"; -import { ConstantContext } from "./JackParser.js"; -import { VarNameContext } from "./JackParser.js"; -import { ArrayAccessContext } from "./JackParser.js"; -import { UnaryOperationContext } from "./JackParser.js"; -import { GroupedExpressionContext } from "./JackParser.js"; -import { BooleanLiteralContext } from "./JackParser.js"; -import { UnaryOperatorContext } from "./JackParser.js"; -import { BinaryOperatorContext } from "./JackParser.js"; +import { + ArrayAccessContext, + BinaryOperatorContext, + BooleanLiteralContext, + ClassDeclarationContext, + ClassNameContext, + ClassVarDecContext, + ConstantContext, + DoStatementContext, + ElseStatementContext, + EqualsContext, + ExpressionContext, + ExpressionListContext, + FieldListContext, + FieldNameContext, + GroupedExpressionContext, + IfElseStatementContext, + IfExpressionContext, + IfStatementContext, + LetStatementContext, + ParameterContext, + ParameterListContext, + ParameterNameContext, + ProgramContext, + RBraceContext, + ReturnStatementContext, + StatementContext, + StatementsContext, + SubroutineBodyContext, + SubroutineCallContext, + SubroutineDecWithoutTypeContext, + SubroutineDeclarationContext, + SubroutineIdContext, + SubroutineNameContext, + SubroutineReturnTypeContext, + SubroutineTypeContext, + UnaryOperationContext, + UnaryOperatorContext, + VarDeclarationContext, + VarNameContext, + VarNameInDeclarationContext, + VarTypeContext, + WhileExpressionContext, + WhileStatementContext, +} from "./JackParser.js"; /** * This interface defines a complete listener for a parse tree produced by @@ -491,8 +491,16 @@ export class JackParserListener implements ParseTreeListener { */ exitBinaryOperator?: (ctx: BinaryOperatorContext) => void; - visitTerminal(node: TerminalNode): void {} - visitErrorNode(node: ErrorNode): void {} - enterEveryRule(node: ParserRuleContext): void {} - exitEveryRule(node: ParserRuleContext): void {} + visitTerminal(node: TerminalNode): void { + return; + } + visitErrorNode(node: ErrorNode): void { + return; + } + enterEveryRule(node: ParserRuleContext): void { + return; + } + exitEveryRule(node: ParserRuleContext): void { + return; + } } diff --git a/simulator/src/jack/listener/common.ts b/simulator/src/jack/listener/common.ts index b29b6550..681c1ff7 100644 --- a/simulator/src/jack/listener/common.ts +++ b/simulator/src/jack/listener/common.ts @@ -43,13 +43,3 @@ export function getCallType( } } } - -export function assertExists( - val: T | undefined | null, - message?: string, -): T { - if (val == null) { - throw new Error(message ?? "Cannot be null or undefined"); - } - return val; -} diff --git a/simulator/src/jack/listener/error.listener.ts b/simulator/src/jack/listener/error.listener.ts index ff03f587..dc06c87d 100644 --- a/simulator/src/jack/listener/error.listener.ts +++ b/simulator/src/jack/listener/error.listener.ts @@ -12,7 +12,7 @@ import { Token, } from "antlr4ng"; import { JackCompilerError, LexerOrParserError } from "../error.js"; -import { assertExists } from "./common.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; export class CustomErrorListener implements ANTLRErrorListener { public errors: JackCompilerError[] = []; @@ -65,7 +65,9 @@ export class CustomErrorListener implements ANTLRErrorListener { _exact: boolean, _ambigAlts: BitSet | undefined, _configs: ATNConfigSet, - ): void {} + ): void { + return; + } reportAttemptingFullContext( _recognizer: Parser, _dfa: DFA, @@ -73,7 +75,9 @@ export class CustomErrorListener implements ANTLRErrorListener { _stopIndex: number, _conflictingAlts: BitSet | undefined, _configs: ATNConfigSet, - ): void {} + ): void { + return; + } reportContextSensitivity( _recognizer: Parser, _dfa: DFA, @@ -81,5 +85,7 @@ export class CustomErrorListener implements ANTLRErrorListener { _stopIndex: number, _prediction: number, _configs: ATNConfigSet, - ): void {} + ): void { + return; + } } diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 72b59039..b03ee6bc 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -51,7 +51,8 @@ import { ScopeType, SubroutineType, } from "../symbol.js"; -import { assertExists, CallType, getCallType } from "./common.js"; +import { CallType, getCallType } from "./common.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; /** * Validates Jack file */ diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index e4d0edf4..947313b3 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -20,7 +20,8 @@ import { scopeTypeToString, VariableSymbol, } from "../symbol.js"; -import { assertExists, CallType, getCallType } from "./common.js"; +import { CallType, getCallType } from "./common.js"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; const binaryOperationToVmCmd: Record = { "+": "add", From a68a248757fdc4756c0a509adb3e5a0b99f2aa35 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:12:28 +0200 Subject: [PATCH 83/87] WIP --- simulator/src/jack/error.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulator/src/jack/error.ts b/simulator/src/jack/error.ts index 983720db..8d9e28e0 100644 --- a/simulator/src/jack/error.ts +++ b/simulator/src/jack/error.ts @@ -1,4 +1,4 @@ -import { assertExists } from "@davidsouther/jiffies/lib/esm/assert"; +import { assertExists } from "@davidsouther/jiffies/lib/esm/assert.js"; import { ParserRuleContext, TerminalNode } from "antlr4ng"; export interface Span { From a2620ec2d81670bf0ff52b6b89dcdcf7a522c3d7 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:26:02 +0200 Subject: [PATCH 84/87] WIP --- simulator/src/jack/anltr.compiler.ts | 26 ++--- simulator/src/jack/listener/common.ts | 14 +-- .../src/jack/listener/validator.listener.ts | 102 +++++++++--------- .../src/jack/listener/vm.writer.listener.ts | 16 +-- simulator/src/jack/symbol.ts | 30 +++--- 5 files changed, 99 insertions(+), 89 deletions(-) diff --git a/simulator/src/jack/anltr.compiler.ts b/simulator/src/jack/anltr.compiler.ts index e79554cf..a98ac5ff 100644 --- a/simulator/src/jack/anltr.compiler.ts +++ b/simulator/src/jack/anltr.compiler.ts @@ -9,13 +9,13 @@ import { CharStream, CommonTokenStream, ParseTreeWalker } from "antlr4ng"; import { CompilationError } from "../languages/base.js"; export function compile( - files: Record, + files: Record ): Record { return _doWithTryCatch(files, Command.Compile); } export function validate( - files: Record, + files: Record ): Record { return _doWithTryCatch(files, Command.Validate); } @@ -35,14 +35,16 @@ function _doWithTryCatch(files: Record, cmd: Command) { return result; } } -enum Command { - Compile, - Validate, -} + +export const Command = { + Compile: 1, + Validate: 2, +} as const; +export type Command = (typeof Command)[keyof typeof Command]; function _do( files: Record, - cmd: Command, + cmd: Command ): Record { if (files.type == "LexerOrParserError") { throw new Error("Expected tree but got a lexer or parser error"); @@ -107,18 +109,18 @@ export class JackCompiler { private errorListener = new CustomErrorListener(); validate( tree: ProgramContext, - filename?: string, + filename?: string ): ProgramContext | JackCompilerError[] { if ( Object.keys(this.globalSymbolTableListener.globalSymbolTable).length == 0 ) { throw new Error( - "Please populate global symbol table using parserAndBind method", + "Please populate global symbol table using parserAndBind method" ); } const validator = new ValidatorListener( this.globalSymbolTableListener.globalSymbolTable, - filename, + filename ); ParseTreeWalker.DEFAULT.walk(validator, tree); @@ -126,7 +128,7 @@ export class JackCompiler { } compile( tree: ProgramContext, - filename?: string, + filename?: string ): string | JackCompilerError[] { const treeOrErrors = this.validate(tree, filename); if (Array.isArray(treeOrErrors)) { @@ -136,7 +138,7 @@ export class JackCompiler { } const validateTree = treeOrErrors as ProgramContext; const vmWriter = new VMWriter( - this.globalSymbolTableListener.globalSymbolTable, + this.globalSymbolTableListener.globalSymbolTable ); ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); return vmWriter.result; diff --git a/simulator/src/jack/listener/common.ts b/simulator/src/jack/listener/common.ts index 681c1ff7..f26e3111 100644 --- a/simulator/src/jack/listener/common.ts +++ b/simulator/src/jack/listener/common.ts @@ -7,15 +7,17 @@ export interface CallTypeResult { symbol?: VariableSymbol; } -export enum CallType { - VarMethod = 1, - LocalMethod = 2, - ClassFunctionOrConstructor = 3, -} +export const CallType = { + VarMethod: 1, + LocalMethod: 2, + ClassFunctionOrConstructor: 3, +} as const; +export type CallType = (typeof CallType)[keyof typeof CallType]; + export function getCallType( subroutineId: SubroutineIdContext, className: string, - localSymbolTable: LocalSymbolTable, + localSymbolTable: LocalSymbolTable ): CallTypeResult { if (subroutineId.DOT() == undefined) { //local method diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index b03ee6bc..039a2bba 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -67,7 +67,7 @@ export class ValidatorListener extends JackParserListener { constructor( private globalSymbolTable: Record, private filename?: string, - public errors: JackCompilerError[] = [], + public errors: JackCompilerError[] = [] ) { super(); } @@ -87,8 +87,8 @@ export class ValidatorListener extends JackParserListener { FilenameDoesntMatchClassNameError( ruleContextToSpan(ctx.className()), this.filename, - this.className, - ), + this.className + ) ); } ctx.localSymbolTable = this.localSymbolTable; @@ -112,7 +112,7 @@ export class ValidatorListener extends JackParserListener { field.IDENTIFIER(), scope, field.getText(), - type, + type ); }); }; @@ -126,9 +126,9 @@ export class ValidatorListener extends JackParserListener { this.addError( IncorrectConstructorReturnTypeError( ruleContextToSpan( - ctx.subroutineDecWithoutType().subroutineReturnType(), - ), - ), + ctx.subroutineDecWithoutType().subroutineReturnType() + ) + ) ); } } else if (ctx.subroutineType().FUNCTION() != null) { @@ -140,7 +140,7 @@ export class ValidatorListener extends JackParserListener { } }; override enterSubroutineDecWithoutType = ( - ctx: SubroutineDecWithoutTypeContext, + ctx: SubroutineDecWithoutTypeContext ) => { const returnType = ctx.subroutineReturnType(); this.subroutineShouldReturnVoidType = returnType.VOID() != null; @@ -152,13 +152,13 @@ export class ValidatorListener extends JackParserListener { const name = ctx.parameterName().getText(); if (this.localSymbolTable.lookup(name)) { this.addError( - DuplicatedVariableError(ruleContextToSpan(ctx.parameterName()), name), + DuplicatedVariableError(ruleContextToSpan(ctx.parameterName()), name) ); } else { this.localSymbolTable.defineArgument( name, ctx.varType().getText(), - this.subroutineType == SubroutineType.Method, + this.subroutineType == SubroutineType.Method ); } }; @@ -182,7 +182,7 @@ export class ValidatorListener extends JackParserListener { nameCtx.IDENTIFIER(), ScopeType.Local, nameCtx.getText(), - type, + type ); }); }; @@ -196,8 +196,8 @@ export class ValidatorListener extends JackParserListener { this.addError( UndeclaredVariableError( terminalNodeToSpan(ctx.IDENTIFIER()), - ctx.getText(), - ), + ctx.getText() + ) ); } else if ( this.subroutineType == SubroutineType.Function && @@ -205,8 +205,8 @@ export class ValidatorListener extends JackParserListener { ) { this.addError( FieldCantBeReferencedInFunctionError( - terminalNodeToSpan(ctx.IDENTIFIER()), - ), + terminalNodeToSpan(ctx.IDENTIFIER()) + ) ); } }; @@ -215,7 +215,7 @@ export class ValidatorListener extends JackParserListener { const thisLiteral = ctx.THIS_LITERAL(); if (thisLiteral != null && this.subroutineType == SubroutineType.Function) { this.addError( - ThisCantBeReferencedInFunctionError(terminalNodeToSpan(thisLiteral)), + ThisCantBeReferencedInFunctionError(terminalNodeToSpan(thisLiteral)) ); } }; @@ -293,8 +293,8 @@ export class ValidatorListener extends JackParserListener { terminalNodeToSpan(intLiteral), parseInt(value), intRange.min, - intRange.max, - ), + intRange.max + ) ); } } else if (constCtx?.STRING_LITERAL() != null) { @@ -309,8 +309,8 @@ export class ValidatorListener extends JackParserListener { WrongLiteralTypeError( ruleContextToSpan(constantCtx ?? ctx), symbol.type, - actualType, - ), + actualType + ) ); } } @@ -325,18 +325,18 @@ export class ValidatorListener extends JackParserListener { unaryOp.expression()?.constant()?.INTEGER_LITERAL() !== null ) { const value = parseInt( - unaryOp.expression()?.constant()?.INTEGER_LITERAL()?.getText() ?? "0", + unaryOp.expression()?.constant()?.INTEGER_LITERAL()?.getText() ?? "0" ); if (-value < intRange.min) { this.addError( IntLiteralIsOutOfRangeError( terminalNodeToSpan( - assertExists(unaryOp.expression()?.constant()?.INTEGER_LITERAL()), + assertExists(unaryOp.expression()?.constant()?.INTEGER_LITERAL()) ), value, intRange.min, - intRange.max, - ), + intRange.max + ) ); } } @@ -348,7 +348,7 @@ export class ValidatorListener extends JackParserListener { const { callType, subroutineIdText } = getCallType( subroutineId, this.className, - this.localSymbolTable, + this.localSymbolTable ); const symbol = this.globalSymbolTable[subroutineIdText]; @@ -357,8 +357,8 @@ export class ValidatorListener extends JackParserListener { UnknownSubroutineCallError( ruleContextToSpan(subroutineId.subroutineName()), subroutineId.subroutineName().getText(), - subroutineId.className()?.getText(), - ), + subroutineId.className()?.getText() + ) ); } else { //method called as a function @@ -369,8 +369,8 @@ export class ValidatorListener extends JackParserListener { this.addError( MethodCalledAsFunctionError( ruleContextToSpan(subroutineId.subroutineName()), - subroutineId.subroutineName().getText(), - ), + subroutineId.subroutineName().getText() + ) ); } // function called as a method @@ -381,8 +381,8 @@ export class ValidatorListener extends JackParserListener { this.addError( FunctionCalledAsMethodError( ruleContextToSpan(subroutineId.subroutineName()), - subroutineId.subroutineName().getText(), - ), + subroutineId.subroutineName().getText() + ) ); } else { //check parameter count @@ -399,8 +399,8 @@ export class ValidatorListener extends JackParserListener { ruleContextToSpan(ctx.expressionList()), subroutineId.getText(), assertExists(symbol.subroutineInfo).paramsCount, - l, - ), + l + ) ); } else { const start = ctx.LPAREN().symbol; @@ -411,8 +411,8 @@ export class ValidatorListener extends JackParserListener { { line: start.line, start: start.start, end: stop.stop + 1 }, subroutineId.getText(), symbol.subroutineInfo?.paramsCount ?? 0, - l, - ), + l + ) ); } } @@ -446,8 +446,8 @@ export class ValidatorListener extends JackParserListener { //TODO: add exact place that doesn't return SubroutineNotAllPathsReturnError( ruleContextToSpan(ctx.subroutineType()), - this.subroutineName, - ), + this.subroutineName + ) ); } this.subroutineType = undefined; @@ -466,11 +466,11 @@ export class ValidatorListener extends JackParserListener { identifierCtx: TerminalNode, scope: ScopeType, name: string, - type: string, + type: string ) { if (this.localSymbolTable.lookup(name)) { this.addError( - DuplicatedVariableError(terminalNodeToSpan(identifierCtx), name), + DuplicatedVariableError(terminalNodeToSpan(identifierCtx), name) ); } else { this.localSymbolTable.define(scope, name, type); @@ -486,7 +486,7 @@ class BinaryTreeNode { constructor( public parent?: BinaryTreeNode, public left?: BinaryTreeNode, - public right?: BinaryTreeNode, + public right?: BinaryTreeNode ) {} public get returns(): boolean { @@ -512,7 +512,7 @@ class BinaryTreeNode { console.log(this.printBT()); } - printBT(prefix = "", side: Side = Side.LEFT) { + printBT(prefix = "", side: Side = Side.Left) { let res = ""; if (this._returns) { res += this.#pad(side); @@ -524,14 +524,14 @@ class BinaryTreeNode { res += " " + false + "\n"; } else { res += this.left?.printBT( - side == Side.LEFT ? "| " : " ", - Side.LEFT, + side == Side.Left ? "| " : " ", + Side.Left ); if (this.right) { res += prefix; res += this.right?.printBT( - side == Side.LEFT ? "|\t" : "\t", - Side.RIGHT, + side == Side.Left ? "|\t" : "\t", + Side.Right ); } else { res += "\n"; @@ -541,11 +541,13 @@ class BinaryTreeNode { return res; } #pad(side: Side): string { - return side == Side.LEFT ? "├──" : "└──"; + return side == Side.Left ? "├──" : "└──"; } } -enum Side { - LEFT, - RIGHT, -} + +const Side = { + Left: 1, + Right: 2, +} as const; +export type Side = (typeof Side)[keyof typeof Side]; const literalTypes = [...builtInTypes, "String"]; diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index 947313b3..2b26e2ca 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -178,7 +178,7 @@ export class VMWriter extends JackParserListener { if (binaryOperationToVmCmd[binaryOp] == undefined) { throw new Error(`Unknown binary operator ${binaryOp}`); } - this.result += "\t" + binaryOperationToVmCmd[binaryOp] + "\n"; + this.result += " " + binaryOperationToVmCmd[binaryOp] + "\n"; } else if (ctx.unaryOperation() != null) { const unaryOp = assertExists( ctx.unaryOperation()?.unaryOperator(), @@ -187,7 +187,7 @@ export class VMWriter extends JackParserListener { if (unaryOperationToVmCmd[unaryOp] == null) { throw new Error(`Unknown unary operator ${unaryOp}`); } - this.result += "\t" + unaryOperationToVmCmd[unaryOp] + "\n"; + this.result += " " + unaryOperationToVmCmd[unaryOp] + "\n"; } }; pushSymbolOntoStack(symbol: VariableSymbol) { @@ -224,7 +224,7 @@ export class VMWriter extends JackParserListener { parent.endLabel = this.createLabel(); this.result += ` goto ${parent.endLabel}\n`; } - this.result += ` label ${ctx.endLabel}\n`; + this.result += `label ${ctx.endLabel} \n`; }; override exitIfExpression = (ctx: IfExpressionContext) => { const parent = ctx.parent as IfStatementContext; @@ -232,14 +232,14 @@ export class VMWriter extends JackParserListener { }; override exitIfElseStatement = (ctx: IfElseStatementContext) => { if (ctx.endLabel) { - this.result += ` label ${ctx.endLabel} \n`; + this.result += `label ${ctx.endLabel}\n`; } }; //while override enterWhileStatement = (ctx: WhileStatementContext) => { ctx.startLabel = this.createLabel(); ctx.endLabel = this.createLabel(); - this.result += ` label ${ctx.startLabel} \n`; + this.result += `label ${ctx.startLabel}\n`; }; override exitWhileExpression = (ctx: WhileExpressionContext) => { const parent = ctx.parent as WhileStatementContext; @@ -248,7 +248,7 @@ export class VMWriter extends JackParserListener { override exitWhileStatement = (ctx: WhileStatementContext) => { this.result += ` goto ${ctx.startLabel}\n`; - this.result += ` label ${ctx.endLabel}\n`; + this.result += `label ${ctx.endLabel}\n`; }; override enterSubroutineCall = (ctx: SubroutineCallContext) => { @@ -297,9 +297,9 @@ export class VMWriter extends JackParserListener { this.result += " return\n"; }; //Utils - ifNotGoto(endLabel: string) { + ifNotGoto(endLabel: string) { this.result += " not\n"; - this.result += ` if-goto ${endLabel} \n`; + this.result += ` if-goto ${endLabel}\n`; } getLabel(ind: number) { return `${this.className}_${ind} `; diff --git a/simulator/src/jack/symbol.ts b/simulator/src/jack/symbol.ts index 6bacd114..423583b9 100644 --- a/simulator/src/jack/symbol.ts +++ b/simulator/src/jack/symbol.ts @@ -1,11 +1,13 @@ /** * Generic symbol. Can be used for both class and function symbols */ -export enum SubroutineType { - Constructor, - Function, - Method, -} +export const SubroutineType = { + Constructor: 1, + Function: 2, + Method: 3, +} as const; +export type SubroutineType = + (typeof SubroutineType)[keyof typeof SubroutineType]; export interface SubroutineInfo { paramsCount: number; type: SubroutineType; @@ -22,7 +24,7 @@ export interface GenericSymbol { export function createSubroutineSymbol( paramsCount: number, type: SubroutineType, - localVarsCount?: number, + localVarsCount?: number ): GenericSymbol { const s = { paramsCount, type } as SubroutineInfo; if (localVarsCount != undefined) { @@ -32,12 +34,14 @@ export function createSubroutineSymbol( } type VariableType = string; -export enum ScopeType { - Static, - This, - Argument, - Local, -} + +export const ScopeType = { + Static: 1, + This: 2, + Argument: 3, + Local: 4, +}; +export type ScopeType = (typeof ScopeType)[keyof typeof ScopeType]; const scopeTypeToStringMap: Record = { [ScopeType.Static]: "static", @@ -102,7 +106,7 @@ export class LocalSymbolTable { define(scope: ScopeType, varName: string, type: VariableType) { if (scope == ScopeType.Argument) { throw new Error( - "Please use defineArgument method to define function arguments", + "Please use defineArgument method to define function arguments" ); } this.scopes[scope].push({ From d41d95ebe00ea3eba2f544fe4fa722b58fefab79 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 22 Oct 2024 17:27:40 +0200 Subject: [PATCH 85/87] WIP --- simulator/src/jack/anltr.compiler.ts | 16 ++-- simulator/src/jack/listener/common.ts | 2 +- .../src/jack/listener/validator.listener.ts | 84 +++++++++---------- .../src/jack/listener/vm.writer.listener.ts | 2 +- simulator/src/jack/symbol.ts | 4 +- 5 files changed, 54 insertions(+), 54 deletions(-) diff --git a/simulator/src/jack/anltr.compiler.ts b/simulator/src/jack/anltr.compiler.ts index a98ac5ff..da20d295 100644 --- a/simulator/src/jack/anltr.compiler.ts +++ b/simulator/src/jack/anltr.compiler.ts @@ -9,13 +9,13 @@ import { CharStream, CommonTokenStream, ParseTreeWalker } from "antlr4ng"; import { CompilationError } from "../languages/base.js"; export function compile( - files: Record + files: Record, ): Record { return _doWithTryCatch(files, Command.Compile); } export function validate( - files: Record + files: Record, ): Record { return _doWithTryCatch(files, Command.Validate); } @@ -44,7 +44,7 @@ export type Command = (typeof Command)[keyof typeof Command]; function _do( files: Record, - cmd: Command + cmd: Command, ): Record { if (files.type == "LexerOrParserError") { throw new Error("Expected tree but got a lexer or parser error"); @@ -109,18 +109,18 @@ export class JackCompiler { private errorListener = new CustomErrorListener(); validate( tree: ProgramContext, - filename?: string + filename?: string, ): ProgramContext | JackCompilerError[] { if ( Object.keys(this.globalSymbolTableListener.globalSymbolTable).length == 0 ) { throw new Error( - "Please populate global symbol table using parserAndBind method" + "Please populate global symbol table using parserAndBind method", ); } const validator = new ValidatorListener( this.globalSymbolTableListener.globalSymbolTable, - filename + filename, ); ParseTreeWalker.DEFAULT.walk(validator, tree); @@ -128,7 +128,7 @@ export class JackCompiler { } compile( tree: ProgramContext, - filename?: string + filename?: string, ): string | JackCompilerError[] { const treeOrErrors = this.validate(tree, filename); if (Array.isArray(treeOrErrors)) { @@ -138,7 +138,7 @@ export class JackCompiler { } const validateTree = treeOrErrors as ProgramContext; const vmWriter = new VMWriter( - this.globalSymbolTableListener.globalSymbolTable + this.globalSymbolTableListener.globalSymbolTable, ); ParseTreeWalker.DEFAULT.walk(vmWriter, validateTree); return vmWriter.result; diff --git a/simulator/src/jack/listener/common.ts b/simulator/src/jack/listener/common.ts index f26e3111..8c7c1b16 100644 --- a/simulator/src/jack/listener/common.ts +++ b/simulator/src/jack/listener/common.ts @@ -17,7 +17,7 @@ export type CallType = (typeof CallType)[keyof typeof CallType]; export function getCallType( subroutineId: SubroutineIdContext, className: string, - localSymbolTable: LocalSymbolTable + localSymbolTable: LocalSymbolTable, ): CallTypeResult { if (subroutineId.DOT() == undefined) { //local method diff --git a/simulator/src/jack/listener/validator.listener.ts b/simulator/src/jack/listener/validator.listener.ts index 039a2bba..86938149 100644 --- a/simulator/src/jack/listener/validator.listener.ts +++ b/simulator/src/jack/listener/validator.listener.ts @@ -67,7 +67,7 @@ export class ValidatorListener extends JackParserListener { constructor( private globalSymbolTable: Record, private filename?: string, - public errors: JackCompilerError[] = [] + public errors: JackCompilerError[] = [], ) { super(); } @@ -87,8 +87,8 @@ export class ValidatorListener extends JackParserListener { FilenameDoesntMatchClassNameError( ruleContextToSpan(ctx.className()), this.filename, - this.className - ) + this.className, + ), ); } ctx.localSymbolTable = this.localSymbolTable; @@ -112,7 +112,7 @@ export class ValidatorListener extends JackParserListener { field.IDENTIFIER(), scope, field.getText(), - type + type, ); }); }; @@ -126,9 +126,9 @@ export class ValidatorListener extends JackParserListener { this.addError( IncorrectConstructorReturnTypeError( ruleContextToSpan( - ctx.subroutineDecWithoutType().subroutineReturnType() - ) - ) + ctx.subroutineDecWithoutType().subroutineReturnType(), + ), + ), ); } } else if (ctx.subroutineType().FUNCTION() != null) { @@ -140,7 +140,7 @@ export class ValidatorListener extends JackParserListener { } }; override enterSubroutineDecWithoutType = ( - ctx: SubroutineDecWithoutTypeContext + ctx: SubroutineDecWithoutTypeContext, ) => { const returnType = ctx.subroutineReturnType(); this.subroutineShouldReturnVoidType = returnType.VOID() != null; @@ -152,13 +152,13 @@ export class ValidatorListener extends JackParserListener { const name = ctx.parameterName().getText(); if (this.localSymbolTable.lookup(name)) { this.addError( - DuplicatedVariableError(ruleContextToSpan(ctx.parameterName()), name) + DuplicatedVariableError(ruleContextToSpan(ctx.parameterName()), name), ); } else { this.localSymbolTable.defineArgument( name, ctx.varType().getText(), - this.subroutineType == SubroutineType.Method + this.subroutineType == SubroutineType.Method, ); } }; @@ -182,7 +182,7 @@ export class ValidatorListener extends JackParserListener { nameCtx.IDENTIFIER(), ScopeType.Local, nameCtx.getText(), - type + type, ); }); }; @@ -196,8 +196,8 @@ export class ValidatorListener extends JackParserListener { this.addError( UndeclaredVariableError( terminalNodeToSpan(ctx.IDENTIFIER()), - ctx.getText() - ) + ctx.getText(), + ), ); } else if ( this.subroutineType == SubroutineType.Function && @@ -205,8 +205,8 @@ export class ValidatorListener extends JackParserListener { ) { this.addError( FieldCantBeReferencedInFunctionError( - terminalNodeToSpan(ctx.IDENTIFIER()) - ) + terminalNodeToSpan(ctx.IDENTIFIER()), + ), ); } }; @@ -215,7 +215,7 @@ export class ValidatorListener extends JackParserListener { const thisLiteral = ctx.THIS_LITERAL(); if (thisLiteral != null && this.subroutineType == SubroutineType.Function) { this.addError( - ThisCantBeReferencedInFunctionError(terminalNodeToSpan(thisLiteral)) + ThisCantBeReferencedInFunctionError(terminalNodeToSpan(thisLiteral)), ); } }; @@ -293,8 +293,8 @@ export class ValidatorListener extends JackParserListener { terminalNodeToSpan(intLiteral), parseInt(value), intRange.min, - intRange.max - ) + intRange.max, + ), ); } } else if (constCtx?.STRING_LITERAL() != null) { @@ -309,8 +309,8 @@ export class ValidatorListener extends JackParserListener { WrongLiteralTypeError( ruleContextToSpan(constantCtx ?? ctx), symbol.type, - actualType - ) + actualType, + ), ); } } @@ -325,18 +325,18 @@ export class ValidatorListener extends JackParserListener { unaryOp.expression()?.constant()?.INTEGER_LITERAL() !== null ) { const value = parseInt( - unaryOp.expression()?.constant()?.INTEGER_LITERAL()?.getText() ?? "0" + unaryOp.expression()?.constant()?.INTEGER_LITERAL()?.getText() ?? "0", ); if (-value < intRange.min) { this.addError( IntLiteralIsOutOfRangeError( terminalNodeToSpan( - assertExists(unaryOp.expression()?.constant()?.INTEGER_LITERAL()) + assertExists(unaryOp.expression()?.constant()?.INTEGER_LITERAL()), ), value, intRange.min, - intRange.max - ) + intRange.max, + ), ); } } @@ -348,7 +348,7 @@ export class ValidatorListener extends JackParserListener { const { callType, subroutineIdText } = getCallType( subroutineId, this.className, - this.localSymbolTable + this.localSymbolTable, ); const symbol = this.globalSymbolTable[subroutineIdText]; @@ -357,8 +357,8 @@ export class ValidatorListener extends JackParserListener { UnknownSubroutineCallError( ruleContextToSpan(subroutineId.subroutineName()), subroutineId.subroutineName().getText(), - subroutineId.className()?.getText() - ) + subroutineId.className()?.getText(), + ), ); } else { //method called as a function @@ -369,8 +369,8 @@ export class ValidatorListener extends JackParserListener { this.addError( MethodCalledAsFunctionError( ruleContextToSpan(subroutineId.subroutineName()), - subroutineId.subroutineName().getText() - ) + subroutineId.subroutineName().getText(), + ), ); } // function called as a method @@ -381,8 +381,8 @@ export class ValidatorListener extends JackParserListener { this.addError( FunctionCalledAsMethodError( ruleContextToSpan(subroutineId.subroutineName()), - subroutineId.subroutineName().getText() - ) + subroutineId.subroutineName().getText(), + ), ); } else { //check parameter count @@ -399,8 +399,8 @@ export class ValidatorListener extends JackParserListener { ruleContextToSpan(ctx.expressionList()), subroutineId.getText(), assertExists(symbol.subroutineInfo).paramsCount, - l - ) + l, + ), ); } else { const start = ctx.LPAREN().symbol; @@ -411,8 +411,8 @@ export class ValidatorListener extends JackParserListener { { line: start.line, start: start.start, end: stop.stop + 1 }, subroutineId.getText(), symbol.subroutineInfo?.paramsCount ?? 0, - l - ) + l, + ), ); } } @@ -446,8 +446,8 @@ export class ValidatorListener extends JackParserListener { //TODO: add exact place that doesn't return SubroutineNotAllPathsReturnError( ruleContextToSpan(ctx.subroutineType()), - this.subroutineName - ) + this.subroutineName, + ), ); } this.subroutineType = undefined; @@ -466,11 +466,11 @@ export class ValidatorListener extends JackParserListener { identifierCtx: TerminalNode, scope: ScopeType, name: string, - type: string + type: string, ) { if (this.localSymbolTable.lookup(name)) { this.addError( - DuplicatedVariableError(terminalNodeToSpan(identifierCtx), name) + DuplicatedVariableError(terminalNodeToSpan(identifierCtx), name), ); } else { this.localSymbolTable.define(scope, name, type); @@ -486,7 +486,7 @@ class BinaryTreeNode { constructor( public parent?: BinaryTreeNode, public left?: BinaryTreeNode, - public right?: BinaryTreeNode + public right?: BinaryTreeNode, ) {} public get returns(): boolean { @@ -525,13 +525,13 @@ class BinaryTreeNode { } else { res += this.left?.printBT( side == Side.Left ? "| " : " ", - Side.Left + Side.Left, ); if (this.right) { res += prefix; res += this.right?.printBT( side == Side.Left ? "|\t" : "\t", - Side.Right + Side.Right, ); } else { res += "\n"; diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index 2b26e2ca..3d9ada47 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -297,7 +297,7 @@ export class VMWriter extends JackParserListener { this.result += " return\n"; }; //Utils - ifNotGoto(endLabel: string) { + ifNotGoto(endLabel: string) { this.result += " not\n"; this.result += ` if-goto ${endLabel}\n`; } diff --git a/simulator/src/jack/symbol.ts b/simulator/src/jack/symbol.ts index 423583b9..e1050d25 100644 --- a/simulator/src/jack/symbol.ts +++ b/simulator/src/jack/symbol.ts @@ -24,7 +24,7 @@ export interface GenericSymbol { export function createSubroutineSymbol( paramsCount: number, type: SubroutineType, - localVarsCount?: number + localVarsCount?: number, ): GenericSymbol { const s = { paramsCount, type } as SubroutineInfo; if (localVarsCount != undefined) { @@ -106,7 +106,7 @@ export class LocalSymbolTable { define(scope: ScopeType, varName: string, type: VariableType) { if (scope == ScopeType.Argument) { throw new Error( - "Please use defineArgument method to define function arguments" + "Please use defineArgument method to define function arguments", ); } this.scopes[scope].push({ From 078f95ba357f65285a59ce8053d2f167fb5a5825 Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:40:32 +0200 Subject: [PATCH 86/87] Fix bug with never ending stack increase --- simulator/src/jack/antlr.compiler.test.ts | 2 ++ .../src/jack/listener/vm.writer.listener.ts | 5 ++++ .../src/jack/resources/test/Average/Main.vm | 2 ++ .../jack/resources/test/ComplexArrays/Main.vm | 16 ++++++++++++ .../jack/resources/test/ConvertToBin/Main.vm | 5 ++++ .../jack/resources/test/Fraction/Fraction.vm | 5 ++++ .../src/jack/resources/test/Fraction/Main.vm | 1 + .../jack/resources/test/HelloWorld/Main.vm | 2 ++ .../src/jack/resources/test/List/List.vm | 4 +++ .../src/jack/resources/test/List/Main.vm | 2 ++ .../src/jack/resources/test/Pong/Ball.vm | 10 +++++++ simulator/src/jack/resources/test/Pong/Bat.vm | 17 ++++++++++++ .../src/jack/resources/test/Pong/Main.vm | 3 +++ .../src/jack/resources/test/Pong/PongGame.vm | 26 +++++++++++++++++-- .../src/jack/resources/test/Square/Main.vm | 2 ++ .../src/jack/resources/test/Square/Square.vm | 26 +++++++++++++++++++ .../jack/resources/test/Square/SquareGame.vm | 11 ++++++++ 17 files changed, 137 insertions(+), 2 deletions(-) diff --git a/simulator/src/jack/antlr.compiler.test.ts b/simulator/src/jack/antlr.compiler.test.ts index 6e143621..d9819ce4 100644 --- a/simulator/src/jack/antlr.compiler.test.ts +++ b/simulator/src/jack/antlr.compiler.test.ts @@ -641,6 +641,7 @@ describe("Jack compiler", () => { return function A.a 0 call A.b 0 + pop temp 0 push constant 0 return `; @@ -679,6 +680,7 @@ describe("Jack compiler", () => { pop local 0 push local 0 call A.b 1 + pop temp 0 push constant 0 return `; diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index 3d9ada47..aa4edcaf 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -3,6 +3,7 @@ import { ArrayAccessContext, ClassDeclarationContext, ConstantContext, + DoStatementContext, ExpressionContext, IfElseStatementContext, IfExpressionContext, @@ -288,6 +289,10 @@ export class VMWriter extends JackParserListener { default: throw new Error(`Unknown call type ${callType}`); } + + }; + override exitDoStatement= (ctx: DoStatementContext) => { + this.result += ` pop temp 0\n`; }; //return override exitReturnStatement = (ctx: ReturnStatementContext) => { diff --git a/simulator/src/jack/resources/test/Average/Main.vm b/simulator/src/jack/resources/test/Average/Main.vm index 318b396d..bd88b53a 100644 --- a/simulator/src/jack/resources/test/Average/Main.vm +++ b/simulator/src/jack/resources/test/Average/Main.vm @@ -140,9 +140,11 @@ label Main_1 push constant 32 call String.appendChar 2 call Output.printString 1 + pop temp 0 push local 3 push local 1 call Math.divide 2 call Output.printInt 1 + pop temp 0 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/ComplexArrays/Main.vm b/simulator/src/jack/resources/test/ComplexArrays/Main.vm index 869dd99a..d125bde9 100644 --- a/simulator/src/jack/resources/test/ComplexArrays/Main.vm +++ b/simulator/src/jack/resources/test/ComplexArrays/Main.vm @@ -194,13 +194,16 @@ function Main.main 3 push constant 32 call String.appendChar 2 call Output.printString 1 + pop temp 0 push constant 2 push local 1 add pop pointer 1 push that 0 call Output.printInt 1 + pop temp 0 call Output.println 0 + pop temp 0 push constant 44 call String.new 1 push constant 84 @@ -292,13 +295,16 @@ function Main.main 3 push constant 32 call String.appendChar 2 call Output.printString 1 + pop temp 0 push constant 5 push local 0 add pop pointer 1 push that 0 call Output.printInt 1 + pop temp 0 call Output.println 0 + pop temp 0 push constant 43 call String.new 1 push constant 84 @@ -388,9 +394,12 @@ function Main.main 3 push constant 32 call String.appendChar 2 call Output.printString 1 + pop temp 0 push local 2 call Output.printInt 1 + pop temp 0 call Output.println 0 + pop temp 0 push constant 0 pop local 2 push local 2 @@ -401,6 +410,7 @@ function Main.main 3 push local 0 push constant 10 call Main.fill 2 + pop temp 0 push constant 3 push local 0 add @@ -545,13 +555,16 @@ label Main_0 push constant 32 call String.appendChar 2 call Output.printString 1 + pop temp 0 push constant 1 push local 2 add pop pointer 1 push that 0 call Output.printInt 1 + pop temp 0 call Output.println 0 + pop temp 0 push constant 45 call String.new 1 push constant 84 @@ -645,13 +658,16 @@ label Main_0 push constant 32 call String.appendChar 2 call Output.printString 1 + pop temp 0 push constant 1 push local 1 add pop pointer 1 push that 0 call Output.printInt 1 + pop temp 0 call Output.println 0 + pop temp 0 push constant 0 return function Main.double 0 diff --git a/simulator/src/jack/resources/test/ConvertToBin/Main.vm b/simulator/src/jack/resources/test/ConvertToBin/Main.vm index 3b7105da..f83fa929 100644 --- a/simulator/src/jack/resources/test/ConvertToBin/Main.vm +++ b/simulator/src/jack/resources/test/ConvertToBin/Main.vm @@ -4,11 +4,13 @@ function Main.main 1 push constant 1 neg call Main.fillMemory 3 + pop temp 0 push constant 8000 call Memory.peek 1 pop local 0 push local 0 call Main.convert 1 + pop temp 0 push constant 0 return function Main.convert 3 @@ -45,6 +47,7 @@ label Main_0 add push constant 1 call Memory.poke 2 + pop temp 0 goto Main_4 label Main_3 push constant 8000 @@ -52,6 +55,7 @@ label Main_3 add push constant 0 call Memory.poke 2 + pop temp 0 label Main_4 goto Main_5 label Main_2 @@ -87,6 +91,7 @@ label Main_8 push argument 0 push argument 2 call Memory.poke 2 + pop temp 0 push argument 1 push constant 1 sub diff --git a/simulator/src/jack/resources/test/Fraction/Fraction.vm b/simulator/src/jack/resources/test/Fraction/Fraction.vm index a7beb616..1f5e205a 100644 --- a/simulator/src/jack/resources/test/Fraction/Fraction.vm +++ b/simulator/src/jack/resources/test/Fraction/Fraction.vm @@ -8,6 +8,7 @@ function Fraction.new 0 pop this 1 push pointer 0 call Fraction.reduce 1 + pop temp 0 push pointer 0 return function Fraction.reduce 1 @@ -68,6 +69,7 @@ function Fraction.dispose 0 pop pointer 0 push pointer 0 call Memory.deAlloc 1 + pop temp 0 push constant 0 return function Fraction.print 0 @@ -75,13 +77,16 @@ function Fraction.print 0 pop pointer 0 push this 0 call Output.printInt 1 + pop temp 0 push constant 1 call String.new 1 push constant 47 call String.appendChar 2 call Output.printString 1 + pop temp 0 push this 1 call Output.printInt 1 + pop temp 0 push constant 0 return function Fraction.gcd 1 diff --git a/simulator/src/jack/resources/test/Fraction/Main.vm b/simulator/src/jack/resources/test/Fraction/Main.vm index f3257634..fcf795d3 100644 --- a/simulator/src/jack/resources/test/Fraction/Main.vm +++ b/simulator/src/jack/resources/test/Fraction/Main.vm @@ -13,5 +13,6 @@ function Main.main 3 pop local 2 push local 2 call Fraction.print 1 + pop temp 0 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/HelloWorld/Main.vm b/simulator/src/jack/resources/test/HelloWorld/Main.vm index 5f7e233a..1a9240be 100644 --- a/simulator/src/jack/resources/test/HelloWorld/Main.vm +++ b/simulator/src/jack/resources/test/HelloWorld/Main.vm @@ -26,6 +26,8 @@ function Main.main 0 push constant 33 call String.appendChar 2 call Output.printString 1 + pop temp 0 call Output.println 0 + pop temp 0 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/List/List.vm b/simulator/src/jack/resources/test/List/List.vm index ebb79850..71f197ed 100644 --- a/simulator/src/jack/resources/test/List/List.vm +++ b/simulator/src/jack/resources/test/List/List.vm @@ -33,8 +33,10 @@ label List_0 push local 0 call List.getData 1 call Output.printInt 1 + pop temp 0 push constant 32 call Output.printChar 1 + pop temp 0 push local 0 call List.getNext 1 pop local 0 @@ -53,8 +55,10 @@ function List.dispose 0 if-goto List_2 push this 1 call List.dispose 1 + pop temp 0 label List_2 push pointer 0 call Memory.deAlloc 1 + pop temp 0 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/List/Main.vm b/simulator/src/jack/resources/test/List/Main.vm index 94891ba4..171cfd91 100644 --- a/simulator/src/jack/resources/test/List/Main.vm +++ b/simulator/src/jack/resources/test/List/Main.vm @@ -11,7 +11,9 @@ function Main.main 1 pop local 0 push local 0 call List.print 1 + pop temp 0 push local 0 call List.dispose 1 + pop temp 0 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/Ball.vm b/simulator/src/jack/resources/test/Pong/Ball.vm index b054897f..fe292882 100644 --- a/simulator/src/jack/resources/test/Pong/Ball.vm +++ b/simulator/src/jack/resources/test/Pong/Ball.vm @@ -22,6 +22,7 @@ function Ball.new 0 pop this 14 push pointer 0 call Ball.show 1 + pop temp 0 push pointer 0 return function Ball.dispose 0 @@ -29,6 +30,7 @@ function Ball.dispose 0 pop pointer 0 push pointer 0 call Memory.deAlloc 1 + pop temp 0 push constant 0 return function Ball.show 0 @@ -37,8 +39,10 @@ function Ball.show 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push pointer 0 call Ball.draw 1 + pop temp 0 push constant 0 return function Ball.hide 0 @@ -46,8 +50,10 @@ function Ball.hide 0 pop pointer 0 push constant 0 call Screen.setColor 1 + pop temp 0 push pointer 0 call Ball.draw 1 + pop temp 0 push constant 0 return function Ball.draw 0 @@ -62,6 +68,7 @@ function Ball.draw 0 push constant 5 add call Screen.drawRectangle 4 + pop temp 0 push constant 0 return function Ball.getLeft 0 @@ -148,6 +155,7 @@ function Ball.move 0 pop pointer 0 push pointer 0 call Ball.hide 1 + pop temp 0 push this 4 push constant 0 lt @@ -278,6 +286,7 @@ label Ball_18 label Ball_19 push pointer 0 call Ball.show 1 + pop temp 0 push this 14 return function Ball.bounce 5 @@ -413,5 +422,6 @@ label Ball_25 push local 0 push local 1 call Ball.setDestination 3 + pop temp 0 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/Bat.vm b/simulator/src/jack/resources/test/Pong/Bat.vm index 6d1ab21e..19418727 100644 --- a/simulator/src/jack/resources/test/Pong/Bat.vm +++ b/simulator/src/jack/resources/test/Pong/Bat.vm @@ -14,6 +14,7 @@ function Bat.new 0 pop this 4 push pointer 0 call Bat.show 1 + pop temp 0 push pointer 0 return function Bat.dispose 0 @@ -21,6 +22,7 @@ function Bat.dispose 0 pop pointer 0 push pointer 0 call Memory.deAlloc 1 + pop temp 0 push constant 0 return function Bat.show 0 @@ -29,8 +31,10 @@ function Bat.show 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push pointer 0 call Bat.draw 1 + pop temp 0 push constant 0 return function Bat.hide 0 @@ -38,8 +42,10 @@ function Bat.hide 0 pop pointer 0 push constant 0 call Screen.setColor 1 + pop temp 0 push pointer 0 call Bat.draw 1 + pop temp 0 push constant 0 return function Bat.draw 0 @@ -54,6 +60,7 @@ function Bat.draw 0 push this 3 add call Screen.drawRectangle 4 + pop temp 0 push constant 0 return function Bat.setDirection 0 @@ -80,10 +87,12 @@ function Bat.setWidth 0 pop pointer 0 push pointer 0 call Bat.hide 1 + pop temp 0 push argument 1 pop this 2 push pointer 0 call Bat.show 1 + pop temp 0 push constant 0 return function Bat.move 0 @@ -108,6 +117,7 @@ function Bat.move 0 label Bat_1 push constant 0 call Screen.setColor 1 + pop temp 0 push this 0 push this 2 add @@ -123,9 +133,11 @@ label Bat_1 push this 3 add call Screen.drawRectangle 4 + pop temp 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 0 @@ -135,6 +147,7 @@ label Bat_1 push this 3 add call Screen.drawRectangle 4 + pop temp 0 goto Bat_2 label Bat_0 push this 0 @@ -155,6 +168,7 @@ label Bat_0 label Bat_3 push constant 0 call Screen.setColor 1 + pop temp 0 push this 0 push constant 4 sub @@ -166,9 +180,11 @@ label Bat_3 push this 3 add call Screen.drawRectangle 4 + pop temp 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push this 0 push this 2 add @@ -182,6 +198,7 @@ label Bat_3 push this 3 add call Screen.drawRectangle 4 + pop temp 0 label Bat_2 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/Main.vm b/simulator/src/jack/resources/test/Pong/Main.vm index 72da76af..ef29075b 100644 --- a/simulator/src/jack/resources/test/Pong/Main.vm +++ b/simulator/src/jack/resources/test/Pong/Main.vm @@ -1,10 +1,13 @@ function Main.main 1 call PongGame.newInstance 0 + pop temp 0 call PongGame.getInstance 0 pop local 0 push local 0 call PongGame.run 1 + pop temp 0 push local 0 call PongGame.dispose 1 + pop temp 0 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Pong/PongGame.vm b/simulator/src/jack/resources/test/Pong/PongGame.vm index f9e69c74..e2b41418 100644 --- a/simulator/src/jack/resources/test/Pong/PongGame.vm +++ b/simulator/src/jack/resources/test/Pong/PongGame.vm @@ -3,6 +3,7 @@ function PongGame.new 0 call Memory.alloc 1 pop pointer 0 call Screen.clearScreen 0 + pop temp 0 push constant 50 pop this 6 push constant 230 @@ -23,14 +24,17 @@ function PongGame.new 0 push constant 400 push constant 0 call Ball.setDestination 3 + pop temp 0 push constant 0 push constant 238 push constant 511 push constant 240 call Screen.drawRectangle 4 + pop temp 0 push constant 22 push constant 0 call Output.moveCursor 2 + pop temp 0 push constant 8 call String.new 1 push constant 83 @@ -50,6 +54,7 @@ function PongGame.new 0 push constant 48 call String.appendChar 2 call Output.printString 1 + pop temp 0 push constant 0 pop this 3 push constant 0 @@ -65,10 +70,13 @@ function PongGame.dispose 0 pop pointer 0 push this 0 call Bat.dispose 1 + pop temp 0 push this 1 call Ball.dispose 1 + pop temp 0 push pointer 0 call Memory.deAlloc 1 + pop temp 0 push constant 0 return function PongGame.newInstance 0 @@ -99,11 +107,14 @@ label PongGame_2 call Keyboard.keyPressed 0 pop local 0 push this 0 - call Bat.move 1 + call Bat.move 1 + pop temp 0 push pointer 0 call PongGame.moveBall 1 + pop temp 0 push constant 50 call Sys.wait 1 + pop temp 0 goto PongGame_2 label PongGame_3 push local 0 @@ -114,6 +125,7 @@ label PongGame_3 push this 0 push constant 1 call Bat.setDirection 2 + pop temp 0 goto PongGame_5 label PongGame_4 push local 0 @@ -124,6 +136,7 @@ label PongGame_4 push this 0 push constant 2 call Bat.setDirection 2 + pop temp 0 goto PongGame_7 label PongGame_6 push local 0 @@ -150,11 +163,14 @@ label PongGame_9 call Keyboard.keyPressed 0 pop local 0 push this 0 - call Bat.move 1 + call Bat.move 1 + pop temp 0 push pointer 0 call PongGame.moveBall 1 + pop temp 0 push constant 50 call Sys.wait 1 + pop temp 0 goto PongGame_9 label PongGame_10 goto PongGame_0 @@ -165,6 +181,7 @@ label PongGame_1 push constant 10 push constant 27 call Output.moveCursor 2 + pop temp 0 push constant 9 call String.new 1 push constant 71 @@ -186,6 +203,7 @@ label PongGame_1 push constant 114 call String.appendChar 2 call Output.printString 1 + pop temp 0 label PongGame_11 push constant 0 return @@ -268,6 +286,7 @@ label PongGame_16 push this 0 push this 6 call Bat.setWidth 2 + pop temp 0 push this 4 push constant 1 add @@ -275,13 +294,16 @@ label PongGame_16 push constant 22 push constant 7 call Output.moveCursor 2 + pop temp 0 push this 4 call Output.printInt 1 + pop temp 0 label PongGame_14 label PongGame_13 push this 1 push local 0 call Ball.bounce 2 + pop temp 0 label PongGame_12 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Square/Main.vm b/simulator/src/jack/resources/test/Square/Main.vm index bcbfcfcc..d4f170a7 100644 --- a/simulator/src/jack/resources/test/Square/Main.vm +++ b/simulator/src/jack/resources/test/Square/Main.vm @@ -3,7 +3,9 @@ function Main.main 1 pop local 0 push local 0 call SquareGame.run 1 + pop temp 0 push local 0 call SquareGame.dispose 1 + pop temp 0 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Square/Square.vm b/simulator/src/jack/resources/test/Square/Square.vm index 99beeb2b..74d17099 100644 --- a/simulator/src/jack/resources/test/Square/Square.vm +++ b/simulator/src/jack/resources/test/Square/Square.vm @@ -10,6 +10,7 @@ function Square.new 0 pop this 2 push pointer 0 call Square.draw 1 + pop temp 0 push pointer 0 return function Square.dispose 0 @@ -17,6 +18,7 @@ function Square.dispose 0 pop pointer 0 push pointer 0 call Memory.deAlloc 1 + pop temp 0 push constant 0 return function Square.draw 0 @@ -25,6 +27,7 @@ function Square.draw 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 0 @@ -34,6 +37,7 @@ function Square.draw 0 push this 2 add call Screen.drawRectangle 4 + pop temp 0 push constant 0 return function Square.erase 0 @@ -41,6 +45,7 @@ function Square.erase 0 pop pointer 0 push constant 0 call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 0 @@ -50,6 +55,7 @@ function Square.erase 0 push this 2 add call Screen.drawRectangle 4 + pop temp 0 push constant 0 return function Square.incSize 0 @@ -70,12 +76,14 @@ function Square.incSize 0 if-goto Square_0 push pointer 0 call Square.erase 1 + pop temp 0 push this 2 push constant 2 add pop this 2 push pointer 0 call Square.draw 1 + pop temp 0 label Square_0 push constant 0 return @@ -89,12 +97,14 @@ function Square.decSize 0 if-goto Square_1 push pointer 0 call Square.erase 1 + pop temp 0 push this 2 push constant 2 sub pop this 2 push pointer 0 call Square.draw 1 + pop temp 0 label Square_1 push constant 0 return @@ -108,6 +118,7 @@ function Square.moveUp 0 if-goto Square_2 push constant 0 call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 2 @@ -121,6 +132,7 @@ function Square.moveUp 0 push this 2 add call Screen.drawRectangle 4 + pop temp 0 push this 1 push constant 2 sub @@ -128,6 +140,7 @@ function Square.moveUp 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 0 @@ -137,6 +150,7 @@ function Square.moveUp 0 push constant 1 add call Screen.drawRectangle 4 + pop temp 0 label Square_2 push constant 0 return @@ -152,6 +166,7 @@ function Square.moveDown 0 if-goto Square_3 push constant 0 call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 0 @@ -161,6 +176,7 @@ function Square.moveDown 0 push constant 1 add call Screen.drawRectangle 4 + pop temp 0 push this 1 push constant 2 add @@ -168,6 +184,7 @@ function Square.moveDown 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 2 @@ -181,6 +198,7 @@ function Square.moveDown 0 push this 2 add call Screen.drawRectangle 4 + pop temp 0 label Square_3 push constant 0 return @@ -194,6 +212,7 @@ function Square.moveLeft 0 if-goto Square_4 push constant 0 call Screen.setColor 1 + pop temp 0 push this 0 push this 2 add @@ -207,6 +226,7 @@ function Square.moveLeft 0 push this 2 add call Screen.drawRectangle 4 + pop temp 0 push this 0 push constant 2 sub @@ -214,6 +234,7 @@ function Square.moveLeft 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 0 @@ -223,6 +244,7 @@ function Square.moveLeft 0 push this 2 add call Screen.drawRectangle 4 + pop temp 0 label Square_4 push constant 0 return @@ -238,6 +260,7 @@ function Square.moveRight 0 if-goto Square_5 push constant 0 call Screen.setColor 1 + pop temp 0 push this 0 push this 1 push this 0 @@ -247,6 +270,7 @@ function Square.moveRight 0 push this 2 add call Screen.drawRectangle 4 + pop temp 0 push this 0 push constant 2 add @@ -254,6 +278,7 @@ function Square.moveRight 0 push constant 1 neg call Screen.setColor 1 + pop temp 0 push this 0 push this 2 add @@ -267,6 +292,7 @@ function Square.moveRight 0 push this 2 add call Screen.drawRectangle 4 + pop temp 0 label Square_5 push constant 0 return \ No newline at end of file diff --git a/simulator/src/jack/resources/test/Square/SquareGame.vm b/simulator/src/jack/resources/test/Square/SquareGame.vm index fcbe7e74..838c2b9f 100644 --- a/simulator/src/jack/resources/test/Square/SquareGame.vm +++ b/simulator/src/jack/resources/test/Square/SquareGame.vm @@ -16,8 +16,10 @@ function SquareGame.dispose 0 pop pointer 0 push this 0 call Square.dispose 1 + pop temp 0 push pointer 0 call Memory.deAlloc 1 + pop temp 0 push constant 0 return function SquareGame.moveSquare 0 @@ -30,6 +32,7 @@ function SquareGame.moveSquare 0 if-goto SquareGame_0 push this 0 call Square.moveUp 1 + pop temp 0 label SquareGame_0 push this 1 push constant 2 @@ -38,6 +41,7 @@ label SquareGame_0 if-goto SquareGame_1 push this 0 call Square.moveDown 1 + pop temp 0 label SquareGame_1 push this 1 push constant 3 @@ -46,6 +50,7 @@ label SquareGame_1 if-goto SquareGame_2 push this 0 call Square.moveLeft 1 + pop temp 0 label SquareGame_2 push this 1 push constant 4 @@ -54,9 +59,11 @@ label SquareGame_2 if-goto SquareGame_3 push this 0 call Square.moveRight 1 + pop temp 0 label SquareGame_3 push constant 5 call Sys.wait 1 + pop temp 0 push constant 0 return function SquareGame.run 2 @@ -79,6 +86,7 @@ label SquareGame_6 pop local 0 push pointer 0 call SquareGame.moveSquare 1 + pop temp 0 goto SquareGame_6 label SquareGame_7 push local 0 @@ -97,6 +105,7 @@ label SquareGame_8 if-goto SquareGame_9 push this 0 call Square.decSize 1 + pop temp 0 label SquareGame_9 push local 0 push constant 88 @@ -105,6 +114,7 @@ label SquareGame_9 if-goto SquareGame_10 push this 0 call Square.incSize 1 + pop temp 0 label SquareGame_10 push local 0 push constant 131 @@ -149,6 +159,7 @@ label SquareGame_15 pop local 0 push pointer 0 call SquareGame.moveSquare 1 + pop temp 0 goto SquareGame_15 label SquareGame_16 goto SquareGame_4 From 520ce317c3a8337ff96e0a68e24d6a3e05d8eb0c Mon Sep 17 00:00:00 2001 From: Roman Lukash <2893931+happytomatoe@users.noreply.github.com> Date: Tue, 22 Oct 2024 18:42:07 +0200 Subject: [PATCH 87/87] Formatting --- simulator/src/jack/listener/vm.writer.listener.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/simulator/src/jack/listener/vm.writer.listener.ts b/simulator/src/jack/listener/vm.writer.listener.ts index aa4edcaf..f111a5d8 100644 --- a/simulator/src/jack/listener/vm.writer.listener.ts +++ b/simulator/src/jack/listener/vm.writer.listener.ts @@ -289,10 +289,9 @@ export class VMWriter extends JackParserListener { default: throw new Error(`Unknown call type ${callType}`); } - }; - override exitDoStatement= (ctx: DoStatementContext) => { - this.result += ` pop temp 0\n`; + override exitDoStatement = (ctx: DoStatementContext) => { + this.result += ` pop temp 0\n`; }; //return override exitReturnStatement = (ctx: ReturnStatementContext) => {