|
60 | 60 | for (var i = 0; i < keys.length; i++) {
|
61 | 61 | var key = keys[i]
|
62 | 62 | var thing = object[key]
|
63 |
| - var rules = Array.isArray(thing) ? thing : [thing] |
| 63 | + var rules = [].concat(thing) |
| 64 | + if (key === 'include') { |
| 65 | + for (var j = 0; j < rules.length; j++) { |
| 66 | + result.push({include: rules[j]}) |
| 67 | + } |
| 68 | + continue |
| 69 | + } |
64 | 70 | var match = []
|
65 | 71 | rules.forEach(function(rule) {
|
66 | 72 | if (isObject(rule)) {
|
|
80 | 86 | var result = []
|
81 | 87 | for (var i = 0; i < array.length; i++) {
|
82 | 88 | var obj = array[i]
|
| 89 | + if (obj.include) { |
| 90 | + var include = [].concat(obj.include) |
| 91 | + for (var j = 0; j < include.length; j++) { |
| 92 | + result.push({include: include[j]}) |
| 93 | + } |
| 94 | + continue |
| 95 | + } |
83 | 96 | if (!obj.name) {
|
84 | 97 | throw new Error('Rule has no name: ' + JSON.stringify(obj))
|
85 | 98 | }
|
|
92 | 105 | if (!isObject(obj)) {
|
93 | 106 | obj = { match: obj }
|
94 | 107 | }
|
| 108 | + if (obj.include) { |
| 109 | + throw new Error('Matching rules cannot also include states') |
| 110 | + } |
95 | 111 |
|
96 | 112 | // nb. error and fallback imply lineBreaks
|
97 | 113 | var options = {
|
|
127 | 143 | return options
|
128 | 144 | }
|
129 | 145 |
|
| 146 | + function toRules(spec) { |
| 147 | + return Array.isArray(spec) ? arrayToRules(spec) : objectToRules(spec) |
| 148 | + } |
| 149 | + |
130 | 150 | var defaultErrorRule = ruleOptions('error', {lineBreaks: true, shouldThrow: true})
|
131 | 151 | function compileRules(rules, hasStates) {
|
132 |
| - rules = Array.isArray(rules) ? arrayToRules(rules) : objectToRules(rules) |
133 |
| - |
134 | 152 | var errorRule = null
|
135 | 153 | var fast = Object.create(null)
|
136 | 154 | var fastAllowed = true
|
|
139 | 157 | for (var i = 0; i < rules.length; i++) {
|
140 | 158 | var options = rules[i]
|
141 | 159 |
|
| 160 | + if (options.include) { |
| 161 | + // all valid inclusions are removed by states() preprocessor |
| 162 | + throw new Error('Inheritance is not allowed in stateless lexers') |
| 163 | + } |
| 164 | + |
142 | 165 | if (options.error || options.fallback) {
|
143 | 166 | // errorRule can only be set once
|
144 | 167 | if (errorRule) {
|
|
214 | 237 | }
|
215 | 238 |
|
216 | 239 | function compile(rules) {
|
217 |
| - var result = compileRules(rules) |
| 240 | + var result = compileRules(toRules(rules)) |
218 | 241 | return new Lexer({start: result}, 'start')
|
219 | 242 | }
|
220 | 243 |
|
|
228 | 251 | }
|
229 | 252 | }
|
230 | 253 | function compileStates(states, start) {
|
| 254 | + var all = states.$all ? toRules(states.$all) : [] |
| 255 | + delete states.$all |
| 256 | + |
231 | 257 | var keys = Object.getOwnPropertyNames(states)
|
232 | 258 | if (!start) start = keys[0]
|
233 | 259 |
|
| 260 | + var ruleMap = Object.create(null) |
| 261 | + for (var i = 0; i < keys.length; i++) { |
| 262 | + var key = keys[i] |
| 263 | + ruleMap[key] = toRules(states[key]).concat(all) |
| 264 | + } |
| 265 | + for (var i = 0; i < keys.length; i++) { |
| 266 | + var key = keys[i] |
| 267 | + var rules = ruleMap[key] |
| 268 | + var included = Object.create(null) |
| 269 | + for (var j = 0; j < rules.length; j++) { |
| 270 | + var rule = rules[j] |
| 271 | + if (!rule.include) continue |
| 272 | + var splice = [j, 1] |
| 273 | + if (rule.include !== key && !included[rule.include]) { |
| 274 | + included[rule.include] = true |
| 275 | + var newRules = ruleMap[rule.include] |
| 276 | + if (!newRules) { |
| 277 | + throw new Error("Cannot include nonexistent state '" + rule.include + "' (in state '" + key + "')") |
| 278 | + } |
| 279 | + for (var k = 0; k < newRules.length; k++) { |
| 280 | + var newRule = newRules[k] |
| 281 | + if (rules.indexOf(newRule) !== -1) continue |
| 282 | + splice.push(newRule) |
| 283 | + } |
| 284 | + } |
| 285 | + rules.splice.apply(rules, splice) |
| 286 | + j-- |
| 287 | + } |
| 288 | + } |
| 289 | + |
234 | 290 | var map = Object.create(null)
|
235 | 291 | for (var i = 0; i < keys.length; i++) {
|
236 | 292 | var key = keys[i]
|
237 |
| - map[key] = compileRules(states[key], true) |
| 293 | + map[key] = compileRules(ruleMap[key], true) |
238 | 294 | }
|
239 | 295 |
|
240 | 296 | for (var i = 0; i < keys.length; i++) {
|
|
0 commit comments