Class: Emfrp::Parser

Inherits:
ParserCombinator::StringParser
  • Object
show all
Defined in:
lib/emfrp/parser/misc.rb,
lib/emfrp/parser/parser.rb,
lib/emfrp/parser/toplevel.rb,
lib/emfrp/parser/expression.rb,
lib/emfrp/parser/parsing_error.rb

Defined Under Namespace

Classes: ParsingError

Constant Summary collapse

SPChar =

Utils & Commons


{
  :space => "\s",
  :tab => "\t",
  :newline => "\n",
  :doublequote => "\"",
  :singlequote => "'",
  :backslash => "\\",
}
OPUsable =
"!#$%&*+./<=>?@\\^|-~"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.convert_case_group(src_str) ⇒ Object

Raises:



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/emfrp/parser/parser.rb', line 50

def self.convert_case_group(src_str)
  raise ParsingError.new("TAB is not allowed to use in sources.") if src_str.chars.include?("\t")
  lines = src_str.each_line.to_a.map(&:chomp)
  len = lines.length
  len.times do |ln|
    if lines[ln].strip.chars.last == ":"
      width = lines[ln].chars.take_while{|c| c == "\s"}.size
      ((ln+1)..(len-1)).each do |ln2|
        width2 = lines[ln2].chars.take_while{|c| c == "\s"}.size
        if ln2 == len - 1
          lines[ln2] << " :endcase"
          break
        elsif lines[ln2].strip == ""
          next
        elsif width2 <= width
          lines[ln2 - 1] << " :endcase"
          break
        end
      end
    end
  end
  lines.map{|l| l + "\n"}.join
end

.from_infixes_to_parser(infixes) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/emfrp/parser/parser.rb', line 74

def self.from_infixes_to_parser(infixes)
  priority_listl = [[], [], [], [], [], [], [], [], [], []]
  priority_listr = [[], [], [], [], [], [], [], [], [], []]
  priority_listn = [[], [], [], [], [], [], [], [], [], []]
  defined_op = {}
  infixes.reverse.each do |id|
    if defined_op[id[:op][:desc]]
      next
    else
      defined_op[id[:op][:desc]] = true
    end
    if id[:priority] == nil || ("0" <= id[:priority][:desc] && id[:priority][:desc] <= "9")
      priority = id[:priority] == nil ? 9 : id[:priority][:desc].to_i
      opp = sat{|i| i.is_a?(SSymbol) && i[:desc] == id[:op][:desc]}.map(&:item)
      if id[:type][:desc] == "infix"
        priority_listn[priority] << opp
      elsif id[:type][:desc] == "infixl"
        priority_listl[priority] << opp
      elsif id[:type][:desc] == "infixr"
        priority_listr[priority] << opp
      else
        raise "invalid infix type"
      end
    else
      raise "invalid prirority"
    end
  end
  priority_list = [{:op => sat{|i| i.is_a?(SSymbol)}.map(&:item), :dir => "left"}]
  10.times do |i|
    if priority_listl[i].length > 0
      priority_list << {:op => priority_listl[i].inject(&:|), :dir => "left"}
    end
    if priority_listr[i].length > 0
      priority_list << {:op => priority_listr[i].inject(&:|), :dir => "right"}
    end
    if priority_listn[i].length > 0
      priority_list << {:op => priority_listn[i].inject(&:|), :dir => "left"}
    end
  end
  return OpParser.make_op_parser(priority_list)
end

.infix_convert(s, parser) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/emfrp/parser/parser.rb', line 121

def self.infix_convert(s, parser)
  case s
  when Syntax
    new_s = s.class[s.map{|k, v| [k, infix_convert(v, parser)]}]
    if s.is_a?(OperatorSeq)
      items = Items.new(new_s[:seq].map{|c| Item.new(c, nil)})
      res = parser.parse(items)
      if res.is_a?(Fail)
        raise "operator parsing fail!!"
      end
      res.parsed
    else
      new_s
    end
  when Array
    s.map{|c| infix_convert(c, parser)}
  else
    s
  end
end

.infix_rearrange(top) ⇒ Object



116
117
118
119
# File 'lib/emfrp/parser/parser.rb', line 116

def self.infix_rearrange(top)
  infix_parser = from_infixes_to_parser(top[:infixes])
  return infix_convert(top, infix_parser)
end

.parse(src_str, file_name, parser) ⇒ Object



39
40
41
42
43
44
45
46
47
48
# File 'lib/emfrp/parser/parser.rb', line 39

def self.parse(src_str, file_name, parser)
  case res = parser.parse_from_string(convert_case_group(src_str), file_name)
  when Fail
    raise ParsingError.new(src_str, file_name, res.status)
  when Ok
    return res.parsed
  else
    raise "unexpected return of parser (bug)"
  end
end

.parse_input(path, file_loader, file_type = module_file) ⇒ Object



13
14
15
16
17
18
19
# File 'lib/emfrp/parser/parser.rb', line 13

def self.parse_input(path, file_loader, file_type=module_file)
  if file_loader.loaded?(path)
    return Top.new
  end
  src_str, file_name = file_loader.load(path)
  parse_src(src_str, file_name, file_loader, file_type)
end

.parse_src(src_str, file_name, file_loader, file_type = module_file) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/emfrp/parser/parser.rb', line 21

def self.parse_src(src_str, file_name, file_loader, file_type=module_file)
  case res = file_type.parse_from_string(convert_case_group(src_str), file_name)
  when Fail
    raise ParsingError.new(src_str, file_name, res.status)
  when Ok
    newnode_tops = res.parsed[:newnodes].map do |newnode|
      NewNodeConvert.parse_module(res.parsed[:module_name][:desc], newnode, file_loader)
    end
    res.parsed[:newnodes] = []
    tops = res.parsed[:uses].map do |use_path|
      parse_input(use_path.map{|x| x[:desc]}, file_loader, material_file)
    end
    return Top.new(*tops, res.parsed, *newnode_tops)
  else
    raise "unexpected return of parser (bug)"
  end
end

Instance Method Details

#err(place, required, code = nil) ⇒ Object



142
143
144
# File 'lib/emfrp/parser/parser.rb', line 142

def err(place, required, code=nil)
  self.onfail(:place => place, :required => required, :code => code)
end

#to_nilObject



146
147
148
# File 'lib/emfrp/parser/parser.rb', line 146

def to_nil
  self.map{|x| x[0]}
end