diff --git a/lib/coffee_script/nodes.rb b/lib/coffee_script/nodes.rb index 50df8f0c..a09a5bb9 100644 --- a/lib/coffee_script/nodes.rb +++ b/lib/coffee_script/nodes.rb @@ -86,6 +86,8 @@ module CoffeeScript class LiteralNode < Node STATEMENTS = ['break', 'continue'] + attr_reader :value + def initialize(value) @value = value end @@ -104,6 +106,8 @@ module CoffeeScript statement custom_return + attr_reader :expression + def initialize(expression) @expression = expression end @@ -120,6 +124,8 @@ module CoffeeScript class CallNode < Node LEADING_DOT = /\A\./ + attr_reader :variable, :arguments + def initialize(variable, arguments=[]) @variable, @arguments = variable, arguments end @@ -148,10 +154,10 @@ module CoffeeScript # A value, indexed or dotted into or vanilla. class ValueNode < Node - attr_reader :name, :properties, :last + attr_reader :literal, :properties, :last - def initialize(name, properties=[]) - @name, @properties = name, properties + def initialize(literal, properties=[]) + @literal, @properties = literal, properties end def <<(other) @@ -164,7 +170,7 @@ module CoffeeScript end def compile(indent, scope, opts={}) - parts = [@name, @properties].flatten.map do |v| + parts = [@literal, @properties].flatten.map do |v| v.respond_to?(:compile) ? v.compile(indent, scope) : v.to_s end @last = parts.last @@ -174,6 +180,8 @@ module CoffeeScript # A dotted accessor into a part of a value. class AccessorNode + attr_reader :name + def initialize(name) @name = name end @@ -185,6 +193,8 @@ module CoffeeScript # An indexed accessor into a part of an array or object. class IndexNode + attr_reader :index + def initialize(index) @index = index end @@ -198,6 +208,8 @@ module CoffeeScript # specifies the index of the end of the slice (just like the first parameter) # is the index of the beginning. class SliceNode + attr_reader :from, :to + def initialize(from, to) @from, @to = from, to end @@ -248,6 +260,8 @@ module CoffeeScript } CONDITIONALS = ['||=', '&&='] + attr_reader :operator, :first, :second + def initialize(operator, first, second=nil) @first, @second = first, second @operator = CONVERSIONS[operator] || operator @@ -277,6 +291,8 @@ module CoffeeScript # A function definition. The only node that creates a new Scope. class CodeNode < Node + attr_reader :params, :body + def initialize(params, body) @params = params @body = body @@ -293,6 +309,8 @@ module CoffeeScript # An object literal. class ObjectNode < Node + attr_reader :properties + def initialize(properties = []) @properties = properties end @@ -305,6 +323,8 @@ module CoffeeScript # An array literal. class ArrayNode < Node + attr_reader :objects + def initialize(objects=[]) @objects = objects end @@ -320,6 +340,8 @@ module CoffeeScript class WhileNode < Node statement + attr_reader :condition, :body + def initialize(condition, body) @condition, @body = condition, body end @@ -342,6 +364,8 @@ module CoffeeScript custom_return custom_assign + attr_reader :body, :source, :name, :index + def initialize(body, source, name, index=nil) @body, @source, @name, @index = body, source, name, index end @@ -383,6 +407,8 @@ module CoffeeScript class TryNode < Node statement + attr_reader :try, :error, :recovery, :finally + def initialize(try, error, recovery, finally=nil) @try, @error, @recovery, @finally = try, error, recovery, finally end @@ -402,6 +428,8 @@ module CoffeeScript class ThrowNode < Node statement + attr_reader :expression + def initialize(expression) @expression = expression end @@ -413,6 +441,8 @@ module CoffeeScript # An extra set of parenthesis, supplied by the script source. class ParentheticalNode < Node + attr_reader :expressions + def initialize(expressions) @expressions = expressions end @@ -429,6 +459,8 @@ module CoffeeScript # Single-expression IfNodes are compiled into ternary operators if possible, # because ternaries are first-class returnable assignable expressions. class IfNode < Node + attr_reader :condition, :body, :else_body + def initialize(condition, body, else_body=nil, tag=nil) @condition = condition @body = body && body.unwrap diff --git a/test/unit/test_parser.rb b/test/unit/test_parser.rb index e74c6d56..d338783e 100644 --- a/test/unit/test_parser.rb +++ b/test/unit/test_parser.rb @@ -13,25 +13,29 @@ class ParserTest < Test::Unit::TestCase end def test_parsing_a_basic_assignment - nodes = @par.parse("a: 'one'") - assert nodes.expressions.length == 1 - assign = nodes.expressions.first + nodes = @par.parse("a: 'one'").expressions + assert nodes.length == 1 + assign = nodes.first assert assign.is_a? AssignNode - assert assign.variable.name == 'a' + assert assign.variable.literal == 'a' end - # - # def test_lexing_object_literal - # code = "{one : 1}" - # assert @lex.tokenize(code) == [["{", "{"], [:IDENTIFIER, "one"], [":", ":"], - # [:NUMBER, "1"], ["}", "}"]] - # end - # - # def test_lexing_function_definition - # code = "x => x * x." - # assert @lex.tokenize(code) == [[:PARAM, "x"], ["=>", "=>"], - # [:IDENTIFIER, "x"], ["*", "*"], [:IDENTIFIER, "x"], [".", "."]] - # end - # + + def test_parsing_an_object_literal + nodes = @par.parse("{one : 1 \n two : 2}").expressions + obj = nodes.first.literal + assert obj.is_a? ObjectNode + assert obj.properties.first.variable == "one" + assert obj.properties.last.variable == "two" + end + + def test_parsing_an_function_definition + code = @par.parse("x, y => x * y.").expressions.first + assert code.params == ['x', 'y'] + body = code.body.expressions.first + assert body.is_a? OpNode + assert body.operator == '*' + end + # def test_lexing_if_statement # code = "clap_your_hands() if happy" # assert @lex.tokenize(code) == [[:IDENTIFIER, "clap_your_hands"], ["(", "("],