mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
after a lot of grammar wrestling, got the if-else chains to parse unambiguously. Now you only need a single period to close chains of any length.
This commit is contained in:
parent
a50446a0ca
commit
049358d006
3 changed files with 46 additions and 16 deletions
|
@ -42,6 +42,8 @@ multiline: [
|
|||
if submarine.shields_up
|
||||
full_speed_ahead()
|
||||
fire_torpedos()
|
||||
else if submarine.sinking
|
||||
abandon_ship()
|
||||
else
|
||||
run_away().
|
||||
|
||||
|
|
|
@ -27,8 +27,7 @@ prechigh
|
|||
right '-=' '+=' '/=' '*=' '||=' '&&='
|
||||
right DELETE
|
||||
right RETURN THROW FOR WHILE
|
||||
left UNLESS
|
||||
left IF
|
||||
left UNLESS IF ELSE
|
||||
nonassoc "."
|
||||
preclow
|
||||
|
||||
|
@ -238,17 +237,6 @@ rule
|
|||
| ArgList Terminator Expression { result = val[0] << val[2] }
|
||||
;
|
||||
|
||||
# If statements, including post-fix ifs and unlesses.
|
||||
If:
|
||||
IF Expression
|
||||
Then Expressions "." { result = IfNode.new(val[1], val[3]) }
|
||||
| IF Expression
|
||||
Then Expressions
|
||||
ELSE Expressions "." { result = IfNode.new(val[1], val[3], val[5]) }
|
||||
| Expression IF Expression { result = IfNode.new(val[2], Expressions.new([val[0]])) }
|
||||
| Expression UNLESS Expression { result = IfNode.new(val[2], Expressions.new([val[0]]), nil, :invert) }
|
||||
;
|
||||
|
||||
# Try/catch/finally exception handling blocks.
|
||||
Try:
|
||||
TRY Expressions CATCH IDENTIFIER
|
||||
|
@ -311,6 +299,41 @@ rule
|
|||
CASE Expression Then Expressions { result = IfNode.new(val[1], val[3]) }
|
||||
;
|
||||
|
||||
# All of the following nutso if-else destructuring is to make the
|
||||
# grammar expand unambiguously.
|
||||
|
||||
# An elsif portion of an if-else block.
|
||||
ElsIf:
|
||||
ELSE IF Expression
|
||||
Then Expressions { result = IfNode.new(val[2], val[4]) }
|
||||
;
|
||||
|
||||
# Multiple elsifs can be chained together.
|
||||
ElsIfs:
|
||||
ElsIf { result = val[0] }
|
||||
| ElsIfs ElsIf { result = val[0].add_else(val[1]) }
|
||||
;
|
||||
|
||||
# Terminating else bodies are strictly optional.
|
||||
ElseBody
|
||||
"." { result = nil }
|
||||
| ELSE Expressions "." { result = val[1] }
|
||||
;
|
||||
|
||||
# All the alternatives for ending an if-else block.
|
||||
IfEnd:
|
||||
ElseBody { result = val[0] }
|
||||
| ElsIfs ElseBody { result = val[0].add_else(val[1]) }
|
||||
;
|
||||
|
||||
# The full complement of if blocks, including postfix one-liner ifs and unlesses.
|
||||
If:
|
||||
IF Expression
|
||||
Then Expressions IfEnd { result = IfNode.new(val[1], val[3], val[4]) }
|
||||
| Expression IF Expression { result = IfNode.new(val[2], Expressions.new([val[0]])) }
|
||||
| Expression UNLESS Expression { result = IfNode.new(val[2], Expressions.new([val[0]]), nil, :invert) }
|
||||
;
|
||||
|
||||
end
|
||||
|
||||
---- header
|
||||
|
|
|
@ -464,20 +464,25 @@ module CoffeeScript
|
|||
@is_statement ||= (@body.statement? || (@else_body && @else_body.statement?))
|
||||
end
|
||||
|
||||
def custom_return?
|
||||
statement?
|
||||
end
|
||||
|
||||
def line_ending
|
||||
statement? ? '' : ';'
|
||||
end
|
||||
|
||||
def compile(indent, scope, opts={})
|
||||
statement? ? compile_statement(indent, scope, opts) : compile_ternary(indent, scope)
|
||||
opts[:statement] || statement? ? compile_statement(indent, scope, opts) : compile_ternary(indent, scope)
|
||||
end
|
||||
|
||||
# Compile the IfNode as a regular if-else statement.
|
||||
# Compile the IfNode as a regular if-else statement. Flattened chains
|
||||
# force sub-else bodies into statement form.
|
||||
def compile_statement(indent, scope, opts)
|
||||
if_part = "if (#{@condition.compile(indent, scope, :no_paren => true)}) {\n#{Expressions.wrap(@body).compile(indent + TAB, scope, opts)}\n#{indent}}"
|
||||
return if_part unless @else_body
|
||||
else_part = chain? ?
|
||||
" else #{@else_body.compile(indent, scope, opts)}" :
|
||||
" else #{@else_body.compile(indent, scope, opts.merge(:statement => true))}" :
|
||||
" else {\n#{Expressions.wrap(@else_body).compile(indent + TAB, scope, opts)}\n#{indent}}"
|
||||
if_part + else_part
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue