| 'use strict'; | 
|   | 
| var brackets = require('expand-brackets'); | 
| var define = require('define-property'); | 
| var utils = require('./utils'); | 
|   | 
| /** | 
|  * Characters to use in text regex (we want to "not" match | 
|  * characters that are matched by other parsers) | 
|  */ | 
|   | 
| var TEXT_REGEX = '([!@*?+]?\\(|\\)|[*?.+\\\\]|\\[:?(?=.*\\])|:?\\])+'; | 
| var not = utils.createRegex(TEXT_REGEX); | 
|   | 
| /** | 
|  * Extglob parsers | 
|  */ | 
|   | 
| function parsers(extglob) { | 
|   extglob.state = extglob.state || {}; | 
|   | 
|   /** | 
|    * Use `expand-brackets` parsers | 
|    */ | 
|   | 
|   extglob.use(brackets.parsers); | 
|   extglob.parser.sets.paren = extglob.parser.sets.paren || []; | 
|   extglob.parser | 
|   | 
|     /** | 
|      * Extglob open: "*(" | 
|      */ | 
|   | 
|     .capture('paren.open', function() { | 
|       var parsed = this.parsed; | 
|       var pos = this.position(); | 
|       var m = this.match(/^([!@*?+])?\(/); | 
|       if (!m) return; | 
|   | 
|       var prev = this.prev(); | 
|       var prefix = m[1]; | 
|       var val = m[0]; | 
|   | 
|       var open = pos({ | 
|         type: 'paren.open', | 
|         parsed: parsed, | 
|         val: val | 
|       }); | 
|   | 
|       var node = pos({ | 
|         type: 'paren', | 
|         prefix: prefix, | 
|         nodes: [open] | 
|       }); | 
|   | 
|       // if nested negation extglobs, just cancel them out to simplify | 
|       if (prefix === '!' && prev.type === 'paren' && prev.prefix === '!') { | 
|         prev.prefix = '@'; | 
|         node.prefix = '@'; | 
|       } | 
|   | 
|       define(node, 'rest', this.input); | 
|       define(node, 'parsed', parsed); | 
|       define(node, 'parent', prev); | 
|       define(open, 'parent', node); | 
|   | 
|       this.push('paren', node); | 
|       prev.nodes.push(node); | 
|     }) | 
|   | 
|     /** | 
|      * Extglob close: ")" | 
|      */ | 
|   | 
|     .capture('paren.close', function() { | 
|       var parsed = this.parsed; | 
|       var pos = this.position(); | 
|       var m = this.match(/^\)/); | 
|       if (!m) return; | 
|   | 
|       var parent = this.pop('paren'); | 
|       var node = pos({ | 
|         type: 'paren.close', | 
|         rest: this.input, | 
|         parsed: parsed, | 
|         val: m[0] | 
|       }); | 
|   | 
|       if (!this.isType(parent, 'paren')) { | 
|         if (this.options.strict) { | 
|           throw new Error('missing opening paren: "("'); | 
|         } | 
|         node.escaped = true; | 
|         return node; | 
|       } | 
|   | 
|       node.prefix = parent.prefix; | 
|       parent.nodes.push(node); | 
|       define(node, 'parent', parent); | 
|     }) | 
|   | 
|     /** | 
|      * Escape: "\\." | 
|      */ | 
|   | 
|     .capture('escape', function() { | 
|       var pos = this.position(); | 
|       var m = this.match(/^\\(.)/); | 
|       if (!m) return; | 
|   | 
|       return pos({ | 
|         type: 'escape', | 
|         val: m[0], | 
|         ch: m[1] | 
|       }); | 
|     }) | 
|   | 
|     /** | 
|      * Question marks: "?" | 
|      */ | 
|   | 
|     .capture('qmark', function() { | 
|       var parsed = this.parsed; | 
|       var pos = this.position(); | 
|       var m = this.match(/^\?+(?!\()/); | 
|       if (!m) return; | 
|       extglob.state.metachar = true; | 
|       return pos({ | 
|         type: 'qmark', | 
|         rest: this.input, | 
|         parsed: parsed, | 
|         val: m[0] | 
|       }); | 
|     }) | 
|   | 
|     /** | 
|      * Character parsers | 
|      */ | 
|   | 
|     .capture('star', /^\*(?!\()/) | 
|     .capture('plus', /^\+(?!\()/) | 
|     .capture('dot', /^\./) | 
|     .capture('text', not); | 
| }; | 
|   | 
| /** | 
|  * Expose text regex string | 
|  */ | 
|   | 
| module.exports.TEXT_REGEX = TEXT_REGEX; | 
|   | 
| /** | 
|  * Extglob parsers | 
|  */ | 
|   | 
| module.exports = parsers; |