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

Returns a new instance of Parser.

Raises:

  • (RuntimeError)


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

def initialize(tokens)
  raise RuntimeError.new('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



70
71
72
73
74
75
76
77
# File 'lib/maxy/gen/parser.rb', line 70

def consume(expected_type)
  token = @tokens.shift
  if token.type == expected_type
    token
  else
    raise RuntimeError.new("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
# 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 RuntimeError.new("Parsing Error: only + is allowed after a ) closing a group.")
    end
  else
    parse_begin_group parent_node
    child_node = parse_identifier parent_node
    parse_equals child_node
    parse_dash child_node
  end

  parse_plus parent_node

  parse_end_group
end

#parse_argumentsObject



62
63
64
65
66
67
68
# File 'lib/maxy/gen/parser.rb', line 62

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

#parse_begin_group(parent) ⇒ Object



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

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

#parse_dash(obj_node) ⇒ Object



90
91
92
93
94
95
# File 'lib/maxy/gen/parser.rb', line 90

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

#parse_end_groupObject



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

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



97
98
99
100
101
102
103
# File 'lib/maxy/gen/parser.rb', line 97

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

Raises:

  • (RuntimeError)


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

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

  arguments = parse_arguments || ''

  raise RuntimeError.new("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_plus(obj_node) ⇒ Object



83
84
85
86
87
88
# File 'lib/maxy/gen/parser.rb', line 83

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

#peek(expected_type) ⇒ Object



79
80
81
# File 'lib/maxy/gen/parser.rb', line 79

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