UNPKG

walt-compiler

Version:

Alternative syntax for WebAssembly text format

1,140 lines (1,008 loc) 204 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.Walt = {}))); }(this, (function (exports) { 'use strict'; var immutable = extend; var hasOwnProperty = Object.prototype.hasOwnProperty; function extend() { var target = {}; for (var i = 0; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; } const identity = id => id; function map(visitors) { function mapper(input) { if (!Array.isArray(input)) { throw new Error('Transform must be used on an Array. Received ' + JSON.stringify(input)); } const visitor = (() => { const [node] = input; if (node.Type in visitors && typeof visitors[node.Type] === 'function') { return visitors[node.Type]; } return identity; })(); if (visitor.length === 2) { return visitor(input, mapper); } const [node, ...rest] = visitor(input); const params = node.params.filter(Boolean).map(child => mapper([child, ...rest])); return immutable(node, { params }); } return mapper; } // This should maybe be it's own module. function mapNode$2(visitor) { const nodeMapper = node => { if (node == null) { return node; } const mappingFunction = (() => { if ('*' in visitor && typeof visitor['*'] === 'function') { return visitor['*']; } if (node.Type in visitor && typeof visitor[node.Type] === 'function') { return visitor[node.Type]; } return identity; })(); if (mappingFunction.length === 2) { return mappingFunction(node, nodeMapper); } const mappedNode = mappingFunction(node); const params = mappedNode.params.map(nodeMapper); return immutable(mappedNode, { params }); }; return nodeMapper; } var mapNode_1$1 = { map, mapNode: mapNode$2 }; var mapNode = mapNode_1$1; var mapNode_1 = mapNode.map; var mapNode_2 = mapNode.mapNode; // Dead simple AST walker, takes a visitor object and calls all methods for // appropriate node Types. var walkNode$2 = function (visitor) { const walkNode = node => { if (node == null) { return node; } const { params } = node; const mappingFunction = (() => { if ('*' in visitor && typeof visitor['*'] === 'function') { return visitor['*']; } if (node.Type in visitor && typeof visitor[node.Type] === 'function') { return visitor[node.Type]; } return () => node; })(); if (mappingFunction.length === 2) { mappingFunction(node, walkNode); return node; } mappingFunction(node); params.forEach(walkNode); return node; }; return walkNode; }; var walkNode = walkNode$2; /** * Copyright 2013-2015, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ var invariant = function (condition, format, a, b, c, d, e, f) { if (format === undefined) { throw new Error('invariant requires an error message argument'); } if (!condition) { var error; if (format === undefined) { error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); } else { var args = [a, b, c, d, e, f]; var argIndex = 0; error = new Error(format.replace(/%s/g, function () { return args[argIndex++]; })); error.name = 'Invariant Violation'; } error.framesToPop = 1; // we don't care about invariant's own frame throw error; } }; var invariant_1 = invariant; var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function unwrapExports (x) { return x && x.__esModule ? x['default'] : x; } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var waltSyntax = createCommonjsModule(function (module, exports) { (function (global, factory) { factory(exports); })(commonjsGlobal, function (exports) { const tokens = { whitespace: /[ \t]+/, comment: [{ match: /\/\/.*?$/ }, { match: /\/\*[^]*?\*\//, lineBreaks: true }], number: [{ match: /0[xX][0-9a-fA-F]+/ }, { match: /0[oO][0-9]+/ }, { match: /0[bB][01]+/ }, { match: /(?:[0-9]+(?:\.[0-9]+)?e-?[0-9]+)/ }, { match: /[0-9]+\.[0-9]+|[0-9]+/ }], char: [{ match: /'(?:\\['\\bfnrtv0]|[^'\\\n])'/, value: x => x.slice(1, -1) }], string: [{ match: /"(?:\\["\\rn]|[^"\\\n])*?"/, value: x => x.slice(1, -1) }, { match: /'(?:\\['\\bfnrtv0]|[^'\\\n])*?'/, value: x => x.slice(1, -1) }, { match: /`(?:\\['\\bfnrtv0]|[^'\\])*?`/, value: x => x.slice(1, -1) }], identifier: { match: /[A-Za-z_$][A-Za-z0-9_$]*/, keywords: { keyword: [ // EcmaScript 'break', 'if', 'else', 'import', 'as', 'from', 'export', 'return', 'switch', 'case', 'default', 'const', 'let', 'for', 'continue', 'do', 'while', 'throw', 'function', // s-expression 'global', 'module', 'type', 'lambda'], type: ['i32', 'i64', 'f32', 'f64', 'bool'] } }, punctuator: ['+', '++', '-', '--', '>>', '>>>', '<<', '=', '==', '+=', '-=', '=>', '<=', '>=', '!=', '%', '*', '/', '^', '&', '~', '|', '!', '**', ':', '(', ')', '.', '{', '}', ',', '[', ']', ';', '>', '<', '?', '||', '&&', '{', '}', '...'], newline: { match: /(?:\r\n|\r|\n)/, lineBreaks: true } }; // Main Program const Program = 'Program'; const Keyword = 'Keyword'; const Export = 'Export'; const Import = 'Import'; const Statement = 'Statement'; const IfThenElse = 'IfThenElse'; const Select = 'Select'; const Else = 'Else'; const UnaryExpression = 'UnaryExpression'; const BinaryExpression = 'BinaryExpression'; const TernaryExpression = 'TernaryExpression'; const NumberLiteral = 'NumberLiteral'; const StringLiteral = 'StringLiteral'; const CharacterLiteral = 'CharacterLiteral'; const Punctuator = 'Punctuator'; const Identifier = 'Identifier'; const ArraySubscript = 'ArraySubscript'; const Constant = 'Constant'; const Type = 'Type'; const ArrayType = 'ArrayType'; const DeclType = 'DeclType'; const GenericType = 'GenericType'; const UserType = 'UserType'; const FunctionType = 'FunctionType'; const Declaration = 'Declaration'; const StaticDeclaration = 'StaticDeclaration'; const StaticValueList = 'StaticValueList'; const ImmutableDeclaration = 'ImmutableDeclaration'; const FunctionDeclaration = 'FunctionDeclaration'; const ArrayDeclaration = 'ArrayDeclaration'; const IndirectFunctionCall = 'IndirectFunctionCall'; const FunctionCall = 'FunctionCall'; const Loop = 'Loop'; const MemoryAssignment = 'MemoryAssignment'; const Assignment = 'Assignment'; const AssignmentExpression = 'AssignmentExpression'; const Param = 'Param'; const Typedef = 'Typedef'; const Struct = 'Struct'; const UnionType = 'UnionType'; const ReturnStatement = 'ReturnStatement'; const Sequence = 'Sequence'; const ObjectLiteral = 'ObjectLiteral'; const Pair = 'Pair'; const TypeCast = 'TypeCast'; const Break = 'Break'; const Comment = 'Comment'; const Sizeof = 'Sizeof'; const Spread = 'Spread'; const Closure = 'Closure'; const Noop = 'Noop'; const ClosureType = 'ClosureType'; const Block = 'Block'; const ObjectField = 'ObjectField'; const FunctionIndex = 'FunctionIndex'; const FunctionIdentifier = 'FunctionIdentifier'; const FunctionPointer = 'FunctionPointer'; const FunctionArguments = 'FunctionArguments'; const FunctionResult = 'FunctionResult'; const FunctionLocals = 'FunctionLocals'; const NativeMethod = 'NativeMethod'; const Unreachable = 'Unreachable'; const Access = 'Access'; const i32 = 'i32'; const f32 = 'f32'; const i64 = 'i64'; const f64 = 'f64'; const Memory = 'Memory'; const Table = 'Table'; const bool = 'bool'; exports.Program = Program; exports.Keyword = Keyword; exports.Export = Export; exports.Import = Import; exports.Statement = Statement; exports.IfThenElse = IfThenElse; exports.Select = Select; exports.Else = Else; exports.UnaryExpression = UnaryExpression; exports.BinaryExpression = BinaryExpression; exports.TernaryExpression = TernaryExpression; exports.NumberLiteral = NumberLiteral; exports.StringLiteral = StringLiteral; exports.CharacterLiteral = CharacterLiteral; exports.Punctuator = Punctuator; exports.Identifier = Identifier; exports.ArraySubscript = ArraySubscript; exports.Constant = Constant; exports.Type = Type; exports.ArrayType = ArrayType; exports.DeclType = DeclType; exports.GenericType = GenericType; exports.UserType = UserType; exports.FunctionType = FunctionType; exports.Declaration = Declaration; exports.StaticDeclaration = StaticDeclaration; exports.StaticValueList = StaticValueList; exports.ImmutableDeclaration = ImmutableDeclaration; exports.FunctionDeclaration = FunctionDeclaration; exports.ArrayDeclaration = ArrayDeclaration; exports.IndirectFunctionCall = IndirectFunctionCall; exports.FunctionCall = FunctionCall; exports.Loop = Loop; exports.MemoryAssignment = MemoryAssignment; exports.Assignment = Assignment; exports.AssignmentExpression = AssignmentExpression; exports.Param = Param; exports.Typedef = Typedef; exports.Struct = Struct; exports.UnionType = UnionType; exports.ReturnStatement = ReturnStatement; exports.Sequence = Sequence; exports.ObjectLiteral = ObjectLiteral; exports.Pair = Pair; exports.TypeCast = TypeCast; exports.Break = Break; exports.Comment = Comment; exports.Sizeof = Sizeof; exports.Spread = Spread; exports.Closure = Closure; exports.Noop = Noop; exports.ClosureType = ClosureType; exports.Block = Block; exports.ObjectField = ObjectField; exports.FunctionIndex = FunctionIndex; exports.FunctionIdentifier = FunctionIdentifier; exports.FunctionPointer = FunctionPointer; exports.FunctionArguments = FunctionArguments; exports.FunctionResult = FunctionResult; exports.FunctionLocals = FunctionLocals; exports.NativeMethod = NativeMethod; exports.Unreachable = Unreachable; exports.Access = Access; exports.i32 = i32; exports.f32 = f32; exports.i64 = i64; exports.f64 = f64; exports.Memory = Memory; exports.Table = Table; exports.bool = bool; exports.builtinTypes = { i32, f32, i64, f64, Memory, Table, bool }; exports.statements = { // Main Program Program, // Syntax Nodes Export, Import, IfThenElse, Else, Declaration, ImmutableDeclaration, FunctionDeclaration, ArrayDeclaration, Loop, MemoryAssignment, Assignment, Typedef, Struct, UnionType, ReturnStatement, Sequence, ObjectLiteral, Pair, Break, Comment, Sizeof, Spread, Noop, Block, Unreachable }; exports.default = { // Main Program Program, // Syntax Nodes Keyword, Export, Import, Statement, IfThenElse, Select, Else, UnaryExpression, BinaryExpression, TernaryExpression, NumberLiteral, StringLiteral, CharacterLiteral, Punctuator, Identifier, ArraySubscript, Constant, Type, ArrayType, DeclType, GenericType, UserType, FunctionType, Declaration, ImmutableDeclaration, FunctionDeclaration, ArrayDeclaration, StaticDeclaration, StaticValueList, IndirectFunctionCall, FunctionCall, Loop, MemoryAssignment, Assignment, AssignmentExpression, Param, Typedef, Struct, UnionType, ReturnStatement, Sequence, ObjectLiteral, Pair, TypeCast, Break, Comment, Sizeof, Spread, Closure, Access, Noop, // Semantic Nodes ClosureType, Block, ObjectField, FunctionIndex, FunctionIdentifier, FunctionPointer, FunctionArguments, FunctionResult, FunctionLocals, // Natives NativeMethod, Unreachable }; exports.tokens = tokens; Object.defineProperty(exports, '__esModule', { value: true }); }); }); var Syntax = unwrapExports(waltSyntax); var waltSyntax_1 = waltSyntax.tokens; var waltSyntax_2 = waltSyntax.semantics; var waltSyntax_3 = waltSyntax.builtinTypes; var waltSyntax_4 = waltSyntax.statements; var waltSyntax_5 = waltSyntax.i32; var waltSyntax_6 = waltSyntax.f32; var waltSyntax_7 = waltSyntax.i64; var waltSyntax_8 = waltSyntax.f64; var moo = createCommonjsModule(function (module) { (function (root, factory) { if (typeof undefined === 'function' && undefined.amd) { undefined([], factory); /* global define */ } else if ('object' === 'object' && module.exports) { module.exports = factory(); } else { root.moo = factory(); } })(commonjsGlobal, function () { var hasOwnProperty = Object.prototype.hasOwnProperty; // polyfill assign(), so we support IE9+ var assign = typeof Object.assign === 'function' ? Object.assign : // https://tc39.github.io/ecma262/#sec-object.assign function (target, sources) { if (target == null) { throw new TypeError('Target cannot be null or undefined'); } target = Object(target); for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; if (source == null) continue; for (var key in source) { if (hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var hasSticky = typeof new RegExp().sticky === 'boolean'; /***************************************************************************/ function isRegExp(o) { return o && o.constructor === RegExp; } function isObject(o) { return o && typeof o === 'object' && o.constructor !== RegExp && !Array.isArray(o); } function reEscape(s) { return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); } function reGroups(s) { var re = new RegExp('|' + s); return re.exec('').length - 1; } function reCapture(s) { return '(' + s + ')'; } function reUnion(regexps) { var source = regexps.map(function (s) { return "(?:" + s + ")"; }).join('|'); return "(?:" + source + ")"; } function regexpOrLiteral(obj) { if (typeof obj === 'string') { return '(?:' + reEscape(obj) + ')'; } else if (isRegExp(obj)) { // TODO: consider /u support if (obj.ignoreCase) { throw new Error('RegExp /i flag not allowed'); } if (obj.global) { throw new Error('RegExp /g flag is implied'); } if (obj.sticky) { throw new Error('RegExp /y flag is implied'); } if (obj.multiline) { throw new Error('RegExp /m flag is implied'); } return obj.source; } else { throw new Error('not a pattern: ' + obj); } } function objectToRules(object) { var keys = Object.getOwnPropertyNames(object); var result = []; for (var i = 0; i < keys.length; i++) { var key = keys[i]; var thing = object[key]; var rules = Array.isArray(thing) ? thing : [thing]; var match = []; rules.forEach(function (rule) { if (isObject(rule)) { if (match.length) result.push(ruleOptions(key, match)); result.push(ruleOptions(key, rule)); match = []; } else { match.push(rule); } }); if (match.length) result.push(ruleOptions(key, match)); } return result; } function arrayToRules(array) { var result = []; for (var i = 0; i < array.length; i++) { var obj = array[i]; if (!obj.name) { throw new Error('Rule has no name: ' + JSON.stringify(obj)); } result.push(ruleOptions(obj.name, obj)); } return result; } function ruleOptions(name, obj) { if (typeof obj !== 'object' || Array.isArray(obj) || isRegExp(obj)) { obj = { match: obj }; } // nb. error implies lineBreaks var options = assign({ tokenType: name, lineBreaks: !!obj.error, pop: false, next: null, push: null, error: false, value: null, getType: null }, obj); // convert to array var match = options.match; options.match = Array.isArray(match) ? match : match ? [match] : []; options.match.sort(function (a, b) { return isRegExp(a) && isRegExp(b) ? 0 : isRegExp(b) ? -1 : isRegExp(a) ? +1 : b.length - a.length; }); if (options.keywords) { options.getType = keywordTransform(options.keywords); } return options; } function compileRules(rules, hasStates) { rules = Array.isArray(rules) ? arrayToRules(rules) : objectToRules(rules); var errorRule = null; var groups = []; var parts = []; for (var i = 0; i < rules.length; i++) { var options = rules[i]; if (options.error) { if (errorRule) { throw new Error("Multiple error rules not allowed: (for token '" + options.tokenType + "')"); } errorRule = options; } // skip rules with no match if (options.match.length === 0) { continue; } groups.push(options); // convert to RegExp var pat = reUnion(options.match.map(regexpOrLiteral)); // validate var regexp = new RegExp(pat); if (regexp.test("")) { throw new Error("RegExp matches empty string: " + regexp); } var groupCount = reGroups(pat); if (groupCount > 0) { throw new Error("RegExp has capture groups: " + regexp + "\nUse (?: … ) instead"); } if (!hasStates && (options.pop || options.push || options.next)) { throw new Error("State-switching options are not allowed in stateless lexers (for token '" + options.tokenType + "')"); } // try and detect rules matching newlines if (!options.lineBreaks && regexp.test('\n')) { throw new Error('Rule should declare lineBreaks: ' + regexp); } // store regex parts.push(reCapture(pat)); } var suffix = hasSticky ? '' : '|(?:)'; var flags = hasSticky ? 'ym' : 'gm'; var combined = new RegExp(reUnion(parts) + suffix, flags); return { regexp: combined, groups: groups, error: errorRule }; } function compile(rules) { var result = compileRules(rules); return new Lexer({ start: result }, 'start'); } function compileStates(states, start) { var keys = Object.getOwnPropertyNames(states); if (!start) start = keys[0]; var map = Object.create(null); for (var i = 0; i < keys.length; i++) { var key = keys[i]; map[key] = compileRules(states[key], true); } for (var i = 0; i < keys.length; i++) { var groups = map[keys[i]].groups; for (var j = 0; j < groups.length; j++) { var g = groups[j]; var state = g && (g.push || g.next); if (state && !map[state]) { throw new Error("Missing state '" + state + "' (in token '" + g.tokenType + "' of state '" + keys[i] + "')"); } if (g && g.pop && +g.pop !== 1) { throw new Error("pop must be 1 (in token '" + g.tokenType + "' of state '" + keys[i] + "')"); } } } return new Lexer(map, start); } function keywordTransform(map) { var reverseMap = Object.create(null); var byLength = Object.create(null); var types = Object.getOwnPropertyNames(map); for (var i = 0; i < types.length; i++) { var tokenType = types[i]; var item = map[tokenType]; var keywordList = Array.isArray(item) ? item : [item]; keywordList.forEach(function (keyword) { (byLength[keyword.length] = byLength[keyword.length] || []).push(keyword); if (typeof keyword !== 'string') { throw new Error("keyword must be string (in keyword '" + tokenType + "')"); } reverseMap[keyword] = tokenType; }); } // fast string lookup // https://jsperf.com/string-lookups function str(x) { return JSON.stringify(x); } var source = ''; source += '(function(value) {\n'; source += 'switch (value.length) {\n'; for (var length in byLength) { var keywords = byLength[length]; source += 'case ' + length + ':\n'; source += 'switch (value) {\n'; keywords.forEach(function (keyword) { var tokenType = reverseMap[keyword]; source += 'case ' + str(keyword) + ': return ' + str(tokenType) + '\n'; }); source += '}\n'; } source += '}\n'; source += '})'; return eval(source); // getType } /***************************************************************************/ var Lexer = function (states, state) { this.startState = state; this.states = states; this.buffer = ''; this.stack = []; this.reset(); }; Lexer.prototype.reset = function (data, info) { this.buffer = data || ''; this.index = 0; this.line = info ? info.line : 1; this.col = info ? info.col : 1; this.setState(info ? info.state : this.startState); return this; }; Lexer.prototype.save = function () { return { line: this.line, col: this.col, state: this.state }; }; Lexer.prototype.setState = function (state) { if (!state || this.state === state) return; this.state = state; var info = this.states[state]; this.groups = info.groups; this.error = info.error || { lineBreaks: true, shouldThrow: true }; this.re = info.regexp; }; Lexer.prototype.popState = function () { this.setState(this.stack.pop()); }; Lexer.prototype.pushState = function (state) { this.stack.push(this.state); this.setState(state); }; Lexer.prototype._eat = hasSticky ? function (re) { // assume re is /y return re.exec(this.buffer); } : function (re) { // assume re is /g var match = re.exec(this.buffer); // will always match, since we used the |(?:) trick if (match[0].length === 0) { return null; } return match; }; Lexer.prototype._getGroup = function (match) { if (match === null) { return -1; } var groupCount = this.groups.length; for (var i = 0; i < groupCount; i++) { if (match[i + 1] !== undefined) { return i; } } throw new Error('oops'); }; function tokenToString() { return this.value; } Lexer.prototype.next = function () { var re = this.re; var buffer = this.buffer; var index = re.lastIndex = this.index; if (index === buffer.length) { return; // EOF } var match = this._eat(re); var i = this._getGroup(match); var group, text; if (i === -1) { group = this.error; // consume rest of buffer text = buffer.slice(index); } else { text = match[0]; group = this.groups[i]; } // count line breaks var lineBreaks = 0; if (group.lineBreaks) { var matchNL = /\n/g; var nl = 1; if (text === '\n') { lineBreaks = 1; } else { while (matchNL.exec(text)) { lineBreaks++;nl = matchNL.lastIndex; } } } var token = { type: group.getType && group.getType(text) || group.tokenType, value: group.value ? group.value(text) : text, text: text, toString: tokenToString, offset: index, lineBreaks: lineBreaks, line: this.line, col: this.col // nb. adding more props to token object will make V8 sad! };var size = text.length; this.index += size; this.line += lineBreaks; if (lineBreaks !== 0) { this.col = size - nl + 1; } else { this.col += size; } // throw, if no rule with {error: true} if (group.shouldThrow) { throw new Error(this.formatError(token, "invalid syntax")); } if (group.pop) this.popState();else if (group.push) this.pushState(group.push);else if (group.next) this.setState(group.next); return token; }; if (typeof Symbol !== 'undefined' && Symbol.iterator) { var LexerIterator = function (lexer) { this.lexer = lexer; }; LexerIterator.prototype.next = function () { var token = this.lexer.next(); return { value: token, done: !token }; }; LexerIterator.prototype[Symbol.iterator] = function () { return this; }; Lexer.prototype[Symbol.iterator] = function () { return new LexerIterator(this); }; } Lexer.prototype.formatError = function (token, message) { var value = token.value; var index = token.offset; var eol = token.lineBreaks ? value.indexOf('\n') : value.length; var start = Math.max(0, index - token.col + 1); var firstLine = this.buffer.substring(start, index + eol); message += " at line " + token.line + " col " + token.col + ":\n\n"; message += " " + firstLine + "\n"; message += " " + Array(token.col).join(" ") + "^"; return message; }; Lexer.prototype.clone = function () { return new Lexer(this.states, this.state); }; Lexer.prototype.has = function (tokenType) { for (var s in this.states) { var groups = this.states[s].groups; for (var i = 0; i < groups.length; i++) { var group = groups[i]; if (group.tokenType === tokenType) return true; if (group.keywords && hasOwnProperty.call(group.keywords, tokenType)) { return true; } } } return false; }; return { compile: compile, states: compileStates, error: Object.freeze({ error: true }) }; }); }); var slice = Array.prototype.slice; var toArray = function (a) { return slice.call(a); }; var tail = function (a) { return slice.call(a, 1); }; // fn, [value] -> fn //-- create a curried function, incorporating any number of //-- pre-existing arguments (e.g. if you're further currying a function). var createFn = function (fn, args, totalArity) { var remainingArity = totalArity - args.length; switch (remainingArity) { case 0: return function () { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 1: return function (a) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 2: return function (a, b) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 3: return function (a, b, c) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 4: return function (a, b, c, d) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 5: return function (a, b, c, d, e) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 6: return function (a, b, c, d, e, f) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 7: return function (a, b, c, d, e, f, g) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 8: return function (a, b, c, d, e, f, g, h) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 9: return function (a, b, c, d, e, f, g, h, i) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; case 10: return function (a, b, c, d, e, f, g, h, i, j) { return processInvocation(fn, concatArgs(args, arguments), totalArity); }; default: return createEvalFn(fn, args, remainingArity); } }; // [value], arguments -> [value] //-- concat new arguments onto old arguments array var concatArgs = function (args1, args2) { return args1.concat(toArray(args2)); }; // fn, [value], int -> fn //-- create a function of the correct arity by the use of eval, //-- so that curry can handle functions of any arity var createEvalFn = function (fn, args, arity) { var argList = makeArgList(arity); //-- hack for IE's faulty eval parsing -- http://stackoverflow.com/a/6807726 var fnStr = 'false||' + 'function(' + argList + '){ return processInvocation(fn, concatArgs(args, arguments)); }'; return eval(fnStr); }; var makeArgList = function (len) { var a = []; for (var i = 0; i < len; i += 1) a.push('a' + i.toString()); return a.join(','); }; var trimArrLength = function (arr, length) { if (arr.length > length) return arr.slice(0, length);else return arr; }; // fn, [value] -> value //-- handle a function being invoked. //-- if the arg list is long enough, the function will be called //-- otherwise, a new curried version is created. var processInvocation = function (fn, argsArr, totalArity) { argsArr = trimArrLength(argsArr, totalArity); if (argsArr.length === totalArity) return fn.apply(null, argsArr); return createFn(fn, argsArr, totalArity); }; // fn -> fn //-- curries a function! <3 var curry = function (fn) { return createFn(fn, [], fn.length); }; // num, fn -> fn //-- curries a function to a certain arity! <33 curry.to = curry(function (arity, fn) { return createFn(fn, [], arity); }); // num, fn -> fn //-- adapts a function in the context-first style //-- to a curried version. <3333 curry.adaptTo = curry(function (num, fn) { return curry.to(num, function (context) { var args = tail(arguments).concat(context); return fn.apply(this, args); }); }); // fn -> fn //-- adapts a function in the context-first style to //-- a curried version. <333 curry.adapt = function (fn) { return curry.adaptTo(fn.length, fn); }; var curry_1 = curry; // Custom Walt Grammar Generator function id(x) { return x[0]; } function grammar() { const lexer = this.lexer; const Syntax = this.Syntax; const { extendNode, drop, nth, nuller, nonEmpty, add, flatten, compose } = this.helpers; const { node, binary, constant, identifier, statement, unary, ternary, subscript, access, fun, declaration, call, struct, result, string, char, typedef, voidFun, type, arrayType, assignment, forLoop, whileLoop, typeGeneric, spread, builtinDecl, assignmentExpr, addressOf } = this.nodes(lexer); return { Lexer: lexer, ParserRules: [{ "name": "_$ebnf$1", "symbols": [] }, { "name": "_$ebnf$1", "symbols": ["_$ebnf$1", "wschar"], "postprocess": function (d) { return d[0].concat([d[1]]); } }, { "name": "_", "symbols": ["_$ebnf$1"], "postprocess": function (d) { return null; } }, { "name": "__$ebnf$1", "symbols": ["wschar"] }, { "name": "__$ebnf$1", "symbols": ["__$ebnf$1", "wschar"], "postprocess": function (d) { return d[0].concat([d[1]]); } }, { "name": "__", "symbols": ["__$ebnf$1"], "postprocess": function (d) { return null; } }, { "name": "wschar", "symbols": [/[ \t\n\v\f]/], "postprocess": id }, { "name": "Struct", "symbols": ["TYPE", "__", "Identifier", "_", "EQUALS", "_", "Union", "SEPARATOR"], "postprocess": struct }, { "name": "Struct", "symbols": ["TYPE", "__", "Identifier", "_", "EQUALS", "_", "NativeType", "SEPARATOR"], "postprocess": struct }, { "name": "Union", "symbols": ["StructDefinition"], "postprocess": id }, { "name": "Union", "symbols": ["StructDefinition", "_", "OR", "_", "Union"], "postprocess": node(Syntax.UnionType) }, { "name": "StructDefinition", "symbols": ["ArrayType"], "postprocess": id }, { "name": "StructDefinition", "symbols": ["Identifier"], "postprocess": id }, { "name": "StructDefinition", "symbols": ["LCB", "_", "StructBody", "_", "RCB"], "postprocess": compose(node(Syntax.ObjectLiteral), flatten) }, { "name": "StructBody", "symbols": ["StructNameAndType"], "postprocess": id }, { "name": "StructBody", "symbols": ["StructNameAndType", "_", "COMMA", "_", "StructBody"], "postprocess": flatten }, { "name": "StructNameAndType", "symbols": ["Identifier", "_", "COLON", "_", "Type"], "postprocess": node(Syntax.Pair) }, { "name": "StructNameAndType", "symbols": ["AddressOf", "_", "COLON", "_", "Type"], "postprocess": node(Syntax.Pair) }, { "name": "AddressOf", "symbols": ["AND", "Identifier"], "postprocess": addressOf }, { "name": "TypeDef", "symbols": ["TYPE", "__", "Identifier", "_", "EQUALS", "_", "TypeDefinition", "_", "FATARROW", "_", "Type", "_", "SEPARATOR"], "postprocess": compose(typedef) }, { "name": "TypeDefinition", "symbols": ["LB", "_", "TypeList", "_", "RB"], "postprocess": flatten }, { "name": "TypeDefinition", "symbols": ["LB", "_", "RB"], "postprocess": flatten }, { "name": "TypeList", "symbols": ["Type"], "postprocess": id }, { "name": "TypeList", "symbols": ["Type", "_", "COMMA", "_", "TypeList"], "postprocess": flatten }, { "name": "_Type", "symbols": ["NativeType"], "postprocess": id }, { "name": "_Type", "symbols": ["GenericType"], "postprocess": id }, { "name": "_Type", "symbols": ["Identifier"], "postprocess": id }, { "name": "ArrayType", "symbols": ["_Type", "_", "LSB", "_", "RSB"], "postprocess": arrayType }, { "name": "Type", "symbols": ["_Type"], "postprocess": id }, { "name": "Type", "symbols": ["ArrayType"], "postprocess": id }, { "name": "GenericType", "symbols": ["Identifier", "LT", "_", "StaticObjectLiteral", "_", "GT"], "postprocess": typeGeneric }, { "name": "StaticObjectLiteral", "symbols": ["LCB", "_", "RCB"], "postprocess": compose(node(Syntax.ObjectLiteral)) }, { "name": "StaticObjectLiteral", "symbols": ["LCB", "_", "StaticPropertyList", "_", "RCB"], "postprocess": compose(node(Syntax.ObjectLiteral), flatten) }, { "name": "StaticPropertyValue", "symbols": ["Number"], "postprocess": id }, { "name": "StaticPropertyValue", "symbols": ["Boolean"], "postprocess": id }, { "name": "StaticPropertyValue", "symbols": ["StringLiteral"], "postprocess": id }, { "name": "StaticProperty", "symbols": ["Identifier", "_", "COLON", "_", "StaticPropertyValue"], "postprocess": node(Syntax.Pair) }, { "name": "StaticPropertyList", "symbols": ["StaticProperty"], "postprocess": id }, { "name": "StaticPropertyList", "symbols": ["StaticProperty", "_", "COMMA", "_", "StaticPropertyList"], "postprocess": flatten }, { "name": "ObjectLiteral", "symbols": ["LCB", "_", "RCB"], "postprocess": node(Syntax.ObjectLiteral) }, { "name": "ObjectLiteral", "symbols": ["LCB", "_", "PropertyList", "_", "RCB"], "postprocess": compose(node(Syntax.ObjectLiteral), flatten) }, { "name": "PropertyList", "symbols": ["Property"], "postprocess": id }, { "name": "PropertyList", "symbols": ["Property", "_", "COMMA", "_", "PropertyList"], "postprocess": flatten }, { "name": "Property", "symbols": ["Identifier", "_", "COLON", "_", "Ternary"], "postprocess": node(Syntax.Pair) }, { "name": "Property", "symbols": ["SPREAD", "Identifier"], "postprocess": spread }, { "name": "Property", "symbols": ["Identifier"], "postprocess": id }, { "name": "Import", "symbols": ["IMPORT", "_", "ImportDefinition", "__", "FROM", "__", "StringLiteral", "_", "SEPARATOR"], "postprocess": node(Syntax.Import) }, { "name": "ImportDefinition", "symbols": ["LCB", "_", "ImportAndTypeList", "_", "RCB"], "postprocess": compose(node(Syntax.ObjectLiteral), flatten) }, { "name": "ImportAndTypeList", "symbols": ["ImportName"], "postprocess": id }, { "name": "ImportAndTypeList", "symbols": ["ImportAndType"], "postprocess": id }, { "name": "ImportAndTypeList", "symbols": ["ImportName", "_", "COMMA", "_", "ImportAndTypeList"], "postprocess": flatten }, { "name": "ImportAndTypeList", "symbols": ["ImportAndType", "_", "COMMA", "_", "ImportAndTypeList"], "postprocess": flatten }, { "name": "ImportAndType", "symbols": ["ImportName", "_", "COLON", "_", "Type"], "postprocess": node(Syntax.Pair) }, { "name": "ImportAndType", "symbols": ["ImportName", "_", "AS", "_", "Identifier"], "postprocess": node(Syntax.BinaryExpression, { value: 'as' }) }, { "name": "ImportAndType", "symbols": ["ImportAndType", "_", "AS", "_", "Identifier"], "postprocess": node(Syntax.BinaryExpression, { value: 'as' }) }, { "name": "ImportName", "symbols": ["Identifier"], "postprocess": id }, { "name": "If", "symbols": ["IF", "_", "LB", "_", "Expression", "_", "RB", "_", "BranchBody"], "postprocess": node(Syntax.IfThenElse) }, { "name": "If", "symbols": ["IF", "_", "LB", "_", "Expression", "_", "RB", "_", "BranchBody", "_", "Else"], "postprocess": node(Syntax.IfThenElse) }, { "name": "Else", "symbols": ["ELSE", "_", "BranchBody"], "postprocess": node(Syntax.Else) }, { "name": "BranchBody", "symbols": ["Statement"], "postprocess": id }, { "name": "BranchBody", "symbols": ["Block"], "postprocess": id }, { "name": "For", "symbols": ["FOR", "_", "LB", "_", "ForArg", "_", "SEPARATOR", "_", "Expression", "_", "SEPARATOR", "_", "ForArg", "_", "RB", "_", "BranchBody"], "postprocess": forLoop }, { "name": "ForArg", "symbols": ["_Assignment"], "postprocess": id }, { "name": "ForArg", "symbols": ["Ternary"], "postprocess": id }, { "name": "While", "symbols": ["WHILE", "_", "LB", "_", "Expression", "_", "RB", "_", "BranchBody"], "postprocess": whileLoop }, { "name": "Break", "symbols": ["BREAK", "_", "SEPARATOR"], "postprocess": node(Syntax.Break) }, { "name": "Program", "symbols": ["_"], "postprocess": compose(node('Program', { value: 'ROOT_NODE' }), flatten) }, { "name": "Program", "symbols": ["_", "SourceElementList", "_"], "postprocess": compose(node('Program', { value: 'ROOT_NODE' }), flatten) }, { "name": "SourceElementList", "symbols": ["SourceElement"], "postprocess": flatten }, { "name": "SourceElementList", "symbols": ["SourceElement", "_", "SourceElementList"], "postprocess": compose(drop, flatten, flatten) }, { "name": "SourceElement", "symbols": ["Function"], "postprocess": id }, { "name": "SourceElement", "symbols": ["GlobalDeclaration"], "postprocess": id }, { "name": "SourceElement", "symbols": ["GlobalImmutableDeclaration"], "postprocess": id }, { "name": "SourceElement", "symbols": ["StaticDeclaration"], "postprocess": id }, { "name": "SourceElement", "symbols": ["Struct"], "postprocess": id }, { "name": "SourceElement", "symbols": ["TypeDef"], "postprocess": id }, { "name": "SourceElement", "symbols": ["Export"], "postprocess": id }, { "name": "SourceElement", "symbols": ["Import"], "postprocess": id }, { "name": "Statement", "symbols": ["ExpressionStatement"], "postprocess": id }, { "name": "Statement", "symbols": ["Declaration"], "postprocess": id }, { "name": "Statement", "symbols": ["ImmutableDeclaration"], "postprocess": id }, { "name": "Statement", "symbols": ["Assignment"], "postprocess": id }, { "name": "Statement", "symbols": ["If"], "postprocess": id }, { "name": "Statement", "symbols": ["For"], "postprocess": id }, { "name": "Statement", "symbols": ["While"], "postprocess": id }, { "name": "Statement", "symbols": ["Break"], "postprocess": id }, { "name": "Statement", "symbols": ["Unreachable"], "postprocess": id }, { "name": "Statement", "symbols": ["ReturnStatement"], "postprocess": id }, { "name": "Block", "symbols": ["LCB", "_", "RCB"], "postprocess": node(Syntax.Block) }, { "name": "Block", "symbols": ["LCB", "_", "StatementList", "_", "RCB"], "postprocess": compose(node(Syntax.Block), flatten) }, { "name": "StatementList", "symbols": ["Statement"], "postprocess": drop }, { "name": "StatementList", "symbols": ["Statement", "_", "StatementList"], "postprocess": flatten }, { "name": "Function", "symbols": ["FUNCTION", "__", "Identifier", "_", "FunctionParameters", "_", "Block"], "postprocess": voidFun }, { "name": "Function", "symbols": ["FUNCTION", "__", "Identifier", "_", "FunctionParameters", "_", "FunctionResult", "_", "Block"], "postprocess": fun }, { "name": "FunctionParameters", "symbols": ["LB", "_", "RB"], "postprocess": node(Syntax.FunctionArguments) }, { "name": "FunctionParameters", "symbols": ["LB", "_", "ParameterList", "_", "RB"], "postprocess": compose(node(Syntax.FunctionArguments), flatten, flatten) }, { "name": "ParameterList", "symbols": ["NameAndType"], "postprocess": id }, { "name": "ParameterList", "symbols": ["NameAndType", "_", "COMMA", "_", "ParameterList"], "postprocess": flatten }, { "name": "NameAndType", "symbols": ["Identifier", "_", "COLON", "_", "DeclType"], "postprocess": node(Syntax.Pair) }, { "name": "DeclType", "symbols": ["Type"], "postprocess": compose(extendNode({ Type: Syntax.DeclType }), nth(0)) }, { "name": "FunctionResult", "symbols": ["COLON", "_", "Type"], "postprocess": compose(result, drop) }, { "name": "GlobalDeclaration", "symbols": ["LET", "_", "NameAndType", "_", "SEPARATOR"], "postprocess": declaration(Syntax.Declaration) }, { "name": "GlobalDeclaration", "symbols": ["LET", "_", "NameAndType", "_", "EQUALS", "_", "Atom", "_", "SEPARATOR"], "postprocess": declaration(Syntax.Declaration) }, { "name": "GlobalImmutableDeclaration", "symbols": ["CONST", "_", "Identifier", "_", "COLON", "_", "GenericType", "_", "SEPARATOR"], "postprocess": builtinDecl }, { "name": "GlobalImmutableDeclaration", "symbols": ["CONST", "_", "NameAndType", "_", "EQUALS", "_", "ObjectLiteral", "_", "SEPARATOR"], "postprocess": declaration(Syntax.ImmutableDeclaration) }, { "name": "GlobalImmutableDeclaration", "symbols": ["CONST", "_", "NameAndType", "_", "EQUALS", "_", "Atom", "_", "SEPARATOR"], "postprocess": declaration(Syntax.ImmutableDeclaration) }, { "name": "Declaration", "symbols": ["LET", "_", "NameAndType", "_", "EQUALS", "_", "Expression", "_", "SEPARATOR"], "postprocess": declaration(Syntax.Declaration) }, { "name": "Declaration", "symbols": ["LET", "_", "NameAndType", "_", "SEPARATOR"], "postprocess": declaration(Syntax.Declaration) }, { "name": "ImmutableDeclaration", "symbols": ["CONST", "_", "NameAndType", "_", "EQUALS", "_", "Expression", "_", "SEPARATOR"], "postprocess": declaration(Syntax.ImmutableDeclaration) }, { "name": "ImmutableDeclaration", "symbols": ["CONST", "_", "NameAndType", "_", "EQUALS", "_", "ObjectLiteral", "_", "SEPARATOR"], "postprocess": declaration(Syntax.ImmutableDeclaration) }, { "name": "ImmutableDeclaration", "symbols": ["CONST", "_", "Identifier", "_", "COLON", "_", "GenericType", "_", "SEPARATOR"], "postprocess": builtinDecl }, { "name": "StaticNameAndType", "symbols": ["Identifier", "_", "COLON", "_", "ArrayType"], "postprocess": node(Syntax.Pair) }, { "name": "StaticDeclaration", "symbols": ["CONST", "_", "StaticNameAndType", "_", "EQUALS", "_", "LSB", "_", "RSB", "_", "SEPARATOR"], "postprocess": declaration(Syntax.StaticDeclaration) }, { "name": "StaticDeclaration", "symbols": ["CONST", "_", "StaticNameAndType", "_", "EQUALS", "_", "LSB", "_", "StaticValueList", "_", "RSB", "_", "SEPARATOR"], "postprocess": compose(declaration(Syntax.StaticDeclaration), flatten) }, { "name": "StaticValueList", "symbols": ["Atom"], "postprocess": id }, { "name": "StaticValueList", "symbols": ["Atom", "_", "COMMA", "_", "StaticValueList"], "postprocess": flatten }, { "name": "Unreachable", "symbols": ["THROW", "_", "SEPARATOR"], "postprocess": node(Syntax.Unreachable) }, { "name": "Unreachable", "symbols": ["THROW", "_", "Expression", "_", "SEPARATOR"], "postprocess": node(Syntax.Unreachable) }, { "name": "Pair", "symbols": ["Identifier", "_", "COLON", "_", "Identifier"], "postprocess": node(Syntax.Pair) }, { "name": "Export", "symbols": ["EXPORT", "__", "ImmutableDeclaration"], "postprocess": node(Syntax.Export, { value: 'export' }) }, { "name": "Export", "symbols": ["EXPORT", "__", "Function"], "postprocess": node(Syntax.Export, { value: 'export' }) }, { "name": "Export", "symbols": ["EXPORT", "__", "TypeDef"], "postprocess": node(Syntax.Export, { value: 'export' }) }, { "name": "Export", "symbols": ["EXPORT", "__", "Struct"], "postprocess": node(Syntax.Export, { value: 'export' }) }, { "name": "ReturnStatement", "symbols": ["RETURN", "__", "Expression", "_", "SEPARATOR"], "postprocess": node(Syntax.ReturnStatement) }, { "name": "ReturnStatement$subexpression$1", "symbols": [{ "literal": ";" }], "postprocess": nuller }, { "name": "ReturnStatement", "symbols": ["RETURN", "ReturnStatement$subexpression$1"], "postprocess": node(Syntax.ReturnStatement) }, { "name": "Assignment", "symbols": ["_Assignment", "_", "SEPARATOR"], "postprocess": id }, { "name": "_Assignment", "symbols": ["Subscript", "_", "EQUALS", "_", "Expression"], "postprocess": d => assignment(d, '=') }, { "name": "_Assignment", "symbols": ["Subscript", "_", "PLSEQUALS", "_", "Expression"], "postprocess": d => assignment(d, '+=') }, { "name": "_Assignment", "symbols": ["Subscript", "_", "MINEQUALS", "_", "Expression"], "postprocess": d => assignment(d, '-=') }, { "name": "_Assignment", "symbols": ["Subscript", "_", "EQUALS", "_", "ObjectLiteral"], "postprocess": d => assignment(d, '=') }, { "name": "ExpressionStatement", "symbols": ["Call", "_", "SEPARATOR"], "postprocess": id }, { "name": "Expression", "symbols": ["AssignmentExpression"], "postprocess": id }, { "name": "AssignmentExpression", "symbols": ["Identifier", "_", "EQUALS", "_", "Ternary"], "postprocess": d => assignmentExpr(d, '=') }, { "name": "AssignmentExpression", "symbols": ["Identifier", "_", "PLSEQUALS", "_", "Ternary"], "postprocess": d => assignmentExpr(d, '+=') }, { "name": "AssignmentExpression", "symbols": ["Identifier", "_", "MINEQUALS", "_", "Ternary"], "postprocess": d => assignmentExpr(d, '-=') }, { "name": "AssignmentExpression", "symbols": ["Ternary"], "postprocess": id }, { "name": "Ternary", "symbols": ["Ternary", "_", "QUESTION", "_", "TernaryPair"], "postprocess": ternary }, { "name": "Ternary", "symbols": ["Binary"], "postprocess": id }, { "name": "TernaryPair", "symbols": ["Expression", "_", "COLON", "_", "Expression"], "postprocess": node(Syntax.Pair) }, { "name": "Binary", "symbols": ["Logical"], "postprocess": id }, { "name": "Logical", "symbols": ["Logical", "_", { "literal": "||" }, "_", "Bitwise"], "postprocess": binary }, { "name": "Logical", "symbols": ["Logical", "_", { "literal": "&&" }, "_", "Bitwise"], "postprocess": binary }, { "name": "Logical", "symbols": ["Bitwise"], "postprocess": id }, { "name": "Bitwise", "symbols": ["Bitwise", "_", { "literal": "|" }, "_", "Sum"], "postprocess": binary }, { "name": "Bitwise", "symbols": ["Bitwise", "_", { "literal": "^" }, "_", "Sum"], "postprocess": binary }, { "name": "Bitwise", "symbols": ["Bitwise", "_", { "literal": "&" }, "_", "Sum"], "postprocess": binary }, { "name": "Bitwise", "symbols": ["Equality"], "postprocess": id }, { "name": "Equality", "symbols": ["Equality", "_", { "literal": "==" }, "_", "Comparison"], "postprocess": binary }, { "name": "Equality", "symbols": ["Equality", "_", { "literal": "!=" }, "_", "Comparison"], "postprocess": binary }, { "name": "Equality", "symbols": ["Comparison"], "postprocess": id }, { "name": "Comparison", "symbols": ["Comparison", "_", { "literal": "<" }, "_", "Shift"], "postprocess": binary }, { "name": "Comparison", "symbols": ["Comparison", "_", { "literal": ">" }, "_", "Shift"], "postprocess": binary }, { "name": "Comparison", "symbols": ["Comparison", "_", { "literal": "<=" }, "_", "Shift"], "postprocess": binary }, { "name": "Comparison", "symbols": ["Comparison", "_", { "literal": ">=" }, "_", "Shift"], "postprocess": binary }, { "name": "Comparison", "symbols": ["Shift"], "postprocess": id }, { "name": "Shift", "symbols": ["Shift", "_", { "literal": ">>" }, "_", "Sum"], "postprocess": binary }, { "name": "Shift", "symbols": ["Shift", "_", { "literal": "<<" }, "_", "Sum"], "postprocess": binary }, { "name": "Shift", "symbols": ["Shift", "_", { "literal": ">>>" }, "_", "Sum"], "postprocess": binary }, { "name": "Shift", "symbols": ["Sum"], "postprocess": id }, { "name": "Sum", "symbols": ["Sum", "_", { "literal": "+" }, "_", "Product"], "postprocess": binary }, { "name": "Sum", "symbols": ["Sum", "_", { "literal": "-" }, "_", "Product"], "postprocess": binary }, { "name": "Sum", "symbols": ["Product"], "postprocess": id }, { "name": "Product", "symbols": ["Product", "_", { "literal": "*" }, "_", "Typecast"], "postprocess": binary }, { "name": "Product", "symbols": ["Product", "_", { "literal": "/" }, "_", "Typecast"], "postprocess": binary }, { "name": "Product", "symbols": ["Product", "_", { "literal": "%" }, "_", "Typecast"], "postprocess": binary }, { "name": "Product", "symbols": ["Typecast"], "postprocess": id }, { "name": "Typecast", "symbols": ["Expression", "_", "COLON", "_", "DeclType"], "postprocess": node(Syntax.Pair) }, { "name": "Typecast", "symbols": ["Expression", "_", "AS", "_", "DeclType"], "postprocess": node(Syntax.Pair) }, { "name": "Typecast", "symbols": ["Unary"], "postprocess": id }, { "name": "Unary", "symbols": [{ "literal": "!" }, "Call"], "postprocess": unary }, { "name": "Unary", "symbols": [{ "literal": "~" }, "Call"], "postprocess": unary }, { "name": "Unary", "symbols": [{ "literal": "-" }, "Call"], "postprocess": unary }, { "name": "Unary", "symbols": [{ "literal": "+" }, "Call"], "postprocess": unary }, { "name": "Unary", "symbols": [{ "literal": "++" }, "Call"], "postprocess": unary }, { "name": "Unary", "symbols": [{ "literal": "--" }, "Call"], "postprocess": unary }, { "name": "Unary", "symbo