react / wstein / node_modules / browserify / node_modules / syntax-error / node_modules / acorn / src / loose / expression.js
80555 viewsimport {LooseParser} from "./state"1import {isDummy} from "./parseutil"2import {tokTypes as tt} from ".."34const lp = LooseParser.prototype56lp.checkLVal = function(expr, binding) {7if (!expr) return expr8switch (expr.type) {9case "Identifier":10return expr1112case "MemberExpression":13return binding ? this.dummyIdent() : expr1415case "ParenthesizedExpression":16expr.expression = this.checkLVal(expr.expression, binding)17return expr1819// FIXME recursively check contents20case "ObjectPattern":21case "ArrayPattern":22case "RestElement":23case "AssignmentPattern":24if (this.options.ecmaVersion >= 6) return expr2526default:27return this.dummyIdent()28}29}3031lp.parseExpression = function(noIn) {32let start = this.storeCurrentPos()33let expr = this.parseMaybeAssign(noIn)34if (this.tok.type === tt.comma) {35let node = this.startNodeAt(start)36node.expressions = [expr]37while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn))38return this.finishNode(node, "SequenceExpression")39}40return expr41}4243lp.parseParenExpression = function() {44this.pushCx()45this.expect(tt.parenL)46let val = this.parseExpression()47this.popCx()48this.expect(tt.parenR)49return val50}5152lp.parseMaybeAssign = function(noIn) {53let start = this.storeCurrentPos()54let left = this.parseMaybeConditional(noIn)55if (this.tok.type.isAssign) {56let node = this.startNodeAt(start)57node.operator = this.tok.value58node.left = this.tok.type === tt.eq ? this.toAssignable(left) : this.checkLVal(left)59this.next()60node.right = this.parseMaybeAssign(noIn)61return this.finishNode(node, "AssignmentExpression")62}63return left64}6566lp.parseMaybeConditional = function(noIn) {67let start = this.storeCurrentPos()68let expr = this.parseExprOps(noIn)69if (this.eat(tt.question)) {70let node = this.startNodeAt(start)71node.test = expr72node.consequent = this.parseMaybeAssign()73node.alternate = this.expect(tt.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent()74return this.finishNode(node, "ConditionalExpression")75}76return expr77}7879lp.parseExprOps = function(noIn) {80let start = this.storeCurrentPos()81let indent = this.curIndent, line = this.curLineStart82return this.parseExprOp(this.parseMaybeUnary(noIn), start, -1, noIn, indent, line)83}8485lp.parseExprOp = function(left, start, minPrec, noIn, indent, line) {86if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) return left87let prec = this.tok.type.binop88if (prec != null && (!noIn || this.tok.type !== tt._in)) {89if (prec > minPrec) {90let node = this.startNodeAt(start)91node.left = left92node.operator = this.tok.value93this.next()94if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) {95node.right = this.dummyIdent()96} else {97let rightStart = this.storeCurrentPos()98node.right = this.parseExprOp(this.parseMaybeUnary(noIn), rightStart, prec, noIn, indent, line)99}100this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression")101return this.parseExprOp(node, start, minPrec, noIn, indent, line)102}103}104return left105}106107lp.parseMaybeUnary = function(noIn) {108if (this.tok.type.prefix) {109let node = this.startNode(), update = this.tok.type === tt.incDec110node.operator = this.tok.value111node.prefix = true112this.next()113node.argument = this.parseMaybeUnary(noIn)114if (update) node.argument = this.checkLVal(node.argument)115return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression")116} else if (this.tok.type === tt.ellipsis) {117let node = this.startNode()118this.next()119node.argument = this.parseMaybeUnary(noIn)120return this.finishNode(node, "SpreadElement")121}122let start = this.storeCurrentPos()123let expr = this.parseExprSubscripts()124while (this.tok.type.postfix && !this.canInsertSemicolon()) {125let node = this.startNodeAt(start)126node.operator = this.tok.value127node.prefix = false128node.argument = this.checkLVal(expr)129this.next()130expr = this.finishNode(node, "UpdateExpression")131}132return expr133}134135lp.parseExprSubscripts = function() {136let start = this.storeCurrentPos()137return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart)138}139140lp.parseSubscripts = function(base, start, noCalls, startIndent, line) {141for (;;) {142if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine()) {143if (this.tok.type == tt.dot && this.curIndent == startIndent)144--startIndent145else146return base147}148149if (this.eat(tt.dot)) {150let node = this.startNodeAt(start)151node.object = base152if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine())153node.property = this.dummyIdent()154else155node.property = this.parsePropertyAccessor() || this.dummyIdent()156node.computed = false157base = this.finishNode(node, "MemberExpression")158} else if (this.tok.type == tt.bracketL) {159this.pushCx()160this.next()161let node = this.startNodeAt(start)162node.object = base163node.property = this.parseExpression()164node.computed = true165this.popCx()166this.expect(tt.bracketR)167base = this.finishNode(node, "MemberExpression")168} else if (!noCalls && this.tok.type == tt.parenL) {169let node = this.startNodeAt(start)170node.callee = base171node.arguments = this.parseExprList(tt.parenR)172base = this.finishNode(node, "CallExpression")173} else if (this.tok.type == tt.backQuote) {174let node = this.startNodeAt(start)175node.tag = base176node.quasi = this.parseTemplate()177base = this.finishNode(node, "TaggedTemplateExpression")178} else {179return base180}181}182}183184lp.parseExprAtom = function() {185let node186switch (this.tok.type) {187case tt._this:188case tt._super:189let type = this.tok.type === tt._this ? "ThisExpression" : "Super"190node = this.startNode()191this.next()192return this.finishNode(node, type)193194case tt.name:195let start = this.storeCurrentPos()196let id = this.parseIdent()197return this.eat(tt.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id]) : id198199case tt.regexp:200node = this.startNode()201let val = this.tok.value202node.regex = {pattern: val.pattern, flags: val.flags}203node.value = val.value204node.raw = this.input.slice(this.tok.start, this.tok.end)205this.next()206return this.finishNode(node, "Literal")207208case tt.num: case tt.string:209node = this.startNode()210node.value = this.tok.value211node.raw = this.input.slice(this.tok.start, this.tok.end)212this.next()213return this.finishNode(node, "Literal")214215case tt._null: case tt._true: case tt._false:216node = this.startNode()217node.value = this.tok.type === tt._null ? null : this.tok.type === tt._true218node.raw = this.tok.type.keyword219this.next()220return this.finishNode(node, "Literal")221222case tt.parenL:223let parenStart = this.storeCurrentPos()224this.next()225let inner = this.parseExpression()226this.expect(tt.parenR)227if (this.eat(tt.arrow)) {228return this.parseArrowExpression(this.startNodeAt(parenStart), inner.expressions || (isDummy(inner) ? [] : [inner]))229}230if (this.options.preserveParens) {231let par = this.startNodeAt(parenStart)232par.expression = inner233inner = this.finishNode(par, "ParenthesizedExpression")234}235return inner236237case tt.bracketL:238node = this.startNode()239node.elements = this.parseExprList(tt.bracketR, true)240return this.finishNode(node, "ArrayExpression")241242case tt.braceL:243return this.parseObj()244245case tt._class:246return this.parseClass()247248case tt._function:249node = this.startNode()250this.next()251return this.parseFunction(node, false)252253case tt._new:254return this.parseNew()255256case tt._yield:257node = this.startNode()258this.next()259if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type != tt.star && !this.tok.type.startsExpr)) {260node.delegate = false261node.argument = null262} else {263node.delegate = this.eat(tt.star)264node.argument = this.parseMaybeAssign()265}266return this.finishNode(node, "YieldExpression")267268case tt.backQuote:269return this.parseTemplate()270271default:272return this.dummyIdent()273}274}275276lp.parseNew = function() {277let node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart278let meta = this.parseIdent(true)279if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) {280node.meta = meta281node.property = this.parseIdent(true)282return this.finishNode(node, "MetaProperty")283}284let start = this.storeCurrentPos()285node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line)286if (this.tok.type == tt.parenL) {287node.arguments = this.parseExprList(tt.parenR)288} else {289node.arguments = []290}291return this.finishNode(node, "NewExpression")292}293294lp.parseTemplateElement = function() {295let elem = this.startNode()296elem.value = {297raw: this.input.slice(this.tok.start, this.tok.end),298cooked: this.tok.value299}300this.next()301elem.tail = this.tok.type === tt.backQuote302return this.finishNode(elem, "TemplateElement")303}304305lp.parseTemplate = function() {306let node = this.startNode()307this.next()308node.expressions = []309let curElt = this.parseTemplateElement()310node.quasis = [curElt]311while (!curElt.tail) {312this.next()313node.expressions.push(this.parseExpression())314if (this.expect(tt.braceR)) {315curElt = this.parseTemplateElement()316} else {317curElt = this.startNode()318curElt.value = {cooked: '', raw: ''}319curElt.tail = true320}321node.quasis.push(curElt)322}323this.expect(tt.backQuote)324return this.finishNode(node, "TemplateLiteral")325}326327lp.parseObj = function() {328let node = this.startNode()329node.properties = []330this.pushCx()331let indent = this.curIndent + 1, line = this.curLineStart332this.eat(tt.braceL)333if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart }334while (!this.closes(tt.braceR, indent, line)) {335let prop = this.startNode(), isGenerator, start336if (this.options.ecmaVersion >= 6) {337start = this.storeCurrentPos()338prop.method = false339prop.shorthand = false340isGenerator = this.eat(tt.star)341}342this.parsePropertyName(prop)343if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue }344if (this.eat(tt.colon)) {345prop.kind = "init"346prop.value = this.parseMaybeAssign()347} else if (this.options.ecmaVersion >= 6 && (this.tok.type === tt.parenL || this.tok.type === tt.braceL)) {348prop.kind = "init"349prop.method = true350prop.value = this.parseMethod(isGenerator)351} else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" &&352!prop.computed && (prop.key.name === "get" || prop.key.name === "set") &&353(this.tok.type != tt.comma && this.tok.type != tt.braceR)) {354prop.kind = prop.key.name355this.parsePropertyName(prop)356prop.value = this.parseMethod(false)357} else {358prop.kind = "init"359if (this.options.ecmaVersion >= 6) {360if (this.eat(tt.eq)) {361let assign = this.startNodeAt(start)362assign.operator = "="363assign.left = prop.key364assign.right = this.parseMaybeAssign()365prop.value = this.finishNode(assign, "AssignmentExpression")366} else {367prop.value = prop.key368}369} else {370prop.value = this.dummyIdent()371}372prop.shorthand = true373}374node.properties.push(this.finishNode(prop, "Property"))375this.eat(tt.comma)376}377this.popCx()378if (!this.eat(tt.braceR)) {379// If there is no closing brace, make the node span to the start380// of the next token (this is useful for Tern)381this.last.end = this.tok.start382if (this.options.locations) this.last.loc.end = this.tok.loc.start383}384return this.finishNode(node, "ObjectExpression")385}386387lp.parsePropertyName = function(prop) {388if (this.options.ecmaVersion >= 6) {389if (this.eat(tt.bracketL)) {390prop.computed = true391prop.key = this.parseExpression()392this.expect(tt.bracketR)393return394} else {395prop.computed = false396}397}398let key = (this.tok.type === tt.num || this.tok.type === tt.string) ? this.parseExprAtom() : this.parseIdent()399prop.key = key || this.dummyIdent()400}401402lp.parsePropertyAccessor = function() {403if (this.tok.type === tt.name || this.tok.type.keyword) return this.parseIdent()404}405406lp.parseIdent = function() {407let name = this.tok.type === tt.name ? this.tok.value : this.tok.type.keyword408if (!name) return this.dummyIdent()409let node = this.startNode()410this.next()411node.name = name412return this.finishNode(node, "Identifier")413}414415lp.initFunction = function(node) {416node.id = null417node.params = []418if (this.options.ecmaVersion >= 6) {419node.generator = false420node.expression = false421}422}423424// Convert existing expression atom to assignable pattern425// if possible.426427lp.toAssignable = function(node, binding) {428if (this.options.ecmaVersion >= 6 && node) {429switch (node.type) {430case "ObjectExpression":431node.type = "ObjectPattern"432let props = node.properties433for (let i = 0; i < props.length; i++)434this.toAssignable(props[i].value, binding)435break436437case "ArrayExpression":438node.type = "ArrayPattern"439this.toAssignableList(node.elements, binding)440break441442case "SpreadElement":443node.type = "RestElement"444node.argument = this.toAssignable(node.argument, binding)445break446447case "AssignmentExpression":448node.type = "AssignmentPattern"449break450}451}452return this.checkLVal(node, binding)453}454455lp.toAssignableList = function(exprList, binding) {456for (let i = 0; i < exprList.length; i++)457exprList[i] = this.toAssignable(exprList[i], binding)458return exprList459}460461lp.parseFunctionParams = function(params) {462params = this.parseExprList(tt.parenR)463return this.toAssignableList(params, true)464}465466lp.parseMethod = function(isGenerator) {467let node = this.startNode()468this.initFunction(node)469node.params = this.parseFunctionParams()470node.generator = isGenerator || false471node.expression = this.options.ecmaVersion >= 6 && this.tok.type !== tt.braceL472node.body = node.expression ? this.parseMaybeAssign() : this.parseBlock()473return this.finishNode(node, "FunctionExpression")474}475476lp.parseArrowExpression = function(node, params) {477this.initFunction(node)478node.params = this.toAssignableList(params, true)479node.expression = this.tok.type !== tt.braceL480node.body = node.expression ? this.parseMaybeAssign() : this.parseBlock()481return this.finishNode(node, "ArrowFunctionExpression")482}483484lp.parseExprList = function(close, allowEmpty) {485this.pushCx()486let indent = this.curIndent, line = this.curLineStart, elts = []487this.next(); // Opening bracket488while (!this.closes(close, indent + 1, line)) {489if (this.eat(tt.comma)) {490elts.push(allowEmpty ? null : this.dummyIdent())491continue492}493let elt = this.parseMaybeAssign()494if (isDummy(elt)) {495if (this.closes(close, indent, line)) break496this.next()497} else {498elts.push(elt)499}500this.eat(tt.comma)501}502this.popCx()503if (!this.eat(close)) {504// If there is no closing brace, make the node span to the start505// of the next token (this is useful for Tern)506this.last.end = this.tok.start507if (this.options.locations) this.last.loc.end = this.tok.loc.start508}509return elts510}511512513