re_duxml 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/ast_ext/node.rb +52 -52
- data/lib/re_duxml/array.rb +36 -37
- data/lib/re_duxml/element/parameterization.rb +18 -18
- data/lib/re_duxml/element.rb +8 -8
- data/lib/re_duxml/evaluate/parser.rb +3 -2
- data/lib/re_duxml/evaluate.rb +78 -77
- data/lib/re_duxml.rb +104 -99
- data/lib/ruby_ext/boolean.rb +37 -37
- data/lib/ruby_ext/fixnum.rb +5 -5
- data/lib/ruby_ext/macro.rb +50 -50
- data/lib/ruby_ext/regexp.rb +6 -6
- data/lib/ruby_ext/string.rb +14 -14
- data/lib/symbolic_ext/coerced.rb +15 -15
- data/lib/symbolic_ext/symbolic.rb +26 -26
- data/lib/symbolic_ext/variable.rb +60 -60
- data/xml/logic.xml +152 -152
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c7362dbfed6bd6c78ddbbd9660a55a639e802a6
|
4
|
+
data.tar.gz: c73453fe830475b19e4c34f60724b79abfdb2a59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4f44cdfc1bd794195f904a99dda9545e04e4ae35da83f8972492193ce8ea98094fe1c9abc188195df25a13324c864d08bd81e62a1c83ee630f6df4a65288678
|
7
|
+
data.tar.gz: d16dec0c48f1f7332781741871cbe90b56d17da1b89783e402c1a941b383c6d02c2b1f92c64e69aa7c62cb484ae8e2b25a983e14af8227eaf3e4277393a12656
|
data/lib/ast_ext/node.rb
CHANGED
@@ -1,53 +1,53 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
require 'ast'
|
3
|
-
|
4
|
-
module AST
|
5
|
-
# redefining in order to allow type itself to be any type e.g. String, Symbol, Fixnum, etc.
|
6
|
-
class Node
|
7
|
-
include AST
|
8
|
-
|
9
|
-
# The `properties` hash is passed to {#assign_properties}.
|
10
|
-
def initialize(type, children=[], properties={})
|
11
|
-
@type, @children = type, children.to_a.freeze
|
12
|
-
|
13
|
-
assign_properties(properties)
|
14
|
-
|
15
|
-
@hash = [@type.object_id, @children, self.class].hash
|
16
|
-
|
17
|
-
freeze
|
18
|
-
end
|
19
|
-
|
20
|
-
# @param logic [Hash] hash of operators allowed in this AST containing each operator's print properties
|
21
|
-
# @return [String] string reconstituted from polish-notation into notation normally required by each operator
|
22
|
-
def print(logic=nil)
|
23
|
-
return type.to_s if children.empty?
|
24
|
-
str = ''
|
25
|
-
op = type.respond_to?(:text) ? type : logic[type.to_s]
|
26
|
-
return str unless op
|
27
|
-
case op.position
|
28
|
-
when :prefix
|
29
|
-
str << op.symbol
|
30
|
-
children.each do |c| str << c.print(logic) end
|
31
|
-
when :postfix
|
32
|
-
children.each do |c| str << c.print(logic) end
|
33
|
-
str << op.symbol
|
34
|
-
when :infix
|
35
|
-
if op.arity > 2
|
36
|
-
str << children.first.print(logic) << op.symbol << children[1].print(logic) << op.pair.
|
37
|
-
else
|
38
|
-
str << (children.first.respond_to?(:print) ? children.first.print(logic) : children.first.
|
39
|
-
end
|
40
|
-
else # should not happen
|
41
|
-
end
|
42
|
-
str
|
43
|
-
end # to_s
|
44
|
-
end # class Node
|
45
|
-
|
46
|
-
def new_ast(op, *obj)
|
47
|
-
args = obj.collect do |o| o.is_a?(Node) ? o : Node.new(o) end
|
48
|
-
args.unshift self if is_a?(Node)
|
49
|
-
args.unshift Node.new(self) if is_a?(Fixnum)
|
50
|
-
args.unshift Node.new(self) if self.is_a?(Symbolic::Variable)
|
51
|
-
Node.new(op, args)
|
52
|
-
end
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require 'ast'
|
3
|
+
|
4
|
+
module AST
|
5
|
+
# redefining in order to allow type itself to be any type e.g. String, Symbol, Fixnum, etc.
|
6
|
+
class Node
|
7
|
+
include AST
|
8
|
+
|
9
|
+
# The `properties` hash is passed to {#assign_properties}.
|
10
|
+
def initialize(type, children=[], properties={})
|
11
|
+
@type, @children = type, children.to_a.freeze
|
12
|
+
|
13
|
+
assign_properties(properties)
|
14
|
+
|
15
|
+
@hash = [@type.object_id, @children, self.class].hash
|
16
|
+
|
17
|
+
freeze
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param logic [Hash] hash of operators allowed in this AST containing each operator's print properties
|
21
|
+
# @return [String] string reconstituted from polish-notation into notation normally required by each operator
|
22
|
+
def print(logic=nil)
|
23
|
+
return type.to_s if children.empty?
|
24
|
+
str = ''
|
25
|
+
op = type.respond_to?(:text) ? type : logic[type.to_s]
|
26
|
+
return str unless op
|
27
|
+
case op.position
|
28
|
+
when :prefix
|
29
|
+
str << op.symbol
|
30
|
+
children.each do |c| str << c.print(logic) end
|
31
|
+
when :postfix
|
32
|
+
children.each do |c| str << c.print(logic) end
|
33
|
+
str << op.symbol
|
34
|
+
when :infix
|
35
|
+
if op.arity > 2
|
36
|
+
str << children.first.print(logic) << op.symbol << children[1].print(logic) << op.pair.symbol << children.last.print
|
37
|
+
else
|
38
|
+
str << (children.first.respond_to?(:print) ? children.first.print(logic) : children.first.symbol) << op.symbol << children.last.print
|
39
|
+
end
|
40
|
+
else # should not happen
|
41
|
+
end
|
42
|
+
str
|
43
|
+
end # to_s
|
44
|
+
end # class Node
|
45
|
+
|
46
|
+
def new_ast(op, *obj)
|
47
|
+
args = obj.collect do |o| o.is_a?(Node) ? o : Node.new(o) end
|
48
|
+
args.unshift self if is_a?(Node)
|
49
|
+
args.unshift Node.new(self) if is_a?(Fixnum)
|
50
|
+
args.unshift Node.new(self) if self.is_a?(Symbolic::Variable)
|
51
|
+
Node.new(op, args)
|
52
|
+
end
|
53
53
|
end
|
data/lib/re_duxml/array.rb
CHANGED
@@ -1,38 +1,37 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
require 'con_duxml/instance'
|
3
|
-
|
4
|
-
module ConDuxml
|
5
|
-
# XML object array
|
6
|
-
# represents a pattern of copies of a this object's children or referents
|
7
|
-
# differentiates between copies using iterator Parameter
|
8
|
-
module Array
|
9
|
-
include Instance
|
10
|
-
|
11
|
-
# @return [Array[Element]] flattened array of all duplicated Elements
|
12
|
-
def activate
|
13
|
-
|
14
|
-
size_expr
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end # class Array
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require 'con_duxml/instance'
|
3
|
+
|
4
|
+
module ConDuxml
|
5
|
+
# XML object array
|
6
|
+
# represents a pattern of copies of a this object's children or referents
|
7
|
+
# differentiates between copies using iterator Parameter
|
8
|
+
module Array
|
9
|
+
include Instance
|
10
|
+
|
11
|
+
# @return [Array[Element]] flattened array of all duplicated Elements
|
12
|
+
def activate
|
13
|
+
size_expr = size.respond_to?(:to_i) ? size.to_i : size.to_s
|
14
|
+
if size_expr.is_a? Fixnum
|
15
|
+
new_children = []
|
16
|
+
size_expr.times do
|
17
|
+
source_nodes = if nodes.empty? and self[:ref]
|
18
|
+
[resolve_ref.clone]
|
19
|
+
else
|
20
|
+
nodes.collect do |node| node.clone end
|
21
|
+
end
|
22
|
+
source_nodes.each do |node|
|
23
|
+
new_children << node
|
24
|
+
end
|
25
|
+
end
|
26
|
+
new_children.flatten
|
27
|
+
else
|
28
|
+
[self]
|
29
|
+
end
|
30
|
+
end # def instantiate
|
31
|
+
|
32
|
+
# size can be Fixnum or a Parameter expression
|
33
|
+
def size
|
34
|
+
self[:size]
|
35
|
+
end
|
36
|
+
end # class Array
|
38
37
|
end # module Dux
|
@@ -1,18 +1,18 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../ruby_ext/string')
|
3
|
-
|
4
|
-
# methods to extend Dux::Object with methods needed to process parameterized XML content
|
5
|
-
module Parameterization
|
6
|
-
# returns true if self[:if] is true or indeterminate (because condition is currently parameterized)
|
7
|
-
# returns false otherwise i.e. this node does not exist in this design build
|
8
|
-
def if?
|
9
|
-
return true unless (if_str = self[:if])
|
10
|
-
if_str.parameterized? || if_str == 'true' ? true : false
|
11
|
-
end
|
12
|
-
|
13
|
-
# changes condition of this object's existence
|
14
|
-
def if=(condition)
|
15
|
-
# check for valid conditional
|
16
|
-
change_attr_value :if, condition
|
17
|
-
end
|
18
|
-
end # module Parameterization
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../ruby_ext/string')
|
3
|
+
|
4
|
+
# methods to extend Dux::Object with methods needed to process parameterized XML content
|
5
|
+
module Parameterization
|
6
|
+
# returns true if self[:if] is true or indeterminate (because condition is currently parameterized)
|
7
|
+
# returns false otherwise i.e. this node does not exist in this design build
|
8
|
+
def if?
|
9
|
+
return true unless (if_str = self[:if])
|
10
|
+
if_str.parameterized? || if_str == 'true' ? true : false
|
11
|
+
end
|
12
|
+
|
13
|
+
# changes condition of this object's existence
|
14
|
+
def if=(condition)
|
15
|
+
# check for valid conditional
|
16
|
+
change_attr_value :if, condition
|
17
|
+
end
|
18
|
+
end # module Parameterization
|
data/lib/re_duxml/element.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
require_relative 'element/parameterization'
|
3
|
-
require 'duxml'
|
4
|
-
|
5
|
-
module Duxml
|
6
|
-
class Element
|
7
|
-
include Parameterization
|
8
|
-
end
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require_relative 'element/parameterization'
|
3
|
+
require 'duxml'
|
4
|
+
|
5
|
+
module Duxml
|
6
|
+
class Element
|
7
|
+
include Parameterization
|
8
|
+
end
|
9
9
|
end
|
@@ -81,7 +81,8 @@ module ReDuxml
|
|
81
81
|
op_stack << token.value
|
82
82
|
when :grouping
|
83
83
|
op_prop = token.value
|
84
|
-
|
84
|
+
op_str = op_prop.respond_to?(:nodes) ? op_prop.symbol : op_prop.to_s
|
85
|
+
case op_str
|
85
86
|
when '('
|
86
87
|
if input.any? && input.first.type == :grouping && input.first.value.to_s == '('
|
87
88
|
input.shift
|
@@ -90,7 +91,7 @@ module ReDuxml
|
|
90
91
|
op_stack << op_prop
|
91
92
|
end
|
92
93
|
when ')'
|
93
|
-
while op_stack.any? && op_stack.last.symbol != op_prop.pair.
|
94
|
+
while op_stack.any? && op_stack.last.symbol != op_prop.pair.symbol
|
94
95
|
consume(arities.pop || op_stack.last.arity)
|
95
96
|
end
|
96
97
|
lparen = op_stack.pop
|
data/lib/re_duxml/evaluate.rb
CHANGED
@@ -1,78 +1,79 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
require_relative 'evaluate/parser'
|
3
|
-
require_relative '../../lib/ruby_ext/macro'
|
4
|
-
|
5
|
-
module ReDuxml
|
6
|
-
class Evaluator
|
7
|
-
LOGIC_FILE = File.expand_path(File.dirname(__FILE__) + '/../../xml/logic.xml')
|
8
|
-
include Math
|
9
|
-
include ReDuxml
|
10
|
-
include Symbolic
|
11
|
-
|
12
|
-
@param_hash
|
13
|
-
@parser
|
14
|
-
|
15
|
-
attr_reader :param_hash, :parser
|
16
|
-
|
17
|
-
def initialize(logic=nil)
|
18
|
-
@parser = Parser.new(logic || LOGIC_FILE)
|
19
|
-
@param_hash = {}
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_s
|
23
|
-
"#<Evaluator: param_hash: '#{param_hash.to_s}' parser_logic: '#{parser}'>"
|
24
|
-
end
|
25
|
-
|
26
|
-
def evaluate(_expr, _param_hash={})
|
27
|
-
@param_hash = _param_hash
|
28
|
-
expr = resolve_params _expr
|
29
|
-
return expr if expr.parameterized?
|
30
|
-
return expr if Regexp.identifier.match(expr).to_s == expr
|
31
|
-
return expr.to_i if expr.to_i.to_s == expr
|
32
|
-
result = reduce parser.parse expr
|
33
|
-
case
|
34
|
-
when result.respond_to?(:imaginary), result.class == TrueClass, result.class == FalseClass then result
|
35
|
-
when result.respond_to?(:
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
expr
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require_relative 'evaluate/parser'
|
3
|
+
require_relative '../../lib/ruby_ext/macro'
|
4
|
+
|
5
|
+
module ReDuxml
|
6
|
+
class Evaluator
|
7
|
+
LOGIC_FILE = File.expand_path(File.dirname(__FILE__) + '/../../xml/logic.xml')
|
8
|
+
include Math
|
9
|
+
include ReDuxml
|
10
|
+
include Symbolic
|
11
|
+
|
12
|
+
@param_hash
|
13
|
+
@parser
|
14
|
+
|
15
|
+
attr_reader :param_hash, :parser
|
16
|
+
|
17
|
+
def initialize(logic=nil)
|
18
|
+
@parser = Parser.new(logic || LOGIC_FILE)
|
19
|
+
@param_hash = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
"#<Evaluator: param_hash: '#{param_hash.to_s}' parser_logic: '#{parser}'>"
|
24
|
+
end
|
25
|
+
|
26
|
+
def evaluate(_expr, _param_hash={})
|
27
|
+
@param_hash = _param_hash
|
28
|
+
expr = resolve_params _expr
|
29
|
+
return expr if expr.parameterized?
|
30
|
+
return expr if Regexp.identifier.match(expr).to_s == expr
|
31
|
+
return expr.to_i if expr.to_i.to_s == expr
|
32
|
+
result = reduce parser.parse expr
|
33
|
+
case
|
34
|
+
when result.respond_to?(:imaginary), result.class == TrueClass, result.class == FalseClass then result
|
35
|
+
when result.respond_to?(:name) then result.name
|
36
|
+
when result.respond_to?(:to_sexp) then result.print(parser.logic)
|
37
|
+
else result.to_s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def resolve_params(_expr)
|
44
|
+
expr = _expr.dup
|
45
|
+
param_hash.each do |param, val| expr.gsub!(param, val) end
|
46
|
+
expr
|
47
|
+
end
|
48
|
+
|
49
|
+
include Symbolic
|
50
|
+
|
51
|
+
def reduce(_ast)
|
52
|
+
ast = _ast.type.respond_to?(:symbol) ? _ast : new_ast(parser.logic[_ast.type.to_s], _ast.children.dup)
|
53
|
+
if ast.children.any?
|
54
|
+
operator = ast.type
|
55
|
+
args = ast.children.collect do |c|
|
56
|
+
new_child = c.children.any? ? reduce(c) : c.type
|
57
|
+
if new_child.is_a?(Node) && new_child.type.is_a?(Symbol)
|
58
|
+
new_ast(parser.logic[new_child.type.to_s], *new_child.children.dup)
|
59
|
+
else
|
60
|
+
new_child
|
61
|
+
end
|
62
|
+
end.flatten
|
63
|
+
begin
|
64
|
+
result = case operator.position
|
65
|
+
when :prefix
|
66
|
+
method(operator.ruby).call(*args)
|
67
|
+
else
|
68
|
+
args.first.send(operator.ruby, *args[1..-1])
|
69
|
+
end
|
70
|
+
result.nil? ? ast : result
|
71
|
+
rescue
|
72
|
+
ast
|
73
|
+
end
|
74
|
+
else
|
75
|
+
ast
|
76
|
+
end
|
77
|
+
end # def reduce(ast)
|
78
|
+
end # class Evaluator
|
78
79
|
end # module ReDux
|
data/lib/re_duxml.rb
CHANGED
@@ -1,99 +1,104 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/ruby_ext/macro')
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/re_duxml/evaluate')
|
4
|
-
require File.expand_path(File.dirname(__FILE__) + '/re_duxml/element')
|
5
|
-
require '
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
# @
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
new_child
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
content_str
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/ruby_ext/macro')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/re_duxml/evaluate')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/re_duxml/element')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/re_duxml/array')
|
6
|
+
require 'con_duxml'
|
7
|
+
|
8
|
+
module ReDuxml
|
9
|
+
include ConDuxml
|
10
|
+
|
11
|
+
# @param doc_or_node [Doc, String] XML to load; can be Doc, String path or String XML; also XML Element when recursing
|
12
|
+
# @return [Doc] instantiated XML with parameters resolved with given values
|
13
|
+
def resolve(doc_or_node, parent_params={})
|
14
|
+
if doc_or_node.is_a?(Element)
|
15
|
+
resolved_node = doc_or_node.stub
|
16
|
+
resolved_node.attributes.each do |attr, val|
|
17
|
+
resolved_node[attr] = resolve_str(val, parent_params)
|
18
|
+
end
|
19
|
+
this_params = get_params(doc_or_node, parent_params)
|
20
|
+
new_children = doc_or_node.nodes.collect do |child|
|
21
|
+
if child.respond_to?(:nodes)
|
22
|
+
new_child = child.clone
|
23
|
+
new_child[:if] = resolve_str(new_child[:if], this_params) if new_child[:if]
|
24
|
+
if new_child.if?
|
25
|
+
new_child[:if] = nil
|
26
|
+
child_params = get_params(new_child, this_params)
|
27
|
+
new_instances = new_child.activate
|
28
|
+
i = -1
|
29
|
+
new_instances.collect do |inst|
|
30
|
+
i += 1
|
31
|
+
resolve(inst, child_params.merge({'iterator' => i.to_s}))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
resolve_str(child, this_params)
|
36
|
+
end
|
37
|
+
end.flatten.compact
|
38
|
+
resolved_node << new_children
|
39
|
+
else
|
40
|
+
@e ||= Evaluator.new
|
41
|
+
@src_doc = get_doc doc_or_node
|
42
|
+
@doc = Doc.new << resolve(src_doc.root, parent_params)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :e, :src_doc
|
47
|
+
private
|
48
|
+
|
49
|
+
|
50
|
+
def get_params(node, param_hash)
|
51
|
+
if node.nodes.any? and !node.text? and node.nodes[0].name == 'duxml:parameters'
|
52
|
+
local_params = {}
|
53
|
+
params = node[0].nodes.clone
|
54
|
+
params.each do |param|
|
55
|
+
new_val = resolve_str(param[:value], param_hash)
|
56
|
+
node[0].delete param unless new_val.parameterized?
|
57
|
+
local_params[param[:name]] = new_val
|
58
|
+
end
|
59
|
+
node.delete node[0] unless node[0].nodes.any?
|
60
|
+
param_hash.merge local_params
|
61
|
+
else
|
62
|
+
param_hash
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# finds index of close parentheses corresponding to first open parentheses found in given str
|
67
|
+
def find_close_parens_index(str)
|
68
|
+
levels = 0
|
69
|
+
index = 0
|
70
|
+
str.each_char do |char|
|
71
|
+
case char
|
72
|
+
when '(' then
|
73
|
+
levels += 1
|
74
|
+
when ')' then
|
75
|
+
levels -= 1
|
76
|
+
else
|
77
|
+
end
|
78
|
+
return index if levels == 0
|
79
|
+
index += 1
|
80
|
+
end
|
81
|
+
raise Exception, "cannot find end of parameter expression!"
|
82
|
+
end
|
83
|
+
|
84
|
+
# @param content_str [String] string that may contain parameterized expressions e.g. "a @(var0+var1) string @(var2)"
|
85
|
+
# @param param_hash [Hash] keys are parameter names, values are parameter values e.g. {var0: 'param', var1: 'eter'}
|
86
|
+
# @return [String] content_str with parameter values substituted and algebraically reduced if any unknown parameters remain e.g. 'a parameter string @(var2)'
|
87
|
+
def resolve_str(content_str, param_hash)
|
88
|
+
question = find_expr content_str
|
89
|
+
return content_str if question.nil?
|
90
|
+
reply = Macro.new e.evaluate(question, param_hash).to_s
|
91
|
+
replacement_str = reply.parameterized? ? reply.macro_string : reply.demacro
|
92
|
+
macro_string = Macro.new(question).macro_string
|
93
|
+
content_str.gsub(macro_string, replacement_str)
|
94
|
+
end
|
95
|
+
|
96
|
+
# @param str [String] string that may contain parameter expression e.g. 'asdf @(param + 2) asdf'
|
97
|
+
# @return [String] macro string e.g. 'asdf @(param + 2) asdf' => 'param + 2'
|
98
|
+
def find_expr(str)
|
99
|
+
expr_start_index = str.index('@(')
|
100
|
+
return nil if expr_start_index.nil?
|
101
|
+
expr_end_index = find_close_parens_index str[expr_start_index+1..-1]
|
102
|
+
str[expr_start_index+2, expr_end_index-1]
|
103
|
+
end
|
104
|
+
end # module Dux
|