class UdonParser::Parser

Public Instance Methods

ensure_encoding(source) click to toggle source
# File lib/udon/udon_parser.rb, line 69
def ensure_encoding(source)
  if defined?(::Encoding)
    if source.encoding == ::Encoding::ASCII_8BIT
      b = source[0, 4].bytes.to_a
      source =
        case
        when b.size>=4 && b[0]==0 && b[1]==0 && b[2]==0
          source.dup.force_encoding(::Encoding::UTF_32BE).encode!(::Encoding::UTF_8)
        when b.size>=4 && b[0]==0 && b[2]==0
          source.dup.force_encoding(::Encoding::UTF_16BE).encode!(::Encoding::UTF_8)
        when b.size>=4 && b[1]==0 && b[2]==0 && b[3]==0
          source.dup.force_encoding(::Encoding::UTF_32LE).encode!(::Encoding::UTF_8)
        when b.size>=4 && b[1]==0 && b[3]==0
          source.dup.force_encoding(::Encoding::UTF_16LE).encode!(::Encoding::UTF_8)
        else source.dup end
    else source = source.encode(::Encoding::UTF_8) end
    source.force_encoding(::Encoding::ASCII_8BIT)
  else
    b = source
    source =
      case
      when b.size >= 4 && b[0] == 0 && b[1] == 0 && b[2] == 0; Iconv.iconv('utf-8', 'utf-32be', b)
      when b.size >= 4 && b[0] == 0 && b[2] == 0; Iconv.iconv('utf-8', 'utf-16be', b)
      when b.size >= 4 && b[1] == 0 && b[2] == 0 && b[3] == 0; Iconv.iconv('utf-8', 'utf-32le', b)
      when b.size >= 4 && b[1] == 0 && b[3] == 0; Iconv.iconv('utf-8', 'utf-16le', b)
      else b end
  end
  return source
end
init(source, opts={}) click to toggle source
Calls superclass method
# File lib/udon/udon_parser.rb, line 63
def init(source, opts={})
  opts ||= {}
  super ensure_encoding(source)
  @global = {}
end
parse() click to toggle source
# File lib/udon/udon_parser.rb, line 99
def parse
  reset
  @line = 1
  @pos = 1
  @leading = true
  @indent = 0
  @ast = document
  return @ast
end

Private Instance Methods

comment(retstate,p=nil,name='comment') click to toggle source
# File lib/udon/udon_parser.rb, line 194
def comment(retstate,p=nil,name='comment')
  ibase=@indent+1
  ipar=@indent
  __state=':first:ws'
  s = UNode.new(:name=>name,:sline=>@line,:schr=>@pos)
  a ||= ''
  loop do
    __i = nextchar
    __state = '{eof}' if __i==:eof
    case __state
    when ':first:ws'
        case
        when __i==9,space?; ibase += 1; next
        when nl?; __state=':nl'; next
        else __i.into(a); __state=':data'; next
        end
    when ':nl'
        case
        when (@indent>ibase); @fwd=true; __state=':data'; next
        when __i==9,space?; next
        when nl?; __i.into(a); a.into(s); next
        when (@indent<=ipar); @fwd=true; s.into(p); return(retstate)
        else __i.into(a); ibase=@indent; __state=':data'; next
        end
    when '{eof}'
        @fwd=true; a.into(s); s.into(p); return(retstate)
    when ':data'
        case
        when nl?; a.into(s); __state=':nl'; next
        else __i.into(a); next
        end
    end
  end
end
cstr(retstate,p=nil,name='cstr') click to toggle source
# File lib/udon/udon_parser.rb, line 295
def cstr(retstate,p=nil,name='cstr')
  nst=0
  __state=':first'
  s = []
  a ||= ''
  b ||= ''
  loop do
    __i = nextchar
    case __state
    when ':delimited:donecheck'
        case
        when (nst==0); @fwd=true; a.into!(p); return(retstate)
        when !eof?; @fwd=true; ')'.into(a); __state=':delimited'; next
        end
    when ':delimited'
        case
        when __i==92; __i.into(b); __state=':delimited:esc'; next
        when __i==40; __i.into(a); nst+=1; next
        when __i==41; nst-=1; __state=':delimited:donecheck'; next
        when !eof?; __i.into(a); next
        end
    when ':first'
        case
        when (eof?); @fwd=true; a.into!(p); return(retstate)
        when __i==40; nst=1; __state=':delimited'; next
        when nl?,(__i>8&&__i<11),space?; @fwd=true; a.into!(p); return(retstate)
        when !eof?; __i.into(a); __state=':normal'; next
        end
    when ':normal'
        case
        when (eof?); @fwd=true; a.into!(p); return(retstate)
        when __i==92; __i.into(b); __state=':normal:esc'; next
        when nl?,(__i>8&&__i<11),space?,__i==46,__i==91; @fwd=true; a.into!(p); return(retstate)
        when !eof?; __i.into(a); next
        end
    when ':normal:esc'
        case
        when (eof?); @fwd=true; b.into(a); a.into!(p); return(retstate)
        when __i==9,space?,__i==46,__i==91; __i.into(a); __state=':normal'; next
        when !eof?; __i.into(b); b.into(a); __state=':normal'; next
        end
    when ':delimited:esc'
        case
        when __i==92; __state=':delimited:esc:2'; next
        when (__i>39&&__i<42); __i.into(a); __state=':delimited'; next
        when !eof?; __i.into(b); b.into(a); __state=':delimited'; next
        end
    when ':delimited:esc:2'
        case
        when (__i>39&&__i<42); @fwd=true; b.into(a); __state=':delimited'; next
        when !eof?; __i.into(b); '\\'.into(a); b.into(a); __state=':delimited'; next
        end
    end
    error("Unexpected \"#{[__i].pack("U*")}\"")
    @fwd = true
    return
  end
end
document(p=nil,name='document') click to toggle source
# File lib/udon/udon_parser.rb, line 159
def document(p=nil,name='document')
  __state=':data_or_child'
  s = []
  a ||= ''
  b ||= ''
  loop do
    __i = nextchar
    __state = '{eof}' if __i==:eof
    case __state
    when ':data_or_child'
        case
        when nl?; @fwd=true; b.into(a); __state=':data'; next
        when __i==9,space?; __i.into(b); next
        when __i==35,__i==124; @fwd=true; b.reset!; a.into(s); __state=':child'; next
        else @fwd=true; b.into(a); __state=':data'; next
        end
    when ':child'
        case
        when __i==35; __state=comment(':data_or_child',s); next
        when __i==124; __state=node(':data_or_child',s); next
        end
    when '{eof}'
        @fwd=true; b.into(a); a.into(s); return(s)
    when ':data'
        case
        when nl?; __i.into(a); a.into(s); __state=':data_or_child'; next
        else __i.into(a); next
        end
    end
    error("Unexpected \"#{[__i].pack("U*")}\"")
    @fwd = true
    return
  end
end
eof?() click to toggle source
# File lib/udon/udon_parser.rb, line 157
def eof?() return @last_c == :eof end
error(msg) click to toggle source
# File lib/udon/udon_parser.rb, line 111
def error(msg)
  $stderr.puts "#{msg} | line: #{@line} | char: #{@pos}"
end
global_state(c) click to toggle source
# File lib/udon/udon_parser.rb, line 115
def global_state(c)
  # Unicode newline characters & combinations
  # Plus leading space for indents.
  # Also tracks line and position for the AST
  @last_is_newline = @last_is_space = false
  case c
  when 0x0b, 0x0c, 0x85, 0x2028, 0x2029
    @last_is_newline = true; @line += 1; @pos = 1
    @leading = true; @indent = 0
  when 0x0a
    nc = peek(4).unpack('U')[0]
    if nc == 0x0d then getch; c = "\n\r" end
    @last_is_newline = true; @line += 1; @pos = 1
    @leading = true; @indent = 0
  when 0x0d
    nc = peek(4).unpack('U')[0]
    if nc == 0x0a then getch; c = "\r\n" end
    @last_is_newline = true; @line += 1; @pos = 1
    @leading = true; @indent = 0
  when 0x20,0x09
    @indent += 1 if @leading
    @last_is_space = true; @pos += 1
  else @leading = false; @pos += 1 end
  return @last_c = c
end
idstr(retstate,p=nil,name='idstr') click to toggle source
# File lib/udon/udon_parser.rb, line 354
def idstr(retstate,p=nil,name='idstr')
  nst=1
  __state=':delimited'
  s = []
  a ||= ''
  b ||= ''
  loop do
    __i = nextchar
    case __state
    when ':delimited:donecheck'
        case
        when (nst==0); @fwd=true; a.into!(p); return(retstate)
        when !eof?; @fwd=true; ']'.into(a); __state=':delimited'; next
        end
    when ':delimited'
        case
        when __i==92; __i.into(b); __state=':delimited:esc'; next
        when __i==91; __i.into(a); nst+=1; next
        when __i==93; nst-=1; __state=':delimited:donecheck'; next
        when !eof?; __i.into(a); next
        end
    when ':delimited:esc'
        case
        when __i==92; __state=':delimited:esc:2'; next
        when __i==91,__i==93; __i.into(a); __state=':delimited'; next
        when !eof?; __i.into(b); b.into(a); __state=':delimited'; next
        end
    when ':delimited:esc:2'
        case
        when __i==91,__i==93; @fwd=true; b.into(a); __state=':delimited'; next
        when !eof?; __i.into(b); '\\'.into(a); b.into(a); __state=':delimited'; next
        end
    end
    error("Unexpected \"#{[__i].pack("U*")}\"")
    @fwd = true
    return
  end
end
nextchar() click to toggle source
# File lib/udon/udon_parser.rb, line 144
def nextchar
  if @fwd then @fwd = false; return @last_c
  else
    c = getch
    if c.nil?
      c = :eof
      @last_is_space = @last_is_newline = false
      return @last_c = c
    end
    return global_state(c.unpack('U')[0])
  end
end
nl?() click to toggle source
# File lib/udon/udon_parser.rb, line 141
def nl?() return @last_is_newline end
node(retstate,p=nil,name='node') click to toggle source
# File lib/udon/udon_parser.rb, line 229
def node(retstate,p=nil,name='node')
  ipar=@indent
  __state=':ident'
  s = UNode.new(:name=>name,:sline=>@line,:schr=>@pos)
  a ||= ''
  loop do
    __i = nextchar
    case __state
    when ':ident:child:nl'
        if !eof?
          @fwd=true; error('nyi'); return(retstate)
        end
    when ':ident:child'
        case
        when (eof?); @fwd=true; a.into(s); s.into(p); return(retstate)
        when nl?; __i.into(a); a.into(s); __state=':ident:child:nl'; next
        when !eof?; __i.into(a); next
        end
    when ':ident:a_or_c'
        case
        when (eof?); @fwd=true; a.into(s.c.last); s.into(p); return(retstate)
        when __i==58; a.reset!; s.c.pop.into(aname); __state=':ident:attr:val'; next
        when __i==9,space?; __i.into(a); next
        when nl?; __i.into(a); a.into(s.c.last); __state=':ident:nl'; next
        when !eof?; __i.into(a); __state=':ident:child'; next
        end
    when ':ident:idret'
        @fwd=true; id=['id',s.c.pop]; id.into(s.a); __state=':ident:nxt'; next
    when ':ident'
        case
        when (eof?); @fwd=true; error('er1'); return(retstate)
        when __i==9,space?; __state=':ident:nxt'; next
        when nl?; __state=':ident:nl'; next
        when __i==46,__i==91,__i==123; @fwd=true; __state=':ident:nxt'; next
        when !eof?; @fwd=true; __state=cstr(':ident:nameret',s); next
        end
    when ':ident:attr:val'
        if !eof?
          @fwd=true; error('nyi'); return(retstate)
        end
    when ':ident:nxt'
        case
        when (eof?); @fwd=true; s.into(p); return(retstate)
        when __i==91; __state=idstr(':ident:idret',s); next
        when __i==46; error('nyi'); return(retstate)
        when nl?; __state=':ident:nl'; next
        when __i==9,space?; next
        when !eof?; @fwd=true; __state=cstr(':ident:a_or_c',s); next
        end
    when ':ident:nameret'
        @fwd=true; s.name.reset!; s.c.pop.into(s.name); __state=':ident:nxt'; next
    when ':ident:nl'
        case
        when (eof?); @fwd=true; error('er3'); return(retstate)
        when __i==9,space?; next
        when nl?; next
        when (@indent<=ipar); @fwd=true; s.into(p); return(retstate)
        when !eof?; @fwd=true; ibase=@indent; __state=':ident:nxt'; next
        end
    end
    error("Unexpected \"#{[__i].pack("U*")}\"")
    @fwd = true
    return
  end
end
space?() click to toggle source
# File lib/udon/udon_parser.rb, line 142
def space?() return @last_is_space end