BVB Source Codes

reactide Show expression.js Source code

Return Download reactide: download expression.js Source code - Download reactide Source code - Type:.js
  1. // A recursive descent parser operates by defining functions for all
  2. // syntactic elements, and recursively calling those, each function
  3. // advancing the input stream and returning an AST node. Precedence
  4. // of constructs (for example, the fact that `!x[1]` means `!(x[1])`
  5. // instead of `(!x)[1]` is handled by the fact that the parser
  6. // function that parses unary prefix operators is called first, and
  7. // in turn calls the function that parses `[]` subscripts 鈥 that
  8. // way, it'll receive the node for `x[1]` already parsed, and wraps
  9. // *that* in the unary operator node.
  10. //
  11. // Acorn uses an [operator precedence parser][opp] to handle binary
  12. // operator precedence, because it is much more compact than using
  13. // the technique outlined above, which uses different, nesting
  14. // functions to specify precedence, for all of the ten binary
  15. // precedence levels that JavaScript defines.
  16. //
  17. // [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser
  18.  
  19. import {types as tt} from "./tokentype"
  20. import {Parser} from "./state"
  21. import {DestructuringErrors} from "./parseutil"
  22.  
  23. const pp = Parser.prototype
  24.  
  25. // Check if property name clashes with already added.
  26. // Object/class getters and setters are not allowed to clash 鈥
  27. // either with each other or with an init property 鈥 and in
  28. // strict mode, init properties are also not allowed to be repeated.
  29.  
  30. pp.checkPropClash = function(prop, propHash) {
  31.   if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
  32.     return
  33.   let {key} = prop, name
  34.   switch (key.type) {
  35.   case "Identifier": name = key.name; break
  36.   case "Literal": name = String(key.value); break
  37.   default: return
  38.   }
  39.   let {kind} = prop
  40.   if (this.options.ecmaVersion >= 6) {
  41.     if (name === "__proto__" && kind === "init") {
  42.       if (propHash.proto) this.raiseRecoverable(key.start, "Redefinition of __proto__ property")
  43.       propHash.proto = true
  44.     }
  45.     return
  46.   }
  47.   name = "$" + name
  48.   let other = propHash[name]
  49.   if (other) {
  50.     let isGetSet = kind !== "init"
  51.     if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init))
  52.       this.raiseRecoverable(key.start, "Redefinition of property")
  53.   } else {
  54.     other = propHash[name] = {
  55.       init: false,
  56.       get: false,
  57.       set: false
  58.     }
  59.   }
  60.   other[kind] = true
  61. }
  62.  
  63. // ### Expression parsing
  64.  
  65. // These nest, from the most general expression type at the top to
  66. // 'atomic', nondivisible expression types at the bottom. Most of
  67. // the functions will simply let the function(s) below them parse,
  68. // and, *if* the syntactic construct they handle is present, wrap
  69. // the AST node that the inner parser gave them in another node.
  70.  
  71. // Parse a full expression. The optional arguments are used to
  72. // forbid the `in` operator (in for loops initalization expressions)
  73. // and provide reference for storing '=' operator inside shorthand
  74. // property assignment in contexts where both object expression
  75. // and object pattern might appear (so it's possible to raise
  76. // delayed syntax error at correct position).
  77.  
  78. pp.parseExpression = function(noIn, refDestructuringErrors) {
  79.   let startPos = this.start, startLoc = this.startLoc
  80.   let expr = this.parseMaybeAssign(noIn, refDestructuringErrors)
  81.   if (this.type === tt.comma) {
  82.     let node = this.startNodeAt(startPos, startLoc)
  83.     node.expressions = [expr]
  84.     while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors))
  85.     return this.finishNode(node, "SequenceExpression")
  86.   }
  87.   return expr
  88. }
  89.  
  90. // Parse an assignment expression. This includes applications of
  91. // operators like `+=`.
  92.  
  93. pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {
  94.   if (this.inGenerator && this.isContextual("yield")) return this.parseYield()
  95.  
  96.   let ownDestructuringErrors = false
  97.   if (!refDestructuringErrors) {
  98.     refDestructuringErrors = new DestructuringErrors
  99.     ownDestructuringErrors = true
  100.   }
  101.   let startPos = this.start, startLoc = this.startLoc
  102.   if (this.type == tt.parenL || this.type == tt.name)
  103.     this.potentialArrowAt = this.start
  104.   let left = this.parseMaybeConditional(noIn, refDestructuringErrors)
  105.   if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc)
  106.   if (this.type.isAssign) {
  107.     this.checkPatternErrors(refDestructuringErrors, true)
  108.     if (!ownDestructuringErrors) DestructuringErrors.call(refDestructuringErrors)
  109.     let node = this.startNodeAt(startPos, startLoc)
  110.     node.operator = this.value
  111.     node.left = this.type === tt.eq ? this.toAssignable(left) : left
  112.     refDestructuringErrors.shorthandAssign = 0 // reset because shorthand default was used correctly
  113.     this.checkLVal(left)
  114.     this.next()
  115.     node.right = this.parseMaybeAssign(noIn)
  116.     return this.finishNode(node, "AssignmentExpression")
  117.   } else {
  118.     if (ownDestructuringErrors) this.checkExpressionErrors(refDestructuringErrors, true)
  119.   }
  120.   return left
  121. }
  122.  
  123. // Parse a ternary conditional (`?:`) operator.
  124.  
  125. pp.parseMaybeConditional = function(noIn, refDestructuringErrors) {
  126.   let startPos = this.start, startLoc = this.startLoc
  127.   let expr = this.parseExprOps(noIn, refDestructuringErrors)
  128.   if (this.checkExpressionErrors(refDestructuringErrors)) return expr
  129.   if (this.eat(tt.question)) {
  130.     let node = this.startNodeAt(startPos, startLoc)
  131.     node.test = expr
  132.     node.consequent = this.parseMaybeAssign()
  133.     this.expect(tt.colon)
  134.     node.alternate = this.parseMaybeAssign(noIn)
  135.     return this.finishNode(node, "ConditionalExpression")
  136.   }
  137.   return expr
  138. }
  139.  
  140. // Start the precedence parser.
  141.  
  142. pp.parseExprOps = function(noIn, refDestructuringErrors) {
  143.   let startPos = this.start, startLoc = this.startLoc
  144.   let expr = this.parseMaybeUnary(refDestructuringErrors, false)
  145.   if (this.checkExpressionErrors(refDestructuringErrors)) return expr
  146.   return this.parseExprOp(expr, startPos, startLoc, -1, noIn)
  147. }
  148.  
  149. // Parse binary operators with the operator precedence parsing
  150. // algorithm. `left` is the left-hand side of the operator.
  151. // `minPrec` provides context that allows the function to stop and
  152. // defer further parser to one of its callers when it encounters an
  153. // operator that has a lower precedence than the set it is parsing.
  154.  
  155. pp.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {
  156.   let prec = this.type.binop
  157.   if (prec != null && (!noIn || this.type !== tt._in)) {
  158.     if (prec > minPrec) {
  159.       let logical = this.type === tt.logicalOR || this.type === tt.logicalAND
  160.       let op = this.value
  161.       this.next()
  162.       let startPos = this.start, startLoc = this.startLoc
  163.       let right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn)
  164.       let node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical)
  165.       return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
  166.     }
  167.   }
  168.   return left
  169. }
  170.  
  171. pp.buildBinary = function(startPos, startLoc, left, right, op, logical) {
  172.   let node = this.startNodeAt(startPos, startLoc)
  173.   node.left = left
  174.   node.operator = op
  175.   node.right = right
  176.   return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")
  177. }
  178.  
  179. // Parse unary operators, both prefix and postfix.
  180.  
  181. pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
  182.   let startPos = this.start, startLoc = this.startLoc, expr
  183.   if (this.type.prefix) {
  184.     let node = this.startNode(), update = this.type === tt.incDec
  185.     node.operator = this.value
  186.     node.prefix = true
  187.     this.next()
  188.     node.argument = this.parseMaybeUnary(null, true)
  189.     this.checkExpressionErrors(refDestructuringErrors, true)
  190.     if (update) this.checkLVal(node.argument)
  191.     else if (this.strict && node.operator === "delete" &&
  192.              node.argument.type === "Identifier")
  193.       this.raiseRecoverable(node.start, "Deleting local variable in strict mode")
  194.     else sawUnary = true
  195.     expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression")
  196.   } else {
  197.     expr = this.parseExprSubscripts(refDestructuringErrors)
  198.     if (this.checkExpressionErrors(refDestructuringErrors)) return expr
  199.     while (this.type.postfix && !this.canInsertSemicolon()) {
  200.       let node = this.startNodeAt(startPos, startLoc)
  201.       node.operator = this.value
  202.       node.prefix = false
  203.       node.argument = expr
  204.       this.checkLVal(expr)
  205.       this.next()
  206.       expr = this.finishNode(node, "UpdateExpression")
  207.     }
  208.   }
  209.  
  210.   if (!sawUnary && this.eat(tt.starstar))
  211.     return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false)
  212.   else
  213.     return expr
  214. }
  215.  
  216. // Parse call, dot, and `[]`-subscript expressions.
  217.  
  218. pp.parseExprSubscripts = function(refDestructuringErrors) {
  219.   let startPos = this.start, startLoc = this.startLoc
  220.   let expr = this.parseExprAtom(refDestructuringErrors)
  221.   let skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"
  222.   if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr
  223.   return this.parseSubscripts(expr, startPos, startLoc)
  224. }
  225.  
  226. pp.parseSubscripts = function(base, startPos, startLoc, noCalls) {
  227.   for (;;) {
  228.     if (this.eat(tt.dot)) {
  229.       let node = this.startNodeAt(startPos, startLoc)
  230.       node.object = base
  231.       node.property = this.parseIdent(true)
  232.       node.computed = false
  233.       base = this.finishNode(node, "MemberExpression")
  234.     } else if (this.eat(tt.bracketL)) {
  235.       let node = this.startNodeAt(startPos, startLoc)
  236.       node.object = base
  237.       node.property = this.parseExpression()
  238.       node.computed = true
  239.       this.expect(tt.bracketR)
  240.       base = this.finishNode(node, "MemberExpression")
  241.     } else if (!noCalls && this.eat(tt.parenL)) {
  242.       let node = this.startNodeAt(startPos, startLoc)
  243.       node.callee = base
  244.       node.arguments = this.parseExprList(tt.parenR, false)
  245.       base = this.finishNode(node, "CallExpression")
  246.     } else if (this.type === tt.backQuote) {
  247.       let node = this.startNodeAt(startPos, startLoc)
  248.       node.tag = base
  249.       node.quasi = this.parseTemplate()
  250.       base = this.finishNode(node, "TaggedTemplateExpression")
  251.     } else {
  252.       return base
  253.     }
  254.   }
  255. }
  256.  
  257. // Parse an atomic expression 鈥 either a single token that is an
  258. // expression, an expression started by a keyword like `function` or
  259. // `new`, or an expression wrapped in punctuation like `()`, `[]`,
  260. // or `{}`.
  261.  
  262. pp.parseExprAtom = function(refDestructuringErrors) {
  263.   let node, canBeArrow = this.potentialArrowAt == this.start
  264.   switch (this.type) {
  265.   case tt._super:
  266.     if (!this.inFunction)
  267.       this.raise(this.start, "'super' outside of function or class")
  268.  
  269.   case tt._this:
  270.     let type = this.type === tt._this ? "ThisExpression" : "Super"
  271.     node = this.startNode()
  272.     this.next()
  273.     return this.finishNode(node, type)
  274.  
  275.   case tt.name:
  276.     let startPos = this.start, startLoc = this.startLoc
  277.     let id = this.parseIdent(this.type !== tt.name)
  278.     if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow))
  279.       return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id])
  280.     return id
  281.  
  282.   case tt.regexp:
  283.     let value = this.value
  284.     node = this.parseLiteral(value.value)
  285.     node.regex = {pattern: value.pattern, flags: value.flags}
  286.     return node
  287.  
  288.   case tt.num: case tt.string:
  289.     return this.parseLiteral(this.value)
  290.  
  291.   case tt._null: case tt._true: case tt._false:
  292.     node = this.startNode()
  293.     node.value = this.type === tt._null ? null : this.type === tt._true
  294.     node.raw = this.type.keyword
  295.     this.next()
  296.     return this.finishNode(node, "Literal")
  297.  
  298.   case tt.parenL:
  299.     return this.parseParenAndDistinguishExpression(canBeArrow)
  300.  
  301.   case tt.bracketL:
  302.     node = this.startNode()
  303.     this.next()
  304.     node.elements = this.parseExprList(tt.bracketR, true, true, refDestructuringErrors)
  305.     return this.finishNode(node, "ArrayExpression")
  306.  
  307.   case tt.braceL:
  308.     return this.parseObj(false, refDestructuringErrors)
  309.  
  310.   case tt._function:
  311.     node = this.startNode()
  312.     this.next()
  313.     return this.parseFunction(node, false)
  314.  
  315.   case tt._class:
  316.     return this.parseClass(this.startNode(), false)
  317.  
  318.   case tt._new:
  319.     return this.parseNew()
  320.  
  321.   case tt.backQuote:
  322.     return this.parseTemplate()
  323.  
  324.   default:
  325.     this.unexpected()
  326.   }
  327. }
  328.  
  329. pp.parseLiteral = function(value) {
  330.   let node = this.startNode()
  331.   node.value = value
  332.   node.raw = this.input.slice(this.start, this.end)
  333.   this.next()
  334.   return this.finishNode(node, "Literal")
  335. }
  336.  
  337. pp.parseParenExpression = function() {
  338.   this.expect(tt.parenL)
  339.   let val = this.parseExpression()
  340.   this.expect(tt.parenR)
  341.   return val
  342. }
  343.  
  344. pp.parseParenAndDistinguishExpression = function(canBeArrow) {
  345.   let startPos = this.start, startLoc = this.startLoc, val
  346.   if (this.options.ecmaVersion >= 6) {
  347.     this.next()
  348.  
  349.     let innerStartPos = this.start, innerStartLoc = this.startLoc
  350.     let exprList = [], first = true
  351.     let refDestructuringErrors = new DestructuringErrors, spreadStart, innerParenStart
  352.     while (this.type !== tt.parenR) {
  353.       first ? first = false : this.expect(tt.comma)
  354.       if (this.type === tt.ellipsis) {
  355.         spreadStart = this.start
  356.         exprList.push(this.parseParenItem(this.parseRest()))
  357.         break
  358.       } else {
  359.         if (this.type === tt.parenL && !innerParenStart) {
  360.           innerParenStart = this.start
  361.         }
  362.         exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem))
  363.       }
  364.     }
  365.     let innerEndPos = this.start, innerEndLoc = this.startLoc
  366.     this.expect(tt.parenR)
  367.  
  368.     if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
  369.       this.checkPatternErrors(refDestructuringErrors, true)
  370.       if (innerParenStart) this.unexpected(innerParenStart)
  371.       return this.parseParenArrowList(startPos, startLoc, exprList)
  372.     }
  373.  
  374.     if (!exprList.length) this.unexpected(this.lastTokStart)
  375.     if (spreadStart) this.unexpected(spreadStart)
  376.     this.checkExpressionErrors(refDestructuringErrors, true)
  377.  
  378.     if (exprList.length > 1) {
  379.       val = this.startNodeAt(innerStartPos, innerStartLoc)
  380.       val.expressions = exprList
  381.       this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc)
  382.     } else {
  383.       val = exprList[0]
  384.     }
  385.   } else {
  386.     val = this.parseParenExpression()
  387.   }
  388.  
  389.   if (this.options.preserveParens) {
  390.     let par = this.startNodeAt(startPos, startLoc)
  391.     par.expression = val
  392.     return this.finishNode(par, "ParenthesizedExpression")
  393.   } else {
  394.     return val
  395.   }
  396. }
  397.  
  398. pp.parseParenItem = function(item) {
  399.   return item
  400. }
  401.  
  402. pp.parseParenArrowList = function(startPos, startLoc, exprList) {
  403.   return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)
  404. }
  405.  
  406. // New's precedence is slightly tricky. It must allow its argument to
  407. // be a `[]` or dot subscript expression, but not a call 鈥 at least,
  408. // not without wrapping it in parentheses. Thus, it uses the noCalls
  409. // argument to parseSubscripts to prevent it from consuming the
  410. // argument list.
  411.  
  412. const empty = []
  413.  
  414. pp.parseNew = function() {
  415.   let node = this.startNode()
  416.   let meta = this.parseIdent(true)
  417.   if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) {
  418.     node.meta = meta
  419.     node.property = this.parseIdent(true)
  420.     if (node.property.name !== "target")
  421.       this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target")
  422.     if (!this.inFunction)
  423.       this.raiseRecoverable(node.start, "new.target can only be used in functions")
  424.     return this.finishNode(node, "MetaProperty")
  425.   }
  426.   let startPos = this.start, startLoc = this.startLoc
  427.   node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true)
  428.   if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, false)
  429.   else node.arguments = empty
  430.   return this.finishNode(node, "NewExpression")
  431. }
  432.  
  433. // Parse template expression.
  434.  
  435. pp.parseTemplateElement = function() {
  436.   let elem = this.startNode()
  437.   elem.value = {
  438.     raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'),
  439.     cooked: this.value
  440.   }
  441.   this.next()
  442.   elem.tail = this.type === tt.backQuote
  443.   return this.finishNode(elem, "TemplateElement")
  444. }
  445.  
  446. pp.parseTemplate = function() {
  447.   let node = this.startNode()
  448.   this.next()
  449.   node.expressions = []
  450.   let curElt = this.parseTemplateElement()
  451.   node.quasis = [curElt]
  452.   while (!curElt.tail) {
  453.     this.expect(tt.dollarBraceL)
  454.     node.expressions.push(this.parseExpression())
  455.     this.expect(tt.braceR)
  456.     node.quasis.push(curElt = this.parseTemplateElement())
  457.   }
  458.   this.next()
  459.   return this.finishNode(node, "TemplateLiteral")
  460. }
  461.  
  462. // Parse an object literal or binding pattern.
  463.  
  464. pp.parseObj = function(isPattern, refDestructuringErrors) {
  465.   let node = this.startNode(), first = true, propHash = {}
  466.   node.properties = []
  467.   this.next()
  468.   while (!this.eat(tt.braceR)) {
  469.     if (!first) {
  470.       this.expect(tt.comma)
  471.       if (this.afterTrailingComma(tt.braceR)) break
  472.     } else first = false
  473.  
  474.     let prop = this.startNode(), isGenerator, startPos, startLoc
  475.     if (this.options.ecmaVersion >= 6) {
  476.       prop.method = false
  477.       prop.shorthand = false
  478.       if (isPattern || refDestructuringErrors) {
  479.         startPos = this.start
  480.         startLoc = this.startLoc
  481.       }
  482.       if (!isPattern)
  483.         isGenerator = this.eat(tt.star)
  484.     }
  485.     this.parsePropertyName(prop)
  486.     this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors)
  487.     this.checkPropClash(prop, propHash)
  488.     node.properties.push(this.finishNode(prop, "Property"))
  489.   }
  490.   return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")
  491. }
  492.  
  493. pp.parsePropertyValue = function(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) {
  494.   if (this.eat(tt.colon)) {
  495.     prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors)
  496.     prop.kind = "init"
  497.   } else if (this.options.ecmaVersion >= 6 && this.type === tt.parenL) {
  498.     if (isPattern) this.unexpected()
  499.     prop.kind = "init"
  500.     prop.method = true
  501.     prop.value = this.parseMethod(isGenerator)
  502.   } else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
  503.              (prop.key.name === "get" || prop.key.name === "set") &&
  504.              (this.type != tt.comma && this.type != tt.braceR)) {
  505.     if (isGenerator || isPattern) this.unexpected()
  506.     prop.kind = prop.key.name
  507.     this.parsePropertyName(prop)
  508.     prop.value = this.parseMethod(false)
  509.     let paramCount = prop.kind === "get" ? 0 : 1
  510.     if (prop.value.params.length !== paramCount) {
  511.       let start = prop.value.start
  512.       if (prop.kind === "get")
  513.         this.raiseRecoverable(start, "getter should have no params")
  514.       else
  515.         this.raiseRecoverable(start, "setter should have exactly one param")
  516.     }
  517.     if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
  518.       this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params")
  519.   } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
  520.     if (this.keywords.test(prop.key.name) ||
  521.         (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name) ||
  522.         (this.inGenerator && prop.key.name == "yield"))
  523.       this.raiseRecoverable(prop.key.start, "'" + prop.key.name + "' can not be used as shorthand property")
  524.     prop.kind = "init"
  525.     if (isPattern) {
  526.       prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key)
  527.     } else if (this.type === tt.eq && refDestructuringErrors) {
  528.       if (!refDestructuringErrors.shorthandAssign)
  529.         refDestructuringErrors.shorthandAssign = this.start
  530.       prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key)
  531.     } else {
  532.       prop.value = prop.key
  533.     }
  534.     prop.shorthand = true
  535.   } else this.unexpected()
  536. }
  537.  
  538. pp.parsePropertyName = function(prop) {
  539.   if (this.options.ecmaVersion >= 6) {
  540.     if (this.eat(tt.bracketL)) {
  541.       prop.computed = true
  542.       prop.key = this.parseMaybeAssign()
  543.       this.expect(tt.bracketR)
  544.       return prop.key
  545.     } else {
  546.       prop.computed = false
  547.     }
  548.   }
  549.   return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(true)
  550. }
  551.  
  552. // Initialize empty function node.
  553.  
  554. pp.initFunction = function(node) {
  555.   node.id = null
  556.   if (this.options.ecmaVersion >= 6) {
  557.     node.generator = false
  558.     node.expression = false
  559.   }
  560. }
  561.  
  562. // Parse object or class method.
  563.  
  564. pp.parseMethod = function(isGenerator) {
  565.   let node = this.startNode(), oldInGen = this.inGenerator
  566.   this.inGenerator = isGenerator
  567.   this.initFunction(node)
  568.   this.expect(tt.parenL)
  569.   node.params = this.parseBindingList(tt.parenR, false, false)
  570.   if (this.options.ecmaVersion >= 6)
  571.     node.generator = isGenerator
  572.   this.parseFunctionBody(node, false)
  573.   this.inGenerator = oldInGen
  574.   return this.finishNode(node, "FunctionExpression")
  575. }
  576.  
  577. // Parse arrow function expression with given parameters.
  578.  
  579. pp.parseArrowExpression = function(node, params) {
  580.   let oldInGen = this.inGenerator
  581.   this.inGenerator = false
  582.   this.initFunction(node)
  583.   node.params = this.toAssignableList(params, true)
  584.   this.parseFunctionBody(node, true)
  585.   this.inGenerator = oldInGen
  586.   return this.finishNode(node, "ArrowFunctionExpression")
  587. }
  588.  
  589. // Parse function body and check parameters.
  590.  
  591. pp.parseFunctionBody = function(node, isArrowFunction) {
  592.   let isExpression = isArrowFunction && this.type !== tt.braceL
  593.  
  594.   if (isExpression) {
  595.     node.body = this.parseMaybeAssign()
  596.     node.expression = true
  597.   } else {
  598.     // Start a new scope with regard to labels and the `inFunction`
  599.     // flag (restore them to their old value afterwards).
  600.     let oldInFunc = this.inFunction, oldLabels = this.labels
  601.     this.inFunction = true; this.labels = []
  602.     node.body = this.parseBlock(true)
  603.     node.expression = false
  604.     this.inFunction = oldInFunc; this.labels = oldLabels
  605.   }
  606.  
  607.   // If this is a strict mode function, verify that argument names
  608.   // are not repeated, and it does not try to bind the words `eval`
  609.   // or `arguments`.
  610.   let useStrict = (!isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) ? node.body.body[0] : null;
  611.   if (this.strict || useStrict) {
  612.     let oldStrict = this.strict
  613.     this.strict = true
  614.     if (node.id)
  615.       this.checkLVal(node.id, true)
  616.     this.checkParams(node, useStrict)
  617.     this.strict = oldStrict
  618.   } else if (isArrowFunction) {
  619.     this.checkParams(node, useStrict)
  620.   }
  621. }
  622.  
  623. // Checks function params for various disallowed patterns such as using "eval"
  624. // or "arguments" and duplicate parameters.
  625.  
  626. pp.checkParams = function(node, useStrict) {
  627.     let nameHash = {}
  628.     for (let i = 0; i < node.params.length; i++) {
  629.       if (useStrict && this.options.ecmaVersion >= 7 && node.params[i].type !== "Identifier")
  630.         this.raiseRecoverable(useStrict.start, "Illegal 'use strict' directive in function with non-simple parameter list");
  631.       this.checkLVal(node.params[i], true, nameHash)
  632.     }
  633. }
  634.  
  635. // Parses a comma-separated list of expressions, and returns them as
  636. // an array. `close` is the token type that ends the list, and
  637. // `allowEmpty` can be turned on to allow subsequent commas with
  638. // nothing in between them to be parsed as `null` (which is needed
  639. // for array literals).
  640.  
  641. pp.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {
  642.   let elts = [], first = true
  643.   while (!this.eat(close)) {
  644.     if (!first) {
  645.       this.expect(tt.comma)
  646.       if (allowTrailingComma && this.afterTrailingComma(close)) break
  647.     } else first = false
  648.  
  649.     let elt
  650.     if (allowEmpty && this.type === tt.comma)
  651.       elt = null
  652.     else if (this.type === tt.ellipsis) {
  653.       elt = this.parseSpread(refDestructuringErrors)
  654.       if (this.type === tt.comma && refDestructuringErrors && !refDestructuringErrors.trailingComma) {
  655.         refDestructuringErrors.trailingComma = this.lastTokStart
  656.       }
  657.     } else
  658.       elt = this.parseMaybeAssign(false, refDestructuringErrors)
  659.     elts.push(elt)
  660.   }
  661.   return elts
  662. }
  663.  
  664. // Parse the next token as an identifier. If `liberal` is true (used
  665. // when parsing properties), it will also convert keywords into
  666. // identifiers.
  667.  
  668. pp.parseIdent = function(liberal) {
  669.   let node = this.startNode()
  670.   if (liberal && this.options.allowReserved == "never") liberal = false
  671.   if (this.type === tt.name) {
  672.     if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) &&
  673.         (this.options.ecmaVersion >= 6 ||
  674.          this.input.slice(this.start, this.end).indexOf("\\") == -1))
  675.       this.raiseRecoverable(this.start, "The keyword '" + this.value + "' is reserved")
  676.     if (!liberal && this.inGenerator && this.value === "yield")
  677.       this.raiseRecoverable(this.start, "Can not use 'yield' as identifier inside a generator")
  678.     node.name = this.value
  679.   } else if (liberal && this.type.keyword) {
  680.     node.name = this.type.keyword
  681.   } else {
  682.     this.unexpected()
  683.   }
  684.   this.next()
  685.   return this.finishNode(node, "Identifier")
  686. }
  687.  
  688. // Parses yield expression inside generator.
  689.  
  690. pp.parseYield = function() {
  691.   let node = this.startNode()
  692.   this.next()
  693.   if (this.type == tt.semi || this.canInsertSemicolon() || (this.type != tt.star && !this.type.startsExpr)) {
  694.     node.delegate = false
  695.     node.argument = null
  696.   } else {
  697.     node.delegate = this.eat(tt.star)
  698.     node.argument = this.parseMaybeAssign()
  699.   }
  700.   return this.finishNode(node, "YieldExpression")
  701. }
  702.  
downloadexpression.js Source code - Download reactide Source code
Related Source Codes/Software:
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
postal - 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top