UNPKG

5.96 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11Object.defineProperty(exports, "__esModule", { value: true });
12const RHS_1 = require("./RHS");
13const GrammarAnnotation_1 = require("./GrammarAnnotation");
14const Terminal_1 = require("./Terminal");
15const Builder_1 = require("./Builder");
16const utils = require("./utils");
17/*@internal*/
18class Production extends Builder_1.default {
19 constructor(spec, node, namespace) {
20 super(spec, node);
21 this.type = node.getAttribute('type');
22 this.name = node.getAttribute('name'); // TODO: unchecked
23 this.params = node.getAttribute('params');
24 this.optional = node.hasAttribute('optional');
25 this.oneOf = node.hasAttribute('oneof');
26 this.rhses = [];
27 this.rhsesById = {};
28 this.namespace = namespace;
29 const rhses = this.node.querySelectorAll('emu-rhs');
30 for (let i = 0; i < rhses.length; i++) {
31 const rhs = new RHS_1.default(this.spec, this, rhses[i]);
32 this.rhses.push(rhs);
33 if (rhs.alternativeId) {
34 this.rhsesById[rhs.alternativeId] = rhs;
35 }
36 }
37 const id = this._id();
38 const entry = this.spec.biblio.byProductionName(this.name, this.namespace);
39 let primary = false;
40 if (node.hasAttribute('primary')) {
41 primary = true;
42 }
43 else {
44 let parent = node.parentElement;
45 if (parent != null) {
46 // highlighted nodes still count as primary unless they are being deleted (i.e. in a <del> tag)
47 while (parent.tagName === 'INS' || parent.tagName === 'MARK') {
48 parent = parent.parentElement;
49 if (parent == null) {
50 break;
51 }
52 }
53 if (parent != null && parent.tagName === 'EMU-GRAMMAR') {
54 primary = parent.hasAttribute('primary') || parent.getAttribute('type') === 'definition';
55 }
56 }
57 }
58 this.primary = primary;
59 if (this.primary) {
60 this.id = id;
61 if (entry && entry.namespace === this.namespace && entry._instance) {
62 entry._instance.primary = false;
63 entry._instance.node.removeAttribute('id');
64 }
65 const newEntry = {
66 type: 'production',
67 id,
68 name: this.name,
69 };
70 // non-enumerable to JSON-stringifying the biblio doesn't include this
71 Object.defineProperty(newEntry, '_instance', { value: this });
72 this.spec.biblio.add(newEntry, this.namespace);
73 }
74 }
75 _id() {
76 if (this.namespace && this.namespace !== this.spec.namespace) {
77 return `prod-${this.namespace}-${this.name}`;
78 }
79 else {
80 return `prod-${this.name}`;
81 }
82 }
83 static enter({ spec, node, clauseStack }) {
84 return __awaiter(this, void 0, void 0, function* () {
85 const ntNode = spec.doc.createElement('emu-nt');
86 const clause = clauseStack[clauseStack.length - 1];
87 const prod = new Production(spec, node, clause ? clause.namespace : spec.namespace);
88 ntNode.innerHTML = '<a href="#prod-' + prod.name + '">' + prod.name + '</a>';
89 if (prod.params)
90 ntNode.setAttribute('params', prod.params);
91 if (prod.optional)
92 ntNode.setAttribute('optional', '');
93 node.insertBefore(ntNode, node.children[0]);
94 const geq = spec.doc.createElement('emu-geq');
95 if (prod.type === 'lexical') {
96 geq.textContent = '::';
97 }
98 else if (prod.type === 'regexp') {
99 geq.textContent = ':::';
100 }
101 else {
102 geq.textContent = ':';
103 }
104 node.insertBefore(spec.doc.createTextNode(' '), ntNode.nextSibling);
105 node.insertBefore(geq, ntNode.nextSibling);
106 node.insertBefore(spec.doc.createTextNode(' '), ntNode.nextSibling);
107 if (prod.oneOf) {
108 const elem = spec.doc.createElement('emu-oneof');
109 elem.textContent = 'one of';
110 node.insertBefore(elem, geq.nextSibling);
111 node.insertBefore(spec.doc.createTextNode(' '), elem);
112 }
113 prod.rhses.forEach(rhs => rhs.build());
114 const ganns = node.querySelectorAll('emu-gann');
115 for (let i = 0; i < ganns.length; i++) {
116 new GrammarAnnotation_1.default(spec, prod, ganns[i]).build();
117 }
118 const ts = node.querySelectorAll('emu-t');
119 for (let i = 0; i < ts.length; i++) {
120 new Terminal_1.default(spec, prod, ts[i]).build();
121 }
122 if (prod.primary) {
123 node.setAttribute('id', prod.id);
124 }
125 if (utils.shouldInline(node)) {
126 const cls = node.getAttribute('class') || '';
127 if (cls.indexOf('inline') === -1) {
128 node.setAttribute('class', cls + ' inline');
129 }
130 }
131 });
132 }
133}
134exports.default = Production;
135Production.byName = {};
136Production.elements = ['EMU-PRODUCTION'];