@@ -1268,14 +1268,26 @@ export default class ExpressionParser extends LValParser {
12681268 }
12691269 }
12701270
1271- // https://github.com/js-choi/proposal-hack-pipes
1271+ // This helper method attempts to parse a topic reference
1272+ // into a new node.
1273+ // See <https://github.com/js-choi/proposal-hack-pipes>.
1274+ //
1275+ // If the `pipelineOperator` plugin is active,
1276+ // and if the given `tokenType` matches the plugin’s configuration,
1277+ // then this method will return a new node.
1278+ //
1279+ // If the `pipelineOperator` plugin is active,
1280+ // but if the given `tokenType` does not match the plugin’s configuration,
1281+ // then this method will throw a `PipeTopicUnconfiguredToken` error.
1282+ //
1283+ // When an appropriate `pipelineOperator` proposal is not active,
1284+ // this method returns `undefined`.
12721285 maybeParseTopicReference ( ) : ?N . Expression {
1273- const pipeProposal = this . getPluginOption ( "pipelineOperator" , "proposal" ) ;
1274-
12751286 // `pipeProposal` is falsy when an input program
12761287 // contains a topic reference on its own,
12771288 // outside of a pipe expression,
12781289 // and without having turned on the pipelineOperator plugin.
1290+ const pipeProposal = this . getPluginOption ( "pipelineOperator" , "proposal" ) ;
12791291 if ( pipeProposal ) {
12801292 // A pipe-operator proposal is active.
12811293
@@ -1287,48 +1299,62 @@ export default class ExpressionParser extends LValParser {
12871299
12881300 const node = this . startNode ( ) ;
12891301
1290- // Determine the node type for the topic reference
1291- // that is appropriate for the active pipe-operator proposal.
1292- let nodeType ;
1293- if ( pipeProposal === "smart" ) {
1294- nodeType = "PipelinePrimaryTopicReference" ;
1295- } else {
1296- // The proposal must otherwise be "hack",
1297- // as enforced by testTopicReferenceConfiguration.
1298- nodeType = "TopicReference" ;
1299- }
1300-
13011302 // Consume the token.
13021303 this . next ( ) ;
13031304
1304- // Register the topic reference so that its pipe body knows
1305- // that its topic was used at least once.
1306- this . registerTopicReference ( ) ;
1307-
1308- if ( ! this . topicReferenceIsAllowedInCurrentContext ( ) ) {
1309- // The topic reference is not allowed in the current context:
1310- // it is outside of a pipe body.
1311- // Raise recoverable errors.
1312- if ( pipeProposal === "smart" ) {
1313- this . raise ( this . state . start , Errors . PrimaryTopicNotAllowed ) ;
1314- } else {
1315- // In this case, `pipeProposal === "hack"` is true.
1316- this . raise ( this . state . start , Errors . PipeTopicUnbound ) ;
1317- }
1318- }
1305+ const start = this . state . start ;
13191306
1320- return this . finishNode ( node , nodeType ) ;
1307+ return this . finishTopicReferenceNode ( node , start , pipeProposal ) ;
13211308 } else {
13221309 // The token does not match the plugin’s configuration.
1310+ const start = this . state . start ;
13231311 throw this . raise (
1324- this . state . start ,
1312+ start ,
13251313 Errors . PipeTopicUnconfiguredToken ,
13261314 tokenType . label ,
13271315 ) ;
13281316 }
13291317 }
13301318 }
13311319
1320+ // This helper method attempts to finish the given `node`
1321+ // into a topic-reference node for the given `pipeProposal`.
1322+ // The method assumes that any topic token was consumed before it was called.
1323+ finishTopicReferenceNode (
1324+ node : N . Node ,
1325+ start : number ,
1326+ pipeProposal : string ,
1327+ ) : ?N . Expression {
1328+ // Determine the node type for the topic reference
1329+ // that is appropriate for the active pipe-operator proposal.
1330+ let nodeType ;
1331+ if ( pipeProposal === "smart" ) {
1332+ nodeType = "PipelinePrimaryTopicReference" ;
1333+ } else {
1334+ // The proposal must otherwise be "hack",
1335+ // as enforced by testTopicReferenceConfiguration.
1336+ nodeType = "TopicReference ";
1337+ }
1338+
1339+ if ( ! this . topicReferenceIsAllowedInCurrentContext ( ) ) {
1340+ // The topic reference is not allowed in the current context:
1341+ // it is outside of a pipe body.
1342+ // Raise recoverable errors.
1343+ if ( pipeProposal === "smart" ) {
1344+ this . raise ( start , Errors . PrimaryTopicNotAllowed ) ;
1345+ } else {
1346+ // In this case, `pipeProposal === "hack"` is true.
1347+ this . raise ( start , Errors . PipeTopicUnbound ) ;
1348+ }
1349+ }
1350+
1351+ // Register the topic reference so that its pipe body knows
1352+ // that its topic was used at least once.
1353+ this . registerTopicReference ( ) ;
1354+
1355+ return this . finishNode ( node , nodeType ) ;
1356+ }
1357+
13321358 // This helper method tests whether the given token type
13331359 // matches the pipelineOperator parser plugin’s configuration.
13341360 // If the active pipe proposal is Hack style,
0 commit comments