diff --git a/source/parser.hera b/source/parser.hera index 61b5084e..33750dba 100644 --- a/source/parser.hera +++ b/source/parser.hera @@ -2437,15 +2437,17 @@ FunctionExpression block, } - # BinaryOp function shorthand - !ArrowFunction OpenParen:open BinaryOp:op CloseParen:close -> + # BinaryOp function shorthand (op) + !ArrowFunction OpenParen:open __:ws1 BinaryOp:op __:ws2 CloseParen:close -> // (foo) doesn't need an arrow wrapper; just foo suffices if (op.special && op.call && !op.negated) return op.call + if (!ws1) ws1 = op.spaced ? [" "] : [] + if (!ws2) ws2 = op.spaced ? [" "] : [] const refA = makeRef("a"), refB = makeRef("b"), body = processBinaryOpExpression([refA, [ - [[], op, [], refB] // BinaryOpRHS + [ws1, op, ws2, refB] // BinaryOpRHS ]]) const parameterList = [ [ refA, "," ], refB ] @@ -2474,6 +2476,8 @@ FunctionExpression # Haskell-style sections OpenParen:open NonPipelineAssignmentExpression:lhs __:ws1 BinaryOp:op __:ws2 CloseParen:close -> + if (!ws1) ws1 = op.spaced ? [" "] : [] + if (!ws2) ws2 = op.spaced ? [" "] : [] const refB = makeRef("b") const fn = makeAmpersandFunction({ ref: refB, @@ -2520,6 +2524,8 @@ FunctionExpression expression: fn, } OpenParen:open __:ws1 !/\+\+|--|⧺|—|[\+\-&]\S/ !( Placeholder ( TypePostfix / BinaryOpRHS ) ) BinaryOp:op __:ws2 NonPipelineAssignmentExpression:rhs CloseParen:close -> + if (!ws1) ws1 = op.spaced ? [" "] : [] + if (!ws2) ws2 = op.spaced ? [" "] : [] const refA = makeRef("a") const fn = makeAmpersandFunction({ ref: refA, @@ -4222,6 +4228,7 @@ BinaryOpSymbol return { $loc, token: "instanceof", + spaced: true, relational: true, special: true, } @@ -4229,6 +4236,7 @@ BinaryOpSymbol return { $loc, token: "instanceof", + spaced: true, relational: true, special: true, negated: true, @@ -4283,6 +4291,7 @@ BinaryOpSymbol return { $loc, token: $1, + spaced: true, relational: true, special: true, // for typeof shorthand } @@ -4363,6 +4372,7 @@ CoffeeOfOp return { $loc, token: "in", + spaced: true, special: true, negated: true, } @@ -4380,6 +4390,7 @@ NotOp return { $loc, token: "instanceof", + spaced: true, relational: true, special: true, negated: true, @@ -4388,6 +4399,7 @@ NotOp return { $loc, token: "in", + spaced: true, special: true, negated: true, } @@ -6778,7 +6790,7 @@ Import In "in" NonIdContinue -> - return { $loc, token: $1 } + return { $loc, token: $1, spaced: true } Infer "infer" NonIdContinue -> diff --git a/source/parser/types.civet b/source/parser/types.civet index 90df9abe..71f03ed9 100644 --- a/source/parser/types.civet +++ b/source/parser/types.civet @@ -194,12 +194,14 @@ export type CommentNode = export type BinaryOp = (string & name?: never + spaced?: never special?: never relational?: never assoc?: never type?: undefined ) | (ASTLeaf & type?: undefined + spaced?: boolean special?: true // The following are allowed only when special is true: prec?: string | number | undefined diff --git a/test/function-block-shorthand.civet b/test/function-block-shorthand.civet index c0fc7ac6..e11c20dc 100644 --- a/test/function-block-shorthand.civet +++ b/test/function-block-shorthand.civet @@ -888,6 +888,34 @@ describe "(op) shorthand", -> items.reduce(((a2,b2) => a2||b2), false) """ + testCase """ + binary op with spaces + --- + ( +/*rhs*/) + (in) + ( in) + (in ) + ( in ) + (not in) + (!in) + (instanceof) + (!instanceof) + ( a +/*rhs*/b); + ((a1,b1) => a1 in b1); + ((a2,b2) => a2 in b2); + ((a3,b3) => a3 in b3); + ((a4,b4) => a4 in b4); + ((a5,b5) => !(a5 in b5)); + ((a6,b6) => !(a6 in b6)); + ((a7,b7) => a7 instanceof b7); + ((a8,b8) => !(a8 instanceof b8)); + ((a9,b9) => a9 instanceof b9); + ((a10,b10) => !(a10 instanceof b10)) + """ + testCase """ binary & --- @@ -1064,9 +1092,27 @@ describe "operator sections", -> testCase """ left section with spaces --- - items.map (1 + ) - --- - items.map((b => 1 + b)) + (1 +/*rhs*/) + (1 in) + (1 in ) + (1 in ) + (1 not in) + (1 !in) + (1 instanceof) + (1 !instanceof) + (1 1 +/*rhs*/b); + (b1 => 1 in b1); + (b2 => 1 in b2); + (b3 => 1 in b3); + (b4 => !(1 in b4)); + (b5 => !(1 in b5)); + (b6 => 1 instanceof b6); + (b7 => !(1 instanceof b7)); + (b8 => 1 instanceof b8); + (b9 => !(1 instanceof b9)) """ testCase """ @@ -1088,9 +1134,27 @@ describe "operator sections", -> testCase """ right section with spaces --- - items.map ( + 1) - --- - items.map((a => a + 1)) + (/*lhs*/+ x) + (in x) + ( in x) + ( in x) + (not in x) + (!in x) + (instanceof x) + (!instanceof x) + ( a/*lhs*/+ x); + (a1 => a1 in x); + (a2 => a2 in x); + (a3 => a3 in x); + (a4 => !(a4 in x)); + (a5 => !(a5 in x)); + (a6 => a6 instanceof x); + (a7 => !(a7 instanceof x)); + (a8 => a8 instanceof x); + (a9 => !(a9 instanceof x)) """ testCase """