From 7cd3f97933ee67eebb67a5aec6035c47ebcc1048 Mon Sep 17 00:00:00 2001 From: Verlon Smith Date: Fri, 30 Oct 2015 21:38:32 -0600 Subject: [PATCH 1/2] Updated parser files --- transpiler/parser/advance.js | 1 + transpiler/parser/declarations.js | 96 ++-- transpiler/parser/expression.js | 18 + transpiler/parser/helperFunctions.js | 2 +- transpiler/parser/parser.js | 4 +- transpiler/parser/parserRunner.js | 453 ++---------------- .../rearrangeTokensPrintToConsoleLog.js | 31 ++ transpiler/parser/statement.js | 4 + transpiler/parser/tokenTypes.js | 2 +- 9 files changed, 147 insertions(+), 464 deletions(-) create mode 100644 transpiler/parser/rearrangeTokensPrintToConsoleLog.js diff --git a/transpiler/parser/advance.js b/transpiler/parser/advance.js index bb07e15..9670335 100644 --- a/transpiler/parser/advance.js +++ b/transpiler/parser/advance.js @@ -41,6 +41,7 @@ var advance = function(state, id) { t.error("Unknown operator."); } } else if (tokenTypes.terminator.hasItem(a) || tokenTypes.verb.hasItem(a)) { + console.log(v); o = state.symbolTable[v]; if (!o) { t.error("Unknown operator."); diff --git a/transpiler/parser/declarations.js b/transpiler/parser/declarations.js index f6fcb75..5318bca 100644 --- a/transpiler/parser/declarations.js +++ b/transpiler/parser/declarations.js @@ -22,7 +22,7 @@ var declarations = { symbol(state, originalSymbol, "\n"); symbol(state, originalSymbol, "\\n"); symbol(state, originalSymbol, "(end)"); - symbol(state, originalSymbol, "(name)"); + symbol(state, originalSymbol, "(name)").nud = helpers.itself; symbol(state, originalSymbol, ":"); symbol(state, originalSymbol, ";"); symbol(state, originalSymbol, ")"); @@ -77,17 +77,22 @@ var declarations = { infix(state, "*", 60); infix(state, "/", 60); infix(state, "%", 60); - //infix(state, ".", 80, function(left) { - // this.first = left; - // if (state.token.type !== "name") { - // state.token.error("Expected a property name."); - // } - // state.token.type = "literal"; - // this.second = state.token; - // state.type = "binary"; - // state = advance(state); - // return state; - //}); + + infix(state, ".", 80, function(left) { + this.first = left; + if (state.token.type !== "IDENTIFIER") { + state.token.error("Expected a property name."); + } + state.token.type = "Identifier"; + this.name = state.token.value; + //state.type = "binary"; + this.type = 'CallExpression'; + this.callee = {}; + this.callee.type = 'MemeberExpression'; + //state.thisIsATest = expression(state, 0); + state = advance(state); + return this; + }); infix(state, "[", 80, function(left) { this.type = "MemberExpression"; @@ -104,35 +109,44 @@ var declarations = { return this; }); - //infix(state, "(", 80, function(left) { - // var a = []; - // if (left.id === "." || left.id === "[") { - // this.type = "ternary"; - // this.first = left.first; - // this.second = left.second; - // this.third = a; - // } else { - // this.type = "binary"; - // this.first = left; - // this.second = a; - // if ((left.type !== "unary" || left.id !== "function") && - // left.type !== "name" && left.id !== "(" && - // left.id !== "&&" && left.id !== "||" && left.id !== "?") { - // left.error("Expected a variable name."); - // } - // } - // if (state.token.id !== ")") { - // while (true) { - // a.push(expression(state, 0)); - // if (state.token.id !== ",") { - // break; - // } - // state = advance(state, ","); - // } - // } - // state = advance(state, ")"); - // return this; - //}); + infix(state, "(", 80, function(left) { + var a = []; + if (left.id === "." || left.id === "[") { + this.type = "ternary"; + this.first = left.first; + this.second = left.second; + this.third = a; + } else { + this.type = "MemberExpression"; + this.computed = false; + this.object = {}; + this.object.type = "Identifier"; + this.object.name = state.token.value; + this.property; + this.arguments = a; + //this.first = left; + //this.second = a; + delete this.value; + //if ((left.type !== "unary" || left.id !== "function") && left.id !== "(" && + // left.type !== 'binary' && left.id !== "&&" && left.id !== "||" && left.id !== "?") { + // left.error("Expected a variable name."); + //} + } + + // + + if (state.token.id !== ")") { + while (true) { + a.push(expression(state, 0)); + if (state.token.id !== ",") { + break; + } + state = advance(state, ","); + } + } + state = advance(state, ")"); + return this; + }); }, prefixes: function(state) { diff --git a/transpiler/parser/expression.js b/transpiler/parser/expression.js index 751683e..94026bb 100644 --- a/transpiler/parser/expression.js +++ b/transpiler/parser/expression.js @@ -111,6 +111,24 @@ var expression = function(state, rbp, dontWrapBinExpNodeInExpStmtBool) { } else if (left.operator === "===") { //TODO + } else if (t.value === ".") { + //TODO stuff + + state = advance(state); + + //console.log("####################################"); + //console.log('----------- START t -------------'); + //console.log(t); + //console.log('----------- END t -------------'); + // + //console.log('----------- START state.token -------------'); + //console.log(state.token); + //console.log('----------- END state.token -------------'); + // + //console.log('----------- START left -------------'); + //console.log(left); + //console.log('----------- END left -------------'); + //console.log("####################################"); } //else if (left.type === "AssignmentExpression") { // //left.left = overwrittenMemberExpression; diff --git a/transpiler/parser/helperFunctions.js b/transpiler/parser/helperFunctions.js index 53dba4a..6eae13c 100644 --- a/transpiler/parser/helperFunctions.js +++ b/transpiler/parser/helperFunctions.js @@ -163,4 +163,4 @@ var helpers = { }; -module.exports = helpers; \ No newline at end of file +module.exports = helpers; diff --git a/transpiler/parser/parser.js b/transpiler/parser/parser.js index ecc68b2..9a915fd 100644 --- a/transpiler/parser/parser.js +++ b/transpiler/parser/parser.js @@ -15,6 +15,7 @@ var declarations = require('./declarations'); var statements = require('./statements'); var rearrangeTokensDynamicDictionaryAssignment = require('./rearrangeTokensDynamicDictionaryAssignment'); var rearrangeTokensDictionaryKeyValueIteration = require('./rearrangeTokensDictionaryKeyValueIteration'); +var rearrangeTokensPrintToConsoleLog = require('./rearrangeTokensPrintToConsoleLog'); var makeParser = function() { @@ -35,7 +36,8 @@ var makeParser = function() { var parseTokenStream = function(inputTokens) { var intermediaryTokenStream = helpers.cleanUpTokenStream(inputTokens); var intermediary = rearrangeTokensDynamicDictionaryAssignment(intermediaryTokenStream); - state.tokens = rearrangeTokensDictionaryKeyValueIteration(intermediary); + var intermediary2 = rearrangeTokensPrintToConsoleLog(intermediary); + state.tokens = rearrangeTokensDictionaryKeyValueIteration(intermediary2); state.scope = newScope(state, originalScope); state = advance(state); diff --git a/transpiler/parser/parserRunner.js b/transpiler/parser/parserRunner.js index abb4a7d..ea4b518 100644 --- a/transpiler/parser/parserRunner.js +++ b/transpiler/parser/parserRunner.js @@ -4,300 +4,33 @@ var helpers = require('./helperFunctions.js'); var makeParse = require('./parser'); var expected = { + "type": "Program", "body": [ { - "type": "VariableDeclaration", - "declarations": [ - { - "type": "VariableDeclarator", - "id": { - "type": "Identifier", - "name": "gameInProgress" - }, - "init": { - "type": "Literal", - "value": false, - "raw": "false" - } - } - ], - "kind": "var" - }, - { - "type": "VariableDeclaration", - "declarations": [ - { - "type": "VariableDeclarator", - "id": { - "type": "Identifier", - "name": "score" - }, - "init": { - "type": "Literal", - "value": 0, - "raw": "0" - } - } - ], - "kind": "var" - }, - { - "type": "VariableDeclaration", - "declarations": [ - { - "type": "VariableDeclarator", - "id": { + "type": "ExpressionStatement", + "expression": { + + "type": "CallExpression", + "callee": { + + "type": "MemberExpression", + "computed": false, + "object": { + "type": "Identifier", - "name": "typeOfScore" + "name": "console" }, - "init": { - "type": "Literal", - "value": "", - "raw": "\"\"" - } - } - ], - "kind": "var" - }, - { - "type": "VariableDeclaration", - "declarations": [ - { - "type": "VariableDeclarator", - "id": { + "property": { "type": "Identifier", - "name": "PAT" - }, - "init": { - "type": "Literal", - "value": "", - "raw": "\"\"" + "name": "log" } - } - ], - "kind": "var" - }, - { - "type": "WhileStatement", - "test": { - "type": "Identifier", - "name": "gameInProgress" - }, - "body": { - "type": "BlockStatement", - "body": [ + }, + "arguments": [ { - "type": "IfStatement", - "test": { - "type": "BinaryExpression", - "operator": "!=", - "left": { - "type": "Identifier", - "name": "typeOfScore" - }, - "right": { - "type": "Literal", - "value": "", - "raw": "\"\"" - } - }, - "consequent": { - "type": "BlockStatement", - "body": [ - { - "type": "IfStatement", - "test": { - "type": "BinaryExpression", - "operator": "==", - "left": { - "type": "Identifier", - "name": "typeOfScore" - }, - "right": { - "type": "Literal", - "value": "TD", - "raw": "\"TD\"" - } - }, - "consequent": { - "type": "BlockStatement", - "body": [ - { - "type": "ExpressionStatement", - "expression": { - "type": "AssignmentExpression", - "operator": "+=", - "left": { - "type": "Identifier", - "name": "score" - }, - "right": { - "type": "Literal", - "value": 6, - "raw": "6" - } - } - } - ] - }, - "alternate": { - "type": "IfStatement", - "test": { - "type": "BinaryExpression", - "operator": "==", - "left": { - "type": "Identifier", - "name": "typeOfScore" - }, - "right": { - "type": "Literal", - "value": "PAT", - "raw": "\"PAT\"" - } - }, - "consequent": { - "type": "BlockStatement", - "body": [ - { - "type": "IfStatement", - "test": { - "type": "BinaryExpression", - "operator": "==", - "left": { - "type": "Identifier", - "name": "PAT" - }, - "right": { - "type": "Literal", - "value": "TD", - "raw": "\"TD\"" - } - }, - "consequent": { - "type": "BlockStatement", - "body": [ - { - "type": "ExpressionStatement", - "expression": { - "type": "AssignmentExpression", - "operator": "+=", - "left": { - "type": "Identifier", - "name": "score" - }, - "right": { - "type": "Literal", - "value": 2, - "raw": "2" - } - } - } - ] - }, - "alternate": { - "type": "BlockStatement", - "body": [ - { - "type": "ExpressionStatement", - "expression": { - "type": "AssignmentExpression", - "operator": "+=", - "left": { - "type": "Identifier", - "name": "score" - }, - "right": { - "type": "Literal", - "value": 1, - "raw": "1" - } - } - } - ] - } - } - ] - }, - "alternate": { - "type": "IfStatement", - "test": { - "type": "BinaryExpression", - "operator": "==", - "left": { - "type": "Identifier", - "name": "typeOfScore" - }, - "right": { - "type": "Literal", - "value": "FG", - "raw": "\"FG\"" - } - }, - "consequent": { - "type": "BlockStatement", - "body": [ - { - "type": "ExpressionStatement", - "expression": { - "type": "AssignmentExpression", - "operator": "+=", - "left": { - "type": "Identifier", - "name": "score" - }, - "right": { - "type": "Literal", - "value": 3, - "raw": "3" - } - } - } - ] - }, - "alternate": { - "type": "BlockStatement", - "body": [ - { - "type": "ExpressionStatement", - "expression": { - "type": "AssignmentExpression", - "operator": "+=", - "left": { - "type": "Identifier", - "name": "score" - }, - "right": { - "type": "Literal", - "value": 2, - "raw": "2" - } - } - } - ] - } - } - } - }, - { - "type": "ExpressionStatement", - "expression": { - "type": "AssignmentExpression", - "operator": "=", - "left": { - "type": "Identifier", - "name": "typeOfScore" - }, - "right": { - "type": "Literal", - "value": "", - "raw": "\"\"" - } - } - } - ] - }, - "alternate": null + "type": "Literal", + "value": "Hello", + "raw": "'Hello'" } ] } @@ -306,140 +39,20 @@ var expected = { "sourceType": "module" }; var tokenStream = [ - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'DECLARATION_KEYWORD', value: 'var' }, - { type: 'IDENTIFIER', value: 'gameInProgress' }, - { type: 'OPERATOR', value: '=' }, - { type: 'BOOLEAN', value: 'false' }, - { type: 'PUNCTUATION', value: ';' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'DECLARATION_KEYWORD', value: 'var' }, - { type: 'IDENTIFIER', value: 'score' }, - { type: 'OPERATOR', value: '=' }, - { type: 'NUMBER', value: '0' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'DECLARATION_KEYWORD', value: 'var' }, - { type: 'IDENTIFIER', value: 'typeOfScore' }, - { type: 'OPERATOR', value: '=' }, - { type: 'STRING', value: '' }, - { type: 'PUNCTUATION', value: ';' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'DECLARATION_KEYWORD', value: 'var' }, - { type: 'IDENTIFIER', value: 'PAT' }, - { type: 'OPERATOR', value: '=' }, - { type: 'STRING', value: '' }, - { type: 'PUNCTUATION', value: ';' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'STATEMENT_KEYWORD', value: 'while' }, - { type: 'IDENTIFIER', value: 'gameInProgress' }, - { type: 'PUNCTUATION', value: '{' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'STATEMENT_KEYWORD', value: 'if' }, - { type: 'PUNCTUATION', value: '(' }, - { type: 'IDENTIFIER', value: 'typeOfScore' }, - { type: 'OPERATOR', value: '!' }, - { type: 'OPERATOR', value: '=' }, - { type: 'STRING', value: '' }, - { type: 'PUNCTUATION', value: ')' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '{' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'STATEMENT_KEYWORD', value: 'if' }, - { type: 'IDENTIFIER', value: 'typeOfScore' }, - { type: 'OPERATOR', value: '=' }, - { type: 'OPERATOR', value: '=' }, - { type: 'STRING', value: 'TD' }, - { type: 'PUNCTUATION', value: '{' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'IDENTIFIER', value: 'score' }, - { type: 'OPERATOR', value: '+' }, - { type: 'OPERATOR', value: '=' }, - { type: 'NUMBER', value: '6' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '}' }, - { type: 'STATEMENT_KEYWORD', value: 'else' }, - { type: 'STATEMENT_KEYWORD', value: 'if' }, - { type: 'IDENTIFIER', value: 'typeOfScore' }, - { type: 'OPERATOR', value: '=' }, - { type: 'OPERATOR', value: '=' }, - { type: 'STRING', value: 'PAT' }, - { type: 'PUNCTUATION', value: '{' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'STATEMENT_KEYWORD', value: 'if' }, - { type: 'IDENTIFIER', value: 'PAT' }, - { type: 'OPERATOR', value: '=' }, - { type: 'OPERATOR', value: '=' }, - { type: 'STRING', value: 'TD' }, - { type: 'PUNCTUATION', value: '{' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'IDENTIFIER', value: 'score' }, - { type: 'OPERATOR', value: '+' }, - { type: 'OPERATOR', value: '=' }, - { type: 'NUMBER', value: '2' }, - { type: 'PUNCTUATION', value: ';' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '}' }, - { type: 'STATEMENT_KEYWORD', value: 'else' }, - { type: 'PUNCTUATION', value: '{' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'IDENTIFIER', value: 'score' }, - { type: 'OPERATOR', value: '+' }, - { type: 'OPERATOR', value: '=' }, - { type: 'NUMBER', value: '1' }, - { type: 'PUNCTUATION', value: ';' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '}' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '}' }, - { type: 'STATEMENT_KEYWORD', value: 'else' }, - { type: 'STATEMENT_KEYWORD', value: 'if' }, - { type: 'PUNCTUATION', value: '(' }, - { type: 'IDENTIFIER', value: 'typeOfScore' }, - { type: 'OPERATOR', value: '=' }, - { type: 'OPERATOR', value: '=' }, - { type: 'STRING', value: 'FG' }, - { type: 'PUNCTUATION', value: ')' }, - { type: 'PUNCTUATION', value: '{' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'IDENTIFIER', value: 'score' }, - { type: 'OPERATOR', value: '+' }, - { type: 'OPERATOR', value: '=' }, - { type: 'NUMBER', value: '3' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '}' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'STATEMENT_KEYWORD', value: 'else' }, - { type: 'PUNCTUATION', value: '{' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'IDENTIFIER', value: 'score' }, - { type: 'OPERATOR', value: '+' }, - { type: 'OPERATOR', value: '=' }, - { type: 'NUMBER', value: '2' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '}' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'IDENTIFIER', value: 'typeOfScore' }, - { type: 'OPERATOR', value: '=' }, - { type: 'STRING', value: '' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '}' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'PUNCTUATION', value: '}' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: 'EOF' } + //{ type: "DECLARATION_KEYWORD", value: "var" }, + //{ type: "IDENTIFIER", value: "console" }, + //{ type: "OPERATOR", value: "=" }, + //{ type: "DICTIONARY_START", value: "[" }, + //{ type: "DICTIONARY_END", value: "]" }, + //{ type: "PUNCTUATION", value: ";"}, + { type: "NATIVE_METHOD", value: "print"}, + //{ type: "INVOCATION_START", value: "(" }, + { type: "PUNCTUATION", value: "(" }, + { type: "STRING", value: "Hello" }, + //{ type: "INVOCATION_END", value: ")" }, + { type: "PUNCTUATION", value: ")" }, + + { type: "TERMINATOR", value: "EOF" }, ]; var parser = makeParse(); diff --git a/transpiler/parser/rearrangeTokensPrintToConsoleLog.js b/transpiler/parser/rearrangeTokensPrintToConsoleLog.js new file mode 100644 index 0000000..114c1dd --- /dev/null +++ b/transpiler/parser/rearrangeTokensPrintToConsoleLog.js @@ -0,0 +1,31 @@ +var util = require('util'); + +var rearrangeTokensPrintToConsoleLog = function(tokens) { + + var reformat = false; + var nativePrintIndices = []; + + for(var i=0; i=0; j--) { + var index = nativePrintIndices[j]; + tokens.splice(index, 1, + { type: "IDENTIFIER", value: "console" }, + { type: "OPERATOR", value: "." }, + { type: "IDENTIFIER", value: "log" }); + } + } + + console.log(util.inspect(tokens, {colors:true, depth:null})); + return tokens; +}; + +module.exports = rearrangeTokensPrintToConsoleLog; \ No newline at end of file diff --git a/transpiler/parser/statement.js b/transpiler/parser/statement.js index 4da75c3..94918ce 100644 --- a/transpiler/parser/statement.js +++ b/transpiler/parser/statement.js @@ -51,6 +51,10 @@ var statement = function(state) { if(state.token.value === "}") { return v; } + if (state.token.value === ')') { + state = advance(state); + } + if(state.token.value === "EOF") { return v; diff --git a/transpiler/parser/tokenTypes.js b/transpiler/parser/tokenTypes.js index c41ff55..e30c1f9 100644 --- a/transpiler/parser/tokenTypes.js +++ b/transpiler/parser/tokenTypes.js @@ -45,7 +45,7 @@ module.exports = { "COMMENT", "MULTI_LINE_COMMENT_START", "MULTI_LINE_COMMENT_END" - ] + ]//INVOCATION_START//INVOCATION_END }; From 549ad309c89e6b341fc00185abbdbbf28b06be9c Mon Sep 17 00:00:00 2001 From: Verlon Smith Date: Sat, 31 Oct 2015 14:32:33 -0600 Subject: [PATCH 2/2] Commits --- tests/lexerTests.js | 5723 ++++++++--------- tests/parserTestsSecondMilestone.js | 492 ++ transpiler/api.js | 3 +- transpiler/lexer/helperFunctions.js | 2 +- transpiler/lexer/lexer.js | 54 +- transpiler/lexer/lexicalTypes.js | 187 +- transpiler/parser/advance.js | 1 - transpiler/parser/declarations.js | 61 +- transpiler/parser/expression.js | 15 - transpiler/parser/parserRunner.js | 377 +- .../rearrangeTokensPrintToConsoleLog.js | 2 +- transpiler/parser/statement.js | 19 + transpiler/parser/tokenTypes.js | 3 +- 13 files changed, 3807 insertions(+), 3132 deletions(-) diff --git a/tests/lexerTests.js b/tests/lexerTests.js index c2065d4..665b45d 100644 --- a/tests/lexerTests.js +++ b/tests/lexerTests.js @@ -35,7 +35,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle variable names with underscores', function () { input = String.raw`var my_var = 5`; output = [ @@ -47,7 +47,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle lines that end with a semicolon', function () { input = String.raw`var myVar = 5;`; output = [ @@ -60,7 +60,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle variable declarations with erratic spacing', function () { input = String.raw`var myVar = 5 ;`; output = [ @@ -109,7 +109,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should variables declared with type annotations', function () { input = String.raw`var name: String = "Joe"; var age: Int = 45;`; @@ -150,7 +150,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle multiple related variables of the same type on a single line, separated by commas', function () { input = String.raw`var firstBase, secondBase, thirdBase: String`; @@ -214,7 +214,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle initializer syntax for arrays', function () { input = String.raw`var empty = [String]();`; output = [ @@ -224,14 +224,14 @@ describe('Lexer', function() { { type: "ARRAY_START", value: "["}, { type: "TYPE_STRING", value: "String"}, { type: "ARRAY_END", value: "]"}, - { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_START", value: "(" }, { type: "INVOCATION_END", value: ")" }, { type: "PUNCTUATION", value: ";"}, { type: "TERMINATOR", value: "EOF" } ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle initializer syntax for dictionaries', function () { input = String.raw`var empty = [String:UInt16]();`; output = [ @@ -243,7 +243,7 @@ describe('Lexer', function() { { type: "PUNCTUATION", value: ":"}, { type: "TYPE_NUMBER", value: "UInt16"}, { type: "DICTIONARY_END", value: "]"}, - { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_START", value: "(" }, { type: "INVOCATION_END", value: ")" }, { type: "PUNCTUATION", value: ";"}, { type: "TERMINATOR", value: "EOF" } @@ -287,7 +287,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle appending items to an array with the addition assignment operator', function () { input = String.raw`var arr = [Int](); arr += [1,2,3];`; output = [ @@ -297,7 +297,7 @@ describe('Lexer', function() { { type: "ARRAY_START", value: "["}, { type: "TYPE_NUMBER", value: "Int"}, { type: "ARRAY_END", value: "]"}, - { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_START", value: "(" }, { type: "INVOCATION_END", value: ")" }, { type: "PUNCTUATION", value: ";" }, { type: "IDENTIFIER", value: "arr" }, @@ -355,7 +355,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle tuples with element names', function () { input = String.raw`let http200Status = (statusCode: 200, description: "OK");`; output = [ @@ -389,7 +389,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle tuples with mixed index numbers and element names, and value lookups using both', function () { input = String.raw`var tup = ("one", two: 2); var one = tup.0; var two = tup.1; var twoRedux = tup.two;`; output = [ @@ -404,25 +404,25 @@ describe('Lexer', function() { { type: "NUMBER", value: "2"}, { type: "TUPLE_END", value: ")"}, { type: "PUNCTUATION", value: ";" }, - + { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "one" }, + { type: "IDENTIFIER", value: "one" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "tup" }, { type: "DOT_SYNTAX", value: "." }, { type: "NUMBER", value: "0"}, { type: "PUNCTUATION", value: ";" }, - + { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "two" }, + { type: "IDENTIFIER", value: "two" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "tup" }, { type: "DOT_SYNTAX", value: "." }, { type: "NUMBER", value: "1"}, { type: "PUNCTUATION", value: ";" }, - + { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "twoRedux" }, + { type: "IDENTIFIER", value: "twoRedux" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "tup" }, { type: "DOT_SYNTAX", value: "." }, @@ -456,7 +456,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle subscript lookups on arrays', function () { input = String.raw`var d = [1, 2]; var one = d[0];`; output = [ @@ -476,12 +476,12 @@ describe('Lexer', function() { { type: "SUBSTRING_LOOKUP_START", value: "[" }, { type: "NUMBER", value: "0" }, { type: "SUBSTRING_LOOKUP_END", value: "]" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle subscript lookups on dictionaries', function () { input = String.raw`var d = ["one": 1, "two": 2]; var one = d["one"];`; @@ -506,7 +506,7 @@ describe('Lexer', function() { { type: "SUBSTRING_LOOKUP_START", value: "[" }, { type: "STRING", value: "one" }, { type: "SUBSTRING_LOOKUP_END", value: "]" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -593,7 +593,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle complex comparisons', function () { input = String.raw`var l = 6 != 7 || 6 == 7 || 6 > 7 || 6 < 7 || 6 >= 7 || 6 <= 7;`; output = [ @@ -810,17 +810,17 @@ describe('Lexer', function() { { type: "NUMBER", value: "6" }, { type: "OPERATOR", value: "=" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "7" }, + { type: "NUMBER", value: "7" }, { type: "OPERATOR", value: "?" }, - { type: "BOOLEAN", value: "true" }, - { type: "PUNCTUATION", value: ":" }, - { type: "BOOLEAN", value: "false" }, - { type: "PUNCTUATION", value: ";" }, + { type: "BOOLEAN", value: "true" }, + { type: "PUNCTUATION", value: ":" }, + { type: "BOOLEAN", value: "false" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle ternary operators that include identifiers', function () { input = String.raw`let h = false; let i = h ? 1 : 2;`; output = [ @@ -834,15 +834,15 @@ describe('Lexer', function() { { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "h" }, { type: "OPERATOR", value: "?" }, - { type: "NUMBER", value: "1" }, + { type: "NUMBER", value: "1" }, { type: "PUNCTUATION", value: ":" }, - { type: "NUMBER", value: "2" }, - { type: "PUNCTUATION", value: ";" }, + { type: "NUMBER", value: "2" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); }); - + }); describe('String concatenation and interpolation', function () { @@ -924,7 +924,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle interpolation containing operations on identifiers', function () { input = String.raw`let a = 3; let b = 5; let sum = "the sum of a and b is \(a + b).";`; output = [ @@ -1070,7 +1070,7 @@ describe('Lexer', function() { { type: "ARRAY_END", value: "]" }, { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF" } - ]; + ]; expect(lexer(input)).to.deep.equal(output); }); @@ -1136,74 +1136,74 @@ describe('Lexer', function() { it('should handle translation of dictionary keys', function () { input = String.raw `var firstNum = 1 - var secondNum = 2 - var firstDict = [firstNum: ["one", "two"], secondNum: ["three", "four"]] - var secondDict = [-3+4: [1,2], (2*3)-4: [3,4]]`; + var secondNum = 2 + var firstDict = [firstNum: ["one", "two"], secondNum: ["three", "four"]] + var secondDict = [-3+4: [1,2], (2*3)-4: [3,4]]`; output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "firstNum" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "secondNum" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "2" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "firstDict" }, - { type: "OPERATOR", value: "=" }, - { type: "DICTIONARY_START", value: "[" }, - { type: "IDENTIFIER", value: "firstNum" }, - { type: "PUNCTUATION", value: ":" }, - { type: "ARRAY_START", value: "[" }, - { type: "STRING", value: "one" }, - { type: "PUNCTUATION", value: "," }, - { type: "STRING", value: "two" }, - { type: "ARRAY_END", value: "]" }, - { type: "PUNCTUATION", value: "," }, - { type: "IDENTIFIER", value: "secondNum" }, - { type: "PUNCTUATION", value: ":" }, - { type: "ARRAY_START", value: "[" }, - { type: "STRING", value: "three" }, - { type: "PUNCTUATION", value: "," }, - { type: "STRING", value: "four" }, - { type: "ARRAY_END", value: "]" }, - { type: "DICTIONARY_END", value: "]" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "secondDict" }, - { type: "OPERATOR", value: "=" }, - { type: "DICTIONARY_START", value: "[" }, - { type: "OPERATOR", value: "-" }, - { type: "NUMBER", value: "3" }, - { type: "OPERATOR", value: "+" }, - { type: "NUMBER", value: "4" }, - { type: "PUNCTUATION", value: ":" }, - { type: "ARRAY_START", value: "[" }, - { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: "," }, - { type: "NUMBER", value: "2" }, - { type: "ARRAY_END", value: "]" }, - { type: "PUNCTUATION", value: "," }, - { type: "PUNCTUATION", value: "(" }, - { type: "NUMBER", value: "2" }, - { type: "OPERATOR", value: "*" }, - { type: "NUMBER", value: "3" }, - { type: "PUNCTUATION", value: ")" }, - { type: "OPERATOR", value: "-" }, - { type: "NUMBER", value: "4" }, - { type: "PUNCTUATION", value: ":" }, - { type: "ARRAY_START", value: "[" }, - { type: "NUMBER", value: "3" }, - { type: "PUNCTUATION", value: "," }, - { type: "NUMBER", value: "4" }, - { type: "ARRAY_END", value: "]" }, - { type: "DICTIONARY_END", value: "]" }, - { type: "TERMINATOR", value: "EOF" } + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "firstNum" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "secondNum" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "2" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "firstDict" }, + { type: "OPERATOR", value: "=" }, + { type: "DICTIONARY_START", value: "[" }, + { type: "IDENTIFIER", value: "firstNum" }, + { type: "PUNCTUATION", value: ":" }, + { type: "ARRAY_START", value: "[" }, + { type: "STRING", value: "one" }, + { type: "PUNCTUATION", value: "," }, + { type: "STRING", value: "two" }, + { type: "ARRAY_END", value: "]" }, + { type: "PUNCTUATION", value: "," }, + { type: "IDENTIFIER", value: "secondNum" }, + { type: "PUNCTUATION", value: ":" }, + { type: "ARRAY_START", value: "[" }, + { type: "STRING", value: "three" }, + { type: "PUNCTUATION", value: "," }, + { type: "STRING", value: "four" }, + { type: "ARRAY_END", value: "]" }, + { type: "DICTIONARY_END", value: "]" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "secondDict" }, + { type: "OPERATOR", value: "=" }, + { type: "DICTIONARY_START", value: "[" }, + { type: "OPERATOR", value: "-" }, + { type: "NUMBER", value: "3" }, + { type: "OPERATOR", value: "+" }, + { type: "NUMBER", value: "4" }, + { type: "PUNCTUATION", value: ":" }, + { type: "ARRAY_START", value: "[" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: "," }, + { type: "NUMBER", value: "2" }, + { type: "ARRAY_END", value: "]" }, + { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "(" }, + { type: "NUMBER", value: "2" }, + { type: "OPERATOR", value: "*" }, + { type: "NUMBER", value: "3" }, + { type: "PUNCTUATION", value: ")" }, + { type: "OPERATOR", value: "-" }, + { type: "NUMBER", value: "4" }, + { type: "PUNCTUATION", value: ":" }, + { type: "ARRAY_START", value: "[" }, + { type: "NUMBER", value: "3" }, + { type: "PUNCTUATION", value: "," }, + { type: "NUMBER", value: "4" }, + { type: "ARRAY_END", value: "]" }, + { type: "DICTIONARY_END", value: "]" }, + { type: "TERMINATOR", value: "EOF" } ]; expect(lexer(input)).to.deep.equal(output); }); @@ -1256,7 +1256,7 @@ describe('Lexer', function() { }); describe('Second milestone', function() { - + describe('Single-Line If statements', function() { it('should handle single-line if statements', function() { @@ -1275,8 +1275,8 @@ describe('Lexer', function() { { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: "}" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1295,14 +1295,14 @@ describe('Lexer', function() { { type: "NUMBER", value: "5" }, { type: "OPERATOR", value: "<" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "6" }, + { type: "NUMBER", value: "6" }, { type: "PUNCTUATION", value: ")" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "b" }, { type: "OPERATOR", value: "+" }, { type: "OPERATOR", value: "+" }, - { type: "PUNCTUATION", value: "}" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1321,15 +1321,15 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "c" }, { type: "OPERATOR", value: "=" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, + { type: "NUMBER", value: "1" }, { type: "PUNCTUATION", value: ")" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "c" }, { type: "OPERATOR", value: "*" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "5" }, - { type: "PUNCTUATION", value: "}" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1347,13 +1347,13 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "d" }, { type: "OPERATOR", value: "!" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "2" }, + { type: "NUMBER", value: "2" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "d" }, { type: "OPERATOR", value: "+" }, { type: "OPERATOR", value: "+" }, - { type: "PUNCTUATION", value: "}" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1371,17 +1371,17 @@ describe('Lexer', function() { { type: "PUNCTUATION", value: "(" }, { type: "IDENTIFIER", value: "e" }, { type: "OPERATOR", value: "+" }, - { type: "NUMBER", value: "1" }, + { type: "NUMBER", value: "1" }, { type: "PUNCTUATION", value: ")" }, { type: "OPERATOR", value: "=" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "2" }, + { type: "NUMBER", value: "2" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "e" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "5" }, - { type: "PUNCTUATION", value: "}" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1401,20 +1401,20 @@ describe('Lexer', function() { { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "f" }, { type: "OPERATOR", value: "=" }, - { type: "BOOLEAN", value: "true" }, + { type: "BOOLEAN", value: "true" }, { type: "PUNCTUATION", value: "}" }, { type: "STATEMENT_KEYWORD", value: "else" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "f" }, { type: "OPERATOR", value: "=" }, - { type: "BOOLEAN", value: "false" }, + { type: "BOOLEAN", value: "false" }, { type: "PUNCTUATION", value: "}" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle single-line if/else-if/else statements with parentheticals', function() { input = String.raw`var a = 1; if (1 > 2) {++a} else if (1 < 2) {--a} else {a = 42}`; output = [ @@ -1508,17 +1508,17 @@ describe('Lexer', function() { { type: "NUMBER", value: "10" }, { type: "PUNCTUATION", value: ";" }, { type: "STATEMENT_KEYWORD", value: "while" }, - { type: "PUNCTUATION", value: "(" }, + { type: "PUNCTUATION", value: "(" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: ">" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "0" }, - { type: "PUNCTUATION", value: ")" }, + { type: "NUMBER", value: "0" }, + { type: "PUNCTUATION", value: ")" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1536,12 +1536,12 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: ">" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "0" }, + { type: "NUMBER", value: "0" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1560,14 +1560,14 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "STATEMENT_KEYWORD", value: "while" }, - { type: "PUNCTUATION", value: "(" }, + { type: "PUNCTUATION", value: "(" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: ">" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "0" }, - { type: "PUNCTUATION", value: ")" }, + { type: "NUMBER", value: "0" }, + { type: "PUNCTUATION", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1586,12 +1586,12 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "STATEMENT_KEYWORD", value: "while" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: ">" }, { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "0" }, + { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -1610,7 +1610,7 @@ describe('Lexer', function() { { type: "NUMBER", value: "0" }, { type: "PUNCTUATION", value: ";" }, { type: "STATEMENT_KEYWORD", value: "for" }, - { type: "PUNCTUATION", value: "(" }, + { type: "PUNCTUATION", value: "(" }, { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: "=" }, @@ -1623,7 +1623,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, - { type: "PUNCTUATION", value: ")" }, + { type: "PUNCTUATION", value: ")" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "+" }, @@ -1697,7 +1697,7 @@ describe('Lexer', function() { { type: "STATEMENT_KEYWORD", value: "for" }, { type: "IDENTIFIER", value: "n" }, { type: "STATEMENT_KEYWORD", value: "in" }, - { type: "IDENTIFIER", value: "numbers" }, + { type: "IDENTIFIER", value: "numbers" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "c" }, { type: "OPERATOR", value: "+" }, @@ -1739,7 +1739,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "n" }, { type: "PUNCTUATION", value: ")" }, { type: "STATEMENT_KEYWORD", value: "in" }, - { type: "IDENTIFIER", value: "numbers" }, + { type: "IDENTIFIER", value: "numbers" }, { type: "PUNCTUATION", value: "{" }, { type: "IDENTIFIER", value: "c" }, { type: "OPERATOR", value: "+" }, @@ -1757,7 +1757,7 @@ describe('Lexer', function() { describe('Multi-line statements', function() { it('should handle simple multi-line variable assignment', function() { input = String.raw`var b = true; - var c = 0;`; + var c = 0;`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "b" }, @@ -1774,11 +1774,11 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle complex multi-line variable assignment without semi-colons', function() { input = String.raw`var e = ["Eggs", "Milk", "Bacon"] - var f = ["one": 1, "two": 2, "three": 3] - let g = [1 : "one",2 :"two", 3: "three"]`; + var f = ["one": 1, "two": 2, "three": 3] + let g = [1 : "one",2 :"two", 3: "three"]`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "e" }, @@ -1828,13 +1828,13 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }) - + it('should handle simple multi-line variable assignment with type annotations', function() { input = String.raw`var name: String = "Joe" - let num: Int = 5; - let anotherNum: UInt16 = 6 - var yetAnotherNum: Float = 4.2; - let truth: Bool = false + let num: Int = 5; + let anotherNum: UInt16 = 6 + var yetAnotherNum: Float = 4.2; + let truth: Bool = false `; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, @@ -1878,7 +1878,7 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle successive single-line comments', function() { input = String.raw`// function body goes here // firstParameterName and secondParameterName refer to @@ -1897,13 +1897,13 @@ describe('Lexer', function() { { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); - }); - + }); + it('should handle multi-line comments', function() { input = String.raw`/* - Comment 1 - Comment 2 - */ + Comment 1 + Comment 2 + */ `; output = [ { type: "MULTI_LINE_COMMENT_START", value: "/*"}, @@ -1917,17 +1917,17 @@ describe('Lexer', function() { { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); - }); - + }); + }); describe('Multi-line if statements', function() { it('should handle simple multi-line if statements', function() { input = String.raw`var a = false - var b = 0; - if (a) { - b++; - }`; + var b = 0; + if (a) { + b++; + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "a" }, @@ -1951,18 +1951,18 @@ describe('Lexer', function() { { type: "OPERATOR", value: "+" }, { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "EOF"}, ] expect(lexer(input)).to.deep.equal(output); }); - + it('should handle simple multi-line if statements with complex conditions', function() { input = String.raw`var diceRoll = 6; - if ++diceRoll == 7 { - diceRoll = 1 - }`; + if ++diceRoll == 7 { + diceRoll = 1 + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "diceRoll" }, @@ -1972,7 +1972,7 @@ describe('Lexer', function() { { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "if" }, { type: "OPERATOR", value: "+" }, - { type: "OPERATOR", value: "+" }, + { type: "OPERATOR", value: "+" }, { type: "IDENTIFIER", value: "diceRoll" }, { type: "OPERATOR", value: "=" }, { type: "OPERATOR", value: "=" }, @@ -1983,7 +1983,7 @@ describe('Lexer', function() { { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "1" }, { type: "TERMINATOR", value: "\\n"}, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "EOF"}, ] expect(lexer(input)).to.deep.equal(output); @@ -1992,20 +1992,20 @@ describe('Lexer', function() { it('should handle simple multi-line nested if statements', function() { input = String.raw`var x = true - var y = false; - var a = "" - var z; - if (x) { - if y { - z = true; - } else if (true) { - a = "<3 JS"; - } else { - a = "never get here"; - } - } else { - a = "x is false"; - }`; + var y = false; + var a = "" + var z; + if (x) { + if y { + z = true; + } else if (true) { + a = "<3 JS"; + } else { + a = "never get here"; + } + } else { + a = "x is false"; + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "x" }, @@ -2043,7 +2043,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "z" }, { type: "OPERATOR", value: "=" }, { type: "BOOLEAN", value: "true" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, { type: "PUNCTUATION", value: "}" }, @@ -2058,7 +2058,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "=" }, { type: "STRING", value: "<3 JS" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, { type: "PUNCTUATION", value: "}" }, @@ -2069,7 +2069,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "=" }, { type: "STRING", value: "never get here" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, { type: "PUNCTUATION", value: "}" }, @@ -2083,23 +2083,23 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "=" }, { type: "STRING", value: "x is false" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "EOF"}, ] expect(lexer(input)).to.deep.equal(output); - }); + }); }); describe('Multi-line for loops', function() { it('should handle simple multi-line for loops', function() { input = String.raw`var b = 0; - for var i = 0; i < 10; i++ { - b++ - }`; + for var i = 0; i < 10; i++ { + b++ + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "b" }, @@ -2131,15 +2131,15 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + it('should handle multi-line nested for loops', function() { input = String.raw`var arrays = [[1,2,3], [4,5,6], [7,8,9]] - var total = 0 - for (var i = 0; i < 3; i++) { - for var j = 0; j < 3; j++ { - total += arrays[i][j] - } - }`; + var total = 0 + for (var i = 0; i < 3; i++) { + for var j = 0; j < 3; j++ { + total += arrays[i][j] + } + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "arrays" }, @@ -2225,15 +2225,15 @@ describe('Lexer', function() { ]; expect(lexer(input)).to.deep.equal(output); }); - + }); describe('Multi-line for-in loops', function() { it('should handle simple multi-line for-in loops', function() { input = String.raw`var c = 0 - var numbers = [1,2,3,4,5] - for n in numbers { - c += n - }`; + var numbers = [1,2,3,4,5] + for n in numbers { + c += n + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "c" }, @@ -2258,7 +2258,7 @@ describe('Lexer', function() { { type: "STATEMENT_KEYWORD", value: "for" }, { type: "IDENTIFIER", value: "n" }, { type: "STATEMENT_KEYWORD", value: "in" }, - { type: "IDENTIFIER", value: "numbers" }, + { type: "IDENTIFIER", value: "numbers" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "c" }, @@ -2274,9 +2274,9 @@ describe('Lexer', function() { it('handle for-in loops that iterate over a range', function () { input = String.raw`var sum = 0 - for i in 0..<5 { - sum += i - }`;; + for i in 0..<5 { + sum += i + }`;; output = [ { type: 'DECLARATION_KEYWORD', value: 'var' }, { type: 'IDENTIFIER', value: 'sum' }, @@ -2304,18 +2304,18 @@ describe('Lexer', function() { it('should handle for-in loops that iterate over items in a dictionary', function () { input = String.raw`let interestingNumbers = [ - "Prime": [2, 3, 5, 7, 11, 13], - "Fibonacci": [1, 1, 2, 3, 5, 8], - "Square": [1, 4, 9, 16, 25], - ] - var largest = 0 - for (kind, numbers) in interestingNumbers { - for number in numbers { - if number > largest { - largest = number - } - } - }`;; + "Prime": [2, 3, 5, 7, 11, 13], + "Fibonacci": [1, 1, 2, 3, 5, 8], + "Square": [1, 4, 9, 16, 25], + ] + var largest = 0 + for (kind, numbers) in interestingNumbers { + for number in numbers { + if number > largest { + largest = number + } + } + }`;; output = [ { type: 'DECLARATION_KEYWORD', value: 'let' }, { type: 'IDENTIFIER', value: 'interestingNumbers' }, @@ -2385,13 +2385,13 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "numbers" }, { type: 'PUNCTUATION', value: ')' }, { type: "STATEMENT_KEYWORD", value: "in" }, - { type: "IDENTIFIER", value: "interestingNumbers" }, + { type: "IDENTIFIER", value: "interestingNumbers" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "for" }, { type: "IDENTIFIER", value: "number" }, { type: "STATEMENT_KEYWORD", value: "in" }, - { type: "IDENTIFIER", value: "numbers" }, + { type: "IDENTIFIER", value: "numbers" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "if" }, @@ -2415,14 +2415,14 @@ describe('Lexer', function() { }); }); - + describe('Multi-Line While/Repeat-While loops', function() { - + it('should handle multi-line while loops without a parenthetical', function() { - input = String.raw`var i = 10; - while i >= 0 { - i-- - }`; + input = String.raw`var i = 10; + while i >= 0 { + i-- + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "i" }, @@ -2441,17 +2441,17 @@ describe('Lexer', function() { { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, { type: "TERMINATOR", value: "\\n"}, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); }); it('should handle multi-line while loops with a parenthetical', function() { - input = String.raw`var i = 10; - while (i >= 0) { - i-- - }`; + input = String.raw`var i = 10; + while (i >= 0) { + i-- + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "i" }, @@ -2472,17 +2472,17 @@ describe('Lexer', function() { { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, { type: "TERMINATOR", value: "\\n"}, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); - }); + }); it('should handle multi-line repeat-while loops with a parenthetical', function() { input = String.raw`var i = 10; - repeat { - i-- - } while (i > 0);`; + repeat { + i-- + } while (i > 0);`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "i" }, @@ -2497,13 +2497,13 @@ describe('Lexer', function() { { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, { type: "TERMINATOR", value: "\\n"}, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "STATEMENT_KEYWORD", value: "while" }, - { type: "PUNCTUATION", value: "(" }, + { type: "PUNCTUATION", value: "(" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: ">" }, - { type: "NUMBER", value: "0" }, - { type: "PUNCTUATION", value: ")" }, + { type: "NUMBER", value: "0" }, + { type: "PUNCTUATION", value: ")" }, { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; @@ -2512,9 +2512,9 @@ describe('Lexer', function() { it('should handle multi-line repeat-while loops without a parenthetical', function() { input = String.raw`var i = 10 - repeat { - i-- - } while i > 0`; + repeat { + i-- + } while i > 0`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "i" }, @@ -2528,33 +2528,33 @@ describe('Lexer', function() { { type: "OPERATOR", value: "-" }, { type: "OPERATOR", value: "-" }, { type: "TERMINATOR", value: "\\n"}, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "STATEMENT_KEYWORD", value: "while" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: ">" }, - { type: "NUMBER", value: "0" }, + { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); }); - + }); - + describe('Switch Statements', function() { - + it('should handle multi-line switch statements', function() { input = String.raw`var x = 2 - var y = ""; - switch x { - case 1,2,3: - y += "positive"; - case -1,-2,-3: - y += "negative"; - case 0: - y += "zero"; - default: - y += "dunno"; - }`; + var y = ""; + switch x { + case 1,2,3: + y += "positive"; + case -1,-2,-3: + y += "negative"; + case 0: + y += "zero"; + default: + y += "dunno"; + }`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "x" }, @@ -2568,14 +2568,14 @@ describe('Lexer', function() { { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "switch" }, - { type: "IDENTIFIER", value: "x" }, + { type: "IDENTIFIER", value: "x" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "case" }, { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "," }, { type: "NUMBER", value: "2" }, - { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "," }, { type: "NUMBER", value: "3" }, { type: "PUNCTUATION", value: ":" }, { type: "TERMINATOR", value: "\\n"}, @@ -2588,10 +2588,10 @@ describe('Lexer', function() { { type: "STATEMENT_KEYWORD", value: "case" }, { type: "OPERATOR", value: "-" }, { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: "," }, - { type: "OPERATOR", value: "-" }, + { type: "PUNCTUATION", value: "," }, + { type: "OPERATOR", value: "-" }, { type: "NUMBER", value: "2" }, - { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "," }, { type: "OPERATOR", value: "-" }, { type: "NUMBER", value: "3" }, { type: "PUNCTUATION", value: ":" }, @@ -2621,38 +2621,38 @@ describe('Lexer', function() { { type: "STRING", value: "dunno" }, { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, - { type: "PUNCTUATION", value: "}" }, + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "EOF"}, ]; expect(lexer(input)).to.deep.equal(output); }); }); - + describe('Complex Control Flow', function () { it('shold handle nested if-else statements within a loop', function () { input = String.raw`var gameInProgress = false; - var score = 0; - var typeOfScore = ""; - var PAT = ""; - while gameInProgress { - if typeOfScore != "" { - if typeOfScore == "TD" { - score += 6 - } else if typeOfScore == "PAT" { - if PAT == "TD" { - score += 2 - } else { - score += 1 - } - } else if typeOfScore == "FG" { - score += 3 - } else { - score += 2 - } - typeOfScore = "" - } - } + var score = 0; + var typeOfScore = ""; + var PAT = ""; + while gameInProgress { + if typeOfScore != "" { + if typeOfScore == "TD" { + score += 6 + } else if typeOfScore == "PAT" { + if PAT == "TD" { + score += 2 + } else { + score += 1 + } + } else if typeOfScore == "FG" { + score += 3 + } else { + score += 2 + } + typeOfScore = "" + } + } `; output = [ { type: 'DECLARATION_KEYWORD', value: 'var' }, @@ -2767,7 +2767,7 @@ describe('Lexer', function() { { type: 'TERMINATOR', value: '\\n' }, { type: 'PUNCTUATION', value: '}' }, { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: 'EOF' } + { type: 'TERMINATOR', value: 'EOF' } ]; expect(lexer(input)).to.deep.equal(output); }); @@ -2779,37 +2779,37 @@ describe('Lexer', function() { var gameInProgress = false; - var score = 0 - - var typeOfScore = ""; - var PAT = ""; - - - while gameInProgress { - if (typeOfScore != "") - { - if typeOfScore == "TD" { - score += 6 - } else if typeOfScore == "PAT" { - if PAT == "TD" { - - score += 2; - } else { - score += 1; - - - } - } else if (typeOfScore == "FG") { - score += 3 - } - - else { - - score += 2 - } - typeOfScore = "" - } - } + var score = 0 + + var typeOfScore = ""; + var PAT = ""; + + + while gameInProgress { + if (typeOfScore != "") + { + if typeOfScore == "TD" { + score += 6 + } else if typeOfScore == "PAT" { + if PAT == "TD" { + + score += 2; + } else { + score += 1; + + + } + } else if (typeOfScore == "FG") { + score += 3 + } + + else { + + score += 2 + } + typeOfScore = "" + } + } `; output = [ @@ -2946,35 +2946,35 @@ describe('Lexer', function() { { type: 'PUNCTUATION', value: '}' }, { type: 'TERMINATOR', value: '\\n' }, { type: 'TERMINATOR', value: '\\n' }, - { type: 'TERMINATOR', value: 'EOF' } + { type: 'TERMINATOR', value: 'EOF' } ]; expect(lexer(input)).to.deep.equal(output); }); - }); - + }); + describe('Third Milestone', function() { - + describe('Functions', function() { it('should handle function declaration and invocation with no spacing and with var in function parameters', function() { input = String.raw`func someFunction(a: Int) -> Int { - a = a + 1; - return a; - } - someFunction(5);`; + a = a + 1; + return a; + } + someFunction(5);`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "someFunction" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "=" }, @@ -2990,32 +2990,32 @@ describe('Lexer', function() { { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "someFunction" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, - { type: "PUNCTUATION", value: ";" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "INVOCATION_END", value: ")" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); }); - + it('should handle function declaration and invocation with no spacing', function() { input = String.raw`func someFunction(a: Int)->Int{ - let a = a + 1; - return a - } - someFunction(5);`; + let a = a + 1; + return a + } + someFunction(5);`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "someFunction" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "let"}, { type: "IDENTIFIER", value: "a" }, @@ -3023,7 +3023,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "+" }, { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "a" }, @@ -3031,33 +3031,33 @@ describe('Lexer', function() { { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "someFunction" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, - { type: "PUNCTUATION", value: ";" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "INVOCATION_END", value: ")" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); }); - - it('should handle function declaration and invocation with spaces between each part of the declaration', function() { + + it('should handle function declaration and invocation with spaces between each part of the declaration', function() { input = String.raw`func someFunction (a: Int) -> Int { - let a = a + 1; - return a - } - someFunction(5);` + let a = a + 1; + return a + } + someFunction(5);` output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "someFunction" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "let"}, { type: "IDENTIFIER", value: "a" }, @@ -3065,7 +3065,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "+" }, { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "a" }, @@ -3073,32 +3073,32 @@ describe('Lexer', function() { { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "someFunction" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, - { type: "PUNCTUATION", value: ";" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "INVOCATION_END", value: ")" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); }); - + it('should handle function declaration and invocation with no space after the function name', function() { input = String.raw`func someFunction(a: Int) -> Int { - let a = a + 1; - return a - } - someFunction(5);`; + let a = a + 1; + return a + } + someFunction(5);`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "someFunction" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "let"}, { type: "IDENTIFIER", value: "a" }, @@ -3106,7 +3106,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "+" }, { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "a" }, @@ -3114,10 +3114,10 @@ describe('Lexer', function() { { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "someFunction" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, - { type: "PUNCTUATION", value: ";" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "INVOCATION_END", value: ")" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); @@ -3125,62 +3125,62 @@ describe('Lexer', function() { it('should handle function declaration and invocation with no space after the parameter declaration', function() { input = String.raw`func someFunction(a: Int)-> Int { - let a = a + 1; - return a - } - someFunction(5);` + let a = a + 1; + return a + } + someFunction(5);` output = [ - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "someFunction" }, - { type: "PARAMS_START", value: "(" }, - { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "DECLARATION_KEYWORD", value: "let"}, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "+" }, - { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: ";" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "IDENTIFIER", value: "a" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}"}, - { type: "TERMINATOR", value: "\\n"}, - { type: "IDENTIFIER", value: "someFunction" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, - { type: "PUNCTUATION", value: ";" }, - { type: "TERMINATOR", value: "EOF"} + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "someFunction" }, + { type: "PARAMS_START", value: "(" }, + { type: "IDENTIFIER", value: "a" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "DECLARATION_KEYWORD", value: "let"}, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "+" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: ";" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "IDENTIFIER", value: "a" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "STATEMENTS_END", value: "}"}, + { type: "TERMINATOR", value: "\\n"}, + { type: "IDENTIFIER", value: "someFunction" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "INVOCATION_END", value: ")" }, + { type: "PUNCTUATION", value: ";" }, + { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); }); it('should handle function declaration and invocation with erratic spacing', function() { input = String.raw`func someFunction(a: Int) -> Int{ - let a = a + 1; - return a - } - someFunction (5) ;`; + let a = a + 1; + return a + } + someFunction (5) ;`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "someFunction" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "let"}, { type: "IDENTIFIER", value: "a" }, @@ -3188,7 +3188,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "+" }, { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: ";" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "a" }, @@ -3196,10 +3196,10 @@ describe('Lexer', function() { { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "someFunction" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, - { type: "PUNCTUATION", value: ";" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "INVOCATION_END", value: ")" }, + { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); @@ -3207,21 +3207,21 @@ describe('Lexer', function() { it('should handle functions that return strings', function() { input = String.raw`func sayHelloWorld() -> String { - return "hello, world" - }`; + return "hello, world" + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "sayHelloWorld" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "STRING", value: "hello, world" }, + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STRING", value: "hello, world" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}"}, + { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); @@ -3229,34 +3229,34 @@ describe('Lexer', function() { it('should handle functions with an input that return strings', function() { input = String.raw`func sayHello(personName: String) -> String { - let greeting = "Hello, " + personName + "!" - return greeting - }`; + let greeting = "Hello, " + personName + "!" + return greeting + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "sayHello" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "personName" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_STRING", value: "String" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_STRING", value: "String" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "greeting" }, { type: "OPERATOR", value: "=" }, - { type: "STRING", value: "Hello, " }, - { type: "OPERATOR", value: "+" }, + { type: "STRING", value: "Hello, " }, + { type: "OPERATOR", value: "+" }, { type: "IDENTIFIER", value: "personName" }, { type: "OPERATOR", value: "+" }, - { type: "STRING", value: "!" }, + { type: "STRING", value: "!" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "IDENTIFIER", value: "greeting" }, + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "IDENTIFIER", value: "greeting" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}"}, + { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); @@ -3264,25 +3264,25 @@ describe('Lexer', function() { it('should handle functions that have if else statements that use curly braces and have a return value', function() { input = String.raw`func sayHello(alreadyGreeted: Bool) -> String { - if alreadyGreeted { - return "blah" - } else { - return "hello" - } - } - - sayHello(true)`; + if alreadyGreeted { + return "blah" + } else { + return "hello" + } + } + + sayHello(true)`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "sayHello" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "alreadyGreeted" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_BOOLEAN", value: "Bool" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_BOOLEAN", value: "Bool" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "if" }, @@ -3290,30 +3290,30 @@ describe('Lexer', function() { { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "STRING", value: "blah" }, + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STRING", value: "blah" }, { type: "TERMINATOR", value: "\\n"}, { type: "PUNCTUATION", value: "}" }, { type: "STATEMENT_KEYWORD", value: "else" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "STRING", value: "hello" }, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STRING", value: "hello" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}" }, + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "sayHello" }, { type: "INVOCATION_START", value: "(" }, - { type: "BOOLEAN", value: "true" }, - { type: "INVOCATION_END", value: ")" }, + { type: "BOOLEAN", value: "true" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ] expect(lexer(input)).to.deep.equal(output); @@ -3321,38 +3321,38 @@ describe('Lexer', function() { it('should handle nested functions with function invocation', function() { input = String.raw`func sayHello(firstName: String, lastName: String) -> String { - func giveString() -> String { - return firstName + " " + lastName - } - return giveString() - }`; + func giveString() -> String { + return firstName + " " + lastName + } + return giveString() + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "sayHello" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "firstName" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_STRING", value: "String" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_STRING", value: "String" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "lastName" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_STRING", value: "String" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_STRING", value: "String" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "giveString" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "firstName" }, { type: "OPERATOR", value: "+" }, { type: "STRING", value: " " }, @@ -3360,16 +3360,16 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "lastName" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}" }, + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "giveString" }, - { type: "INVOCATION_START", value: "(" }, - { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}" }, + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -3377,24 +3377,24 @@ describe('Lexer', function() { it('should handle functions with string interpolation', function () { input = String.raw`func greet(name: String, day: String) -> String { - return "Hello \(name), today is \(day)." - } - greet("Bob", day: "Tuesday")`; + return "Hello \(name), today is \(day)." + } + greet("Bob", day: "Tuesday")`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "greet" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "name" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_STRING", value: "String" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_STRING", value: "String" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "day" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_STRING", value: "String" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_STRING", value: "String" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENT_KEYWORD", value: "return"}, { type: "STRING", value: "Hello " }, @@ -3410,13 +3410,13 @@ describe('Lexer', function() { { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "greet" }, - { type: "INVOCATION_START", value: "(" }, - { type: "STRING", value: "Bob" }, + { type: "INVOCATION_START", value: "(" }, + { type: "STRING", value: "Bob" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "day" }, { type: "PUNCTUATION", value: ":" }, - { type: "STRING", value: "Tuesday" }, - { type: "INVOCATION_END", value: ")" }, + { type: "STRING", value: "Tuesday" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -3424,48 +3424,48 @@ describe('Lexer', function() { it('should handle functions with many arguments', function () { input = String.raw`func addSevenInts(first: Int, second: Int, third: Int, fourth: Int, fifth: Int, sixth: Int, seventh: Int) -> Int { - let sum = first + second + third + fourth + fifth + sixth + seventh - return sum - } - addSevenInts(143242134, second: 34543, third: 4, fourth: 6, fifth: 0, sixth: 56, seventh: 5)`; + let sum = first + second + third + fourth + fifth + sixth + seventh + return sum + } + addSevenInts(143242134, second: 34543, third: 4, fourth: 6, fifth: 0, sixth: 56, seventh: 5)`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "addSevenInts" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "first" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "second" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "third" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "fourth" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "fifth" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "sixth" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "seventh" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PARAMS_END", value: ")" }, { type: "RETURN_ARROW", value: "->" }, - + { type: "TYPE_NUMBER", value: "Int" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "sum" }, { type: "OPERATOR", value: "=" }, @@ -3483,14 +3483,14 @@ describe('Lexer', function() { { type: "OPERATOR", value: "+" }, { type: "IDENTIFIER", value: "seventh" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "sum" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "addSevenInts" }, { type: "INVOCATION_START", value: "(" }, { type: "NUMBER", value: "143242134" }, @@ -3527,46 +3527,46 @@ describe('Lexer', function() { it('should handle function invocations with internal parentheses', function () { input = String.raw`func addOne(input: Int) -> Int { - return input + 1 - } - addOne(((17 * 4) - 3) * 5)`; + return input + 1 + } + addOne(((17 * 4) - 3) * 5)`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "addOne" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "input" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "input" }, { type: "OPERATOR", value: "+" }, { type: "NUMBER", value: "1" }, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}" }, + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "addOne" }, { type: "INVOCATION_START", value: "(" }, { type: "PUNCTUATION", value: "(" }, - { type: "PUNCTUATION", value: "(" }, - { type: "NUMBER", value: "17" }, + { type: "PUNCTUATION", value: "(" }, + { type: "NUMBER", value: "17" }, { type: "OPERATOR", value: "*" }, - { type: "NUMBER", value: "4" }, - { type: "PUNCTUATION", value: ")" }, + { type: "NUMBER", value: "4" }, + { type: "PUNCTUATION", value: ")" }, { type: "OPERATOR", value: "-" }, - { type: "NUMBER", value: "3" }, - { type: "PUNCTUATION", value: ")" }, + { type: "NUMBER", value: "3" }, + { type: "PUNCTUATION", value: ")" }, { type: "OPERATOR", value: "*" }, - { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, + { type: "NUMBER", value: "5" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -3574,34 +3574,34 @@ describe('Lexer', function() { it('should handle functions that return tuples', function () { input = String.raw`func returnTuple(num: Int) -> (plusFive: Int, timesFive: Int) { - let plusFiveResult = num + 5 - let timesFiveResult = num * 5 - return (plusFiveResult, timesFiveResult) - } - returnTuple(5)`; + let plusFiveResult = num + 5 + let timesFiveResult = num * 5 + return (plusFiveResult, timesFiveResult) + } + returnTuple(5)`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "returnTuple" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "num" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, - + { type: "TUPLE_START", value: "("}, { type: "TUPLE_ELEMENT_NAME", value: "plusFive" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, - { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "," }, { type: "TUPLE_ELEMENT_NAME", value: "timesFive" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "TUPLE_END", value: ")"}, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "plusFiveResult" }, { type: "OPERATOR", value: "=" }, @@ -3609,7 +3609,7 @@ describe('Lexer', function() { { type: "OPERATOR", value: "+" }, { type: "NUMBER", value: "5" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "timesFiveResult" }, { type: "OPERATOR", value: "=" }, @@ -3617,22 +3617,22 @@ describe('Lexer', function() { { type: "OPERATOR", value: "*" }, { type: "NUMBER", value: "5" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "TUPLE_START", value: "("}, { type: "IDENTIFIER", value: "plusFiveResult" }, - { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "timesFiveResult" }, { type: "TUPLE_END", value: ")"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "returnTuple" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -3640,58 +3640,58 @@ describe('Lexer', function() { it('should handle functions that return tuples with mixed values', function () { input = String.raw`func nameAndAge(name: String, age: Int) -> (name: String, age: Int) { - return (name, age) - } - let person = nameAndAge("Steve", age: 45)`; + return (name, age) + } + let person = nameAndAge("Steve", age: 45)`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "nameAndAge" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "name" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_STRING", value: "String" }, - { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "age" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, - + { type: "TUPLE_START", value: "(" }, { type: "TUPLE_ELEMENT_NAME", value: "name" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_STRING", value: "String" }, - { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "," }, { type: "TUPLE_ELEMENT_NAME", value: "age" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "TUPLE_END", value: ")" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "TUPLE_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "TUPLE_START", value: "("}, { type: "IDENTIFIER", value: "name" }, - { type: "PUNCTUATION", value: "," }, + { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "age" }, { type: "TUPLE_END", value: ")"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let"}, { type: "IDENTIFIER", value: "person" }, - { type: "OPERATOR", value: "=" }, + { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "nameAndAge" }, - { type: "INVOCATION_START", value: "(" }, - { type: "STRING", value: "Steve" }, + { type: "INVOCATION_START", value: "(" }, + { type: "STRING", value: "Steve" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "age" }, { type: "PUNCTUATION", value: ":" }, - { type: "NUMBER", value: "45" }, - { type: "INVOCATION_END", value: ")" }, + { type: "NUMBER", value: "45" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -3699,40 +3699,40 @@ describe('Lexer', function() { it('should handle functions with for loops, if and else if statments, and native count methods', function () { input = String.raw`func minMax(array: [Int]) -> (min: Int, max: Int) { - var currentMin = array[0] - var currentMax = array[0] - for value in array[1.. currentMax { - currentMax = value - } - } - return (currentMin, currentMax) - }`; + var currentMin = array[0] + var currentMax = array[0] + for value in array[1.. currentMax { + currentMax = value + } + } + return (currentMin, currentMax) + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "minMax" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "array" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "ARRAY_START", value: "["}, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "ARRAY_END", value: "]"}, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "ARRAY_END", value: "]"}, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, { type: "TUPLE_START", value: "("}, { type: "TUPLE_ELEMENT_NAME", value: "min"}, { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, + { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "TUPLE_ELEMENT_NAME", value: "max"}, { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, + { type: "TYPE_NUMBER", value: "Int" }, { type: "TUPLE_END", value: ")"}, - { type: "STATEMENTS_START", value: "{" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "currentMin" }, { type: "OPERATOR", value: "=" }, @@ -3756,14 +3756,14 @@ describe('Lexer', function() { { type: "STATEMENT_KEYWORD", value: "in" }, { type: "IDENTIFIER", value: "array" }, { type: "SUBSTRING_LOOKUP_START", value: "[" }, - + { type: "NUMBER", value: "1" }, { type: "HALF-OPEN_RANGE", value: "..<" }, { type: "IDENTIFIER", value: "array" }, { type: "DOT_SYNTAX", value: "." }, - { type: "TYPE_PROPERTY", value: "count" }, - + { type: "TYPE_PROPERTY", value: "count" }, + { type: "SUBSTRING_LOOKUP_END", value: "]" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, @@ -3777,7 +3777,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "currentMin" }, { type: "OPERATOR", value: "=" }, - { type: "IDENTIFIER", value: "value" }, + { type: "IDENTIFIER", value: "value" }, { type: "TERMINATOR", value: "\\n"}, { type: "PUNCTUATION", value: "}" }, @@ -3808,7 +3808,7 @@ describe('Lexer', function() { { type: "TUPLE_END", value: ")"}, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}" }, + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -3816,38 +3816,38 @@ describe('Lexer', function() { it('should handle functions with for loops and if and else if statments', function () { input = String.raw`func minMax(array: [Int]) -> (min: Int, max: Int) { - var currentMin = array[0] - var currentMax = array[0] - for value in array[1..<2] { - if value < currentMin { - currentMin = value - } else if value > currentMax { - currentMax = value - } - } - return (currentMin, currentMax) - }`; + var currentMin = array[0] + var currentMax = array[0] + for value in array[1..<2] { + if value < currentMin { + currentMin = value + } else if value > currentMax { + currentMax = value + } + } + return (currentMin, currentMax) + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "minMax" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "array" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "ARRAY_START", value: "["}, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "ARRAY_END", value: "]"}, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "ARRAY_END", value: "]"}, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, { type: "TUPLE_START", value: "("}, { type: "TUPLE_ELEMENT_NAME", value: "min"}, { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, + { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "TUPLE_ELEMENT_NAME", value: "max"}, { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, + { type: "TYPE_NUMBER", value: "Int" }, { type: "TUPLE_END", value: ")"}, - { type: "STATEMENTS_START", value: "{" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "var" }, @@ -3873,10 +3873,10 @@ describe('Lexer', function() { { type: "STATEMENT_KEYWORD", value: "in" }, { type: "IDENTIFIER", value: "array" }, { type: "SUBSTRING_LOOKUP_START", value: "[" }, - + { type: "NUMBER", value: "1" }, { type: "HALF-OPEN_RANGE", value: "..<" }, - { type: "NUMBER", value: "2" }, + { type: "NUMBER", value: "2" }, { type: "SUBSTRING_LOOKUP_END", value: "]" }, { type: "PUNCTUATION", value: "{" }, @@ -3891,7 +3891,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "currentMin" }, { type: "OPERATOR", value: "=" }, - { type: "IDENTIFIER", value: "value" }, + { type: "IDENTIFIER", value: "value" }, { type: "TERMINATOR", value: "\\n"}, { type: "PUNCTUATION", value: "}" }, @@ -3907,7 +3907,7 @@ describe('Lexer', function() { { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "value" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "\\n"}, @@ -3922,119 +3922,48 @@ describe('Lexer', function() { { type: "TUPLE_END", value: ")"}, { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENTS_END", value: "}" }, + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); }); - it('should handle functions that only have variadic parameters', function () { + it('should handle functions that have variadic parameters', function () { input = String.raw`func sumOf(numbers: Int...) -> Int { - var sum = 0 - for number in numbers { - sum += number - } - return sum - } - sumOf(1,2,3)`; + var sum = 0 + for number in numbers { + sum += number + } + return sum + } + sumOf(1,2,3)`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "sumOf" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "numbers" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, - { type: "VARIADIC_PARAM", value: "..." }, - { type: "PARAMS_END", value: ")" }, + { type: "VARIADIC_PARAM", value: "..." }, + { type: "PARAMS_END", value: ")" }, { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, + { type: "TYPE_NUMBER", value: "Int" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "sum" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "for" }, - { type: "IDENTIFIER", value: "number" }, - { type: "STATEMENT_KEYWORD", value: "in" }, - { type: "IDENTIFIER", value: "numbers" }, - { type: "PUNCTUATION", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "IDENTIFIER", value: "sum" }, - { type: "OPERATOR", value: "+" }, - { type: "OPERATOR", value: "=" }, - { type: "IDENTIFIER", value: "number" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "PUNCTUATION", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "IDENTIFIER", value: "sum" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "IDENTIFIER", value: "sumOf" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: "," }, - { type: "NUMBER", value: "2" }, - { type: "PUNCTUATION", value: "," }, - { type: "NUMBER", value: "3" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); - it('should handle functions that has an optional parameter and variadic parameters', function () { - input = String.raw`func sumOf(start: Int=0, numbers: Int...) -> Int { - var sum = start - for number in numbers { - sum += number - } - return sum - } - sumOf(start: 1,2,3)`; - output = [ - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "sumOf" }, - { type: "PARAMS_START", value: "(" }, - { type: "IDENTIFIER", value: "start" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "0" }, - { type: "PUNCTUATION", value: "," }, - { type: "IDENTIFIER", value: "numbers" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "VARIADIC_PARAM", value: "..." }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "sum" }, - { type: "OPERATOR", value: "=" }, - { type: "IDENTIFIER", value: "start" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "STATEMENT_KEYWORD", value: "for" }, { type: "IDENTIFIER", value: "number" }, { type: "STATEMENT_KEYWORD", value: "in" }, { type: "IDENTIFIER", value: "numbers" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "sum" }, { type: "OPERATOR", value: "+" }, { type: "OPERATOR", value: "=" }, @@ -4047,20 +3976,18 @@ describe('Lexer', function() { { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "sum" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "sumOf" }, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "start" }, - { type: "PUNCTUATION", value: ":" }, - { type: "NUMBER", value: "1" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "1" }, { type: "PUNCTUATION", value: "," }, - { type: "NUMBER", value: "2" }, + { type: "NUMBER", value: "2" }, { type: "PUNCTUATION", value: "," }, - { type: "NUMBER", value: "3" }, - { type: "INVOCATION_END", value: ")" }, + { type: "NUMBER", value: "3" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -4068,39 +3995,39 @@ describe('Lexer', function() { it('should handle functions that return functions where the return function is specified within parentheses', function () { input = String.raw`func makeIncrementer() -> ((Int) -> Int) { - func addOne(number: Int) -> Int { - return 1 + number - } - return addOne - }`; + func addOne(number: Int) -> Int { + return 1 + number + } + return addOne + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "makeIncrementer" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "RETURN_ARROW", value: "->" }, - { type: "PUNCTUATION", value: "(" }, + { type: "PUNCTUATION", value: "(" }, { type: "PARAMS_START", value: "(" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, + { type: "RETURN_ARROW", value: "->" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "addOne" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "number" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PARAMS_END", value: ")" }, { type: "RETURN_ARROW", value: "->" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "NUMBER", value: "1" }, { type: "OPERATOR", value: "+" }, @@ -4108,11 +4035,11 @@ describe('Lexer', function() { { type: "TERMINATOR", value: "\\n"}, { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "addOne" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; @@ -4121,37 +4048,37 @@ describe('Lexer', function() { it('should handle functions that return functions where the return function is specified without parentheses', function () { input = String.raw`func makeIncrementer() -> (Int) -> Int { - func addOne(number: Int) -> Int { - return 1 + number - } - return addOne - }`; + func addOne(number: Int) -> Int { + return 1 + number + } + return addOne + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "makeIncrementer" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "RETURN_ARROW", value: "->" }, { type: "PARAMS_START", value: "(" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, + { type: "RETURN_ARROW", value: "->" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "addOne" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "number" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PARAMS_END", value: ")" }, { type: "RETURN_ARROW", value: "->" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "NUMBER", value: "1" }, { type: "OPERATOR", value: "+" }, @@ -4160,11 +4087,11 @@ describe('Lexer', function() { { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "addOne" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; @@ -4173,38 +4100,38 @@ describe('Lexer', function() { xit('should handle functions that take a function specified with parentheses as an argument', function () { input = String.raw`func any(list: [Int], condition: ((Int) -> Bool)) -> Bool { - for item in list { - if condition(item) { - return true - } - } - return false - }`; + for item in list { + if condition(item) { + return true + } + } + return false + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "any" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "list" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "ARRAY_START", value: "["}, { type: "TYPE_NUMBER", value: "Int" }, { type: "ARRAY_END", value: "]"}, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "condition" }, - { type: "PUNCTUATION", value: ":" }, - { type: "PUNCTUATION", value: "(" }, + { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: "(" }, { type: "PARAMS_START", value: "(" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, + { type: "RETURN_ARROW", value: "->" }, { type: "TYPE_BOOLEAN", value: "Bool" }, { type: "PUNCTUATION", value: ")" }, { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, + { type: "RETURN_ARROW", value: "->" }, { type: "TYPE_BOOLEAN", value: "Bool" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "for" }, { type: "IDENTIFIER", value: "item" }, { type: "STATEMENT_KEYWORD", value: "in" }, @@ -4214,26 +4141,26 @@ describe('Lexer', function() { { type: "STATEMENT_KEYWORD", value: "if" }, { type: "IDENTIFIER", value: "condition" }, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "item" }, - { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "item" }, + { type: "INVOCATION_END", value: ")" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "BOOLEAN", value: "true" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "BOOLEAN", value: "false" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; @@ -4242,36 +4169,36 @@ describe('Lexer', function() { it('should handle functions that take a function specified without parentheses as an argument', function () { input = String.raw`func any(list: [Int], condition: (Int) -> Bool) -> Bool { - for item in list { - if condition(item) { - return true - } - } - return false - }`; + for item in list { + if condition(item) { + return true + } + } + return false + }`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "any" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "list" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "ARRAY_START", value: "["}, { type: "TYPE_NUMBER", value: "Int" }, { type: "ARRAY_END", value: "]"}, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "condition" }, - { type: "PUNCTUATION", value: ":" }, + { type: "PUNCTUATION", value: ":" }, { type: "PARAMS_START", value: "(" }, { type: "TYPE_NUMBER", value: "Int" }, { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, + { type: "RETURN_ARROW", value: "->" }, { type: "TYPE_BOOLEAN", value: "Bool" }, { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, + { type: "RETURN_ARROW", value: "->" }, { type: "TYPE_BOOLEAN", value: "Bool" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "for" }, { type: "IDENTIFIER", value: "item" }, { type: "STATEMENT_KEYWORD", value: "in" }, @@ -4281,26 +4208,26 @@ describe('Lexer', function() { { type: "STATEMENT_KEYWORD", value: "if" }, { type: "IDENTIFIER", value: "condition" }, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "item" }, - { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "item" }, + { type: "INVOCATION_END", value: ")" }, { type: "PUNCTUATION", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "BOOLEAN", value: "true" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "BOOLEAN", value: "false" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; @@ -4309,45 +4236,45 @@ describe('Lexer', function() { it('should handle functions with mathematical operations and parentheses in their invocation', function () { input = String.raw `func addOne(input: Int) -> Int { - return input + 1 - } - addOne(((5 + 4) + 1) + 7)`; + return input + 1 + } + addOne(((5 + 4) + 1) + 7)`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "addOne" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "input" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "return"}, { type: "IDENTIFIER", value: "input" }, { type: "OPERATOR", value: "+" }, { type: "NUMBER", value: "1" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "addOne" }, - { type: "INVOCATION_START", value: "(" }, - { type: "PUNCTUATION", value: "(" }, - { type: "PUNCTUATION", value: "(" }, - { type: "NUMBER", value: "5" }, + { type: "INVOCATION_START", value: "(" }, + { type: "PUNCTUATION", value: "(" }, + { type: "PUNCTUATION", value: "(" }, + { type: "NUMBER", value: "5" }, { type: "OPERATOR", value: "+" }, - { type: "NUMBER", value: "4" }, - { type: "PUNCTUATION", value: ")" }, + { type: "NUMBER", value: "4" }, + { type: "PUNCTUATION", value: ")" }, { type: "OPERATOR", value: "+" }, - { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: ")" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: ")" }, { type: "OPERATOR", value: "+" }, - { type: "NUMBER", value: "7" }, - { type: "INVOCATION_END", value: ")" }, + { type: "NUMBER", value: "7" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"}, ]; expect(lexer(input)).to.deep.equal(output); @@ -4355,114 +4282,36 @@ describe('Lexer', function() { xit('should handle functions whose invocation contains string interpolation that contains a function invocation', function () { input = String.raw`func returnWorld() -> String { - return "World" - } - func printInput(input: String) { - print(input) - } - printInput("Hello, \(returnWorld())!")`; - output = [ - - ]; - expect(lexer(input)).to.deep.equal(output); - }); - - it('should handle functions that use inputs, native methods, and string interpolation ', function () { - input = String.raw`func printFirstName(firstName:String) { - println(firstName) - } - func printFirstName(firstName:String,surname:String) { - println("\(firstName) \(surname)") - } - printFirstName("Joe") - printFirstName("Joe", "Blow")`; + return "World" + } + func printInput(input: String) { + print(input) + } + printInput("Hello, \(returnWorld())!")`; output = [ - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "printFirstName" }, - { type: "PARAMS_START", value: "(" }, - { type: "IDENTIFIER", value: "firstName" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_STRING", value: "String" }, - { type: "PARAMS_END", value: ")" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "NATIVE_METHOD", value: "println"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "firstName" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "printFirstName" }, - { type: "PARAMS_START", value: "(" }, - { type: "IDENTIFIER", value: "firstName" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_STRING", value: "String" }, - { type: "PUNCTUATION", value: "," }, - { type: "IDENTIFIER", value: "surname" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_STRING", value: "String" }, - { type: "PARAMS_END", value: ")" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "NATIVE_METHOD", value: "println"}, - { type: "INVOCATION_START", value: "(" }, - { type: "STRING", value: "" }, - { type: "STRING_INTERPOLATION_START", value: "\\(" }, - { type: "IDENTIFIER", value: "firstName" }, - { type: "STRING_INTERPOLATION_END", value: ")" }, - { type: "STRING", value: " " }, - { type: "STRING_INTERPOLATION_START", value: "\\(" }, - { type: "IDENTIFIER", value: "surname" }, - { type: "STRING_INTERPOLATION_END", value: ")" }, - { type: "STRING", value: "" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "IDENTIFIER", value: "printFirstName" }, - { type: "INVOCATION_START", value: "(" }, - { type: "STRING", value: "Joe" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "IDENTIFIER", value: "printFirstName" }, - { type: "INVOCATION_START", value: "(" }, - { type: "STRING", value: "Joe" }, - { type: "PUNCTUATION", value: "," }, - { type: "STRING", value: "Blow" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); }); it('should handle functions with an integer input and no returned output', function () { input = String.raw`func printManyTimes(a: Int) { - for i in 1...a { - print("a"); - } - } - printManyTimes(1)`; + for i in 1...a { + print("a"); + } + } + printManyTimes(1)`; output = [ { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "printManyTimes" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, - { type: "STATEMENTS_START", value: "{" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, + { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENT_KEYWORD", value: "for" }, { type: "IDENTIFIER", value: "i" }, { type: "STATEMENT_KEYWORD", value: "in" }, @@ -4481,14 +4330,14 @@ describe('Lexer', function() { { type: "PUNCTUATION", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "printManyTimes" }, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "1" }, - { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "1" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"}, ]; expect(lexer(input)).to.deep.equal(output); @@ -4499,54 +4348,54 @@ describe('Lexer', function() { }); describe('Classes and Stuctures', function () { - + it('should handle basic definitions of classes and structs', function () { input = String.raw`class VideoMode { - var interlaced = false - var frameRate = 0.0 - } - struct Resolution { - var width = 0 - var height = 0 - }`; + var interlaced = false + var frameRate = 0.0 + } + struct Resolution { + var width = 0 + var height = 0 + }`; output = [ { type: "DECLARATION_KEYWORD", value: "class" }, { type: "IDENTIFIER", value: "VideoMode" }, { type: "CLASS_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "interlaced" }, { type: "OPERATOR", value: "=" }, { type: "BOOLEAN", value: "false" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "frameRate" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0.0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "CLASS_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "struct" }, { type: "IDENTIFIER", value: "Resolution" }, { type: "STRUCT_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "width" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "height" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STRUCT_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; @@ -4556,54 +4405,54 @@ describe('Lexer', function() { it('should handle basic initialization of classes and structs', function () { input = String.raw`class VideoMode { - var interlaced = false - var frameRate = 0.0 - } - struct Resolution { - var width = 0 - var height = 0 - } - - let someVideoMode = VideoMode() - let someResolution = Resolution();`; + var interlaced = false + var frameRate = 0.0 + } + struct Resolution { + var width = 0 + var height = 0 + } + + let someVideoMode = VideoMode() + let someResolution = Resolution();`; output = [ { type: "DECLARATION_KEYWORD", value: "class" }, { type: "IDENTIFIER", value: "VideoMode" }, { type: "CLASS_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "interlaced" }, { type: "OPERATOR", value: "=" }, { type: "BOOLEAN", value: "false" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "frameRate" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0.0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "CLASS_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "struct" }, { type: "IDENTIFIER", value: "Resolution" }, { type: "STRUCT_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "width" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "height" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STRUCT_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "TERMINATOR", value: "\\n"}, @@ -4612,16 +4461,16 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "someVideoMode" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "VideoMode" }, - { type: "INITIALIZATION_START", value: "(" }, - { type: "INITIALIZATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, + { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "someResolution" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "Resolution" }, - { type: "INITIALIZATION_START", value: "(" }, - { type: "INITIALIZATION_END", value: ")" }, + { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_END", value: ")" }, { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "EOF"} ]; @@ -4630,57 +4479,57 @@ describe('Lexer', function() { it('should handle basic property access via dot notation', function () { input = String.raw`class VideoMode { - var interlaced = false - var frameRate = 0.0 - } - struct Resolution { - var width = 0 - var height = 0 - } - - let someVideoMode = VideoMode() - let someResolution = Resolution(); - - let someFrameRate = someVideoMode.frameRate; - let someWidth = someResolution.width`; + var interlaced = false + var frameRate = 0.0 + } + struct Resolution { + var width = 0 + var height = 0 + } + + let someVideoMode = VideoMode() + let someResolution = Resolution(); + + let someFrameRate = someVideoMode.frameRate; + let someWidth = someResolution.width`; output = [ { type: "DECLARATION_KEYWORD", value: "class" }, { type: "IDENTIFIER", value: "VideoMode" }, { type: "CLASS_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "interlaced" }, { type: "OPERATOR", value: "=" }, { type: "BOOLEAN", value: "false" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "frameRate" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0.0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "CLASS_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "struct" }, { type: "IDENTIFIER", value: "Resolution" }, { type: "STRUCT_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "width" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "height" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STRUCT_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "TERMINATOR", value: "\\n"}, @@ -4689,20 +4538,20 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "someVideoMode" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "VideoMode" }, - { type: "INITIALIZATION_START", value: "(" }, - { type: "INITIALIZATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, + { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "someResolution" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "Resolution" }, - { type: "INITIALIZATION_START", value: "(" }, - { type: "INITIALIZATION_END", value: ")" }, + { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_END", value: ")" }, { type: "PUNCTUATION", value: ";" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "TERMINATOR", value: "\\n"}, - + { type: "TERMINATOR", value: "\\n"}, + { type: "TERMINATOR", value: "\\n"}, + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "someFrameRate" }, { type: "OPERATOR", value: "=" }, @@ -4711,7 +4560,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "frameRate" }, { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "someWidth" }, { type: "OPERATOR", value: "=" }, @@ -4725,38 +4574,38 @@ describe('Lexer', function() { it('should handle basic memberwise initialization', function () { input = String.raw`struct Resolution { - var width = 0 - var height = 0 - } + var width = 0 + var height = 0 + } - let someResolution = Resolution(width: 640, height: 480)`; + let someResolution = Resolution(width: 640, height: 480)`; output = [ { type: "DECLARATION_KEYWORD", value: "struct" }, { type: "IDENTIFIER", value: "Resolution" }, { type: "STRUCT_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "width" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "height" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STRUCT_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "someResolution" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "Resolution" }, - { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_START", value: "(" }, { type: "IDENTIFIER", value: "width" }, { type: "PUNCTUATION", value: ":" }, { type: "NUMBER", value: "640" }, @@ -4764,7 +4613,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "height" }, { type: "PUNCTUATION", value: ":" }, { type: "NUMBER", value: "480" }, - { type: "INITIALIZATION_END", value: ")" }, + { type: "INITIALIZATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -4772,48 +4621,48 @@ describe('Lexer', function() { it('should handle complex memberwise initialization with internal parentheses', function () { input = String.raw`var resolutionHeight = 480 - struct Resolution { - var width = 0 - var height = 0 - } + struct Resolution { + var width = 0 + var height = 0 + } - let someResolution = Resolution(width: ((50 * 2) * 6) + 40, height: resolutionHeight)`; + let someResolution = Resolution(width: ((50 * 2) * 6) + 40, height: resolutionHeight)`; output = [ { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "resolutionHeight" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "480" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "struct" }, { type: "IDENTIFIER", value: "Resolution" }, { type: "STRUCT_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "width" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "height" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STRUCT_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "someResolution" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "Resolution" }, - { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_START", value: "(" }, { type: "IDENTIFIER", value: "width" }, { type: "PUNCTUATION", value: ":" }, - + { type: "PUNCTUATION", value: "(" }, { type: "PUNCTUATION", value: "(" }, { type: "NUMBER", value: "50" }, @@ -4830,7 +4679,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "height" }, { type: "PUNCTUATION", value: ":" }, { type: "IDENTIFIER", value: "resolutionHeight" }, - { type: "INITIALIZATION_END", value: ")" }, + { type: "INITIALIZATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -4838,12 +4687,12 @@ describe('Lexer', function() { xit('should handle complex memberwise initialization with string interpolation that contains a function invocation', function () { input = String.raw`struct Greeting { - var greeting = "" - } - func returnWorld() -> String { - return "World" - } - var helloWorld = Greeting(greeting: "Hello, \(returnWorld())!")`; + var greeting = "" + } + func returnWorld() -> String { + return "World" + } + var helloWorld = Greeting(greeting: "Hello, \(returnWorld())!")`; output = [ ]; @@ -4852,38 +4701,38 @@ describe('Lexer', function() { it('should handle variable and constant stored properties', function () { input = String.raw`struct FixedLengthRange { - var firstValue: Int - let length: Int - } + var firstValue: Int + let length: Int + } - let rangeOfOneHundred = FixedLengthRange(firstValue: 1, length: 100)`; + let rangeOfOneHundred = FixedLengthRange(firstValue: 1, length: 100)`; output = [ { type: "DECLARATION_KEYWORD", value: "struct" }, { type: "IDENTIFIER", value: "FixedLengthRange" }, { type: "STRUCT_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "firstValue" }, { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "length" }, { type: "PUNCTUATION", value: ":" }, { type: "TYPE_NUMBER", value: "Int"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "STRUCT_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "rangeOfOneHundred" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "FixedLengthRange" }, - { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_START", value: "(" }, { type: "IDENTIFIER", value: "firstValue" }, { type: "PUNCTUATION", value: ":" }, { type: "NUMBER", value: "1" }, @@ -4891,7 +4740,7 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "length" }, { type: "PUNCTUATION", value: ":" }, { type: "NUMBER", value: "100" }, - { type: "INITIALIZATION_END", value: ")" }, + { type: "INITIALIZATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -4899,45 +4748,45 @@ describe('Lexer', function() { it('should handle properties of all kinds', function () { input = String.raw`class Medley { - var a = 1 - var b = "hai, world" - let c = true - /* Comment 1 - - */ var d = 1 // Comment 2 - var e = ["Eggs", "Milk", "Bacon"]; - var f = ["one": 1, "two": 2, "three": 3] - let http200Status = (statusCode: 200, description: "OK") - var g = 5 + 6 / 4 - (-16 % 4.2) * 55 - let h = 6 != 9 - var i = "Stephen" + " " + "Tabor" + "!" - }`; + var a = 1 + var b = "hai, world" + let c = true + /* Comment 1 + + */ var d = 1 // Comment 2 + var e = ["Eggs", "Milk", "Bacon"]; + var f = ["one": 1, "two": 2, "three": 3] + let http200Status = (statusCode: 200, description: "OK") + var g = 5 + 6 / 4 - (-16 % 4.2) * 55 + let h = 6 != 9 + var i = "Stephen" + " " + "Tabor" + "!" + }`; output = [ { type: "DECLARATION_KEYWORD", value: "class" }, { type: "IDENTIFIER", value: "Medley" }, { type: "CLASS_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "a" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "1" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "b" }, { type: "OPERATOR", value: "=" }, { type: "STRING", value: "hai, world" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "c" }, { type: "OPERATOR", value: "=" }, { type: "BOOLEAN", value: "true" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "MULTI_LINE_COMMENT_START", value: "/*"}, - { type: "COMMENT", value: " Comment 1 "}, + { type: "COMMENT", value: " Comment 1"}, { type: "TERMINATOR", value: "\\n"}, { type: "TERMINATOR", value: "\\n"}, { type: "MULTI_LINE_COMMENT_END", value: "*/"}, @@ -4948,7 +4797,7 @@ describe('Lexer', function() { { type: "COMMENT_START", value: "//"}, { type: "COMMENT", value: " Comment 2"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "e" }, { type: "OPERATOR", value: "=" }, @@ -4961,7 +4810,7 @@ describe('Lexer', function() { { type: "ARRAY_END", value: "]" }, { type: "PUNCTUATION", value: ";" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "f" }, { type: "OPERATOR", value: "=" }, @@ -4979,7 +4828,7 @@ describe('Lexer', function() { { type: "NUMBER", value: "3" }, { type: "DICTIONARY_END", value: "]" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "http200Status" }, { type: "OPERATOR", value: "=" }, @@ -4993,7 +4842,7 @@ describe('Lexer', function() { { type: "STRING", value: "OK"}, { type: "TUPLE_END", value: ")"}, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "g" }, { type: "OPERATOR", value: "=" }, @@ -5012,7 +4861,7 @@ describe('Lexer', function() { { type: "OPERATOR", value: "*" }, { type: "NUMBER", value: "55" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "let" }, { type: "IDENTIFIER", value: "h" }, { type: "OPERATOR", value: "=" }, @@ -5021,7 +4870,7 @@ describe('Lexer', function() { { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "9" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "i" }, { type: "OPERATOR", value: "=" }, @@ -5033,7 +4882,7 @@ describe('Lexer', function() { { type: "OPERATOR", value: "+" }, { type: "STRING", value: "!" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "CLASS_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "EOF"} ]; @@ -5042,98 +4891,98 @@ describe('Lexer', function() { it('should handle basic class instance method definitions, and their invocation', function () { input = String.raw`class Counter { - var total = 0 - func increment() { - ++total - } - func incrementBy(amount: Int) { - total += amount - } - func reset() { - total = 0 - } - } - var someCounter = Counter() - someCounter.incrementBy(5)`; + var total = 0 + func increment() { + ++total + } + func incrementBy(amount: Int) { + total += amount + } + func reset() { + total = 0 + } + } + var someCounter = Counter() + someCounter.incrementBy(5)`; output = [ { type: "DECLARATION_KEYWORD", value: "class" }, { type: "IDENTIFIER", value: "Counter" }, { type: "CLASS_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "total" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "increment" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "OPERATOR", value: "+" }, { type: "OPERATOR", value: "+" }, { type: "IDENTIFIER", value: "total" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "incrementBy" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "amount" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "total" }, { type: "OPERATOR", value: "+" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "amount" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "reset" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "total" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "CLASS_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + {type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "someCounter" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "Counter" }, - { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_START", value: "(" }, { type: "INITIALIZATION_END", value: ")" }, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "someCounter" }, { type: "DOT_SYNTAX", value: "." }, { type: "IDENTIFIER", value: "incrementBy" }, - { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_START", value: "(" }, { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -5141,61 +4990,61 @@ describe('Lexer', function() { it('should handle basic class instance method definitions with multiple parameter names, and their invocation', function () { input = String.raw`class Counter { - var total = 0 - func increment() { - ++total - } - func incrementBy(amount: Int, numberOfTimes: Int) { - total += amount * numberOfTimes - } - func reset() { - total = 0 - } - } - var someCounter = Counter() - someCounter.incrementBy(50, numberOfTimes: 10) - someCounter.total`; + var total = 0 + func increment() { + ++total + } + func incrementBy(amount: Int, numberOfTimes: Int) { + total += amount * numberOfTimes + } + func reset() { + total = 0 + } + } + var someCounter = Counter() + someCounter.incrementBy(50, numberOfTimes: 10) + someCounter.total`; output = [ { type: "DECLARATION_KEYWORD", value: "class" }, { type: "IDENTIFIER", value: "Counter" }, { type: "CLASS_DEFINITION_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "total" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "increment" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "OPERATOR", value: "+" }, { type: "OPERATOR", value: "+" }, { type: "IDENTIFIER", value: "total" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "incrementBy" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "amount" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "numberOfTimes" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "total" }, { type: "OPERATOR", value: "+" }, { type: "OPERATOR", value: "=" }, @@ -5203,48 +5052,48 @@ describe('Lexer', function() { { type: "OPERATOR", value: "*" }, { type: "IDENTIFIER", value: "numberOfTimes" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "reset" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "total" }, { type: "OPERATOR", value: "=" }, { type: "NUMBER", value: "0" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "STATEMENTS_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "CLASS_DEFINITION_END", value: "}" }, { type: "TERMINATOR", value: "\\n"}, - + {type: "DECLARATION_KEYWORD", value: "var" }, { type: "IDENTIFIER", value: "someCounter" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "Counter" }, - { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_START", value: "(" }, { type: "INITIALIZATION_END", value: ")" }, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "someCounter" }, { type: "DOT_SYNTAX", value: "." }, { type: "IDENTIFIER", value: "incrementBy" }, - { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_START", value: "(" }, { type: "NUMBER", value: "50" }, { type: "PUNCTUATION", value: "," }, { type: "IDENTIFIER", value: "numberOfTimes" }, { type: "PUNCTUATION", value: ":" }, { type: "NUMBER", value: "10" }, - { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "\\n"}, - + { type: "IDENTIFIER", value: "someCounter" }, { type: "DOT_SYNTAX", value: "." }, { type: "IDENTIFIER", value: "total" }, @@ -5255,19 +5104,19 @@ describe('Lexer', function() { it('should handle basic instance method definitions that use self, and their invocation', function () { input = String.raw`class Counter { - var total = 0 - func increment() { - ++self.total - } - func incrementBy(amount: Int) { - self.total += amount - } - func reset() { - self.total = 0 - } - } - var someCounter = Counter() - someCounter.incrementBy(5)`; + var total = 0 + func increment() { + ++self.total + } + func incrementBy(amount: Int) { + self.total += amount + } + func reset() { + self.total = 0 + } + } + var someCounter = Counter() + someCounter.incrementBy(5)`; output = [ { type: "DECLARATION_KEYWORD", value: "class" }, @@ -5284,7 +5133,7 @@ describe('Lexer', function() { { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "increment" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, @@ -5302,9 +5151,9 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "incrementBy" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "amount" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, @@ -5322,7 +5171,7 @@ describe('Lexer', function() { { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "reset" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, @@ -5343,16 +5192,16 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "someCounter" }, { type: "OPERATOR", value: "=" }, { type: "IDENTIFIER", value: "Counter" }, - { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_START", value: "(" }, { type: "INITIALIZATION_END", value: ")" }, { type: "TERMINATOR", value: "\\n"}, { type: "IDENTIFIER", value: "someCounter" }, { type: "DOT_SYNTAX", value: "." }, { type: "IDENTIFIER", value: "incrementBy" }, - { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_START", value: "(" }, { type: "NUMBER", value: "5" }, - { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_END", value: ")" }, { type: "TERMINATOR", value: "EOF"} ]; expect(lexer(input)).to.deep.equal(output); @@ -5360,17 +5209,17 @@ describe('Lexer', function() { it('should handle basic struct mutating method definitions', function () { input = String.raw`struct Counter { - var total = 0 - mutating func increment() { - ++total - } - mutating func incrementBy(amount: Int) { - total += amount - } - mutating func reset() { - total = 0 - } - }`; + var total = 0 + mutating func increment() { + ++total + } + mutating func incrementBy(amount: Int) { + total += amount + } + mutating func reset() { + total = 0 + } + }`; output = [ { type: "DECLARATION_KEYWORD", value: "struct" }, { type: "IDENTIFIER", value: "Counter" }, @@ -5387,7 +5236,7 @@ describe('Lexer', function() { { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "increment" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, @@ -5404,9 +5253,9 @@ describe('Lexer', function() { { type: "IDENTIFIER", value: "incrementBy" }, { type: "PARAMS_START", value: "(" }, { type: "IDENTIFIER", value: "amount" }, - { type: "PUNCTUATION", value: ":" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "PARAMS_END", value: ")" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, @@ -5423,7 +5272,7 @@ describe('Lexer', function() { { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "reset" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, @@ -5443,11 +5292,11 @@ describe('Lexer', function() { it('should handle basic struct mutating methods that assign to self', function () { input = String.raw`struct Counter { - var total = 0 - mutating func increment() { - self = Counter(total: ++total) - } - }`; + var total = 0 + mutating func increment() { + self = Counter(total: ++total) + } + }`; output = [ { type: "DECLARATION_KEYWORD", value: "struct" }, { type: "IDENTIFIER", value: "Counter" }, @@ -5464,7 +5313,7 @@ describe('Lexer', function() { { type: "DECLARATION_KEYWORD", value: "func"}, { type: "IDENTIFIER", value: "increment" }, { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, + { type: "PARAMS_END", value: ")" }, { type: "STATEMENTS_START", value: "{" }, { type: "TERMINATOR", value: "\\n"}, @@ -5491,1804 +5340,1804 @@ describe('Lexer', function() { it('should handle type methods declared with the static or class keyword', function () { input = String.raw`class ParentClass { - static func returnTen() -> Int { - return 10 - } - class func returnString() -> String { - return "my string" - } - } - ParentClass.returnTen() - ParentClass.returnString()`; + static func returnTen() -> Int { + return 10 + } + class func returnString() -> String { + return "my string" + } + } + ParentClass.returnTen() + ParentClass.returnString()`; + + output = [ + { type: "DECLARATION_KEYWORD", value: "class" }, + { type: "IDENTIFIER", value: "ParentClass" }, + { type: "CLASS_DEFINITION_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "static"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "returnTen" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "NUMBER", value: "10" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "class"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "returnString" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STRING", value: "my string" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CLASS_DEFINITION_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "ParentClass" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "IDENTIFIER", value: "returnTen" }, + { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "ParentClass" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "IDENTIFIER", value: "returnString" }, + { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - output = [ - { type: "DECLARATION_KEYWORD", value: "class" }, - { type: "IDENTIFIER", value: "ParentClass" }, - { type: "CLASS_DEFINITION_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "static"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "returnTen" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "NUMBER", value: "10" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle basic class inheritance', function () { + input = String.raw`class SuperClass { + var a = 0 + var b = 1 + func incrementA() { + ++a + } + static func returnTen() -> Int { + return 10 + } + class func returnString() -> String { + return "my string" + } + } + + class SubClass: SuperClass { + var c = 2 + }`; + output = [ + { type: "DECLARATION_KEYWORD", value: "class" }, + { type: "IDENTIFIER", value: "SuperClass" }, + { type: "CLASS_DEFINITION_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "0" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "b" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "incrementA" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "OPERATOR", value: "+" }, + { type: "OPERATOR", value: "+" }, + { type: "IDENTIFIER", value: "a" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "static"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "returnTen" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "NUMBER", value: "10" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "class"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "returnString" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STRING", value: "my string" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CLASS_DEFINITION_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "class" }, + { type: "IDENTIFIER", value: "SubClass" }, + { type: "INHERITANCE_OPERATOR", value: ":" }, + { type: "IDENTIFIER", value: "SuperClass" }, + { type: "CLASS_DEFINITION_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "c" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "2" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CLASS_DEFINITION_END", value: "}" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "class"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "returnString" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "STRING", value: "my string" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle methods declared as final methods and methods that override inherited methods', function () { + input = String.raw`class SuperClass { + var a = 0 + var b = 1 + func incrementA() { + ++a + } + static func returnTen() -> Int { + return 10 + } + final func returnString() -> String { + return "my string" + } + } + + class SubClass: SuperClass { + override func incrementA() { + a++ + } + }`; + output = [ + { type: "DECLARATION_KEYWORD", value: "class" }, + { type: "IDENTIFIER", value: "SuperClass" }, + { type: "CLASS_DEFINITION_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "0" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "b" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "incrementA" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "OPERATOR", value: "+" }, + { type: "OPERATOR", value: "+" }, + { type: "IDENTIFIER", value: "a" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "static"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "returnTen" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "NUMBER", value: "10" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CONTEXT_SPECIFIC_KEYWORD", value: "final"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "returnString" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STRING", value: "my string" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CLASS_DEFINITION_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "class" }, + { type: "IDENTIFIER", value: "SubClass" }, + { type: "INHERITANCE_OPERATOR", value: ":" }, + { type: "IDENTIFIER", value: "SuperClass" }, + { type: "CLASS_DEFINITION_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CONTEXT_SPECIFIC_KEYWORD", value: "override"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "incrementA" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "+" }, + { type: "OPERATOR", value: "+" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CLASS_DEFINITION_END", value: "}" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); +}); - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CLASS_DEFINITION_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "IDENTIFIER", value: "ParentClass" }, - { type: "DOT_SYNTAX", value: "." }, - { type: "IDENTIFIER", value: "returnTen" }, - { type: "INVOCATION_START", value: "(" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "IDENTIFIER", value: "ParentClass" }, - { type: "DOT_SYNTAX", value: "." }, - { type: "IDENTIFIER", value: "returnString" }, - { type: "INVOCATION_START", value: "(" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); +it('should handle class declaration, initialization, property value lookups, and method calls with erratic spacing and inconsistent use of semi-colons', function () { + input = String.raw` class SuperClass { var a = 0 + + var b = 1 ; + func incrementA(){ + ++a + } + static func returnTen() -> Int { + return 10 + } + final func returnString()-> String { + return "my string" + } +} + +class SubClass : SuperClass { + override func incrementA() { + a++ ; + } +} + +var someSuper = SuperClass () + +someSuper.a ;someSuper.returnString() ; +`; +output = [ + { type: "DECLARATION_KEYWORD", value: "class" }, + { type: "IDENTIFIER", value: "SuperClass" }, + { type: "CLASS_DEFINITION_START", value: "{" }, + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "0" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "b" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: ";" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "incrementA" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "OPERATOR", value: "+" }, + { type: "OPERATOR", value: "+" }, + { type: "IDENTIFIER", value: "a" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "static"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "returnTen" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_NUMBER", value: "Int" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "NUMBER", value: "10" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CONTEXT_SPECIFIC_KEYWORD", value: "final"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "returnString" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "RETURN_ARROW", value: "->" }, + { type: "TYPE_STRING", value: "String" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "return"}, + { type: "STRING", value: "my string" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CLASS_DEFINITION_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "class" }, + { type: "IDENTIFIER", value: "SubClass" }, + { type: "INHERITANCE_OPERATOR", value: ":" }, + { type: "IDENTIFIER", value: "SuperClass" }, + { type: "CLASS_DEFINITION_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CONTEXT_SPECIFIC_KEYWORD", value: "override"}, + { type: "DECLARATION_KEYWORD", value: "func"}, + { type: "IDENTIFIER", value: "incrementA" }, + { type: "PARAMS_START", value: "(" }, + { type: "PARAMS_END", value: ")" }, + { type: "STATEMENTS_START", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "+" }, + { type: "OPERATOR", value: "+" }, + { type: "PUNCTUATION", value: ";" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENTS_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "CLASS_DEFINITION_END", value: "}" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "someSuper" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "SuperClass" }, + { type: "INITIALIZATION_START", value: "(" }, + { type: "INITIALIZATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "someSuper" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "IDENTIFIER", value: "a" }, + { type: "PUNCTUATION", value: ";" }, + { type: "IDENTIFIER", value: "someSuper" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "IDENTIFIER", value: "returnString" }, + { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_END", value: ")" }, + { type: "PUNCTUATION", value: ";" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "TERMINATOR", value: "EOF"} +]; +expect(lexer(input)).to.deep.equal(output); +}); - it('should handle basic class inheritance', function () { - input = String.raw`class SuperClass { - var a = 0 - var b = 1 - func incrementA() { - ++a - } - static func returnTen() -> Int { - return 10 - } - class func returnString() -> String { - return "my string" - } - } - - class SubClass: SuperClass { - var c = 2 - }`; - output = [ - { type: "DECLARATION_KEYWORD", value: "class" }, - { type: "IDENTIFIER", value: "SuperClass" }, - { type: "CLASS_DEFINITION_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "0" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "b" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "incrementA" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, +}); - { type: "OPERATOR", value: "+" }, - { type: "OPERATOR", value: "+" }, - { type: "IDENTIFIER", value: "a" }, - { type: "TERMINATOR", value: "\\n"}, +describe('Native Methods and Type Properties', function () { + + it('should handle calls to print', function () { + input = String.raw`var name = "Joe" + var arr = [1,2] + var tup = (1,2) + print(name) + print("Hello, \(name)") + print(5 * (1 + 1)) + print(arr[1]) + print(tup.0)`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "name" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "Joe" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "arr" }, + { type: "OPERATOR", value: "=" }, + { type: "ARRAY_START", value: "[" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: "," }, + { type: "NUMBER", value: "2" }, + { type: "ARRAY_END", value: "]" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "tup" }, + { type: "OPERATOR", value: "=" }, + { type: "TUPLE_START", value: "(" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: "," }, + { type: "NUMBER", value: "2" }, + { type: "TUPLE_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "name" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "STRING", value: "Hello, " }, + { type: "STRING_INTERPOLATION_START", value: "\\(" }, + { type: "IDENTIFIER", value: "name" }, + { type: "STRING_INTERPOLATION_END", value: ")" }, + { type: "STRING", value: "" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "OPERATOR", value: "*" }, + { type: "PUNCTUATION", value: "(" }, + { type: "NUMBER", value: "1" }, + { type: "OPERATOR", value: "+" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: ")" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "arr" }, + { type: "SUBSTRING_LOOKUP_START", value: "[" }, + { type: "NUMBER", value: "1" }, + { type: "SUBSTRING_LOOKUP_END", value: "]" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "tup" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NUMBER", value: "0"}, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "EOF" } + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "static"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "returnTen" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "NUMBER", value: "10" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle type conversion of strings, ints, floats, doubles', function () { + input = String.raw `var one = 1 + var oneToString = String(one) + var oneBackToInt = Int(oneToString) + var twoTwo = "2.2" + var twoTwoToFloat = Float(twoTwo) + var twoTwoToDouble = Double(twoTwo) + var twoTwoBackToString = String(twoTwoToFloat)`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "one" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "oneToString" }, + { type: "OPERATOR", value: "=" }, + { type: "TYPE_STRING", value: "String"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "one" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "oneBackToInt" }, + { type: "OPERATOR", value: "=" }, + { type: "TYPE_NUMBER", value: "Int"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "oneToString" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "twoTwo" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "2.2" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "twoTwoToFloat" }, + { type: "OPERATOR", value: "=" }, + { type: "TYPE_NUMBER", value: "Float"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "twoTwo" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "twoTwoToDouble" }, + { type: "OPERATOR", value: "=" }, + { type: "TYPE_NUMBER", value: "Double"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "twoTwo" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "twoTwoBackToString" }, + { type: "OPERATOR", value: "=" }, + { type: "TYPE_STRING", value: "String"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "twoTwoToFloat" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "EOF" } + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "class"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "returnString" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "STRING", value: "my string" }, - { type: "TERMINATOR", value: "\\n"}, + describe('Range Operations', function () { + + it('should handle closed ranges', function () { + input = String.raw`var a = 1...5`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1" }, + { type: "CLOSED_RANGE", value: "..." }, + { type: "NUMBER", value: "5" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CLASS_DEFINITION_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "class" }, - { type: "IDENTIFIER", value: "SubClass" }, - { type: "INHERITANCE_OPERATOR", value: ":" }, - { type: "IDENTIFIER", value: "SuperClass" }, - { type: "CLASS_DEFINITION_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "c" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "2" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CLASS_DEFINITION_END", value: "}" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); + it('should handle decimal ending in 0 closed ranges', function () { + input = String.raw`var a = 1.0...5.0`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1.0" }, + { type: "CLOSED_RANGE", value: "..." }, + { type: "NUMBER", value: "5.0" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - it('should handle methods declared as final methods and methods that override inherited methods', function () { - input = String.raw`class SuperClass { - var a = 0 - var b = 1 - func incrementA() { - ++a - } - static func returnTen() -> Int { - return 10 - } - final func returnString() -> String { - return "my string" - } - } - - class SubClass: SuperClass { - override func incrementA() { - a++ - } - }`; - output = [ - { type: "DECLARATION_KEYWORD", value: "class" }, - { type: "IDENTIFIER", value: "SuperClass" }, - { type: "CLASS_DEFINITION_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "0" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "b" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "incrementA" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle random decimal closed ranges', function () { + input = String.raw`var a = 1.2...5.3`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1.2" }, + { type: "CLOSED_RANGE", value: "..." }, + { type: "NUMBER", value: "5.3" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "OPERATOR", value: "+" }, - { type: "OPERATOR", value: "+" }, - { type: "IDENTIFIER", value: "a" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle half-open ranges', function () { + input = String.raw`var b = 1..<5`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "b" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1" }, + { type: "HALF-OPEN_RANGE", value: "..<" }, + { type: "NUMBER", value: "5" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "static"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "returnTen" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "NUMBER", value: "10" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle decimal ending in 0 half-open ranges', function () { + input = String.raw`var a = 1.0..<5.0`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1.0" }, + { type: "HALF-OPEN_RANGE", value: "..<" }, + { type: "NUMBER", value: "5.0" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CONTEXT_SPECIFIC_KEYWORD", value: "final"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "returnString" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "STRING", value: "my string" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle random decimal half-open ranges', function () { + input = String.raw`var a = 1.2..<5.3`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1.2" }, + { type: "HALF-OPEN_RANGE", value: "..<" }, + { type: "NUMBER", value: "5.3" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CLASS_DEFINITION_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "class" }, - { type: "IDENTIFIER", value: "SubClass" }, - { type: "INHERITANCE_OPERATOR", value: ":" }, - { type: "IDENTIFIER", value: "SuperClass" }, - { type: "CLASS_DEFINITION_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CONTEXT_SPECIFIC_KEYWORD", value: "override"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "incrementA" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle all ranges', function () { + input = String.raw`var a = 1...5; var b = 2..<6`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "a" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "1" }, + { type: "CLOSED_RANGE", value: "..." }, + { type: "NUMBER", value: "5" }, + { type: "PUNCTUATION", value: ";"}, + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "b" }, + { type: "OPERATOR", value: "=" }, + { type: "NUMBER", value: "2" }, + { type: "HALF-OPEN_RANGE", value: "..<" }, + { type: "NUMBER", value: "6" }, + { type: "TERMINATOR", value: "EOF"} + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "+" }, - { type: "OPERATOR", value: "+" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle ranges delimited by identifiers', function () { + input = String.raw`let start = 0; let end = 10; let range = start.. Int { - return 10 - } - final func returnString()-> String { - return "my string" - } - } - - class SubClass : SuperClass { - override func incrementA() { - a++ ; - } - } - - var someSuper = SuperClass () - - someSuper.a ;someSuper.returnString() ; - `; - output = [ - { type: "DECLARATION_KEYWORD", value: "class" }, - { type: "IDENTIFIER", value: "SuperClass" }, - { type: "CLASS_DEFINITION_START", value: "{" }, - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "0" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "b" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: ";" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "incrementA" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "OPERATOR", value: "+" }, - { type: "OPERATOR", value: "+" }, - { type: "IDENTIFIER", value: "a" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "static"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "returnTen" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_NUMBER", value: "Int" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "NUMBER", value: "10" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CONTEXT_SPECIFIC_KEYWORD", value: "final"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "returnString" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "RETURN_ARROW", value: "->" }, - { type: "TYPE_STRING", value: "String" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENT_KEYWORD", value: "return"}, - { type: "STRING", value: "my string" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CLASS_DEFINITION_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "class" }, - { type: "IDENTIFIER", value: "SubClass" }, - { type: "INHERITANCE_OPERATOR", value: ":" }, - { type: "IDENTIFIER", value: "SuperClass" }, - { type: "CLASS_DEFINITION_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CONTEXT_SPECIFIC_KEYWORD", value: "override"}, - { type: "DECLARATION_KEYWORD", value: "func"}, - { type: "IDENTIFIER", value: "incrementA" }, - { type: "PARAMS_START", value: "(" }, - { type: "PARAMS_END", value: ")" }, - { type: "STATEMENTS_START", value: "{" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "+" }, - { type: "OPERATOR", value: "+" }, - { type: "PUNCTUATION", value: ";" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "STATEMENTS_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "CLASS_DEFINITION_END", value: "}" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "someSuper" }, - { type: "OPERATOR", value: "=" }, - { type: "IDENTIFIER", value: "SuperClass" }, - { type: "INITIALIZATION_START", value: "(" }, - { type: "INITIALIZATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - { type: "TERMINATOR", value: "\\n"}, - - { type: "IDENTIFIER", value: "someSuper" }, - { type: "DOT_SYNTAX", value: "." }, - { type: "IDENTIFIER", value: "a" }, - { type: "PUNCTUATION", value: ";" }, - { type: "IDENTIFIER", value: "someSuper" }, - { type: "DOT_SYNTAX", value: "." }, - { type: "IDENTIFIER", value: "returnString" }, - { type: "INVOCATION_START", value: "(" }, - { type: "INVOCATION_END", value: ")" }, - { type: "PUNCTUATION", value: ";" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); + describe('String Properties and Methods', function () { + + it('should handle the String characters property', function () { + input = String.raw `var s = "my string, 123!" + for c in s.characters { + print(c) + }`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "s" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "my string, 123!" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "STATEMENT_KEYWORD", value: "for" }, + { type: "IDENTIFIER", value: "c" }, + { type: "STATEMENT_KEYWORD", value: "in" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "characters" }, + { type: "PUNCTUATION", value: "{" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "c" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "PUNCTUATION", value: "}" }, + { type: "TERMINATOR", value: "EOF"}, + ]; + expect(lexer(input)).to.deep.equal(output); + }); - }); + it('should handle the String count property', function () { + input = String.raw `var s = "my string, 123!" + let fifteen = s.characters.count`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "s" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "my string, 123!" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "let" }, + { type: "IDENTIFIER", value: "fifteen" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "characters" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "count" }, + { type: "TERMINATOR", value: "EOF"}, + ]; + expect(lexer(input)).to.deep.equal(output); + }); - describe('Native Methods and Type Properties', function () { + it('should handle the string isEmpty property', function () { + input = String.raw `var s: String = "" + s.isEmpty`; + + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "s" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_STRING", value: "String"}, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "isEmpty"}, + { type: "TERMINATOR", value: "EOF"}, + ]; + expect(lexer(input)).to.deep.equal(output); + }); - it('should handle calls to print', function () { - input = String.raw`var name = "Joe" - var arr = [1,2] - var tup = (1,2) - print(name) - print("Hello, \(name)") - print(5 * (1 + 1)) - print(arr[1]) - print(tup.0)`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "name" }, - { type: "OPERATOR", value: "=" }, - { type: "STRING", value: "Joe" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "arr" }, - { type: "OPERATOR", value: "=" }, - { type: "ARRAY_START", value: "[" }, - { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: "," }, - { type: "NUMBER", value: "2" }, - { type: "ARRAY_END", value: "]" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "tup" }, - { type: "OPERATOR", value: "=" }, - { type: "TUPLE_START", value: "(" }, - { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: "," }, - { type: "NUMBER", value: "2" }, - { type: "TUPLE_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "NATIVE_METHOD", value: "print"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "name" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "NATIVE_METHOD", value: "print"}, - { type: "INVOCATION_START", value: "(" }, - { type: "STRING", value: "Hello, " }, - { type: "STRING_INTERPOLATION_START", value: "\\(" }, - { type: "IDENTIFIER", value: "name" }, - { type: "STRING_INTERPOLATION_END", value: ")" }, - { type: "STRING", value: "" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "NATIVE_METHOD", value: "print"}, - { type: "INVOCATION_START", value: "(" }, - { type: "NUMBER", value: "5" }, - { type: "OPERATOR", value: "*" }, - { type: "PUNCTUATION", value: "(" }, - { type: "NUMBER", value: "1" }, - { type: "OPERATOR", value: "+" }, - { type: "NUMBER", value: "1" }, - { type: "PUNCTUATION", value: ")" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, + it('should handle the String append method', function () { + input = String.raw `var s = "my string, 123!" + var addChar: Character = "!" + s.append(addChar)`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "s" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "my string, 123!" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "addChar" }, + { type: "PUNCTUATION", value: ":" }, + { type: "TYPE_STRING", value: "Character"}, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "!" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "append"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "addChar" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "EOF"}, + ]; + expect(lexer(input)).to.deep.equal(output); + }); - { type: "NATIVE_METHOD", value: "print"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "arr" }, - { type: "SUBSTRING_LOOKUP_START", value: "[" }, - { type: "NUMBER", value: "1" }, - { type: "SUBSTRING_LOOKUP_END", value: "]" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "NATIVE_METHOD", value: "print"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "tup" }, - { type: "DOT_SYNTAX", value: "." }, - { type: "NUMBER", value: "0"}, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "EOF" } - ]; - expect(lexer(input)).to.deep.equal(output); - }); + it('should handle the String indices and their associated methods', function () { + input = String.raw`var s = "my string, 123!" + var zero = s.startIndex + var one = s.startIndex.successor() + var two = s.startIndex.advancedBy(2) + var m = s[s.startIndex] + var y = s[s.startIndex.advancedBy(1)] + var fifteen = s.endIndex + var fourteen = s.endIndex.predecessor() + var bang = s[s.endIndex.predecessor()]`; + //TODO // print("the letter s: \(s[s.startIndex.advancedBy(3)])")`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "s" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "my string, 123!" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "zero" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "startIndex" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "one" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "startIndex" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "successor"}, + { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "two" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "startIndex" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "advancedBy"}, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "2" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "m" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "SUBSTRING_LOOKUP_START", value: "[" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "startIndex" }, + { type: "SUBSTRING_LOOKUP_END", value: "]" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "y" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "SUBSTRING_LOOKUP_START", value: "[" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "startIndex" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "advancedBy"}, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "1" }, + { type: "INVOCATION_END", value: ")" }, + { type: "SUBSTRING_LOOKUP_END", value: "]" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "fifteen" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "endIndex" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "fourteen" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "endIndex" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "predecessor"}, + { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "bang" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "s" }, + { type: "SUBSTRING_LOOKUP_START", value: "[" }, + { type: "IDENTIFIER", value: "s" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "endIndex" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "predecessor"}, + { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_END", value: ")" }, + { type: "SUBSTRING_LOOKUP_END", value: "]" }, + // { type: "TERMINATOR", value: "\\n"}, + + // { type: "NATIVE_METHOD", value: "print"}, + // { type: "INVOCATION_START", value: "(" }, + // { type: "STRING", value: "the letter s: " }, + // { type: "STRING_INTERPOLATION_START", value: "\\(" }, + // { type: "IDENTIFIER", value: "s" }, + // { type: "SUBSTRING_LOOKUP_START", value: "[" }, + // { type: "IDENTIFIER", value: "s" }, + // { type: "DOT_SYNTAX", value: "." }, + // { type: "TYPE_PROPERTY", value: "startIndex" }, + // { type: "DOT_SYNTAX", value: "." }, + // { type: "NATIVE_METHOD", value: "advancedBy"}, + // { type: "INVOCATION_START", value: "(" }, + // { type: "NUMBER", value: "3" }, + // { type: "INVOCATION_END", value: ")" }, + // { type: "SUBSTRING_LOOKUP_END", value: "]" }, + // { type: "STRING_INTERPOLATION_END", value: ")" }, + // { type: "STRING", value: "" }, + // { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "EOF"}, + ]; + expect(lexer(input)).to.deep.equal(output); + }); - it('should handle type conversion of strings, ints, floats, doubles', function () { - input = String.raw `var one = 1 - var oneToString = String(one) - var oneBackToInt = Int(oneToString) - var twoTwo = "2.2" - var twoTwoToFloat = Float(twoTwo) - var twoTwoToDouble = Double(twoTwo) - var twoTwoBackToString = String(twoTwoToFloat)`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "one" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "oneToString" }, - { type: "OPERATOR", value: "=" }, - { type: "TYPE_STRING", value: "String"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "one" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "oneBackToInt" }, - { type: "OPERATOR", value: "=" }, - { type: "TYPE_NUMBER", value: "Int"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "oneToString" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "twoTwo" }, - { type: "OPERATOR", value: "=" }, - { type: "STRING", value: "2.2" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "twoTwoToFloat" }, - { type: "OPERATOR", value: "=" }, - { type: "TYPE_NUMBER", value: "Float"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "twoTwo" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "twoTwoToDouble" }, - { type: "OPERATOR", value: "=" }, - { type: "TYPE_NUMBER", value: "Double"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "twoTwo" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "\\n"}, - - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "twoTwoBackToString" }, - { type: "OPERATOR", value: "=" }, - { type: "TYPE_STRING", value: "String"}, - { type: "INVOCATION_START", value: "(" }, - { type: "IDENTIFIER", value: "twoTwoToFloat" }, - { type: "INVOCATION_END", value: ")" }, - { type: "TERMINATOR", value: "EOF" } - ]; - expect(lexer(input)).to.deep.equal(output); - }); + it('should handle the String methods for inserting and removing characters', function () { + input = String.raw`var greeting = "World" + var firstPart = "Hello, " + greeting.insert("!", atIndex: greeting.endIndex) + greeting.insertContentsOf(firstPart.characters, at: greeting.startIndex) + greeting.removeAtIndex(greeting.endIndex.predecessor()) + var range = greeting.startIndex...greeting.startIndex.advancedBy(6) + greeting.removeRange(range)`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "greeting" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "World" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "firstPart" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "Hello, " }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "insert"}, + { type: "INVOCATION_START", value: "(" }, + { type: "STRING", value: "!" }, + { type: "PUNCTUATION", value: "," }, + { type: "METHOD_ARGUMENT_NAME", value: "atIndex" }, + { type: "PUNCTUATION", value: ":" }, + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "endIndex" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "insertContentsOf"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "firstPart" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "characters" }, + { type: "PUNCTUATION", value: "," }, + { type: "METHOD_ARGUMENT_NAME", value: "at" }, + { type: "PUNCTUATION", value: ":" }, + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "startIndex" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "removeAtIndex"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "endIndex" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "predecessor"}, + { type: "INVOCATION_START", value: "(" }, + { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "range" }, + { type: "OPERATOR", value: "=" }, + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "startIndex" }, + { type: "CLOSED_RANGE", value: "..." }, + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "TYPE_PROPERTY", value: "startIndex" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "advancedBy"}, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "6" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "IDENTIFIER", value: "greeting" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "removeRange"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "range" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "EOF"}, + ]; + expect(lexer(input)).to.deep.equal(output); + }); - describe('Range Operations', function () { - - it('should handle closed ranges', function () { - input = String.raw`var a = 1...5`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, - { type: "CLOSED_RANGE", value: "..." }, - { type: "NUMBER", value: "5" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); + it('should handle the has prefix and has suffix string methods', function () { + input = String.raw `var famousAuthor = "F. Scott Fitzgerald" + print(famousAuthor.hasPrefix("F. Scott")) + var famousDriver = "Dale Earnhardt, Jr." + print(famousDriver.hasSuffix("Jr."))`; + output = [ + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "famousAuthor" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "F. Scott Fitzgerald" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "famousAuthor" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "hasPrefix"}, + { type: "INVOCATION_START", value: "(" }, + { type: "STRING", value: "F. Scott" }, + { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "famousDriver" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "Dale Earnhardt, Jr." }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "famousDriver" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NATIVE_METHOD", value: "hasSuffix"}, + { type: "INVOCATION_START", value: "(" }, + { type: "STRING", value: "Jr." }, + { type: "INVOCATION_END", value: ")" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "EOF"}, + ]; + expect(lexer(input)).to.deep.equal(output); + }); - it('should handle decimal ending in 0 closed ranges', function () { - input = String.raw`var a = 1.0...5.0`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1.0" }, - { type: "CLOSED_RANGE", value: "..." }, - { type: "NUMBER", value: "5.0" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); + }); - it('should handle random decimal closed ranges', function () { - input = String.raw`var a = 1.2...5.3`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1.2" }, - { type: "CLOSED_RANGE", value: "..." }, - { type: "NUMBER", value: "5.3" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); - - it('should handle half-open ranges', function () { - input = String.raw`var b = 1..<5`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "b" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, - { type: "HALF-OPEN_RANGE", value: "..<" }, - { type: "NUMBER", value: "5" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); - - it('should handle decimal ending in 0 half-open ranges', function () { - input = String.raw`var a = 1.0..<5.0`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1.0" }, - { type: "HALF-OPEN_RANGE", value: "..<" }, - { type: "NUMBER", value: "5.0" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); - - it('should handle random decimal half-open ranges', function () { - input = String.raw`var a = 1.2..<5.3`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1.2" }, - { type: "HALF-OPEN_RANGE", value: "..<" }, - { type: "NUMBER", value: "5.3" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); - - it('should handle all ranges', function () { - input = String.raw`var a = 1...5; var b = 2..<6`; - output = [ - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "a" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "1" }, - { type: "CLOSED_RANGE", value: "..." }, - { type: "NUMBER", value: "5" }, - { type: "PUNCTUATION", value: ";"}, - { type: "DECLARATION_KEYWORD", value: "var" }, - { type: "IDENTIFIER", value: "b" }, - { type: "OPERATOR", value: "=" }, - { type: "NUMBER", value: "2" }, - { type: "HALF-OPEN_RANGE", value: "..<" }, - { type: "NUMBER", value: "6" }, - { type: "TERMINATOR", value: "EOF"} - ]; - expect(lexer(input)).to.deep.equal(output); - }); - - it('should handle ranges delimited by identifiers', function () { - input = String.raw`let start = 0; let end = 10; let range = start..", tokens); if (insideFunction[insideFunction.length - 1].insideReturnStatement === false) { insideFunction[insideFunction.length - 1].insideReturnStatement = true; - } + } advanceAndClear(2); continue; } if (insideFunction.length && lastFunction.insideParams === true && chunk === '(') { lexerFunctions.checkFor('FUNCTION_DECLARATION', chunk, tokens); - var len = tokens.length - 1; - while (tokens[len].type !== 'IDENTIFIER') { - len--; - } - FUNCTION_NAMES[tokens[len].value] = true; - advanceAndClear(1); - continue; + var len = tokens.length - 1; + while (tokens[len].type !== 'IDENTIFIER') { + len--; + } + FUNCTION_NAMES[tokens[len].value] = true; + advanceAndClear(1); + continue; } // Function Invocation Start @@ -175,8 +175,8 @@ module.exports = function(code) { // continue; // } - if (chunk === '(' && ((FUNCTION_NAMES[lastToken.value] && - tokens[tokens.length - 2].value !== 'func') || lastToken.type === 'NATIVE_METHOD' || lastToken.type === 'TYPE_STRING' || + if (chunk === '(' && ((FUNCTION_NAMES[lastToken.value] && + tokens[tokens.length - 2].value !== 'func') || lastToken.type === 'NATIVE_METHOD' || lastToken.type === 'TYPE_STRING' || lastToken.type === 'TYPE_NUMBER')) { lexerFunctions.checkFor('FUNCTION_INVOCATION', chunk, tokens); var tmp = {}; @@ -212,7 +212,7 @@ module.exports = function(code) { advanceAndClear(1); continue; } - + //Function invocation end // tuple handling @@ -256,7 +256,7 @@ module.exports = function(code) { advanceAndClear(1); continue; } - + if (insideFunction.length && chunk === ')' && insideFunction[insideFunction.length - 1].insideParams === true) { lexerFunctions.checkFor('FUNCTION_DECLARATION', chunk, tokens); insideFunction[insideFunction.length - 1].insideParams = "ended"; @@ -264,7 +264,7 @@ module.exports = function(code) { continue; } - if (tokens.length >= 2 && tokens[tokens.length - 2]['type'] === 'PUNCTUATION' && + if (tokens.length >= 2 && tokens[tokens.length - 2]['type'] === 'PUNCTUATION' && tokens[tokens.length - 2]['value'] === '(' && lastFunction && lastFunction.insideReturnStatement === true) { tokens[tokens.length - 2].type = 'PARAMS_START'; } @@ -303,9 +303,9 @@ module.exports = function(code) { lexerFunctions.handleEndOfFile(nextCol, tokens); continue; } - + // collection initializer syntax handling - if (tokens.length && currCol === '(' && + if (tokens.length && currCol === '(' && (lastToken.type === 'ARRAY_END' || lastToken.type === 'DICTIONARY_END')) { lexerFunctions.checkFor('FUNCTION_INVOCATION', currCol, tokens); var tmp = {}; @@ -316,7 +316,7 @@ module.exports = function(code) { advanceAndClear(1); continue; } - + ///////////////////////////////////////////// // // // classes and structures handling // @@ -324,9 +324,9 @@ module.exports = function(code) { /////////////////////////////////////////////////////////////////////////// // handles inheritance operators - if (tokens.length > 2 && tokens[tokens.length - 2].value === ':' && + if (tokens.length > 2 && tokens[tokens.length - 2].value === ':' && CLASS_NAMES[lastToken.value] && CLASS_NAMES[tokens[tokens.length - 3].value]) { - tokens[tokens.length - 2].type = 'INHERITANCE_OPERATOR'; + tokens[tokens.length - 2].type = 'INHERITANCE_OPERATOR'; } if (insideClass.length && insideClass[insideClass.length - 1].curly === 0 && chunk === '{') { @@ -358,7 +358,7 @@ module.exports = function(code) { lexerFunctions.handleEndOfFile(nextCol, tokens); continue; } - if (tokens.length && (CLASS_NAMES[lastToken.value] || + if (tokens.length && (CLASS_NAMES[lastToken.value] || STRUCT_NAMES[lastToken.value]) && chunk === '(') { lexerFunctions.checkFor('INITIALIZATION', chunk, tokens) var temp = {}; @@ -368,7 +368,7 @@ module.exports = function(code) { advanceAndClear(1); continue; } - if (chunk === ')' && insideInitialization.length && + if (chunk === ')' && insideInitialization.length && insideInitialization[insideInitialization.length - 1].parens === 1) { lexerFunctions.checkFor('INITIALIZATION', chunk, tokens); insideInitialization.pop(); @@ -376,26 +376,26 @@ module.exports = function(code) { lexerFunctions.handleEndOfFile(nextCol, tokens); continue; } - + // handles parentheses inside class and struct initialization - if (chunk === '(' && insideInitialization.length && + if (chunk === '(' && insideInitialization.length && insideInitialization[insideInitialization.length - 1].parens >= 1) { insideInitialization[insideInitialization.length - 1].parens++; } if (chunk === ')' && insideInitialization.length) { insideInitialization[insideInitialization.length - 1].parens--; } - + // handles property access and method calls via dot notation if (currCol === '.' && !lexerFunctions.checkForWhitespace(prevCol) && !lexerFunctions.checkForWhitespace(nextCol) && ( - lastToken.type === 'IDENTIFIER' || lastToken.value === 'self' || - lastToken.type === 'TYPE_PROPERTY')) { + lastToken.type === 'IDENTIFIER' || lastToken.value === 'self' || + lastToken.type === 'TYPE_PROPERTY')) { lexerFunctions.makeToken(undefined, chunk, tokens, 'DOT_SYNTAX', '.'); advanceAndClear(1); continue; } - + /////////////////////////////////////////////////////////////////////////// // main evaluation block diff --git a/transpiler/lexer/lexicalTypes.js b/transpiler/lexer/lexicalTypes.js index 90c0864..ba3a898 100644 --- a/transpiler/lexer/lexicalTypes.js +++ b/transpiler/lexer/lexicalTypes.js @@ -19,7 +19,6 @@ module.exports = { 'insertContentsOf': 'NATIVE_METHOD', 'predecessor': 'NATIVE_METHOD', 'print': 'NATIVE_METHOD', - 'println': 'NATIVE_METHOD', 'removeAtIndex': 'NATIVE_METHOD', 'removeAll': 'NATIVE_METHOD', 'removeFirst': 'NATIVE_METHOD', @@ -29,14 +28,14 @@ module.exports = { 'successor': 'NATIVE_METHOD', 'updateValue': 'NATIVE_METHOD', }, - + METHOD_ARGUMENT_NAME: { 'at': 'METHOD_ARGUMENT_NAME', 'atIndex': 'METHOD_ARGUMENT_NAME', 'forKey': 'METHOD_ARGUMENT_NAME', 'repeatedValue': 'METHOD_ARGUMENT_NAME' }, - + TYPE_PROPERTY: { 'characters': 'TYPE_PROPERTY', 'count': 'TYPE_PROPERTY', @@ -63,17 +62,17 @@ module.exports = { '(': 'INVOCATION_START', ')': 'INVOCATION_END' }, - + CLASS_DEFINITION: { '{': 'CLASS_DEFINITION_START', '}': 'CLASS_DEFINITION_END' }, - + STRUCT_DEFINITION: { '{': 'STRUCT_DEFINITION_START', '}': 'STRUCT_DEFINITION_END' }, - + INITIALIZATION: { '(': 'INITIALIZATION_START', ')': 'INITIALIZATION_END' @@ -83,19 +82,19 @@ module.exports = { '[': 'ARRAY_START', ']': 'COLLECTION_END' }, - + COMMENT: { '//': 'COMMENT_START', '/*': 'MULTI_LINE_COMMENT_START', - '*/': 'MULTI_LINE_COMMENT_END' + '*/': 'MULTI_LINE_COMMENT_END' }, - - KEYWORD: { - + + KEYWORD: { + // keywords used in declarations - 'class': 'DECLARATION_KEYWORD', - 'deinit': 'DECLARATION_KEYWORD', - 'enum': 'DECLARATION_KEYWORD', + 'class': 'DECLARATION_KEYWORD', + 'deinit': 'DECLARATION_KEYWORD', + 'enum': 'DECLARATION_KEYWORD', 'extension': 'DECLARATION_KEYWORD', 'func': 'DECLARATION_KEYWORD', 'import': 'DECLARATION_KEYWORD', @@ -103,16 +102,16 @@ module.exports = { 'inout': 'DECLARATION_KEYWORD', 'internal': 'DECLARATION_KEYWORD', 'let': 'DECLARATION_KEYWORD', - 'operator': 'DECLARATION_KEYWORD', - 'private': 'DECLARATION_KEYWORD', - 'protocol': 'DECLARATION_KEYWORD', - 'public': 'DECLARATION_KEYWORD', - 'static': 'DECLARATION_KEYWORD', - 'struct': 'DECLARATION_KEYWORD', - 'subscript': 'DECLARATION_KEYWORD', + 'operator': 'DECLARATION_KEYWORD', + 'private': 'DECLARATION_KEYWORD', + 'protocol': 'DECLARATION_KEYWORD', + 'public': 'DECLARATION_KEYWORD', + 'static': 'DECLARATION_KEYWORD', + 'struct': 'DECLARATION_KEYWORD', + 'subscript': 'DECLARATION_KEYWORD', 'typealias': 'DECLARATION_KEYWORD', 'var': 'DECLARATION_KEYWORD', - + // keywords used in statements 'break': 'STATEMENT_KEYWORD', 'case': 'STATEMENT_KEYWORD', @@ -131,99 +130,99 @@ module.exports = { 'switch': 'STATEMENT_KEYWORD', 'where': 'STATEMENT_KEYWORD', 'while': 'STATEMENT_KEYWORD', - + // keywords used in expressions and types - 'as': 'EXPRESSION_OR_TYPE_KEYWORD', - 'catch': 'EXPRESSION_OR_TYPE_KEYWORD', - 'dynamicType': 'EXPRESSION_OR_TYPE_KEYWORD', - 'is': 'EXPRESSION_OR_TYPE_KEYWORD', - 'nil': 'EXPRESSION_OR_TYPE_KEYWORD', - 'rethrows': 'EXPRESSION_OR_TYPE_KEYWORD', - 'super': 'EXPRESSION_OR_TYPE_KEYWORD', - 'self': 'EXPRESSION_OR_TYPE_KEYWORD', - 'Self': 'EXPRESSION_OR_TYPE_KEYWORD', - 'throw': 'EXPRESSION_OR_TYPE_KEYWORD', - 'throws': 'EXPRESSION_OR_TYPE_KEYWORD', - 'try': 'EXPRESSION_OR_TYPE_KEYWORD', - '__COLUMN__': 'EXPRESSION_OR_TYPE_KEYWORD', - '__FILE__': 'EXPRESSION_OR_TYPE_KEYWORD', - '__FUNCTION__': 'EXPRESSION_OR_TYPE_KEYWORD', + 'as': 'EXPRESSION_OR_TYPE_KEYWORD', + 'catch': 'EXPRESSION_OR_TYPE_KEYWORD', + 'dynamicType': 'EXPRESSION_OR_TYPE_KEYWORD', + 'is': 'EXPRESSION_OR_TYPE_KEYWORD', + 'nil': 'EXPRESSION_OR_TYPE_KEYWORD', + 'rethrows': 'EXPRESSION_OR_TYPE_KEYWORD', + 'super': 'EXPRESSION_OR_TYPE_KEYWORD', + 'self': 'EXPRESSION_OR_TYPE_KEYWORD', + 'Self': 'EXPRESSION_OR_TYPE_KEYWORD', + 'throw': 'EXPRESSION_OR_TYPE_KEYWORD', + 'throws': 'EXPRESSION_OR_TYPE_KEYWORD', + 'try': 'EXPRESSION_OR_TYPE_KEYWORD', + '__COLUMN__': 'EXPRESSION_OR_TYPE_KEYWORD', + '__FILE__': 'EXPRESSION_OR_TYPE_KEYWORD', + '__FUNCTION__': 'EXPRESSION_OR_TYPE_KEYWORD', '__LINE__': 'EXPRESSION_OR_TYPE_KEYWORD', - + // keywords used in patterns '_': 'PATTERN_KEYWORD', - + // keywords reserved in particular contexts 'associativity': 'CONTEXT_SPECIFIC_KEYWORD', - 'convenience': 'CONTEXT_SPECIFIC_KEYWORD', - 'dynamic': 'CONTEXT_SPECIFIC_KEYWORD', - 'didSet': 'CONTEXT_SPECIFIC_KEYWORD', - 'final': 'CONTEXT_SPECIFIC_KEYWORD', - 'get': 'CONTEXT_SPECIFIC_KEYWORD', - 'infix': 'CONTEXT_SPECIFIC_KEYWORD', - 'indirect': 'CONTEXT_SPECIFIC_KEYWORD', - 'lazy': 'CONTEXT_SPECIFIC_KEYWORD', - 'left': 'CONTEXT_SPECIFIC_KEYWORD', - 'mutating': 'CONTEXT_SPECIFIC_KEYWORD', - 'none': 'CONTEXT_SPECIFIC_KEYWORD', - 'nonmutating': 'CONTEXT_SPECIFIC_KEYWORD', - 'optional': 'CONTEXT_SPECIFIC_KEYWORD', - 'override': 'CONTEXT_SPECIFIC_KEYWORD', - 'postfix': 'CONTEXT_SPECIFIC_KEYWORD', - 'precedence': 'CONTEXT_SPECIFIC_KEYWORD', - 'prefix': 'CONTEXT_SPECIFIC_KEYWORD', - 'Protocol': 'CONTEXT_SPECIFIC_KEYWORD', - 'required': 'CONTEXT_SPECIFIC_KEYWORD', - 'right': 'CONTEXT_SPECIFIC_KEYWORD', - 'set': 'CONTEXT_SPECIFIC_KEYWORD', - 'Type': 'CONTEXT_SPECIFIC_KEYWORD', - 'unowned': 'CONTEXT_SPECIFIC_KEYWORD', - 'weak': 'CONTEXT_SPECIFIC_KEYWORD', + 'convenience': 'CONTEXT_SPECIFIC_KEYWORD', + 'dynamic': 'CONTEXT_SPECIFIC_KEYWORD', + 'didSet': 'CONTEXT_SPECIFIC_KEYWORD', + 'final': 'CONTEXT_SPECIFIC_KEYWORD', + 'get': 'CONTEXT_SPECIFIC_KEYWORD', + 'infix': 'CONTEXT_SPECIFIC_KEYWORD', + 'indirect': 'CONTEXT_SPECIFIC_KEYWORD', + 'lazy': 'CONTEXT_SPECIFIC_KEYWORD', + 'left': 'CONTEXT_SPECIFIC_KEYWORD', + 'mutating': 'CONTEXT_SPECIFIC_KEYWORD', + 'none': 'CONTEXT_SPECIFIC_KEYWORD', + 'nonmutating': 'CONTEXT_SPECIFIC_KEYWORD', + 'optional': 'CONTEXT_SPECIFIC_KEYWORD', + 'override': 'CONTEXT_SPECIFIC_KEYWORD', + 'postfix': 'CONTEXT_SPECIFIC_KEYWORD', + 'precedence': 'CONTEXT_SPECIFIC_KEYWORD', + 'prefix': 'CONTEXT_SPECIFIC_KEYWORD', + 'Protocol': 'CONTEXT_SPECIFIC_KEYWORD', + 'required': 'CONTEXT_SPECIFIC_KEYWORD', + 'right': 'CONTEXT_SPECIFIC_KEYWORD', + 'set': 'CONTEXT_SPECIFIC_KEYWORD', + 'Type': 'CONTEXT_SPECIFIC_KEYWORD', + 'unowned': 'CONTEXT_SPECIFIC_KEYWORD', + 'weak': 'CONTEXT_SPECIFIC_KEYWORD', 'willSet': 'CONTEXT_SPECIFIC_KEYWORD' - + }, OPERATOR: { - - '/': 'OPERATOR', - '=': 'OPERATOR', - '-': 'OPERATOR', - '+': 'OPERATOR', - '!': 'OPERATOR', - '*': 'OPERATOR', - '%': 'OPERATOR', - '<': 'OPERATOR', - '>': 'OPERATOR', - '&': 'OPERATOR', - '|': 'OPERATOR', - '^': 'OPERATOR', - '?': 'OPERATOR', + + '/': 'OPERATOR', + '=': 'OPERATOR', + '-': 'OPERATOR', + '+': 'OPERATOR', + '!': 'OPERATOR', + '*': 'OPERATOR', + '%': 'OPERATOR', + '<': 'OPERATOR', + '>': 'OPERATOR', + '&': 'OPERATOR', + '|': 'OPERATOR', + '^': 'OPERATOR', + '?': 'OPERATOR', '~': 'OPERATOR' - + }, // TODO end of file terminator at end of string, new line terminator, semicolon terminator PUNCTUATION: { - + '(': 'PUNCTUATION', - ')': 'PUNCTUATION', - '{': 'PUNCTUATION', - '}': 'PUNCTUATION', - '.': 'PUNCTUATION', - ',': 'PUNCTUATION', - ':': 'PUNCTUATION', - ';': 'PUNCTUATION', - '@': 'PUNCTUATION', - '#': 'PUNCTUATION', + ')': 'PUNCTUATION', + '{': 'PUNCTUATION', + '}': 'PUNCTUATION', + '.': 'PUNCTUATION', + ',': 'PUNCTUATION', + ':': 'PUNCTUATION', + ';': 'PUNCTUATION', + '@': 'PUNCTUATION', + '#': 'PUNCTUATION', '`': 'PUNCTUATION', // '?': 'PUNCTUATION' }, SUBSTRING_LOOKUP: { - '[': 'SUBSTRING_LOOKUP_START', - ']': 'SUBSTRING_LOOKUP_END', + '[': 'SUBSTRING_LOOKUP_START', + ']': 'SUBSTRING_LOOKUP_END', }, SPECIAL_STRING: { @@ -237,7 +236,7 @@ module.exports = { '\\r': 'TERMINATOR', '\\t': 'TAB' }, - + TYPE: { 'Character': 'TYPE_STRING', 'Double': 'TYPE_NUMBER', @@ -256,5 +255,5 @@ module.exports = { 'UInt64': 'TYPE_NUMBER' } - + }; \ No newline at end of file diff --git a/transpiler/parser/advance.js b/transpiler/parser/advance.js index 9670335..bb07e15 100644 --- a/transpiler/parser/advance.js +++ b/transpiler/parser/advance.js @@ -41,7 +41,6 @@ var advance = function(state, id) { t.error("Unknown operator."); } } else if (tokenTypes.terminator.hasItem(a) || tokenTypes.verb.hasItem(a)) { - console.log(v); o = state.symbolTable[v]; if (!o) { t.error("Unknown operator."); diff --git a/transpiler/parser/declarations.js b/transpiler/parser/declarations.js index 5318bca..2ff8fd5 100644 --- a/transpiler/parser/declarations.js +++ b/transpiler/parser/declarations.js @@ -111,29 +111,28 @@ var declarations = { infix(state, "(", 80, function(left) { var a = []; - if (left.id === "." || left.id === "[") { - this.type = "ternary"; - this.first = left.first; - this.second = left.second; - this.third = a; - } else { - this.type = "MemberExpression"; - this.computed = false; - this.object = {}; - this.object.type = "Identifier"; - this.object.name = state.token.value; - this.property; - this.arguments = a; - //this.first = left; - //this.second = a; - delete this.value; - //if ((left.type !== "unary" || left.id !== "function") && left.id !== "(" && - // left.type !== 'binary' && left.id !== "&&" && left.id !== "||" && left.id !== "?") { - // left.error("Expected a variable name."); - //} - } - - // + //if (left.id === "." || left.id === "[") { + // this.type = "ternary"; + // this.first = left.first; + // this.second = left.second; + // this.third = a; + //} + this.type = "MemberExpression"; + this.computed = false; + this.object = {}; + this.object.type = "Identifier"; + this.object.name = left.first.value; + this.property = {} + this.property. type = "Identifier"; + this.property.name = left.name; + //this.arguments = a; + //this.first = left; + //this.second = a; + delete this.value; + //if ((left.type !== "unary" || left.id !== "function") && left.id !== "(" && + // left.type !== 'binary' && left.id !== "&&" && left.id !== "||" && left.id !== "?") { + // left.error("Expected a variable name."); + //} if (state.token.id !== ")") { while (true) { @@ -145,7 +144,19 @@ var declarations = { } } state = advance(state, ")"); - return this; + delete this.value; + + var outputRes = { + type: 'ExpressionStatement', + expression: + { + type: 'CallExpression', + callee: this, + arguments: a + } + }; + + return outputRes; }); }, @@ -163,7 +174,7 @@ var declarations = { return e; }); - prefix(state, "function", function() { + prefix(state, "func", function() { var a = []; state.scope = newScope(state, originalScope); if (state.token.type === "name") { diff --git a/transpiler/parser/expression.js b/transpiler/parser/expression.js index 94026bb..93b3492 100644 --- a/transpiler/parser/expression.js +++ b/transpiler/parser/expression.js @@ -113,22 +113,7 @@ var expression = function(state, rbp, dontWrapBinExpNodeInExpStmtBool) { //TODO } else if (t.value === ".") { //TODO stuff - state = advance(state); - - //console.log("####################################"); - //console.log('----------- START t -------------'); - //console.log(t); - //console.log('----------- END t -------------'); - // - //console.log('----------- START state.token -------------'); - //console.log(state.token); - //console.log('----------- END state.token -------------'); - // - //console.log('----------- START left -------------'); - //console.log(left); - //console.log('----------- END left -------------'); - //console.log("####################################"); } //else if (left.type === "AssignmentExpression") { // //left.left = overwrittenMemberExpression; diff --git a/transpiler/parser/parserRunner.js b/transpiler/parser/parserRunner.js index ea4b518..1c92647 100644 --- a/transpiler/parser/parserRunner.js +++ b/transpiler/parser/parserRunner.js @@ -4,55 +4,374 @@ var helpers = require('./helperFunctions.js'); var makeParse = require('./parser'); var expected = { - "type": "Program", "body": [ - { - "type": "ExpressionStatement", - "expression": { + { + + "type": "VariableDeclaration", + "declarations": [ + { + + "type": "VariableDeclarator", + "id": { + + "type": "Identifier", + "name": "name" + }, + "init": { + + "type": "Literal", + "value": "Joe", + "raw": "\"Joe\"" + } + } + ], + "kind": "var" + }, + { + + "type": "VariableDeclaration", + "declarations": [ + { + + "type": "VariableDeclarator", + "id": { + + "type": "Identifier", + "name": "arr" + }, + "init": { + + "type": "ArrayExpression", + "elements": [ + { + + "type": "Literal", + "value": 1, + "raw": "1" + }, + { + + "type": "Literal", + "value": 2, + "raw": "2" + } + ] + } + } + ], + "kind": "var" + }, + { + + "type": "VariableDeclaration", + "declarations": [ + { + + "type": "VariableDeclarator", + "id": { + + "type": "Identifier", + "name": "tup" + }, + "init": { + + "type": "ObjectExpression", + "properties": [ + { + + "type": "Property", + "key": { + + "type": "Literal", + "value": 0, + "raw": "0" + }, + "computed": false, + "value": { - "type": "CallExpression", - "callee": { + "type": "Literal", + "value": 1, + "raw": "1" + }, + "kind": "init", + "method": false, + "shorthand": false + }, + { + + "type": "Property", + "key": { + + "type": "Literal", + "value": 1, + "raw": "1" + }, + "computed": false, + "value": { + + "type": "Literal", + "value": 2, + "raw": "2" + }, + "kind": "init", + "method": false, + "shorthand": false + } + ] + } + } + ], + "kind": "var" + }, + { + + "type": "ExpressionStatement", + "expression": { + + "type": "CallExpression", + "callee": { + + "type": "MemberExpression", + "computed": false, + "object": { + + "type": "Identifier", + "name": "console" + }, + "property": { + + "type": "Identifier", + "name": "log" + } + }, + "arguments": [ + { + + "type": "BinaryExpression", + "operator": "+", + "left": { + + "type": "Literal", + "value": "Hello, ", + "raw": "'Hello, '" + }, + "right": { + + "type": "Identifier", + "name": "name" + } + } + ] + } + }, + { + + "type": "ExpressionStatement", + "expression": { + + "type": "CallExpression", + "callee": { + + "type": "MemberExpression", + "computed": false, + "object": { + + "type": "Identifier", + "name": "console" + }, + "property": { + + "type": "Identifier", + "name": "log" + } + }, + "arguments": [ + { + + "type": "BinaryExpression", + "operator": "*", + "left": { + + "type": "Literal", + "value": 5, + "raw": "5" + }, + "right": { + + "type": "BinaryExpression", + "operator": "+", + "left": { + + "type": "Literal", + "value": 1, + "raw": "1" + }, + "right": { + + "type": "Literal", + "value": 1, + "raw": "1" + } + } + } + ] + } + }, + { + + "type": "ExpressionStatement", + "expression": { + + "type": "CallExpression", + "callee": { + + "type": "MemberExpression", + "computed": false, + "object": { + + "type": "Identifier", + "name": "console" + }, + "property": { + + "type": "Identifier", + "name": "log" + } + }, + "arguments": [ + { "type": "MemberExpression", - "computed": false, + "computed": true, "object": { "type": "Identifier", - "name": "console" + "name": "arr" }, "property": { - "type": "Identifier", - "name": "log" + + "type": "Literal", + "value": 1, + "raw": "1" } + } + ] + } + }, + { + "type": "ExpressionStatement", + "expression": { + + "type": "CallExpression", + "callee": { + + "type": "MemberExpression", + "computed": false, + "object": { + + "type": "Identifier", + "name": "console" }, - "arguments": [ - { + "property": { + + "type": "Identifier", + "name": "log" + } + }, + "arguments": [ + { + + "type": "MemberExpression", + "computed": true, + "object": { + + "type": "Identifier", + "name": "tup" + }, + "property": { + "type": "Literal", - "value": "Hello", - "raw": "'Hello'" + "value": 0, + "raw": "0" } - ] - } + } + ] } - ], + } +], "sourceType": "module" }; var tokenStream = [ - //{ type: "DECLARATION_KEYWORD", value: "var" }, - //{ type: "IDENTIFIER", value: "console" }, - //{ type: "OPERATOR", value: "=" }, - //{ type: "DICTIONARY_START", value: "[" }, - //{ type: "DICTIONARY_END", value: "]" }, - //{ type: "PUNCTUATION", value: ";"}, + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "name" }, + { type: "OPERATOR", value: "=" }, + { type: "STRING", value: "Joe" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "arr" }, + { type: "OPERATOR", value: "=" }, + { type: "ARRAY_START", value: "[" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: "," }, + { type: "NUMBER", value: "2" }, + { type: "ARRAY_END", value: "]" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "DECLARATION_KEYWORD", value: "var" }, + { type: "IDENTIFIER", value: "tup" }, + { type: "OPERATOR", value: "=" }, + { type: "TUPLE_START", value: "(" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: "," }, + { type: "NUMBER", value: "2" }, + { type: "TUPLE_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "name" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "NATIVE_METHOD", value: "print"}, - //{ type: "INVOCATION_START", value: "(" }, - { type: "PUNCTUATION", value: "(" }, - { type: "STRING", value: "Hello" }, - //{ type: "INVOCATION_END", value: ")" }, - { type: "PUNCTUATION", value: ")" }, + { type: "INVOCATION_START", value: "(" }, + { type: "STRING", value: "Hello, " }, + { type: "STRING_INTERPOLATION_START", value: "\\(" }, + { type: "IDENTIFIER", value: "name" }, + { type: "STRING_INTERPOLATION_END", value: ")" }, + { type: "STRING", value: "" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, - { type: "TERMINATOR", value: "EOF" }, + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "NUMBER", value: "5" }, + { type: "OPERATOR", value: "*" }, + { type: "PUNCTUATION", value: "(" }, + { type: "NUMBER", value: "1" }, + { type: "OPERATOR", value: "+" }, + { type: "NUMBER", value: "1" }, + { type: "PUNCTUATION", value: ")" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "arr" }, + { type: "SUBSTRING_LOOKUP_START", value: "[" }, + { type: "NUMBER", value: "1" }, + { type: "SUBSTRING_LOOKUP_END", value: "]" }, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "\\n"}, + + { type: "NATIVE_METHOD", value: "print"}, + { type: "INVOCATION_START", value: "(" }, + { type: "IDENTIFIER", value: "tup" }, + { type: "DOT_SYNTAX", value: "." }, + { type: "NUMBER", value: "0"}, + { type: "INVOCATION_END", value: ")" }, + { type: "TERMINATOR", value: "EOF" } ]; var parser = makeParse(); diff --git a/transpiler/parser/rearrangeTokensPrintToConsoleLog.js b/transpiler/parser/rearrangeTokensPrintToConsoleLog.js index 114c1dd..8d9cf6a 100644 --- a/transpiler/parser/rearrangeTokensPrintToConsoleLog.js +++ b/transpiler/parser/rearrangeTokensPrintToConsoleLog.js @@ -24,7 +24,7 @@ var rearrangeTokensPrintToConsoleLog = function(tokens) { } } - console.log(util.inspect(tokens, {colors:true, depth:null})); + //console.log(util.inspect(tokens, {colors:true, depth:null})); return tokens; }; diff --git a/transpiler/parser/statement.js b/transpiler/parser/statement.js index 94918ce..d0ca70f 100644 --- a/transpiler/parser/statement.js +++ b/transpiler/parser/statement.js @@ -51,15 +51,34 @@ var statement = function(state) { if(state.token.value === "}") { return v; } + + while (true) { + //state = advance(state); + if (![';', '\\n', ')', '.'].hasItem(state.token.value)) { + state = advance(state); + } else { + break; + } + } if (state.token.value === ')') { state = advance(state); } + + if(state.token.value === "\\n") { + state = advance(state); + } + + + + if(state.token.value === "EOF") { return v; } else if (!v.assignment && v.id !== "(") { + console.log(state.token); + console.log(v); v.error("Bad expression statement."); } //state = advance(state, ";"); diff --git a/transpiler/parser/tokenTypes.js b/transpiler/parser/tokenTypes.js index e30c1f9..1ab10b5 100644 --- a/transpiler/parser/tokenTypes.js +++ b/transpiler/parser/tokenTypes.js @@ -29,7 +29,8 @@ module.exports = { "PUNCTUATION", "OPERATOR", "SUBSTRING_LOOKUP_END", - "SUBSTRING_LOOKUP_START" + "SUBSTRING_LOOKUP_START", + "DOT_SYNTAX" ], noun : [ "DECLARATION_KEYWORD", pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy