re_duxml 0.1.0
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 +7 -0
- data/lib/ast_ext/node.rb +53 -0
- data/lib/re_duxml/array.rb +38 -0
- data/lib/re_duxml/element/parameterization.rb +18 -0
- data/lib/re_duxml/element.rb +9 -0
- data/lib/re_duxml/evaluate/lexer.rb +107 -0
- data/lib/re_duxml/evaluate/operator.rb +96 -0
- data/lib/re_duxml/evaluate/parser.rb +144 -0
- data/lib/re_duxml/evaluate.rb +78 -0
- data/lib/re_duxml.rb +99 -0
- data/lib/ruby_ext/boolean.rb +38 -0
- data/lib/ruby_ext/fixnum.rb +6 -0
- data/lib/ruby_ext/macro.rb +51 -0
- data/lib/ruby_ext/regexp.rb +7 -0
- data/lib/ruby_ext/string.rb +15 -0
- data/lib/symbolic_ext/coerced.rb +16 -0
- data/lib/symbolic_ext/symbolic.rb +26 -0
- data/lib/symbolic_ext/variable.rb +61 -0
- data/xml/logic.xml +153 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 996c30dfa1b40d7aa2d27de06d5bb770e4858f23
|
4
|
+
data.tar.gz: 20462c1ca90131bff9c05fbe9826001fd46f0cec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 46717577e85998db3f56ca0e26fd87b28f6220908fac32002683190b85d550340d3ca9b324163474f47a9ca5888b9f122fd22ed47af48a5c8abd528a071418e0
|
7
|
+
data.tar.gz: 2a04ed33b59e2209fb77c240d305233547af83973cb85e67c1d44cb9c14a9a96025f54d68b0b0b3f0e18c6ba5cc29d87e7a3dd369079182cc319450a5c9e284c
|
data/lib/ast_ext/node.rb
ADDED
@@ -0,0 +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.to_s << children.last.print
|
37
|
+
else
|
38
|
+
str << (children.first.respond_to?(:print) ? children.first.print(logic) : children.first.to_s) << 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
|
+
end
|
@@ -0,0 +1,38 @@
|
|
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
|
+
# TODO add implicit @iterator param
|
14
|
+
size_expr = size.respond_to?(:to_i) ? size.to_i : size.to_s
|
15
|
+
if size_expr.is_a? Fixnum
|
16
|
+
new_children = []
|
17
|
+
size_expr.times do
|
18
|
+
source_nodes = if nodes.empty? and self[:ref]
|
19
|
+
[resolve_ref.clone]
|
20
|
+
else
|
21
|
+
nodes.collect do |node| node.clone end
|
22
|
+
end
|
23
|
+
source_nodes.each do |node|
|
24
|
+
new_children << node
|
25
|
+
end
|
26
|
+
end
|
27
|
+
new_children.flatten
|
28
|
+
else
|
29
|
+
[self]
|
30
|
+
end
|
31
|
+
end # def instantiate
|
32
|
+
|
33
|
+
# size can be Fixnum or a Parameter expression
|
34
|
+
def size
|
35
|
+
self[:size]
|
36
|
+
end
|
37
|
+
end # class Array
|
38
|
+
end # module Dux
|
@@ -0,0 +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
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require_relative '../../ruby_ext/regexp'
|
3
|
+
require_relative '../../../lib/symbolic_ext/symbolic'
|
4
|
+
|
5
|
+
module Lexer
|
6
|
+
@string_hash
|
7
|
+
@input
|
8
|
+
@tokens
|
9
|
+
attr_reader :string_hash
|
10
|
+
attr_accessor :input, :tokens
|
11
|
+
|
12
|
+
TOKEN_TYPES = {
|
13
|
+
string: /STRING[\d]+/,
|
14
|
+
function: /log|exp|sqrt/,
|
15
|
+
bool: /true|false/,
|
16
|
+
param: Regexp.identifier,
|
17
|
+
num: /\d+/,
|
18
|
+
grouping: /[\(\):,]/
|
19
|
+
}
|
20
|
+
|
21
|
+
Struct.new('Token', :type, :value)
|
22
|
+
|
23
|
+
def lex(expr)
|
24
|
+
@input = tag_strings(expr).split(/\b/).reverse.collect do |s| s.strip end
|
25
|
+
@tokens = []
|
26
|
+
while (sub_str = input.pop) do
|
27
|
+
type = get_type sub_str
|
28
|
+
value = formatted_value(sub_str, type)
|
29
|
+
tokens << (@last_token = Struct::Token.new(type, value)) unless value.nil?
|
30
|
+
end
|
31
|
+
@last_token = nil
|
32
|
+
tokens
|
33
|
+
end # def lex(expr)
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
attr_reader :last_token
|
38
|
+
|
39
|
+
def formatted_value(sub_str, type)
|
40
|
+
formatted_str = untag_strings subst_minus(sub_str)
|
41
|
+
case type
|
42
|
+
when :operator, :grouping
|
43
|
+
split_or_keep formatted_str
|
44
|
+
when :param then get_var(formatted_str)
|
45
|
+
when :num then formatted_str.to_i
|
46
|
+
when :bool then formatted_str == 'true'
|
47
|
+
else
|
48
|
+
formatted_str
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_var(str)
|
53
|
+
if(var_token = tokens.find do |t| t.value.to_s == str end)
|
54
|
+
var_token.value
|
55
|
+
else
|
56
|
+
Symbolic.send(:var, name: str)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def split_or_keep(str)
|
61
|
+
if str.size > 1 && logic[str].nil?
|
62
|
+
str.split(//).reverse.each do |c| input << c unless c.strip.empty? end
|
63
|
+
nil
|
64
|
+
else
|
65
|
+
logic[str]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_type(sub_str)
|
70
|
+
TOKEN_TYPES.each do |type, regexp|
|
71
|
+
return type if regexp.match(sub_str).to_s == sub_str
|
72
|
+
end
|
73
|
+
:operator
|
74
|
+
end
|
75
|
+
|
76
|
+
def subst_minus(_str)
|
77
|
+
str = _str.dup
|
78
|
+
if str == '-'
|
79
|
+
unless last_token.nil? || last_token.type == 'operator' || %w(\( , :).include?(last_token.value)
|
80
|
+
str = "\u2013"
|
81
|
+
str.encode('utf-8')
|
82
|
+
end
|
83
|
+
end
|
84
|
+
str
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
def untag_strings(_expr)
|
89
|
+
expr = _expr.dup
|
90
|
+
string_hash.each do |k, v| expr.gsub!(k, v) end
|
91
|
+
expr
|
92
|
+
end
|
93
|
+
|
94
|
+
#strings can contain whitespaces and characters the parser may miscategorize as operators, etc.
|
95
|
+
# so they are replaced with unique keys in a module attribute hash for retrieval when doing string operations
|
96
|
+
# and returning final result
|
97
|
+
def tag_strings(expr)
|
98
|
+
tagged_str = expr.dup
|
99
|
+
@string_hash = {}
|
100
|
+
expr.scan(Regexp.string) do |s|
|
101
|
+
k = "STRING#{s.object_id}"
|
102
|
+
tagged_str[s] = k
|
103
|
+
@string_hash[k] = s
|
104
|
+
end
|
105
|
+
tagged_str
|
106
|
+
end
|
107
|
+
end # module Lexer
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
module Operator
|
3
|
+
# @return [Boolean]
|
4
|
+
def grouping?
|
5
|
+
nodes.find do |n|
|
6
|
+
return true if n.name == 'pair'
|
7
|
+
end
|
8
|
+
false
|
9
|
+
end
|
10
|
+
|
11
|
+
def parent=(logic)
|
12
|
+
@logic = logic
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Boolean]
|
16
|
+
def right_associative?
|
17
|
+
nodes.find do |n|
|
18
|
+
return n.text == 'true' if n.name == 'right_associative'
|
19
|
+
end
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [String] name of ruby method corresponding to this operator
|
24
|
+
def ruby
|
25
|
+
nodes.find do |n|
|
26
|
+
return n.text if n.name == 'ruby'
|
27
|
+
end
|
28
|
+
symbol
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [String] literal for operator e.g. '+'
|
32
|
+
def symbol
|
33
|
+
return nil unless self.respond_to?(:nodes)
|
34
|
+
nodes.find do |n|
|
35
|
+
return n.text if n.name == 'symbol'
|
36
|
+
end
|
37
|
+
raise Exception
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Symbol] :prefix, :infix (default), or :postfix
|
41
|
+
def position
|
42
|
+
nodes.find do |n|
|
43
|
+
return n.text.to_sym if n.name == 'position'
|
44
|
+
end
|
45
|
+
:infix
|
46
|
+
end
|
47
|
+
|
48
|
+
def reverse
|
49
|
+
nodes.find do |n|
|
50
|
+
return @logic[n.text] if n.name == 'reverse'
|
51
|
+
end
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def pair
|
56
|
+
return nil unless grouping?
|
57
|
+
nodes.find do |n|
|
58
|
+
return @logic[n.text] if n.name == 'pair'
|
59
|
+
end
|
60
|
+
raise Exception
|
61
|
+
end
|
62
|
+
|
63
|
+
def inverse
|
64
|
+
nodes.find do |n|
|
65
|
+
return @logic[n.text] if n.name == 'inverse'
|
66
|
+
end
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s
|
71
|
+
symbol
|
72
|
+
end
|
73
|
+
|
74
|
+
def print
|
75
|
+
nodes.find do |n|
|
76
|
+
return n.text if n.name == 'print'
|
77
|
+
end
|
78
|
+
symbol
|
79
|
+
end
|
80
|
+
|
81
|
+
# @return [Regexp] expression to find operator in string
|
82
|
+
def regexp
|
83
|
+
nodes.find do |n|
|
84
|
+
return Regexp.new(n.text) if %w(regexp symbol ).include?(n.name)
|
85
|
+
end
|
86
|
+
# TODO exception here?
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [Fixnum] number of arguments required
|
90
|
+
def arity
|
91
|
+
nodes.find do |n|
|
92
|
+
return n.text.to_i if n.name == 'arity'
|
93
|
+
end
|
94
|
+
2
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require 'duxml'
|
3
|
+
require_relative 'operator'
|
4
|
+
require_relative 'lexer'
|
5
|
+
|
6
|
+
module ReDuxml
|
7
|
+
class Parser
|
8
|
+
# hash of unique strings found in the parsed expression for substitution before (@see Lexer#lex) and
|
9
|
+
# after parsing to allow parser to handle strings that may contain white spaces, operators, etc.
|
10
|
+
@string_hash
|
11
|
+
|
12
|
+
# array of Struct::Tokens from lexer
|
13
|
+
@input
|
14
|
+
|
15
|
+
# array of AST nodes produced by parser; can be popped to subordinate to higher precedence operation nodes
|
16
|
+
@output
|
17
|
+
|
18
|
+
# array of operator definitions (not classes!) in XML form, extended by module Operator
|
19
|
+
@op_stack
|
20
|
+
|
21
|
+
# hash of operator symbol strings to Operator object that contains properties and methods to access them
|
22
|
+
@logic
|
23
|
+
|
24
|
+
# stack to track argument count for operators requiring more than 2
|
25
|
+
@arities
|
26
|
+
|
27
|
+
attr_reader :string_hash, :logic
|
28
|
+
attr_accessor :input, :output, :op_stack, :arities
|
29
|
+
|
30
|
+
include Duxml
|
31
|
+
include Lexer
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
doc.logic.name
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(_logic)
|
38
|
+
if _logic
|
39
|
+
load _logic
|
40
|
+
@logic = {}
|
41
|
+
doc.logic.Operator.each do |op|
|
42
|
+
op.parent = @logic
|
43
|
+
@logic[op.symbol] = op
|
44
|
+
end
|
45
|
+
end
|
46
|
+
raise Exception if logic.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
# TODO attribute code to Dentaku
|
50
|
+
def parse(expr)
|
51
|
+
@input = lex(expr)
|
52
|
+
@output = []
|
53
|
+
@op_stack = []
|
54
|
+
@arities = []
|
55
|
+
|
56
|
+
return nil if input.empty?
|
57
|
+
|
58
|
+
while(token = input.shift)
|
59
|
+
case token.type
|
60
|
+
when :num, :bool, :string, :param
|
61
|
+
output.push AST::Node.new(token.value)
|
62
|
+
when :operator
|
63
|
+
op_prop = token.value
|
64
|
+
arities << op_prop.arity-1 if op_prop.symbol == '?'
|
65
|
+
if op_prop.right_associative?
|
66
|
+
while op_stack.last && op_prop.precedence < op_stack.last.precedence
|
67
|
+
if !op_stack.last.grouping?
|
68
|
+
consume
|
69
|
+
else
|
70
|
+
break
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
while op_stack.last && op_prop.precedence <= op_stack.last.precedence && !op_stack.last.grouping?
|
75
|
+
consume
|
76
|
+
end
|
77
|
+
end
|
78
|
+
op_stack << op_prop
|
79
|
+
when :function
|
80
|
+
arities << 0
|
81
|
+
op_stack << token.value
|
82
|
+
when :grouping
|
83
|
+
op_prop = token.value
|
84
|
+
case op_prop.to_s
|
85
|
+
when '('
|
86
|
+
if input.any? && input.first.type == :grouping && input.first.value.to_s == '('
|
87
|
+
input.shift
|
88
|
+
consume(0)
|
89
|
+
else
|
90
|
+
op_stack << op_prop
|
91
|
+
end
|
92
|
+
when ')'
|
93
|
+
while op_stack.any? && op_stack.last.symbol != op_prop.pair.to_s
|
94
|
+
consume(arities.pop || op_stack.last.arity)
|
95
|
+
end
|
96
|
+
lparen = op_stack.pop
|
97
|
+
fail ParseError, "Unbalanced parenthesis" unless lparen && lparen.grouping?
|
98
|
+
|
99
|
+
if op_stack.last && op_stack.last.position == 'prefix'
|
100
|
+
consume(arities.pop)
|
101
|
+
end
|
102
|
+
when ','
|
103
|
+
arities[-1] += 1
|
104
|
+
while op_stack.any? && op_stack.last.symbol != '('
|
105
|
+
consume
|
106
|
+
end
|
107
|
+
when ':'
|
108
|
+
while op_stack.any? && op_stack.last.symbol != '?'
|
109
|
+
consume(arities.pop)
|
110
|
+
end
|
111
|
+
arities[-1] += 1
|
112
|
+
op_stack << op_prop
|
113
|
+
else
|
114
|
+
fail ParseError, "Unknown grouping token #{ token.value }"
|
115
|
+
end # case token.value ... when :grouping
|
116
|
+
else
|
117
|
+
fail ParseError, "Not implemented for tokens of type #{ token.type }"
|
118
|
+
end # case token.type
|
119
|
+
end # while (token = input.shift)
|
120
|
+
|
121
|
+
while op_stack.any?
|
122
|
+
consume
|
123
|
+
end
|
124
|
+
|
125
|
+
unless output.count == 1
|
126
|
+
fail ParseError, "Invalid statement"
|
127
|
+
end
|
128
|
+
|
129
|
+
output.first
|
130
|
+
end # def parse(expr)
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def consume(count=2)
|
135
|
+
op_stack.pop if op_stack.last.symbol == ':'
|
136
|
+
operator = op_stack.pop
|
137
|
+
output.push AST::Node.new(operator, get_args(operator.arity || count))
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_args(count)
|
141
|
+
Array.new(count) { output.pop }.reverse.compact
|
142
|
+
end
|
143
|
+
end # class Parser
|
144
|
+
end # module ReDuxml
|
@@ -0,0 +1,78 @@
|
|
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?(:print) then result.print(parser.logic)
|
36
|
+
else result.to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def resolve_params(_expr)
|
43
|
+
expr = _expr.dup
|
44
|
+
param_hash.each do |param, val| expr.gsub!(param, val) end
|
45
|
+
expr
|
46
|
+
end
|
47
|
+
|
48
|
+
include Symbolic
|
49
|
+
|
50
|
+
def reduce(_ast)
|
51
|
+
ast = _ast.type.respond_to?(:symbol) ? _ast : new_ast(parser.logic[_ast.type.to_s], _ast.children.dup)
|
52
|
+
if ast.children.any?
|
53
|
+
operator = ast.type
|
54
|
+
args = ast.children.collect do |c|
|
55
|
+
new_child = c.children.any? ? reduce(c) : c.type
|
56
|
+
if new_child.is_a?(Node) && new_child.type.is_a?(Symbol)
|
57
|
+
new_ast(parser.logic[new_child.type.to_s], *new_child.children.dup)
|
58
|
+
else
|
59
|
+
new_child
|
60
|
+
end
|
61
|
+
end.flatten
|
62
|
+
begin
|
63
|
+
result = case operator.position
|
64
|
+
when :prefix
|
65
|
+
method(operator.ruby).call(*args)
|
66
|
+
else
|
67
|
+
args.first.send(operator.ruby, *args[1..-1])
|
68
|
+
end
|
69
|
+
result.nil? ? ast : result
|
70
|
+
rescue
|
71
|
+
ast
|
72
|
+
end
|
73
|
+
else
|
74
|
+
ast
|
75
|
+
end
|
76
|
+
end # def reduce(ast)
|
77
|
+
end # class Evaluator
|
78
|
+
end # module ReDux
|
data/lib/re_duxml.rb
ADDED
@@ -0,0 +1,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 'con_duxml'
|
6
|
+
|
7
|
+
module ReDuxml
|
8
|
+
include ConDuxml
|
9
|
+
|
10
|
+
# @param doc_or_node [Doc, String] XML to load; can be Doc, String path or String XML; also XML Element when recursing
|
11
|
+
# @return [Doc] instantiated XML with parameters resolved with given values
|
12
|
+
def resolve(doc_or_node, parent_params={})
|
13
|
+
if doc_or_node.is_a?(Element)
|
14
|
+
resolved_node = doc_or_node.stub
|
15
|
+
this_params = get_params(doc_or_node, parent_params)
|
16
|
+
new_children = doc_or_node.nodes.collect do |child|
|
17
|
+
if child.respond_to?(:nodes)
|
18
|
+
new_child = child.clone
|
19
|
+
new_child.attributes.each do |attr, val|
|
20
|
+
new_child[attr] = resolve_str(val, this_params)
|
21
|
+
end
|
22
|
+
if new_child.if?
|
23
|
+
new_child[:if] = nil
|
24
|
+
child_params = get_params(new_child, this_params)
|
25
|
+
new_child.activate.collect do |inst|
|
26
|
+
resolve(inst, child_params)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
else
|
30
|
+
resolve_str(child, this_params)
|
31
|
+
end
|
32
|
+
end.flatten.compact
|
33
|
+
resolved_node << new_children
|
34
|
+
else
|
35
|
+
@e ||= Evaluator.new
|
36
|
+
@src_doc = get_doc doc_or_node
|
37
|
+
@doc = Doc.new << resolve(src_doc.root, parent_params)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
attr_reader :e, :src_doc
|
42
|
+
private
|
43
|
+
|
44
|
+
|
45
|
+
def get_params(node, param_hash)
|
46
|
+
if node.nodes.any? and !node.text? and node.nodes[0].name == 'duxml:parameters'
|
47
|
+
local_params = {}
|
48
|
+
params = node[0].nodes.clone
|
49
|
+
params.each do |param|
|
50
|
+
new_val = resolve_str(param[:value], param_hash)
|
51
|
+
node[0].delete param unless new_val.parameterized?
|
52
|
+
local_params[param[:name]] = new_val
|
53
|
+
end
|
54
|
+
node.delete node[0] unless node[0].nodes.any?
|
55
|
+
param_hash.merge local_params
|
56
|
+
else
|
57
|
+
param_hash
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# finds index of close parentheses corresponding to first open parentheses found in given str
|
62
|
+
def find_close_parens_index(str)
|
63
|
+
levels = 0
|
64
|
+
index = 0
|
65
|
+
str.each_char do |char|
|
66
|
+
case char
|
67
|
+
when '(' then
|
68
|
+
levels += 1
|
69
|
+
when ')' then
|
70
|
+
levels -= 1
|
71
|
+
else
|
72
|
+
end
|
73
|
+
return index if levels == 0
|
74
|
+
index += 1
|
75
|
+
end
|
76
|
+
raise Exception, "cannot find end of parameter expression!"
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param content_str [String] string that may contain parameterized expressions e.g. "a @(var0+var1) string @(var2)"
|
80
|
+
# @param param_hash [Hash] keys are parameter names, values are parameter values e.g. {var0: 'param', var1: 'eter'}
|
81
|
+
# @return [String] content_str with parameter values substituted and algebraically reduced if any unknown parameters remain e.g. 'a parameter string @(var2)'
|
82
|
+
def resolve_str(content_str, param_hash)
|
83
|
+
question = find_expr content_str
|
84
|
+
return content_str if question.nil?
|
85
|
+
reply = Macro.new e.evaluate(question, param_hash).to_s
|
86
|
+
replacement_str = reply.parameterized? ? reply.macro_string : reply.demacro
|
87
|
+
macro_string = Macro.new(question).macro_string
|
88
|
+
content_str.gsub(macro_string, replacement_str)
|
89
|
+
end
|
90
|
+
|
91
|
+
# @param str [String] string that may contain parameter expression e.g. 'asdf @(param + 2) asdf'
|
92
|
+
# @return [String] macro string e.g. 'asdf @(param + 2) asdf' => 'param + 2'
|
93
|
+
def find_expr(str)
|
94
|
+
expr_start_index = str.index('@(')
|
95
|
+
return nil if expr_start_index.nil?
|
96
|
+
expr_end_index = find_close_parens_index str[expr_start_index+1..-1]
|
97
|
+
str[expr_start_index+2, expr_end_index-1]
|
98
|
+
end
|
99
|
+
end # module Dux
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require_relative '../../lib/ast_ext/node'
|
3
|
+
|
4
|
+
class TrueClass
|
5
|
+
def ternary(a, b)
|
6
|
+
a
|
7
|
+
end
|
8
|
+
|
9
|
+
def and(obj)
|
10
|
+
obj
|
11
|
+
end
|
12
|
+
|
13
|
+
def or(obj)
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def not
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class FalseClass
|
23
|
+
def ternary(a, b)
|
24
|
+
b
|
25
|
+
end
|
26
|
+
|
27
|
+
def and(obj)
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def or(obj)
|
32
|
+
obj
|
33
|
+
end
|
34
|
+
|
35
|
+
def not
|
36
|
+
true
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require_relative 'string'
|
3
|
+
|
4
|
+
# string wrapped in parameter expression macro symbol and delimiters,
|
5
|
+
# indicating content is to be parsed and resolved when building and validating XML design
|
6
|
+
class Macro
|
7
|
+
include Enumerable
|
8
|
+
include Comparable
|
9
|
+
|
10
|
+
# is '@' by default
|
11
|
+
MACRO_SYMBOL = '@'
|
12
|
+
# are parentheses by default e.g. '()'
|
13
|
+
DELIMITERS = %w{( )}
|
14
|
+
|
15
|
+
@macro_string
|
16
|
+
|
17
|
+
# string including MACRO_SYMBOL and DELIMITERS
|
18
|
+
attr_accessor :macro_string
|
19
|
+
|
20
|
+
# checks a string to see if it's a valid macro expression without leading or trailing non-expression or delimiter text
|
21
|
+
def self.is_macro?(str)
|
22
|
+
str[0,2] == MACRO_SYMBOL+DELIMITERS.first && str[-1] == DELIMITERS.last && str.balanced_parens?
|
23
|
+
end
|
24
|
+
|
25
|
+
# takes given string and wraps in MACRO_SYMBOL and DELIMITERS if not already wrapped
|
26
|
+
# e.g. str => 'asdf'
|
27
|
+
# Macro.new str => '@(asdf)'
|
28
|
+
def initialize(str)
|
29
|
+
@macro_string = Macro.is_macro?(str) ? str : "#{MACRO_SYMBOL}#{DELIMITERS.first}#{str}#{DELIMITERS.last}"
|
30
|
+
end
|
31
|
+
|
32
|
+
# compares #demacro'd @macro_string to obj
|
33
|
+
def <=>(obj)
|
34
|
+
demacro <=> obj
|
35
|
+
end
|
36
|
+
|
37
|
+
# just yields each character of #demacro'd @macro_string
|
38
|
+
def each(&block)
|
39
|
+
demacro.split(//).each do |char| yield char end
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns string without MACRO_SYMBOL and DELIMITERS
|
43
|
+
def demacro
|
44
|
+
macro_string[2..-2]
|
45
|
+
end
|
46
|
+
|
47
|
+
# returns nil if not, and match data for any parameter names found
|
48
|
+
def parameterized?
|
49
|
+
macro_string.match Regexp.identifier
|
50
|
+
end
|
51
|
+
end # class Macro
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require 'duxml'
|
3
|
+
|
4
|
+
# extending String with #parameterized? and #balanced_parens? only to assist macro.rb
|
5
|
+
class String
|
6
|
+
# returns whether or not contents include any Macro strings i.e. Parameter expressions
|
7
|
+
def parameterized?
|
8
|
+
self.include?('@(')
|
9
|
+
end
|
10
|
+
|
11
|
+
# returns whether number of open parentheses and close parentheses match
|
12
|
+
def balanced_parens?
|
13
|
+
self.match(/\(/).size == self.match(/\)/).size
|
14
|
+
end
|
15
|
+
end # class String
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require_relative 'variable'
|
3
|
+
|
4
|
+
module Symbolic
|
5
|
+
class Coerced
|
6
|
+
include AST
|
7
|
+
|
8
|
+
def %(numeric)
|
9
|
+
numeric.new_ast(:%, @symbolic)
|
10
|
+
end
|
11
|
+
|
12
|
+
def **(numeric)
|
13
|
+
numeric.new_ast(:**, @symbolic)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require_relative 'coerced'
|
3
|
+
|
4
|
+
module Symbolic
|
5
|
+
include AST
|
6
|
+
|
7
|
+
def %(var)
|
8
|
+
return 0 if self.object_id == var.object_id
|
9
|
+
return self % var if self.is_a?(Numeric) && var.is_a?(Numeric)
|
10
|
+
new_ast :%, var
|
11
|
+
end
|
12
|
+
|
13
|
+
def -@(var)
|
14
|
+
return -var unless var.is_a?(Node)
|
15
|
+
return -var.type if var.type.is_a?(Numeric)
|
16
|
+
reversed = var.type.reverse
|
17
|
+
reversed ? new_ast(reversed, *var.children.dup) : new_ast(:-@, [var])
|
18
|
+
end
|
19
|
+
|
20
|
+
def not(var)
|
21
|
+
return nil if var.is_a?(Symbolic::Variable)
|
22
|
+
return !var unless var.is_a?(Node)
|
23
|
+
inverted = var.type.inverse
|
24
|
+
inverted ? new_ast(inverted, *var.children.dup) : new_ast(:!, [var])
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
require 'symbolic'
|
3
|
+
require_relative '../ruby_ext/fixnum'
|
4
|
+
require_relative '../ruby_ext/boolean'
|
5
|
+
|
6
|
+
module Symbolic
|
7
|
+
class Variable
|
8
|
+
include AST
|
9
|
+
|
10
|
+
def and(obj)
|
11
|
+
return self if obj.equal?(true) || obj.equal?(self)
|
12
|
+
return false if obj.equal?(false)
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def or(obj)
|
17
|
+
return self if obj.equal?(false) || obj.equal?(self)
|
18
|
+
return true if obj.equal?(true)
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def <(obj)
|
23
|
+
eql?(obj) ? false : nil
|
24
|
+
end
|
25
|
+
|
26
|
+
def >(obj)
|
27
|
+
eql?(obj) ? false : nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def !=(obj)
|
31
|
+
if obj.is_a?(Variable) || obj.is_a?(Numeric)
|
32
|
+
return object_id == obj.object_id ? false : nil
|
33
|
+
end
|
34
|
+
|
35
|
+
return !self if obj.equal?(true)
|
36
|
+
return self if obj.equal?(false)
|
37
|
+
return false if obj.equal?(self)
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def ==(obj)
|
42
|
+
if obj.is_a?(Variable) || obj.is_a?(Numeric)
|
43
|
+
result = object_id == obj.object_id ? true : nil
|
44
|
+
return result
|
45
|
+
end
|
46
|
+
|
47
|
+
return !self if obj.equal?(false)
|
48
|
+
return self if obj.equal?(true)
|
49
|
+
return true if obj.equal?(self)
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def >=(obj)
|
54
|
+
object_id == obj.object_id ? true : nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def <=(obj)
|
58
|
+
object_id == obj.object_id ? true : nil
|
59
|
+
end
|
60
|
+
end # class Variable
|
61
|
+
end # module Symbolic
|
data/xml/logic.xml
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<logic>
|
3
|
+
<!-- indexing -->
|
4
|
+
<operator id="op_square" precedence="90" logic="string">
|
5
|
+
<regexp>\[</regexp>
|
6
|
+
<symbol>[</symbol>
|
7
|
+
<pair>]</pair>
|
8
|
+
</operator>
|
9
|
+
<operator id="cl_square" precedence="90" logic="string">
|
10
|
+
<regexp>\]</regexp>
|
11
|
+
<symbol>]</symbol>
|
12
|
+
<position>postfix</position>
|
13
|
+
<pair>[</pair>
|
14
|
+
<arity>1</arity>
|
15
|
+
</operator>
|
16
|
+
|
17
|
+
<!-- grouping -->
|
18
|
+
<operator id="op_parens" precedence="100" logic="global">
|
19
|
+
<regexp>\(</regexp>
|
20
|
+
<symbol>(</symbol>
|
21
|
+
<position>prefix</position>
|
22
|
+
<pair>)</pair>
|
23
|
+
<arity>1</arity>
|
24
|
+
</operator>
|
25
|
+
<operator id="cl_parens" precedence="100" logic="global">
|
26
|
+
<regexp>\)</regexp>
|
27
|
+
<symbol>)</symbol>
|
28
|
+
<position>postfix</position>
|
29
|
+
<pair>(</pair>
|
30
|
+
<arity>1</arity>
|
31
|
+
</operator>
|
32
|
+
|
33
|
+
<!-- combinators -->
|
34
|
+
<operator id="interro" logic="global" precedence="0">
|
35
|
+
<regexp>\?</regexp>
|
36
|
+
<symbol>?</symbol>
|
37
|
+
<right_associative>true</right_associative>
|
38
|
+
<ruby>ternary</ruby>
|
39
|
+
<arity>3</arity>
|
40
|
+
<pair>:</pair>
|
41
|
+
</operator>
|
42
|
+
<operator id="colon" logic="global" precedence="0">
|
43
|
+
<symbol>:</symbol>
|
44
|
+
<pair>?</pair>
|
45
|
+
</operator>
|
46
|
+
<operator id="and" logic="boolean" precedence="10">
|
47
|
+
<regexp>&{2}</regexp>
|
48
|
+
<symbol>&&</symbol>
|
49
|
+
<ruby>and</ruby>
|
50
|
+
<identity>true</identity>
|
51
|
+
</operator>
|
52
|
+
<operator id="or" logic="boolean" precedence="10">
|
53
|
+
<regexp>\|{2}</regexp>
|
54
|
+
<symbol>||</symbol>
|
55
|
+
<ruby>or</ruby>
|
56
|
+
<identity>false</identity>
|
57
|
+
</operator>
|
58
|
+
<operator id="not" logic="boolean" precedence="11">
|
59
|
+
<position>prefix</position>
|
60
|
+
<regexp>(!)(?=\w|!)</regexp>
|
61
|
+
<ruby>not</ruby>
|
62
|
+
<symbol>!</symbol>
|
63
|
+
<arity>1</arity>
|
64
|
+
<identity>monad</identity>
|
65
|
+
<right_associative>true</right_associative>
|
66
|
+
<inverse>!</inverse>
|
67
|
+
</operator>
|
68
|
+
|
69
|
+
<!-- comparators -->
|
70
|
+
<operator id="eq" logic="arithmetic string" precedence="30">
|
71
|
+
<symbol>==</symbol>
|
72
|
+
<reverse>==</reverse>
|
73
|
+
<inverse>!=</inverse>
|
74
|
+
</operator>
|
75
|
+
<operator id="lt" logic="arithmetic string" precedence="35">
|
76
|
+
<symbol><</symbol>
|
77
|
+
<reverse>></reverse>
|
78
|
+
<inverse>>=</inverse>
|
79
|
+
</operator>
|
80
|
+
<operator id="gt" logic="arithmetic string" precedence="35">
|
81
|
+
<symbol>></symbol>
|
82
|
+
<reverse><</reverse>
|
83
|
+
<inverse><=</inverse>
|
84
|
+
</operator>
|
85
|
+
<operator id="le" logic="arithmetic string" precedence="35">
|
86
|
+
<symbol><=</symbol>
|
87
|
+
<reverse>>=</reverse>
|
88
|
+
<inverse>></inverse>
|
89
|
+
</operator>
|
90
|
+
<operator id="ge" logic="arithmetic string" precedence="35">
|
91
|
+
<symbol>>=</symbol>
|
92
|
+
<reverse><=</reverse>
|
93
|
+
<inverse><</inverse>
|
94
|
+
</operator>
|
95
|
+
<operator id="ne" logic="arithmetic string" precedence="30">
|
96
|
+
<symbol>!=</symbol>
|
97
|
+
<reverse>!=</reverse>
|
98
|
+
<inverse>==</inverse>
|
99
|
+
</operator>
|
100
|
+
|
101
|
+
<!-- arithmetic -->
|
102
|
+
<operator id="add" precedence="55" logic="arithmetic string">
|
103
|
+
<regexp>\+</regexp>
|
104
|
+
<symbol>+</symbol>
|
105
|
+
<identity>0</identity>
|
106
|
+
<inverse>–</inverse>
|
107
|
+
</operator>
|
108
|
+
<operator id="sub" precedence="55" logic="arithmetic">
|
109
|
+
<symbol>–</symbol>
|
110
|
+
<ruby>-</ruby>
|
111
|
+
<identity>0</identity>
|
112
|
+
<inverse>+</inverse>
|
113
|
+
</operator>
|
114
|
+
<operator id="neg" precedence="65" logic="arithmetic">
|
115
|
+
<position>prefix</position>
|
116
|
+
<symbol>-</symbol>
|
117
|
+
<ruby>-@</ruby>
|
118
|
+
<arity>1</arity>
|
119
|
+
<right_associative>true</right_associative>
|
120
|
+
<identity>0</identity>
|
121
|
+
<inverse>-</inverse>
|
122
|
+
</operator>
|
123
|
+
<operator id="mul" precedence="60" logic="arithmetic">
|
124
|
+
<regexp>\*</regexp>
|
125
|
+
<symbol>*</symbol>
|
126
|
+
<print>×</print>
|
127
|
+
<identity>1</identity>
|
128
|
+
<inverse>/</inverse>
|
129
|
+
</operator>
|
130
|
+
<operator id="div" precedence="60" logic="arithmetic">
|
131
|
+
<regexp>\/</regexp>
|
132
|
+
<symbol>/</symbol>
|
133
|
+
<print>÷</print>
|
134
|
+
<identity>1</identity>
|
135
|
+
<inverse>*</inverse>
|
136
|
+
</operator>
|
137
|
+
<operator id="mod" precedence="60" logic="arithmetic">
|
138
|
+
<symbol>%</symbol>
|
139
|
+
</operator>
|
140
|
+
<operator id="exp" precedence="70" logic="arithmetic">
|
141
|
+
<regexp>\*{2}</regexp>
|
142
|
+
<symbol>**</symbol>
|
143
|
+
<ruby>**</ruby>
|
144
|
+
<print>^</print>
|
145
|
+
<identity>1</identity>
|
146
|
+
<inverse>log</inverse>
|
147
|
+
</operator>
|
148
|
+
<operator id="log" precedence="70" logic="arithmetic">
|
149
|
+
<symbol>log</symbol>
|
150
|
+
<position>prefix</position>
|
151
|
+
<inverse>^</inverse>
|
152
|
+
</operator>
|
153
|
+
</logic>
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: re_duxml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Peter Kong
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: con_duxml
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.4.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.4.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ast
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: symbolic
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.3'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- peter.kong@nxp.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- lib/ast_ext/node.rb
|
63
|
+
- lib/re_duxml/array.rb
|
64
|
+
- lib/re_duxml/element/parameterization.rb
|
65
|
+
- lib/re_duxml/element.rb
|
66
|
+
- lib/re_duxml/evaluate/lexer.rb
|
67
|
+
- lib/re_duxml/evaluate/operator.rb
|
68
|
+
- lib/re_duxml/evaluate/parser.rb
|
69
|
+
- lib/re_duxml/evaluate.rb
|
70
|
+
- lib/re_duxml.rb
|
71
|
+
- lib/ruby_ext/boolean.rb
|
72
|
+
- lib/ruby_ext/fixnum.rb
|
73
|
+
- lib/ruby_ext/macro.rb
|
74
|
+
- lib/ruby_ext/regexp.rb
|
75
|
+
- lib/ruby_ext/string.rb
|
76
|
+
- lib/symbolic_ext/coerced.rb
|
77
|
+
- lib/symbolic_ext/symbolic.rb
|
78
|
+
- lib/symbolic_ext/variable.rb
|
79
|
+
- xml/logic.xml
|
80
|
+
homepage: http://www.github.com/re_duxml
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 1.9.3
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 1.8.11
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.0.14.1
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Reusable Dynamic Universal XML
|
104
|
+
test_files: []
|