fabulator 0.0.7 → 0.0.8
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.
- data/History.txt +8 -0
- data/TODO +7 -0
- data/VERSION +1 -1
- data/lib/fabulator/action.rb +9 -1
- data/lib/fabulator/core/actions.rb +7 -3
- data/lib/fabulator/core/constraint.rb +16 -1
- data/lib/fabulator/expr/context.rb +35 -6
- data/lib/fabulator/expr/node.rb +11 -1
- data/lib/fabulator/expr/parser.rb +103 -78
- data/lib/fabulator/lib.rb +5 -4
- data/lib/fabulator/lib/action.rb +45 -0
- data/lib/fabulator/lib/attribute.rb +11 -0
- data/lib/fabulator/lib/function.rb +36 -0
- data/lib/fabulator/lib/lib.rb +78 -5
- data/lib/fabulator/structural.rb +39 -11
- data/lib/fabulator/tag_lib.rb +2 -6
- data/xsm_expression_parser.racc +33 -6
- metadata +7 -4
data/lib/fabulator/lib.rb
CHANGED
@@ -47,6 +47,7 @@ require 'fabulator/lib/lib'
|
|
47
47
|
require 'fabulator/lib/structural'
|
48
48
|
require 'fabulator/lib/action'
|
49
49
|
require 'fabulator/lib/attribute'
|
50
|
+
require 'fabulator/lib/function'
|
50
51
|
|
51
52
|
module Fabulator
|
52
53
|
module Lib
|
@@ -57,10 +58,10 @@ module Fabulator
|
|
57
58
|
structural :structural, Structural
|
58
59
|
structural :action, Action
|
59
60
|
structural :attribute, Attribute
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
structural :function, Function
|
62
|
+
structural :mapping, Mapping
|
63
|
+
structural :reduction, Reduction
|
64
|
+
structural :consolidation, Consolidation
|
64
65
|
#structural :type, Type
|
65
66
|
#structural :filter, Filter
|
66
67
|
#structural :constraint, Constraint
|
data/lib/fabulator/lib/action.rb
CHANGED
@@ -1,13 +1,58 @@
|
|
1
|
+
#
|
2
|
+
# Provides functional support -- not quite closures (yet)
|
3
|
+
#
|
1
4
|
module Fabulator
|
2
5
|
module Lib
|
3
6
|
class Action < Fabulator::Structural
|
7
|
+
attr_accessor :attributes
|
8
|
+
|
4
9
|
namespace FAB_LIB_NS
|
5
10
|
|
6
11
|
attribute :name, :static => true
|
12
|
+
attribute 'has-actions', :static => true, :as => :has_actions, :type => :boolean
|
7
13
|
|
8
14
|
contains :attribute
|
9
15
|
|
10
16
|
has_actions
|
17
|
+
|
18
|
+
def compile_action(e, context)
|
19
|
+
ret = nil
|
20
|
+
context.with(e) do |ctx|
|
21
|
+
ret = ActionRef.new(self, ctx, ctx.compile_actions(e))
|
22
|
+
end
|
23
|
+
ret
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class ActionRef
|
28
|
+
def initialize(defining_action, context, actions = nil)
|
29
|
+
@context = context
|
30
|
+
@action = defining_action
|
31
|
+
@actions = actions
|
32
|
+
@static_attributes = { }
|
33
|
+
@action.attributes.collect{ |a| a.is_static? }.each do |a|
|
34
|
+
@static_attributes[a.path] = a.value(@context)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def run(context, autovivify = false)
|
39
|
+
ret = [ ]
|
40
|
+
@context.with(context) do |ctx|
|
41
|
+
@static_attributes.each_pair do |p,v|
|
42
|
+
ctx.set_value(p, v)
|
43
|
+
end
|
44
|
+
# These can be passed to f:eval to get their value
|
45
|
+
@action.attributes.collect{ |a| !a.is_static? }.each do |attr|
|
46
|
+
ctx.set_value(attr.path, attr.value(ctx))
|
47
|
+
end
|
48
|
+
# we can f:eval($actions) in whatever current context we have
|
49
|
+
if @action.has_actions?
|
50
|
+
ctx.set_var('actions', ctx.root.anon_node(@actions, [ FAB_NS, 'expression' ]))
|
51
|
+
end
|
52
|
+
ret = @action.run(ctx)
|
53
|
+
end
|
54
|
+
ret
|
55
|
+
end
|
11
56
|
end
|
12
57
|
end
|
13
58
|
end
|
@@ -4,6 +4,17 @@ module Fabulator
|
|
4
4
|
namespace FAB_LIB_NS
|
5
5
|
|
6
6
|
attribute :name, :static => true
|
7
|
+
attribute :ns, :static => true, :inherited => true
|
8
|
+
attribute :static, :static => true, :type => :boolean
|
9
|
+
attribute :eval, :static => true, :type => :boolean
|
10
|
+
|
11
|
+
def is_static?
|
12
|
+
@static
|
13
|
+
end
|
14
|
+
|
15
|
+
def value(context)
|
16
|
+
context.attribute(@ns, @name, { :static => @static, :eval => @eval })
|
17
|
+
end
|
7
18
|
end
|
8
19
|
end
|
9
20
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Fabulator
|
2
|
+
module Lib
|
3
|
+
class Function < Fabulator::Structural
|
4
|
+
namespace FAB_LIB_NS
|
5
|
+
|
6
|
+
attribute :name, :static => true
|
7
|
+
|
8
|
+
has_actions
|
9
|
+
end
|
10
|
+
|
11
|
+
class Mapping < Fabulator::Structural
|
12
|
+
namespace FAB_LIB_NS
|
13
|
+
|
14
|
+
attribute :name, :static => true
|
15
|
+
|
16
|
+
has_actions
|
17
|
+
end
|
18
|
+
|
19
|
+
class Reduction < Fabulator::Structural
|
20
|
+
namespace FAB_LIB_NS
|
21
|
+
|
22
|
+
attribute :name, :static => true
|
23
|
+
|
24
|
+
has_actions
|
25
|
+
end
|
26
|
+
|
27
|
+
class Consolidation < Fabulator::Structural
|
28
|
+
namespace FAB_LIB_NS
|
29
|
+
|
30
|
+
attribute :name, :static => true
|
31
|
+
|
32
|
+
has_actions
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
data/lib/fabulator/lib/lib.rb
CHANGED
@@ -3,6 +3,8 @@ module Fabulator
|
|
3
3
|
class Lib < Fabulator::Structural
|
4
4
|
|
5
5
|
namespace FAB_LIB_NS
|
6
|
+
|
7
|
+
element :library
|
6
8
|
|
7
9
|
attribute :ns, :static => true
|
8
10
|
|
@@ -17,16 +19,75 @@ module Fabulator
|
|
17
19
|
contains :constraint, :storage => :hash, :key => :name
|
18
20
|
|
19
21
|
def register_library
|
20
|
-
Fabulator::TagLib.namespaces[
|
21
|
-
@attributes.each do |attr|
|
22
|
-
Fabulator::TagLib.attributes << [ @ns, attr[:name], attr[:options] ]
|
23
|
-
end
|
22
|
+
Fabulator::TagLib.namespaces[self.ns] = self
|
24
23
|
end
|
25
24
|
|
26
|
-
def compile_action(e,
|
25
|
+
def compile_action(e, context)
|
26
|
+
name = e.name
|
27
|
+
return nil unless @actions.has_key?(name)
|
28
|
+
@actions[name].compile_action(e, context)
|
27
29
|
end
|
28
30
|
|
29
31
|
def run_function(context, nom, args)
|
32
|
+
# look for a function/mapping/consolidation
|
33
|
+
# then pass along to any objects in @contained
|
34
|
+
|
35
|
+
fctn = nil
|
36
|
+
fctn_type = nil
|
37
|
+
|
38
|
+
if nom =~ /^(.*)\*$/
|
39
|
+
cnom = $1
|
40
|
+
if !@consolidations[cnom].nil?
|
41
|
+
fctn = @consolidations[cnom]
|
42
|
+
fctn_type = :reduction
|
43
|
+
end
|
44
|
+
else
|
45
|
+
if @consolidations.has_key?(nom)
|
46
|
+
fctn = @reductions[nom]
|
47
|
+
fctn_type = :reduction
|
48
|
+
end
|
49
|
+
if fctn.nil?
|
50
|
+
fctn = @mappings[nom]
|
51
|
+
fctn_type = :mapping
|
52
|
+
end
|
53
|
+
if fctn.nil?
|
54
|
+
fctn = @functions[nom]
|
55
|
+
fctn_type = :function
|
56
|
+
end
|
57
|
+
if fctn.nil?
|
58
|
+
fctn = @reductions[nom]
|
59
|
+
fctn_type = :reduction
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
if !fctn.nil?
|
64
|
+
res = [ ]
|
65
|
+
context.in_context do |ctx|
|
66
|
+
args = args.flatten
|
67
|
+
case fctn_type
|
68
|
+
when :function:
|
69
|
+
args.size.times do |i|
|
70
|
+
ctx.set_var((i+1).to_s, args[i])
|
71
|
+
end
|
72
|
+
ctx.set_var('0', args)
|
73
|
+
res = fctn.run(ctx)
|
74
|
+
when :mapping:
|
75
|
+
res = args.collect{ |a| fctn.run(ctx.with_root(a)) }.flatten
|
76
|
+
when :reduction:
|
77
|
+
ctx.set_var('0', args.flatten)
|
78
|
+
res = fctn.run(ctx)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
return res
|
82
|
+
end
|
83
|
+
|
84
|
+
return [] if @contained.nil?
|
85
|
+
|
86
|
+
@contained.each do |c|
|
87
|
+
ret = c.run_function(context, nom, args)
|
88
|
+
return ret unless ret.nil? || ret.empty?
|
89
|
+
end
|
90
|
+
[]
|
30
91
|
end
|
31
92
|
|
32
93
|
def function_return_type(name)
|
@@ -38,9 +99,21 @@ module Fabulator
|
|
38
99
|
end
|
39
100
|
|
40
101
|
def run_filter(context, nom)
|
102
|
+
return if @contained.nil?
|
103
|
+
@contained.each do |c|
|
104
|
+
ret = c.run_filter(context, nom)
|
105
|
+
return ret unless ret.nil?
|
106
|
+
end
|
107
|
+
nil
|
41
108
|
end
|
42
109
|
|
43
110
|
def run_constraint(context, nom)
|
111
|
+
return if @contained.nil?
|
112
|
+
@contained.each do |c|
|
113
|
+
ret = c.run_constraint(context, nom)
|
114
|
+
return ret unless ret.nil?
|
115
|
+
end
|
116
|
+
false
|
44
117
|
end
|
45
118
|
end
|
46
119
|
end
|
data/lib/fabulator/structural.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
module Fabulator
|
2
2
|
class Structural < Action
|
3
3
|
|
4
|
-
def
|
4
|
+
def initialize
|
5
|
+
@context = Fabulator::Expr::Context.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def compile_xml(xml, context = nil)
|
5
9
|
XML.default_line_numbers = true
|
6
10
|
if xml.is_a?(String)
|
7
11
|
xml = LibXML::XML::Document.string xml
|
@@ -17,12 +21,12 @@ module Fabulator
|
|
17
21
|
end
|
18
22
|
|
19
23
|
self.setup(xml)
|
20
|
-
|
21
|
-
self
|
22
24
|
end
|
23
25
|
|
24
|
-
def self.element(nom)
|
25
|
-
@@elements
|
26
|
+
def self.element(nom = nil)
|
27
|
+
@@elements ||= { }
|
28
|
+
@@elements[self.name] = nom unless nom.nil?
|
29
|
+
@@elements[self.name]
|
26
30
|
end
|
27
31
|
|
28
32
|
def self.contains(nom, opts = { })
|
@@ -33,16 +37,40 @@ module Fabulator
|
|
33
37
|
@@structurals[self.name][ns][nom.to_sym] = opts
|
34
38
|
end
|
35
39
|
|
40
|
+
def self.contained_in(ns, nom, h = {})
|
41
|
+
@@contained_in ||= { }
|
42
|
+
|
43
|
+
@@contained_in[ns] ||= { }
|
44
|
+
@@contained_in[ns][nom.to_sym] ||= { }
|
45
|
+
@@contained_in[ns][nom.to_sym][self.namespace] ||= { }
|
46
|
+
@@contained_in[ns][nom.to_sym][self.namespace][self.element.to_sym] = h.update({ :as => :contained})
|
47
|
+
end
|
48
|
+
|
36
49
|
def self.structurals
|
37
|
-
|
50
|
+
ret = @@structurals[self.name]
|
51
|
+
els = self.element
|
52
|
+
els = [ els ] unless els.is_a?(Array)
|
53
|
+
|
54
|
+
return ret if self.element.nil?
|
55
|
+
|
56
|
+
@@contained_in ||= { }
|
57
|
+
|
58
|
+
return ret if @@contained_in[self.namespace].nil?
|
59
|
+
|
60
|
+
pot = @@contained_in[self.namespace][self.element.to_sym]
|
61
|
+
return ret if pot.nil? || pot.empty?
|
62
|
+
|
63
|
+
pot.each_pair do |ns, noms|
|
64
|
+
ret[ns] ||= { }
|
65
|
+
ret[ns] = ret[ns].update(noms)
|
66
|
+
end
|
67
|
+
ret
|
38
68
|
end
|
39
69
|
|
40
70
|
def self.accepts_structural?(ns, nom)
|
41
|
-
|
42
|
-
|
43
|
-
return
|
44
|
-
return false if @@structurals[self.name][ns][nom.to_sym].nil?
|
45
|
-
return true
|
71
|
+
s = self.structurals
|
72
|
+
in_s = (s[ns][nom.to_sym] rescue nil)
|
73
|
+
return !in_s.nil?
|
46
74
|
end
|
47
75
|
|
48
76
|
def accepts_structural?(ns, nom)
|
data/lib/fabulator/tag_lib.rb
CHANGED
@@ -74,7 +74,7 @@ module Fabulator
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def structural_class(nom)
|
77
|
-
Fabulator::TagLib.structural_classes[self.class.name][nom]
|
77
|
+
Fabulator::TagLib.structural_classes[self.class.name][nom.to_sym]
|
78
78
|
end
|
79
79
|
|
80
80
|
def self.inherited(base)
|
@@ -418,14 +418,10 @@ module Fabulator
|
|
418
418
|
r
|
419
419
|
}
|
420
420
|
Fabulator::TagLib.structural_classes[self.name] ||= {}
|
421
|
-
Fabulator::TagLib.structural_classes[self.name][name] = klass
|
421
|
+
Fabulator::TagLib.structural_classes[self.name][name.to_sym] = klass
|
422
422
|
end
|
423
423
|
end
|
424
424
|
|
425
|
-
def structural_class(nom)
|
426
|
-
(Fabulator::TagLib.structural_classes[self.class.name][nom] rescue nil)
|
427
|
-
end
|
428
|
-
|
429
425
|
def function(name, returns = nil, takes = nil, &block)
|
430
426
|
self.function_descriptions[name] = { :returns => returns, :takes => takes }
|
431
427
|
self.function_descriptions[name][:description] = Fabulator::TagLib.last_description if Fabulator::TagLib.last_description
|
data/xsm_expression_parser.racc
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
class Fabulator::Expr::Parser
|
2
|
+
#--
|
2
3
|
# based on XSM expression grammer from
|
3
4
|
# http://cpansearch.perl.org/src/JSMITH/Gestinanna-0.02/parser.PL
|
4
|
-
|
5
|
+
#
|
5
6
|
# instead of compiling ruby code, we'll instantiate objects to handle the
|
6
7
|
# run-time performance
|
8
|
+
#++
|
7
9
|
|
8
10
|
start statements
|
9
11
|
|
@@ -184,15 +186,38 @@ rule
|
|
184
186
|
end
|
185
187
|
|
186
188
|
---- inner
|
189
|
+
# == Fabulator Expression Parser
|
190
|
+
#
|
191
|
+
# <tt>Fabulator::Expr::Parser</tt> provides a parser for Fabulator
|
192
|
+
# expressions operating on a DOM-like data model provided by
|
193
|
+
# Fabulator::Expr::Context and Fabulator::Expr::Node.
|
194
|
+
#
|
195
|
+
# The expression language is based on XQuery and XPath.
|
196
|
+
#
|
197
|
+
|
187
198
|
require 'fabulator/expr'
|
188
199
|
require 'rational'
|
189
200
|
require 'bigdecimal'
|
190
201
|
require 'bigdecimal/util'
|
191
202
|
|
192
|
-
|
193
|
-
|
203
|
+
# Within the context of a Fabulator::Expr::Context object, this will
|
204
|
+
# parse the given string and return an object that can be run to return
|
205
|
+
# an array if Fabulator::Expr::Node objects.
|
206
|
+
#
|
207
|
+
# Example:
|
208
|
+
#
|
209
|
+
# parser = Fabulator::Expr::Parser.new
|
210
|
+
# context = Fabulator::Expr::Context.new
|
211
|
+
# expr = parser.parse('//foo', context)
|
212
|
+
# foos = expr.run(context)
|
213
|
+
#
|
214
|
+
# Results in 'foos' being an array of all of the nodes in the
|
215
|
+
# context that are named 'foo' regardless of their depth in the
|
216
|
+
# node tree.
|
217
|
+
def parse(text, context)
|
218
|
+
@source = text
|
194
219
|
@curpos = 0
|
195
|
-
@context =
|
220
|
+
@context = context
|
196
221
|
@line = 0
|
197
222
|
@col = 0
|
198
223
|
|
@@ -203,6 +228,8 @@ end
|
|
203
228
|
do_parse
|
204
229
|
end
|
205
230
|
|
231
|
+
# Used internally by the parser to raise a Fabulator::Expr::ParserError
|
232
|
+
# when the parse fails.
|
206
233
|
def on_error(*args)
|
207
234
|
raise Fabulator::Expr::ParserError.new("unable to parse '#{args[1]}' near line #{@line + 1}, column #{@col}")
|
208
235
|
end
|
@@ -396,8 +423,8 @@ end
|
|
396
423
|
if res[1] == 'if'
|
397
424
|
@token = [ :IF, 'if' ]
|
398
425
|
else
|
399
|
-
if @source[@curpos+res[1].length .. @curpos+res[1].length]
|
400
|
-
@token = [ :FUNCTION_NAME, res[1]
|
426
|
+
if @source[@curpos+res[1].length .. @curpos+res[1].length + 1] =~ /^(\??\*?)/
|
427
|
+
@token = [ :FUNCTION_NAME, res[1]+$1 ]
|
401
428
|
else
|
402
429
|
@token = [ :FUNCTION_NAME, res[1] ]
|
403
430
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fabulator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 8
|
10
|
+
version: 0.0.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- James Smith
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-09-
|
18
|
+
date: 2010-09-11 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -106,6 +106,7 @@ extensions: []
|
|
106
106
|
|
107
107
|
extra_rdoc_files:
|
108
108
|
- README.rdoc
|
109
|
+
- TODO
|
109
110
|
files:
|
110
111
|
- History.txt
|
111
112
|
- Manifest.txt
|
@@ -165,6 +166,7 @@ files:
|
|
165
166
|
- lib/fabulator/lib.rb
|
166
167
|
- lib/fabulator/lib/action.rb
|
167
168
|
- lib/fabulator/lib/attribute.rb
|
169
|
+
- lib/fabulator/lib/function.rb
|
168
170
|
- lib/fabulator/lib/lib.rb
|
169
171
|
- lib/fabulator/lib/structural.rb
|
170
172
|
- lib/fabulator/structural.rb
|
@@ -180,6 +182,7 @@ files:
|
|
180
182
|
- test/test_helper.rb
|
181
183
|
- xslt/form.xsl
|
182
184
|
- xsm_expression_parser.racc
|
185
|
+
- TODO
|
183
186
|
- test/cucumber.rb
|
184
187
|
has_rdoc: true
|
185
188
|
homepage: http://github.com/jgsmith/ruby-fabulator
|