re_duxml 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|