Class: Maxy::Gen::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/maxy/gen/parser.rb

Instance Method Summary collapse

Constructor Details

#initialize(tokens) ⇒ Parser



4
5
6
7
8
9
10
11
# File 'lib/maxy/gen/parser.rb', line 4

def initialize(tokens)
  raise 'No object definitions were found. please run `maxy-gen install` first' unless File.exist?("#{ENV['HOME']}/.maxy-gen/library.yml")

  @library = Psych.load_file("#{ENV['HOME']}/.maxy-gen/library.yml").freeze
  @tokens = tokens
  @tree = RootNode.new([])
  @groups = []
end

Instance Method Details

#consume(expected_type) ⇒ Object



73
74
75
76
77
78
79
80
# File 'lib/maxy/gen/parser.rb', line 73

def consume(expected_type)
  token = @tokens.shift
  if token.type == expected_type
    token
  else
    raise "Expected token type #{expected_type.inspect}, but got #{token.type.inspect}"
  end
end

#parse(parent_node = @tree, closing_group = false) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/maxy/gen/parser.rb', line 13

def parse(parent_node=@tree, closing_group=false)
  if closing_group
    if peek(:dash) || peek(:identifier) || peek(:escaped_identifier)
      raise 'Parsing Error: only + is allowed after a ) closing a group.'
    end
  else
    parse_begin_group parent_node
    child_node = parse_identifier parent_node
    parse_less_than child_node
    parse_equals child_node
    parse_dash child_node
  end

  parse_plus parent_node

  parse_end_group
end

#parse_argumentsObject



65
66
67
68
69
70
71
# File 'lib/maxy/gen/parser.rb', line 65

def parse_arguments
  if peek(:arguments)
    args = consume(:arguments)
    args.value =~ /\A{([^{}]*)}\Z/
    $1
  end
end

#parse_begin_group(parent) ⇒ Object



31
32
33
34
35
36
# File 'lib/maxy/gen/parser.rb', line 31

def parse_begin_group(parent)
  if peek(:oparen)
    consume(:oparen)
    @groups << parent
  end
end

#parse_dash(obj_node) ⇒ Object



93
94
95
96
97
98
# File 'lib/maxy/gen/parser.rb', line 93

def parse_dash(obj_node)
  if peek(:dash)
    consume(:dash)
    parse(obj_node)
  end
end

#parse_end_groupObject



38
39
40
41
42
43
44
# File 'lib/maxy/gen/parser.rb', line 38

def parse_end_group
  return @tree if @tokens.empty?
  if peek(:cparen)
    consume(:cparen)
    parse(@groups.pop, true)
  end
end

#parse_equals(obj_node) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/maxy/gen/parser.rb', line 100

def parse_equals(obj_node)
  if peek(:equals)
    consume(:equals)
    obj_node.flags << :connect_children_individually
    parse(obj_node)
  end
end

#parse_identifier(parent) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/maxy/gen/parser.rb', line 46

def parse_identifier(parent)
  if peek(:identifier)
    obj_name = consume(:identifier).value
  elsif peek(:escaped_identifier)
    obj_name = consume(:escaped_identifier).value
  elsif peek(:mc_identifier)
    obj_name = consume(:mc_identifier).value
  end

  arguments = parse_arguments || ''

  raise "Could not find #{obj_name} in object definitions." if @library[:objects][obj_name].nil?

  new_obj_node = ObjectNode.new(obj_name, arguments, [])
  parent.child_nodes << new_obj_node

  new_obj_node
end

#parse_less_than(obj_node) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/maxy/gen/parser.rb', line 108

def parse_less_than(obj_node)
  if peek(:less_than)
    consume(:less_than)
    obj_node.flags << :connect_all_child_inlets
    parse(obj_node)
  end
end

#parse_plus(obj_node) ⇒ Object



86
87
88
89
90
91
# File 'lib/maxy/gen/parser.rb', line 86

def parse_plus(obj_node)
  if peek(:plus)
    consume(:plus)
    parse(obj_node)
  end
end

#peek(expected_type) ⇒ Object



82
83
84
# File 'lib/maxy/gen/parser.rb', line 82

def peek(expected_type)
  @tokens.length.positive? && @tokens.fetch(0).type == expected_type
end