From 5659c7bae3526eeebfcbf23a87ed9f05a72f33f1 Mon Sep 17 00:00:00 2001 From: Martin Fieber Date: Mon, 4 Feb 2019 20:14:32 +0100 Subject: [PATCH] chore: ease up used tooling --- .editorconfig | 14 +- .eslintrc.js | 18 +- .travis.yml | 10 +- CODE_OF_CONDUCT.md | 20 +- CONTRIBUTING.md | 12 +- README.md | 12 +- docs/language.md | 204 +- package.json | 4 +- prettier.config.js | 4 - renovate.json | 18 +- src/cli/commands/execute.js | 16 +- src/cli/commands/repl.js | 46 +- src/cli/commands/tests.js | 48 +- src/cli/index.js | 48 +- src/compiler/__tests__/expression-if.test.js | 164 +- src/compiler/__tests__/literals.test.js | 56 +- .../__tests__/operation-basic.test.js | 100 +- .../__tests__/operation-complex.test.js | 58 +- src/compiler/index.js | 172 +- src/parser/__mocks__/index.js | 34 +- src/parser/__mocks__/setup.js | 2 +- src/parser/__tests__/phase-01/_README.md | 142 +- src/parser/__tests__/phase-01/base.test.js | 112 +- .../__tests__/phase-01/type-float.test.js | 674 +-- .../__tests__/phase-01/type-integer.test.js | 674 +-- src/parser/__tests__/phase-02/_README.md | 96 +- .../__tests__/phase-02/type-combined.test.js | 1018 ++-- .../__tests__/phase-02/type-float.test.js | 398 +- .../__tests__/phase-02/type-integer.test.js | 398 +- src/parser/__tests__/phase-03/_README.md | 2 +- .../__tests__/phase-03/type-combined.test.js | 116 +- .../__tests__/phase-03/type-float.test.js | 204 +- .../__tests__/phase-03/type-integer.test.js | 204 +- src/parser/__tests__/phase-04/_README.md | 88 +- .../__tests__/phase-04/expression-if-test.js | 558 +-- src/parser/__tests__/phase-05/_README.md | 138 +- .../__tests__/phase-05/expression-if-test.js | 1710 +++---- src/parser/__tests__/phase-06/_README.md | 300 +- .../__tests__/phase-06/expression-if-test.js | 4386 ++++++++--------- src/parser/__tests__/phase-07/_README.md | 2 +- .../__tests__/phase-07/expression-if-test.js | 606 +-- src/parser/__tests__/phase-08/_README.md | 2 +- .../__tests__/phase-08/expression-if-test.js | 258 +- .../__tests__/phase-08/type-combined.test.js | 138 +- .../__tests__/phase-08/type-float.test.js | 264 +- .../__tests__/phase-08/type-integer.test.js | 264 +- src/parser/__tests__/phase-09/_README.md | 160 +- .../__tests__/phase-09/multiline-test.js | 2614 +++++----- src/parser/index.js | 20 +- src/strex-lang.peg | 226 +- 50 files changed, 8406 insertions(+), 8426 deletions(-) delete mode 100644 prettier.config.js diff --git a/.editorconfig b/.editorconfig index ff5fac0..0f17867 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,17 +1,9 @@ root = true [*] -end_of_line = lf -insert_final_newline = true - -[{*.{json,js,css},.*rc}] charset = utf-8 -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true - -[package.json] -charset = utf-8 -indent_style = space +end_of_line = lf indent_size = 2 +indent_style = space +insert_final_newline = true trim_trailing_whitespace = true diff --git a/.eslintrc.js b/.eslintrc.js index 8ca2475..d425f04 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,10 +1,12 @@ +"use strict"; + module.exports = { - extends: ['google', 'prettier'], - plugins: ['prettier'], - parserOptions: { - ecmaVersion: 2017 - }, - rules: { - 'prettier/prettier': 'error' - } + extends: ["google", "prettier"], + plugins: ["prettier"], + parserOptions: { + ecmaVersion: 2017 + }, + rules: { + "prettier/prettier": "error" + } }; diff --git a/.travis.yml b/.travis.yml index 3f715cc..dbc5385 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ language: node_js node_js: - - 'node' - - 8 + - "10" + - 8 install: - - npm install + - npm install script: - - npm run lint - - npm test -- --ensure + - npm run lint + - npm test -- --ensure diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 9e88da2..70f5a93 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo Examples of behavior that contributes to creating a positive environment include: -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -- The use of sexualized language or imagery and unwelcome sexual attention or advances -- Trolling, insulting/derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or electronic address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fccfe88..991af23 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,10 +8,10 @@ You want do something for this repo? Nice and easy! And of course: you are the b If you report a bug, please try to: -- Perform a web / GitHub search to avoid creating a duplicate ticket. -- Include enough information to reproduce the problem. -- Mention the exact version of the project causing you problems, as well as any related software and versions (such as operating system, browser, etc.). -- Test against the latest version of the project (and if possible also the master branch) to see if the problem has already been fixed. +- Perform a web / GitHub search to avoid creating a duplicate ticket. +- Include enough information to reproduce the problem. +- Mention the exact version of the project causing you problems, as well as any related software and versions (such as operating system, browser, etc.). +- Test against the latest version of the project (and if possible also the master branch) to see if the problem has already been fixed. Once you have tried the above, create a GitHub issue notifying your bug report. @@ -19,8 +19,8 @@ Once you have tried the above, create a GitHub issue notifying your bug report. If you want to contribute code, please: -- Write [good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), explain what your patch does, and why it is needed. How to is described in the [Commit changes chapter](#commit-changes). -- Keep it simple: Any patch that changes a lot of code or is difficult to understand should be discussed before you put in the effort. +- Write [good commit messages](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), explain what your patch does, and why it is needed. How to is described in the [Commit changes chapter](#commit-changes). +- Keep it simple: Any patch that changes a lot of code or is difficult to understand should be discussed before you put in the effort. Once you have tried the above, create a GitHub pull request with your changes changes and feel awesome 🎉. diff --git a/README.md b/README.md index ba4ada9..d240510 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,12 @@ The _StrexLang_ ("Strange expression language") is only used to train regular ex ## Contents -- [Goal](#goal) -- [Language](#language) -- [How to start](#how-to-start) - - [Installation](#installation) - - [Start development](#start-development) - - [Phases](#phases) +- [Goal](#goal) +- [Language](#language) +- [How to start](#how-to-start) + - [Installation](#installation) + - [Start development](#start-development) + - [Phases](#phases) --- diff --git a/docs/language.md b/docs/language.md index 2859ca2..de12310 100644 --- a/docs/language.md +++ b/docs/language.md @@ -1,9 +1,9 @@ ## Language -- [Language](#language) - - [Example](#example) - - [Features](#features) - - [AST](#ast) +- [Language](#language) + - [Example](#example) + - [Features](#features) + - [AST](#ast) --- @@ -30,25 +30,25 @@ _StrexLang_ is a very small language without any functions. It contains of expre #### Types -- **Signed and unsigned integer** (e.g. `-3`, `0`, `23`) - - Can be used as literal -- **Signed and unsigned float** (e.g. `-3.2`, `0.1`, `23.9`) - - Can be used as literal -- **Implicit boolean** (`true` and `false`) - - Can not be used as literal - - Is only be used for compare results in `if`-statements +- **Signed and unsigned integer** (e.g. `-3`, `0`, `23`) + - Can be used as literal +- **Signed and unsigned float** (e.g. `-3.2`, `0.1`, `23.9`) + - Can be used as literal +- **Implicit boolean** (`true` and `false`) + - Can not be used as literal + - Is only be used for compare results in `if`-statements #### Operator -- `+` - Math operator for addition (works with Integer and Float) -- `-` - Math operator for subtraction (works with Integer and Float) -- `*` - Math operator for multiplication (works with Integer and Float) -- `/` - Math operator for division (works with Integer and Float) -- `|` - "Or" (alternate/pipe) operator (works with implicit boolean) -- `&` - "And" (consequent) operator (works with implicit boolean) -- `=` - Equals operator (works with Integer and Float to compare value) -- `>` - Greater-than operator (works with Integer and Float to compare value) -- `<` - Less-than operator (works with Integer and Float to compare value) +- `+` - Math operator for addition (works with Integer and Float) +- `-` - Math operator for subtraction (works with Integer and Float) +- `*` - Math operator for multiplication (works with Integer and Float) +- `/` - Math operator for division (works with Integer and Float) +- `|` - "Or" (alternate/pipe) operator (works with implicit boolean) +- `&` - "And" (consequent) operator (works with implicit boolean) +- `=` - Equals operator (works with Integer and Float to compare value) +- `>` - Greater-than operator (works with Integer and Float to compare value) +- `<` - Less-than operator (works with Integer and Float to compare value) #### Calculation @@ -109,70 +109,70 @@ the resulting AST would look like the following (defined as JSON): ```json { - "body": [ - { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "4" - }, - "right": { - "type": "IntegerLiteral", - "value": "3" - }, - "operator": "+" + "body": [ + { + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "4" + }, + "right": { + "type": "IntegerLiteral", + "value": "3" + }, + "operator": "+" + }, + { + "type": "IfExpression", + "test": { + "type": "BooleanExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "7" }, - { - "type": "IfExpression", - "test": { - "type": "BooleanExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "7" - }, - "operator": "=" - }, - "consequent": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "5" - }, - "operator": "+" - }, - "alternate": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "4" - }, - "operator": "-" - } + "operator": "=" + }, + "consequent": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" }, - { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "2" - }, - "operator": "-" + "right": { + "type": "IntegerLiteral", + "value": "5" }, - { - "type": "PrintOut" - } - ] + "operator": "+" + }, + "alternate": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "4" + }, + "operator": "-" + } + }, + { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "2" + }, + "operator": "-" + }, + { + "type": "PrintOut" + } + ] } ``` @@ -180,7 +180,7 @@ Step by step the AST is defined as follows. It starts with the actual program bo ```json { - "body": [] + "body": [] } ``` @@ -188,16 +188,16 @@ The `body` array contains any defined statement and expression of the program li ```json { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "4" - }, - "right": { - "type": "IntegerLiteral", - "value": "3" - }, - "operator": "+" + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "4" + }, + "right": { + "type": "IntegerLiteral", + "value": "3" + }, + "operator": "+" } ``` @@ -249,15 +249,15 @@ The next line uses the last expression as left hand to assign the operator `-` w ```json { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "2" - }, - "operator": "-" + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "2" + }, + "operator": "-" } ``` @@ -265,7 +265,7 @@ The last statement is the "empty line" that results in a print out to the stdout ```json { - "type": "PrintOut" + "type": "PrintOut" } ``` diff --git a/package.json b/package.json index 7fa353f..0261c9f 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "start": "node src/cli", "test": "node src/cli --test", "lint": "eslint '**/*.js'", - "release": "standard-version" + "release": "standard-version", + "format": "prettier --write \"**/*.{js,css,md,json,yml}\"", + "format:check": "prettier --list-different \"**/*.{js,css,md,json,yml}\"" }, "keywords": [ "strexlang", diff --git a/prettier.config.js b/prettier.config.js deleted file mode 100644 index 1771dfa..0000000 --- a/prettier.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - tabWidth: 4, - singleQuote: true -}; diff --git a/renovate.json b/renovate.json index f86d6d5..429be72 100644 --- a/renovate.json +++ b/renovate.json @@ -1,13 +1,13 @@ { - "extends": ["config:base"], - "dependencies": { - "semanticPrefix": "chore:", - "semanticCommitScope": "" - }, - "pin": { - "semanticPrefix": "chore:", - "semanticCommitScope": "" - }, + "extends": ["config:base"], + "dependencies": { "semanticPrefix": "chore:", "semanticCommitScope": "" + }, + "pin": { + "semanticPrefix": "chore:", + "semanticCommitScope": "" + }, + "semanticPrefix": "chore:", + "semanticCommitScope": "" } diff --git a/src/cli/commands/execute.js b/src/cli/commands/execute.js index 750e135..baf0bcb 100644 --- a/src/cli/commands/execute.js +++ b/src/cli/commands/execute.js @@ -4,12 +4,12 @@ * This command is to execute strex files. The result will be written to the * standard output. */ -'use strict'; +"use strict"; -const { promisify } = require('util'); -const fs = require('fs'); +const { promisify } = require("util"); +const fs = require("fs"); -const compiler = require('../../compiler'); +const compiler = require("../../compiler"); const statAsync = promisify(fs.stat); const readFileAsync = promisify(fs.readFile); @@ -21,8 +21,8 @@ const readFileAsync = promisify(fs.readFile); * @return {Promise} */ module.exports = async function execute({ execute, ensure }) { - if (await statAsync(execute)) { - const fileContent = await readFileAsync(execute); - return compiler(fileContent, ensure); - } + if (await statAsync(execute)) { + const fileContent = await readFileAsync(execute); + return compiler(fileContent, ensure); + } }; diff --git a/src/cli/commands/repl.js b/src/cli/commands/repl.js index 093e5d1..3ff3993 100644 --- a/src/cli/commands/repl.js +++ b/src/cli/commands/repl.js @@ -5,11 +5,11 @@ * * REPL: https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop */ -'use strict'; +"use strict"; -const os = require('os'); -const replServer = require('repl'); -const compiler = require('../../compiler'); +const os = require("os"); +const replServer = require("repl"); +const compiler = require("../../compiler"); /** * The StrexLang REPL (Read–eval–print loop). @@ -18,26 +18,26 @@ const compiler = require('../../compiler'); * @return {Promise} Resolves to the evaluated expression. */ module.exports = async function repl({ ensure }) { - let lines = []; + let lines = []; - return new Promise((resolve, reject) => { - const server = replServer.start({ - eval: line => { - try { - if (line === os.EOL) { - const result = compiler(lines.join(''), ensure); - lines = []; - console.log(result); - } + return new Promise((resolve, reject) => { + const server = replServer.start({ + eval: line => { + try { + if (line === os.EOL) { + const result = compiler(lines.join(""), ensure); + lines = []; + console.log(result); + } - lines.push(line); - } catch (exception) { - reject(exception); - } - }, - writer: output => output - }); - - server.on('exit', resolve); + lines.push(line); + } catch (exception) { + reject(exception); + } + }, + writer: output => output }); + + server.on("exit", resolve); + }); }; diff --git a/src/cli/commands/tests.js b/src/cli/commands/tests.js index 6b207aa..80d1a50 100644 --- a/src/cli/commands/tests.js +++ b/src/cli/commands/tests.js @@ -5,10 +5,10 @@ * all tests or takes the given phase and executes all phases that came before * as well. So if `phase-02` is given it will execute `phase-01,phase-02`. */ -'use strict'; +"use strict"; -const path = require('path'); -const jest = require('jest'); +const path = require("path"); +const jest = require("jest"); /** * Create an array of phases as range to target phase @@ -17,9 +17,9 @@ const jest = require('jest'); * @return {string[]} Phase range */ function createPhaseRange(toPhase) { - return Array(toPhase) - .fill('') - .map((_, index) => `phase-${String(index + 1).padStart(2, '0')}`); + return Array(toPhase) + .fill("") + .map((_, index) => `phase-${String(index + 1).padStart(2, "0")}`); } /** @@ -29,27 +29,27 @@ function createPhaseRange(toPhase) { * @return {Promise} */ module.exports = async function test({ test, ensure }) { - const jestArgs = []; + const jestArgs = []; - if (typeof test === 'string') { - const arg = - test === 'compiler' - ? test - : createPhaseRange(parseInt(test.split('-')[1], 10)).join('|'); - jestArgs.push(arg); - } + if (typeof test === "string") { + const arg = + test === "compiler" + ? test + : createPhaseRange(parseInt(test.split("-")[1], 10)).join("|"); + jestArgs.push(arg); + } - // Use reference implementation - if (ensure) { - const setupTestsFilePath = path.resolve( - __dirname, - '../../parser/__mocks__/setup.js' - ); + // Use reference implementation + if (ensure) { + const setupTestsFilePath = path.resolve( + __dirname, + "../../parser/__mocks__/setup.js" + ); - jestArgs.push(`--setupTestFrameworkScriptFile=${setupTestsFilePath}`); + jestArgs.push(`--setupTestFrameworkScriptFile=${setupTestsFilePath}`); - process.env.STREX_LANG_ENSURE = '1'; - } + process.env.STREX_LANG_ENSURE = "1"; + } - return jest.run(jestArgs); + return jest.run(jestArgs); }; diff --git a/src/cli/index.js b/src/cli/index.js index 6ec6a25..ce343b3 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -6,37 +6,37 @@ * * REPL: https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop */ -'use strict'; +"use strict"; -const commander = require('commander'); -const pkg = require('../../package.json'); +const commander = require("commander"); +const pkg = require("../../package.json"); -const test = require('./commands/tests'); -const execute = require('./commands/execute'); -const repl = require('./commands/repl'); +const test = require("./commands/tests"); +const execute = require("./commands/execute"); +const repl = require("./commands/repl"); const print = console.log; (async function cli() { - commander - .version(pkg.version, '-v, --version') - .option('-x, --execute ', 'Execute a strex file') - .option('-t, --test [phase]', 'Run tests for phases') - .option('-e, --ensure', 'Execute with reference implementation') - .parse(process.argv); + commander + .version(pkg.version, "-v, --version") + .option("-x, --execute ", "Execute a strex file") + .option("-t, --test [phase]", "Run tests for phases") + .option("-e, --ensure", "Execute with reference implementation") + .parse(process.argv); - try { - if (commander.test) { - return print(await test(commander)); - } - - if (commander.execute) { - return print(await execute(commander)); - } + try { + if (commander.test) { + return print(await test(commander)); + } - return await repl(commander); - } catch (exception) { - console.error(exception.message); - process.exit(1); + if (commander.execute) { + return print(await execute(commander)); } + + return await repl(commander); + } catch (exception) { + console.error(exception.message); + process.exit(1); + } })(); diff --git a/src/compiler/__tests__/expression-if.test.js b/src/compiler/__tests__/expression-if.test.js index 7aeeead..5d43449 100644 --- a/src/compiler/__tests__/expression-if.test.js +++ b/src/compiler/__tests__/expression-if.test.js @@ -1,116 +1,116 @@ /* eslint-disable max-len */ -const compiler = require('../index'); +const compiler = require("../index"); -const ENSURE = process.env.STREX_LANG_ENSURE === '1'; +const ENSURE = process.env.STREX_LANG_ENSURE === "1"; -describe('compiler > expression > if', () => { - describe('basic comparisons', () => { - test('by equality true', () => { - const actual = compiler('10\n= 10 ? - 5\n', ENSURE); - const expected = '5'; +describe("compiler > expression > if", () => { + describe("basic comparisons", () => { + test("by equality true", () => { + const actual = compiler("10\n= 10 ? - 5\n", ENSURE); + const expected = "5"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('by equality false', () => { - const actual = compiler('8\n= 10 ? - 5 : + 2\n', ENSURE); - const expected = '10'; + test("by equality false", () => { + const actual = compiler("8\n= 10 ? - 5 : + 2\n", ENSURE); + const expected = "10"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('by greater than true', () => { - const actual = compiler('1\n> 0 ? + 2\n', ENSURE); - const expected = '3'; + test("by greater than true", () => { + const actual = compiler("1\n> 0 ? + 2\n", ENSURE); + const expected = "3"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('by greater than false', () => { - const actual = compiler('5\n> 6 ? - 5 : * 2\n', ENSURE); - const expected = '10'; + test("by greater than false", () => { + const actual = compiler("5\n> 6 ? - 5 : * 2\n", ENSURE); + const expected = "10"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('by smaller than true', () => { - const actual = compiler('- 10\n< 0 - 1 ? + 10\n', ENSURE); - const expected = '0'; + test("by smaller than true", () => { + const actual = compiler("- 10\n< 0 - 1 ? + 10\n", ENSURE); + const expected = "0"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('by smaller than false', () => { - const actual = compiler('1\n< 0 - 1 ? + 1 : - 2\n', ENSURE); - const expected = '-1'; + test("by smaller than false", () => { + const actual = compiler("1\n< 0 - 1 ? + 1 : - 2\n", ENSURE); + const expected = "-1"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); }); + }); - describe('with the "and" operator', () => { - test('for one operations true', () => { - const actual = compiler('1\n> 0 & < 2 ? + 0.1\n', ENSURE); - const expected = '1.1'; + describe('with the "and" operator', () => { + test("for one operations true", () => { + const actual = compiler("1\n> 0 & < 2 ? + 0.1\n", ENSURE); + const expected = "1.1"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('for one operations false', () => { - const actual = compiler('1\n> 0 & < 1 ? + 0.1 : - 0.1\n', ENSURE); - const expected = '0.9'; + test("for one operations false", () => { + const actual = compiler("1\n> 0 & < 1 ? + 0.1 : - 0.1\n", ENSURE); + const expected = "0.9"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('for multiple operations true', () => { - const actual = compiler('5.5\n> 0 & < 10 & > 2 ? - 0.5\n', ENSURE); - const expected = '5'; + test("for multiple operations true", () => { + const actual = compiler("5.5\n> 0 & < 10 & > 2 ? - 0.5\n", ENSURE); + const expected = "5"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('for multiple operations false', () => { - const actual = compiler( - '0.1\n> 0 & < 10 & > 2 ? - 0.1 : + 0.9\n', - ENSURE - ); - const expected = '1'; + test("for multiple operations false", () => { + const actual = compiler( + "0.1\n> 0 & < 10 & > 2 ? - 0.1 : + 0.9\n", + ENSURE + ); + const expected = "1"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); }); + }); - describe('with the "or" operator', () => { - test('for one operations true', () => { - const actual = compiler('5\n> 10 | = 5 ? + 1\n', ENSURE); - const expected = '6'; + describe('with the "or" operator', () => { + test("for one operations true", () => { + const actual = compiler("5\n> 10 | = 5 ? + 1\n", ENSURE); + const expected = "6"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('for one operations false', () => { - const actual = compiler('1\n> 2 | < 1 ? - 1 : + 4\n', ENSURE); - const expected = '5'; + test("for one operations false", () => { + const actual = compiler("1\n> 2 | < 1 ? - 1 : + 4\n", ENSURE); + const expected = "5"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('for multiple operations true', () => { - const actual = compiler('1\n> 2 | < 0 | = 1 ? - 0.2\n', ENSURE); - const expected = '0.8'; + test("for multiple operations true", () => { + const actual = compiler("1\n> 2 | < 0 | = 1 ? - 0.2\n", ENSURE); + const expected = "0.8"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('for multiple operations false', () => { - const actual = compiler( - '00.2\n= 1 | < 0.1 | > 1 ? * 2 : / 0.1\n', - ENSURE - ); - const expected = '2'; + test("for multiple operations false", () => { + const actual = compiler( + "00.2\n= 1 | < 0.1 | > 1 ? * 2 : / 0.1\n", + ENSURE + ); + const expected = "2"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); }); + }); }); diff --git a/src/compiler/__tests__/literals.test.js b/src/compiler/__tests__/literals.test.js index 8bd9de5..8311145 100644 --- a/src/compiler/__tests__/literals.test.js +++ b/src/compiler/__tests__/literals.test.js @@ -1,41 +1,41 @@ /* eslint-disable max-len */ -const compiler = require('../index'); +const compiler = require("../index"); -const ENSURE = process.env.STREX_LANG_ENSURE === '1'; +const ENSURE = process.env.STREX_LANG_ENSURE === "1"; -describe('compiler > literals', () => { - test('returns the number zero as a string if empty input', () => { - const actual = compiler('', ENSURE); - const expected = '0'; +describe("compiler > literals", () => { + test("returns the number zero as a string if empty input", () => { + const actual = compiler("", ENSURE); + const expected = "0"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('returns a given integer', () => { - const actual = compiler('42\n', ENSURE); - const expected = '42'; + test("returns a given integer", () => { + const actual = compiler("42\n", ENSURE); + const expected = "42"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('returns a given integer without leading zero', () => { - const actual = compiler('0023\n', ENSURE); - const expected = '23'; + test("returns a given integer without leading zero", () => { + const actual = compiler("0023\n", ENSURE); + const expected = "23"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('returns a given float', () => { - const actual = compiler('9999.99999999999999999999999\n', ENSURE); - const expected = '9999.99999999999999999999999'; + test("returns a given float", () => { + const actual = compiler("9999.99999999999999999999999\n", ENSURE); + const expected = "9999.99999999999999999999999"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('returns a given float without leading zero', () => { - const actual = compiler('0003.9\n', ENSURE); - const expected = '3.9'; + test("returns a given float without leading zero", () => { + const actual = compiler("0003.9\n", ENSURE); + const expected = "3.9"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); }); diff --git a/src/compiler/__tests__/operation-basic.test.js b/src/compiler/__tests__/operation-basic.test.js index c1b277a..623b7a1 100644 --- a/src/compiler/__tests__/operation-basic.test.js +++ b/src/compiler/__tests__/operation-basic.test.js @@ -1,73 +1,73 @@ /* eslint-disable max-len */ -const compiler = require('../index'); +const compiler = require("../index"); -const ENSURE = process.env.STREX_LANG_ENSURE === '1'; +const ENSURE = process.env.STREX_LANG_ENSURE === "1"; -describe('compiler > operation > basic', () => { - describe('for integer', () => { - test('calculates correct result for different equations with the + operator', () => { - const actual = compiler('1 + 2\n+4\n+3\n', ENSURE); - const expected = '10'; +describe("compiler > operation > basic", () => { + describe("for integer", () => { + test("calculates correct result for different equations with the + operator", () => { + const actual = compiler("1 + 2\n+4\n+3\n", ENSURE); + const expected = "10"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('calculates correct result for different equations with the - operator', () => { - const actual = compiler('34\n-4\n-10\n', ENSURE); - const expected = '20'; + test("calculates correct result for different equations with the - operator", () => { + const actual = compiler("34\n-4\n-10\n", ENSURE); + const expected = "20"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('calculates correct result for different equations with the * operator', () => { - const actual = compiler('2 * 4\n*3\n', ENSURE); - const expected = '24'; + test("calculates correct result for different equations with the * operator", () => { + const actual = compiler("2 * 4\n*3\n", ENSURE); + const expected = "24"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('calculates correct result for different equations with the / operator', () => { - const actual = compiler('100\n/10\n/2\n', ENSURE); - const expected = '5'; + test("calculates correct result for different equations with the / operator", () => { + const actual = compiler("100\n/10\n/2\n", ENSURE); + const expected = "5"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); }); + }); - describe('for float', () => { - test('calculates correct result for different equations with the + operator', () => { - const actual = compiler('1.0 + 2.3\n+4.456\n+0.5\n', ENSURE); - const expected = '8.256'; + describe("for float", () => { + test("calculates correct result for different equations with the + operator", () => { + const actual = compiler("1.0 + 2.3\n+4.456\n+0.5\n", ENSURE); + const expected = "8.256"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('calculates correct result for different equations with the - operator', () => { - const actual = compiler('6.89\n-0.0001\n-1.3\n', ENSURE); - const expected = '5.5899'; + test("calculates correct result for different equations with the - operator", () => { + const actual = compiler("6.89\n-0.0001\n-1.3\n", ENSURE); + const expected = "5.5899"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('calculates correct result for different equations with the * operator', () => { - const actual = compiler('2.5 * 0.5\n*0.1\n', ENSURE); - const expected = '0.125'; + test("calculates correct result for different equations with the * operator", () => { + const actual = compiler("2.5 * 0.5\n*0.1\n", ENSURE); + const expected = "0.125"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('calculates correct result for different equations with the / operator', () => { - const actual = compiler('10.0\n/100.1\n/2.2\n', ENSURE); - const expected = '0.045409136318227227318'; + test("calculates correct result for different equations with the / operator", () => { + const actual = compiler("10.0\n/100.1\n/2.2\n", ENSURE); + const expected = "0.045409136318227227318"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('edge case calculation', () => { - const actual = compiler('0.1 + 0.2\n', ENSURE); - const expected = '0.3'; + test("edge case calculation", () => { + const actual = compiler("0.1 + 0.2\n", ENSURE); + const expected = "0.3"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); }); + }); }); diff --git a/src/compiler/__tests__/operation-complex.test.js b/src/compiler/__tests__/operation-complex.test.js index 22409d0..46912ec 100644 --- a/src/compiler/__tests__/operation-complex.test.js +++ b/src/compiler/__tests__/operation-complex.test.js @@ -1,40 +1,40 @@ /* eslint-disable max-len */ -const compiler = require('../index'); +const compiler = require("../index"); -const ENSURE = process.env.STREX_LANG_ENSURE === '1'; +const ENSURE = process.env.STREX_LANG_ENSURE === "1"; -describe('compiler > operation > complex', () => { - test('calculates correct result for different mixed equations [1]', () => { - const actual = compiler('1 + 100\n*3\n+ 4 / 2\n-1*4\n', ENSURE); - const expected = '301'; +describe("compiler > operation > complex", () => { + test("calculates correct result for different mixed equations [1]", () => { + const actual = compiler("1 + 100\n*3\n+ 4 / 2\n-1*4\n", ENSURE); + const expected = "301"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('calculates correct result for different mixed equations [2]', () => { - const actual = compiler('1 + 2 * 2\n/ 3 + 2\n', ENSURE); - const expected = '1'; + test("calculates correct result for different mixed equations [2]", () => { + const actual = compiler("1 + 2 * 2\n/ 3 + 2\n", ENSURE); + const expected = "1"; - expect(actual).toBe(expected); - }); + expect(actual).toBe(expected); + }); - test('use braces to change precedence [1]', () => { - const actualWithBraces = compiler('2.2 * (2 + 3.0) / 4\n', ENSURE); - const actualWithoutBraces = compiler('2.2 * 2 + 3.0 / 4\n', ENSURE); - const expectedWithBraces = '2.75'; - const expectedWithoutBraces = '5.15'; + test("use braces to change precedence [1]", () => { + const actualWithBraces = compiler("2.2 * (2 + 3.0) / 4\n", ENSURE); + const actualWithoutBraces = compiler("2.2 * 2 + 3.0 / 4\n", ENSURE); + const expectedWithBraces = "2.75"; + const expectedWithoutBraces = "5.15"; - expect(actualWithBraces).toBe(expectedWithBraces); - expect(actualWithoutBraces).toBe(expectedWithoutBraces); - }); + expect(actualWithBraces).toBe(expectedWithBraces); + expect(actualWithoutBraces).toBe(expectedWithoutBraces); + }); - test('use braces to change precedence [2]', () => { - const actualWithBraces = compiler('2 / (4.5 + 1) * 4\n', ENSURE); - const actualWithoutBraces = compiler('2 / 4.5 + 1 * 4\n', ENSURE); - const expectedWithBraces = '1.4545454545454545454'; - const expectedWithoutBraces = '4.4444444444444444444'; + test("use braces to change precedence [2]", () => { + const actualWithBraces = compiler("2 / (4.5 + 1) * 4\n", ENSURE); + const actualWithoutBraces = compiler("2 / 4.5 + 1 * 4\n", ENSURE); + const expectedWithBraces = "1.4545454545454545454"; + const expectedWithoutBraces = "4.4444444444444444444"; - expect(actualWithBraces).toBe(expectedWithBraces); - expect(actualWithoutBraces).toBe(expectedWithoutBraces); - }); + expect(actualWithBraces).toBe(expectedWithBraces); + expect(actualWithoutBraces).toBe(expectedWithoutBraces); + }); }); diff --git a/src/compiler/index.js b/src/compiler/index.js index 52040a7..35c5136 100644 --- a/src/compiler/index.js +++ b/src/compiler/index.js @@ -5,24 +5,24 @@ * AST can also produce real values. Also this enables you to directly test your * implementation by producing a value rather an AST. */ -'use strict'; +"use strict"; -const Decimal = require('decimal.js'); +const Decimal = require("decimal.js"); const TYPE = { - PROGRAM: 'Program', - PRINT_OUT: 'PrintOut', - INTEGER_LITERAL: 'IntegerLiteral', - FLOAT_LITERAL: 'FloatLiteral', - BINARY_EXPRESSION: 'BinaryExpression', - BOOLEAN_EXPRESSION: 'BooleanExpression', - LAST_EXPRESSION: 'LastExpression', - IF_EXPRESSION: 'IfExpression' + PROGRAM: "Program", + PRINT_OUT: "PrintOut", + INTEGER_LITERAL: "IntegerLiteral", + FLOAT_LITERAL: "FloatLiteral", + BINARY_EXPRESSION: "BinaryExpression", + BOOLEAN_EXPRESSION: "BooleanExpression", + LAST_EXPRESSION: "LastExpression", + IF_EXPRESSION: "IfExpression" }; const BOOLEAN_OPERATOR = { - AND: '&', - OR: '|' + AND: "&", + OR: "|" }; /** @@ -32,17 +32,17 @@ const BOOLEAN_OPERATOR = { * @return {string} */ function getOperationName(operator) { - const METHOD_MAPPING = { - '+': 'plus', - '-': 'minus', - '*': 'times', - '/': 'dividedBy', - '=': 'equals', - '>': 'greaterThan', - '<': 'lessThan' - }; - - return METHOD_MAPPING[operator]; + const METHOD_MAPPING = { + "+": "plus", + "-": "minus", + "*": "times", + "/": "dividedBy", + "=": "equals", + ">": "greaterThan", + "<": "lessThan" + }; + + return METHOD_MAPPING[operator]; } /** @@ -54,11 +54,11 @@ function getOperationName(operator) { * @return {boolean} */ function evaluateAndExpression(evaluation, test, index) { - const { left, right } = test; - const leftExpression = evaluateBooleanExpression(evaluation, left, index); - const rightExpression = evaluateBooleanExpression(evaluation, right, index); + const { left, right } = test; + const leftExpression = evaluateBooleanExpression(evaluation, left, index); + const rightExpression = evaluateBooleanExpression(evaluation, right, index); - return Boolean(leftExpression && rightExpression); + return Boolean(leftExpression && rightExpression); } /** @@ -70,12 +70,10 @@ function evaluateAndExpression(evaluation, test, index) { * @return {boolean} */ function evaluateOrExpression(evaluation, test, index) { - const { left, right } = test; - const leftExpression = evaluateBooleanExpression(evaluation, left, index); + const { left, right } = test; + const leftExpression = evaluateBooleanExpression(evaluation, left, index); - return ( - leftExpression || evaluateBooleanExpression(evaluation, right, index) - ); + return leftExpression || evaluateBooleanExpression(evaluation, right, index); } /** @@ -87,31 +85,27 @@ function evaluateOrExpression(evaluation, test, index) { * @return {boolean} */ function evaluateBooleanExpression(evaluation, test, index) { - const lineNumber = index + 1; - const { type, left, right, operator } = test; - - if (type !== TYPE.BOOLEAN_EXPRESSION) { - throw new SyntaxError( - `Please use a boolean expression for tests in line ${lineNumber}` - ); - } - - switch (operator) { - case BOOLEAN_OPERATOR.AND: - return evaluateAndExpression(evaluation, test, index); - case BOOLEAN_OPERATOR.OR: - return evaluateOrExpression(evaluation, test, index); - default: - const leftExpression = evaluateExpression(evaluation, left, index); - const rightExpression = evaluateExpression( - evaluation, - right, - index - ); - const method = getOperationName(operator); - - return leftExpression[method](rightExpression); - } + const lineNumber = index + 1; + const { type, left, right, operator } = test; + + if (type !== TYPE.BOOLEAN_EXPRESSION) { + throw new SyntaxError( + `Please use a boolean expression for tests in line ${lineNumber}` + ); + } + + switch (operator) { + case BOOLEAN_OPERATOR.AND: + return evaluateAndExpression(evaluation, test, index); + case BOOLEAN_OPERATOR.OR: + return evaluateOrExpression(evaluation, test, index); + default: + const leftExpression = evaluateExpression(evaluation, left, index); + const rightExpression = evaluateExpression(evaluation, right, index); + const method = getOperationName(operator); + + return leftExpression[method](rightExpression); + } } /** @@ -123,33 +117,29 @@ function evaluateBooleanExpression(evaluation, test, index) { * @return {Decimal} */ function evaluateExpression(evaluation, line, index) { - switch (line.type) { - case TYPE.INTEGER_LITERAL: - case TYPE.FLOAT_LITERAL: - return new Decimal(line.value); - case TYPE.LAST_EXPRESSION: - case TYPE.PRINT_OUT: - return evaluation; - case TYPE.BINARY_EXPRESSION: - const { left, right, operator } = line; - const leftExpression = evaluateExpression(evaluation, left, index); - const rightExpression = evaluateExpression( - evaluation, - right, - index - ); - const method = getOperationName(operator); - - return leftExpression[method](rightExpression); - case TYPE.IF_EXPRESSION: - const { test, consequent, alternate } = line; - - return evaluateBooleanExpression(evaluation, test, index) - ? evaluateExpression(evaluation, consequent, index) - : evaluateExpression(evaluation, alternate, index); - default: - return evaluation; - } + switch (line.type) { + case TYPE.INTEGER_LITERAL: + case TYPE.FLOAT_LITERAL: + return new Decimal(line.value); + case TYPE.LAST_EXPRESSION: + case TYPE.PRINT_OUT: + return evaluation; + case TYPE.BINARY_EXPRESSION: + const { left, right, operator } = line; + const leftExpression = evaluateExpression(evaluation, left, index); + const rightExpression = evaluateExpression(evaluation, right, index); + const method = getOperationName(operator); + + return leftExpression[method](rightExpression); + case TYPE.IF_EXPRESSION: + const { test, consequent, alternate } = line; + + return evaluateBooleanExpression(evaluation, test, index) + ? evaluateExpression(evaluation, consequent, index) + : evaluateExpression(evaluation, alternate, index); + default: + return evaluation; + } } /** @@ -159,14 +149,12 @@ function evaluateExpression(evaluation, line, index) { * @return {string} Evaluated expression */ module.exports = function compiler(input, ensure = false) { - const parser = ensure - ? require('../parser/__mocks__') - : require('../parser'); - const ast = parser(input); + const parser = ensure ? require("../parser/__mocks__") : require("../parser"); + const ast = parser(input); - if (ast.type !== TYPE.PROGRAM) { - throw new TypeError('Invalid input generated by parser.'); - } + if (ast.type !== TYPE.PROGRAM) { + throw new TypeError("Invalid input generated by parser."); + } - return ast.body.reduce(evaluateExpression, new Decimal('0')).toFixed(); + return ast.body.reduce(evaluateExpression, new Decimal("0")).toFixed(); }; diff --git a/src/parser/__mocks__/index.js b/src/parser/__mocks__/index.js index dc7c204..af9c009 100644 --- a/src/parser/__mocks__/index.js +++ b/src/parser/__mocks__/index.js @@ -3,29 +3,29 @@ * * This is a mock file to test the tests and compiler. */ -'use strict'; +"use strict"; -const fs = require('fs'); -const path = require('path'); -const peg = require('pegjs'); +const fs = require("fs"); +const path = require("path"); +const peg = require("pegjs"); const grammar = fs.readFileSync( - path.resolve(__dirname, '../../strex-lang.peg'), - { encoding: 'utf8' } + path.resolve(__dirname, "../../strex-lang.peg"), + { encoding: "utf8" } ); const parser = peg.generate(grammar); module.exports = function(input) { - try { - return parser.parse(input); - } catch (exception) { - const { - location: { start }, - message - } = exception; + try { + return parser.parse(input); + } catch (exception) { + const { + location: { start }, + message + } = exception; - throw new SyntaxError( - `Line ${start.line}, column ${start.column}: ${message}` - ); - } + throw new SyntaxError( + `Line ${start.line}, column ${start.column}: ${message}` + ); + } }; diff --git a/src/parser/__mocks__/setup.js b/src/parser/__mocks__/setup.js index 22c5767..79b768e 100644 --- a/src/parser/__mocks__/setup.js +++ b/src/parser/__mocks__/setup.js @@ -1,4 +1,4 @@ /** * Please don't modify! */ -jest.mock('../index.js'); +jest.mock("../index.js"); diff --git a/src/parser/__tests__/phase-01/_README.md b/src/parser/__tests__/phase-01/_README.md index 8f114b5..999a15c 100644 --- a/src/parser/__tests__/phase-01/_README.md +++ b/src/parser/__tests__/phase-01/_README.md @@ -4,12 +4,12 @@ This is the first phase to implement the parser for _StrexLang_. ### Syntax goal -- **Integer** e.g. `4`, `-4580` -- **Float** e.g. `9.0`, `-6.83654`, `0235.5678` -- **Basic arithmetic** with `+`, `-`, `*` and `/` -- **Print out** on empty line -- Whitespace is optional -- Multiplication and division operators have precedence over the addition and subtraction operators +- **Integer** e.g. `4`, `-4580` +- **Float** e.g. `9.0`, `-6.83654`, `0235.5678` +- **Basic arithmetic** with `+`, `-`, `*` and `/` +- **Print out** on empty line +- Whitespace is optional +- Multiplication and division operators have precedence over the addition and subtraction operators ### Test @@ -29,13 +29,13 @@ Results in the following AST: ```json { - "type": "Program", - "body": [ - { - "type": "IntegerLiteral", - "value": "42" - } - ] + "type": "Program", + "body": [ + { + "type": "IntegerLiteral", + "value": "42" + } + ] } ``` @@ -51,13 +51,13 @@ Results in the following AST: ```json { - "type": "Program", - "body": [ - { - "type": "FloatLiteral", - "value": "00034.29786" - } - ] + "type": "Program", + "body": [ + { + "type": "FloatLiteral", + "value": "00034.29786" + } + ] } ``` @@ -73,21 +73,21 @@ Results in the following AST: ```json { - "type": "Program", - "body": [ - { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "1 " - }, - "right": { - "type": "IntegerLiteral", - "value": "2" - }, - "operator": "+" - } - ] + "type": "Program", + "body": [ + { + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "1 " + }, + "right": { + "type": "IntegerLiteral", + "value": "2" + }, + "operator": "+" + } + ] } ``` @@ -99,29 +99,29 @@ Complex example with precedence: ```json { - "type": "Program", - "body": [ - { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "1 " - }, - "right": { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "2 " - }, - "right": { - "type": "IntegerLiteral", - "value": "3" - }, - "operator": "*" - }, - "operator": "+" - } - ] + "type": "Program", + "body": [ + { + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "1 " + }, + "right": { + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "2 " + }, + "right": { + "type": "IntegerLiteral", + "value": "3" + }, + "operator": "*" + }, + "operator": "+" + } + ] } ``` @@ -138,18 +138,18 @@ Results in the following AST: ```json { - "type": "Program", - "body": [ - { - "type": "IntegerLiteral", - "value": "42" - }, - { - "type": "PrintOut", - "value": { - "type": "LastExpression" - } - } - ] + "type": "Program", + "body": [ + { + "type": "IntegerLiteral", + "value": "42" + }, + { + "type": "PrintOut", + "value": { + "type": "LastExpression" + } + } + ] } ``` diff --git a/src/parser/__tests__/phase-01/base.test.js b/src/parser/__tests__/phase-01/base.test.js index 4355616..6856dfa 100644 --- a/src/parser/__tests__/phase-01/base.test.js +++ b/src/parser/__tests__/phase-01/base.test.js @@ -1,60 +1,60 @@ -const parser = require('../../index'); - -describe('parser > base', () => { - describe('body', () => { - test('creates an empty body if input is missing', () => { - const code = ``; - const ast = parser(code); - const expected = { - type: 'Program', - body: [] - }; - - expect(ast).toEqual(expected); - }); - - test('does not throw on JSON.stringify', () => { - const code = ``; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); +const parser = require("../../index"); + +describe("parser > base", () => { + describe("body", () => { + test("creates an empty body if input is missing", () => { + const code = ``; + const ast = parser(code); + const expected = { + type: "Program", + body: [] + }; + + expect(ast).toEqual(expected); }); - describe('print out', () => { - test('creates a print out statement on empty line', () => { - const code = `\n`; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'PrintOut', - value: { type: 'LastExpression' } - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates one print out statement on multiple empty line', () => { - const code = `\n\n`; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'PrintOut', - value: { type: 'LastExpression' } - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('does not throw on JSON.stringify', () => { - const code = `\n\n`; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); + test("does not throw on JSON.stringify", () => { + const code = ``; + expect(() => JSON.stringify(parser(code))).not.toThrow(); }); + }); + + describe("print out", () => { + test("creates a print out statement on empty line", () => { + const code = `\n`; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "PrintOut", + value: { type: "LastExpression" } + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates one print out statement on multiple empty line", () => { + const code = `\n\n`; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "PrintOut", + value: { type: "LastExpression" } + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("does not throw on JSON.stringify", () => { + const code = `\n\n`; + expect(() => JSON.stringify(parser(code))).not.toThrow(); + }); + }); }); diff --git a/src/parser/__tests__/phase-01/type-float.test.js b/src/parser/__tests__/phase-01/type-float.test.js index 049707a..2a3b09d 100644 --- a/src/parser/__tests__/phase-01/type-float.test.js +++ b/src/parser/__tests__/phase-01/type-float.test.js @@ -1,370 +1,370 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > types > float', () => { - describe('basic literal', () => { - test('creates a float expression for the last expression', () => { - const code = '- 20.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '20.1' - }, - operator: '-' - } - ] - }; +describe("parser > types > float", () => { + describe("basic literal", () => { + test("creates a float expression for the last expression", () => { + const code = "- 20.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "20.1" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates a float expression for the last expression without whitespace', () => { - const code = '-5.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '5.5' - }, - operator: '-' - } - ] - }; + test("creates a float expression for the last expression without whitespace", () => { + const code = "-5.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "5.5" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an unsigned float literal', () => { - const code = '3.003332\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'FloatLiteral', - value: '3.003332' - } - ] - }; + test("creates an unsigned float literal", () => { + const code = "3.003332\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "FloatLiteral", + value: "3.003332" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw on JSON.stringify', () => { - const code = `4.8\n`; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); + test("does not throw on JSON.stringify", () => { + const code = `4.8\n`; + expect(() => JSON.stringify(parser(code))).not.toThrow(); }); + }); - describe('without braces', () => { - test('creates a float expression with + operator', () => { - const code = '24811.1 + 5.4\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '24811.1' - }, - right: { - type: 'FloatLiteral', - value: '5.4' - }, - operator: '+' - } - ] - }; + describe("without braces", () => { + test("creates a float expression with + operator", () => { + const code = "24811.1 + 5.4\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "24811.1" + }, + right: { + type: "FloatLiteral", + value: "5.4" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates a float expression with + operator without whitespace', () => { - const code = '24811.1+5.4\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '24811.1' - }, - right: { - type: 'FloatLiteral', - value: '5.4' - }, - operator: '+' - } - ] - }; + test("creates a float expression with + operator without whitespace", () => { + const code = "24811.1+5.4\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "24811.1" + }, + right: { + type: "FloatLiteral", + value: "5.4" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates a float expression with - operator', () => { - const code = '1.1 - 45.56\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.1' - }, - right: { - type: 'FloatLiteral', - value: '45.56' - }, - operator: '-' - } - ] - }; + test("creates a float expression with - operator", () => { + const code = "1.1 - 45.56\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.1" + }, + right: { + type: "FloatLiteral", + value: "45.56" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates a float expression with - operator without whitespace', () => { - const code = '1.1-45.56\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.1' - }, - right: { - type: 'FloatLiteral', - value: '45.56' - }, - operator: '-' - } - ] - }; + test("creates a float expression with - operator without whitespace", () => { + const code = "1.1-45.56\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.1" + }, + right: { + type: "FloatLiteral", + value: "45.56" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates a float expression with / operator', () => { - const code = '36.456 / 6.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '36.456' - }, - right: { - type: 'FloatLiteral', - value: '6.0' - }, - operator: '/' - } - ] - }; + test("creates a float expression with / operator", () => { + const code = "36.456 / 6.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "36.456" + }, + right: { + type: "FloatLiteral", + value: "6.0" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates a float expression with / operator without whitespace', () => { - const code = '36.456/6.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '36.456' - }, - right: { - type: 'FloatLiteral', - value: '6.0' - }, - operator: '/' - } - ] - }; + test("creates a float expression with / operator without whitespace", () => { + const code = "36.456/6.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "36.456" + }, + right: { + type: "FloatLiteral", + value: "6.0" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates a float expression with * operator', () => { - const code = '10.0 * 3.3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '10.0' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '*' - } - ] - }; + test("creates a float expression with * operator", () => { + const code = "10.0 * 3.3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "10.0" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates a float expression with * operator without whitespace', () => { - const code = '10.0*3.3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '10.0' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '*' - } - ] - }; + test("creates a float expression with * operator without whitespace", () => { + const code = "10.0*3.3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "10.0" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); - describe('with all operands', () => { - test('creates an expression with all operands on float', () => { - const code = '1.1 + 2.2 * 3.3 - 4.4 / 5.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.1' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.2' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '*' - }, - operator: '+' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '4.4' - }, - right: { - type: 'FloatLiteral', - value: '5.5' - }, - operator: '/' - }, - operator: '-' - } - ] - }; + describe("with all operands", () => { + test("creates an expression with all operands on float", () => { + const code = "1.1 + 2.2 * 3.3 - 4.4 / 5.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.1" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.2" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: "*" + }, + operator: "+" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "4.4" + }, + right: { + type: "FloatLiteral", + value: "5.5" + }, + operator: "/" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an expression with all operands on float without whitespace', () => { - const code = '1.1+2.2*3.3-4.4/5.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.1' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.2' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '*' - }, - operator: '+' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '4.4' - }, - right: { - type: 'FloatLiteral', - value: '5.5' - }, - operator: '/' - }, - operator: '-' - } - ] - }; + test("creates an expression with all operands on float without whitespace", () => { + const code = "1.1+2.2*3.3-4.4/5.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.1" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.2" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: "*" + }, + operator: "+" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "4.4" + }, + right: { + type: "FloatLiteral", + value: "5.5" + }, + operator: "/" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw on JSON.stringify', () => { - const code = `1.1 + 2.2 * 3.3 - 4.4 / 5.5\n`; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); + test("does not throw on JSON.stringify", () => { + const code = `1.1 + 2.2 * 3.3 - 4.4 / 5.5\n`; + expect(() => JSON.stringify(parser(code))).not.toThrow(); }); + }); }); diff --git a/src/parser/__tests__/phase-01/type-integer.test.js b/src/parser/__tests__/phase-01/type-integer.test.js index 483ddf6..285cf4a 100644 --- a/src/parser/__tests__/phase-01/type-integer.test.js +++ b/src/parser/__tests__/phase-01/type-integer.test.js @@ -1,370 +1,370 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > types > integer', () => { - describe('basic literal', () => { - test('creates an integer expression for the last expression', () => { - const code = '- 2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - } - ] - }; +describe("parser > types > integer", () => { + describe("basic literal", () => { + test("creates an integer expression for the last expression", () => { + const code = "- 2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an integer expression for the last expression without whitespace', () => { - const code = '-5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '-' - } - ] - }; + test("creates an integer expression for the last expression without whitespace", () => { + const code = "-5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an unsigned integer literal', () => { - const code = '3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IntegerLiteral', - value: '3' - } - ] - }; + test("creates an unsigned integer literal", () => { + const code = "3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IntegerLiteral", + value: "3" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw on JSON.stringify', () => { - const code = `568\n`; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); + test("does not throw on JSON.stringify", () => { + const code = `568\n`; + expect(() => JSON.stringify(parser(code))).not.toThrow(); }); + }); - describe('without braces', () => { - test('creates an integer expression with + operator', () => { - const code = '2 + 5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '+' - } - ] - }; + describe("without braces", () => { + test("creates an integer expression with + operator", () => { + const code = "2 + 5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an integer expression with + operator without whitespace', () => { - const code = '2+5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '+' - } - ] - }; + test("creates an integer expression with + operator without whitespace", () => { + const code = "2+5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an integer expression with - operator', () => { - const code = '1 - 45\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '45' - }, - operator: '-' - } - ] - }; + test("creates an integer expression with - operator", () => { + const code = "1 - 45\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "45" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an integer expression with - operator without whitespace', () => { - const code = '1-45\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '45' - }, - operator: '-' - } - ] - }; + test("creates an integer expression with - operator without whitespace", () => { + const code = "1-45\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "45" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an integer expression with / operator', () => { - const code = '36 / 6\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '36' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '/' - } - ] - }; + test("creates an integer expression with / operator", () => { + const code = "36 / 6\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "36" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an integer expression with / operator without whitespace', () => { - const code = '36/6\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '36' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '/' - } - ] - }; + test("creates an integer expression with / operator without whitespace", () => { + const code = "36/6\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "36" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an integer expression with * operator', () => { - const code = '10 * 3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '10' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - } - ] - }; + test("creates an integer expression with * operator", () => { + const code = "10 * 3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "10" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an integer expression with * operator without whitespace', () => { - const code = '10*3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '10' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - } - ] - }; + test("creates an integer expression with * operator without whitespace", () => { + const code = "10*3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "10" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); - describe('with all operands', () => { - test('creates an expression with all operands on integer', () => { - const code = '1 + 2 * 3 - 4 / 5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - }, - operator: '+' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '4' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '/' - }, - operator: '-' - } - ] - }; + describe("with all operands", () => { + test("creates an expression with all operands on integer", () => { + const code = "1 + 2 * 3 - 4 / 5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + }, + operator: "+" + }, + right: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "4" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "/" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an expression with all operands on integer without whitespace', () => { - const code = '1+2*3-4/5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - }, - operator: '+' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '4' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '/' - }, - operator: '-' - } - ] - }; + test("creates an expression with all operands on integer without whitespace", () => { + const code = "1+2*3-4/5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + }, + operator: "+" + }, + right: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "4" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "/" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw on JSON.stringify', () => { - const code = `1 + 2 * 3 - 4 / 5\n`; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); + test("does not throw on JSON.stringify", () => { + const code = `1 + 2 * 3 - 4 / 5\n`; + expect(() => JSON.stringify(parser(code))).not.toThrow(); }); + }); }); diff --git a/src/parser/__tests__/phase-02/_README.md b/src/parser/__tests__/phase-02/_README.md index 162ab84..ae34c3a 100644 --- a/src/parser/__tests__/phase-02/_README.md +++ b/src/parser/__tests__/phase-02/_README.md @@ -4,8 +4,8 @@ This is the second phase to implement the parser for _StrexLang_. ### Syntax goal -- **Combined types** uses integer and float in one expression -- **Braces** to change the precedence of expressions +- **Combined types** uses integer and float in one expression +- **Braces** to change the precedence of expressions ### Test @@ -23,21 +23,21 @@ Integer and float numbers can be used together and always result in float number ```json { - "type": "Program", - "body": [ - { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "2 " - }, - "right": { - "type": "FloatLiteral", - "value": "4.2" - }, - "operator": "+" - } - ] + "type": "Program", + "body": [ + { + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "2 " + }, + "right": { + "type": "FloatLiteral", + "value": "4.2" + }, + "operator": "+" + } + ] } ``` @@ -51,36 +51,36 @@ Braces can be used in arithmetic to define precedence. ```json { - "type": "Program", - "body": [ - { - "type": "BinaryExpression", - "left": { - "type": "BinaryExpression", - "left": { - "type": "FloatLiteral", - "value": "2.2 " - }, - "right": { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "2 " - }, - "right": { - "type": "FloatLiteral", - "value": "3.0" - }, - "operator": "+" - }, - "operator": "*" - }, - "right": { - "type": "IntegerLiteral", - "value": "4" - }, - "operator": "/" - } - ] + "type": "Program", + "body": [ + { + "type": "BinaryExpression", + "left": { + "type": "BinaryExpression", + "left": { + "type": "FloatLiteral", + "value": "2.2 " + }, + "right": { + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "2 " + }, + "right": { + "type": "FloatLiteral", + "value": "3.0" + }, + "operator": "+" + }, + "operator": "*" + }, + "right": { + "type": "IntegerLiteral", + "value": "4" + }, + "operator": "/" + } + ] } ``` diff --git a/src/parser/__tests__/phase-02/type-combined.test.js b/src/parser/__tests__/phase-02/type-combined.test.js index 8175726..2893c3c 100644 --- a/src/parser/__tests__/phase-02/type-combined.test.js +++ b/src/parser/__tests__/phase-02/type-combined.test.js @@ -1,516 +1,516 @@ /* eslint-disable max-len */ -const parser = require('../../index'); - -describe('parser > types > combined', () => { - describe('without braces', () => { - test('creates an expression with + operator on float and integer', () => { - const code = '2 + 4.09\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'FloatLiteral', - value: '4.09' - }, - operator: '+' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates an expression with + operator on float and integer without whitespace', () => { - const code = '2+4.09\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'FloatLiteral', - value: '4.09' - }, - operator: '+' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates an expression with - operator on float and integer', () => { - const code = '1.11 - 23\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.11' - }, - right: { - type: 'IntegerLiteral', - value: '23' - }, - operator: '-' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates an expression with - operator on float and integer without whitespace', () => { - const code = '1.11-23\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.11' - }, - right: { - type: 'IntegerLiteral', - value: '23' - }, - operator: '-' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates an expression with / operator on float and integer', () => { - const code = '98 / 0.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '98' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '/' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates an expression with / operator on float and integer without whitespace', () => { - const code = '98/0.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '98' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '/' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates an expression with * operator on float and integer', () => { - const code = '100 * 3.3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '100' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '*' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates an expression with * operator on float and integer without whitespaces', () => { - const code = '100*3.3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '100' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '*' - } - ] - }; - - expect(ast).toEqual(expected); - }); +const parser = require("../../index"); + +describe("parser > types > combined", () => { + describe("without braces", () => { + test("creates an expression with + operator on float and integer", () => { + const code = "2 + 4.09\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "FloatLiteral", + value: "4.09" + }, + operator: "+" + } + ] + }; + + expect(ast).toEqual(expected); }); - describe('with braces', () => { - test('creates combined expressions if braces are used at the start on float and integer', () => { - const code = '(5 - 2.5) / 2.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '5' - }, - right: { - type: 'FloatLiteral', - value: '2.5' - }, - operator: '-' - }, - right: { - type: 'FloatLiteral', - value: '2.5' - }, - operator: '/' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates combined expressions if braces are used at the start on float and integer without whitespaces', () => { - const code = '(5-2.5)/2.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '5' - }, - right: { - type: 'FloatLiteral', - value: '2.5' - }, - operator: '-' - }, - right: { - type: 'FloatLiteral', - value: '2.5' - }, - operator: '/' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates combined expressions if braces are used in the middle on float and integer', () => { - const code = '2 / (3.2 - 2) + 5.0001\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '3.2' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '/' - }, - right: { - type: 'FloatLiteral', - value: '5.0001' - }, - operator: '+' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates combined expressions if braces are used in the middle on float and integer without whitespaces', () => { - const code = '2/(3.2-2)+5.0001\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '3.2' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '/' - }, - right: { - type: 'FloatLiteral', - value: '5.0001' - }, - operator: '+' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates combined expressions if braces are used at the end on float and integer', () => { - const code = '2 * (0.1 + 3)\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '0.1' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '+' - }, - operator: '*' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates combined expressions if braces are used at the end on float and integer without whitespaces', () => { - const code = '2*(0.1+3)\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '0.1' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '+' - }, - operator: '*' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('does not throw on JSON.stringify', () => { - const code = '2 * (0.1 + 3)\n'; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); + test("creates an expression with + operator on float and integer without whitespace", () => { + const code = "2+4.09\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "FloatLiteral", + value: "4.09" + }, + operator: "+" + } + ] + }; + + expect(ast).toEqual(expected); }); - describe('with all operands', () => { - test('creates an expression with all operands on integer and float', () => { - const code = '1 + 2.2 * 3 - 4.4 / 5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.2' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - }, - operator: '+' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '4.4' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '/' - }, - operator: '-' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('creates an expression with all operands on integer and float without whitespace', () => { - const code = '1+2.2*3-4.4/5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.2' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - }, - operator: '+' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '4.4' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '/' - }, - operator: '-' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('does not throw on JSON.stringify', () => { - const code = '1 + 2.2 * 3 - 4.4 / 5\n'; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); + test("creates an expression with - operator on float and integer", () => { + const code = "1.11 - 23\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.11" + }, + right: { + type: "IntegerLiteral", + value: "23" + }, + operator: "-" + } + ] + }; + + expect(ast).toEqual(expected); }); + + test("creates an expression with - operator on float and integer without whitespace", () => { + const code = "1.11-23\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.11" + }, + right: { + type: "IntegerLiteral", + value: "23" + }, + operator: "-" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates an expression with / operator on float and integer", () => { + const code = "98 / 0.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "98" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: "/" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates an expression with / operator on float and integer without whitespace", () => { + const code = "98/0.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "98" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: "/" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates an expression with * operator on float and integer", () => { + const code = "100 * 3.3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "100" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: "*" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates an expression with * operator on float and integer without whitespaces", () => { + const code = "100*3.3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "100" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: "*" + } + ] + }; + + expect(ast).toEqual(expected); + }); + }); + + describe("with braces", () => { + test("creates combined expressions if braces are used at the start on float and integer", () => { + const code = "(5 - 2.5) / 2.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "5" + }, + right: { + type: "FloatLiteral", + value: "2.5" + }, + operator: "-" + }, + right: { + type: "FloatLiteral", + value: "2.5" + }, + operator: "/" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates combined expressions if braces are used at the start on float and integer without whitespaces", () => { + const code = "(5-2.5)/2.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "5" + }, + right: { + type: "FloatLiteral", + value: "2.5" + }, + operator: "-" + }, + right: { + type: "FloatLiteral", + value: "2.5" + }, + operator: "/" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates combined expressions if braces are used in the middle on float and integer", () => { + const code = "2 / (3.2 - 2) + 5.0001\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "3.2" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "/" + }, + right: { + type: "FloatLiteral", + value: "5.0001" + }, + operator: "+" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates combined expressions if braces are used in the middle on float and integer without whitespaces", () => { + const code = "2/(3.2-2)+5.0001\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "3.2" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "/" + }, + right: { + type: "FloatLiteral", + value: "5.0001" + }, + operator: "+" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates combined expressions if braces are used at the end on float and integer", () => { + const code = "2 * (0.1 + 3)\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "0.1" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "+" + }, + operator: "*" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates combined expressions if braces are used at the end on float and integer without whitespaces", () => { + const code = "2*(0.1+3)\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "0.1" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "+" + }, + operator: "*" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("does not throw on JSON.stringify", () => { + const code = "2 * (0.1 + 3)\n"; + expect(() => JSON.stringify(parser(code))).not.toThrow(); + }); + }); + + describe("with all operands", () => { + test("creates an expression with all operands on integer and float", () => { + const code = "1 + 2.2 * 3 - 4.4 / 5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.2" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + }, + operator: "+" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "4.4" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "/" + }, + operator: "-" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("creates an expression with all operands on integer and float without whitespace", () => { + const code = "1+2.2*3-4.4/5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.2" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + }, + operator: "+" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "4.4" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "/" + }, + operator: "-" + } + ] + }; + + expect(ast).toEqual(expected); + }); + + test("does not throw on JSON.stringify", () => { + const code = "1 + 2.2 * 3 - 4.4 / 5\n"; + expect(() => JSON.stringify(parser(code))).not.toThrow(); + }); + }); }); diff --git a/src/parser/__tests__/phase-02/type-float.test.js b/src/parser/__tests__/phase-02/type-float.test.js index e35a1e4..b1a8cba 100644 --- a/src/parser/__tests__/phase-02/type-float.test.js +++ b/src/parser/__tests__/phase-02/type-float.test.js @@ -1,214 +1,214 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > types > float', () => { - describe('with braces', () => { - test('creates combined float expressions if braces are used at the start', () => { - const code = '(5.6 - 1.0) / 2.4\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '5.6' - }, - right: { - type: 'FloatLiteral', - value: '1.0' - }, - operator: '-' - }, - right: { - type: 'FloatLiteral', - value: '2.4' - }, - operator: '/' - } - ] - }; +describe("parser > types > float", () => { + describe("with braces", () => { + test("creates combined float expressions if braces are used at the start", () => { + const code = "(5.6 - 1.0) / 2.4\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "5.6" + }, + right: { + type: "FloatLiteral", + value: "1.0" + }, + operator: "-" + }, + right: { + type: "FloatLiteral", + value: "2.4" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined float expressions if braces are used at the start without whitespace', () => { - const code = '(5.6-1.0)/2.4\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '5.6' - }, - right: { - type: 'FloatLiteral', - value: '1.0' - }, - operator: '-' - }, - right: { - type: 'FloatLiteral', - value: '2.4' - }, - operator: '/' - } - ] - }; + test("creates combined float expressions if braces are used at the start without whitespace", () => { + const code = "(5.6-1.0)/2.4\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "5.6" + }, + right: { + type: "FloatLiteral", + value: "1.0" + }, + operator: "-" + }, + right: { + type: "FloatLiteral", + value: "2.4" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined float expressions if braces are used in the middle', () => { - const code = '2.2 * (2.1 + 3.0) / 4.9\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.1' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '+' - }, - operator: '*' - }, - right: { - type: 'FloatLiteral', - value: '4.9' - }, - operator: '/' - } - ] - }; + test("creates combined float expressions if braces are used in the middle", () => { + const code = "2.2 * (2.1 + 3.0) / 4.9\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.2" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.1" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "+" + }, + operator: "*" + }, + right: { + type: "FloatLiteral", + value: "4.9" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined float expressions if braces are used in the middle without whitespace', () => { - const code = '2.2*(2.1+3.0)/4.9\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.1' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '+' - }, - operator: '*' - }, - right: { - type: 'FloatLiteral', - value: '4.9' - }, - operator: '/' - } - ] - }; + test("creates combined float expressions if braces are used in the middle without whitespace", () => { + const code = "2.2*(2.1+3.0)/4.9\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.2" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.1" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "+" + }, + operator: "*" + }, + right: { + type: "FloatLiteral", + value: "4.9" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined float expressions if braces are used at the end', () => { - const code = '2.2 * (2.1 + 3.0)\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.1' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '+' - }, - operator: '*' - } - ] - }; + test("creates combined float expressions if braces are used at the end", () => { + const code = "2.2 * (2.1 + 3.0)\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.2" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.1" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "+" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined float expressions if braces are used at the end without whitespace', () => { - const code = '2.2*(2.1+3.0)\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.1' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '+' - }, - operator: '*' - } - ] - }; + test("creates combined float expressions if braces are used at the end without whitespace", () => { + const code = "2.2*(2.1+3.0)\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.2" + }, + right: { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.1" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "+" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); }); diff --git a/src/parser/__tests__/phase-02/type-integer.test.js b/src/parser/__tests__/phase-02/type-integer.test.js index 1a4cfe0..643b57a 100644 --- a/src/parser/__tests__/phase-02/type-integer.test.js +++ b/src/parser/__tests__/phase-02/type-integer.test.js @@ -1,214 +1,214 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > types > integer', () => { - describe('with braces', () => { - test('creates combined integer expressions if braces are used at the start', () => { - const code = '(5 - 1) / 2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '5' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '/' - } - ] - }; +describe("parser > types > integer", () => { + describe("with braces", () => { + test("creates combined integer expressions if braces are used at the start", () => { + const code = "(5 - 1) / 2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "5" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined integer expressions if braces are used at the start without whitespace', () => { - const code = '(5-1)/2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '5' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '/' - } - ] - }; + test("creates combined integer expressions if braces are used at the start without whitespace", () => { + const code = "(5-1)/2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "5" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined integer expressions if braces are used in the middle', () => { - const code = '2 / (3 - 2) + 5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '3' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '/' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '+' - } - ] - }; + test("creates combined integer expressions if braces are used in the middle", () => { + const code = "2 / (3 - 2) + 5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "3" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "/" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined integer expressions if braces are used in the middle without whitespace', () => { - const code = '2/(3-2)+5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '3' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '/' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '+' - } - ] - }; + test("creates combined integer expressions if braces are used in the middle without whitespace", () => { + const code = "2/(3-2)+5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "3" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "/" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined integer expressions if braces are used at the end', () => { - const code = '2 * (2 + 3)\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '+' - }, - operator: '*' - } - ] - }; + test("creates combined integer expressions if braces are used at the end", () => { + const code = "2 * (2 + 3)\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "+" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates combined integer expressions if braces are used at the end without whitespace', () => { - const code = '2*(2+3)\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '+' - }, - operator: '*' - } - ] - }; + test("creates combined integer expressions if braces are used at the end without whitespace", () => { + const code = "2*(2+3)\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "+" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); }); diff --git a/src/parser/__tests__/phase-03/_README.md b/src/parser/__tests__/phase-03/_README.md index fa32f25..03a454e 100644 --- a/src/parser/__tests__/phase-03/_README.md +++ b/src/parser/__tests__/phase-03/_README.md @@ -4,7 +4,7 @@ This is the third phase to implement the parser for _StrexLang_. ### Syntax goal -- **Error handling** for integer and float expressions +- **Error handling** for integer and float expressions ### Test diff --git a/src/parser/__tests__/phase-03/type-combined.test.js b/src/parser/__tests__/phase-03/type-combined.test.js index bebc21e..af1bde1 100644 --- a/src/parser/__tests__/phase-03/type-combined.test.js +++ b/src/parser/__tests__/phase-03/type-combined.test.js @@ -1,61 +1,61 @@ /* eslint-disable max-len */ -const parser = require('../../index'); - -describe('parser > types > combined', () => { - describe('error handling', () => { - test('throws an error if right hand expression on multiple operator is missing for integer and float [1]', () => { - const code = '2.1 + 6 -\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer and float [2]', () => { - const code = '58 + 10.004 - 2 *\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer and float [3]', () => { - const code = '12 + 98.7 /\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer and float [4]', () => { - const code = '2.2 + 31 +\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer and float is missing on two + operations', () => { - const code = '1.1 + + 2\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer and float is missing on two + operations without whitespace', () => { - const code = '1++2.2\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer and float is missing on two - operations', () => { - const code = '10.00 - - 3000\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer and float is missing on two - operations without whitespace', () => { - const code = '1000--30.00\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer and float is missing on two * operations', () => { - const code = '3.3 * * 1\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer and float is missing on two * operations without whitespace', () => { - const code = '3**1.45\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer and float is missing on two / operations', () => { - const code = '3.6 / / 6\n'; - expect(() => parser(code)).toThrow(); - }); +const parser = require("../../index"); + +describe("parser > types > combined", () => { + describe("error handling", () => { + test("throws an error if right hand expression on multiple operator is missing for integer and float [1]", () => { + const code = "2.1 + 6 -\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer and float [2]", () => { + const code = "58 + 10.004 - 2 *\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer and float [3]", () => { + const code = "12 + 98.7 /\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer and float [4]", () => { + const code = "2.2 + 31 +\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer and float is missing on two + operations", () => { + const code = "1.1 + + 2\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer and float is missing on two + operations without whitespace", () => { + const code = "1++2.2\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer and float is missing on two - operations", () => { + const code = "10.00 - - 3000\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer and float is missing on two - operations without whitespace", () => { + const code = "1000--30.00\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer and float is missing on two * operations", () => { + const code = "3.3 * * 1\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer and float is missing on two * operations without whitespace", () => { + const code = "3**1.45\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer and float is missing on two / operations", () => { + const code = "3.6 / / 6\n"; + expect(() => parser(code)).toThrow(); }); + }); }); diff --git a/src/parser/__tests__/phase-03/type-float.test.js b/src/parser/__tests__/phase-03/type-float.test.js index 3a593d0..565787c 100644 --- a/src/parser/__tests__/phase-03/type-float.test.js +++ b/src/parser/__tests__/phase-03/type-float.test.js @@ -1,105 +1,105 @@ /* eslint-disable max-len */ -const parser = require('../../index'); - -describe('parser > types > float', () => { - describe('error handling', () => { - test('does not throw on null division', () => { - const code = '1.3 / 0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.3' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '/' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('throws an error if right hand expression on + operator is missing for float', () => { - const code = '3.1 +\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on - operator is missing for float', () => { - const code = '0.001 -\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on * operator is missing for float', () => { - const code = '9.9 *\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on / operator is missing for float', () => { - const code = '9.9999999999999999 /\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for float [1]', () => { - const code = '1.2 + 4.6 -\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for float [2]', () => { - const code = '1.2 + 4.6 - 4.2 *\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for float [3]', () => { - const code = '1.2 + 3.0 /\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for float [4]', () => { - const code = '2.2 + 3.1 +\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if float is missing on two + operations', () => { - const code = '1.1 + + 2.4\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if float is missing on two + operations without whitespace', () => { - const code = '1.1++2.4\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if float is missing on two - operations', () => { - const code = '10.00 - - 30.00\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if float is missing on two - operations without whitespace', () => { - const code = '10.00--30.00\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if float is missing on two * operations', () => { - const code = '0.3 * * 1.1\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if float is missing on two * operations without whitespace', () => { - const code = '0.3**1.1\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if float is missing on two / operations', () => { - const code = '36.45 / / 6.66\n'; - expect(() => parser(code)).toThrow(); - }); +const parser = require("../../index"); + +describe("parser > types > float", () => { + describe("error handling", () => { + test("does not throw on null division", () => { + const code = "1.3 / 0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.3" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: "/" + } + ] + }; + + expect(ast).toEqual(expected); }); + + test("throws an error if right hand expression on + operator is missing for float", () => { + const code = "3.1 +\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on - operator is missing for float", () => { + const code = "0.001 -\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on * operator is missing for float", () => { + const code = "9.9 *\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on / operator is missing for float", () => { + const code = "9.9999999999999999 /\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for float [1]", () => { + const code = "1.2 + 4.6 -\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for float [2]", () => { + const code = "1.2 + 4.6 - 4.2 *\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for float [3]", () => { + const code = "1.2 + 3.0 /\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for float [4]", () => { + const code = "2.2 + 3.1 +\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if float is missing on two + operations", () => { + const code = "1.1 + + 2.4\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if float is missing on two + operations without whitespace", () => { + const code = "1.1++2.4\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if float is missing on two - operations", () => { + const code = "10.00 - - 30.00\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if float is missing on two - operations without whitespace", () => { + const code = "10.00--30.00\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if float is missing on two * operations", () => { + const code = "0.3 * * 1.1\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if float is missing on two * operations without whitespace", () => { + const code = "0.3**1.1\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if float is missing on two / operations", () => { + const code = "36.45 / / 6.66\n"; + expect(() => parser(code)).toThrow(); + }); + }); }); diff --git a/src/parser/__tests__/phase-03/type-integer.test.js b/src/parser/__tests__/phase-03/type-integer.test.js index 12a77ba..d5bfa02 100644 --- a/src/parser/__tests__/phase-03/type-integer.test.js +++ b/src/parser/__tests__/phase-03/type-integer.test.js @@ -1,105 +1,105 @@ /* eslint-disable max-len */ -const parser = require('../../index'); - -describe('parser > types > integer', () => { - describe('error handling', () => { - test('does not throw on null division', () => { - const code = '1 / 0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '/' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('throws an error if right hand expression on + operator is missing for integer', () => { - const code = '3 +\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on - operator is missing for integer', () => { - const code = '1 -\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on * operator is missing for integer', () => { - const code = '18754 *\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on / operator is missing for integer', () => { - const code = '9999999999999999 /\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer [1]', () => { - const code = '2 + 6 -\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer [2]', () => { - const code = '58 + 10004 - 2 *\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer [3]', () => { - const code = '12 + 987 /\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer [4]', () => { - const code = '22 + 31 +\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer is missing on two + operations', () => { - const code = '1 + + 2\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer is missing on two + operations without whitespace', () => { - const code = '1++2\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer is missing on two - operations', () => { - const code = '1000 - - 3000\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer is missing on two - operations without whitespace', () => { - const code = '1000--3000\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer is missing on two * operations', () => { - const code = '3 * * 1\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer is missing on two * operations without whitespace', () => { - const code = '3**1\n'; - expect(() => parser(code)).toThrow(); - }); - - test('throws an error if integer is missing on two / operations', () => { - const code = '36 / / 6\n'; - expect(() => parser(code)).toThrow(); - }); +const parser = require("../../index"); + +describe("parser > types > integer", () => { + describe("error handling", () => { + test("does not throw on null division", () => { + const code = "1 / 0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: "/" + } + ] + }; + + expect(ast).toEqual(expected); }); + + test("throws an error if right hand expression on + operator is missing for integer", () => { + const code = "3 +\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on - operator is missing for integer", () => { + const code = "1 -\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on * operator is missing for integer", () => { + const code = "18754 *\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on / operator is missing for integer", () => { + const code = "9999999999999999 /\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer [1]", () => { + const code = "2 + 6 -\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer [2]", () => { + const code = "58 + 10004 - 2 *\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer [3]", () => { + const code = "12 + 987 /\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer [4]", () => { + const code = "22 + 31 +\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer is missing on two + operations", () => { + const code = "1 + + 2\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer is missing on two + operations without whitespace", () => { + const code = "1++2\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer is missing on two - operations", () => { + const code = "1000 - - 3000\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer is missing on two - operations without whitespace", () => { + const code = "1000--3000\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer is missing on two * operations", () => { + const code = "3 * * 1\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer is missing on two * operations without whitespace", () => { + const code = "3**1\n"; + expect(() => parser(code)).toThrow(); + }); + + test("throws an error if integer is missing on two / operations", () => { + const code = "36 / / 6\n"; + expect(() => parser(code)).toThrow(); + }); + }); }); diff --git a/src/parser/__tests__/phase-04/_README.md b/src/parser/__tests__/phase-04/_README.md index 5601e13..a5d18e7 100644 --- a/src/parser/__tests__/phase-04/_README.md +++ b/src/parser/__tests__/phase-04/_README.md @@ -4,7 +4,7 @@ This is the fourth phase to implement the parser for _StrexLang_. ### Syntax goal -- **Basic if-expressions** e.g. `= 1 ? + 2 : + 3` +- **Basic if-expressions** e.g. `= 1 ? + 2 : + 3` ### Test @@ -24,48 +24,48 @@ The expression after `?` is the true-case, after `:` the false-case and both can ```json { - "type": "Program", - "body": [ - { - "type": "IfExpression", - "test": { - "type": "BooleanExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "1 " - }, - "operator": "=" - }, - "consequent": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "2 " - } - ], - "operator": "+" - }, - "alternate": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "3" - } - ], - "operator": "+" - } - } - ] + "type": "Program", + "body": [ + { + "type": "IfExpression", + "test": { + "type": "BooleanExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "1 " + }, + "operator": "=" + }, + "consequent": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "2 " + } + ], + "operator": "+" + }, + "alternate": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "3" + } + ], + "operator": "+" + } + } + ] } ``` diff --git a/src/parser/__tests__/phase-04/expression-if-test.js b/src/parser/__tests__/phase-04/expression-if-test.js index f0784f1..bb7a77e 100644 --- a/src/parser/__tests__/phase-04/expression-if-test.js +++ b/src/parser/__tests__/phase-04/expression-if-test.js @@ -1,294 +1,294 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > expressions > if', () => { - describe('basic behaviour', () => { - test('creates an if-expression with integer', () => { - const code = '= 1 ? + 2 : - 3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; +describe("parser > expressions > if", () => { + describe("basic behaviour", () => { + test("creates an if-expression with integer", () => { + const code = "= 1 ? + 2 : - 3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with integer without whitespace', () => { - const code = '=1?+2:-3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression with integer without whitespace", () => { + const code = "=1?+2:-3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with float', () => { - const code = '= 1.1 ? * 2.5 : - 3.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.5' - }, - operator: '*' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression with float", () => { + const code = "= 1.1 ? * 2.5 : - 3.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.5" + }, + operator: "*" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with float without whitespace', () => { - const code = '=1.1?+2.5:-3.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression with float without whitespace", () => { + const code = "=1.1?+2.5:-3.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with float and integer', () => { - const code = '= 1 ? + 2.5 : - 3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression with float and integer", () => { + const code = "= 1 ? + 2.5 : - 3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with float and integer without whitespace', () => { - const code = '=1?+2.5:-3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression with float and integer without whitespace", () => { + const code = "=1?+2.5:-3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); }); diff --git a/src/parser/__tests__/phase-05/_README.md b/src/parser/__tests__/phase-05/_README.md index 237cace..4206099 100644 --- a/src/parser/__tests__/phase-05/_README.md +++ b/src/parser/__tests__/phase-05/_README.md @@ -4,7 +4,7 @@ This is the fifth phase to implement the parser for _StrexLang_. ### Syntax goal -- **sub if-expressions** e.g. `> 1 ? = 2 ? -2 : -3 : - 6` +- **sub if-expressions** e.g. `> 1 ? = 2 ? -2 : -3 : - 6` ### Test @@ -22,75 +22,75 @@ Now both expression for the true- and false-case can be if-expressions itself. ```json { - "type": "Program", - "body": [ - { - "type": "IfExpression", - "test": { - "type": "BooleanExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "1 " - }, - "operator": ">" - }, - "consequent": { - "type": "IfExpression", - "test": { - "type": "BooleanExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "2 " - }, - "operator": "=" - }, - "consequent": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "2 " - } - ], - "operator": "-" - }, - "alternate": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "3 " - } - ], - "operator": "-" - } - }, - "alternate": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "6" - } - ], - "operator": "-" + "type": "Program", + "body": [ + { + "type": "IfExpression", + "test": { + "type": "BooleanExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "1 " + }, + "operator": ">" + }, + "consequent": { + "type": "IfExpression", + "test": { + "type": "BooleanExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "2 " + }, + "operator": "=" + }, + "consequent": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "2 " } + ], + "operator": "-" + }, + "alternate": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "3 " + } + ], + "operator": "-" } - ] + }, + "alternate": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "6" + } + ], + "operator": "-" + } + } + ] } ``` diff --git a/src/parser/__tests__/phase-05/expression-if-test.js b/src/parser/__tests__/phase-05/expression-if-test.js index 605a993..dbbc3ee 100644 --- a/src/parser/__tests__/phase-05/expression-if-test.js +++ b/src/parser/__tests__/phase-05/expression-if-test.js @@ -1,882 +1,882 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > expressions > if', () => { - describe('with sub-if-expressions', () => { - test('creates an if-expression with integer including a sub-if-expressions for "consequent"', () => { - const code = '> 1 ? = 2 ? -2 : -3 : - 6\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - consequent: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '-' - } - } - ] - }; +describe("parser > expressions > if", () => { + describe("with sub-if-expressions", () => { + test('creates an if-expression with integer including a sub-if-expressions for "consequent"', () => { + const code = "> 1 ? = 2 ? -2 : -3 : - 6\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + consequent: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with integer including a sub-if-expressions for "consequent" without whitespace', () => { - const code = '>1?=2?-2:-3:-6\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - consequent: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with integer including a sub-if-expressions for "consequent" without whitespace', () => { + const code = ">1?=2?-2:-3:-6\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + consequent: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with integer including a sub-if-expressions for "alternate"', () => { - const code = '> 1 ? - 6 : = 2 ? -2 : -3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '-' - }, - alternate: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - } - ] - }; + test('creates an if-expression with integer including a sub-if-expressions for "alternate"', () => { + const code = "> 1 ? - 6 : = 2 ? -2 : -3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "-" + }, + alternate: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with integer including a sub-if-expressions for "alternate" without whitespace', () => { - const code = '>1?-6:=2?-2:-3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '-' - }, - alternate: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - } - ] - }; + test('creates an if-expression with integer including a sub-if-expressions for "alternate" without whitespace', () => { + const code = ">1?-6:=2?-2:-3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "-" + }, + alternate: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with float including a sub-if-expressions for "consequent"', () => { - const code = '> 1.1 ? = 2.67 ? -2.0 : -3.0001 : - 65.34\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '>' - }, - consequent: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.67' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.0' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0001' - }, - operator: '-' - } - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '65.34' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with float including a sub-if-expressions for "consequent"', () => { + const code = "> 1.1 ? = 2.67 ? -2.0 : -3.0001 : - 65.34\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: ">" + }, + consequent: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.67" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.0" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0001" + }, + operator: "-" + } + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "65.34" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with float including a sub-if-expressions for "consequent" without whitespace', () => { - const code = '>1.1?=2.67?-2.0:-3.0001:-65.34\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '>' - }, - consequent: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.67' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.0' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0001' - }, - operator: '-' - } - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '65.34' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with float including a sub-if-expressions for "consequent" without whitespace', () => { + const code = ">1.1?=2.67?-2.0:-3.0001:-65.34\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: ">" + }, + consequent: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.67" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.0" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0001" + }, + operator: "-" + } + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "65.34" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with float including a sub-if-expressions for "alternate"', () => { - const code = '> 1.4 ? - 6.66 : = 2.2 ? -24.0 : -3.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.4' - }, - operator: '>' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '6.66' - }, - operator: '-' - }, - alternate: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '24.0' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.1' - }, - operator: '-' - } - } - } - ] - }; + test('creates an if-expression with float including a sub-if-expressions for "alternate"', () => { + const code = "> 1.4 ? - 6.66 : = 2.2 ? -24.0 : -3.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.4" + }, + operator: ">" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "6.66" + }, + operator: "-" + }, + alternate: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "24.0" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.1" + }, + operator: "-" + } + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with float including a sub-if-expressions for "alternate" without whitespace', () => { - const code = '>1.4?-6.66:=2.2?-24.0:-3.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.4' - }, - operator: '>' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '6.66' - }, - operator: '-' - }, - alternate: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '24.0' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.1' - }, - operator: '-' - } - } - } - ] - }; + test('creates an if-expression with float including a sub-if-expressions for "alternate" without whitespace', () => { + const code = ">1.4?-6.66:=2.2?-24.0:-3.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.4" + }, + operator: ">" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "6.66" + }, + operator: "-" + }, + alternate: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "24.0" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.1" + }, + operator: "-" + } + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with integer and float including a sub-if-expressions for "consequent"', () => { - const code = '> 1 ? = 2.67 ? -2 : -3.0001 : * 6533\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - consequent: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.67' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0001' - }, - operator: '-' - } - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '6533' - }, - operator: '*' - } - } - ] - }; + test('creates an if-expression with integer and float including a sub-if-expressions for "consequent"', () => { + const code = "> 1 ? = 2.67 ? -2 : -3.0001 : * 6533\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + consequent: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.67" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0001" + }, + operator: "-" + } + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "6533" + }, + operator: "*" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with integer and float including a sub-if-expressions for "consequent" without whitespace', () => { - const code = '>1?=2.67?-2:-3.0001:*6533\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - consequent: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.67' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0001' - }, - operator: '-' - } - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '6533' - }, - operator: '*' - } - } - ] - }; + test('creates an if-expression with integer and float including a sub-if-expressions for "consequent" without whitespace', () => { + const code = ">1?=2.67?-2:-3.0001:*6533\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + consequent: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.67" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0001" + }, + operator: "-" + } + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "6533" + }, + operator: "*" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with integer and float including a sub-if-expressions for "alternate"', () => { - const code = '> 1.4 ? - 6 : = 2.2 ? -240 : / 3.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.4' - }, - operator: '>' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '-' - }, - alternate: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '240' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.1' - }, - operator: '/' - } - } - } - ] - }; + test('creates an if-expression with integer and float including a sub-if-expressions for "alternate"', () => { + const code = "> 1.4 ? - 6 : = 2.2 ? -240 : / 3.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.4" + }, + operator: ">" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "-" + }, + alternate: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "240" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.1" + }, + operator: "/" + } + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with integer and float including a sub-if-expressions for "alternate" without whitespaces', () => { - const code = '>1.4?-6:=2.2?-240:/3.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.4' - }, - operator: '>' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '-' - }, - alternate: { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '240' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.1' - }, - operator: '/' - } - } - } - ] - }; + test('creates an if-expression with integer and float including a sub-if-expressions for "alternate" without whitespaces', () => { + const code = ">1.4?-6:=2.2?-240:/3.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.4" + }, + operator: ">" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "-" + }, + alternate: { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "240" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.1" + }, + operator: "/" + } + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); }); diff --git a/src/parser/__tests__/phase-06/_README.md b/src/parser/__tests__/phase-06/_README.md index 355c0ed..37d52f4 100644 --- a/src/parser/__tests__/phase-06/_README.md +++ b/src/parser/__tests__/phase-06/_README.md @@ -4,9 +4,9 @@ This is the sixth phase to implement the parser for _StrexLang_. ### Syntax goal -- **if-expressions with "or"** e.g. `= 1 | > 2 ? + 2 : + 3` -- **if-expressions with "and"** e.g. `< 4 & > 1 ? + 2 : + 3` -- **if-expressions with "or" and "and"** e.g. `= 1 | > 2 & < 3 ? + 2 : + 3` +- **if-expressions with "or"** e.g. `= 1 | > 2 ? + 2 : + 3` +- **if-expressions with "and"** e.g. `< 4 & > 1 ? + 2 : + 3` +- **if-expressions with "or" and "and"** e.g. `= 1 | > 2 & < 3 ? + 2 : + 3` ### Test @@ -24,54 +24,54 @@ The `|` or-operator can be used to test against multiple boolean expressions whe ```json { - "type": "Program", - "body": [ - { - "type": "IfExpression", - "test": { - "type": "BooleanExpression", - "left": { - "type": "BooleanExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "1 " - }, - "operator": "=" - }, - "right": undefined, - "operator": "|" - }, - "consequent": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "2 " - } - ], - "operator": "+" - }, - "alternate": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "3" - } - ], - "operator": "/" - } - } - ] + "type": "Program", + "body": [ + { + "type": "IfExpression", + "test": { + "type": "BooleanExpression", + "left": { + "type": "BooleanExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "1 " + }, + "operator": "=" + }, + "right": undefined, + "operator": "|" + }, + "consequent": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "2 " + } + ], + "operator": "+" + }, + "alternate": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "3" + } + ], + "operator": "/" + } + } + ] } ``` @@ -85,54 +85,54 @@ The `&` and-operator can be used to test against multiple boolean expressions th ```json { - "type": "Program", - "body": [ - { - "type": "IfExpression", - "test": { - "type": "BooleanExpression", - "left": { - "type": "BooleanExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "4 " - }, - "operator": "<" - }, - "right": undefined, - "operator": "&" - }, - "consequent": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "3 " - } - ], - "operator": "*" - }, - "alternate": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "4" - } - ], - "operator": "/" - } - } - ] + "type": "Program", + "body": [ + { + "type": "IfExpression", + "test": { + "type": "BooleanExpression", + "left": { + "type": "BooleanExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "4 " + }, + "operator": "<" + }, + "right": undefined, + "operator": "&" + }, + "consequent": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "3 " + } + ], + "operator": "*" + }, + "alternate": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "4" + } + ], + "operator": "/" + } + } + ] } ``` @@ -146,58 +146,58 @@ This is the combination of or- and and-operator for if-expressions. ```json { - "type": "Program", - "body": [ - { - "type": "IfExpression", - "test": { - "type": "BooleanExpression", - "left": { - "type": "BooleanExpression", - "left": { - "type": "BooleanExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "1 " - }, - "operator": ">" - }, - "right": undefined, - "operator": "&" - }, - "right": undefined, - "operator": "|" + "type": "Program", + "body": [ + { + "type": "IfExpression", + "test": { + "type": "BooleanExpression", + "left": { + "type": "BooleanExpression", + "left": { + "type": "BooleanExpression", + "left": { + "type": "LastExpression" }, - "consequent": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "1 " - } - ], - "operator": "+" + "right": { + "type": "IntegerLiteral", + "value": "1 " }, - "alternate": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": [ - { - "type": "IntegerLiteral", - "value": "1" - } - ], - "operator": "-" - } - } - ] + "operator": ">" + }, + "right": undefined, + "operator": "&" + }, + "right": undefined, + "operator": "|" + }, + "consequent": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "1 " + } + ], + "operator": "+" + }, + "alternate": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": [ + { + "type": "IntegerLiteral", + "value": "1" + } + ], + "operator": "-" + } + } + ] } ``` diff --git a/src/parser/__tests__/phase-06/expression-if-test.js b/src/parser/__tests__/phase-06/expression-if-test.js index 27bbdc7..c2b5fdb 100644 --- a/src/parser/__tests__/phase-06/expression-if-test.js +++ b/src/parser/__tests__/phase-06/expression-if-test.js @@ -1,2259 +1,2259 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > expressions > if', () => { - describe('with | as "or" operator', () => { - test('creates an if-expression with two "or" tests on integer', () => { - const code = '= 1 | > 3 ? + 2 : / 3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '/' - } - } - ] - }; +describe("parser > expressions > if", () => { + describe('with | as "or" operator', () => { + test('creates an if-expression with two "or" tests on integer', () => { + const code = "= 1 | > 3 ? + 2 : / 3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "/" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "or" tests on integer without whitespace', () => { - const code = '=1|>3?+2:-3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "or" tests on integer without whitespace', () => { + const code = "=1|>3?+2:-3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "or" tests on float', () => { - const code = '= 1.1 | > 3.3 ? + 2.2 : - 3.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "or" tests on float', () => { + const code = "= 1.1 | > 3.3 ? + 2.2 : - 3.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "or" tests on float without whitespace', () => { - const code = '=1.1|>3.3?+2.2:-3.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "or" tests on float without whitespace', () => { + const code = "=1.1|>3.3?+2.2:-3.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "or" tests on integer and float', () => { - const code = '= 0 | > 3.3 ? + 2 : - 3.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "or" tests on integer and float', () => { + const code = "= 0 | > 3.3 ? + 2 : - 3.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "or" tests on integer and float without whitespace', () => { - const code = '=0|>3.3?+2:-3.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.0' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "or" tests on integer and float without whitespace', () => { + const code = "=0|>3.3?+2:-3.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.0" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "or" tests on integer', () => { - const code = '= 1 | > 3 | < - 2 ? + 2 : - 3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '>' - }, - operator: '|' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "or" tests on integer', () => { + const code = "= 1 | > 3 | < - 2 ? + 2 : - 3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: ">" + }, + operator: "|" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "or" tests on integer without whitespace', () => { - const code = '=1|>3|<-2?+2:-3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '>' - }, - operator: '|' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "or" tests on integer without whitespace', () => { + const code = "=1|>3|<-2?+2:-3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: ">" + }, + operator: "|" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "or" tests on float', () => { - const code = '= 1.1 | > 3.3 | < -2.2 ? + 2.34 : - 3.01\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '|' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.34' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.01' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "or" tests on float', () => { + const code = "= 1.1 | > 3.3 | < -2.2 ? + 2.34 : - 3.01\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "|" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.34" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.01" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "or" tests on float without whitespace', () => { - const code = '=1.1|>3.3|<-2.2?+2.34:-3.01\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '|' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.34' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.01' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "or" tests on float without whitespace', () => { + const code = "=1.1|>3.3|<-2.2?+2.34:-3.01\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "|" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.34" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.01" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "or" tests on integer and float', () => { - const code = '= 1 | > 3.3 | < -2 ? + 2.34 : - 3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '|' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.34' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "or" tests on integer and float', () => { + const code = "= 1 | > 3.3 | < -2 ? + 2.34 : - 3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "|" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.34" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "or" tests on integer and float without whitespace', () => { - const code = '=1|>3.3|<-2?+2.34:-3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '|' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.34' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "or" tests on integer and float without whitespace', () => { + const code = "=1|>3.3|<-2?+2.34:-3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "|" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.34" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); - describe('with & as "and" operator', () => { - test('creates an if-expression with two "and" tests on integer', () => { - const code = '< 4 & > 1 ? * 3 : / 4\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '<' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '/' - } - } - ] - }; + describe('with & as "and" operator', () => { + test('creates an if-expression with two "and" tests on integer', () => { + const code = "< 4 & > 1 ? * 3 : / 4\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "<" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "/" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "and" tests on integer without whitespace', () => { - const code = '<4&>1?*3:/4\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '<' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '/' - } - } - ] - }; + test('creates an if-expression with two "and" tests on integer without whitespace', () => { + const code = "<4&>1?*3:/4\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "<" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "/" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "and" tests on float', () => { - const code = '> 0.1 & > 1.2 ? + 1.5 : - 1.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.2' - }, - operator: '>' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "and" tests on float', () => { + const code = "> 0.1 & > 1.2 ? + 1.5 : - 1.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.2" + }, + operator: ">" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "and" tests on float without whitespace', () => { - const code = '>0.1&>1.2?+1.5:-1.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.2' - }, - operator: '>' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "and" tests on float without whitespace', () => { + const code = ">0.1&>1.2?+1.5:-1.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.2" + }, + operator: ">" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "and" tests on integer and float', () => { - const code = '> 0 & > 1.2 ? + 1 : - 1.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.2' - }, - operator: '>' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "and" tests on integer and float', () => { + const code = "> 0 & > 1.2 ? + 1 : - 1.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.2" + }, + operator: ">" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with two "and" tests on integer and float without whitespace', () => { - const code = '>0&>1.2?+1:-1.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.2' - }, - operator: '>' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with two "and" tests on integer and float without whitespace', () => { + const code = ">0&>1.2?+1:-1.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.2" + }, + operator: ">" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "and" tests on integer', () => { - const code = '= 1 & > 3 & < -1 ? + 2 : - 2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '>' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - }, - operator: '<' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "and" tests on integer', () => { + const code = "= 1 & > 3 & < -1 ? + 2 : - 2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: ">" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + }, + operator: "<" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "and" tests on integer without whitespace', () => { - const code = '=1&>3&<-1?+2:-2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '>' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - }, - operator: '<' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "and" tests on integer without whitespace', () => { + const code = "=1&>3&<-1?+2:-2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: ">" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + }, + operator: "<" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "and" tests on float', () => { - const code = '= 1.1 & > 3.3 & < -2.2 ? + 2.34 : - 3.01\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.34' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.01' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "and" tests on float', () => { + const code = "= 1.1 & > 3.3 & < -2.2 ? + 2.34 : - 3.01\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.34" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.01" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "and" tests on float without whitespace', () => { - const code = '=1.1&>3.3&<-2.2?+2.34:-3.01\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.34' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.01' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "and" tests on float without whitespace', () => { + const code = "=1.1&>3.3&<-2.2?+2.34:-3.01\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.34" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.01" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "and" tests on integer and float', () => { - const code = '= 1 & > 3.3 & < -2 ? + 2.34 : - 3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.34' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "and" tests on integer and float', () => { + const code = "= 1 & > 3.3 & < -2 ? + 2.34 : - 3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.34" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression with multiple "and" tests on integer and float without whitespace', () => { - const code = '=1&>3.3&<-2?+2.34:-3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '3.3' - }, - operator: '>' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - operator: '<' - }, - operator: '&' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.34' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - } - } - ] - }; + test('creates an if-expression with multiple "and" tests on integer and float without whitespace', () => { + const code = "=1&>3.3&<-2?+2.34:-3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "3.3" + }, + operator: ">" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + operator: "<" + }, + operator: "&" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.34" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); - describe('with & and | operator', () => { - test('creates an if-expression on integer', () => { - const code = '< 4 & > 1 | = 1 ? * 3 : / 4\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '<' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '/' - } - } - ] - }; + describe("with & and | operator", () => { + test("creates an if-expression on integer", () => { + const code = "< 4 & > 1 | = 1 ? * 3 : / 4\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "<" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "/" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression on integer without whitespace', () => { - const code = '<4&>1|=1?*3:/4\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '<' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '*' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '/' - } - } - ] - }; + test("creates an if-expression on integer without whitespace", () => { + const code = "<4&>1|=1?*3:/4\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "<" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "*" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "/" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression on float', () => { - const code = '> 0.1 & < 1.2 | > 5.5 ? + 1.5 : - 1.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.2' - }, - operator: '<' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '5.5' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression on float", () => { + const code = "> 0.1 & < 1.2 | > 5.5 ? + 1.5 : - 1.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.2" + }, + operator: "<" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "5.5" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression on float without whitespaces', () => { - const code = '>0.1&<1.2|>5.5?+1.5:-1.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.2' - }, - operator: '<' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '5.5' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression on float without whitespaces", () => { + const code = ">0.1&<1.2|>5.5?+1.5:-1.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.2" + }, + operator: "<" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "5.5" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression on integer and float', () => { - const code = '> 1 & < 1.2 | > 5 ? + 1.5 : - 1.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.2' - }, - operator: '<' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression on integer and float", () => { + const code = "> 1 & < 1.2 | > 5 ? + 1.5 : - 1.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.2" + }, + operator: "<" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates an if-expression on integer and float without whitespace', () => { - const code = '> 1 & < 1.2 | > 5 ? + 1.5 : - 1.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.2' - }, - operator: '<' - }, - operator: '&' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '>' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '-' - } - } - ] - }; + test("creates an if-expression on integer and float without whitespace", () => { + const code = "> 1 & < 1.2 | > 5 ? + 1.5 : - 1.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.2" + }, + operator: "<" + }, + operator: "&" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: ">" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw on JSON.stringify', () => { - const code = `> 1 & < 1.2 | > 5 ? + 1.5 : - 1.5\n`; - expect(() => JSON.stringify(parser(code))).not.toThrow(); - }); + test("does not throw on JSON.stringify", () => { + const code = `> 1 & < 1.2 | > 5 ? + 1.5 : - 1.5\n`; + expect(() => JSON.stringify(parser(code))).not.toThrow(); }); + }); }); diff --git a/src/parser/__tests__/phase-07/_README.md b/src/parser/__tests__/phase-07/_README.md index 11c07c6..8bfd73e 100644 --- a/src/parser/__tests__/phase-07/_README.md +++ b/src/parser/__tests__/phase-07/_README.md @@ -4,7 +4,7 @@ This is the seventh phase to implement the parser for _StrexLang_. ### Syntax goal -- **Error messages for if-expressions** +- **Error messages for if-expressions** ### Test diff --git a/src/parser/__tests__/phase-07/expression-if-test.js b/src/parser/__tests__/phase-07/expression-if-test.js index 95a22ab..146e9e5 100644 --- a/src/parser/__tests__/phase-07/expression-if-test.js +++ b/src/parser/__tests__/phase-07/expression-if-test.js @@ -1,336 +1,336 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > expressions > if', () => { - describe('error handling', () => { - test('throws an error if if-expression is missing the test with integer', () => { - const code = '? + 2 : - 3\n'; - expect(() => parser(code)).toThrow(); - }); +describe("parser > expressions > if", () => { + describe("error handling", () => { + test("throws an error if if-expression is missing the test with integer", () => { + const code = "? + 2 : - 3\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the test with integer without whitespace', () => { - const code = '?+2:-3\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the test with integer without whitespace", () => { + const code = "?+2:-3\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the test with float', () => { - const code = '? + 2.001 : - 3.1\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the test with float", () => { + const code = "? + 2.001 : - 3.1\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the test with float without whitespace', () => { - const code = '?+2.001:-3.1\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the test with float without whitespace", () => { + const code = "?+2.001:-3.1\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the test with integer and float', () => { - const code = '? + 2.001 : - 3\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the test with integer and float", () => { + const code = "? + 2.001 : - 3\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the test with integer and float without whitespace', () => { - const code = '?+2.001:-3\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the test with integer and float without whitespace", () => { + const code = "?+2.001:-3\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the consequent with integer', () => { - const code = '= 1 ? : - 3\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the consequent with integer", () => { + const code = "= 1 ? : - 3\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the consequent with integer without whitespace', () => { - const code = '=1?:-3\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the consequent with integer without whitespace", () => { + const code = "=1?:-3\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the consequent with float', () => { - const code = '= 1.0 ? : - 3.0\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the consequent with float", () => { + const code = "= 1.0 ? : - 3.0\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the consequent with float without whitespace', () => { - const code = '=1.0?:-3.0\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the consequent with float without whitespace", () => { + const code = "=1.0?:-3.0\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the consequent with integer and float', () => { - const code = '= 1 ? : - 3.0\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the consequent with integer and float", () => { + const code = "= 1 ? : - 3.0\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the consequent with integer and float without whitespace', () => { - const code = '=1?:-3.0\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the consequent with integer and float without whitespace", () => { + const code = "=1?:-3.0\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the alternate with integer', () => { - const code = '= 1 ? + 2 :\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the alternate with integer", () => { + const code = "= 1 ? + 2 :\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the alternate with integer without whitespace', () => { - const code = '=1?+2:\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the alternate with integer without whitespace", () => { + const code = "=1?+2:\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the alternate with float', () => { - const code = '= 1.23 ? + 2.05 :\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the alternate with float", () => { + const code = "= 1.23 ? + 2.05 :\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the alternate with float without whitespace', () => { - const code = '=1.23?+2.05:\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the alternate with float without whitespace", () => { + const code = "=1.23?+2.05:\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the alternate with integer and float', () => { - const code = '= 1.23 ? + 2 :\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the alternate with integer and float", () => { + const code = "= 1.23 ? + 2 :\n"; + expect(() => parser(code)).toThrow(); + }); - test('throws an error if if-expression is missing the alternate with integer and float without whitespace', () => { - const code = '=1.23?+2:\n'; - expect(() => parser(code)).toThrow(); - }); + test("throws an error if if-expression is missing the alternate with integer and float without whitespace", () => { + const code = "=1.23?+2:\n"; + expect(() => parser(code)).toThrow(); + }); - test('does not throw if if-expression is missing the alternate operator with integer', () => { - const code = '= 1 ? + 2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'LastExpression' - } - } - ] - }; + test("does not throw if if-expression is missing the alternate operator with integer", () => { + const code = "= 1 ? + 2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw if if-expression is missing the alternate operator with integer without whitespace', () => { - const code = '=1?+2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'LastExpression' - } - } - ] - }; + test("does not throw if if-expression is missing the alternate operator with integer without whitespace", () => { + const code = "=1?+2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw if if-expression is missing the alternate operator with float', () => { - const code = '= 1.23 ? + 2.05\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.23' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.05' - }, - operator: '+' - }, - alternate: { - type: 'LastExpression' - } - } - ] - }; + test("does not throw if if-expression is missing the alternate operator with float", () => { + const code = "= 1.23 ? + 2.05\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.23" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.05" + }, + operator: "+" + }, + alternate: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw if if-expression is missing the alternate operator with float without whitespace', () => { - const code = '=1.23?+2.05\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.23' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '2.05' - }, - operator: '+' - }, - alternate: { - type: 'LastExpression' - } - } - ] - }; + test("does not throw if if-expression is missing the alternate operator with float without whitespace", () => { + const code = "=1.23?+2.05\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.23" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "2.05" + }, + operator: "+" + }, + alternate: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw if if-expression is missing the alternate operator with integer and float', () => { - const code = '= 1.23 ? + 2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.23' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'LastExpression' - } - } - ] - }; + test("does not throw if if-expression is missing the alternate operator with integer and float", () => { + const code = "= 1.23 ? + 2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.23" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('does not throw if if-expression is missing the alternate operator with integer and float without whitespace', () => { - const code = '=1.23?+2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '1.23' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - alternate: { - type: 'LastExpression' - } - } - ] - }; + test("does not throw if if-expression is missing the alternate operator with integer and float without whitespace", () => { + const code = "=1.23?+2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "1.23" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + alternate: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); }); diff --git a/src/parser/__tests__/phase-08/_README.md b/src/parser/__tests__/phase-08/_README.md index 4a65bb3..f40b6b2 100644 --- a/src/parser/__tests__/phase-08/_README.md +++ b/src/parser/__tests__/phase-08/_README.md @@ -6,7 +6,7 @@ This is the eighth phase to implement the parser for _StrexLang_. ### Syntax goal -- **Human readable error messages** +- **Human readable error messages** ### Test diff --git a/src/parser/__tests__/phase-08/expression-if-test.js b/src/parser/__tests__/phase-08/expression-if-test.js index 7dbd39e..7ea8764 100644 --- a/src/parser/__tests__/phase-08/expression-if-test.js +++ b/src/parser/__tests__/phase-08/expression-if-test.js @@ -1,132 +1,132 @@ /* eslint-disable max-len */ -const parser = require('../../index'); - -describe('parser > expressions > if', () => { - describe('error handling', () => { - test('throws an error if if-expression is missing the test with integer', () => { - const code = '? + 2 : - 3'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing test for if-expression' - ); - }); - - test('throws an error if if-expression is missing the test with integer without whitespace', () => { - const code = '?+2:-3'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing test for if-expression' - ); - }); - - test('throws an error if if-expression is missing the test with float', () => { - const code = '? + 2.001 : - 3.1'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing test for if-expression' - ); - }); - - test('throws an error if if-expression is missing the test with float without whitespace', () => { - const code = '?+2.001:-3.1'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing test for if-expression' - ); - }); - - test('throws an error if if-expression is missing the test with integer and float', () => { - const code = '? + 2.001 : - 3'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing test for if-expression' - ); - }); - - test('throws an error if if-expression is missing the test with integer and float without whitespace', () => { - const code = '?+2.001:-3'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing test for if-expression' - ); - }); - - test('throws an error if if-expression is missing the consequent with integer', () => { - const code = '= 1 ? : - 3'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing consequent for if-expression' - ); - }); - - test('throws an error if if-expression is missing the consequent with integer without whitespace', () => { - const code = '=1?:-3'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing consequent for if-expression' - ); - }); - - test('throws an error if if-expression is missing the consequent with float', () => { - const code = '= 1.0 ? : - 3.0'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing consequent for if-expression' - ); - }); - - test('throws an error if if-expression is missing the consequent with float without whitespace', () => { - const code = '=1.0?:-3.0'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing consequent for if-expression' - ); - }); - - test('throws an error if if-expression is missing the consequent with integer and float', () => { - const code = '= 1 ? : - 3.0'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing consequent for if-expression' - ); - }); - - test('throws an error if if-expression is missing the consequent with integer and float without whitespace', () => { - const code = '=1?:-3.0'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing consequent for if-expression' - ); - }); - - test('throws an error if if-expression is missing the alternate with integer', () => { - const code = '= 1 ? + 2 :'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing alternate for if-expression' - ); - }); - - test('throws an error if if-expression is missing the alternate with integer without whitespace', () => { - const code = '=1?+2:'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing alternate for if-expression' - ); - }); - - test('throws an error if if-expression is missing the alternate with float', () => { - const code = '= 1.23 ? + 2.05 :'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing alternate for if-expression' - ); - }); - - test('throws an error if if-expression is missing the alternate with float without whitespace', () => { - const code = '=1.23?+2.05:'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing alternate for if-expression' - ); - }); - - test('throws an error if if-expression is missing the alternate with integer and float', () => { - const code = '= 1.23 ? + 2 :'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing alternate for if-expression' - ); - }); - - test('throws an error if if-expression is missing the alternate with integer and float without whitespace', () => { - const code = '=1.23?+2:'; - expect(() => parser(code)).toThrow( - 'Line 1, column 1: Missing alternate for if-expression' - ); - }); +const parser = require("../../index"); + +describe("parser > expressions > if", () => { + describe("error handling", () => { + test("throws an error if if-expression is missing the test with integer", () => { + const code = "? + 2 : - 3"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing test for if-expression" + ); }); + + test("throws an error if if-expression is missing the test with integer without whitespace", () => { + const code = "?+2:-3"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing test for if-expression" + ); + }); + + test("throws an error if if-expression is missing the test with float", () => { + const code = "? + 2.001 : - 3.1"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing test for if-expression" + ); + }); + + test("throws an error if if-expression is missing the test with float without whitespace", () => { + const code = "?+2.001:-3.1"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing test for if-expression" + ); + }); + + test("throws an error if if-expression is missing the test with integer and float", () => { + const code = "? + 2.001 : - 3"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing test for if-expression" + ); + }); + + test("throws an error if if-expression is missing the test with integer and float without whitespace", () => { + const code = "?+2.001:-3"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing test for if-expression" + ); + }); + + test("throws an error if if-expression is missing the consequent with integer", () => { + const code = "= 1 ? : - 3"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing consequent for if-expression" + ); + }); + + test("throws an error if if-expression is missing the consequent with integer without whitespace", () => { + const code = "=1?:-3"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing consequent for if-expression" + ); + }); + + test("throws an error if if-expression is missing the consequent with float", () => { + const code = "= 1.0 ? : - 3.0"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing consequent for if-expression" + ); + }); + + test("throws an error if if-expression is missing the consequent with float without whitespace", () => { + const code = "=1.0?:-3.0"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing consequent for if-expression" + ); + }); + + test("throws an error if if-expression is missing the consequent with integer and float", () => { + const code = "= 1 ? : - 3.0"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing consequent for if-expression" + ); + }); + + test("throws an error if if-expression is missing the consequent with integer and float without whitespace", () => { + const code = "=1?:-3.0"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing consequent for if-expression" + ); + }); + + test("throws an error if if-expression is missing the alternate with integer", () => { + const code = "= 1 ? + 2 :"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing alternate for if-expression" + ); + }); + + test("throws an error if if-expression is missing the alternate with integer without whitespace", () => { + const code = "=1?+2:"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing alternate for if-expression" + ); + }); + + test("throws an error if if-expression is missing the alternate with float", () => { + const code = "= 1.23 ? + 2.05 :"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing alternate for if-expression" + ); + }); + + test("throws an error if if-expression is missing the alternate with float without whitespace", () => { + const code = "=1.23?+2.05:"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing alternate for if-expression" + ); + }); + + test("throws an error if if-expression is missing the alternate with integer and float", () => { + const code = "= 1.23 ? + 2 :"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing alternate for if-expression" + ); + }); + + test("throws an error if if-expression is missing the alternate with integer and float without whitespace", () => { + const code = "=1.23?+2:"; + expect(() => parser(code)).toThrow( + "Line 1, column 1: Missing alternate for if-expression" + ); + }); + }); }); diff --git a/src/parser/__tests__/phase-08/type-combined.test.js b/src/parser/__tests__/phase-08/type-combined.test.js index a8d2826..3e09033 100644 --- a/src/parser/__tests__/phase-08/type-combined.test.js +++ b/src/parser/__tests__/phase-08/type-combined.test.js @@ -1,83 +1,83 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > types > combined', () => { - describe('error handling', () => { - test('throws an error if right hand expression on multiple operator is missing for integer and float [1]', () => { - const code = '2.1 + 6 -\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 9: Expected end of line but "-" found.' - ); - }); +describe("parser > types > combined", () => { + describe("error handling", () => { + test("throws an error if right hand expression on multiple operator is missing for integer and float [1]", () => { + const code = "2.1 + 6 -\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 9: Expected end of line but "-" found.' + ); + }); - test('throws an error if right hand expression on multiple operator is missing for integer and float [2]', () => { - const code = '58 + 10.004 - 2 *\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 17: Expected end of line but "*" found.' - ); - }); + test("throws an error if right hand expression on multiple operator is missing for integer and float [2]", () => { + const code = "58 + 10.004 - 2 *\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 17: Expected end of line but "*" found.' + ); + }); - test('throws an error if right hand expression on multiple operator is missing for integer and float [3]', () => { - const code = '12 + 98.7 /\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 11: Expected end of line but "/" found.' - ); - }); + test("throws an error if right hand expression on multiple operator is missing for integer and float [3]", () => { + const code = "12 + 98.7 /\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 11: Expected end of line but "/" found.' + ); + }); - test('throws an error if right hand expression on multiple operator is missing for integer and float [4]', () => { - const code = '2.2 + 31 +\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 10: Expected end of line but "+" found.' - ); - }); + test("throws an error if right hand expression on multiple operator is missing for integer and float [4]", () => { + const code = "2.2 + 31 +\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 10: Expected end of line but "+" found.' + ); + }); - test('throws an error if integer and float is missing on two + operations', () => { - const code = '1.1 + + 2\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "+" found.' - ); - }); + test("throws an error if integer and float is missing on two + operations", () => { + const code = "1.1 + + 2\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "+" found.' + ); + }); - test('throws an error if integer and float is missing on two + operations without whitespace', () => { - const code = '1++2.2\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 2: Expected end of line but "+" found.' - ); - }); + test("throws an error if integer and float is missing on two + operations without whitespace", () => { + const code = "1++2.2\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 2: Expected end of line but "+" found.' + ); + }); - test('throws an error if integer and float is missing on two - operations', () => { - const code = '10.00 - - 3000\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 7: Expected end of line but "-" found.' - ); - }); + test("throws an error if integer and float is missing on two - operations", () => { + const code = "10.00 - - 3000\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 7: Expected end of line but "-" found.' + ); + }); - test('throws an error if integer and float is missing on two - operations without whitespace', () => { - const code = '1000--30.00\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "-" found.' - ); - }); + test("throws an error if integer and float is missing on two - operations without whitespace", () => { + const code = "1000--30.00\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "-" found.' + ); + }); - test('throws an error if integer and float is missing on two * operations', () => { - const code = '3.3 * * 1\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "*" found.' - ); - }); + test("throws an error if integer and float is missing on two * operations", () => { + const code = "3.3 * * 1\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "*" found.' + ); + }); - test('throws an error if integer and float is missing on two * operations without whitespace', () => { - const code = '3**1.45\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 2: Expected end of line but "*" found.' - ); - }); + test("throws an error if integer and float is missing on two * operations without whitespace", () => { + const code = "3**1.45\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 2: Expected end of line but "*" found.' + ); + }); - test('throws an error if integer and float is missing on two / operations', () => { - const code = '3.6 / / 6\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "/" found.' - ); - }); + test("throws an error if integer and float is missing on two / operations", () => { + const code = "3.6 / / 6\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "/" found.' + ); }); + }); }); diff --git a/src/parser/__tests__/phase-08/type-float.test.js b/src/parser/__tests__/phase-08/type-float.test.js index 4ef515d..4b31454 100644 --- a/src/parser/__tests__/phase-08/type-float.test.js +++ b/src/parser/__tests__/phase-08/type-float.test.js @@ -1,135 +1,135 @@ /* eslint-disable max-len */ -const parser = require('../../index'); - -describe('parser > types > float', () => { - describe('error handling', () => { - test('does not throw on null division', () => { - const code = '1.3 / 0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.3' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '/' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('throws an error if right hand expression on + operator is missing for float', () => { - const code = '3.1 +\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "+" found.' - ); - }); - - test('throws an error if right hand expression on - operator is missing for float', () => { - const code = '0.001 -\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 7: Expected end of line but "-" found.' - ); - }); - - test('throws an error if right hand expression on * operator is missing for float', () => { - const code = '9.9 *\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "*" found.' - ); - }); - - test('throws an error if right hand expression on / operator is missing for float', () => { - const code = '9.9999999999999999 /\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 20: Expected end of line but "/" found.' - ); - }); - - test('throws an error if right hand expression on multiple operator is missing for float [1]', () => { - const code = '1.2 + 4.6 -\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 11: Expected end of line but "-" found.' - ); - }); - - test('throws an error if right hand expression on multiple operator is missing for float [2]', () => { - const code = '1.2 + 4.6 - 4.2 *\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 17: Expected end of line but "*" found.' - ); - }); - - test('throws an error if right hand expression on multiple operator is missing for float [3]', () => { - const code = '1.2 + 3.0 /\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 11: Expected end of line but "/" found.' - ); - }); - - test('throws an error if right hand expression on multiple operator is missing for float [4]', () => { - const code = '2.2 + 3.1 +\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 11: Expected end of line but "+" found.' - ); - }); - - test('throws an error if float is missing on two + operations', () => { - const code = '1.1 + + 2.4\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "+" found.' - ); - }); - - test('throws an error if float is missing on two + operations without whitespace', () => { - const code = '1.1++2.4\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 4: Expected end of line but "+" found.' - ); - }); - - test('throws an error if float is missing on two - operations', () => { - const code = '10.00 - - 30.00\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 7: Expected end of line but "-" found.' - ); - }); - - test('throws an error if float is missing on two - operations without whitespace', () => { - const code = '10.00--30.00\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 6: Expected end of line but "-" found.' - ); - }); - - test('throws an error if float is missing on two * operations', () => { - const code = '0.3 * * 1.1\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "*" found.' - ); - }); - - test('throws an error if float is missing on two * operations without whitespace', () => { - const code = '0.3**1.1\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 4: Expected end of line but "*" found.' - ); - }); - - test('throws an error if float is missing on two / operations', () => { - const code = '36.45 / / 6.66\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 7: Expected end of line but "/" found.' - ); - }); +const parser = require("../../index"); + +describe("parser > types > float", () => { + describe("error handling", () => { + test("does not throw on null division", () => { + const code = "1.3 / 0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.3" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: "/" + } + ] + }; + + expect(ast).toEqual(expected); }); + + test("throws an error if right hand expression on + operator is missing for float", () => { + const code = "3.1 +\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "+" found.' + ); + }); + + test("throws an error if right hand expression on - operator is missing for float", () => { + const code = "0.001 -\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 7: Expected end of line but "-" found.' + ); + }); + + test("throws an error if right hand expression on * operator is missing for float", () => { + const code = "9.9 *\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "*" found.' + ); + }); + + test("throws an error if right hand expression on / operator is missing for float", () => { + const code = "9.9999999999999999 /\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 20: Expected end of line but "/" found.' + ); + }); + + test("throws an error if right hand expression on multiple operator is missing for float [1]", () => { + const code = "1.2 + 4.6 -\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 11: Expected end of line but "-" found.' + ); + }); + + test("throws an error if right hand expression on multiple operator is missing for float [2]", () => { + const code = "1.2 + 4.6 - 4.2 *\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 17: Expected end of line but "*" found.' + ); + }); + + test("throws an error if right hand expression on multiple operator is missing for float [3]", () => { + const code = "1.2 + 3.0 /\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 11: Expected end of line but "/" found.' + ); + }); + + test("throws an error if right hand expression on multiple operator is missing for float [4]", () => { + const code = "2.2 + 3.1 +\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 11: Expected end of line but "+" found.' + ); + }); + + test("throws an error if float is missing on two + operations", () => { + const code = "1.1 + + 2.4\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "+" found.' + ); + }); + + test("throws an error if float is missing on two + operations without whitespace", () => { + const code = "1.1++2.4\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 4: Expected end of line but "+" found.' + ); + }); + + test("throws an error if float is missing on two - operations", () => { + const code = "10.00 - - 30.00\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 7: Expected end of line but "-" found.' + ); + }); + + test("throws an error if float is missing on two - operations without whitespace", () => { + const code = "10.00--30.00\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 6: Expected end of line but "-" found.' + ); + }); + + test("throws an error if float is missing on two * operations", () => { + const code = "0.3 * * 1.1\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "*" found.' + ); + }); + + test("throws an error if float is missing on two * operations without whitespace", () => { + const code = "0.3**1.1\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 4: Expected end of line but "*" found.' + ); + }); + + test("throws an error if float is missing on two / operations", () => { + const code = "36.45 / / 6.66\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 7: Expected end of line but "/" found.' + ); + }); + }); }); diff --git a/src/parser/__tests__/phase-08/type-integer.test.js b/src/parser/__tests__/phase-08/type-integer.test.js index c1da4a6..bfe5fac 100644 --- a/src/parser/__tests__/phase-08/type-integer.test.js +++ b/src/parser/__tests__/phase-08/type-integer.test.js @@ -1,135 +1,135 @@ /* eslint-disable max-len */ -const parser = require('../../index'); - -describe('parser > types > integer', () => { - describe('error handling', () => { - test('does not throw on null division', () => { - const code = '1 / 0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '/' - } - ] - }; - - expect(ast).toEqual(expected); - }); - - test('throws an error if right hand expression on + operator is missing for integer', () => { - const code = '3 +\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 3: Expected end of line but "+" found.' - ); - }); - - test('throws an error if right hand expression on - operator is missing for integer', () => { - const code = '1 -\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 3: Expected end of line but "-" found.' - ); - }); - - test('throws an error if right hand expression on * operator is missing for integer', () => { - const code = '18754 *\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 7: Expected end of line but "*" found.' - ); - }); - - test('throws an error if right hand expression on / operator is missing for integer', () => { - const code = '9999999999999999 /\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 18: Expected end of line but "/" found.' - ); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer [1]', () => { - const code = '2 + 6 -\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 7: Expected end of line but "-" found.' - ); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer [2]', () => { - const code = '58 + 10004 - 2 *\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 16: Expected end of line but "*" found.' - ); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer [3]', () => { - const code = '12 + 987 /\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 10: Expected end of line but "/" found.' - ); - }); - - test('throws an error if right hand expression on multiple operator is missing for integer [4]', () => { - const code = '22 + 31 +\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 9: Expected end of line but "+" found.' - ); - }); - - test('throws an error if integer is missing on two + operations', () => { - const code = '1 + + 2\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 3: Expected end of line but "+" found.' - ); - }); - - test('throws an error if integer is missing on two + operations without whitespace', () => { - const code = '1++2\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 2: Expected end of line but "+" found.' - ); - }); - - test('throws an error if integer is missing on two - operations', () => { - const code = '1000 - - 3000\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 6: Expected end of line but "-" found.' - ); - }); - - test('throws an error if integer is missing on two - operations without whitespace', () => { - const code = '1000--3000\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 5: Expected end of line but "-" found.' - ); - }); - - test('throws an error if integer is missing on two * operations', () => { - const code = '3 * * 1\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 3: Expected end of line but "*" found.' - ); - }); - - test('throws an error if integer is missing on two * operations without whitespace', () => { - const code = '3**1\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 2: Expected end of line but "*" found.' - ); - }); - - test('throws an error if integer is missing on two / operations', () => { - const code = '36 / / 6\n'; - expect(() => parser(code)).toThrow( - 'Line 1, column 4: Expected end of line but "/" found.' - ); - }); +const parser = require("../../index"); + +describe("parser > types > integer", () => { + describe("error handling", () => { + test("does not throw on null division", () => { + const code = "1 / 0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: "/" + } + ] + }; + + expect(ast).toEqual(expected); }); + + test("throws an error if right hand expression on + operator is missing for integer", () => { + const code = "3 +\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 3: Expected end of line but "+" found.' + ); + }); + + test("throws an error if right hand expression on - operator is missing for integer", () => { + const code = "1 -\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 3: Expected end of line but "-" found.' + ); + }); + + test("throws an error if right hand expression on * operator is missing for integer", () => { + const code = "18754 *\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 7: Expected end of line but "*" found.' + ); + }); + + test("throws an error if right hand expression on / operator is missing for integer", () => { + const code = "9999999999999999 /\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 18: Expected end of line but "/" found.' + ); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer [1]", () => { + const code = "2 + 6 -\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 7: Expected end of line but "-" found.' + ); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer [2]", () => { + const code = "58 + 10004 - 2 *\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 16: Expected end of line but "*" found.' + ); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer [3]", () => { + const code = "12 + 987 /\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 10: Expected end of line but "/" found.' + ); + }); + + test("throws an error if right hand expression on multiple operator is missing for integer [4]", () => { + const code = "22 + 31 +\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 9: Expected end of line but "+" found.' + ); + }); + + test("throws an error if integer is missing on two + operations", () => { + const code = "1 + + 2\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 3: Expected end of line but "+" found.' + ); + }); + + test("throws an error if integer is missing on two + operations without whitespace", () => { + const code = "1++2\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 2: Expected end of line but "+" found.' + ); + }); + + test("throws an error if integer is missing on two - operations", () => { + const code = "1000 - - 3000\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 6: Expected end of line but "-" found.' + ); + }); + + test("throws an error if integer is missing on two - operations without whitespace", () => { + const code = "1000--3000\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 5: Expected end of line but "-" found.' + ); + }); + + test("throws an error if integer is missing on two * operations", () => { + const code = "3 * * 1\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 3: Expected end of line but "*" found.' + ); + }); + + test("throws an error if integer is missing on two * operations without whitespace", () => { + const code = "3**1\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 2: Expected end of line but "*" found.' + ); + }); + + test("throws an error if integer is missing on two / operations", () => { + const code = "36 / / 6\n"; + expect(() => parser(code)).toThrow( + 'Line 1, column 4: Expected end of line but "/" found.' + ); + }); + }); }); diff --git a/src/parser/__tests__/phase-09/_README.md b/src/parser/__tests__/phase-09/_README.md index cbe3e90..9605114 100644 --- a/src/parser/__tests__/phase-09/_README.md +++ b/src/parser/__tests__/phase-09/_README.md @@ -4,8 +4,8 @@ This is the ninth phase to implement the parser for _StrexLang_. ### Syntax goal -- **Last expression** syntax -- **Multi line** +- **Last expression** syntax +- **Multi line** ### Test @@ -24,32 +24,32 @@ The "last expression" is the value evaluated the line before. If no last express ```json { - "type": "Program", - "body": [ - { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "4" - }, - "right": { - "type": "IntegerLiteral", - "value": "3" - }, - "operator": "+" - }, - { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "2" - }, - "operator": "-" - } - ] + "type": "Program", + "body": [ + { + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "4" + }, + "right": { + "type": "IntegerLiteral", + "value": "3" + }, + "operator": "+" + }, + { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "2" + }, + "operator": "-" + } + ] } ``` @@ -65,59 +65,59 @@ As many lines as needed can be used to write StrexLang expressions. By referenci ```json { - "type": "Program", - "body": [ - { - "type": "BinaryExpression", - "left": { - "type": "IntegerLiteral", - "value": "4" - }, - "right": { - "type": "IntegerLiteral", - "value": "3" - }, - "operator": "+" + "type": "Program", + "body": [ + { + "type": "BinaryExpression", + "left": { + "type": "IntegerLiteral", + "value": "4" + }, + "right": { + "type": "IntegerLiteral", + "value": "3" + }, + "operator": "+" + }, + { + "type": "IfExpression", + "test": { + "type": "BooleanExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "7" + }, + "operator": "=" + }, + "consequent": { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" }, - { - "type": "IfExpression", - "test": { - "type": "BooleanExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "7" - }, - "operator": "=" - }, - "consequent": { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "2" - }, - "operator": "-" - }, - "alternate": { - "type": "LastExpression" - } + "right": { + "type": "IntegerLiteral", + "value": "2" }, - { - "type": "BinaryExpression", - "left": { - "type": "LastExpression" - }, - "right": { - "type": "IntegerLiteral", - "value": "3" - }, - "operator": "*" - } - ] + "operator": "-" + }, + "alternate": { + "type": "LastExpression" + } + }, + { + "type": "BinaryExpression", + "left": { + "type": "LastExpression" + }, + "right": { + "type": "IntegerLiteral", + "value": "3" + }, + "operator": "*" + } + ] } ``` diff --git a/src/parser/__tests__/phase-09/multiline-test.js b/src/parser/__tests__/phase-09/multiline-test.js index f87cf62..a30eb70 100644 --- a/src/parser/__tests__/phase-09/multiline-test.js +++ b/src/parser/__tests__/phase-09/multiline-test.js @@ -1,1368 +1,1368 @@ /* eslint-disable max-len */ -const parser = require('../../index'); +const parser = require("../../index"); -describe('parser > base > multiline', () => { - describe('with arithmetic', () => { - test('creates integer expressions with + operator', () => { - const code = '1 + 2\n+3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '+' - } - ] - }; +describe("parser > base > multiline", () => { + describe("with arithmetic", () => { + test("creates integer expressions with + operator", () => { + const code = "1 + 2\n+3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with + operator without whitespace', () => { - const code = '1+2\n+3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '+' - } - ] - }; + test("creates integer expressions with + operator without whitespace", () => { + const code = "1+2\n+3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with - operator', () => { - const code = '5 - 3\n- 1\n- 1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '5' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - } - ] - }; + test("creates integer expressions with - operator", () => { + const code = "5 - 3\n- 1\n- 1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "5" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with - operator without whitespace', () => { - const code = '5-3\n-1\n-1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '5' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - } - ] - }; + test("creates integer expressions with - operator without whitespace", () => { + const code = "5-3\n-1\n-1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "5" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with * operator', () => { - const code = '42\n* 5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IntegerLiteral', - value: '42' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '*' - } - ] - }; + test("creates integer expressions with * operator", () => { + const code = "42\n* 5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IntegerLiteral", + value: "42" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with * operator without whitespace', () => { - const code = '42\n*5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'IntegerLiteral', - value: '42' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '*' - } - ] - }; + test("creates integer expressions with * operator without whitespace", () => { + const code = "42\n*5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "IntegerLiteral", + value: "42" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with / operator', () => { - const code = '36 / 6\n/ 3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '36' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '/' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '/' - } - ] - }; + test("creates integer expressions with / operator", () => { + const code = "36 / 6\n/ 3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "36" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "/" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with / operator without whitespace', () => { - const code = '36/6\n/3\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '36' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '/' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '/' - } - ] - }; + test("creates integer expressions with / operator without whitespace", () => { + const code = "36/6\n/3\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "36" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "/" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with mixed operators', () => { - const code = '1 + 2\n- 5\n* 10\n/ 2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '10' - }, - operator: '*' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '/' - } - ] - }; + test("creates integer expressions with mixed operators", () => { + const code = "1 + 2\n- 5\n* 10\n/ 2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "10" + }, + operator: "*" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates integer expressions with mixed operators without whitespace', () => { - const code = '1+2\n-5\n*10\n/2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '10' - }, - operator: '*' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '/' - } - ] - }; + test("creates integer expressions with mixed operators without whitespace", () => { + const code = "1+2\n-5\n*10\n/2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "10" + }, + operator: "*" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with + operator', () => { - const code = '1.2 + 44.01\n+ 5.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.2' - }, - right: { - type: 'FloatLiteral', - value: '44.01' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '5.0' - }, - operator: '+' - } - ] - }; + test("creates float expressions with + operator", () => { + const code = "1.2 + 44.01\n+ 5.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.2" + }, + right: { + type: "FloatLiteral", + value: "44.01" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "5.0" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with + operator without whitespace', () => { - const code = '1.2+44.01\n+5.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '1.2' - }, - right: { - type: 'FloatLiteral', - value: '44.01' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '5.0' - }, - operator: '+' - } - ] - }; + test("creates float expressions with + operator without whitespace", () => { + const code = "1.2+44.01\n+5.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "1.2" + }, + right: { + type: "FloatLiteral", + value: "44.01" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "5.0" + }, + operator: "+" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with - operator', () => { - const code = '10.5 - 0.5\n- 4.10\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '10.5' - }, - right: { - type: 'FloatLiteral', - value: '0.5' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '4.10' - }, - operator: '-' - } - ] - }; + test("creates float expressions with - operator", () => { + const code = "10.5 - 0.5\n- 4.10\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "10.5" + }, + right: { + type: "FloatLiteral", + value: "0.5" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "4.10" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with - operator without whitespace', () => { - const code = '10.5-0.5\n-4.10\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '10.5' - }, - right: { - type: 'FloatLiteral', - value: '0.5' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '4.10' - }, - operator: '-' - } - ] - }; + test("creates float expressions with - operator without whitespace", () => { + const code = "10.5-0.5\n-4.10\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "10.5" + }, + right: { + type: "FloatLiteral", + value: "0.5" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "4.10" + }, + operator: "-" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with * operator', () => { - const code = '0.5 * 1.5\n* 4.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '0.5' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '*' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '4.0' - }, - operator: '*' - } - ] - }; + test("creates float expressions with * operator", () => { + const code = "0.5 * 1.5\n* 4.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "0.5" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "*" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "4.0" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with * operator without whitespace', () => { - const code = '0.5*1.5\n*4.0\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '0.5' - }, - right: { - type: 'FloatLiteral', - value: '1.5' - }, - operator: '*' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '4.0' - }, - operator: '*' - } - ] - }; + test("creates float expressions with * operator without whitespace", () => { + const code = "0.5*1.5\n*4.0\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "0.5" + }, + right: { + type: "FloatLiteral", + value: "1.5" + }, + operator: "*" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "4.0" + }, + operator: "*" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with / operator', () => { - const code = '2.0 / 0.5\n/ 0.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.0' - }, - right: { - type: 'FloatLiteral', - value: '0.5' - }, - operator: '/' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '0.5' - }, - operator: '/' - } - ] - }; + test("creates float expressions with / operator", () => { + const code = "2.0 / 0.5\n/ 0.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.0" + }, + right: { + type: "FloatLiteral", + value: "0.5" + }, + operator: "/" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "0.5" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with / operator without whitespace', () => { - const code = '2.0/0.5\n/0.5\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '2.0' - }, - right: { - type: 'FloatLiteral', - value: '0.5' - }, - operator: '/' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '0.5' - }, - operator: '/' - } - ] - }; + test("creates float expressions with / operator without whitespace", () => { + const code = "2.0/0.5\n/0.5\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "2.0" + }, + right: { + type: "FloatLiteral", + value: "0.5" + }, + operator: "/" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "0.5" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with mixed operators', () => { - const code = '4.2 - 0.1\n* 5.0\n+ 001.5\n/ 0.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '4.2' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '5.0' - }, - operator: '*' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '001.5' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '/' - } - ] - }; + test("creates float expressions with mixed operators", () => { + const code = "4.2 - 0.1\n* 5.0\n+ 001.5\n/ 0.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "4.2" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "5.0" + }, + operator: "*" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "001.5" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('creates float expressions with mixed operators without whitespace', () => { - const code = '4.2-0.1\n*5.0\n+001.5\n/0.1\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '4.2' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '-' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '5.0' - }, - operator: '*' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '001.5' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'FloatLiteral', - value: '0.1' - }, - operator: '/' - } - ] - }; + test("creates float expressions with mixed operators without whitespace", () => { + const code = "4.2-0.1\n*5.0\n+001.5\n/0.1\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "4.2" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: "-" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "5.0" + }, + operator: "*" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "001.5" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "FloatLiteral", + value: "0.1" + }, + operator: "/" + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); - describe('with if-expressions', () => { - test('for one expression', () => { - const code = '1 + 2\n= 3 ? * 5 : / 2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '*' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '/' - } - } - ] - }; + describe("with if-expressions", () => { + test("for one expression", () => { + const code = "1 + 2\n= 3 ? * 5 : / 2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "*" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "/" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('for one expression without whitespace', () => { - const code = '1+2\n=3?*5:/2\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '*' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '/' - } - } - ] - }; + test("for one expression without whitespace", () => { + const code = "1+2\n=3?*5:/2\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "*" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "/" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('for multiple expressions', () => { - const code = '2 - 2\n> 0 | < 5 ? - 1 : + 1\n= 1 ? + 0 : - 100\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '<' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '+' - } - }, - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '100' - }, - operator: '-' - } - } - ] - }; + test("for multiple expressions", () => { + const code = "2 - 2\n> 0 | < 5 ? - 1 : + 1\n= 1 ? + 0 : - 100\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "<" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "+" + } + }, + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "100" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('for multiple expressions without whitespace', () => { - const code = '2-2\n>0|<5?-1:+1\n=1?+0:-100\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '2' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '-' - }, - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '>' - }, - right: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '5' - }, - operator: '<' - }, - operator: '|' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '-' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '+' - } - }, - { - type: 'IfExpression', - test: { - type: 'BooleanExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '1' - }, - operator: '=' - }, - consequent: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '0' - }, - operator: '+' - }, - alternate: { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '100' - }, - operator: '-' - } - } - ] - }; + test("for multiple expressions without whitespace", () => { + const code = "2-2\n>0|<5?-1:+1\n=1?+0:-100\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "2" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "-" + }, + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: ">" + }, + right: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "5" + }, + operator: "<" + }, + operator: "|" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "-" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "+" + } + }, + { + type: "IfExpression", + test: { + type: "BooleanExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "1" + }, + operator: "=" + }, + consequent: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "0" + }, + operator: "+" + }, + alternate: { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "100" + }, + operator: "-" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); - describe('including print out', () => { - test('as single statement at the end', () => { - const code = '1 + 2\n- 3\n\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - }, - { - type: 'PrintOut', - value: { - type: 'LastExpression' - } - } - ] - }; + describe("including print out", () => { + test("as single statement at the end", () => { + const code = "1 + 2\n- 3\n\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + }, + { + type: "PrintOut", + value: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('as single statement at the end without whitespace', () => { - const code = '1+2\n-3\n\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '1' - }, - right: { - type: 'IntegerLiteral', - value: '2' - }, - operator: '+' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '3' - }, - operator: '-' - }, - { - type: 'PrintOut', - value: { - type: 'LastExpression' - } - } - ] - }; + test("as single statement at the end without whitespace", () => { + const code = "1+2\n-3\n\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "1" + }, + right: { + type: "IntegerLiteral", + value: "2" + }, + operator: "+" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "3" + }, + operator: "-" + }, + { + type: "PrintOut", + value: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('with multiple statements', () => { - const code = '4 * 6\n- 42\n\n9.5 / 0.5\n- 4\n\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '4' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '*' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '42' - }, - operator: '-' - }, - { - type: 'PrintOut', - value: { - type: 'LastExpression' - } - }, - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '9.5' - }, - right: { - type: 'FloatLiteral', - value: '0.5' - }, - operator: '/' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '-' - }, - { - type: 'PrintOut', - value: { - type: 'LastExpression' - } - } - ] - }; + test("with multiple statements", () => { + const code = "4 * 6\n- 42\n\n9.5 / 0.5\n- 4\n\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "4" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "*" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "42" + }, + operator: "-" + }, + { + type: "PrintOut", + value: { + type: "LastExpression" + } + }, + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "9.5" + }, + right: { + type: "FloatLiteral", + value: "0.5" + }, + operator: "/" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "-" + }, + { + type: "PrintOut", + value: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); + }); - test('with multiple statements without whitespace', () => { - const code = '4*6\n-42\n\n9.5/0.5\n-4\n\n'; - const ast = parser(code); - const expected = { - type: 'Program', - body: [ - { - type: 'BinaryExpression', - left: { - type: 'IntegerLiteral', - value: '4' - }, - right: { - type: 'IntegerLiteral', - value: '6' - }, - operator: '*' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '42' - }, - operator: '-' - }, - { - type: 'PrintOut', - value: { - type: 'LastExpression' - } - }, - { - type: 'BinaryExpression', - left: { - type: 'FloatLiteral', - value: '9.5' - }, - right: { - type: 'FloatLiteral', - value: '0.5' - }, - operator: '/' - }, - { - type: 'BinaryExpression', - left: { - type: 'LastExpression' - }, - right: { - type: 'IntegerLiteral', - value: '4' - }, - operator: '-' - }, - { - type: 'PrintOut', - value: { - type: 'LastExpression' - } - } - ] - }; + test("with multiple statements without whitespace", () => { + const code = "4*6\n-42\n\n9.5/0.5\n-4\n\n"; + const ast = parser(code); + const expected = { + type: "Program", + body: [ + { + type: "BinaryExpression", + left: { + type: "IntegerLiteral", + value: "4" + }, + right: { + type: "IntegerLiteral", + value: "6" + }, + operator: "*" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "42" + }, + operator: "-" + }, + { + type: "PrintOut", + value: { + type: "LastExpression" + } + }, + { + type: "BinaryExpression", + left: { + type: "FloatLiteral", + value: "9.5" + }, + right: { + type: "FloatLiteral", + value: "0.5" + }, + operator: "/" + }, + { + type: "BinaryExpression", + left: { + type: "LastExpression" + }, + right: { + type: "IntegerLiteral", + value: "4" + }, + operator: "-" + }, + { + type: "PrintOut", + value: { + type: "LastExpression" + } + } + ] + }; - expect(ast).toEqual(expected); - }); + expect(ast).toEqual(expected); }); + }); }); diff --git a/src/parser/index.js b/src/parser/index.js index e011ac6..a6e68bc 100644 --- a/src/parser/index.js +++ b/src/parser/index.js @@ -1,7 +1,7 @@ /** * Modify me! */ -'use strict'; +"use strict"; /** * This file defines the parser and should be modified to produce an AST like @@ -20,15 +20,15 @@ * @return {Object} AST in a JSON serializable format */ module.exports = function parser(input) { - const body = []; + const body = []; - // Do what you have to do with `input` to generate the AST. Try to use the - // string function `.replace` with a regular expression, split the string - // or if you want to you can try to create a tokenizer. - // START HERE ... + // Do what you have to do with `input` to generate the AST. Try to use the + // string function `.replace` with a regular expression, split the string + // or if you want to you can try to create a tokenizer. + // START HERE ... - return { - type: 'Program', - body - }; + return { + type: "Program", + body + }; }; diff --git a/src/strex-lang.peg b/src/strex-lang.peg index dddfff6..fe24bb6 100644 --- a/src/strex-lang.peg +++ b/src/strex-lang.peg @@ -1,162 +1,162 @@ { - const TYPE = { - PROGRAM: 'Program', - PRINT_OUT: 'PrintOut', - INTEGER_LITERAL: 'IntegerLiteral', - FLOAT_LITERAL: 'FloatLiteral', - BINARY_EXPRESSION: 'BinaryExpression', - BOOLEAN_EXPRESSION: 'BooleanExpression', - LAST_EXPRESSION: 'LastExpression', - IF_EXPRESSION: 'IfExpression', - }; - - const createExpressionReducer = type => (result, [, operator, right]) => ( - { type, left: result, right, operator } - ); - - const LAST_EXP_VALUE = { type: TYPE.LAST_EXPRESSION }; + const TYPE = { + PROGRAM: 'Program', + PRINT_OUT: 'PrintOut', + INTEGER_LITERAL: 'IntegerLiteral', + FLOAT_LITERAL: 'FloatLiteral', + BINARY_EXPRESSION: 'BinaryExpression', + BOOLEAN_EXPRESSION: 'BooleanExpression', + LAST_EXPRESSION: 'LastExpression', + IF_EXPRESSION: 'IfExpression', + }; + + const createExpressionReducer = type => (result, [, operator, right]) => ( + { type, left: result, right, operator } + ); + + const LAST_EXP_VALUE = { type: TYPE.LAST_EXPRESSION }; } Program - = body:(Line / PrintOut)* { - return { type: TYPE.PROGRAM, body }; - } + = body:(Line / PrintOut)* { + return { type: TYPE.PROGRAM, body }; + } PrintOut 'print out' - = EOL+ { - return { - type: TYPE.PRINT_OUT, - value: LAST_EXP_VALUE, - }; - } + = EOL+ { + return { + type: TYPE.PRINT_OUT, + value: LAST_EXP_VALUE, + }; + } Line - = line:Expressions EOL { - return line; - } + = line:Expressions EOL { + return line; + } Expressions - = LastExpression - / BinaryExpression - / IfExpression - / EOF + = LastExpression + / BinaryExpression + / IfExpression + / EOF LastExpression - = _ operator:(AdditiveOperator / MultiplicativeOperator) right:BinaryExpression { - return { - type: TYPE.BINARY_EXPRESSION, - left: LAST_EXP_VALUE, - right, - operator, - }; - } + = _ operator:(AdditiveOperator / MultiplicativeOperator) right:BinaryExpression { + return { + type: TYPE.BINARY_EXPRESSION, + left: LAST_EXP_VALUE, + right, + operator, + }; + } BinaryExpression 'binary expression' - = _ head:Term tail:(_ AdditiveOperator Term)* _ { - return tail.reduce(createExpressionReducer(TYPE.BINARY_EXPRESSION), head); - } + = _ head:Term tail:(_ AdditiveOperator Term)* _ { + return tail.reduce(createExpressionReducer(TYPE.BINARY_EXPRESSION), head); + } IfExpression 'if expression' - = test:CompareOrExpression? '?' consequent:Expressions? alternate:(':' Expressions?)? { - if (!test) { - error('Missing test for if-expression'); - } - - if (!consequent) { - error('Missing consequent for if-expression'); - } - - if (alternate && !alternate[1]) { - error('Missing alternate for if-expression'); - } - - return { - type: TYPE.IF_EXPRESSION, - test, - consequent, - alternate: alternate ? alternate[1] : LAST_EXP_VALUE, - }; + = test:CompareOrExpression? '?' consequent:Expressions? alternate:(':' Expressions?)? { + if (!test) { + error('Missing test for if-expression'); } -CompareOrExpression 'compare or expression' - = head:CompareAndExpression tail:(_ OrOperator CompareAndExpression)* _ { - return tail.reduce(createExpressionReducer(TYPE.BOOLEAN_EXPRESSION), head); + if (!consequent) { + error('Missing consequent for if-expression'); } -CompareAndExpression 'compare and expression' - = head:BooleanExpression tail:(_ AndOperator BooleanExpression)* _ { - return tail.reduce(createExpressionReducer(TYPE.BOOLEAN_EXPRESSION), head); + if (alternate && !alternate[1]) { + error('Missing alternate for if-expression'); } + return { + type: TYPE.IF_EXPRESSION, + test, + consequent, + alternate: alternate ? alternate[1] : LAST_EXP_VALUE, + }; + } + +CompareOrExpression 'compare or expression' + = head:CompareAndExpression tail:(_ OrOperator CompareAndExpression)* _ { + return tail.reduce(createExpressionReducer(TYPE.BOOLEAN_EXPRESSION), head); + } + +CompareAndExpression 'compare and expression' + = head:BooleanExpression tail:(_ AndOperator BooleanExpression)* _ { + return tail.reduce(createExpressionReducer(TYPE.BOOLEAN_EXPRESSION), head); + } + BooleanExpression 'boolean expression' - = _ operator:CompareOperator right:(LastExpression / BinaryExpression) { - return { - type: TYPE.BOOLEAN_EXPRESSION, - left: LAST_EXP_VALUE, - right, - operator, - }; - } + = _ operator:CompareOperator right:(LastExpression / BinaryExpression) { + return { + type: TYPE.BOOLEAN_EXPRESSION, + left: LAST_EXP_VALUE, + right, + operator, + }; + } Term - = _ head:Factor tail:(_ MultiplicativeOperator Factor)* _ { - return tail.reduce(createExpressionReducer(TYPE.BINARY_EXPRESSION), head); - } + = _ head:Factor tail:(_ MultiplicativeOperator Factor)* _ { + return tail.reduce(createExpressionReducer(TYPE.BINARY_EXPRESSION), head); + } Factor - = _ '(' expr:BinaryExpression ')' _ { return expr; } - / FloatLiteral - / IntegerLiteral + = _ '(' expr:BinaryExpression ')' _ { return expr; } + / FloatLiteral + / IntegerLiteral IntegerLiteral 'integer' - = _ digits:([0-9]+) _ { - return { - type: TYPE.INTEGER_LITERAL, - value: digits.join(''), - }; - } + = _ digits:([0-9]+) _ { + return { + type: TYPE.INTEGER_LITERAL, + value: digits.join(''), + }; + } FloatLiteral 'float' - = _ digits:([0-9]+ '.' [0-9]+) _ { - return { - type: TYPE.FLOAT_LITERAL, - value: `${digits[0].join('')}${digits[1]}${digits[2].join('')}`, - }; - } + = _ digits:([0-9]+ '.' [0-9]+) _ { + return { + type: TYPE.FLOAT_LITERAL, + value: `${digits[0].join('')}${digits[1]}${digits[2].join('')}`, + }; + } AdditiveOperator - = '+' - / '-' + = '+' + / '-' MultiplicativeOperator - = '*' - / '/' + = '*' + / '/' CompareOperator - = '=' - / '>' - / '<' + = '=' + / '>' + / '<' OrOperator - = '|' + = '|' AndOperator - = '&' + = '&' _ - = WhiteSpace* + = WhiteSpace* WhiteSpace 'whitespace' - = "\t" - / "\v" - / "\f" - / " " - / "\u00A0" - / "\uFEFF" + = "\t" + / "\v" + / "\f" + / " " + / "\u00A0" + / "\uFEFF" EOL 'end of line' - = '\n' - / '\n\r' + = '\n' + / '\n\r' EOF 'end of file' - = !. + = !.