UNPKG

@grammar/son

Version:

SON grammar.

396 lines 16 kB
import $ from './spellu-engine.mjs'; var grammar$son; (function (grammar$son) { grammar$son.recipe = { name: 'son', rules: { 'root': { parser: 'value', }, 'value': { parser: '|', argument: [ { parser: 'array' }, { parser: 'object' }, { parser: 'string' }, { parser: 'number' }, { parser: 'boolean' }, { parser: 'null' }, ], }, 'array': { parser: '&', argument: [ { parser: '?', argument: { syntax: "son.token.bracket-[" /* OpenBracketToken */, pattern: '[' } }, { parser: '*', argument: [ { parser: 'array-item' }, { parser: '?', argument: { syntax: "son.token.comma" /* CommaToken */, pattern: ',' } }, ], options: { allowTrailingSeparator: true }, optional: true, }, { parser: '?', argument: { syntax: "son.token.bracket-]" /* CloseBracketToken */, pattern: ']' } }, ], }, 'array-item': { parser: 'value', }, 'object': { parser: '&', argument: [ { parser: '?', argument: { syntax: "son.token.brace-{" /* OpenBraceToken */, pattern: '{' } }, { parser: '*', argument: [ { parser: 'object-item' }, { parser: '?', argument: { syntax: "son.token.comma" /* CommaToken */, pattern: ',' } }, ], options: { allowTrailingSeparator: true }, optional: true, }, { parser: '?', argument: { syntax: "son.token.brace-}" /* CloseBraceToken */, pattern: '}' } }, ], }, 'object-item': { parser: '&', argument: [ { parser: 'object-key' }, { parser: '?', argument: { syntax: "son.token.colon" /* ColonToken */, pattern: ':' } }, { parser: 'value' }, ], }, 'object-key': { parser: '|', argument: [ { parser: 'string' }, { parser: 'number' }, { parser: 'identifier' }, ], }, 'identifier': { parser: '?', argument: { syntax: "son.token.identifier" /* IdentifierToken */, pattern: /[a-zA-Z_$][0-9a-zA-Z_$]*/ }, }, 'string': { parser: '|', argument: [ { parser: 'doublequoted-string' }, { parser: 'singlequoted-string' }, ], }, 'doublequoted-string': { parser: '&', argument: [ { parser: '?', argument: { syntax: "son.token.double-quote" /* DoubleQuote */, pattern: '"' } }, { parser: '#', argument: [ { syntax: "son.token.escaped-unicode-character" /* EscapedUnicodeCharacterToken */, pattern: /\\u[0-9a-fA-F]{4}/ }, { syntax: "son.token.escaped-sign-character" /* EscapedSignCharacterToken */, pattern: /\\[\\tnr"]/ }, { syntax: "son.token.error" /* ErrorToken */, pattern: /\\u[0-9a-fA-F]{1,3}/ }, { syntax: "son.token.error" /* ErrorToken */, pattern: /\\./ }, { syntax: "son.token.text" /* TextToken */, pattern: /[^\\"]+/ }, ], multiplicity: 0, }, { parser: '#', argument: { syntax: "son.token.double-quote" /* DoubleQuote */, pattern: '"' } }, ], }, 'singlequoted-string': { parser: '&', argument: [ { parser: '?', argument: { syntax: "son.token.single-quote" /* SingleQuote */, pattern: "'" } }, { parser: '#', argument: [ { syntax: "son.token.escaped-unicode-character" /* EscapedUnicodeCharacterToken */, pattern: /\\u[0-9a-fA-F]{4}/ }, { syntax: "son.token.escaped-sign-character" /* EscapedSignCharacterToken */, pattern: /\\[\\tnr"]/ }, { syntax: "son.token.error" /* ErrorToken */, pattern: /\\u[0-9a-fA-F]{1,3}/ }, { syntax: "son.token.error" /* ErrorToken */, pattern: /\\./ }, { syntax: "son.token.text" /* TextToken */, pattern: /[^\\']+/ }, ], multiplicity: 0, }, { parser: '#', argument: { syntax: "son.token.single-quote" /* SingleQuote */, pattern: "'" } }, ], }, 'number': { parser: '?', argument: [ { syntax: "son.token.number" /* NumberToken */, pattern: /[-]?(?:0|[1-9][0-9]*)(?:[.][0-9]+)?(?:[eE][+-]?[0-9]+)?/ }, ], }, 'boolean': { parser: '?', argument: [ { syntax: "son.token.boolean" /* BooleanToken */, pattern: 'true' }, { syntax: "son.token.boolean" /* BooleanToken */, pattern: 'false' }, ], }, 'null': { parser: '?', argument: [ { syntax: "son.token.null" /* NullToken */, pattern: 'null' }, ], }, }, }; })(grammar$son || (grammar$son = {})); (function (grammar$son) { grammar$son.processors = {}; })(grammar$son || (grammar$son = {})); (function (grammar$son) { grammar$son.processors['cst'] = { recipe: grammar$son.recipe, parts: {} }; })(grammar$son || (grammar$son = {})); (function (grammar$son) { grammar$son.processors['ast'] = { recipe: grammar$son.recipe, parts: { 'value'(_) { return _; }, 'array'(_) { return $.createNode(_, "son.Array" /* Array */, { items: _[1] || [] }); }, 'array-item'(_) { return _; }, 'object'(_) { return $.createNode(_, "son.Object" /* Object */, { items: _[1] || [] }); }, 'object-item'(_) { return [_[0], _[2]]; }, 'string'(_) { const value = _[1].map(_ => convertStringLiteral(_)).join(''); return $.createNode(_, "son.String" /* String */, { value, tokens: _[1] }); }, 'number'(_) { return $.createNode(_, "son.Number" /* Number */, { value: Number(_.value), token: _ }); }, 'boolean'(_) { return $.createNode(_, "son.Boolean" /* Boolean */, { value: _.value === 'true' ? true : false, token: _ }); }, 'null'(_) { return $.createNode(_, "son.Null" /* Null */, { value: null, token: _ }); }, }, }; const escapedSigns = { '\\\\': '\\', '\\t': '\t', '\\r': '\r', '\\n': '\n', '\\"': '\"', }; function convertStringLiteral(token) { switch (token.syntax) { case "son.token.text" /* TextToken */: return token.value; case "son.token.escaped-unicode-character" /* EscapedUnicodeCharacterToken */: return String.fromCharCode(parseInt(token.value.substring(2), 16)); case "son.token.escaped-sign-character" /* EscapedSignCharacterToken */: return escapedSigns[token.value] || token.value; case "son.token.error" /* ErrorToken */: return token.value; default: return ''; } } })(grammar$son || (grammar$son = {})); (function (grammar$son) { /** * literal.string * literal.number * literal.boolean * literal.null * entity.object-key.literal.string * entity.object-key.literal.number * entity.object-key.identifier */ grammar$son.processors['syntax'] = { recipe: grammar$son.recipe, parts: { 'object-key'(_) { return $.createSyntaxScope('entity', $.createSyntaxScope('object-key', _)); }, 'identifier'(_) { return $.createSyntaxScope('identifier', _); }, 'string'(_) { return $.createSyntaxScope('literal', $.createSyntaxScope('string', _)); }, 'number'(_) { return $.createSyntaxScope('literal', $.createSyntaxScope('number', _)); }, 'boolean'(_) { return $.createSyntaxScope('literal', $.createSyntaxScope('boolean', _)); }, 'null'(_) { return $.createSyntaxScope('literal', $.createSyntaxScope('null', _)); }, }, }; const escapedSigns = { '\\\\': '\\', '\\t': '\t', '\\r': '\r', '\\n': '\n', '\\"': '\"', }; function convertStringLiteral(token) { switch (token.syntax) { case "son.token.text" /* TextToken */: return token.value; case "son.token.escaped-unicode-character" /* EscapedUnicodeCharacterToken */: return String.fromCharCode(parseInt(token.value.substring(2), 16)); case "son.token.escaped-sign-character" /* EscapedSignCharacterToken */: return escapedSigns[token.value] || token.value; case "son.token.error" /* ErrorToken */: return token.value; default: return ''; } } })(grammar$son || (grammar$son = {})); (function (grammar$son) { grammar$son.processors['value'] = { recipe: grammar$son.recipe, parts: { 'array'(_) { return _[1] || []; }, 'array-item'(_) { return _; }, 'object'(_) { return Object.fromEntries(_[1] || []); }, 'object-item'(_) { return [_[0], _[2]]; }, 'identifier'(_) { return _.value; }, 'string'(_) { return _[1].reduce((v, _) => v.concat(convertStringLiteral(_)), ''); }, 'number'(_) { return Number(_.value); }, 'boolean'(_) { return _.value === 'true' ? true : false; }, 'null'(_) { return null; }, }, }; const escapedSigns = { '\\\\': '\\', '\\t': '\t', '\\r': '\r', '\\n': '\n', '\\"': '\"', }; function convertStringLiteral(token) { switch (token.syntax) { case "son.token.text" /* TextToken */: return token.value; case "son.token.escaped-unicode-character" /* EscapedUnicodeCharacterToken */: return String.fromCharCode(parseInt(token.value.substring(2), 16)); case "son.token.escaped-sign-character" /* EscapedSignCharacterToken */: return escapedSigns[token.value] || token.value; case "son.token.error" /* ErrorToken */: return token.value; default: return ''; } } })(grammar$son || (grammar$son = {})); (function (grammar$son) { let ProcessorSuite; (function (ProcessorSuite) { ProcessorSuite["CST"] = "cst"; ProcessorSuite["AST"] = "ast"; ProcessorSuite["Syntax"] = "syntax"; ProcessorSuite["Value"] = "value"; })(ProcessorSuite = grammar$son.ProcessorSuite || (grammar$son.ProcessorSuite = {})); function selectProcessorSuite(suite) { return [grammar$son.processors[suite]]; } grammar$son.selectProcessorSuite = selectProcessorSuite; function scan(source, suite = ProcessorSuite.AST, rule, options = {}) { options.processors = selectProcessorSuite(suite); return $.scan($.createSource(source), rule ?? grammar$son.recipe.name, options); } grammar$son.scan = scan; function tokenize(source, options = {}) { return $.tokenize(scan(source, ProcessorSuite.Syntax, undefined, options)); } grammar$son.tokenize = tokenize; function parse(source, options = {}) { return scan(source, ProcessorSuite.Value, undefined, options); } grammar$son.parse = parse; })(grammar$son || (grammar$son = {})); (function (grammar$son) { const printOptions = { pretty: false, }; function print(value, options = {}) { options = { ...printOptions, ...options }; const printer = new SONPrinter(options); return printer.print(value); } grammar$son.print = print; class SONPrinter extends $.TextPrinter { constructor(options = {}) { super({ space: options.pretty ? ' ' : '', lineBreak: options.pretty ? '\n' : '', indent: options.pretty ? 'tab' : 0, }); } print(value) { this.node(value); return this.flash(); } node(...nodes) { for (const node of nodes) { let block = this._blocks[node.syntax]; if (!block) { // throw new Error(`Syntax printer "${value.syntax}" is not defined.`) block = printer => printer.text('#ERROR#'); } block(this, node); } return this; } _blocks = { ["son.Array" /* Array */](printer, _) { if (_.items.length == 0) { printer.text('[]'); } else { printer.text('[').newLine().indentUp(); { const items = [..._.items]; const lastValue = items.pop(); for (const value of items) { printer.node(value).text(',').newLine(); } { printer.node(lastValue).newLine(); } } printer.indentDown().text(']'); } }, ["son.Object" /* Object */](printer, _) { if (_.items.length == 0) { printer.text('{}'); } else { printer.text('{').newLine().indentUp(); { const items = [..._.items]; const [lastKey, lastValue] = items.pop(); for (const [key, value] of items) { printer.node(key).text(':').node(value).text(',').newLine(); } { printer.node(lastKey).text(':').node(lastValue).newLine(); } } printer.indentDown().text('}'); } }, ["son.String" /* String */](printer, _) { const string = _.tokens.map((_) => _.value).join(''); printer.quote('"', string); }, ["son.Number" /* Number */](printer, _) { printer.text(_.token.value); }, ["son.Boolean" /* Boolean */](printer, _) { printer.text(_.token.value); }, ["son.Null" /* Null */](printer, _) { printer.text(_.token.value); }, }; } })(grammar$son || (grammar$son = {})); export default grammar$son; //# sourceMappingURL=grammar-son.mjs.map