lib/minjs/ecma262/base.rb in minjs-0.3.0 vs lib/minjs/ecma262/base.rb in minjs-0.4.0
- old
+ new
@@ -1,16 +1,26 @@
module Minjs
module ECMA262
+ #ECMA262 Elements
class Base
+ # Returns a ECMAScript string containg the representation of element.
+ # @param options [Hash] options for Base#concat
+ # @return [String] ECMAScript string.
def to_js(options = {})
self.class.to_s + "??"
end
+ # to string
def to_s
to_js({})
end
+ # concatenate some of ECMA262 elements and convert it to ECMAScript
+ #
+ # @param args ECMA262 element
+ # @option options :debug [Boolean] if set, output is easy to read.
+ #
def concat(options, *args)
prev = nil
j = []
args.flatten.each do|x|
sep = ''
@@ -22,30 +32,31 @@
end
if prev
if prev.match(/[\w\$]\z/) and js.match(/\A[\w\$]/)
sep = ' '
end
- #';;' means 'empty statement' that must not be deleted
+ # ';;' means 'empty statement' or separator of 'for statement'
+ # that must not be deleted
if prev.match(/;;\Z/)
prev.sub!(/;;\Z/, ";")
elsif prev.match(/;\Z/) and js == "}"
prev.sub!(/;\Z/, "")
- elsif prev.match(/;\Z/) and js == ";" and !options[:for_args]
+ elsif prev.match(/;\Z/) and js == ";"
prev.sub!(/;\Z/, "")
elsif prev.match(/[\-]\Z/) and js.match(/^\-/)
sep = ' '
elsif prev.match(/[\+]\Z/) and js.match(/^\+/)
sep = ' '
end
end
#for debug
unless options[:no_debug]
if (@logger and @logger.debug?) || options[:debug]
- if js.match(/;\z/) and !options[:for_args]
+ if js.match(/;\z/)
nl = "\n"
end
- if js.match(/}\z/) and !options[:for_args]
+ if js.match(/}\z/)
nl = "\n"
end
end
end
js = "#{sep}#{js}#{nl}";
@@ -53,41 +64,67 @@
prev = js
end
j.join("")
end
+ # Replaces child (if own it) object
+ #
+ # @param from [Base] from
+ # @param to [Base] to
def replace(from, to)
puts "warning: #{self.class}: replace not implement"
end
+ # duplicate object
+ #
+ # duplicate this object's children (if own) and itself.
def deep_dup
puts "warning: #{self.class}: deep_dup not implement"
end
+ # compare object
def ==(obj)
puts "warning: #{self.class}: == not implement"
raise "warning: #{self.class}: == not implement"
end
+ # add / remove parenthesis if need
def add_remove_paren(node = self)
node.traverse(nil) {|st, parent|
if st.respond_to? :remove_paren
st.add_paren
st.remove_paren
end
}
node
end
+
+ # Traverses this children and itself with given block.
+ #
+ # If this element has children, traverse children first,
+ # then yield block with parent and self.
+ #
+ # @param parent [Base] parent element.
+ # @yield [parent, self] parent and this element.
+ # @yieldparam [Base] self this element.
+ # @yieldparam [Base] parent parent element.
+ def traverse(parent, &block)
+
+ end
end
+ # Class of ECMA262 Statement List
+ #
+ # @see http://www.ecma-international.org/ecma-262 ECMA262 12.1
class StatementList < Base
attr_reader :statement_list
def initialize(statement_list)
@statement_list = statement_list #array
end
+ # Groups statements and reduce number of them as few as posibble.
def grouping
remove_empty_statement
new_sl = []
sl = []
g = []
@@ -147,58 +184,73 @@
end
end
@statement_list = new_sl
end
+ # duplicate object
+ # @see Base#deep_dup
def deep_dup
self.class.new(@statement_list.collect{|s| s.deep_dup})
end
+ # Replaces children object
+ # @see Base#replace
def replace(from, to)
idx = @statement_list.index(from)
if idx
@statement_list[idx] = to
end
end
+ # Removes statement from statement list
+ # @param st statement
def remove(st)
@statement_list.delete(st)
end
+ # Removes empty statement in this statement list
def remove_empty_statement
@statement_list.reject!{|x|
x.class == StEmpty
}
end
+ # Traverses this children and itself with given block.
+ # @see Base#traverse
def traverse(parent, &block)
_self = self
@statement_list.each do|st|
st.traverse(self, &block)
end
- yield self, parent
+ yield parent, self
end
+ # compare object
def ==(obj)
@statement_list == obj.statement_list
end
+ # Returns a ECMAScript string containg the representation of element.
+ # @see Base#to_js
def to_js(options = {})
concat options, @statement_list
end
+ # Returns number of the statements
def length
@statement_list.length
end
+ # return true if this can convert to expression.
def to_exp?
@statement_list.each do |s|
return false if s.to_exp? == false
end
return true
end
+ # Converts statement list to expression and returns it.
def to_exp(options = {})
return nil if to_exp? == false
t = @statement_list[0].to_exp(options)
return t.to_exp(options) if @statement_list.length <= 1
i = 1
@@ -211,71 +263,100 @@
def each(&block)
@statement_list.each(&block)
end
+ # Returns the statement at index
+ # @param i index
+ # @return [Statement] statement
def [](i)
@statement_list[i]
end
- def []=(i, s)
- @statement_list[i] = s
+ # Sets the statement at index.
+ # @param i index
+ # @param st statement
+ def []=(i, st)
+ @statement_list[i] = st
end
+ # Returns index of statement.
+ # @param st statement.
+ # @return [Fixnum] index of statement.
def index(st)
@statement_list.index(st)
end
end
+ # Class of ECMA262 Source Elements
+ #
+ # @see http://www.ecma-international.org/ecma-262 ECMA262 14
class SourceElements < StatementList
#
# source_elements: [statement, statement, ...]
#
def initialize(source_elements)
@statement_list = source_elements
end
+ # alias of statement_list
def source_elements
@statement_list
end
+ # alias of statement_list=
def source_elements=(source_elements)
@statement_list = source_elements
end
+ alias :source_elements :statement_list
+
+ # compare object
def ==(obj)
statement_list == obj.statement_list
end
end
+ # Class of ECMA262 Program
+ #
+ # @see http://www.ecma-international.org/ecma-262 ECMA262 14
class Prog < Base
attr_reader :source_elements
attr_reader :context
def initialize(context, source_elements)
@source_elements = source_elements
@context = context
end
+ # duplicate object
+ # @see Base#deep_dup
def deep_dup
self.class.new(context, source_elements.deep_dup)
end
+ # Replaces children object
+ # @see Base#replace
def replace(from, to)
if from == @source_elements
@source_elements = to
end
end
+ # Traverses this children and itself with given block.
+ # @see Base#traverse
def traverse(parent, &block)
@source_elements.traverse(self, &block)
- yield self, parent
+ yield parent, self
end
+ # compare object
def ==(obj)
self.class == obj.class and self.source_elements == obj.source_elements
end
+ # Returns a ECMAScript string containg the representation of element.
+ # @see Base#to_js
def to_js(options = {})
concat options, @source_elements
end
end
end