diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 51156faed2..d234a72e21 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -1227,6 +1227,26 @@ export default class ExpressionParser extends LValParser { return node; } + case tt.moduloAssign: + if ( + this.getPluginOption("pipelineOperator", "proposal") === "hack" && + this.getPluginOption("pipelineOperator", "topicToken") === "%" + ) { + // If we find %= in an expression position, and the Hack-pipes proposal is active, + // then the % could be the topic token (e.g., in x |> %==y or x |> %===y), and so we + // reparse it as %. + // The next readToken() call will start parsing from =. + + this.state.value = "%"; + this.state.type = tt.modulo; + this.state.pos--; + this.state.end--; + this.state.endLoc.column--; + } else { + throw this.unexpected(); + } + + // falls through case tt.modulo: case tt.hash: { const pipeProposal = this.getPluginOption( diff --git a/packages/babel-parser/src/tokenizer/index.js b/packages/babel-parser/src/tokenizer/index.js index a11c916499..0894adf143 100644 --- a/packages/babel-parser/src/tokenizer/index.js +++ b/packages/babel-parser/src/tokenizer/index.js @@ -615,7 +615,7 @@ export default class Tokenizer extends ParserErrors { if (next === charCodes.equalsTo && !this.state.inType) { width++; - type = tt.assign; + type = code === charCodes.percentSign ? tt.moduloAssign : tt.assign; } this.finishOp(type, width); diff --git a/packages/babel-parser/src/tokenizer/types.js b/packages/babel-parser/src/tokenizer/types.js index 6b394ba4db..9188b7b4aa 100644 --- a/packages/babel-parser/src/tokenizer/types.js +++ b/packages/babel-parser/src/tokenizer/types.js @@ -140,6 +140,9 @@ export const types: { [name: string]: TokenType } = { eq: new TokenType("=", { beforeExpr, isAssign }), assign: new TokenType("_=", { beforeExpr, isAssign }), slashAssign: new TokenType("_=", { beforeExpr, isAssign }), + // This is only needed to support % as a Hack-pipe topic token. If the proposal + // ends up choosing a different token, it can be merged with tt.assign. + moduloAssign: new TokenType("_=", { beforeExpr, isAssign }), incDec: new TokenType("++/--", { prefix, postfix, startsExpr }), bang: new TokenType("!", { beforeExpr, prefix, startsExpr }), tilde: new TokenType("~", { beforeExpr, prefix, startsExpr }),