diff --git a/lib/maxy/gen/generator.rb b/lib/maxy/gen/generator.rb index d844782..895d5b1 100644 --- a/lib/maxy/gen/generator.rb +++ b/lib/maxy/gen/generator.rb @@ -35,10 +35,14 @@ def generate_node(node, id) @patch['patcher']['boxes'] << make_box(node, id) @object_count += 1 - node.child_nodes.each do |child_node| + node.child_nodes.each_with_index do |child_node, index| child_id = "obj_#{@object_count}" generate_node(child_node, child_id) - @patch['patcher']['lines'] << make_line(id, child_id) + if node.flags.include? :connect_children_individually + @patch['patcher']['lines'] << make_line(id, child_id, index, 0) + else + @patch['patcher']['lines'] << make_line(id, child_id) + end end end @@ -46,15 +50,19 @@ def make_box(node, id) box = @library[:objects][node.name].dup box['id'] = id box['patching_rect'] = [OFFSET_X + (node.x_rank - 1) * STEP_X, OFFSET_Y + (node.y_rank - 1) * STEP_Y, box['width'] || WIDTH, box['height'] || HEIGHT] - unless box['text'].nil? - box['text'] += " #{node.args}" - end + box['text'] += " #{node.args}" unless box['text'].nil? box end - def make_line(parent_id, child_id) - { patchline: { destination: [child_id, 0], source: [parent_id, 0]} } + def make_line(parent_id, child_id, parent_outlet = 0, child_inlet = 0) + { + patchline: + { + destination: [child_id, child_inlet], + source: [parent_id, parent_outlet] + } + } end def align_tree(node, x_rank = 1, y_rank = 1) @@ -71,6 +79,5 @@ def align_tree(node, x_rank = 1, y_rank = 1) node end end - end -end \ No newline at end of file +end diff --git a/lib/maxy/gen/parser.rb b/lib/maxy/gen/parser.rb index cff9379..5f8c672 100644 --- a/lib/maxy/gen/parser.rb +++ b/lib/maxy/gen/parser.rb @@ -18,6 +18,7 @@ def parse(parent_node=@tree, closing_group=false) else parse_begin_group parent_node child_node = parse_identifier parent_node + parse_equals child_node parse_dash child_node end @@ -92,9 +93,21 @@ def parse_dash(obj_node) parse(obj_node) end end + + def parse_equals(obj_node) + if peek(:equals) + consume(:equals) + obj_node.flags << :connect_children_individually + parse(obj_node) + end + end end - ObjectNode = Struct.new(:name, :args, :child_nodes, :x_rank, :y_rank) + ObjectNode = Struct.new(:name, :args, :child_nodes, :x_rank, :y_rank, :flags) do + def initialize(name, args, child_nodes, x_rank=0, y_rank=0, flags=[]) + super + end + end RootNode = Struct.new(:child_nodes) end diff --git a/lib/maxy/gen/tokenizer.rb b/lib/maxy/gen/tokenizer.rb index 2f120bd..a8cb3aa 100644 --- a/lib/maxy/gen/tokenizer.rb +++ b/lib/maxy/gen/tokenizer.rb @@ -3,11 +3,12 @@ module Gen class Tokenizer TOKEN_TYPES = [ [:arguments, /({[^{}]*})/], - [:escaped_identifier, /(\\[\S][^-+{}()\\]*)(?=[-+*{}])?/], - [:identifier, /([^-+{}()\\]+)(?=[-+*{}])?/], + [:escaped_identifier, /(\\[\S][^-+={}()\\]*)(?=[-+=*{}])?/], + [:identifier, /([^-+={}()\\]+)(?=[-+=*{}])?/], [:oparen, /(\()/], [:cparen, /(\))/], [:plus, /(\+)/], + [:equals, /(=)/], [:dash, /(-)/] ] diff --git a/lib/maxy/gen/version.rb b/lib/maxy/gen/version.rb index b0a3b19..d64d2aa 100644 --- a/lib/maxy/gen/version.rb +++ b/lib/maxy/gen/version.rb @@ -1,5 +1,5 @@ module Maxy module Gen - VERSION = "0.3.0" + VERSION = "0.3.1" end end diff --git a/spec/maxy/generator_spec.rb b/spec/maxy/generator_spec.rb index c614a3b..d57a5ae 100644 --- a/spec/maxy/generator_spec.rb +++ b/spec/maxy/generator_spec.rb @@ -72,5 +72,26 @@ expect(duplicate_keys).to be_empty end + it 'should connect children individually if asked to do so' do + tree = RootNode.new([ + ObjectNode.new('trigger', 'b b b', [ + ObjectNode.new('int', '', []), + ObjectNode.new('int', '', []), + ObjectNode.new('int', '', []) + ], 0, 0, [:connect_children_individually]) + ]) + generator = Generator.new + generated = generator.generate(tree) + + lines = JSON.parse(generated)['patcher']['lines'] -end \ No newline at end of file + expect(JSON.parse(generated)['patcher']['boxes']).not_to be_empty + expect(lines).not_to be_empty + + expect(JSON.parse(generated)['patcher']['boxes'].size).to eq(4) + expect(lines.size).to eq(3) + expect(lines[0]['patchline']['source']).to eq(['obj_1', 0]) + expect(lines[1]['patchline']['source']).to eq(['obj_1', 1]) + expect(lines[2]['patchline']['source']).to eq(['obj_1', 2]) + end +end diff --git a/spec/maxy/parser_spec.rb b/spec/maxy/parser_spec.rb index 406d658..4fb087c 100644 --- a/spec/maxy/parser_spec.rb +++ b/spec/maxy/parser_spec.rb @@ -99,4 +99,24 @@ expect { Parser.new(tokens).parse }.to raise_error(RuntimeError) end + it 'should parse a row to multiple expression (=) ' do + tokens = [Token.new(:identifier, 'trigger'), + Token.new(:arguments, '{b b b}'), + Token.new(:equals, '='), + Token.new(:oparen, '('), + Token.new(:identifier, 'int'), + Token.new(:plus, '+'), + Token.new(:identifier, 'int'), + Token.new(:plus, '+'), + Token.new(:identifier, 'int'), + Token.new(:cparen, ')')] + tree = Parser.new(tokens).parse + + expect(tree.child_nodes[0].name).to eq('trigger') + expect(tree.child_nodes[0].child_nodes.size).to eq(3) + expect(tree.child_nodes[0].flags).to include(:connect_children_individually) + expect(tree.child_nodes[0].child_nodes[0]).to eq(ObjectNode.new('int', '', [], 0, 0, [])) + expect(tree.child_nodes[0].child_nodes[2]).to eq(ObjectNode.new('int', '', [], 0, 0, [])) + end + end \ No newline at end of file diff --git a/spec/maxy/tokenizer_spec.rb b/spec/maxy/tokenizer_spec.rb index 201b972..120a358 100644 --- a/spec/maxy/tokenizer_spec.rb +++ b/spec/maxy/tokenizer_spec.rb @@ -43,4 +43,10 @@ expect(tokens.map(&:type)).to eq([:identifier, :dash, :oparen, :escaped_identifier, :dash, :identifier, :cparen, :plus, :oparen, :identifier, :dash, :identifier, :cparen]) expect(tokens.map(&:value)).to eq(%w(inlet - ( \* - outlet ) + ( trigger - outlet ))) end + + it 'should tokenize an equals sign' do + tokens = Tokenizer.new('trigger{b b b}=(int+int+int)').tokenize + expect(tokens.map(&:type)).to eq([:identifier, :arguments, :equals, :oparen, :identifier, :plus, :identifier, :plus, :identifier, :cparen]) + expect(tokens.map(&:value)).to eq(%w(trigger {b\ b\ b} = ( int + int + int ) )) + end end \ No newline at end of file