re_duxml 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|