UNPKG

@grammar/xml

Version:

XML 1.1 grammar.

273 lines 12.4 kB
import $ from './spellu-engine.mjs'; /** * XML 1.1 */ var grammar$xml; (function (grammar$xml) { function createRecipe() { return { name: 'xml', rules: { root: { parser: '&', argument: [ { parser: 'xml-declaration' }, { parser: 'document-type', optional: true }, { parser: 'node-list' }, ], }, // <?xml ...?> // <?xml-stylesheet ...?> 'xml-declaration': { parser: '&', argument: [ { parser: '?', argument: { syntax: "token.xml.XmlDeclaration.L" /* XmlDeclarationOpenToken */, pattern: '<?xml' } }, { parser: '?', argument: { syntax: "xml.TextSection" /* TextSection */, pattern: /[^\?]+/ } }, { parser: '?', argument: { syntax: "token.xml.XmlDeclaration.R" /* XmlDeclarationCloseToken */, pattern: '?>' } }, ], }, // <!doctype ...> // <!...> 'document-type': { parser: '&', argument: [ { parser: '?', argument: { syntax: "token.xml.MarkupDeclaration.L" /* MarkupDeclarationOpenToken */, pattern: '<!' } }, { parser: '?', argument: { syntax: "xml.DoctypeDeclaration" /* DoctypeDeclaration */, pattern: /(?:doctype|DOCTYPE)\s+([0-9a-zA-Z:_\-]+)\s*/, capture: 1 } }, { parser: '?', argument: { syntax: "token.xml.MarkupDeclaration.R" /* MarkupDeclarationCloseToken */, pattern: '>' } }, ], }, 'node-list': { parser: '|', argument: [ { parser: 'comment' }, { parser: 'tag-open' }, { parser: 'tag-close' }, { parser: 'cdata' }, { parser: 'text' }, ], multiplicity: 0, }, 'comment': { parser: '&', argument: [ { parser: '?', argument: { syntax: "xml.CommentSection" /* CommentSection */, pattern: '<!--' } }, { parser: '#', argument: [ { syntax: 'xml.comment.content', pattern: /.+(?=-->)/ }, ] }, { parser: '#', argument: { syntax: "xml.CommentSection" /* CommentSection */, pattern: '-->' } }, ], }, 'tag-open': { parser: '&', argument: [ { parser: '?', argument: { syntax: "token.xml.<" /* TagOpenToken */, pattern: '<' } }, { parser: '#', argument: { syntax: "xml.TagName" /* TagName */, pattern: /[0-9a-zA-Z:_\-]+/ } }, { parser: 'attribute', multiplicity: 0 }, { parser: '?', argument: { syntax: "token.xml./" /* SlashToken */, pattern: '/' }, optional: true }, { parser: '?', argument: { syntax: "token.xml.>" /* TagCloseToken */, pattern: '>' } }, ], }, 'tag-close': { parser: '&', argument: [ { parser: '?', argument: { syntax: "token.xml.<" /* TagOpenToken */, pattern: '<' } }, { parser: '#', argument: { syntax: "token.xml./" /* SlashToken */, pattern: '/' } }, { parser: '#', argument: { syntax: "xml.TagName" /* TagName */, pattern: /[0-9a-zA-Z:_\-]+/ } }, { parser: '?', argument: { syntax: "token.xml.>" /* TagCloseToken */, pattern: '>' } }, ], }, 'attribute': { parser: '&', argument: [ { parser: '?', argument: { syntax: "xml.AttributeName" /* AttributeName */, pattern: /[0-9a-zA-Z:_\-]+/ } }, { parser: '?', argument: { syntax: "token.xml.=" /* EqualToken */, pattern: '=' } }, { parser: 'string-literal' }, ], }, 'cdata': { parser: '&', argument: [ // FIXME: Syntax { parser: '?', argument: { syntax: "token.xml.<" /* TagOpenToken */, pattern: '<![CDATA[' } }, { parser: '#', argument: { syntax: "xml.Text" /* Text */, pattern: /.*?(?=\]\]>)/ms } }, { parser: '#', argument: { syntax: "token.xml.>" /* TagCloseToken */, pattern: ']]>' } }, ], }, 'text': { parser: '?', argument: { syntax: "xml.Text" /* Text */, pattern: /.+?(?=<)|.+/ms } }, 'string-literal': { parser: '&', argument: [ { parser: '?', argument: { syntax: 'token.xml.doublequote', pattern: '"' } }, { parser: '#', argument: { syntax: 'token.xml.content', pattern: /[^"]*/ } }, { parser: '#', argument: { syntax: 'token.xml.doublequote', pattern: '"' } }, ], }, }, }; } grammar$xml.createRecipe = createRecipe; })(grammar$xml || (grammar$xml = {})); (function (grammar$xml) { var processors; (function (processors) { processors.cst = { recipe: grammar$xml.createRecipe(), parts: {}, }; })(processors = grammar$xml.processors || (grammar$xml.processors = {})); })(grammar$xml || (grammar$xml = {})); (function (grammar$xml) { var processors; (function (processors) { processors.ast = { recipe: grammar$xml.createRecipe(), parts: { 'root'(_) { return $.createNode(_, "xml.Document" /* XmlDocument */, { xmlDeclaration: _[0], doctype: _[1], nodeList: _[2], }); }, 'xml-declaration'(_) { return $.createNode(_, "xml.XmlDeclaration" /* XmlDeclaration */, { attributeList: [], }); }, 'document-type'(_) { return $.createNode(_, "xml.DoctypeDeclaration" /* DoctypeDeclaration */, { string: _[1], }); }, 'comment'(_) { return $.createNode(_, "xml.CommentSection" /* CommentSection */, { text: _.value, }); }, 'tag-open'(_) { return $.createNode(_, "xml.TagSection" /* TagSection */, { isOpen: true, isClose: _[3] ? true : false, tagName: _[1], attributeList: _[2], }); }, 'tag-close'(_) { return $.createNode(_, "xml.TagSection" /* TagSection */, { isOpen: false, isClose: true, tagName: _[2], attributeList: [], }); }, 'attribute'(_) { return $.createNode(_, "xml.Attribute" /* Attribute */, { name: _[0], value: _[2], }); }, 'cdata'(_) { return $.createNode(_, "xml.CDataSection" /* CDataSection */, { text: _[1], }); }, 'text'(_) { return $.createNode(_, "xml.TextSection" /* TextSection */, { text: _, }); }, 'string-literal'(_) { return _[1]; }, }, }; })(processors = grammar$xml.processors || (grammar$xml.processors = {})); })(grammar$xml || (grammar$xml = {})); (function (grammar$xml) { let ProcessorSuite; (function (ProcessorSuite) { ProcessorSuite["CST"] = "cst"; ProcessorSuite["AST"] = "ast"; })(ProcessorSuite = grammar$xml.ProcessorSuite || (grammar$xml.ProcessorSuite = {})); function selectProcessorSuite(suite) { return [grammar$xml.processors[suite]]; } grammar$xml.selectProcessorSuite = selectProcessorSuite; function scan(source, suite = ProcessorSuite.AST, rule, options = {}) { const processors = selectProcessorSuite(suite); return $.scan($.createSource(source), rule ?? processors[0]?.recipe.name, { ...options, processors: processors }); } grammar$xml.scan = scan; function tokens(source, options = {}) { return $.flatten(scan(source, ProcessorSuite.CST, undefined, options)); } grammar$xml.tokens = tokens; })(grammar$xml || (grammar$xml = {})); (function (grammar$xml) { function assemble(source) { return new NodeTreeAssembler().assemble(source); } grammar$xml.assemble = assemble; class NodeTreeAssembler { nodeStack = []; tagStack = []; assemble(source) { this.nodeStack = [...source.nodeList]; this.tagStack = []; return $.createNode(source, "xml.Document" /* XmlDocument */, { xmlDeclaration: source.xmlDeclaration, doctype: source.doctype, nodeList: this.assembleNodes(), }); } assembleNodes() { const semanticNodeList = []; while (this.nodeStack.length > 0) { let node = this.nodeStack.shift(); if (node.syntax === "xml.TagSection" /* TagSection */) { const nodeTag = node; if (nodeTag.isOpen) { // self closing tag if (nodeTag.isClose) { const element = $.createNode(nodeTag, "xml.ElementDeclaration" /* ElementDeclaration */, { tagName: nodeTag.tagName, attributeList: nodeTag.attributeList, nodeList: [], }); semanticNodeList.push(element); } // open tag else { this.tagStack.push(nodeTag); const element = $.createNode(nodeTag, "xml.ElementDeclaration" /* ElementDeclaration */, { tagName: nodeTag.tagName, attributeList: nodeTag.attributeList, nodeList: this.assembleNodes(), }); semanticNodeList.push(element); } } // close tag else { if (this.tagStack.length > 0) { const openNode = this.tagStack.pop(); const closeNode = nodeTag; if (openNode.tagName.value === closeNode.tagName.value) { return semanticNodeList; } else { // Error: close tag is not matched console.error('Ca1'); } } else { // Error: close tag is not matched console.error('Ca2'); } } } else { semanticNodeList.push(node); } } return semanticNodeList; } } })(grammar$xml || (grammar$xml = {})); export default grammar$xml; //# sourceMappingURL=grammar-xml.mjs.map