From cea417de0207a9b5b8a6249c32ef4d0dd6a82083 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Mon, 28 Dec 2009 23:08:02 -0500 Subject: [PATCH] moving along with whitespace --- lib/coffee_script/grammar.y | 143 ++++++++---------- .../execution/test_array_comprehension.coffee | 2 +- .../execution/test_assign_to_try_catch.coffee | 2 +- .../execution/test_calling_super.coffee | 16 +- .../execution/test_chained_calls.coffee | 2 +- .../fixtures/execution/test_everything.coffee | 8 +- .../execution/test_fancy_if_statement.coffee | 5 +- .../execution/test_newline_escaping.coffee | 6 +- test/fixtures/execution/test_switch.coffee | 14 +- 9 files changed, 91 insertions(+), 107 deletions(-) diff --git a/lib/coffee_script/grammar.y b/lib/coffee_script/grammar.y index 5eaf94e7..467852db 100644 --- a/lib/coffee_script/grammar.y +++ b/lib/coffee_script/grammar.y @@ -30,11 +30,12 @@ prechigh right '-=' '+=' '/=' '*=' '%=' right DELETE INSTANCEOF TYPEOF left '.' + right INDENT + left OUTDENT right THROW FOR IN WHILE NEW SUPER left UNLESS IF ELSE EXTENDS left ASSIGN '||=' '&&=' - right RETURN INDENT - left OUTDENT + right RETURN preclow # We expect 3 shift/reduce errors for optional syntax. @@ -88,8 +89,7 @@ rule ; Block: - Then Expression { result = Expressions.new([val[1]]) } - | INDENT Expressions OUTDENT { result = val[1] } + INDENT Expressions OUTDENT { result = val[1] } ; # All tokens that can terminate an expression. @@ -98,12 +98,6 @@ rule | ";" ; - # All tokens that can serve to begin the second block of a multi-part expression. - Then: - THEN - | Terminator - ; - # All hard-coded values. Literal: NUMBER { result = LiteralNode.new(val[0]) } @@ -122,13 +116,13 @@ rule # Assignment to a variable. Assign: - Value ASSIGN Expression { result = AssignNode.new(val[0], val[2]) } + Value ASSIGN Expression { result = AssignNode.new(val[0], val[2]) } ; # Assignment within an object literal. AssignObj: - IDENTIFIER ASSIGN Expression { result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) } - | STRING ASSIGN Expression { result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) } + IDENTIFIER ASSIGN Expression { result = AssignNode.new(ValueNode.new(val[0]), val[2], :object) } + | STRING ASSIGN Expression { result = AssignNode.new(ValueNode.new(LiteralNode.new(val[0])), val[2], :object) } | Comment { result = val[0] } ; @@ -146,69 +140,45 @@ rule # For Ruby's Operator precedence, see: # https://www.cs.auckland.ac.nz/references/ruby/ProgrammingRuby/language.html Operation: - '!' Expression { result = OpNode.new(val[0], val[1]) } - | '!!' Expression { result = OpNode.new(val[0], val[1]) } - | '-' Expression = UMINUS { result = OpNode.new(val[0], val[1]) } - | NOT Expression { result = OpNode.new(val[0], val[1]) } - | '~' Expression { result = OpNode.new(val[0], val[1]) } - | '--' Expression { result = OpNode.new(val[0], val[1]) } - | '++' Expression { result = OpNode.new(val[0], val[1]) } - | Expression '--' { result = OpNode.new(val[1], val[0], nil, true) } - | Expression '++' { result = OpNode.new(val[1], val[0], nil, true) } + PrefixOperation + | InfixOperation + | PostfixOperation + ; - | Expression '*' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '/' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '%' Expression { result = OpNode.new(val[1], val[0], val[2]) } + PrefixOperation: + PrefixSymbol PureExpression { result = OpNode.new(val[0], val[1]) } + ; - | Expression '+' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '-' Expression { result = OpNode.new(val[1], val[0], val[2]) } + PostfixOperation: + PureExpression PostfixSymbol { result = OpNode.new(val[1], val[0], nil, true) } + ; - | Expression '<<' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '>>' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '>>>' Expression { result = OpNode.new(val[1], val[0], val[2]) } + InfixOperation: + PureExpression + InfixSymbol PureExpression { result = OpNode.new(val[1], val[0], val[2]) } + ; - | Expression '&' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '|' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '^' Expression { result = OpNode.new(val[1], val[0], val[2]) } + PrefixSymbol: + '!' | '!!' | '-' = UMINUS | NOT | '~' | '--' | '++' | DELETE | TYPEOF + ; - | Expression '<=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '<' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '>' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '>=' Expression { result = OpNode.new(val[1], val[0], val[2]) } + PostfixSymbol: + '--' | '++' + ; - | Expression '==' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '!=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression IS Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression ISNT Expression { result = OpNode.new(val[1], val[0], val[2]) } - - | Expression '&&' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '||' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression AND Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression OR Expression { result = OpNode.new(val[1], val[0], val[2]) } - - | Expression '-=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '+=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '/=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '*=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '%=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '||=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - | Expression '&&=' Expression { result = OpNode.new(val[1], val[0], val[2]) } - - | DELETE Expression { result = OpNode.new(val[0], val[1]) } - | TYPEOF Expression { result = OpNode.new(val[0], val[1]) } - | Expression INSTANCEOF Expression { result = OpNode.new(val[1], val[0], val[2]) } + InfixSymbol: + '*' | '/' | '%' | '+' | '-' | '<<' | '>>' | '>>>' | '&' | '|' | '^' + | '<=' | '<' | '>' | '>=' | '==' | '!=' | IS | ISNT | '&&' | '||' + | AND | OR | '-=' | '+=' | '/=' | '*=' | '%=' | '||=' | '&&=' | INSTANCEOF ; # Function definition. Code: - ParamList "=>" CodeBody { result = CodeNode.new(val[0], val[2]) } - | "=>" CodeBody { result = CodeNode.new([], val[1]) } - ; - - # The body of a function. - CodeBody: - /* nothing */ { result = Expressions.new([]) } - | Block { result = val[0] } + ParamList "=>" Block { result = CodeNode.new(val[0], val[2]) } + | ParamList "=>" Expression { result = CodeNode.new(val[0], Expressions.new([val[2]])) } + | "=>" Block { result = CodeNode.new([], val[1]) } + | "=>" Expression { result = CodeNode.new([], Expressions.new([val[1]])) } + | "=>" { result = CodeNode.new([], nil) } ; # The parameters to a function definition. @@ -299,7 +269,7 @@ rule Try: TRY Block Catch { result = TryNode.new(val[1], val[2][0], val[2][1]) } | TRY Block Catch - FINALLY Block { result = TryNode.new(val[1], val[2][0], val[2][1], val[4]) } + FINALLY Block { result = TryNode.new(val[1], val[2][0], val[2][1], val[4]) } ; # A catch clause. @@ -310,7 +280,7 @@ rule # Throw an exception. Throw: - THROW Expression { result = ThrowNode.new(val[1]) } + THROW PureExpression { result = ThrowNode.new(val[1]) } ; # Parenthetical expressions. @@ -320,7 +290,7 @@ rule # The while loop. (there is no do..while). While: - WHILE Expression Block { result = WhileNode.new(val[1], val[3]) } + WHILE PureExpression Block { result = WhileNode.new(val[1], val[3]) } ; # Array comprehensions, including guard and current index. @@ -328,8 +298,7 @@ rule For: Expression FOR ForVariables ForSource "." { result = ForNode.new(val[0], val[3][0], val[2][0], val[3][1], val[2][1]) } - | FOR ForVariables ForSource - Terminator Expressions "." { result = ForNode.new(val[4], val[2][0], val[1][0], val[2][1], val[1][1]) } + | FOR ForVariables ForSource Block { result = ForNode.new(val[3], val[2][0], val[1][0], val[2][1], val[1][1]) } ; # An array comprehension has variables for the current element and index. @@ -347,10 +316,12 @@ rule # Switch/When blocks. Switch: - SWITCH Expression Then - Whens { result = val[3].rewrite_condition(val[1]) } - | SWITCH Expression Then - Whens ELSE Block { result = val[3].rewrite_condition(val[1]).add_else(val[5]) } + SWITCH Expression INDENT + Whens OUTDENT { result = val[3].rewrite_condition(val[1]) } + | SWITCH Expression INDENT + Whens ELSE Block OUTDENT { result = val[3].rewrite_condition(val[1]).add_else(val[5]) } + | SWITCH Expression INDENT + Whens ELSE Expression OUTDENT { result = val[3].rewrite_condition(val[1]).add_else(val[5]) } ; # The inner list of whens. @@ -361,15 +332,27 @@ rule # An individual when. When: - WHEN Expression Then Block { result = IfNode.new(val[1], val[3]) } + WHEN PureExpression Block { result = IfNode.new(val[1], val[2], nil, {:statement => true}) } + | WHEN PureExpression + THEN Expression Terminator { result = IfNode.new(val[1], val[3], nil, {:statement => true}) } ; # All of the following nutso if-else destructuring is to make the # grammar expand unambiguously. + # The condition itself. + IfClause: + IF PureExpression { result = val[1] } + ; + + IfBlock: + IfClause Block { result = IfNode.new(val[0], val[1]) } + | IfClause THEN Expression { result = IfNode.new(val[0], val[2]) } + ; + # An elsif portion of an if-else block. ElsIf: - ELSE IF Expression Block { result = IfNode.new(val[2], val[4]) } + ELSE IfBlock { result = val[1] } ; # Multiple elsifs can be chained together. @@ -392,9 +375,9 @@ rule # The full complement of if blocks, including postfix one-liner ifs and unlesses. If: - IF Expression Block IfEnd { result = IfNode.new(val[1], val[2], val[3]) } - | Expression IF Expression { result = IfNode.new(val[2], Expressions.new([val[0]]), nil, {:statement => true}) } - | Expression UNLESS Expression { result = IfNode.new(val[2], Expressions.new([val[0]]), nil, {:statement => true, :invert => true}) } + IfBlock IfEnd { result = val[0].add_else(val[1]) } + | Block IfClause { result = IfNode.new(val[1], Expressions.new([val[0]]), nil, {:statement => true}) } + | Block UNLESS PureExpression { result = IfNode.new(val[2], Expressions.new([val[0]]), nil, {:statement => true, :invert => true}) } ; end diff --git a/test/fixtures/execution/test_array_comprehension.coffee b/test/fixtures/execution/test_array_comprehension.coffee index 7df03142..34e2b1e2 100644 --- a/test/fixtures/execution/test_array_comprehension.coffee +++ b/test/fixtures/execution/test_array_comprehension.coffee @@ -3,6 +3,6 @@ results: n * 2 for n in nums. # next: for n in [1, 2, 3] if n % 2 isnt 0 # print('hi') if false -# n * n * 2. +# n * n * 2 print(results.join(',') is '2,18') \ No newline at end of file diff --git a/test/fixtures/execution/test_assign_to_try_catch.coffee b/test/fixtures/execution/test_assign_to_try_catch.coffee index a8397fd0..4db2d263 100644 --- a/test/fixtures/execution/test_assign_to_try_catch.coffee +++ b/test/fixtures/execution/test_assign_to_try_catch.coffee @@ -1,6 +1,6 @@ result: try nonexistent * missing catch error - true. + true print(result) \ No newline at end of file diff --git a/test/fixtures/execution/test_calling_super.coffee b/test/fixtures/execution/test_calling_super.coffee index 10e52c49..d2d6ed0d 100644 --- a/test/fixtures/execution/test_calling_super.coffee +++ b/test/fixtures/execution/test_calling_super.coffee @@ -1,21 +1,21 @@ -Base: => . +Base: => Base.prototype.func: string => - 'zero/' + string. + 'zero/' + string -FirstChild: => . +FirstChild: => FirstChild extends Base FirstChild.prototype.func: string => - super('one/') + string. + super('one/') + string -SecondChild: => . +SecondChild: => SecondChild extends FirstChild SecondChild.prototype.func: string => - super('two/') + string. + super('two/') + string -ThirdChild: => . +ThirdChild: => ThirdChild extends SecondChild ThirdChild.prototype.func: string => - super('three/') + string. + super('three/') + string result: (new ThirdChild()).func('four') diff --git a/test/fixtures/execution/test_chained_calls.coffee b/test/fixtures/execution/test_chained_calls.coffee index ac0ef269..4cf76ec3 100644 --- a/test/fixtures/execution/test_chained_calls.coffee +++ b/test/fixtures/execution/test_chained_calls.coffee @@ -1,4 +1,4 @@ -identity_wrap: x => => x.. +identity_wrap: x => => x result: identity_wrap(identity_wrap(true))()() diff --git a/test/fixtures/execution/test_everything.coffee b/test/fixtures/execution/test_everything.coffee index ca24c640..1ecba88a 100644 --- a/test/fixtures/execution/test_everything.coffee +++ b/test/fixtures/execution/test_everything.coffee @@ -3,7 +3,7 @@ func: => b: [] while a >= 0 b.push('o') - a--. + a-- c: { "text": b @@ -14,14 +14,14 @@ func: => c.text: if false 'error' else - c.text + '---'. + c.text + '---' d = { text = c.text } - c.list: l for l in d.text.split('') if l is '-'. + c.list: l for l in d.text.split('') if l is '-' - c.single: c.list[1..1][0]. + c.single: c.list[1..1][0] print(func() == '-') diff --git a/test/fixtures/execution/test_fancy_if_statement.coffee b/test/fixtures/execution/test_fancy_if_statement.coffee index 9e14947b..1e7546a0 100644 --- a/test/fixtures/execution/test_fancy_if_statement.coffee +++ b/test/fixtures/execution/test_fancy_if_statement.coffee @@ -3,9 +3,8 @@ c: false result: if a if b - if c then false - else + if c then false else if d - true.... + true print(result) \ No newline at end of file diff --git a/test/fixtures/execution/test_newline_escaping.coffee b/test/fixtures/execution/test_newline_escaping.coffee index 2f52e932..972e2f79 100644 --- a/test/fixtures/execution/test_newline_escaping.coffee +++ b/test/fixtures/execution/test_newline_escaping.coffee @@ -1,6 +1,6 @@ six: \ - 1 + \ - 2 + \ - 3 +1 + \ +2 + \ +3 print(six is 6) \ No newline at end of file diff --git a/test/fixtures/execution/test_switch.coffee b/test/fixtures/execution/test_switch.coffee index bce30883..2fc7da81 100644 --- a/test/fixtures/execution/test_switch.coffee +++ b/test/fixtures/execution/test_switch.coffee @@ -1,11 +1,13 @@ num: 10 result: switch num -when 5 then false -when 'a' - false -when 10 then true -when 11 then false -else false. + when 5 then false + when 'a' + true + true + false + when 10 then true + when 11 then false + else false print(result)