From 63290aea41e7592476219d34672b7ff9eebc7c89 Mon Sep 17 00:00:00 2001 From: mohayonao Date: Sat, 26 Apr 2014 08:55:59 +0900 Subject: [PATCH] add language parser - add parser written in test version - remove JavaScript literal - remove dictionary for JavaScript keywords, Segmented methods - fix NumericLiteral, support Integer/Float - fix CharLiteral - fix SymbolLiteral - add tests for parse.tokenize - fix BinaryExpression - fix UnaryExpression - add test cases for parser - build v0.0.11 --- assets/index.tmpl | 1 + build/scscript.js | 2387 +++++++++++- package.json | 2 +- src/sc/lang/installer.js | 1 + src/sc/lang/parser.js | 2325 +++++++++++ src/sc/lang/parser_test.js | 877 +++++ src/sc/test/parser-test-case.js | 6419 +++++++++++++++++++++++++++++++ src/sc/test/related.json | 6 +- 8 files changed, 11984 insertions(+), 34 deletions(-) create mode 100644 src/sc/lang/parser.js create mode 100644 src/sc/lang/parser_test.js create mode 100644 src/sc/test/parser-test-case.js diff --git a/assets/index.tmpl b/assets/index.tmpl index 190b3e5..7877fc5 100644 --- a/assets/index.tmpl +++ b/assets/index.tmpl @@ -27,6 +27,7 @@ + #{TESTS} diff --git a/build/scscript.js b/build/scscript.js index 243e640..f4dbb2c 100644 --- a/build/scscript.js +++ b/build/scscript.js @@ -1,7 +1,7 @@ (function(global) { "use strict"; -var sc = { VERSION: "0.0.10" }; +var sc = { VERSION: "0.0.11" }; // src/sc/sc.js (function(sc) { @@ -460,14 +460,14 @@ var sc = { VERSION: "0.0.10" }; (function(sc) { var $SC = function(msg, rcv, args) { - var method; + var method; - method = rcv[msg]; - if (method) { - return method.apply(rcv, args); - } + method = rcv[msg]; + if (method) { + return method.apply(rcv, args); + } - throw new Error(String(rcv) + " cannot understand message '" + msg + "'"); + throw new Error(String(rcv) + " cannot understand message '" + msg + "'"); }; /* istanbul ignore next */ @@ -1061,10 +1061,10 @@ var sc = { VERSION: "0.0.10" }; alwaysReturn$Nil: $SC.Nil, alwaysReturn$True: $SC.True, alwaysReturn$False: $SC.False, - alwaysReturn$Integer_0: function () { + alwaysReturn$Integer_0: function() { return int0Instance; }, - alwaysReturn$Integer_1: function () { + alwaysReturn$Integer_1: function() { return int1Instance; }, defaultValue$Nil: function($obj) { @@ -4038,7 +4038,7 @@ var sc = { VERSION: "0.0.10" }; }; spec.toString = function() { - return String(""+ this._); + return String("" + this._); }; spec.$new = function() { @@ -9803,70 +9803,70 @@ var sc = { VERSION: "0.0.10" }; switch (patternType) { case 1: for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(0, i+1))); + list.push($SC.Array(raw.slice(0, i + 1))); } break; case 2: for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(lastIndex-i, lastIndex+1))); + list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); } break; case 3: for (i = lastIndex; i >= 0; --i) { - list.push($SC.Array(raw.slice(0, i+1))); + list.push($SC.Array(raw.slice(0, i + 1))); } break; case 4: for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(i, lastIndex+1))); + list.push($SC.Array(raw.slice(i, lastIndex + 1))); } break; case 5: for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(0, i+1))); + list.push($SC.Array(raw.slice(0, i + 1))); } - for (i = lastIndex-1; i >= 0; --i) { - list.push($SC.Array(raw.slice(0, i+1))); + for (i = lastIndex - 1; i >= 0; --i) { + list.push($SC.Array(raw.slice(0, i + 1))); } break; case 6: for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(lastIndex-i, lastIndex+1))); + list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); } - for (i = lastIndex-1; i >= 0; --i) { - list.push($SC.Array(raw.slice(lastIndex-i, lastIndex+1))); + for (i = lastIndex - 1; i >= 0; --i) { + list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); } break; case 7: for (i = lastIndex; i >= 0; --i) { - list.push($SC.Array(raw.slice(0, i+1))); + list.push($SC.Array(raw.slice(0, i + 1))); } for (i = 1; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(0, i+1))); + list.push($SC.Array(raw.slice(0, i + 1))); } break; case 8: for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(i, lastIndex+1))); + list.push($SC.Array(raw.slice(i, lastIndex + 1))); } for (i = lastIndex - 1; i >= 0; --i) { - list.push($SC.Array(raw.slice(i, lastIndex+1))); + list.push($SC.Array(raw.slice(i, lastIndex + 1))); } break; case 9: for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(0, i+1))); + list.push($SC.Array(raw.slice(0, i + 1))); } for (i = 1; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(i, lastIndex+1))); + list.push($SC.Array(raw.slice(i, lastIndex + 1))); } break; case 10: for (i = 0; i <= lastIndex; ++i) { - list.push($SC.Array(raw.slice(lastIndex-i, lastIndex+1))); + list.push($SC.Array(raw.slice(lastIndex - i, lastIndex + 1))); } - for (i = lastIndex-1; i >= 0; --i) { - list.push($SC.Array(raw.slice(0, i+1))); + for (i = lastIndex - 1; i >= 0; --i) { + list.push($SC.Array(raw.slice(0, i + 1))); } break; } @@ -9961,7 +9961,7 @@ var sc = { VERSION: "0.0.10" }; for (i = 0; i < newSize; ++i) { k = i; obj3 = new Array(tupSize); - for (j = tupSize - 1; j >=0; --j) { + for (j = tupSize - 1; j >= 0; --j) { if (Array.isArray(obj1[j]._)) { obj4 = obj1[j]._; obj3[j] = obj4[k % obj4.length]; @@ -10022,10 +10022,10 @@ var sc = { VERSION: "0.0.10" }; if (raw.length < size) { a = new Array(size); - for (i = 0, imax = raw.length; i< imax; ++i) { + for (i = 0, imax = raw.length; i < imax; ++i) { a[i] = raw[i]; } - for (b = a[i-1]; i < size; ++i) { + for (b = a[i - 1]; i < size; ++i) { a[i] = b; } } else { @@ -10230,4 +10230,2327 @@ var sc = { VERSION: "0.0.10" }; })(sc); +// src/sc/lang/parser.js +(function(sc) { + + var parser = {}; + + var Token = parser.Token = { + BooleanLiteral: "Boolean", + CharLiteral: "Char", + EOF: "", + FloatLiteral: "Float", + Identifier: "Identifier", + IntegerLiteral: "Integer", + Keyword: "Keyword", + Label: "Label", + NilLiteral: "Nil", + Punctuator: "Punctuator", + StringLiteral: "String", + SymbolLiteral: "Symbol" + }; + + var Syntax = parser.Syntax = { + AssignmentExpression: "AssignmentExpression", + BinaryExpression: "BinaryExpression", + BlockExpression: "BlockExpression", + CallExpression: "CallExpression", + FunctionExpression: "FunctionExpression", + GlobalExpression: "GlobalExpression", + Identifier: "Identifier", + ListExpression: "ListExpression", + ListIndexer: "ListIndexer", + Label: "Label", + Literal: "Literal", + MemberExpression: "MemberExpression", + ObjectExpression: "ObjectExpression", + Program: "Program", + RangeExpression: "RangeExpression", + ThisExpression: "ThisExpression", + UnaryExpression: "UnaryExpression", + VariableDeclaration: "VariableDeclaration", + VariableDeclarator: "VariableDeclarator" + }; + + var Message = parser.Message = { + ArgumentAlreadyDeclared: "argument '%0' already declared", + InvalidLHSInAssignment: "invalid left-hand side in assignment", + NotImplemented: "not implemented %0", + UnexpectedEOS: "unexpected end of input", + UnexpectedIdentifier: "unexpected identifier", + UnexpectedChar: "unexpected char", + UnexpectedLabel: "unexpected label", + UnexpectedNumber: "unexpected number", + UnexpectedString: "unexpected string", + UnexpectedSymbol: "unexpected symbol", + UnexpectedToken: "unexpected token %0", + VariableAlreadyDeclared: "variable '%0' already declared", + VariableNotDefined: "variable '%0' not defined" + }; + + var Keywords = parser.Keywords = { + var: "keyword", + arg: "keyword", + const: "keyword", + this: "function", + thisThread: "function", + thisProcess: "function", + thisFunction: "function", + thisFunctionDef: "function", + }; + + var binaryPrecedenceDefaults = { + "?" : 1, + "??" : 1, + "!?" : 1, + "->" : 2, + "||" : 3, + "&&" : 4, + "|" : 5, + "&" : 6, + "==" : 7, + "!=" : 7, + "===": 7, + "!==": 7, + "<" : 8, + ">" : 8, + "<=" : 8, + ">=" : 8, + "<<" : 9, + ">>" : 9, + "+>>": 9, + "+" : 10, + "-" : 10, + "*" : 11, + "/" : 11, + "%" : 11, + "!" : 12, + }; + + function q(str) { + return "'" + str + "'"; + } + + function char2num(ch) { + var n = ch.charCodeAt(0); + + if (48 <= n && n <= 57) { + return n - 48; + } + if (65 <= n && n <= 90) { + return n - 55; + } + return n - 87; // if (97 <= n && n <= 122) + } + + function isNumber(ch) { + return "0" <= ch && ch <= "9"; + } + + function Scope(parser) { + this.parser = parser; + this.stack = []; + } + + Scope.prototype.add = function(type, id) { + var peek = this.stack[this.stack.length - 1]; + var vars, args, declared; + + vars = peek.vars; + args = peek.args; + declared = peek.declared; + + switch (type) { + case "var": + if (args[id] || vars[id]) { + this.parser.throwError({}, Message.VariableAlreadyDeclared, id); + } else { + vars[id] = true; + delete declared[id]; + } + break; + case "arg": + if (args[id]) { + this.parser.throwError({}, Message.ArgumentAlreadyDeclared, id); + } + args[id] = true; + delete declared[id]; + break; + } + }; + + Scope.prototype.begin = function() { + var peek = this.stack[this.stack.length - 1]; + var declared = {}; + + if (peek) { + Array.prototype.concat.apply([], [ + peek.declared, peek.args, peek.vars + ].map(Object.keys)).forEach(function(key) { + declared[key] = true; + }); + } + + this.stack.push({ vars: {}, args: {}, declared: declared }); + }; + + Scope.prototype.end = function() { + this.stack.pop(); + }; + + function LocationMarker(parser) { + this.parser = parser; + this.marker = [ + parser.index, + parser.lineNumber, + parser.index - parser.lineStart + ]; + } + + LocationMarker.prototype.apply = function(node) { + var parser = this.parser; + var marker = this.marker; + + /* istanbul ignore else */ + if (this.parser.opts.range) { + node.range = [ marker[0], parser.index ]; + } + /* istanbul ignore else */ + if (this.parser.opts.loc) { + node.loc = { + start: { + line: marker[1], + column: marker[2] + }, + end: { + line: parser.lineNumber, + column: parser.index - parser.lineStart + } + }; + } + }; + + function SCParser(source, opts) { + /* istanbul ignore next */ + if (typeof source !== "string") { + if (typeof source === "undefined") { + source = ""; + } + source = String(source); + } + source = source.replace(/\r\n?/g, "\n"); + this.source = source; + this.opts = opts; + this.length = source.length; + this.index = 0; + this.lineNumber = this.length ? 1 : 0; + this.lineStart = 0; + this.reverted = null; + this.scope = new Scope(this); + this.marker = []; + this.tokens = opts.tokens ? [] : null; + this.errors = opts.tolerant ? [] : null; + this.state = { + closedFunction: false, + disallowNotMember: false, + disallowGenerator: false, + innerElements: false, + immutableList: false, + underscore: [] + }; + } + + SCParser.prototype.parse = function() { + return this.parseProgram(); + }; + + SCParser.prototype.skipComment = function() { + var source = this.source; + var length = this.length; + var index = this.index; + var lineNumber = this.lineNumber; + var lineStart = this.lineStart; + var ch, depth; + + LOOP: while (index < length) { + ch = source.charAt(index); + switch (ch) { + + case " ": + case "\t": + index += 1; + continue LOOP; + /* falls through */ + + case "\n": + index += 1; + lineNumber += 1; + lineStart = index; + continue LOOP; + /* falls through */ + + case "/": + ch = source.charAt(index + 1); + switch (ch) { + case "/": + // line comment + index += 2; + while (index < length) { + ch = source.charAt(index); + index += 1; + if (ch === "\n") { + lineNumber += 1; + lineStart = index; + break; + } + } + break; + + case "*": + // block comment + depth = 1; + index += 2; + while (index < length) { + ch = source.charAt(index); + switch (ch) { + case "/": + ch = source.charAt(index + 1); + if (ch === "*") { + depth += 1; + index += 1; + } + break; + case "*": + ch = source.charAt(index + 1); + if (ch === "/") { + depth -= 1; + index += 1; + if (depth === 0) { + index += 1; + continue LOOP; + } + } + break; + case "\n": + lineNumber += 1; + lineStart = index; + break; + } + index += 1; + } + this.throwError({}, Message.UnexpectedToken, "ILLEGAL"); + break; + + default: + break LOOP; + } + break; + + default: + break LOOP; + } + } + + this.index = index; + this.lineNumber = lineNumber; + this.lineStart = lineStart; + }; + + SCParser.prototype.collectToken = function() { + var loc, token, source, t; + + this.skipComment(); + + loc = { + start: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; + + token = this.advance(); + + loc.end = { + line: this.lineNumber, + column: this.index - this.lineStart + }; + + if (token.type !== Token.EOF) { + source = this.source; + t = { + type: token.type, + value: source.slice(token.range[0], token.range[1]) + }; + if (this.opts.range) { + t.range = [ token.range[0], token.range[1] ]; + } + if (this.opts.loc) { + t.loc = loc; + } + this.tokens.push(t); + } + + return token; + }; + + SCParser.prototype.advance = function() { + var ch, token; + + this.skipComment(); + + if (this.length <= this.index) { + return this.EOFToken(); + } + + ch = this.source.charAt(this.index); + + // Symbol literal starts with back slash + if (ch === "\\") { + return this.scanSymbolLiteral(); + } + + // Char literal starts with dollar + if (ch === "$") { + return this.scanCharLiteral(); + } + + // String literal starts with single quote or double quote + if (ch === "'" || ch === "\"") { + return this.scanStringLiteral(); + } + + // for partial application + if (ch === "_") { + return this.scanUnderscore(); + } + + if (ch === "-") { + token = this.scanNegativeNumericLiteral(); + if (token) { + return token; + } + } + + // Identifier starts with alphabet + if (("A" <= ch && ch <= "Z") || ("a" <= ch && ch <= "z")) { + return this.scanIdentifier(); + } + + // Number literal starts with number + if (isNumber(ch)) { + return this.scanNumericLiteral(); + } + + return this.scanPunctuator(); + }; + + SCParser.prototype.expect = function(value) { + var token = this.lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + this.throwUnexpected(token, value); + } + }; + + SCParser.prototype.peek = function() { + var index, lineNumber, lineStart; + + index = this.index; + lineNumber = this.lineNumber; + lineStart = this.lineStart; + + if (this.opts.tokens) { + this.lookahead = this.collectToken(); + } else { + this.lookahead = this.advance(); + } + + this.index = index; + this.lineNumber = lineNumber; + this.lineStart = lineStart; + }; + + SCParser.prototype.lex = function() { + var token = this.lookahead; + + this.index = token.range[1]; + this.lineNumber = token.lineNumber; + this.lineStart = token.lineStart; + + if (this.opts.tokens) { + this.lookahead = this.collectToken(); + } else { + this.lookahead = this.advance(); + } + + this.index = token.range[1]; + this.lineNumber = token.lineNumber; + this.lineStart = token.lineStart; + + return token; + }; + + SCParser.prototype.EOFToken = function() { + return { + type: Token.EOF, + value: "", + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ this.index, this.index ] + }; + }; + + SCParser.prototype.restore = function(saved) { + this.lookahead = saved[0]; + this.index = saved[1]; + this.lineNumber = saved[2]; + this.lineStart = saved[3]; + if (this.tokens) { + this.tokens.pop(); + } + }; + + SCParser.prototype.save = function() { + return [ this.lookahead, this.index, this.lineNumber, this.lineStart ]; + }; + + SCParser.prototype.scanCharLiteral = function() { + var start, value; + + start = this.index; + value = this.source.charAt(this.index + 1); + + this.index += 2; + + return { + type : Token.CharLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanIdentifier = function() { + var source = this.source.slice(this.index); + var start = this.index; + var value, type; + + value = /^[a-zA-Z][a-zA-Z0-9_]*/.exec(source)[0]; + + this.index += value.length; + + if (this.source.charAt(this.index) === ":") { + this.index += 1; + return { + type: Token.Label, + value: value, + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] + }; + } else if (this.isKeyword(value)) { + type = Token.Keyword; + } else { + switch (value) { + case "inf": + type = Token.FloatLiteral; + value = "Infinity"; + break; + case "pi": + type = Token.FloatLiteral; + value = "Math.PI"; + break; + case "nil": + type = Token.NilLiteral; + value = "null"; + break; + case "true": + case "false": + type = Token.BooleanLiteral; + break; + default: + type = Token.Identifier; + break; + } + } + + return { + type: type, + value: value, + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanNumericLiteral = function(neg) { + return this.scanNAryNumberLiteral(neg) || this.scanDecimalNumberLiteral(neg); + }; + + SCParser.prototype.scanNegativeNumericLiteral = function() { + var token, ch1, ch2, ch3; + var start, value = null; + + start = this.index; + ch1 = this.source.charAt(this.index + 1); + + if (isNumber(ch1)) { + this.index += 1; + token = this.scanNumericLiteral(true); + token.range[0] = start; + return token; + } + + ch2 = this.source.charAt(this.index + 2); + ch3 = this.source.charAt(this.index + 3); + + if (ch1 + ch2 === "pi") { + this.index += 3; + value = -Math.PI; + } else if (ch1 + ch2 + ch3 === "inf") { + this.index += 4; + value = -Infinity; + } + + if (value !== null) { + return { + type : Token.FloatLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + } + + return null; + }; + + SCParser.prototype.scanNAryNumberLiteral = function(neg) { + var re, start, items; + var base, integer, frac, pi; + var x, i, imax; + var value, type; + + re = /^(\d+)r((?:[\da-zA-Z](?:_(?=[\da-zA-Z]))?)+)(?:\.((?:[\da-zA-Z](?:_(?=[\da-zA-Z]))?)+))?/; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + if (!items) { + return; + } + + base = items[1].replace(/^0+(?=\d)/g, "")|0; + integer = items[2].replace(/(^0+(?=\d)|_)/g, ""); + frac = items[3] && items[3].replace(/_/g, ""); + + if (!frac && base < 26 && integer.substr(-2) === "pi") { + integer = integer.substr(0, integer.length - 2); + pi = true; + } + + type = Token.IntegerLiteral; + value = 0; + + for (i = 0, imax = integer.length; i < imax; ++i) { + value *= base; + x = char2num(integer[i]); + if (x >= base) { + this.throwError({}, Message.UnexpectedToken, integer[i]); + } + value += x; + } + + if (frac) { + type = Token.FloatLiteral; + for (i = 0, imax = frac.length; i < imax; ++i) { + x = char2num(frac[i]); + if (x >= base) { + this.throwError({}, Message.UnexpectedToken, integer[i]); + } + value += x * Math.pow(base, -(i + 1)); + } + } + + if (neg) { + value *= -1; + } + + if (pi) { + type = Token.FloatLiteral; + value = "(" + value + " * Math.PI)"; + } + + this.index += items[0].length; + + return { + type : type, + value: String(value), + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanDecimalNumberLiteral = function(neg) { + var re, start, items, integer, frac, pi; + var value, type; + + re = /^((?:\d(?:_(?=\d))?)+((?:\.(?:\d(?:_(?=\d))?)+)?(?:e[-+]?(?:\d(?:_(?=\d))?)+)?))(pi)?/; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + integer = items[1]; + frac = items[2]; + pi = items[3]; + + type = (frac || pi) ? Token.FloatLiteral : Token.IntegerLiteral; + value = +integer.replace(/(^0+(?=\d)|_)/g, ""); + + if (neg) { + value *= -1; + } + + if (pi) { + value = "(" + value + " * Math.PI)"; + } + + this.index += items[0].length; + + return { + type : type, + value: String(value), + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanPunctuator = function() { + var re, start, items; + + re = /^(\.{1,3}|[(){}[\]:;,~#`]|[-+*\/%<=>!?&|@]+)/; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + if (items) { + this.index += items[0].length; + return { + type : Token.Punctuator, + value: items[0], + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + } + + this.throwError({}, Message.UnexpectedToken, this.source.charAt(this.index)); + + this.index = this.length; + + return this.EOFToken(); + }; + + SCParser.prototype.scanStringLiteral = function() { + var source, start; + var length, index; + var quote, ch, value, type; + + source = this.source; + length = this.length; + index = start = this.index; + quote = source.charAt(start); + type = (quote === '"') ? Token.StringLiteral : Token.SymbolLiteral; + + index += 1; + while (index < length) { + ch = source.charAt(index); + index += 1; + if (ch === quote) { + value = source.substr(start, index - start); + value = value.replace(/\n/g, "\\n"); + this.index = index; + return { + type : type, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + } else if (ch === "\n") { + this.lineNumber += 1; + this.lineStart = index; + } else if (ch === "\\") { + index += 1; + } + } + + this.index = index; + this.throwError({}, Message.UnexpectedToken, "ILLEGAL"); + + return this.EOFToken(); + }; + + SCParser.prototype.scanSymbolLiteral = function() { + var re, start, items; + var value; + + re = /^\\([a-z_]\w*)?/i; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + value = items[1]; + + this.index += items[0].length; + + return { + type : Token.SymbolLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanUnderscore = function() { + var start = this.index; + + this.index += 1; + + return { + type: Token.Identifier, + value: "_", + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.createAssignmentExpression = function(operator, left, right, remain) { + var node = { + type: Syntax.AssignmentExpression, + operator: operator, + left: left, + right: right + }; + if (remain) { + node.remain = remain; + } + return node; + }; + + SCParser.prototype.createBinaryExpression = function(operator, left, right) { + var node = { + type: Syntax.BinaryExpression, + operator: operator.value, + left: left, + right: right + }; + if (operator.adverb) { + node.adverb = operator.adverb; + } + return node; + }; + + SCParser.prototype.createBlockExpression = function(body) { + return { + type: Syntax.BlockExpression, + body: body + }; + }; + + SCParser.prototype.createCallExpression = function(callee, args) { + return { + type: Syntax.CallExpression, + callee: callee, + args: args + }; + }; + + SCParser.prototype.createGlobalExpression = function(id) { + return { + type: Syntax.GlobalExpression, + id: id + }; + }; + + SCParser.prototype.createFunctionExpression = function(args, body, closed, partial, blocklist) { + var node; + + node = { + type: Syntax.FunctionExpression, + body: body + }; + if (args) { + node.args = args; + } + if (closed) { + node.closed = true; + } + if (partial) { + node.partial = true; + } + if (blocklist) { + node.blocklist = true; + } + return node; + }; + + SCParser.prototype.createIdentifier = function(name) { + return { + type: Syntax.Identifier, + name: name + }; + }; + + SCParser.prototype.createLabel = function(name) { + return { + type: Syntax.Label, + name: name + }; + }; + + SCParser.prototype.createListExpression = function(elements, immutable) { + var node = { + type: Syntax.ListExpression, + elements: elements + }; + if (immutable) { + node.immutable = !!immutable; + } + return node; + }; + + SCParser.prototype.createListIndexer = function(first, second, last) { + return { + type: Syntax.ListIndexer, + first: first, + second: second, + last: last + }; + }; + + SCParser.prototype.createLiteral = function(token) { + return { + type: Syntax.Literal, + value: token.value, + valueType: token.type + }; + }; + + SCParser.prototype.createLocationMarker = function() { + if (this.opts.loc || this.opts.range) { + this.skipComment(); + return new LocationMarker(this); + } + }; + + SCParser.prototype.createMemberExpression = function(accessor, object, property) { + return { + type: Syntax.MemberExpression, + computed: accessor === "[", + object: object, + property: property + }; + }; + + SCParser.prototype.createObjectExpression = function(elements) { + return { + type: Syntax.ObjectExpression, + elements: elements + }; + }; + + SCParser.prototype.createProgram = function(body) { + return { + type: Syntax.Program, + body: body + }; + }; + + SCParser.prototype.createRangeExpression = function(first, second, last, generator) { + var node = { + type: Syntax.RangeExpression, + first: first, + second: second, + last: last + }; + if (generator) { + node.generator = true; + } + return node; + }; + + SCParser.prototype.createThisExpression = function(name) { + return { + type: Syntax.ThisExpression, + name: name + }; + }; + + SCParser.prototype.createUnaryExpression = function(operator, arg) { + return { + type: Syntax.UnaryExpression, + operator: operator, + arg: arg + }; + }; + + SCParser.prototype.createVariableDeclaration = function(declarations, kind) { + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: kind + }; + }; + + SCParser.prototype.createVariableDeclarator = function(id, init) { + var node = { + type: Syntax.VariableDeclarator, + id: id + }; + if (init) { + node.init = init; + } + return node; + }; + + SCParser.prototype.isClassName = function(node) { + var name, ch; + + if (node.type === Syntax.Identifier) { + name = node.value || node.name; + ch = name.charAt(0); + return "A" <= ch && ch <= "Z"; + } + + return false; + }; + + SCParser.prototype.isKeyword = function(value) { + return !!Keywords[value] || false; + }; + + SCParser.prototype.isLeftHandSide = function(expr) { + switch (expr.type) { + case Syntax.Identifier: + case Syntax.MemberExpression: + case Syntax.GlobalExpression: + return true; + } + return false; + }; + + SCParser.prototype.match = function(value) { + var token = this.lookahead; + return token.type === Token.Punctuator && token.value === value; + }; + + SCParser.prototype.matchAny = function(list) { + var value, i, imax; + + if (this.lookahead.type === Token.Punctuator) { + value = this.lookahead.value; + for (i = 0, imax = list.length; i < imax; ++i) { + if (list[i] === value) { + return value; + } + } + } + + return null; + }; + + SCParser.prototype.matchKeyword = function(value) { + var token = this.lookahead; + return token.type === Token.Keyword && token.value === value; + }; + + SCParser.prototype.withScope = function(fn) { + var result; + + this.scope.begin(); + result = fn.call(this); + this.scope.end(); + + return result; + }; + + // 1. Program + SCParser.prototype.parseProgram = function() { + var node; + + this.skipComment(); + this.markStart(); + this.peek(); + + node = this.withScope(function() { + var body; + + body = this.parseFunctionBody(""); + if (body.length === 1 && body[0].type === Syntax.BlockExpression) { + body = body[0].body; + } + + return this.createProgram(body); + }); + + return this.markEnd(node); + }; + + // 2. Function + // 2.1 Function Expression + SCParser.prototype.parseFunctionExpression = function(closed, blocklist) { + var node; + + node = this.withScope(function() { + var args, body; + + if (this.match("|")) { + args = this.parseFunctionArgument("|"); + } else if (this.matchKeyword("arg")) { + args = this.parseFunctionArgument(";"); + } + body = this.parseFunctionBody("}"); + + return this.createFunctionExpression(args, body, closed, false, blocklist); + }); + + return node; + }; + + // 2.2 Function Argument + SCParser.prototype.parseFunctionArgument = function(expect) { + var args = { list: [] }, lookahead; + + this.lex(); + + if (!this.match("...")) { + do { + args.list.push(this.parseFunctionArgumentElement()); + if (!this.match(",")) { + break; + } + this.lex(); + } while (this.lookahead.type !== Token.EOF); + } + + if (this.match("...")) { + this.lex(); + lookahead = this.lookahead; + args.remain = this.parseVariableIdentifier(); + this.scope.add("arg", args.remain.name); + } + + this.expect(expect); + + return args; + }; + + SCParser.prototype.parseFunctionArgumentElement = function() { + var init = null, id; + + this.skipComment(); + this.markStart(); + id = this.parseVariableIdentifier(); + this.scope.add("arg", id.name); + + if (this.match("=")) { + this.lex(); + init = this.parseUnaryExpression(); + } + + return this.markEnd(this.createVariableDeclarator(id, init)); + }; + + // 2.3 Function Body + SCParser.prototype.parseFunctionBody = function(match) { + var elements = []; + + while (this.matchKeyword("var")) { + elements.push(this.parseVariableDeclaration()); + } + + while (this.lookahead.type !== Token.EOF && !this.match(match)) { + elements.push(this.parseExpression()); + if (this.lookahead.type !== Token.EOF && !this.match(match)) { + this.expect(";"); + } else { + break; + } + } + + return elements; + }; + + // 3. Variable Declarations + SCParser.prototype.parseVariableDeclaration = function() { + var declaration; + + this.skipComment(); + this.markStart(); + + this.lex(); // var + + declaration = this.markEnd( + this.createVariableDeclaration( + this.parseVariableDeclarationList(), "var" + ) + ); + + this.expect(";"); + + return declaration; + }; + + SCParser.prototype.parseVariableDeclarationList = function() { + var list = []; + + do { + list.push(this.parseVariableDeclarationElement()); + if (!this.match(",")) { + break; + } + this.lex(); + } while (this.lookahead.type !== Token.EOF); + + return list; + }; + + SCParser.prototype.parseVariableDeclarationElement = function() { + var init = null, id; + + this.skipComment(); + this.markStart(); + id = this.parseVariableIdentifier(); + this.scope.add("var", id.name); + + if (this.match("=")) { + this.lex(); + init = this.parseAssignmentExpression(); + } + + return this.markEnd(this.createVariableDeclarator(id, init)); + }; + + // 4. Expression + SCParser.prototype.parseExpression = function(node) { + return this.parseAssignmentExpression(node); + }; + + // 4.1 Expressions + SCParser.prototype.parseExpressions = function(node) { + var nodes = []; + + if (node) { + nodes.push(node); + this.lex(); + } + + while (this.lookahead.type !== Token.EOF && !this.matchAny([ ",", ")", "]", ".." ])) { + this.skipComment(); + this.markStart(); + node = this.parseAssignmentExpression(); + this.markEnd(node); + nodes.push(node); + if (this.match(";")) { + this.lex(); + } + } + + if (nodes.length === 0) { + this.throwUnexpected(this.lookahead); + } + + return nodes.length === 1 ? nodes[0] : nodes; + }; + + // 4.2 Assignment Expression + SCParser.prototype.parseAssignmentExpression = function(node) { + var token, left, right; + var sharp, destructuringAssignment; + var marker, saved; + + if (node) { + return this.parsePartialExpression(node); + } + + token = this.lookahead; + + this.skipComment(); + marker = this.createLocationMarker(); + this.markStart(); + + saved = this.save(); + + if (this.match("#")) { + sharp = true; + token = this.lex(); + if (this.matchAny([ "[", "{" ])) { + // this.revert(token); + this.restore(saved); + } else { + destructuringAssignment = true; + left = this.parseDestructuringAssignmentLeft(); + token = this.lookahead; + this.expect("="); + + right = this.parseAssignmentExpression(); + node = this.createAssignmentExpression( + token.value, left.list, right, left.remain + ); + } + } + + if (!destructuringAssignment) { + node = left = this.parsePartialExpression(); + + if (this.match("=")) { + if (!this.isLeftHandSide(left)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } + + token = this.lex(); + right = this.parseAssignmentExpression(); + node = this.createAssignmentExpression( + token.value, left, right + ); + } + } + + return this.markEnd(node); + }; + + SCParser.prototype.parseDestructuringAssignmentLeft = function() { + var params = { list: [] }, element; + + do { + element = this.parseLeftHandSideExpression(); + if (!this.isLeftHandSide(element)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } + params.list.push(element); + if (this.match(",")) { + this.lex(); + } else if (this.match("...")) { + this.lex(); + params.remain = this.parseLeftHandSideExpression(); + if (!this.isLeftHandSide(params.remain)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } + break; + } + } while (this.lookahead.type !== Token.EOF && !this.match("=")); + + return params; + }; + + // 4.3 Partial Expression + SCParser.prototype.parsePartialExpression = function(node) { + var underscore; + + if (this.state.innerElements) { + node = this.parseBinaryExpression(node); + } else { + underscore = this.state.underscore; + this.state.underscore = []; + + node = this.parseBinaryExpression(node); + + if (this.state.underscore.length) { + node = this.withScope(function() { + var args, i, imax; + + args = new Array(this.state.underscore.length); + for (i = 0, imax = args.length; i < imax; ++i) { + args[i] = this.state.underscore[i]; + this.scope.add("arg", this.state.underscore[i].name); + } + + return this.createFunctionExpression( + { list: args }, [ node ], false, true, false + ); + }); + } + + this.state.underscore = underscore; + } + + return node; + }; + + // 4.4 Conditional Expression + // 4.5 Binary Expression + SCParser.prototype.parseBinaryExpression = function(node) { + var marker, markers, expr, token, prec, stack; + var left, operator, right, i; + + this.skipComment(); + + marker = this.createLocationMarker(); + left = this.parseUnaryExpression(node); + + token = this.lookahead; + prec = this.binaryPrecedence(token); + if (prec === 0) { + if (node) { + return this.parseUnaryExpression(node); + } + return left; + } + this.lex(); + + token.prec = prec; + token.adverb = this.parseAdverb(); + + markers = [ marker, this.createLocationMarker() ]; + right = this.parseUnaryExpression(); + + stack = [ left, token, right ]; + + while ((prec = this.binaryPrecedence(this.lookahead)) > 0) { + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop(); + left = stack.pop(); + expr = this.createBinaryExpression(operator, left, right); + markers.pop(); + + marker = markers.pop(); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + stack.push(expr); + markers.push(marker); + } + + // Shift. + token = this.lex(); + token.prec = prec; + token.adverb = this.parseAdverb(); + + stack.push(token); + markers.push(this.createLocationMarker()); + expr = this.parseUnaryExpression(); + stack.push(expr); + } + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + markers.pop(); + while (i > 1) { + expr = this.createBinaryExpression(stack[i - 1], stack[i - 2], expr); + i -= 2; + marker = markers.pop(); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + } + + return expr; + }; + + SCParser.prototype.binaryPrecedence = function(token) { + var table, prec = 0; + + if (this.opts.binaryPrecedence) { + if (typeof this.opts.binaryPrecedence === "object") { + table = this.opts.binaryPrecedence; + } else { + table = binaryPrecedenceDefaults; + } + } else { + table = {}; + } + switch (token.type) { + case Token.Punctuator: + if (token.value !== "=") { + if (table.hasOwnProperty(token.value)) { + prec = table[token.value]; + } else if (/^[-+*\/%<=>!?&|@]+$/.test(token.value)) { + prec = 255; + } + } + break; + case Token.Label: + prec = 255; + break; + } + + return prec; + }; + + SCParser.prototype.parseAdverb = function() { + var adverb, lookahead; + + if (this.match(".")) { + this.lex(); + + lookahead = this.lookahead; + adverb = this.parsePrimaryExpression(); + + if (adverb.type === Syntax.Identifier || adverb.type === Syntax.Literal) { + return adverb; + } + + this.throwUnexpected(lookahead); + } + + return null; + }; + + // 4.6 Unary Expressions + SCParser.prototype.parseUnaryExpression = function(node) { + var token, expr; + + this.markStart(); + + if (this.match("`")) { + token = this.lex(); + expr = this.parseUnaryExpression(); + expr = this.createUnaryExpression(token.value, expr); + } else { + expr = this.parseLeftHandSideExpression(node); + } + + return this.markEnd(expr); + }; + + // 4.7 LeftHandSide Expressions + SCParser.prototype.parseLeftHandSideExpression = function(node) { + var marker, expr, args, m, prev, lookahead, closedFunction, disallowNotMember; + var disallowGenerator, blocklist; + + this.skipComment(); + + marker = this.createLocationMarker(); + disallowNotMember = this.state.disallowNotMember; + this.state.disallowNotMember = false; + expr = this.parsePrimaryExpression(node); + this.state.disallowNotMember = disallowNotMember; + + blocklist = false; + + while ((m = this.matchAny([ "(", "{", "#", "[", "." ])) !== null) { + lookahead = this.lookahead; + if ((prev === "{" && (m !== "#" && m !== "{")) || (prev === "(" && m === "(")) { + this.throwUnexpected(lookahead); + } + switch (m) { + case "(": + if (this.isClassName(expr)) { + expr = this.createMemberExpression( + ".", expr, this.markTouch(this.createIdentifier("new")) + ); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + } + node = this.parseCallArgument(); + expr = this.createCallExpression(expr, node); + break; + case "#": + closedFunction = this.state.closedFunction; + this.state.closedFunction = true; + this.lex(); + if (!this.match("{")) { + this.throwUnexpected(this.lookahead); + } + m = "{"; + /* falls through */ + case "{": + if (expr.type === Syntax.MemberExpression && !expr.computed) { + expr = this.createCallExpression(expr, { list: [] }); + } else if (expr.type === Syntax.Identifier) { + if (this.isClassName(expr)) { + expr = this.createMemberExpression( + ".", expr, this.markTouch(this.createIdentifier("new")) + ); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + } + expr = this.createCallExpression(expr, { list: [] }); + } else if (expr.type !== Syntax.CallExpression) { + this.throwUnexpected(lookahead); + } + lookahead = this.lookahead; + disallowGenerator = this.state.disallowGenerator; + this.state.disallowGenerator = true; + disallowNotMember = this.state.disallowNotMember; + this.state.disallowNotMember = true; + node = this.parseBraces(true); + this.state.disallowNotMember = disallowNotMember; + this.state.disallowGenerator = disallowGenerator; + this.state.closedFunction = closedFunction; + args = expr.args; + if (args && !args.expand && !args.keywords) { + args.list.push(node); + } else { + this.throwUnexpected(lookahead); + } + break; + case "[": + if (expr.type === Syntax.CallExpression) { + this.throwUnexpected(this.lookahead); + } + if (this.isClassName(expr)) { + expr = this.createMemberExpression( + ".", expr, this.markTouch(this.createIdentifier("newFrom")) + ); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + disallowNotMember = this.state.disallowNotMember; + this.state.disallowNotMember = true; + this.markStart(); + node = this.markEnd(this.parseLeftHandSideExpression()); + this.state.disallowNotMember = disallowNotMember; + expr = this.createCallExpression(expr, { list: [ node ] }); + } else { + node = this.parseListIndexer(); + expr = this.createMemberExpression("[", expr, node); + } + break; + case ".": + this.lex(); + if (this.match("(")) { + expr = this.createMemberExpression( + ".", expr, this.markTouch(this.createIdentifier("value")) + ); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + node = this.parseCallArgument(); + expr = this.createCallExpression(expr, node); + } else if (this.match("[")) { + node = this.parseListIndexer(); + expr = this.createMemberExpression("[", expr, node); + } else { + node = this.parseProperty(); + expr = this.createMemberExpression(".", expr, node); + } + break; + } + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + prev = m; + } + + return expr; + }; + + SCParser.prototype.parseCallArgument = function() { + var args, node, key, value, hasKeyword, lookahead; + + args = { list: [] }; + hasKeyword = false; + + this.expect("("); + + while (this.lookahead.type !== Token.EOF && !this.match(")")) { + lookahead = this.lookahead; + if (!hasKeyword) { + if (this.match("*")) { + this.lex(); + args.expand = this.parseExpressions(); + hasKeyword = true; + } else if (lookahead.type === Token.Label) { + key = this.lex().value; + value = this.parseExpressions(); + args.keywords = {}; + args.keywords[key] = value; + hasKeyword = true; + } else { + node = this.parseExpressions(); + args.list.push(node); + } + } else { + if (lookahead.type !== Token.Label) { + this.throwUnexpected(lookahead); + } + key = this.lex().value; + value = this.parseExpressions(); + if (!args.keywords) { + args.keywords = {}; + } + args.keywords[key] = value; + } + if (this.match(")")) { + break; + } + this.expect(","); + } + + this.expect(")"); + + return args; + }; + + SCParser.prototype.parseListIndexer = function() { + var first = null, second = null, last = null; + var node = null; + + this.expect("["); + + if (!this.match("]")) { + this.markStart(); + + if (this.match("..")) { + // [..A] + this.lex(); + if (!this.match("]")) { + last = this.parseExpressions(); + node = this.markEnd(this.createListIndexer(null, null, last)); + } else { + node = this.markEnd(this.createListIndexer(null, null, null)); + } + } else { + if (!this.match(",")) { + first = this.parseExpressions(); + } else { + this.throwUnexpected(this.lookahead); + } + if (this.match("..")) { + this.lex(); + if (!this.match("]")) { + // [A..B] + last = this.parseExpressions(); + } + node = this.markEnd(this.createListIndexer(first, null, last)); + } else if (this.match(",")) { + this.lex(); + second = this.parseExpressions(); + if (this.match("..")) { + // [A, B..C] + this.lex(); + if (!this.match("]")) { + last = this.parseExpressions(); + } + } else { + this.throwUnexpected(this.lookahead); + } + node = this.markEnd(this.createListIndexer(first, second, last)); + } else { + // [A] + node = this.markEnd(first); + } + } + } + + this.expect("]"); + + if (node === null) { + this.throwUnexpected({ value: "]" }); + } + + return node; + }; + + SCParser.prototype.parseProperty = function() { + var token; + + this.skipComment(); + this.markStart(); + token = this.lex(); + + if (token.type !== Token.Identifier || this.isClassName(token)) { + this.throwUnexpected(token); + } + + return this.markEnd(this.createIdentifier(token.value)); + }; + + // 4.8 Primary Expressions + SCParser.prototype.parsePrimaryExpression = function(node) { + var expr, token, lookahead, closedFunction, disallowGenerator; + + if (node) { + return node; + } + + this.skipComment(); + this.markStart(); + + if (this.match("~")) { + this.lex(); + expr = this.createGlobalExpression(this.parseIdentifier()); + } else { + lookahead = this.lookahead; + + switch (this.matchAny([ "(", "{", "[", "#" ]) || this.lookahead.type) { + case "(": + expr = this.parseParentheses(); + break; + case "{": + expr = this.parseBraces(); + break; + case "[": + expr = this.parseListInitialiser(); + break; + case "#": + this.lex(); + switch (this.matchAny([ "[", "{" ])) { + case "[": + if (this.state.immutableList) { + this.throwUnexpected(lookahead); + } + this.state.immutableList = true; + expr = this.parseListInitialiser(); + this.state.immutableList = false; + break; + case "{": + disallowGenerator = this.state.disallowGenerator; + this.state.disallowGenerator = true; + closedFunction = this.state.closedFunction; + this.state.closedFunction = true; + expr = this.parseBraces(); + this.state.closedFunction = closedFunction; + this.state.disallowGenerator = disallowGenerator; + break; + default: + expr = {}; + this.throwUnexpected(this.lookahead); + break; + } + break; + case Token.Keyword: + if (Keywords[this.lookahead.value] === "keyword") { + this.throwUnexpected(this.lookahead); + } + expr = this.createThisExpression(this.lex().value); + break; + case Token.Identifier: + lookahead = this.lookahead; + expr = this.parseIdentifier(); + if (expr.name === "_") { + expr.name += this.state.underscore.length.toString(); + this.state.underscore.push(expr); + } + break; + case Token.BooleanLiteral: + case Token.CharLiteral: + case Token.FloatLiteral: + case Token.IntegerLiteral: + case Token.NilLiteral: + case Token.SymbolLiteral: + expr = this.createLiteral(this.lex()); + break; + case Token.StringLiteral: + token = this.lex(); + if (token.value.charAt(0) === '"' && token.value.indexOf("#{") !== -1) { + expr = this.parseInterpolatedString(token); + } else { + expr = this.createLiteral(token); + } + break; + } + } + + if (!expr) { + expr = {}; + this.throwUnexpected(this.lex()); + } + + return this.markEnd(expr); + }; + + SCParser.prototype.parseInterpolatedString = function(token) { + var value, len, items; + var i, j, ch, depth, code, parser; + + value = token.value.substr(1, token.value.length - 2); + len = value.length; + items = []; + + i = 0; + + do { + j = i; + LOOP1: while (j < len) { + ch = value.charAt(j); + switch (ch) { + case "#": + if (value.charAt(j + 1) === "{") { + break LOOP1; + } + break; + case "\\": + j += 1; + break; + } + j += 1; + } + + if (j >= len) { + break; + } + code = value.substr(i, j - i); + if (code) { + items.push(q(code)); + } + i = j + 2; + j = i; + depth = 0; + LOOP2: while (j < len) { + ch = value.charAt(j); + switch (ch) { + case "}": + if (depth === 0) { + code = value.substr(i, j - i); + if (code) { + items.push("(" + code + ").asString"); + } + break LOOP2; + } + depth -= 1; + break; + case "{": + depth += 1; + break; + } + j += 1; + } + i = j + 1; + } while (i < len); + + if (i < len) { + items.push(q(value.substr(i))); + } + + code = items.join("++"); + parser = new SCParser(code, {}); + parser.peek(); + + return parser.parseExpression(); + }; + + // ( ... ) + SCParser.prototype.parseParentheses = function() { + var marker, node, expr, generator; + + this.skipComment(); + + marker = this.createLocationMarker(); + this.expect("("); + + if (this.match(":")) { + this.lex(); + generator = true; + } + + if (this.lookahead.type === Token.Label) { + expr = this.parseObjectInitialiser(); + } else if (this.matchKeyword("var")) { + expr = this.withScope(function() { + var body; + body = this.parseFunctionBody(")"); + return this.createBlockExpression(body); + }); + } else if (this.match("..")) { + expr = this.parseRangeInitialiser(null, generator); + } else if (this.match(")")) { + expr = this.createObjectExpression([]); + } else { + node = this.parseExpression(); + if (this.matchAny([ ",", ".." ])) { + expr = this.parseRangeInitialiser(node, generator); + } else if (this.match(":")) { + expr = this.parseObjectInitialiser(node); + } else if (this.match(";")) { + expr = this.parseExpressions(node); + if (this.matchAny([ ",", ".." ])) { + expr = this.parseRangeInitialiser(expr, generator); + } + marker = null; + } else { + expr = this.parseExpression(node); + marker = null; + } + } + + this.expect(")"); + + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + + return expr; + }; + + SCParser.prototype.parseObjectInitialiser = function(node) { + var elements = [], innerElements; + + innerElements = this.state.innerElements; + this.state.innerElements = true; + + if (node) { + this.expect(":"); + } else { + node = this.parseLabel(); + } + elements.push(node, this.parseExpression()); + + if (this.match(",")) { + this.lex(); + } + + while (this.lookahead.type !== Token.EOF && !this.match(")")) { + if (this.lookahead.type === Token.Label) { + node = this.parseLabel(); + } else { + node = this.parseExpression(); + } + elements.push(node); + if (node.type !== Syntax.Label) { + this.expect(":"); + } + elements.push(this.parseExpression()); + if (!this.match(")")) { + this.expect(","); + } + } + + this.state.innerElements = innerElements; + + return this.createObjectExpression(elements); + }; + + SCParser.prototype.parseRangeInitialiser = function(node, generator) { + var first = null, second = null, last = null; + var innerElements; + + innerElements = this.state.innerElements; + this.state.innerElements = true; + + if (node === null) { + // (..last) + this.expect(".."); + if (this.match(")")) { + this.throwUnexpected(this.lookahead); + } + last = this.parseExpressions(); + } else { + first = node; + if (this.match(",")) { + // (first, second .. last) + this.lex(); + second = this.parseExpressions(); + if (Array.isArray(second) && second.length === 0) { + this.throwUnexpected(this.lookahead); + } + this.expect(".."); + if (!this.match(")")) { + last = this.parseExpressions(); + } else if (!generator) { + this.throwUnexpected(this.lookahead); + } + } else { + // (first..last) + this.lex(); + if (!this.match(")")) { + last = this.parseExpressions(); + } else if (!generator) { + this.throwUnexpected(this.lookahead); + } + } + } + + this.state.innerElements = innerElements; + + return this.createRangeExpression(first, second, last, generator); + }; + + SCParser.prototype.parseListInitialiser = function() { + var elements, innerElements; + + elements = []; + + innerElements = this.state.innerElements; + this.state.innerElements = true; + + this.expect("["); + + while (this.lookahead.type !== Token.EOF && !this.match("]")) { + if (this.lookahead.type === Token.Label) { + elements.push(this.parseLabel()); + elements.push(this.parseExpression()); + } else { + elements.push(this.parseExpression()); + if (this.match(":")) { + this.lex(); + elements.push(this.parseExpression()); + } + } + if (!this.match("]")) { + this.expect(","); + } + } + + this.expect("]"); + + this.state.innerElements = innerElements; + + return this.createListExpression(elements, this.state.immutableList); + }; + + // { ... } + SCParser.prototype.parseBraces = function(blocklist) { + var expr; + + this.skipComment(); + this.markStart(); + + this.expect("{"); + + if (this.match(":")) { + if (!this.state.disallowGenerator) { + this.lex(); + expr = this.parseGeneratorInitialiser(); + } else { + expr = {}; + this.throwUnexpected(this.lookahead); + } + } else { + expr = this.parseFunctionExpression(this.state.closedFunction, blocklist); + } + + this.expect("}"); + + return this.markEnd(expr); + }; + + SCParser.prototype.parseGeneratorInitialiser = function() { + this.throwError({}, Message.NotImplemented, "generator literal"); + + this.parseExpression(); + this.expect(","); + + while (this.lookahead.type !== Token.EOF && !this.match("}")) { + this.parseExpression(); + if (!this.match("}")) { + this.expect(","); + } + } + + return this.createLiteral({ value: "null", valueType: Token.NilLiteral }); + }; + + SCParser.prototype.parseLabel = function() { + this.skipComment(); + this.markStart(); + return this.markEnd(this.createLabel(this.lex().value)); + }; + + SCParser.prototype.parseIdentifier = function() { + var expr; + + this.skipComment(); + this.markStart(); + + if (this.lookahead.type !== Syntax.Identifier) { + this.throwUnexpected(this.lookahead); + } + + expr = this.lex(); + + return this.markEnd(this.createIdentifier(expr.value)); + }; + + SCParser.prototype.parseVariableIdentifier = function() { + var token, value, ch; + + this.skipComment(); + this.markStart(); + + token = this.lex(); + value = token.value; + + if (token.type !== Token.Identifier) { + this.throwUnexpected(token); + } else { + ch = value.charAt(0); + if (("A" <= ch && ch <= "Z") || ch === "_") { + this.throwUnexpected(token); + } + } + + return this.markEnd(this.createIdentifier(value)); + }; + + SCParser.prototype.markStart = function() { + /* istanbul ignore else */ + if (this.opts.loc) { + this.marker.push( + this.index - this.lineStart, + this.lineNumber + ); + } + /* istanbul ignore else */ + if (this.opts.range) { + this.marker.push( + this.index + ); + } + }; + + SCParser.prototype.markEnd = function(node) { + if (Array.isArray(node) || node.range || node.loc) { + /* istanbul ignore else */ + if (this.opts.range) { + this.marker.pop(); + } + /* istanbul ignore else */ + if (this.opts.loc) { + this.marker.pop(); + this.marker.pop(); + } + } else { + /* istanbul ignore else */ + if (this.opts.range) { + node.range = [ this.marker.pop(), this.index ]; + } + /* istanbul ignore else */ + if (this.opts.loc) { + node.loc = { + start: { + line: this.marker.pop(), + column: this.marker.pop() + }, + end: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; + } + } + return node; + }; + + SCParser.prototype.markTouch = function(node) { + /* istanbul ignore else */ + if (this.opts.range) { + node.range = [ this.index, this.index ]; + } + /* istanbul ignore else */ + if (this.opts.loc) { + node.loc = { + start: { + line: this.lineNumber, + column: this.index - this.lineStart + }, + end: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; + } + return node; + }; + + SCParser.prototype.throwError = function(token, messageFormat) { + var args, message; + var error, index, lineNumber, column; + var prev; + + args = Array.prototype.slice.call(arguments, 2); + message = messageFormat.replace(/%(\d)/g, function(whole, index) { + return args[index]; + }); + + if (typeof token.lineNumber === "number") { + index = token.range[0]; + lineNumber = token.lineNumber; + column = token.range[0] - token.lineStart + 1; + } else { + index = this.index; + lineNumber = this.lineNumber; + column = this.index - this.lineStart + 1; + } + + error = new Error("Line " + lineNumber + ": " + message); + error.index = index; + error.lineNumber = lineNumber; + error.column = column; + error.description = message; + + if (this.errors) { + prev = this.errors[this.errors.length - 1]; + if (!(prev && error.index === prev.index)) { + this.errors.push(error); + } + } else { + throw error; + } + }; + + SCParser.prototype.throwUnexpected = function(token) { + switch (token.type) { + case Token.EOF: + this.throwError(token, Message.UnexpectedEOS); + break; + case Token.FloatLiteral: + case Token.IntegerLiteral: + this.throwError(token, Message.UnexpectedNumber); + break; + case Token.CharLiteral: + this.throwError(token, Message.UnexpectedChar); + break; + case Token.StringLiteral: + this.throwError(token, Message.UnexpectedString); + break; + case Token.SymbolLiteral: + this.throwError(token, Message.UnexpectedSymbol); + break; + case Token.Identifier: + this.throwError(token, Message.UnexpectedIdentifier); + break; + default: + this.throwError(token, Message.UnexpectedToken, token.value); + break; + } + }; + + parser.parse = function(source, opts) { + var instance, ast; + + opts = opts || /* istanbul ignore next */ {}; + + instance = new SCParser(source, opts); + ast = instance.parse(); + + if (!!opts.tokens && typeof instance.tokens !== "undefined") { + ast.tokens = instance.tokens; + } + if (!!opts.tolerant && typeof instance.errors !== "undefined") { + ast.errors = instance.errors; + } + + return ast; + }; + + sc.lang.parser = parser; + + var SCScript = sc.SCScript; + + SCScript.tokenize = function(source, opts) { + opts = opts || /* istanbul ignore next */ {}; + opts.tokens = true; + return parser.parse(source, opts).tokens || /* istanbul ignore next */ []; + }; + + SCScript.parse = parser.parse; + +})(sc); + })(this.self||global); diff --git a/package.json b/package.json index 025d3f4..df7ba39 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scscript", - "version": "0.0.10", + "version": "0.0.11", "author": "Nao Yonamine ", "homepage": "http://mohayonao.github.io/SCScript/", "bugs": "https://github.com/mohayonao/SCScript/issues", diff --git a/src/sc/lang/installer.js b/src/sc/lang/installer.js index 80f1a1f..58519c3 100644 --- a/src/sc/lang/installer.js +++ b/src/sc/lang/installer.js @@ -1 +1,2 @@ +require("./parser"); require("./classlib/installer"); diff --git a/src/sc/lang/parser.js b/src/sc/lang/parser.js new file mode 100644 index 0000000..b0d8454 --- /dev/null +++ b/src/sc/lang/parser.js @@ -0,0 +1,2325 @@ +(function(sc) { + "use strict"; + + require("./sc"); + + var parser = {}; + + var Token = parser.Token = { + BooleanLiteral: "Boolean", + CharLiteral: "Char", + EOF: "", + FloatLiteral: "Float", + Identifier: "Identifier", + IntegerLiteral: "Integer", + Keyword: "Keyword", + Label: "Label", + NilLiteral: "Nil", + Punctuator: "Punctuator", + StringLiteral: "String", + SymbolLiteral: "Symbol" + }; + + var Syntax = parser.Syntax = { + AssignmentExpression: "AssignmentExpression", + BinaryExpression: "BinaryExpression", + BlockExpression: "BlockExpression", + CallExpression: "CallExpression", + FunctionExpression: "FunctionExpression", + GlobalExpression: "GlobalExpression", + Identifier: "Identifier", + ListExpression: "ListExpression", + ListIndexer: "ListIndexer", + Label: "Label", + Literal: "Literal", + MemberExpression: "MemberExpression", + ObjectExpression: "ObjectExpression", + Program: "Program", + RangeExpression: "RangeExpression", + ThisExpression: "ThisExpression", + UnaryExpression: "UnaryExpression", + VariableDeclaration: "VariableDeclaration", + VariableDeclarator: "VariableDeclarator" + }; + + var Message = parser.Message = { + ArgumentAlreadyDeclared: "argument '%0' already declared", + InvalidLHSInAssignment: "invalid left-hand side in assignment", + NotImplemented: "not implemented %0", + UnexpectedEOS: "unexpected end of input", + UnexpectedIdentifier: "unexpected identifier", + UnexpectedChar: "unexpected char", + UnexpectedLabel: "unexpected label", + UnexpectedNumber: "unexpected number", + UnexpectedString: "unexpected string", + UnexpectedSymbol: "unexpected symbol", + UnexpectedToken: "unexpected token %0", + VariableAlreadyDeclared: "variable '%0' already declared", + VariableNotDefined: "variable '%0' not defined" + }; + + var Keywords = parser.Keywords = { + var: "keyword", + arg: "keyword", + const: "keyword", + this: "function", + thisThread: "function", + thisProcess: "function", + thisFunction: "function", + thisFunctionDef: "function", + }; + + var binaryPrecedenceDefaults = { + "?" : 1, + "??" : 1, + "!?" : 1, + "->" : 2, + "||" : 3, + "&&" : 4, + "|" : 5, + "&" : 6, + "==" : 7, + "!=" : 7, + "===": 7, + "!==": 7, + "<" : 8, + ">" : 8, + "<=" : 8, + ">=" : 8, + "<<" : 9, + ">>" : 9, + "+>>": 9, + "+" : 10, + "-" : 10, + "*" : 11, + "/" : 11, + "%" : 11, + "!" : 12, + }; + + function q(str) { + return "'" + str + "'"; + } + + function char2num(ch) { + var n = ch.charCodeAt(0); + + if (48 <= n && n <= 57) { + return n - 48; + } + if (65 <= n && n <= 90) { + return n - 55; + } + return n - 87; // if (97 <= n && n <= 122) + } + + function isNumber(ch) { + return "0" <= ch && ch <= "9"; + } + + function Scope(parser) { + this.parser = parser; + this.stack = []; + } + + Scope.prototype.add = function(type, id) { + var peek = this.stack[this.stack.length - 1]; + var vars, args, declared; + + vars = peek.vars; + args = peek.args; + declared = peek.declared; + + switch (type) { + case "var": + if (args[id] || vars[id]) { + this.parser.throwError({}, Message.VariableAlreadyDeclared, id); + } else { + vars[id] = true; + delete declared[id]; + } + break; + case "arg": + if (args[id]) { + this.parser.throwError({}, Message.ArgumentAlreadyDeclared, id); + } + args[id] = true; + delete declared[id]; + break; + } + }; + + Scope.prototype.begin = function() { + var peek = this.stack[this.stack.length - 1]; + var declared = {}; + + if (peek) { + Array.prototype.concat.apply([], [ + peek.declared, peek.args, peek.vars + ].map(Object.keys)).forEach(function(key) { + declared[key] = true; + }); + } + + this.stack.push({ vars: {}, args: {}, declared: declared }); + }; + + Scope.prototype.end = function() { + this.stack.pop(); + }; + + function LocationMarker(parser) { + this.parser = parser; + this.marker = [ + parser.index, + parser.lineNumber, + parser.index - parser.lineStart + ]; + } + + LocationMarker.prototype.apply = function(node) { + var parser = this.parser; + var marker = this.marker; + + /* istanbul ignore else */ + if (this.parser.opts.range) { + node.range = [ marker[0], parser.index ]; + } + /* istanbul ignore else */ + if (this.parser.opts.loc) { + node.loc = { + start: { + line: marker[1], + column: marker[2] + }, + end: { + line: parser.lineNumber, + column: parser.index - parser.lineStart + } + }; + } + }; + + function SCParser(source, opts) { + /* istanbul ignore next */ + if (typeof source !== "string") { + if (typeof source === "undefined") { + source = ""; + } + source = String(source); + } + source = source.replace(/\r\n?/g, "\n"); + this.source = source; + this.opts = opts; + this.length = source.length; + this.index = 0; + this.lineNumber = this.length ? 1 : 0; + this.lineStart = 0; + this.reverted = null; + this.scope = new Scope(this); + this.marker = []; + this.tokens = opts.tokens ? [] : null; + this.errors = opts.tolerant ? [] : null; + this.state = { + closedFunction: false, + disallowNotMember: false, + disallowGenerator: false, + innerElements: false, + immutableList: false, + underscore: [] + }; + } + + SCParser.prototype.parse = function() { + return this.parseProgram(); + }; + + SCParser.prototype.skipComment = function() { + var source = this.source; + var length = this.length; + var index = this.index; + var lineNumber = this.lineNumber; + var lineStart = this.lineStart; + var ch, depth; + + LOOP: while (index < length) { + ch = source.charAt(index); + switch (ch) { + + case " ": + case "\t": + index += 1; + continue LOOP; + /* falls through */ + + case "\n": + index += 1; + lineNumber += 1; + lineStart = index; + continue LOOP; + /* falls through */ + + case "/": + ch = source.charAt(index + 1); + switch (ch) { + case "/": + // line comment + index += 2; + while (index < length) { + ch = source.charAt(index); + index += 1; + if (ch === "\n") { + lineNumber += 1; + lineStart = index; + break; + } + } + break; + + case "*": + // block comment + depth = 1; + index += 2; + while (index < length) { + ch = source.charAt(index); + switch (ch) { + case "/": + ch = source.charAt(index + 1); + if (ch === "*") { + depth += 1; + index += 1; + } + break; + case "*": + ch = source.charAt(index + 1); + if (ch === "/") { + depth -= 1; + index += 1; + if (depth === 0) { + index += 1; + continue LOOP; + } + } + break; + case "\n": + lineNumber += 1; + lineStart = index; + break; + } + index += 1; + } + this.throwError({}, Message.UnexpectedToken, "ILLEGAL"); + break; + + default: + break LOOP; + } + break; + + default: + break LOOP; + } + } + + this.index = index; + this.lineNumber = lineNumber; + this.lineStart = lineStart; + }; + + SCParser.prototype.collectToken = function() { + var loc, token, source, t; + + this.skipComment(); + + loc = { + start: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; + + token = this.advance(); + + loc.end = { + line: this.lineNumber, + column: this.index - this.lineStart + }; + + if (token.type !== Token.EOF) { + source = this.source; + t = { + type: token.type, + value: source.slice(token.range[0], token.range[1]) + }; + if (this.opts.range) { + t.range = [ token.range[0], token.range[1] ]; + } + if (this.opts.loc) { + t.loc = loc; + } + this.tokens.push(t); + } + + return token; + }; + + SCParser.prototype.advance = function() { + var ch, token; + + this.skipComment(); + + if (this.length <= this.index) { + return this.EOFToken(); + } + + ch = this.source.charAt(this.index); + + // Symbol literal starts with back slash + if (ch === "\\") { + return this.scanSymbolLiteral(); + } + + // Char literal starts with dollar + if (ch === "$") { + return this.scanCharLiteral(); + } + + // String literal starts with single quote or double quote + if (ch === "'" || ch === "\"") { + return this.scanStringLiteral(); + } + + // for partial application + if (ch === "_") { + return this.scanUnderscore(); + } + + if (ch === "-") { + token = this.scanNegativeNumericLiteral(); + if (token) { + return token; + } + } + + // Identifier starts with alphabet + if (("A" <= ch && ch <= "Z") || ("a" <= ch && ch <= "z")) { + return this.scanIdentifier(); + } + + // Number literal starts with number + if (isNumber(ch)) { + return this.scanNumericLiteral(); + } + + return this.scanPunctuator(); + }; + + SCParser.prototype.expect = function(value) { + var token = this.lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + this.throwUnexpected(token, value); + } + }; + + SCParser.prototype.peek = function() { + var index, lineNumber, lineStart; + + index = this.index; + lineNumber = this.lineNumber; + lineStart = this.lineStart; + + if (this.opts.tokens) { + this.lookahead = this.collectToken(); + } else { + this.lookahead = this.advance(); + } + + this.index = index; + this.lineNumber = lineNumber; + this.lineStart = lineStart; + }; + + SCParser.prototype.lex = function() { + var token = this.lookahead; + + this.index = token.range[1]; + this.lineNumber = token.lineNumber; + this.lineStart = token.lineStart; + + if (this.opts.tokens) { + this.lookahead = this.collectToken(); + } else { + this.lookahead = this.advance(); + } + + this.index = token.range[1]; + this.lineNumber = token.lineNumber; + this.lineStart = token.lineStart; + + return token; + }; + + SCParser.prototype.EOFToken = function() { + return { + type: Token.EOF, + value: "", + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ this.index, this.index ] + }; + }; + + SCParser.prototype.restore = function(saved) { + this.lookahead = saved[0]; + this.index = saved[1]; + this.lineNumber = saved[2]; + this.lineStart = saved[3]; + if (this.tokens) { + this.tokens.pop(); + } + }; + + SCParser.prototype.save = function() { + return [ this.lookahead, this.index, this.lineNumber, this.lineStart ]; + }; + + SCParser.prototype.scanCharLiteral = function() { + var start, value; + + start = this.index; + value = this.source.charAt(this.index + 1); + + this.index += 2; + + return { + type : Token.CharLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanIdentifier = function() { + var source = this.source.slice(this.index); + var start = this.index; + var value, type; + + value = /^[a-zA-Z][a-zA-Z0-9_]*/.exec(source)[0]; + + this.index += value.length; + + if (this.source.charAt(this.index) === ":") { + this.index += 1; + return { + type: Token.Label, + value: value, + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] + }; + } else if (this.isKeyword(value)) { + type = Token.Keyword; + } else { + switch (value) { + case "inf": + type = Token.FloatLiteral; + value = "Infinity"; + break; + case "pi": + type = Token.FloatLiteral; + value = "Math.PI"; + break; + case "nil": + type = Token.NilLiteral; + value = "null"; + break; + case "true": + case "false": + type = Token.BooleanLiteral; + break; + default: + type = Token.Identifier; + break; + } + } + + return { + type: type, + value: value, + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanNumericLiteral = function(neg) { + return this.scanNAryNumberLiteral(neg) || this.scanDecimalNumberLiteral(neg); + }; + + SCParser.prototype.scanNegativeNumericLiteral = function() { + var token, ch1, ch2, ch3; + var start, value = null; + + start = this.index; + ch1 = this.source.charAt(this.index + 1); + + if (isNumber(ch1)) { + this.index += 1; + token = this.scanNumericLiteral(true); + token.range[0] = start; + return token; + } + + ch2 = this.source.charAt(this.index + 2); + ch3 = this.source.charAt(this.index + 3); + + if (ch1 + ch2 === "pi") { + this.index += 3; + value = -Math.PI; + } else if (ch1 + ch2 + ch3 === "inf") { + this.index += 4; + value = -Infinity; + } + + if (value !== null) { + return { + type : Token.FloatLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + } + + return null; + }; + + SCParser.prototype.scanNAryNumberLiteral = function(neg) { + var re, start, items; + var base, integer, frac, pi; + var x, i, imax; + var value, type; + + re = /^(\d+)r((?:[\da-zA-Z](?:_(?=[\da-zA-Z]))?)+)(?:\.((?:[\da-zA-Z](?:_(?=[\da-zA-Z]))?)+))?/; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + if (!items) { + return; + } + + base = items[1].replace(/^0+(?=\d)/g, "")|0; + integer = items[2].replace(/(^0+(?=\d)|_)/g, ""); + frac = items[3] && items[3].replace(/_/g, ""); + + if (!frac && base < 26 && integer.substr(-2) === "pi") { + integer = integer.substr(0, integer.length - 2); + pi = true; + } + + type = Token.IntegerLiteral; + value = 0; + + for (i = 0, imax = integer.length; i < imax; ++i) { + value *= base; + x = char2num(integer[i]); + if (x >= base) { + this.throwError({}, Message.UnexpectedToken, integer[i]); + } + value += x; + } + + if (frac) { + type = Token.FloatLiteral; + for (i = 0, imax = frac.length; i < imax; ++i) { + x = char2num(frac[i]); + if (x >= base) { + this.throwError({}, Message.UnexpectedToken, integer[i]); + } + value += x * Math.pow(base, -(i + 1)); + } + } + + if (neg) { + value *= -1; + } + + if (pi) { + type = Token.FloatLiteral; + value = "(" + value + " * Math.PI)"; + } + + this.index += items[0].length; + + return { + type : type, + value: String(value), + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanDecimalNumberLiteral = function(neg) { + var re, start, items, integer, frac, pi; + var value, type; + + re = /^((?:\d(?:_(?=\d))?)+((?:\.(?:\d(?:_(?=\d))?)+)?(?:e[-+]?(?:\d(?:_(?=\d))?)+)?))(pi)?/; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + integer = items[1]; + frac = items[2]; + pi = items[3]; + + type = (frac || pi) ? Token.FloatLiteral : Token.IntegerLiteral; + value = +integer.replace(/(^0+(?=\d)|_)/g, ""); + + if (neg) { + value *= -1; + } + + if (pi) { + value = "(" + value + " * Math.PI)"; + } + + this.index += items[0].length; + + return { + type : type, + value: String(value), + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanPunctuator = function() { + var re, start, items; + + re = /^(\.{1,3}|[(){}[\]:;,~#`]|[-+*\/%<=>!?&|@]+)/; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + if (items) { + this.index += items[0].length; + return { + type : Token.Punctuator, + value: items[0], + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + } + + this.throwError({}, Message.UnexpectedToken, this.source.charAt(this.index)); + + this.index = this.length; + + return this.EOFToken(); + }; + + SCParser.prototype.scanStringLiteral = function() { + var source, start; + var length, index; + var quote, ch, value, type; + + source = this.source; + length = this.length; + index = start = this.index; + quote = source.charAt(start); + type = (quote === '"') ? Token.StringLiteral : Token.SymbolLiteral; + + index += 1; + while (index < length) { + ch = source.charAt(index); + index += 1; + if (ch === quote) { + value = source.substr(start, index - start); + value = value.replace(/\n/g, "\\n"); + this.index = index; + return { + type : type, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + } else if (ch === "\n") { + this.lineNumber += 1; + this.lineStart = index; + } else if (ch === "\\") { + index += 1; + } + } + + this.index = index; + this.throwError({}, Message.UnexpectedToken, "ILLEGAL"); + + return this.EOFToken(); + }; + + SCParser.prototype.scanSymbolLiteral = function() { + var re, start, items; + var value; + + re = /^\\([a-z_]\w*)?/i; + start = this.index; + items = re.exec(this.source.slice(this.index)); + + value = items[1]; + + this.index += items[0].length; + + return { + type : Token.SymbolLiteral, + value: value, + lineNumber: this.lineNumber, + lineStart : this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.scanUnderscore = function() { + var start = this.index; + + this.index += 1; + + return { + type: Token.Identifier, + value: "_", + lineNumber: this.lineNumber, + lineStart: this.lineStart, + range: [ start, this.index ] + }; + }; + + SCParser.prototype.createAssignmentExpression = function(operator, left, right, remain) { + var node = { + type: Syntax.AssignmentExpression, + operator: operator, + left: left, + right: right + }; + if (remain) { + node.remain = remain; + } + return node; + }; + + SCParser.prototype.createBinaryExpression = function(operator, left, right) { + var node = { + type: Syntax.BinaryExpression, + operator: operator.value, + left: left, + right: right + }; + if (operator.adverb) { + node.adverb = operator.adverb; + } + return node; + }; + + SCParser.prototype.createBlockExpression = function(body) { + return { + type: Syntax.BlockExpression, + body: body + }; + }; + + SCParser.prototype.createCallExpression = function(callee, args) { + return { + type: Syntax.CallExpression, + callee: callee, + args: args + }; + }; + + SCParser.prototype.createGlobalExpression = function(id) { + return { + type: Syntax.GlobalExpression, + id: id + }; + }; + + SCParser.prototype.createFunctionExpression = function(args, body, closed, partial, blocklist) { + var node; + + node = { + type: Syntax.FunctionExpression, + body: body + }; + if (args) { + node.args = args; + } + if (closed) { + node.closed = true; + } + if (partial) { + node.partial = true; + } + if (blocklist) { + node.blocklist = true; + } + return node; + }; + + SCParser.prototype.createIdentifier = function(name) { + return { + type: Syntax.Identifier, + name: name + }; + }; + + SCParser.prototype.createLabel = function(name) { + return { + type: Syntax.Label, + name: name + }; + }; + + SCParser.prototype.createListExpression = function(elements, immutable) { + var node = { + type: Syntax.ListExpression, + elements: elements + }; + if (immutable) { + node.immutable = !!immutable; + } + return node; + }; + + SCParser.prototype.createListIndexer = function(first, second, last) { + return { + type: Syntax.ListIndexer, + first: first, + second: second, + last: last + }; + }; + + SCParser.prototype.createLiteral = function(token) { + return { + type: Syntax.Literal, + value: token.value, + valueType: token.type + }; + }; + + SCParser.prototype.createLocationMarker = function() { + if (this.opts.loc || this.opts.range) { + this.skipComment(); + return new LocationMarker(this); + } + }; + + SCParser.prototype.createMemberExpression = function(accessor, object, property) { + return { + type: Syntax.MemberExpression, + computed: accessor === "[", + object: object, + property: property + }; + }; + + SCParser.prototype.createObjectExpression = function(elements) { + return { + type: Syntax.ObjectExpression, + elements: elements + }; + }; + + SCParser.prototype.createProgram = function(body) { + return { + type: Syntax.Program, + body: body + }; + }; + + SCParser.prototype.createRangeExpression = function(first, second, last, generator) { + var node = { + type: Syntax.RangeExpression, + first: first, + second: second, + last: last + }; + if (generator) { + node.generator = true; + } + return node; + }; + + SCParser.prototype.createThisExpression = function(name) { + return { + type: Syntax.ThisExpression, + name: name + }; + }; + + SCParser.prototype.createUnaryExpression = function(operator, arg) { + return { + type: Syntax.UnaryExpression, + operator: operator, + arg: arg + }; + }; + + SCParser.prototype.createVariableDeclaration = function(declarations, kind) { + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: kind + }; + }; + + SCParser.prototype.createVariableDeclarator = function(id, init) { + var node = { + type: Syntax.VariableDeclarator, + id: id + }; + if (init) { + node.init = init; + } + return node; + }; + + SCParser.prototype.isClassName = function(node) { + var name, ch; + + if (node.type === Syntax.Identifier) { + name = node.value || node.name; + ch = name.charAt(0); + return "A" <= ch && ch <= "Z"; + } + + return false; + }; + + SCParser.prototype.isKeyword = function(value) { + return !!Keywords[value] || false; + }; + + SCParser.prototype.isLeftHandSide = function(expr) { + switch (expr.type) { + case Syntax.Identifier: + case Syntax.MemberExpression: + case Syntax.GlobalExpression: + return true; + } + return false; + }; + + + SCParser.prototype.match = function(value) { + var token = this.lookahead; + return token.type === Token.Punctuator && token.value === value; + }; + + SCParser.prototype.matchAny = function(list) { + var value, i, imax; + + if (this.lookahead.type === Token.Punctuator) { + value = this.lookahead.value; + for (i = 0, imax = list.length; i < imax; ++i) { + if (list[i] === value) { + return value; + } + } + } + + return null; + }; + + SCParser.prototype.matchKeyword = function(value) { + var token = this.lookahead; + return token.type === Token.Keyword && token.value === value; + }; + + SCParser.prototype.withScope = function(fn) { + var result; + + this.scope.begin(); + result = fn.call(this); + this.scope.end(); + + return result; + }; + + // 1. Program + SCParser.prototype.parseProgram = function() { + var node; + + this.skipComment(); + this.markStart(); + this.peek(); + + node = this.withScope(function() { + var body; + + body = this.parseFunctionBody(""); + if (body.length === 1 && body[0].type === Syntax.BlockExpression) { + body = body[0].body; + } + + return this.createProgram(body); + }); + + return this.markEnd(node); + }; + + // 2. Function + // 2.1 Function Expression + SCParser.prototype.parseFunctionExpression = function(closed, blocklist) { + var node; + + node = this.withScope(function() { + var args, body; + + if (this.match("|")) { + args = this.parseFunctionArgument("|"); + } else if (this.matchKeyword("arg")) { + args = this.parseFunctionArgument(";"); + } + body = this.parseFunctionBody("}"); + + return this.createFunctionExpression(args, body, closed, false, blocklist); + }); + + return node; + }; + + // 2.2 Function Argument + SCParser.prototype.parseFunctionArgument = function(expect) { + var args = { list: [] }, lookahead; + + this.lex(); + + if (!this.match("...")) { + do { + args.list.push(this.parseFunctionArgumentElement()); + if (!this.match(",")) { + break; + } + this.lex(); + } while (this.lookahead.type !== Token.EOF); + } + + if (this.match("...")) { + this.lex(); + lookahead = this.lookahead; + args.remain = this.parseVariableIdentifier(); + this.scope.add("arg", args.remain.name); + } + + this.expect(expect); + + return args; + }; + + SCParser.prototype.parseFunctionArgumentElement = function() { + var init = null, id; + + this.skipComment(); + this.markStart(); + id = this.parseVariableIdentifier(); + this.scope.add("arg", id.name); + + if (this.match("=")) { + this.lex(); + init = this.parseUnaryExpression(); + } + + return this.markEnd(this.createVariableDeclarator(id, init)); + }; + + // 2.3 Function Body + SCParser.prototype.parseFunctionBody = function(match) { + var elements = []; + + while (this.matchKeyword("var")) { + elements.push(this.parseVariableDeclaration()); + } + + while (this.lookahead.type !== Token.EOF && !this.match(match)) { + elements.push(this.parseExpression()); + if (this.lookahead.type !== Token.EOF && !this.match(match)) { + this.expect(";"); + } else { + break; + } + } + + return elements; + }; + + // 3. Variable Declarations + SCParser.prototype.parseVariableDeclaration = function() { + var declaration; + + this.skipComment(); + this.markStart(); + + this.lex(); // var + + declaration = this.markEnd( + this.createVariableDeclaration( + this.parseVariableDeclarationList(), "var" + ) + ); + + this.expect(";"); + + return declaration; + }; + + SCParser.prototype.parseVariableDeclarationList = function() { + var list = []; + + do { + list.push(this.parseVariableDeclarationElement()); + if (!this.match(",")) { + break; + } + this.lex(); + } while (this.lookahead.type !== Token.EOF); + + return list; + }; + + SCParser.prototype.parseVariableDeclarationElement = function() { + var init = null, id; + + this.skipComment(); + this.markStart(); + id = this.parseVariableIdentifier(); + this.scope.add("var", id.name); + + if (this.match("=")) { + this.lex(); + init = this.parseAssignmentExpression(); + } + + return this.markEnd(this.createVariableDeclarator(id, init)); + }; + + // 4. Expression + SCParser.prototype.parseExpression = function(node) { + return this.parseAssignmentExpression(node); + }; + + // 4.1 Expressions + SCParser.prototype.parseExpressions = function(node) { + var nodes = []; + + if (node) { + nodes.push(node); + this.lex(); + } + + while (this.lookahead.type !== Token.EOF && !this.matchAny([ ",", ")", "]", ".." ])) { + this.skipComment(); + this.markStart(); + node = this.parseAssignmentExpression(); + this.markEnd(node); + nodes.push(node); + if (this.match(";")) { + this.lex(); + } + } + + if (nodes.length === 0) { + this.throwUnexpected(this.lookahead); + } + + return nodes.length === 1 ? nodes[0] : nodes; + }; + + // 4.2 Assignment Expression + SCParser.prototype.parseAssignmentExpression = function(node) { + var token, left, right; + var sharp, destructuringAssignment; + var marker, saved; + + if (node) { + return this.parsePartialExpression(node); + } + + token = this.lookahead; + + this.skipComment(); + marker = this.createLocationMarker(); + this.markStart(); + + saved = this.save(); + + if (this.match("#")) { + sharp = true; + token = this.lex(); + if (this.matchAny([ "[", "{" ])) { + // this.revert(token); + this.restore(saved); + } else { + destructuringAssignment = true; + left = this.parseDestructuringAssignmentLeft(); + token = this.lookahead; + this.expect("="); + + right = this.parseAssignmentExpression(); + node = this.createAssignmentExpression( + token.value, left.list, right, left.remain + ); + } + } + + if (!destructuringAssignment) { + node = left = this.parsePartialExpression(); + + if (this.match("=")) { + if (!this.isLeftHandSide(left)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } + + token = this.lex(); + right = this.parseAssignmentExpression(); + node = this.createAssignmentExpression( + token.value, left, right + ); + } + } + + return this.markEnd(node); + }; + + SCParser.prototype.parseDestructuringAssignmentLeft = function() { + var params = { list: [] }, element; + + do { + element = this.parseLeftHandSideExpression(); + if (!this.isLeftHandSide(element)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } + params.list.push(element); + if (this.match(",")) { + this.lex(); + } else if (this.match("...")) { + this.lex(); + params.remain = this.parseLeftHandSideExpression(); + if (!this.isLeftHandSide(params.remain)) { + this.throwError({}, Message.InvalidLHSInAssignment); + } + break; + } + } while (this.lookahead.type !== Token.EOF && !this.match("=")); + + return params; + }; + + // 4.3 Partial Expression + SCParser.prototype.parsePartialExpression = function(node) { + var underscore; + + if (this.state.innerElements) { + node = this.parseBinaryExpression(node); + } else { + underscore = this.state.underscore; + this.state.underscore = []; + + node = this.parseBinaryExpression(node); + + if (this.state.underscore.length) { + node = this.withScope(function() { + var args, i, imax; + + args = new Array(this.state.underscore.length); + for (i = 0, imax = args.length; i < imax; ++i) { + args[i] = this.state.underscore[i]; + this.scope.add("arg", this.state.underscore[i].name); + } + + return this.createFunctionExpression( + { list: args }, [ node ], false, true, false + ); + }); + } + + this.state.underscore = underscore; + } + + return node; + }; + + // 4.4 Conditional Expression + // 4.5 Binary Expression + SCParser.prototype.parseBinaryExpression = function(node) { + var marker, markers, expr, token, prec, stack; + var left, operator, right, i; + + this.skipComment(); + + marker = this.createLocationMarker(); + left = this.parseUnaryExpression(node); + + token = this.lookahead; + prec = this.binaryPrecedence(token); + if (prec === 0) { + if (node) { + return this.parseUnaryExpression(node); + } + return left; + } + this.lex(); + + token.prec = prec; + token.adverb = this.parseAdverb(); + + markers = [ marker, this.createLocationMarker() ]; + right = this.parseUnaryExpression(); + + stack = [ left, token, right ]; + + while ((prec = this.binaryPrecedence(this.lookahead)) > 0) { + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop(); + left = stack.pop(); + expr = this.createBinaryExpression(operator, left, right); + markers.pop(); + + marker = markers.pop(); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + stack.push(expr); + markers.push(marker); + } + + // Shift. + token = this.lex(); + token.prec = prec; + token.adverb = this.parseAdverb(); + + stack.push(token); + markers.push(this.createLocationMarker()); + expr = this.parseUnaryExpression(); + stack.push(expr); + } + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + markers.pop(); + while (i > 1) { + expr = this.createBinaryExpression(stack[i - 1], stack[i - 2], expr); + i -= 2; + marker = markers.pop(); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + } + + return expr; + }; + + SCParser.prototype.binaryPrecedence = function(token) { + var table, prec = 0; + + if (this.opts.binaryPrecedence) { + if (typeof this.opts.binaryPrecedence === "object") { + table = this.opts.binaryPrecedence; + } else { + table = binaryPrecedenceDefaults; + } + } else { + table = {}; + } + switch (token.type) { + case Token.Punctuator: + if (token.value !== "=") { + if (table.hasOwnProperty(token.value)) { + prec = table[token.value]; + } else if (/^[-+*\/%<=>!?&|@]+$/.test(token.value)) { + prec = 255; + } + } + break; + case Token.Label: + prec = 255; + break; + } + + return prec; + }; + + SCParser.prototype.parseAdverb = function() { + var adverb, lookahead; + + if (this.match(".")) { + this.lex(); + + lookahead = this.lookahead; + adverb = this.parsePrimaryExpression(); + + if (adverb.type === Syntax.Identifier || adverb.type === Syntax.Literal) { + return adverb; + } + + this.throwUnexpected(lookahead); + } + + return null; + }; + + // 4.6 Unary Expressions + SCParser.prototype.parseUnaryExpression = function(node) { + var token, expr; + + this.markStart(); + + if (this.match("`")) { + token = this.lex(); + expr = this.parseUnaryExpression(); + expr = this.createUnaryExpression(token.value, expr); + } else { + expr = this.parseLeftHandSideExpression(node); + } + + return this.markEnd(expr); + }; + + // 4.7 LeftHandSide Expressions + SCParser.prototype.parseLeftHandSideExpression = function(node) { + var marker, expr, args, m, prev, lookahead, closedFunction, disallowNotMember; + var disallowGenerator, blocklist; + + this.skipComment(); + + marker = this.createLocationMarker(); + disallowNotMember = this.state.disallowNotMember; + this.state.disallowNotMember = false; + expr = this.parsePrimaryExpression(node); + this.state.disallowNotMember = disallowNotMember; + + blocklist = false; + + while ((m = this.matchAny([ "(", "{", "#", "[", "." ])) !== null) { + lookahead = this.lookahead; + if ((prev === "{" && (m !== "#" && m !== "{")) || (prev === "(" && m === "(")) { + this.throwUnexpected(lookahead); + } + switch (m) { + case "(": + if (this.isClassName(expr)) { + expr = this.createMemberExpression( + ".", expr, this.markTouch(this.createIdentifier("new")) + ); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + } + node = this.parseCallArgument(); + expr = this.createCallExpression(expr, node); + break; + case "#": + closedFunction = this.state.closedFunction; + this.state.closedFunction = true; + this.lex(); + if (!this.match("{")) { + this.throwUnexpected(this.lookahead); + } + m = "{"; + /* falls through */ + case "{": + if (expr.type === Syntax.MemberExpression && !expr.computed) { + expr = this.createCallExpression(expr, { list: [] }); + } else if (expr.type === Syntax.Identifier) { + if (this.isClassName(expr)) { + expr = this.createMemberExpression( + ".", expr, this.markTouch(this.createIdentifier("new")) + ); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + } + expr = this.createCallExpression(expr, { list: [] }); + } else if (expr.type !== Syntax.CallExpression) { + this.throwUnexpected(lookahead); + } + lookahead = this.lookahead; + disallowGenerator = this.state.disallowGenerator; + this.state.disallowGenerator = true; + disallowNotMember = this.state.disallowNotMember; + this.state.disallowNotMember = true; + node = this.parseBraces(true); + this.state.disallowNotMember = disallowNotMember; + this.state.disallowGenerator = disallowGenerator; + this.state.closedFunction = closedFunction; + args = expr.args; + if (args && !args.expand && !args.keywords) { + args.list.push(node); + } else { + this.throwUnexpected(lookahead); + } + break; + case "[": + if (expr.type === Syntax.CallExpression) { + this.throwUnexpected(this.lookahead); + } + if (this.isClassName(expr)) { + expr = this.createMemberExpression( + ".", expr, this.markTouch(this.createIdentifier("newFrom")) + ); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + disallowNotMember = this.state.disallowNotMember; + this.state.disallowNotMember = true; + this.markStart(); + node = this.markEnd(this.parseLeftHandSideExpression()); + this.state.disallowNotMember = disallowNotMember; + expr = this.createCallExpression(expr, { list: [ node ] }); + } else { + node = this.parseListIndexer(); + expr = this.createMemberExpression("[", expr, node); + } + break; + case ".": + this.lex(); + if (this.match("(")) { + expr = this.createMemberExpression( + ".", expr, this.markTouch(this.createIdentifier("value")) + ); + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + node = this.parseCallArgument(); + expr = this.createCallExpression(expr, node); + } else if (this.match("[")) { + node = this.parseListIndexer(); + expr = this.createMemberExpression("[", expr, node); + } else { + node = this.parseProperty(); + expr = this.createMemberExpression(".", expr, node); + } + break; + } + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + prev = m; + } + + return expr; + }; + + SCParser.prototype.parseCallArgument = function() { + var args, node, key, value, hasKeyword, lookahead; + + args = { list: [] }; + hasKeyword = false; + + this.expect("("); + + while (this.lookahead.type !== Token.EOF && !this.match(")")) { + lookahead = this.lookahead; + if (!hasKeyword) { + if (this.match("*")) { + this.lex(); + args.expand = this.parseExpressions(); + hasKeyword = true; + } else if (lookahead.type === Token.Label) { + key = this.lex().value; + value = this.parseExpressions(); + args.keywords = {}; + args.keywords[key] = value; + hasKeyword = true; + } else { + node = this.parseExpressions(); + args.list.push(node); + } + } else { + if (lookahead.type !== Token.Label) { + this.throwUnexpected(lookahead); + } + key = this.lex().value; + value = this.parseExpressions(); + if (!args.keywords) { + args.keywords = {}; + } + args.keywords[key] = value; + } + if (this.match(")")) { + break; + } + this.expect(","); + } + + this.expect(")"); + + return args; + }; + + SCParser.prototype.parseListIndexer = function() { + var first = null, second = null, last = null; + var node = null; + + this.expect("["); + + if (!this.match("]")) { + this.markStart(); + + if (this.match("..")) { + // [..A] + this.lex(); + if (!this.match("]")) { + last = this.parseExpressions(); + node = this.markEnd(this.createListIndexer(null, null, last)); + } else { + node = this.markEnd(this.createListIndexer(null, null, null)); + } + } else { + if (!this.match(",")) { + first = this.parseExpressions(); + } else { + this.throwUnexpected(this.lookahead); + } + if (this.match("..")) { + this.lex(); + if (!this.match("]")) { + // [A..B] + last = this.parseExpressions(); + } + node = this.markEnd(this.createListIndexer(first, null, last)); + } else if (this.match(",")) { + this.lex(); + second = this.parseExpressions(); + if (this.match("..")) { + // [A, B..C] + this.lex(); + if (!this.match("]")) { + last = this.parseExpressions(); + } + } else { + this.throwUnexpected(this.lookahead); + } + node = this.markEnd(this.createListIndexer(first, second, last)); + } else { + // [A] + node = this.markEnd(first); + } + } + } + + this.expect("]"); + + if (node === null) { + this.throwUnexpected({ value: "]" }); + } + + return node; + }; + + SCParser.prototype.parseProperty = function() { + var token; + + this.skipComment(); + this.markStart(); + token = this.lex(); + + if (token.type !== Token.Identifier || this.isClassName(token)) { + this.throwUnexpected(token); + } + + return this.markEnd(this.createIdentifier(token.value)); + }; + + // 4.8 Primary Expressions + SCParser.prototype.parsePrimaryExpression = function(node) { + var expr, token, lookahead, closedFunction, disallowGenerator; + + if (node) { + return node; + } + + this.skipComment(); + this.markStart(); + + if (this.match("~")) { + this.lex(); + expr = this.createGlobalExpression(this.parseIdentifier()); + } else { + lookahead = this.lookahead; + + switch (this.matchAny([ "(", "{", "[", "#" ]) || this.lookahead.type) { + case "(": + expr = this.parseParentheses(); + break; + case "{": + expr = this.parseBraces(); + break; + case "[": + expr = this.parseListInitialiser(); + break; + case "#": + this.lex(); + switch (this.matchAny([ "[", "{" ])) { + case "[": + if (this.state.immutableList) { + this.throwUnexpected(lookahead); + } + this.state.immutableList = true; + expr = this.parseListInitialiser(); + this.state.immutableList = false; + break; + case "{": + disallowGenerator = this.state.disallowGenerator; + this.state.disallowGenerator = true; + closedFunction = this.state.closedFunction; + this.state.closedFunction = true; + expr = this.parseBraces(); + this.state.closedFunction = closedFunction; + this.state.disallowGenerator = disallowGenerator; + break; + default: + expr = {}; + this.throwUnexpected(this.lookahead); + break; + } + break; + case Token.Keyword: + if (Keywords[this.lookahead.value] === "keyword") { + this.throwUnexpected(this.lookahead); + } + expr = this.createThisExpression(this.lex().value); + break; + case Token.Identifier: + lookahead = this.lookahead; + expr = this.parseIdentifier(); + if (expr.name === "_") { + expr.name += this.state.underscore.length.toString(); + this.state.underscore.push(expr); + } + break; + case Token.BooleanLiteral: + case Token.CharLiteral: + case Token.FloatLiteral: + case Token.IntegerLiteral: + case Token.NilLiteral: + case Token.SymbolLiteral: + expr = this.createLiteral(this.lex()); + break; + case Token.StringLiteral: + token = this.lex(); + if (token.value.charAt(0) === '"' && token.value.indexOf("#{") !== -1) { + expr = this.parseInterpolatedString(token); + } else { + expr = this.createLiteral(token); + } + break; + } + } + + if (!expr) { + expr = {}; + this.throwUnexpected(this.lex()); + } + + return this.markEnd(expr); + }; + + SCParser.prototype.parseInterpolatedString = function(token) { + var value, len, items; + var i, j, ch, depth, code, parser; + + value = token.value.substr(1, token.value.length - 2); + len = value.length; + items = []; + + i = 0; + + do { + j = i; + LOOP1: while (j < len) { + ch = value.charAt(j); + switch (ch) { + case "#": + if (value.charAt(j + 1) === "{") { + break LOOP1; + } + break; + case "\\": + j += 1; + break; + } + j += 1; + } + + if (j >= len) { + break; + } + code = value.substr(i, j - i); + if (code) { + items.push(q(code)); + } + i = j + 2; + j = i; + depth = 0; + LOOP2: while (j < len) { + ch = value.charAt(j); + switch (ch) { + case "}": + if (depth === 0) { + code = value.substr(i, j - i); + if (code) { + items.push("(" + code + ").asString"); + } + break LOOP2; + } + depth -= 1; + break; + case "{": + depth += 1; + break; + } + j += 1; + } + i = j + 1; + } while (i < len); + + if (i < len) { + items.push(q(value.substr(i))); + } + + code = items.join("++"); + parser = new SCParser(code, {}); + parser.peek(); + + return parser.parseExpression(); + }; + + // ( ... ) + SCParser.prototype.parseParentheses = function() { + var marker, node, expr, generator; + + this.skipComment(); + + marker = this.createLocationMarker(); + this.expect("("); + + if (this.match(":")) { + this.lex(); + generator = true; + } + + if (this.lookahead.type === Token.Label) { + expr = this.parseObjectInitialiser(); + } else if (this.matchKeyword("var")) { + expr = this.withScope(function() { + var body; + body = this.parseFunctionBody(")"); + return this.createBlockExpression(body); + }); + } else if (this.match("..")) { + expr = this.parseRangeInitialiser(null, generator); + } else if (this.match(")")) { + expr = this.createObjectExpression([]); + } else { + node = this.parseExpression(); + if (this.matchAny([ ",", ".." ])) { + expr = this.parseRangeInitialiser(node, generator); + } else if (this.match(":")) { + expr = this.parseObjectInitialiser(node); + } else if (this.match(";")) { + expr = this.parseExpressions(node); + if (this.matchAny([ ",", ".." ])) { + expr = this.parseRangeInitialiser(expr, generator); + } + marker = null; + } else { + expr = this.parseExpression(node); + marker = null; + } + } + + this.expect(")"); + + /* istanbul ignore else */ + if (marker) { + marker.apply(expr); + } + + return expr; + }; + + SCParser.prototype.parseObjectInitialiser = function(node) { + var elements = [], innerElements; + + innerElements = this.state.innerElements; + this.state.innerElements = true; + + if (node) { + this.expect(":"); + } else { + node = this.parseLabel(); + } + elements.push(node, this.parseExpression()); + + if (this.match(",")) { + this.lex(); + } + + while (this.lookahead.type !== Token.EOF && !this.match(")")) { + if (this.lookahead.type === Token.Label) { + node = this.parseLabel(); + } else { + node = this.parseExpression(); + } + elements.push(node); + if (node.type !== Syntax.Label) { + this.expect(":"); + } + elements.push(this.parseExpression()); + if (!this.match(")")) { + this.expect(","); + } + } + + this.state.innerElements = innerElements; + + return this.createObjectExpression(elements); + }; + + SCParser.prototype.parseRangeInitialiser = function(node, generator) { + var first = null, second = null, last = null; + var innerElements; + + innerElements = this.state.innerElements; + this.state.innerElements = true; + + if (node === null) { + // (..last) + this.expect(".."); + if (this.match(")")) { + this.throwUnexpected(this.lookahead); + } + last = this.parseExpressions(); + } else { + first = node; + if (this.match(",")) { + // (first, second .. last) + this.lex(); + second = this.parseExpressions(); + if (Array.isArray(second) && second.length === 0) { + this.throwUnexpected(this.lookahead); + } + this.expect(".."); + if (!this.match(")")) { + last = this.parseExpressions(); + } else if (!generator) { + this.throwUnexpected(this.lookahead); + } + } else { + // (first..last) + this.lex(); + if (!this.match(")")) { + last = this.parseExpressions(); + } else if (!generator) { + this.throwUnexpected(this.lookahead); + } + } + } + + this.state.innerElements = innerElements; + + return this.createRangeExpression(first, second, last, generator); + }; + + SCParser.prototype.parseListInitialiser = function() { + var elements, innerElements; + + elements = []; + + innerElements = this.state.innerElements; + this.state.innerElements = true; + + this.expect("["); + + while (this.lookahead.type !== Token.EOF && !this.match("]")) { + if (this.lookahead.type === Token.Label) { + elements.push(this.parseLabel()); + elements.push(this.parseExpression()); + } else { + elements.push(this.parseExpression()); + if (this.match(":")) { + this.lex(); + elements.push(this.parseExpression()); + } + } + if (!this.match("]")) { + this.expect(","); + } + } + + this.expect("]"); + + this.state.innerElements = innerElements; + + return this.createListExpression(elements, this.state.immutableList); + }; + + // { ... } + SCParser.prototype.parseBraces = function(blocklist) { + var expr; + + this.skipComment(); + this.markStart(); + + this.expect("{"); + + if (this.match(":")) { + if (!this.state.disallowGenerator) { + this.lex(); + expr = this.parseGeneratorInitialiser(); + } else { + expr = {}; + this.throwUnexpected(this.lookahead); + } + } else { + expr = this.parseFunctionExpression(this.state.closedFunction, blocklist); + } + + this.expect("}"); + + return this.markEnd(expr); + }; + + SCParser.prototype.parseGeneratorInitialiser = function() { + this.throwError({}, Message.NotImplemented, "generator literal"); + + this.parseExpression(); + this.expect(","); + + while (this.lookahead.type !== Token.EOF && !this.match("}")) { + this.parseExpression(); + if (!this.match("}")) { + this.expect(","); + } + } + + return this.createLiteral({ value: "null", valueType: Token.NilLiteral }); + }; + + SCParser.prototype.parseLabel = function() { + this.skipComment(); + this.markStart(); + return this.markEnd(this.createLabel(this.lex().value)); + }; + + SCParser.prototype.parseIdentifier = function() { + var expr; + + this.skipComment(); + this.markStart(); + + if (this.lookahead.type !== Syntax.Identifier) { + this.throwUnexpected(this.lookahead); + } + + expr = this.lex(); + + return this.markEnd(this.createIdentifier(expr.value)); + }; + + SCParser.prototype.parseVariableIdentifier = function() { + var token, value, ch; + + this.skipComment(); + this.markStart(); + + token = this.lex(); + value = token.value; + + if (token.type !== Token.Identifier) { + this.throwUnexpected(token); + } else { + ch = value.charAt(0); + if (("A" <= ch && ch <= "Z") || ch === "_") { + this.throwUnexpected(token); + } + } + + return this.markEnd(this.createIdentifier(value)); + }; + + SCParser.prototype.markStart = function() { + /* istanbul ignore else */ + if (this.opts.loc) { + this.marker.push( + this.index - this.lineStart, + this.lineNumber + ); + } + /* istanbul ignore else */ + if (this.opts.range) { + this.marker.push( + this.index + ); + } + }; + + SCParser.prototype.markEnd = function(node) { + if (Array.isArray(node) || node.range || node.loc) { + /* istanbul ignore else */ + if (this.opts.range) { + this.marker.pop(); + } + /* istanbul ignore else */ + if (this.opts.loc) { + this.marker.pop(); + this.marker.pop(); + } + } else { + /* istanbul ignore else */ + if (this.opts.range) { + node.range = [ this.marker.pop(), this.index ]; + } + /* istanbul ignore else */ + if (this.opts.loc) { + node.loc = { + start: { + line: this.marker.pop(), + column: this.marker.pop() + }, + end: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; + } + } + return node; + }; + + SCParser.prototype.markTouch = function(node) { + /* istanbul ignore else */ + if (this.opts.range) { + node.range = [ this.index, this.index ]; + } + /* istanbul ignore else */ + if (this.opts.loc) { + node.loc = { + start: { + line: this.lineNumber, + column: this.index - this.lineStart + }, + end: { + line: this.lineNumber, + column: this.index - this.lineStart + } + }; + } + return node; + }; + + SCParser.prototype.throwError = function(token, messageFormat) { + var args, message; + var error, index, lineNumber, column; + var prev; + + args = Array.prototype.slice.call(arguments, 2); + message = messageFormat.replace(/%(\d)/g, function(whole, index) { + return args[index]; + }); + + if (typeof token.lineNumber === "number") { + index = token.range[0]; + lineNumber = token.lineNumber; + column = token.range[0] - token.lineStart + 1; + } else { + index = this.index; + lineNumber = this.lineNumber; + column = this.index - this.lineStart + 1; + } + + error = new Error("Line " + lineNumber + ": " + message); + error.index = index; + error.lineNumber = lineNumber; + error.column = column; + error.description = message; + + if (this.errors) { + prev = this.errors[this.errors.length - 1]; + if (!(prev && error.index === prev.index)) { + this.errors.push(error); + } + } else { + throw error; + } + }; + + SCParser.prototype.throwUnexpected = function(token) { + switch (token.type) { + case Token.EOF: + this.throwError(token, Message.UnexpectedEOS); + break; + case Token.FloatLiteral: + case Token.IntegerLiteral: + this.throwError(token, Message.UnexpectedNumber); + break; + case Token.CharLiteral: + this.throwError(token, Message.UnexpectedChar); + break; + case Token.StringLiteral: + this.throwError(token, Message.UnexpectedString); + break; + case Token.SymbolLiteral: + this.throwError(token, Message.UnexpectedSymbol); + break; + case Token.Identifier: + this.throwError(token, Message.UnexpectedIdentifier); + break; + default: + this.throwError(token, Message.UnexpectedToken, token.value); + break; + } + }; + + parser.parse = function(source, opts) { + var instance, ast; + + opts = opts || /* istanbul ignore next */ {}; + + instance = new SCParser(source, opts); + ast = instance.parse(); + + if (!!opts.tokens && typeof instance.tokens !== "undefined") { + ast.tokens = instance.tokens; + } + if (!!opts.tolerant && typeof instance.errors !== "undefined") { + ast.errors = instance.errors; + } + + return ast; + }; + + sc.lang.parser = parser; + + var SCScript = sc.SCScript; + + SCScript.tokenize = function(source, opts) { + opts = opts || /* istanbul ignore next */ {}; + opts.tokens = true; + return parser.parse(source, opts).tokens || /* istanbul ignore next */ []; + }; + + SCScript.parse = parser.parse; + +})(sc); diff --git a/src/sc/lang/parser_test.js b/src/sc/lang/parser_test.js new file mode 100644 index 0000000..7e76a75 --- /dev/null +++ b/src/sc/lang/parser_test.js @@ -0,0 +1,877 @@ +"use strict"; + +require("./parser"); +require("../test/parser-test-case"); + +var SCScript = sc.SCScript; +var Syntax = sc.lang.parser.Syntax; +var Token = sc.lang.parser.Token; +var Message = sc.lang.parser.Message; + +describe("sc.lang.parser", function() { + function s(str) { + str = JSON.stringify(str); + return '"' + str.substr(1, str.length - 2) + '"'; + } + + function error(options, messageFormat) { + var e, args, description, message; + + args = Array.prototype.slice.call(arguments, 2); + description = messageFormat.replace(/%(\d)/g, function(whole, index) { + return args[index]; + }); + + if (options.line !== -1) { + message = "Line " + options.line + ": " + description; + } else { + message = description; + } + + e = new Error(message); + e.index = options.index; + e.lineNumber = options.line; + e.column = options.column; + e.description = description; + + return e; + } + + describe("tokenize", function() { + var cases = { + "": [], + "a": [ + { + type: "Identifier", + value: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + ], + "this": [ + { + type: "Keyword", + value: "this", + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 4 } + } + }, + ], + "thisThread": [ + { + type: "Keyword", + value: "thisThread", + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + }, + ], + "thisProcess": [ + { + type: "Keyword", + value: "thisProcess", + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 11 } + } + }, + ], + "thisFunction": [ + { + type: "Keyword", + value: "thisFunction", + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 12 } + } + }, + ], + "thisFunctionDef": [ + { + type: "Keyword", + value: "thisFunctionDef", + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 15 } + } + }, + ], + "var": { + error : "unexpected", + }, + "arg": { + error : "unexpected", + }, + "const": { + error : "unexpected", + }, + "10": [ + { + type: "Integer", + value: "10", + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 2 } + } + }, + ], + "-10": [ + { + type: "Integer", + value: "-10", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 3 } + } + }, + ], + "+10": { + error : "unexpected" + }, + "1_000": [ + { + type: "Integer", + value: "1_000", + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 5 } + } + }, + ], + "1_": { + error : "unexpected" + }, + "1__000": { + error : "unexpected" + }, + "10pi": [ + { + type: "Float", + value: "10pi", + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 4 } + } + }, + ], + "-10.5e-1pi": [ + { + type: "Float", + value: "-10.5e-1pi", + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + }, + ], + "1_0000.0000_0000e-1_000": [ + { + type: "Float", + value: "1_0000.0000_0000e-1_000", + range: [ 0, 23 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 23 } + } + }, + ], + "2r1101": [ + { + type: "Integer", + value: "2r1101", + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + }, + ], + "-2r1101": [ + { + type: "Integer", + value: "-2r1101", + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + }, + ], + "2r1101pi": [ + { + type: "Float", + value: "2r1101pi", + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 8 } + } + }, + ], + "2r1.101": [ + { + type: "Float", + value: "2r1.101", + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + }, + ], + "2r1a": { + error : "unexpected" + }, + "2r1.Z": { + error : "unexpected" + }, + "pi": [ + { + type: "Float", + value: "pi", + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 2 } + } + }, + ], + "-pi": [ + { + type: "Float", + value: "-pi", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 3 } + } + }, + ], + "inf": [ + { + type: "Float", + value: "inf", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 3 } + } + }, + ], + "-inf": [ + { + type: "Float", + value: "-inf", + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 4 } + } + }, + ], + "$.": [ + { + type: "Char", + value: "$.", + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 2 } + } + }, + ], + "$ch": { + error : "unexpected" + }, + "\\symbol": [ + { + type: "Symbol", + value: "\\symbol", + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + }, + ], + "\\00_symbol": { + error : "unexpected" + }, + "'symbol'": [ + { + type: "Symbol", + value: "'symbol'", + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 8 } + } + }, + ], + "'symbol": { + error : "unexpected" + }, + '"s\\tri\ng"': [ + { + type: "String", + value: '"s\\tri\ng"', + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 2, column: 2 } + } + }, + ], + '"string': { + error : "unexpected" + }, + "nil": [ + { + type: "Nil", + value: "nil", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 3 } + } + }, + ], + "true": [ + { + type: "Boolean", + value: "true", + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 4 } + } + }, + ], + "false": [ + { + type: "Boolean", + value: "false", + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 5 } + } + }, + ], + "[]": [ + { + type: "Punctuator", + value: "[", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + { + type: "Punctuator", + value: "]", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + ], + "#[]": [ + { + type: "Punctuator", + value: "#", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + { + type: "Punctuator", + value: "[", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + { + type: "Punctuator", + value: "]", + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + ], + "{}": [ + { + type: "Punctuator", + value: "{", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + { + type: "Punctuator", + value: "}", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + ], + "#{}": [ + { + type: "Punctuator", + value: "#", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + { + type: "Punctuator", + value: "{", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + { + type: "Punctuator", + value: "}", + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + ], + "^": { + error : "unexpected" + } + }; + + Object.keys(cases).forEach(function(source) { + var items, opts, result, error; + var mocha_it; + + items = cases[source]; + + if (Array.isArray(items)) { + opts = { range: true, loc: true }; + result = items; + error = null; + mocha_it = it; + } else { + opts = items.opts || {}; + result = items.result; + error = items.error; + mocha_it = it[items.it] || it; + } + + if (error) { + mocha_it(s(source) + " should throw error", function() { + expect(function() { + SCScript.tokenize(source, opts); + }).to.throw(error); + }); + } else { + mocha_it(s(source), function() { + var test = SCScript.tokenize(source, opts); + expect(test).to.eqls(result); + }); + } + }); + }); + describe("parse", function() { + var cases = sc.test.parser.cases; + Object.keys(cases).forEach(function(source) { + var items = cases[source]; + var mocha_it, result, test; + + mocha_it = it[items.it] || it; + + if (items.ast) { + if (items.ast instanceof Error) { + mocha_it(s(source), function() { + result = items.ast.message; + expect(function() { + SCScript.parse(source); + }).to.throw(result); + }); + } else { + mocha_it(s(source), function() { + result = items.ast; + test = SCScript.parse(source, { range: true, loc: true }); + expect(test).to.eqls(result); + }); + } + } + }); + }); + describe("parse with binary precedence", function() { + var cases = { + "1 + 2 * 3": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "*", + left: { + type: Syntax.BinaryExpression, + operator: "+", + left: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 0, 1 ] + }, + right: { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ] + }, + range: [ 0, 5 ] + }, + right: { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ] + }, + range: [ 0, 9 ] + } + ], + range: [ 0, 9 ] + }, + binaryPrecedence: false + }, + "4 + 5 * 6": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "+", + left: { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 0, 1 ] + }, + right: { + type: Syntax.BinaryExpression, + operator: "*", + left: { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ] + }, + right: { + type: Syntax.Literal, + value: "6", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ] + }, + range: [ 4, 9 ] + }, + range: [ 0, 9 ] + } + ], + range: [ 0, 9 ] + }, + binaryPrecedence: true + }, + "7 + 8 * 9": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "*", + left: { + type: Syntax.BinaryExpression, + operator: "+", + left: { + type: Syntax.Literal, + value: "7", + valueType: Token.IntegerLiteral, + range: [ 0, 1 ] + }, + right: { + type: Syntax.Literal, + value: "8", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ] + }, + range: [ 0, 5 ] + }, + right: { + type: Syntax.Literal, + value: "9", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ] + }, + range: [ 0, 9 ] + } + ], + range: [ 0, 9 ] + }, + binaryPrecedence: { "+": 2, "*": 1 } + }, + }; + Object.keys(cases).forEach(function(source) { + var items = cases[source]; + var mocha_it, result, test; + + mocha_it = it[items.it] || it; + + mocha_it(s(source), function() { + result = items.ast; + test = SCScript.parse(source, { range: true, binaryPrecedence: items.binaryPrecedence }); + expect(test).to.eqls(result); + }); + }); + }); + describe("parse error", function() { + var cases = { + "日本語": [ + error({ line: 1, column: 1, index: 0 }, Message.UnexpectedToken, "日"), + ], + "/*": [ + error({ line: 1, column: 1, index: 0 }, Message.UnexpectedToken, "ILLEGAL"), + ], + "'": [ + error({ line: 1, column: 2, index: 1 }, Message.UnexpectedToken, "ILLEGAL"), + ], + "``": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedEOS), + ], + "[1": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedEOS), + ], + "(1": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedEOS), + ], + "(1..)": [ + error({ line: 1, column: 5, index: 4 }, Message.UnexpectedToken, ")"), + ], + "(1, 3..)": [ + error({ line: 1, column: 8, index: 7 }, Message.UnexpectedToken, ")"), + ], + "(1,..10)": [ + error({ line: 1, column: 4, index: 3 }, Message.UnexpectedToken, ".."), + ], + "(..)": [ + error({ line: 1, column: 4, index: 3 }, Message.UnexpectedToken, ")"), + ], + "{|a, a|}": [ + error({ line: 1, column: 7, index: 6 }, Message.ArgumentAlreadyDeclared, "a"), + ], + "{|0.0, a|}": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedNumber), + ], + "{|a...0| }": [ + error({ line: 1, column: 7, index: 6 }, Message.UnexpectedNumber), + ], + "var [ ];": [ + error({ line: 1, column: 5, index: 4 }, Message.UnexpectedToken, "["), + error({ line: 1, column: 7, index: 6 }, Message.UnexpectedToken, "]"), + error({ line: 1, column: 8, index: 7 }, Message.UnexpectedToken, ";"), + ], + "var Bad;": [ + error({ line: 1, column: 5, index: 4 }, Message.UnexpectedIdentifier), + ], + "var a, a;": [ + error({ line: 1, column: 9, index: 8 }, Message.VariableAlreadyDeclared, "a"), + ], + "var _;": [ + error({ line: 1, column: 5, index: 4 }, Message.UnexpectedIdentifier), + ], + "var _a;": [ + error({ line: 1, column: 5, index: 4 }, Message.UnexpectedIdentifier), + error({ line: 1, column: 6, index: 5 }, Message.UnexpectedIdentifier), + error({ line: 1, column: 7, index: 6 }, Message.UnexpectedToken, ";"), + ], + "a; var b;": [ + error({ line: 1, column: 4, index: 3 }, Message.UnexpectedToken, "var"), + error({ line: 1, column: 8, index: 7 }, Message.UnexpectedIdentifier), + error({ line: 1, column: 9, index: 8 }, Message.UnexpectedToken, ";"), + ], + "10 = a": [ + error({ line: 1, column: 3, index: 2 }, Message.InvalidLHSInAssignment), + ], + "#10 = []": [ + error({ line: 1, column: 4, index: 3 }, Message.InvalidLHSInAssignment), + ], + "#a...10 = []": [ + error({ line: 1, column: 8, index: 7 }, Message.InvalidLHSInAssignment), + ], + "{|a=#2}": [ + error({ line: 1, column: 6, index: 5 }, Message.UnexpectedNumber), + ], + "_a = 0": [ + error({ line: 1, column: 2, index: 1 }, Message.UnexpectedIdentifier), + error({ line: 1, column: 4, index: 3 }, Message.UnexpectedToken, "="), + error({ line: 1, column: 6, index: 5 }, Message.UnexpectedNumber), + ], + "a max : b": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedIdentifier), + error({ line: 1, column: 7, index: 6 }, Message.UnexpectedToken, ":"), + error({ line: 1, column: 9, index: 8 }, Message.UnexpectedIdentifier), + ], + "a +.[] c": [ + error({ line: 1, column: 5, index: 4 }, Message.UnexpectedToken, "["), + // error({ line: 1, column: 6, index: 5 }, Message.UnexpectedToken, "]"), + // error({ line: 1, column: 8, index: 7 }, Message.UnexpectedIdentifier), + ], + "a[]": [ + error({ line: 1, column: 4, index: 3 }, Message.UnexpectedToken, "]"), + ], + "a[1, 2]": [ + error({ line: 1, column: 7, index: 6 }, Message.UnexpectedToken, "]"), + ], + "a[,2..]": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedToken, ","), + ], + "a.0": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedNumber), + ], + "a.$a": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedChar), + ], + 'a."a"': [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedString), + ], + "a.'a'": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedSymbol), + ], + "a.SinOsc": [ + error({ line: 1, column: 3, index: 2 }, Message.UnexpectedIdentifier), + ], + "a.value(b:1, 10)": [ + error({ line: 1, column: 14, index: 13 }, Message.UnexpectedNumber), + error({ line: 1, column: 16, index: 15 }, Message.UnexpectedToken, ")"), + ], + "a.value(b:1, *c)": [ + error({ line: 1, column: 14, index: 13 }, Message.UnexpectedToken, "*"), + ], + "a.value(*b, 10)": [ + error({ line: 1, column: 13, index: 12 }, Message.UnexpectedNumber), + error({ line: 1, column: 15, index: 14 }, Message.UnexpectedToken, ")"), + ], + "a.value(1: 2)": [ + error({ line: 1, column: 10, index: 9 }, Message.UnexpectedToken, ":"), + ], + "a[0] {}": [ + error({ line: 1, column: 6, index: 5 }, Message.UnexpectedToken, "{"), + ], + "a[0] #{}": [ + error({ line: 1, column: 6, index: 5 }, Message.UnexpectedToken, "#"), + error({ line: 1, column: 7, index: 6 }, Message.UnexpectedToken, "{"), + ], + "~10": [ + error({ line: 1, column: 2, index: 1 }, Message.UnexpectedNumber), + ], + "if (true) [0]": [ + error({ line: 1, column: 11, index: 10 }, Message.UnexpectedToken, "["), + ], + "if (*a) {}": [ + error({ line: 1, column: 9, index: 8 }, Message.UnexpectedToken, "{"), + ], + "if (a:true) {}": [ + error({ line: 1, column: 13, index: 12 }, Message.UnexpectedToken, "{"), + ], + "if (true) #[]": [ + error({ line: 1, column: 12, index: 11 }, Message.UnexpectedToken, "["), + error({ line: 1, column: 13, index: 12 }, Message.UnexpectedToken, "]"), + error({ line: 1, column: 14, index: 13 }, Message.UnexpectedEOS), + ], + "if (*a) #{}": [ + error({ line: 1, column: 10, index: 9 }, Message.UnexpectedToken, "{"), + ], + "if (a:true) #{}": [ + error({ line: 1, column: 14, index: 13 }, Message.UnexpectedToken, "{"), + ], + "{: a, a<-[], b<-[] }": [ + error({ line: 1, column: 3, index: 2 }, Message.NotImplemented, "generator literal"), + ], + "if {: a, a <-[], a } ": [ + error({ line: 1, column: 5, index: 4 }, Message.UnexpectedToken, ":"), + error({ line: 1, column: 7, index: 6 }, Message.UnexpectedIdentifier), + error({ line: 1, column: 8, index: 7 }, Message.UnexpectedToken, ","), + error({ line: 1, column: 10, index: 9 }, Message.UnexpectedIdentifier), + error({ line: 1, column: 12, index: 11 }, Message.UnexpectedToken, "<-"), + error({ line: 1, column: 16, index: 15 }, Message.UnexpectedToken, "]"), + error({ line: 1, column: 20, index: 19 }, Message.UnexpectedToken, "}"), + ], + "a(1, 2, ": [ + error({ line: 1, column: 9, index: 8 }, Message.UnexpectedEOS), + ], + "a(a:)": [ + error({ line: 1, column: 5, index: 4 }, Message.UnexpectedToken, ")"), + ], + "a(a:0, b:)": [ + error({ line: 1, column: 10, index: 9 }, Message.UnexpectedToken, ")"), + ], + "if (true) (false)": [ + error({ line: 1, column: 11, index: 10 }, Message.UnexpectedToken, "("), + ], + "if (true) [ 1, 2, 3 ]": [ + error({ line: 1, column: 11, index: 10 }, Message.UnexpectedToken, "["), + error({ line: 1, column: 17, index: 16 }, Message.UnexpectedToken, ","), + error({ line: 1, column: 19, index: 18 }, Message.UnexpectedNumber), + error({ line: 1, column: 21, index: 20 }, Message.UnexpectedToken, "]"), + ], + "if {true} (false)": [ + error({ line: 1, column: 11, index: 10 }, Message.UnexpectedToken, "("), + ], + "if {true} [ 1, 2, 3 ]": [ + error({ line: 1, column: 11, index: 10 }, Message.UnexpectedToken, "["), + error({ line: 1, column: 17, index: 16 }, Message.UnexpectedToken, ","), + error({ line: 1, column: 19, index: 18 }, Message.UnexpectedNumber), + error({ line: 1, column: 21, index: 20 }, Message.UnexpectedToken, "]"), + ], + "if {true} .value": [ + error({ line: 1, column: 11, index: 10 }, Message.UnexpectedToken, ".") + ], + }; + + Object.keys(cases).forEach(function(source) { + var result = cases[source]; + + it(s(source), function() { + var test = SCScript.parse(source, { tolerant: true }); + expect(test.errors).to.eqls(result); + }); + }); + }); +}); diff --git a/src/sc/test/parser-test-case.js b/src/sc/test/parser-test-case.js new file mode 100644 index 0000000..6335f2e --- /dev/null +++ b/src/sc/test/parser-test-case.js @@ -0,0 +1,6419 @@ +(function(sc) { + "use strict"; + + require("../lang/parser"); + + var Token = sc.lang.parser.Token; + var Syntax = sc.lang.parser.Syntax; + + var q = function(str) { + return "'" + str + "'"; + }; + + var cases = { + "": { + ast: { + type: Syntax.Program, + body: [], + range: [ 0, 0 ], + loc: { + start: { line: 0, column: 0 }, + end : { line: 0, column: 0 } + } + } + }, + " \n\t": { + ast: { + type: Syntax.Program, + body: [], + range: [ 6, 6 ], + loc: { + start: { line: 2, column: 1 }, + end : { line: 2, column: 1 } + } + } + }, + "// single line comment\n": { + ast: { + type: Syntax.Program, + body: [], + range: [ 23, 23 ], + loc: { + start: { line: 2, column: 0 }, + end : { line: 2, column: 0 } + } + } + }, + "/*\n/* / * */\n*/": { + ast: { + type: Syntax.Program, + body: [], + range: [ 15, 15 ], + loc: { + start: { line: 3, column: 3 }, + end : { line: 3, column: 3 } + } + } + }, + "-10pi": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.Literal, + value: "(-10 * Math.PI)", + valueType: Token.FloatLiteral, + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 5 } + } + } + ], + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 5 } + } + } + }, + "`100": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.UnaryExpression, + operator: "`", + arg: { + type: Syntax.Literal, + value: "100", + valueType: Token.IntegerLiteral, + range: [ 1, 4 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 4 } + } + }, + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 4 } + } + } + ], + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 4 } + } + } + }, + "a -.f b": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "-", + adverb : { + type: Syntax.Identifier, + name: "f", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + left: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + right: { + type: Syntax.Identifier, + name: "b", + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end : { line: 1, column: 7 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 }, + } + }, + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 }, + } + } + }, + "a /.1 b": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "/", + adverb : { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + left: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + right: { + type: Syntax.Identifier, + name: "b", + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end : { line: 1, column: 7 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 }, + } + }, + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 }, + } + } + }, + "a max:.1 b": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "max", + adverb : { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end : { line: 1, column: 8 } + } + }, + left: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + right: { + type: Syntax.Identifier, + name: "b", + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end : { line: 1, column: 10 } + } + }, + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 }, + } + }, + ], + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 }, + } + } + }, + "[ 0, 0.5 ]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 }, + } + }, + { + type: Syntax.Literal, + value: "0.5", + valueType: Token.FloatLiteral, + range: [ 5, 8 ], + loc: { + start: { line: 1, column: 5 }, + end : { line: 1, column: 8 }, + } + }, + ], + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 }, + } + } + ], + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 }, + } + } + }, + "#[ 0, 0.5 ]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.ListExpression, + immutable: true, + elements: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 3, 4 ], + loc: { + start: { line: 1, column: 3 }, + end : { line: 1, column: 4 }, + } + }, + { + type: Syntax.Literal, + value: "0.5", + valueType: Token.FloatLiteral, + range: [ 6, 9 ], + loc: { + start: { line: 1, column: 6 }, + end : { line: 1, column: 9 }, + } + }, + ], + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 11 }, + } + } + ], + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 11 }, + } + } + }, + "#[ [] ]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.ListExpression, + immutable: true, + elements: [ + { + type: Syntax.ListExpression, + immutable: true, + elements: [ + ], + range: [ 3, 5 ], + loc: { + start: { line: 1, column: 3 }, + end : { line: 1, column: 5 }, + } + }, + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 }, + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 }, + } + } + }, + "#[ #[] ]": { + ast: new Error("unexpected token #") + }, + "[ a: 1, 2: 3]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Label, + name: "a", + range: [ 2, 4 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 4 } + } + }, + { + type : Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end : { line: 1, column: 6 } + } + }, + { + type : Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end : { line: 1, column: 9 } + } + }, + { + type : Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end : { line: 1, column: 12 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 13 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 13 } + } + } + }, + "a = 2pi": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + right: { + type: Syntax.Literal, + value: "(2 * Math.PI)", + valueType: Token.FloatLiteral, + range: [ 4, 7 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 7 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + }, + "#a, b = c": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: [ + { + type: Syntax.Identifier, + name: "a", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + { + type: Syntax.Identifier, + name: "b", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + } + ], + right: { + type: Syntax.Identifier, + name: "c", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end : { line: 1, column: 9 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 9 } + } + } + }, + "#a, b ... c = d": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: [ + { + type: Syntax.Identifier, + name: "a", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + { + type: Syntax.Identifier, + name: "b", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + } + ], + remain: { + type: Syntax.Identifier, + name: "c", + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end : { line: 1, column: 11 } + } + }, + right: { + type: Syntax.Identifier, + name: "d", + range: [ 14, 15 ], + loc: { + start: { line: 1, column: 14 }, + end : { line: 1, column: 15 } + } + }, + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 15 } + } + } + ], + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 15 } + } + } + }, + "#a, b = #c, d = [ 0, 1 ]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: [ + { + type: Syntax.Identifier, + name: "a", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + { + type: Syntax.Identifier, + name: "b", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + } + ], + right: { + type: Syntax.AssignmentExpression, + operator: "=", + left: [ + { + type: Syntax.Identifier, + name: "c", + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end : { line: 1, column: 10 } + } + }, + { + type: Syntax.Identifier, + name: "d", + range: [ 12, 13 ], + loc: { + start: { line: 1, column: 12 }, + end : { line: 1, column: 13 } + } + } + ], + right: { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 18, 19 ], + loc: { + start: { line: 1, column: 18 }, + end : { line: 1, column: 19 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 21, 22 ], + loc: { + start: { line: 1, column: 21 }, + end : { line: 1, column: 22 } + } + } + ], + range: [ 16, 24 ], + loc: { + start: { line: 1, column: 16 }, + end : { line: 1, column: 24 } + } + }, + range: [ 8, 24 ], + loc: { + start: { line: 1, column: 8 }, + end : { line: 1, column: 24 } + } + }, + range: [ 0, 24 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 24 } + } + } + ], + range: [ 0, 24 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 24 } + } + } + }, + "a.b.c = 1": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Identifier, + name: "b", + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 3 } + } + }, + property: { + type: Syntax.Identifier, + name: "c", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 5 } + } + }, + right: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end : { line: 1, column: 9 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 9 } + } + } + }, + "a[0] = 1": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 4 } + } + }, + right: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end : { line: 1, column: 8 } + } + }, + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 8 } + } + } + ], + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 8 } + } + } + }, + "a[5..10] = 1": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + second: null, + last: { + type: Syntax.Literal, + value: "10", + valueType: Token.IntegerLiteral, + range: [ 5, 7 ], + loc: { + start: { line: 1, column: 5 }, + end : { line: 1, column: 7 } + } + }, + range: [ 2, 7 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 7 } + } + }, + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 8 } + } + }, + right: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end : { line: 1, column: 12 } + } + }, + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 12 } + } + } + ], + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 12 } + } + } + }, + "a[7,9..13] = 1": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "7", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + second: { + type: Syntax.Literal, + value: "9", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + last: { + type: Syntax.Literal, + value: "13", + valueType: Token.IntegerLiteral, + range: [ 7, 9 ], + loc: { + start: { line: 1, column: 7 }, + end : { line: 1, column: 9 } + } + }, + range: [ 2, 9 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 9 } + } + }, + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + }, + right: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end : { line: 1, column: 14 } + } + }, + range: [ 0, 14 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 14 } + } + } + ], + range: [ 0, 14 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 14 } + } + } + }, + "a[..5] = 1": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: null, + second: null, + last: { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + range: [ 2, 5 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 5 } + } + }, + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + }, + right: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end : { line: 1, column: 10 } + } + }, + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + } + ], + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + } + }, + "a[12..] = 1": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "12", + valueType: Token.IntegerLiteral, + range: [ 2, 4 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 4 } + } + }, + second: null, + last: null, + range: [ 2, 6 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 6 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + }, + right: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end : { line: 1, column: 11 } + } + }, + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 11 } + } + } + ], + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 11 } + } + } + }, + "a[1,3..] = 1": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + second: { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + last: null, + range: [ 2, 7 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 7 } + } + }, + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 8 } + } + }, + right: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end : { line: 1, column: 12 } + } + }, + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 12 } + } + } + ], + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 12 } + } + } + }, + "a[..] = 1": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: null, + second: null, + last: null, + range: [ 2, 4 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 4 } + } + }, + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 5 } + } + }, + right: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end : { line: 1, column: 9 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 9 } + } + } + }, + "a[..]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: null, + second: null, + last: null, + range: [ 2, 4 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 4 } + } + }, + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 5 } + } + } + ], + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 5 } + } + } + }, + "a[..3]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: null, + second: null, + last: { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + range: [ 2, 5 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 5 } + } + }, + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + } + ], + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + } + }, + "a[3..]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + second: null, + last: null, + range: [ 2, 5 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 5 } + } + }, + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + } + ], + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + } + }, + "a[2..4]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + second: null, + last: { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end : { line: 1, column: 6 } + } + }, + range: [ 2, 6 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 6 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + }, + "a[4..2]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + second: null, + last: { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end : { line: 1, column: 6 } + } + }, + range: [ 2, 6 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 6 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + }, + "a[0, 2..]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + second: { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end : { line: 1, column: 6 } + } + }, + last: null, + range: [ 2, 8 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 8 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 9 } + } + } + }, + "a[0, -2..]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + second: { + type: Syntax.Literal, + value: "-2", + valueType: Token.IntegerLiteral, + range: [ 5, 7 ], + loc: { + start: { line: 1, column: 5 }, + end : { line: 1, column: 7 } + } + }, + last: null, + range: [ 2, 9 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 9 } + } + }, + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + } + ], + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + } + }, + "a[0;1,2;3..4;5]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + } + ], + second: [ + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end : { line: 1, column: 7 } + } + }, + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end : { line: 1, column: 9 } + } + } + ], + last: [ + { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end : { line: 1, column: 12 } + } + }, + { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end : { line: 1, column: 14 } + } + } + ], + range: [ 2, 14 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 14 } + } + }, + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 15 } + } + } + ], + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 15 } + } + } + }, + "a[b[c=0;1]=0;1]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 1 } + } + }, + property: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "b", + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 3 } + } + }, + property: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "c", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + right: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end : { line: 1, column: 7 } + } + }, + range: [ 4, 7 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 7 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end : { line: 1, column: 9 } + } + } + ], + range: [ 2, 10 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 10 } + } + }, + right: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end : { line: 1, column: 12 } + } + }, + range: [ 2, 12 ], + loc: { + start: { line: 1, column: 2 }, + end : { line: 1, column: 12 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end : { line: 1, column: 14 } + } + } + ], + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 15 } + } + } + ], + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 15 } + } + } + }, + "(..10)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: null, + second: null, + last: { + type: Syntax.Literal, + value: "10", + valueType: Token.IntegerLiteral, + range: [ 3, 5 ], + loc: { + start: { line: 1, column: 3 }, + end : { line: 1, column: 5 } + } + }, + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + } + ], + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + } + }, + "(1..16)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + second: null, + last: { + type: Syntax.Literal, + value: "16", + valueType: Token.IntegerLiteral, + range: [ 4, 6 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 6 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + }, + "(16..1)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: { + type: Syntax.Literal, + value: "16", + valueType: Token.IntegerLiteral, + range: [ 1, 3 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 3 } + } + }, + second: null, + last: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end : { line: 1, column: 6 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + }, + "(1, 3..11)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + second: { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 5 } + } + }, + last: { + type: Syntax.Literal, + value: "11", + valueType: Token.IntegerLiteral, + range: [ 7, 9 ], + loc: { + start: { line: 1, column: 7 }, + end : { line: 1, column: 9 } + } + }, + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + } + ], + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 10 } + } + } + }, + "(..20)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: null, + second: null, + last: { + type: Syntax.Literal, + value: "20", + valueType: Token.IntegerLiteral, + range: [ 3, 5 ], + loc: { + start: { line: 1, column: 3 }, + end : { line: 1, column: 5 } + } + }, + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + } + ], + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 6 } + } + } + }, + "(a..20)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: { + type: Syntax.Identifier, + name: "a", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end : { line: 1, column: 2 } + } + }, + second: null, + last: { + type: Syntax.Literal, + value: "20", + valueType: Token.IntegerLiteral, + range: [ 4, 6 ], + loc: { + start: { line: 1, column: 4 }, + end : { line: 1, column: 6 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end : { line: 1, column: 7 } + } + } + }, + "(0;1,2;3..4;5)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 3, 4 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + } + ], + second: [ + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + } + ], + last: [ + { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 12, 13 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + } + ], + range: [ 0, 14 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + } + ], + range: [ 0, 14 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + } + }, + "(:0..)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + second: null, + last: null, + generator: true, + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + } + ], + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + } + }, + "(:0, 2..)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.RangeExpression, + first: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + second: { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + last: null, + generator: true, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + }, + "5 !== 5.0": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "!==", + left: { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: Syntax.Literal, + value: "5", + valueType: Token.FloatLiteral, + range: [ 6, 9 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + }, + "5 == 5.0": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "==", + left: { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: Syntax.Literal, + value: "5", + valueType: Token.FloatLiteral, + range: [ 5, 8 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 8 } + } + }, + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + } + ], + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + } + }, + "{ arg a, b, c=3; }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "b", + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "c", + range: [ 12, 13 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + init: { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 14, 15 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + range: [ 12, 15 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 15 } + } + } + ] + }, + body: [], + range: [ 0, 18 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + } + ], + range: [ 0, 18 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + } + }, + "{ arg a, b, c ... d; }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "b", + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "c", + range: [ 12, 13 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + range: [ 12, 13 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + } + ], + remain: { + type: Syntax.Identifier, + name: "d", + range: [ 18, 19 ], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + } + }, + body: [], + range: [ 0, 22 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + } + ], + range: [ 0, 22 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + } + }, + "{ arg ...args; }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + args: { + list: [], + remain: { + type: Syntax.Identifier, + name: "args", + range: [ 9, 13 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 13 } + } + } + }, + body: [], + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + ], + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + }, + "{ |x = 1| x }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "x", + range: [ 3, 4 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + init: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + range: [ 3, 8 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 8 } + } + } + ] + }, + body: [ + { + type: "Identifier", + name: "x", + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + }, + "{ a; b; c }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.Identifier, + name: "a", + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + { + type: Syntax.Identifier, + name: "b", + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + { + type: Syntax.Identifier, + name: "c", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + } + ], + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + } + ], + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + } + }, + "{|x=1| var a = x * x; a * a; }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "x", + range: [ 2, 3 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 3 } + } + }, + init: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [ 2, 5 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 5 } + } + } + ] + }, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + init: { + type: Syntax.BinaryExpression, + operator: "*", + left: { + type: Syntax.Identifier, + name: "x", + range: [ 15, 16 ], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + right: { + type: Syntax.Identifier, + name: "x", + range: [ 19, 20 ], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + range: [ 15, 20 ], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 20 } + } + }, + range: [ 11, 20 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 20 } + } + } + ], + range: [ 7, 20 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 20 } + } + }, + { + type: Syntax.BinaryExpression, + operator: "*", + left: { + type: Syntax.Identifier, + name: "a", + range: [ 22, 23 ], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 23 } + } + }, + right: { + type: Syntax.Identifier, + name: "a", + range: [ 26, 27 ], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 27 } + } + }, + range: [ 22, 27 ], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 27 } + } + } + ], + range: [ 0, 30 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + } + ], + range: [ 0, 30 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + } + }, + "a = #{}": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: Syntax.FunctionExpression, + body: [], + closed: true, + range: [ 5, 7 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 7 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + }, + "var level=0, slope=1, curve=1;": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "level", + range: [ 4, 9 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + init: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + range: [ 4, 11 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 11 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "slope", + range: [ 13, 18 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 18 } + } + }, + init: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 19, 20 ], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + range: [ 13, 20 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 20 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "curve", + range: [ 22, 27 ], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 27 } + } + }, + init: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 28, 29 ], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 29 } + } + }, + range: [ 22, 29 ], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 29 } + } + } + ], + range: [ 0, 29 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 29 } + } + } + ], + range: [ 0, 30 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 30 } + } + } + }, + "{ |x, y| var a; a = x + y; x.wait; a }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "x", + range: [ 3, 4 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + range: [ 3, 4 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "y", + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + } + ] + }, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + } + ], + range: [ 9, 14 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + }, + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "a", + range: [ 16, 17 ], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + right: { + type: Syntax.BinaryExpression, + operator: "+", + left: { + type: Syntax.Identifier, + name: "x", + range: [ 20, 21 ], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + right: { + type: Syntax.Identifier, + name: "y", + range: [ 24, 25 ], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + }, + range: [ 20, 25 ], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 25 } + } + }, + range: [ 16, 25 ], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 25 } + } + }, + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "x", + range: [ 27, 28 ], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 28 } + } + }, + property: { + type: Syntax.Identifier, + name: "wait", + range: [ 29, 33 ], + loc: { + start: { line: 1, column: 29 }, + end: { line: 1, column: 33 } + } + }, + range: [ 27, 33 ], + loc: { + start: { line: 1, column: 27 }, + end: { line: 1, column: 33 } + } + }, + { + type: Syntax.Identifier, + name: "a", + range: [ 35, 36 ], + loc: { + start: { line: 1, column: 35 }, + end: { line: 1, column: 36 } + } + } + ], + range: [ 0, 38 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + } + ], + range: [ 0, 38 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 38 } + } + } + }, + "{ if (true) { 1.wait }; 0 }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "if", + range: [ 2, 4 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 4 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "true", + valueType: Token.BooleanLiteral, + range: [ 6, 10 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 10 } + } + }, + { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 14, 15 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + property: { + type: Syntax.Identifier, + name: "wait", + range: [ 16, 20 ], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 20 } + } + }, + range: [ 14, 20 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 20 } + } + } + ], + blocklist: true, + range: [ 12, 22 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 22 } + } + } + ] + }, + range: [ 2, 22 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 22 } + } + }, + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 24, 25 ], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + } + ], + range: [ 0, 27 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + } + ], + range: [ 0, 27 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + } + }, + "{ wait(1); 0 }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "wait", + range: [ 2, 6 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 6 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + } + ] + }, + range: [ 2, 9 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 9 } + } + }, + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + } + ], + range: [ 0, 14 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + } + ], + range: [ 0, 14 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + } + }, + "max(0, 1, 2, *a, a: 5, b: 6)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + } + ], + expand: { + type: Syntax.Identifier, + name: "a", + range: [ 14, 15 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + keywords: { + a: { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 20, 21 ], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + b: { + type: Syntax.Literal, + value: "6", + valueType: Token.IntegerLiteral, + range: [ 26, 27 ], + loc: { + start: { line: 1, column: 26 }, + end: { line: 1, column: 27 } + } + } + } + }, + range: [ 0, 28 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + } + ], + range: [ 0, 28 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 28 } + } + } + }, + "max(1, 2, *a)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + } + ], + expand: { + type: Syntax.Identifier, + name: "a", + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + } + }, + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + }, + "max(1, 2, a: 5)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + } + ], + keywords: { + a: { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + } + } + }, + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + } + ], + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + } + }, + "max(0, *a, a: 3)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + } + ], + expand: { + type: Syntax.Identifier, + name: "a", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + keywords: { + a: { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 14, 15 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + } + } + }, + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + ], + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + }, + "max(0, *a)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + } + ], + expand: { + type: Syntax.Identifier, + name: "a", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + } + }, + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + } + ], + range: [ 0, 10 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 10 } + } + } + }, + "max(0, a: 1)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + } + ], + keywords: { + a: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + } + } + }, + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + ], + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + }, + "max(*a, a: 2)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [], + expand: { + type: Syntax.Identifier, + name: "a", + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + keywords: { + a: { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + } + } + }, + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + }, + "max(*a)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [], + expand: { + type: Syntax.Identifier, + name: "a", + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + }, + "max()": { // TODO: throw error + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [] + }, + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + } + ], + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + } + }, + "max(0; 1, 2; 3, 4; 5, a: 6; 7, b: 8; 9)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "max", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + } + ], + [ + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + } + ], + [ + { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 16, 17 ], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + }, + { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 19, 20 ], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + } + ] + ], + keywords: { + a: [ + { + type: Syntax.Literal, + value: "6", + valueType: Token.IntegerLiteral, + range: [ 25, 26 ], + loc: { + start: { line: 1, column: 25 }, + end: { line: 1, column: 26 } + } + }, + { + type: Syntax.Literal, + value: "7", + valueType: Token.IntegerLiteral, + range: [ 28, 29 ], + loc: { + start: { line: 1, column: 28 }, + end: { line: 1, column: 29 } + } + } + ], + b: [ + { + type: Syntax.Literal, + value: "8", + valueType: Token.IntegerLiteral, + range: [ 34, 35 ], + loc: { + start: { line: 1, column: 34 }, + end: { line: 1, column: 35 } + } + }, + { + type: Syntax.Literal, + value: "9", + valueType: Token.IntegerLiteral, + range: [ 37, 38 ], + loc: { + start: { line: 1, column: 37 }, + end: { line: 1, column: 38 } + } + } + ] + } + }, + range: [ 0, 39 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + } + ], + range: [ 0, 39 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 39 } + } + } + }, + "a = (1; 2; 3)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: [ + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + }, + "a = (var a = 1; a)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: Syntax.BlockExpression, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + init: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + range: [ 9, 14 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 14 } + } + } + ], + range: [ 5, 14 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 14 } + } + }, + { + type: Syntax.Identifier, + name: "a", + range: [ 16, 17 ], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 17 } + } + } + ], + range: [ 4, 18 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 18 } + } + }, + range: [ 0, 18 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + } + ], + range: [ 0, 18 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + } + }, + "a.midicps.min(220)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Identifier, + name: "midicps", + range: [ 2, 9 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 9 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + property: { + type: Syntax.Identifier, + name: "min", + range: [ 10, 13 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 13 } + } + }, + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "220", + valueType: Token.IntegerLiteral, + range: [ 14, 17 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 17 } + } + } + ] + }, + range: [ 0, 18 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + } + ], + range: [ 0, 18 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 18 } + } + } + }, + "Point(3, 4)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "Point", + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + property: { + type: Syntax.Identifier, + name: "new", + range: [ 5, 5 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 5 } + } + }, + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + } + ] + }, + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + } + ], + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + } + }, + "Point.new(3, 4)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "Point", + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + property: { + type: Syntax.Identifier, + name: "new", + range: [ 6, 9 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + } + ] + }, + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + } + ], + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + } + }, + "Point.new": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "Point", + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + property: { + type: Syntax.Identifier, + name: "new", + range: [ 6, 9 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 9 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + }, + "Routine {|i| i.postln}": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "Routine", + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + property: { + type: Syntax.Identifier, + name: "new", + range: [ 7, 7 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 7 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + args: { + list: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "i", + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + } + ] + }, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "i", + range: [ 14, 15 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + property: { + type: Syntax.Identifier, + name: "postln", + range: [ 16, 22 ], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + }, + range: [ 14, 22 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 22 } + } + } + ], + blocklist: true, + range: [ 9, 23 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 23 } + } + } + ] + }, + range: [ 0, 23 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + } + ], + range: [ 0, 23 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + } + }, + "Set[3, 4, 5]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "Set", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + property: { + type: Syntax.Identifier, + name: "newFrom", + range: [ 3, 3 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 3 } + } + }, + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + } + ], + range: [ 3, 12 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 12 } + } + } + ] + }, + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + ], + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + }, + "Set [1, 2].value": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "Set", + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + property: { + type: Syntax.Identifier, + name: "newFrom", + range: [ 3, 3 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 3 } + } + }, + range: [ 0, 3 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 3 } + } + }, + args: { + list: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + } + ], + range: [ 4, 10 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 10 } + } + }, + property: { + type: Syntax.Identifier, + name: "value", + range: [ 11, 16 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 16 } + } + }, + range: [ 4, 16 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 16 } + } + } + ] + }, + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + ], + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + }, + "a.(0, 1)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Identifier, + name: "value", + range: [ 2, 2 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 2 } + } + }, + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + args: { + list: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 3, 4 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + } + ] + }, + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + } + ], + range: [ 0, 8 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 8 } + } + } + }, + "a.[0]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 3, 4 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + } + ], + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + } + }, + "a.[0;1]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: [ + { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 3, 4 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 4 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + }, + "a.[..5]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: true, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: { + type: Syntax.ListIndexer, + first: null, + second: null, + last: { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [ 3, 6 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 6 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + ], + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + } + }, + "a.value(*[])": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Identifier, + name: "value", + range: [ 2, 7 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 7 } + } + }, + range: [ 0, 7 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 7 } + } + }, + args: { + list: [], + expand: { + type: Syntax.ListExpression, + elements: [], + range: [ 9, 11 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 11 } + } + } + }, + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + ], + range: [ 0, 12 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 12 } + } + } + }, + "if (x<3) {\\abc} {\\def}": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "if", + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + args: { + list: [ + { + type: Syntax.BinaryExpression, + operator: "<", + left: { + type: Syntax.Identifier, + name: "x", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + range: [ 4, 7 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 7 } + } + }, + { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.Literal, + value: "abc", + valueType: Token.SymbolLiteral, + range: [ 10, 14 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 14 } + } + } + ], + blocklist: true, + range: [ 9, 15 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 15 } + } + }, + { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.Literal, + value: "def", + valueType: Token.SymbolLiteral, + range: [ 17, 21 ], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 21 } + } + } + ], + blocklist: true, + range: [ 16, 22 ], + loc: { + start: { line: 1, column: 16 }, + end: { line: 1, column: 22 } + } + } + ] + }, + range: [ 0, 22 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + } + ], + range: [ 0, 22 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 22 } + } + } + }, + "z.do {|x| x.play }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "z", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Identifier, + name: "do", + range: [ 2, 4 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 4 } + } + }, + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + args: { + list: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "x", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + } + ] + }, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "x", + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + property: { + type: Syntax.Identifier, + name: "play", + range: [ 13, 17 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 17 } + } + }, + range: [ 11, 17 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + } + ], + blocklist: true, + range: [ 6, 19 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 19 } + } + } + ] + }, + range: [ 0, 19 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + } + ], + range: [ 0, 19 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + } + }, + "z.do #{|x| x.play }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "z", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Identifier, + name: "do", + range: [ 2, 4 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 4 } + } + }, + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + args: { + list: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "x", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + } + ] + }, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "x", + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + property: { + type: Syntax.Identifier, + name: "play", + range: [ 13, 17 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 17 } + } + }, + range: [ 11, 17 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + } + ], + closed: true, + blocklist: true, + range: [ 6, 19 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 19 } + } + } + ] + }, + range: [ 0, 19 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + } + ], + range: [ 0, 19 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 19 } + } + } + }, + "loop { 'x'.postln; 1.wait }": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.Identifier, + name: "loop", + range: [ 0, 4 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 4 } + } + }, + args: { + list: [ + { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Literal, + value: q("x"), + valueType: Token.SymbolLiteral, + range: [ 7, 10 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 10 } + } + }, + property: { + type: Syntax.Identifier, + name: "postln", + range: [ 11, 17 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 17 } + } + }, + range: [ 7, 17 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 17 } + } + }, + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 19, 20 ], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 20 } + } + }, + property: { + type: Syntax.Identifier, + name: "wait", + range: [ 21, 25 ], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 25 } + } + }, + range: [ 19, 25 ], + loc: { + start: { line: 1, column: 19 }, + end: { line: 1, column: 25 } + } + } + ], + blocklist: true, + range: [ 5, 27 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 27 } + } + } + ] + }, + range: [ 0, 27 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + } + ], + range: [ 0, 27 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + } + }, + "~a = 0": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.GlobalExpression, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + right: { + type: Syntax.Literal, + value: "0", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + } + ], + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + } + }, + "()": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.ObjectExpression, + elements: [], + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + } + ], + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + } + }, + "( \\answer : 42 )": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.ObjectExpression, + elements: [ + { + type: Syntax.Literal, + value: "answer", + valueType: Token.SymbolLiteral, + range: [ 2, 9 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 9 } + } + }, + { + type: Syntax.Literal, + value: "42", + valueType: Token.IntegerLiteral, + range: [ 12, 14 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + } + ], + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + ], + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + }, + "x = ( a: 1, b: 2, c: 3 )": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "x", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: Syntax.ObjectExpression, + elements: [ + { + type: Syntax.Label, + name: "a", + range: [ 6, 8 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 8 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + { + type: Syntax.Label, + name: "b", + range: [ 12, 14 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + }, + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 15, 16 ], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + { + type: Syntax.Label, + name: "c", + range: [ 18, 20 ], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 20 } + } + }, + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 21, 22 ], + loc: { + start: { line: 1, column: 21 }, + end: { line: 1, column: 22 } + } + } + ], + range: [ 4, 24 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 24 } + } + }, + range: [ 0, 24 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + } + ], + range: [ 0, 24 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 24 } + } + } + }, + "x = ( a : 1, b : 2, c : 3 )": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "x", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: Syntax.ObjectExpression, + elements: [ + { + type: Syntax.Identifier, + name: "a", + range: [ 6, 7 ], + loc: { + start: { line: 1, column: 6 }, + end: { line: 1, column: 7 } + } + }, + { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 10, 11 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 11 } + } + }, + { + type: Syntax.Identifier, + name: "b", + range: [ 13, 14 ], + loc: { + start: { line: 1, column: 13 }, + end: { line: 1, column: 14 } + } + }, + { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 17, 18 ], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + }, + { + type: Syntax.Identifier, + name: "c", + range: [ 20, 21 ], + loc: { + start: { line: 1, column: 20 }, + end: { line: 1, column: 21 } + } + }, + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 24, 25 ], + loc: { + start: { line: 1, column: 24 }, + end: { line: 1, column: 25 } + } + } + ], + range: [ 4, 27 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 27 } + } + }, + range: [ 0, 27 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + } + ], + range: [ 0, 27 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 27 } + } + } + }, + "x = (1 + 2: 3, 4: 5)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "x", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: Syntax.ObjectExpression, + elements: [ + { + type: Syntax.BinaryExpression, + operator: "+", + left: { + type: Syntax.Literal, + value: "1", + valueType: Token.IntegerLiteral, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + right: { + type: Syntax.Literal, + value: "2", + valueType: Token.IntegerLiteral, + range: [ 9, 10 ], + loc: { + start: { line: 1, column: 9 }, + end: { line: 1, column: 10 } + } + }, + range: [ 5, 10 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 10 } + } + }, + { + type: Syntax.Literal, + value: "3", + valueType: Token.IntegerLiteral, + range: [ 12, 13 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 13 } + } + }, + { + type: Syntax.Literal, + value: "4", + valueType: Token.IntegerLiteral, + range: [ 15, 16 ], + loc: { + start: { line: 1, column: 15 }, + end: { line: 1, column: 16 } + } + }, + { + type: Syntax.Literal, + value: "5", + valueType: Token.IntegerLiteral, + range: [ 18, 19 ], + loc: { + start: { line: 1, column: 18 }, + end: { line: 1, column: 19 } + } + } + ], + range: [ 4, 20 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 20 } + } + }, + range: [ 0, 20 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + } + ], + range: [ 0, 20 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + } + }, + "f = _ + _": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "f", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + right: { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.Identifier, + name: "_0", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + { + type: Syntax.Identifier, + name: "_1", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + } + ] + }, + body: [ + { + type: Syntax.BinaryExpression, + operator: "+", + left: { + type: Syntax.Identifier, + name: "_0", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + right: { + type: Syntax.Identifier, + name: "_1", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + range: [ 4, 9 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + } + ], + partial: true, + range: [ 4, 9 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 9 } + } + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + }, + "[_, _]": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.FunctionExpression, + args: { + list: [ + { + type: Syntax.Identifier, + name: "_0", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + { + type: Syntax.Identifier, + name: "_1", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + } + ] + }, + body: [ + { + type: Syntax.ListExpression, + elements: [ + { + type: Syntax.Identifier, + name: "_0", + range: [ 1, 2 ], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 2 } + } + }, + { + type: Syntax.Identifier, + name: "_1", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + } + ], + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + } + ], + partial: true, + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + } + ], + range: [ 0, 6 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 6 } + } + } + }, + "var a; var b;": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + } + ], + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "b", + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + }, + range: [ 11, 12 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 12 } + } + } + ], + range: [ 7, 12 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 12 } + } + } + ], + range: [ 0, 13 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 13 } + } + } + }, + "var a; a = 10;": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + } + ], + range: [ 0, 5 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 5 } + } + }, + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "a", + range: [ 7, 8 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 8 } + } + }, + right: { + type: Syntax.Literal, + value: "10", + valueType: Token.IntegerLiteral, + range: [ 11, 13 ], + loc: { + start: { line: 1, column: 11 }, + end: { line: 1, column: 13 } + } + }, + range: [ 7, 13 ], + loc: { + start: { line: 1, column: 7 }, + end: { line: 1, column: 13 } + } + } + ], + range: [ 0, 14 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 14 } + } + } + }, + "(var a; a = 10;)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + }, + range: [ 5, 6 ], + loc: { + start: { line: 1, column: 5 }, + end: { line: 1, column: 6 } + } + } + ], + range: [ 1, 6 ], + loc: { + start: { line: 1, column: 1 }, + end: { line: 1, column: 6 } + } + }, + { + type: Syntax.AssignmentExpression, + operator: "=", + left: { + type: Syntax.Identifier, + name: "a", + range: [ 8, 9 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 9 } + } + }, + right: { + type: Syntax.Literal, + value: "10", + valueType: Token.IntegerLiteral, + range: [ 12, 14 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 14 } + } + }, + range: [ 8, 14 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 14 } + } + } + ], + range: [ 0, 16 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 16 } + } + } + }, + "var a = { var a; a }; a": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 4, 5 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 5 } + } + }, + init: { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.VariableDeclaration, + kind: "var", + declarations: [ + { + type: Syntax.VariableDeclarator, + id: { + type: Syntax.Identifier, + name: "a", + range: [ 14, 15 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + }, + range: [ 14, 15 ], + loc: { + start: { line: 1, column: 14 }, + end: { line: 1, column: 15 } + } + } + ], + range: [ 10, 15 ], + loc: { + start: { line: 1, column: 10 }, + end: { line: 1, column: 15 } + } + }, + { + type: Syntax.Identifier, + name: "a", + range: [ 17, 18 ], + loc: { + start: { line: 1, column: 17 }, + end: { line: 1, column: 18 } + } + } + ], + range: [ 8, 20 ], + loc: { + start: { line: 1, column: 8 }, + end: { line: 1, column: 20 } + } + }, + range: [ 4, 20 ], + loc: { + start: { line: 1, column: 4 }, + end: { line: 1, column: 20 } + } + } + ], + range: [ 0, 20 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + }, + { + type: Syntax.Identifier, + name: "a", + range: [ 22, 23 ], + loc: { + start: { line: 1, column: 22 }, + end: { line: 1, column: 23 } + } + } + ], + range: [ 0, 23 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 23 } + } + } + }, + "thisProcess.platform;": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.ThisExpression, + name: "thisProcess", + range: [ 0, 11 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 11 } + } + }, + property: { + type: Syntax.Identifier, + name: "platform", + range: [ 12, 20 ], + loc: { + start: { line: 1, column: 12 }, + end: { line: 1, column: 20 } + } + }, + range: [ 0, 20 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 20 } + } + } + ], + range: [ 0, 21 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 21 } + } + } + }, + "a.(Class)": { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.CallExpression, + callee: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Identifier, + name: "a", + range: [ 0, 1 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 1 } + } + }, + property: { + type: Syntax.Identifier, + name: "value", + range: [ 2, 2 ], + loc: { + start: { line: 1, column: 2 }, + end: { line: 1, column: 2 } + } + }, + range: [ 0, 2 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 2 } + } + }, + args: { + list: [ + { + type: Syntax.Identifier, + name: "Class", + range: [ 3, 8 ], + loc: { + start: { line: 1, column: 3 }, + end: { line: 1, column: 8 } + } + } + ] + }, + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + ], + range: [ 0, 9 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 9 } + } + } + }, + '"#{69.midicps}"': { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Literal, + value: "69", + valueType: Token.IntegerLiteral + }, + property: { + type: Syntax.Identifier, + name: "midicps", + } + }, + property: { + type: Syntax.Identifier, + name: "asString", + }, + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + } + ], + range: [ 0, 15 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 15 } + } + } + }, + '"\\#{}##{{69.midicps}.value}#{}hz"': { + ast: { + type: Syntax.Program, + body: [ + { + type: Syntax.BinaryExpression, + operator: "++", + left: { + type: Syntax.BinaryExpression, + operator: "++", + left: { + type: Syntax.Literal, + value: "'\\#{}#'", + valueType: Token.SymbolLiteral + }, + right: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.FunctionExpression, + body: [ + { + type: Syntax.MemberExpression, + computed: false, + object: { + type: Syntax.Literal, + value: "69", + valueType: Token.IntegerLiteral + }, + property: { + type: Syntax.Identifier, + name: "midicps" + } + } + ] + }, + property: { + type: Syntax.Identifier, + name: "value" + } + }, + property: { + type: Syntax.Identifier, + name: "asString" + } + } + }, + right: { + type: Syntax.Literal, + value: "'hz'", + valueType: Token.SymbolLiteral + }, + range: [ 0, 33 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 33 } + } + } + ], + range: [ 0, 33 ], + loc: { + start: { line: 1, column: 0 }, + end: { line: 1, column: 33 } + } + } + }, + }; + + sc.test.parser = { + cases: cases + }; + +})(sc); diff --git a/src/sc/test/related.json b/src/sc/test/related.json index 0967ef4..32cf1cd 100644 --- a/src/sc/test/related.json +++ b/src/sc/test/related.json @@ -1 +1,5 @@ -{} +{ + "sc/test/parser-test-case": [ + "sc/lang/parser" + ] +}