sfp 0.3.5 → 0.3.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -2
- data/bin/sfp +8 -2
- data/lib/sfp/SfpLangLexer.rb +340 -372
- data/lib/sfp/SfpLangParser.rb +4065 -3960
- data/lib/sfp/Sfplib.rb +32 -31
- data/lib/sfp/parser.rb +43 -129
- data/lib/sfp/sas_translator.rb +25 -28
- data/sfp.gemspec +3 -3
- data/src/SfpLang.g +52 -39
- metadata +18 -8
data/lib/sfp/Sfplib.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
module Sfp
|
2
2
|
module SfpLangHelper
|
3
|
-
attr_accessor :root_dir, :home_dir
|
3
|
+
attr_accessor :root_dir, :home_dir, :constraint_next_id
|
4
4
|
attr_reader :root, :used_classes, :arrays, :conformant
|
5
5
|
|
6
6
|
def init
|
7
7
|
@root = Hash.new
|
8
8
|
@now = @root
|
9
|
-
@id = 0
|
10
9
|
@root['Object'] = { '_self' => 'Object', '_context' => 'class', '_parent' => @root }
|
11
10
|
@unexpanded_classes = Array.new
|
12
11
|
@used_classes = Array.new
|
@@ -15,8 +14,8 @@ module Sfp
|
|
15
14
|
end
|
16
15
|
|
17
16
|
def next_id
|
18
|
-
nid = "c"
|
19
|
-
@
|
17
|
+
nid = "c#{@constraint_next_id}"
|
18
|
+
@constraint_next_id += 1
|
20
19
|
return nid
|
21
20
|
end
|
22
21
|
|
@@ -48,25 +47,25 @@ module Sfp
|
|
48
47
|
|
49
48
|
raise Exception, 'File not found: ' + file if not File.exist?(filepath)
|
50
49
|
|
51
|
-
|
52
|
-
|
50
|
+
parser = Sfp::Parser.new({ :root_dir => @root_dir,
|
51
|
+
:home_dir => File.expand_path(File.dirname(filepath)),
|
52
|
+
:constraint_next_id => @constraint_next_id })
|
53
53
|
parser.parse(File.read(filepath))
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
if @root[key]['_context'] != val['_context']
|
61
|
-
@root[key] = val
|
62
|
-
else
|
63
|
-
val['_context'].each_pair { |k2,v2| @root[key][k2] = v2 }
|
64
|
-
end
|
54
|
+
parser.root.each_pair do |key,val|
|
55
|
+
if val.is_a?(Hash)
|
56
|
+
if val['_context'] == 'state' and @root.has_key?(key) and @root[key]['_context'] == 'state'
|
57
|
+
val.each_pair { |k2,v2| @root[key][k2] = v2 if k2[0,1] != '_' }
|
58
|
+
elsif val['_context'] == 'constraint' and @root.has_key?(key) and @root[key]['_context'] == 'constraint'
|
59
|
+
val.each_pair { |k2,v2| @root[key][k2] = v2 if k2[0,1] != '_' }
|
65
60
|
else
|
66
61
|
@root[key] = val
|
62
|
+
val['_parent'] = @root if val['_context'] != 'state'
|
67
63
|
end
|
64
|
+
else
|
65
|
+
@root[key] = val
|
68
66
|
end
|
69
|
-
|
67
|
+
end
|
68
|
+
@constraint_next_id = parser.constraint_next_id
|
70
69
|
end
|
71
70
|
|
72
71
|
def goto_parent(remove_parent=false)
|
@@ -76,20 +75,22 @@ module Sfp
|
|
76
75
|
return n
|
77
76
|
end
|
78
77
|
|
79
|
-
def
|
80
|
-
@
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
if
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
c['_finals'] = sclass['_finals']
|
90
|
-
end
|
78
|
+
def expand_class(c)
|
79
|
+
sclass = @root.at?(c['_extends'])
|
80
|
+
c.inherits( sclass )
|
81
|
+
c['_super'] = (sclass.has_key?('_super') ? sclass['_super'].clone : Array.new)
|
82
|
+
c['_super'] << c['_extends']
|
83
|
+
if sclass['_finals'].is_a?(Array)
|
84
|
+
if c['_finals'].is_a?(Array)
|
85
|
+
c['_finals'].concat(sclass['_finals'])
|
86
|
+
else
|
87
|
+
c['_finals'] = sclass['_finals']
|
91
88
|
end
|
92
|
-
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def expand_classes
|
93
|
+
@unexpanded_classes.each { |c| expand_class(c) }
|
93
94
|
end
|
94
95
|
|
95
96
|
def expand_object(obj)
|
data/lib/sfp/parser.rb
CHANGED
@@ -1,136 +1,50 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
# @param string : a string in SFP language
|
23
|
-
def parse(string)
|
24
|
-
lexer = SfpLang::Lexer.new(string)
|
25
|
-
tokens = ANTLR3::CommonTokenStream.new(lexer)
|
26
|
-
parser = SfpLang::Parser.new(tokens)
|
27
|
-
parser.root_dir = @root_dir
|
28
|
-
parser.home_dir = @home_dir
|
29
|
-
parser.sfp
|
30
|
-
@root = parser.root
|
31
|
-
@conformant = parser.conformant
|
32
|
-
@parser_arrays = parser.arrays
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_json(params={})
|
36
|
-
return 'null' if @root.nil?
|
37
|
-
return Sfp::Helper.to_pretty_json(@root) if params[:pretty]
|
38
|
-
return Sfp::Helper.to_json(@root)
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.parse_file(filepath)
|
42
|
-
homedir = File.expand_path(File.dirname(filepath))
|
43
|
-
parser = Sfp::Parser.new({:home_dir => homedir})
|
44
|
-
parser.parse(File.read(filepath))
|
45
|
-
parser.root
|
46
|
-
end
|
47
|
-
|
48
|
-
=begin
|
49
|
-
# Parse SFP file and return its JSON representation
|
50
|
-
def self.parse_file(file)
|
51
|
-
return file_to_sfp(file)
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.file_to_sfp(file)
|
55
|
-
parser = Parser.new
|
56
|
-
parser.parse_file(file)
|
57
|
-
return parser.to_sfp
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.to_sfp(string)
|
61
|
-
parser = Parser.new
|
62
|
-
parser.parse(string)
|
63
|
-
return parser.to_sfp
|
64
|
-
end
|
65
|
-
|
66
|
-
# parse SFP file
|
67
|
-
def parse_file(file)
|
68
|
-
f = File.open(file, 'rb')
|
69
|
-
lexer = SFP::Lexer.new(f)
|
70
|
-
tokens = ANTLR3::CommonTokenStream.new(lexer)
|
71
|
-
parser = SFP::Parser.new(tokens)
|
72
|
-
parser.root_dir = (@root_dir == nil or @root_dir == '' ?
|
73
|
-
File.expand_path('.') : @root_dir)
|
74
|
-
parser.home_dir = File.dirname(f.path)
|
75
|
-
parser.sfp
|
76
|
-
@conformant = parser.conformant
|
77
|
-
@root = parser.root
|
78
|
-
@parser_arrays = parser.arrays
|
79
|
-
end
|
80
|
-
|
81
|
-
# parse SFP in a string
|
82
|
-
def parse(text)
|
83
|
-
lexer = SFP::Lexer.new(text)
|
84
|
-
tokens = ANTLR3::CommonTokenStream.new(lexer)
|
85
|
-
parser = SFP::Parser.new(tokens)
|
86
|
-
parser.root_dir = (@root_dir == nil or @root_dir == '' ?
|
87
|
-
File.expand_path(File.dirname('.')) : @root_dir)
|
88
|
-
parser.home_dir = parser.root_dir
|
89
|
-
parser.sfp
|
90
|
-
@root = parser.root
|
91
|
-
@parser_arrays = parser.arrays
|
92
|
-
end
|
93
|
-
|
94
|
-
# dump the parsed specification into standard output
|
95
|
-
def dump(root=nil)
|
96
|
-
return if root == nil
|
97
|
-
root = Nuri::Sfp.deep_clone(@root)
|
98
|
-
root.accept(ParentEliminator.new)
|
99
|
-
puts JSON.pretty_generate(root)
|
100
|
-
end
|
101
|
-
|
102
|
-
def self.dump(root)
|
103
|
-
return if root == nil
|
104
|
-
root = Nuri::Sfp.deep_clone(root)
|
105
|
-
root.accept(ParentEliminator.new)
|
106
|
-
puts JSON.pretty_generate(root)
|
107
|
-
end
|
108
|
-
|
109
|
-
def to_sfp
|
110
|
-
@root
|
111
|
-
end
|
112
|
-
|
113
|
-
def to_json
|
114
|
-
root = self.to_sfp
|
115
|
-
return if root == nil
|
116
|
-
root = Nuri::Sfp.deep_clone(root)
|
117
|
-
return Nuri::Sfp.to_json(root)
|
118
|
-
end
|
119
|
-
=end
|
1
|
+
# main class which processes configuration description in SFP language either
|
2
|
+
# in file or as a string
|
3
|
+
class Sfp::Parser
|
4
|
+
# enable this class to process SFP into FDR (SAS+)
|
5
|
+
include Sfp::SasTranslator
|
6
|
+
|
7
|
+
attr_accessor :root_dir, :home_dir, :conformant
|
8
|
+
attr_reader :root, :constraint_next_id
|
9
|
+
|
10
|
+
def initialize(params={})
|
11
|
+
@root_dir = (params[:root_dir].is_a?(String) ?
|
12
|
+
params[:root_dir].strip :
|
13
|
+
nil)
|
14
|
+
@home_dir = (params[:home_dir].is_a?(String) ?
|
15
|
+
params[:home_dir].strip :
|
16
|
+
nil)
|
17
|
+
@root = params[:root]
|
18
|
+
@conformant = !!params[:conformant]
|
19
|
+
@constraint_next_id = (params[:constraint_next_id] ? params[:constraint_next_id] : 0)
|
120
20
|
end
|
121
21
|
|
122
|
-
|
123
|
-
def
|
124
|
-
|
125
|
-
|
126
|
-
|
22
|
+
# @param string : a string in SFP language
|
23
|
+
def parse(string, options={})
|
24
|
+
lexer = SfpLang::Lexer.new(string)
|
25
|
+
tokens = ANTLR3::CommonTokenStream.new(lexer)
|
26
|
+
parser = SfpLang::Parser.new(tokens)
|
27
|
+
parser.root_dir = @root_dir
|
28
|
+
parser.home_dir = @home_dir
|
29
|
+
parser.constraint_next_id = @constraint_next_id
|
30
|
+
parser.sfp
|
31
|
+
@constraint_next_id = parser.constraint_next_id
|
32
|
+
@root = parser.root
|
33
|
+
@conformant = parser.conformant
|
34
|
+
@parser_arrays = parser.arrays
|
127
35
|
end
|
128
36
|
|
129
|
-
def
|
130
|
-
|
131
|
-
|
132
|
-
return
|
37
|
+
def to_json(params={})
|
38
|
+
return 'null' if @root.nil?
|
39
|
+
return Sfp::Helper.to_pretty_json(@root) if params[:pretty]
|
40
|
+
return Sfp::Helper.to_json(@root)
|
133
41
|
end
|
134
|
-
=end
|
135
42
|
|
43
|
+
def self.parse_file(filepath, options={})
|
44
|
+
#homedir = File.expand_path(File.dirname(filepath))
|
45
|
+
options[:home_dir] = File.expand_path(File.dirname(filepath)) if !options[:home_dir]
|
46
|
+
parser = Sfp::Parser.new(options) #{:home_dir => homedir})
|
47
|
+
parser.parse(File.read(filepath))
|
48
|
+
parser.root
|
49
|
+
end
|
136
50
|
end
|
data/lib/sfp/sas_translator.rb
CHANGED
@@ -162,15 +162,11 @@ module Sfp
|
|
162
162
|
end
|
163
163
|
|
164
164
|
### process all procedures
|
165
|
-
@variables.each_value
|
165
|
+
@variables.each_value do |var|
|
166
166
|
if var.is_final
|
167
|
-
var.init.each { |k,v|
|
168
|
-
if v.is_a?(Hash) and v.isprocedure
|
169
|
-
process_procedure(v, var.init)
|
170
|
-
end
|
171
|
-
}
|
167
|
+
var.init.each { |k,v| process_procedure(v, var.init) if v.is_a?(Hash) and v.isprocedure }
|
172
168
|
end
|
173
|
-
|
169
|
+
end
|
174
170
|
self.reset_operators_name
|
175
171
|
|
176
172
|
### process sometime modalities ###
|
@@ -304,7 +300,7 @@ module Sfp
|
|
304
300
|
postprocess_simple_global_constraint_to_operator(operator).each { |op|
|
305
301
|
@operators[op.name] = op
|
306
302
|
}
|
307
|
-
end
|
303
|
+
end if @operators.is_a?(Hash)
|
308
304
|
end
|
309
305
|
|
310
306
|
def postprocess_simple_global_constraint_to_operator(operator)
|
@@ -701,12 +697,10 @@ module Sfp
|
|
701
697
|
return map
|
702
698
|
end
|
703
699
|
|
704
|
-
def and_equals_constraint_to_map(
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
map[k] = v['_value'] if v['_type'] == 'equals'
|
709
|
-
}
|
700
|
+
def and_equals_constraint_to_map(c)
|
701
|
+
return { c['_self'] => c['_value'] } if c['_type'] == 'equals'
|
702
|
+
map = {}
|
703
|
+
c.each { |k,v| map[k] = v['_value'] if k[0,1] != '_' and v['_type'] == 'equals' }
|
710
704
|
return map
|
711
705
|
end
|
712
706
|
|
@@ -790,18 +784,7 @@ module Sfp
|
|
790
784
|
|
791
785
|
operators = ground_procedure_parameters(procedure)
|
792
786
|
if operators != nil
|
793
|
-
|
794
|
-
operators.each do |op|
|
795
|
-
#begin
|
796
|
-
process_operator(op)
|
797
|
-
#rescue UndefinedValueException
|
798
|
-
# invalid_operators << op
|
799
|
-
# puts "TODO -- invalid operator: " + op['_self'].to_s
|
800
|
-
#end
|
801
|
-
end
|
802
|
-
#operators.delete_if { |op| not invalid_operators.index(op).nil? }
|
803
|
-
else
|
804
|
-
#puts 'proc: ' + procedure.ref + ' cannot be grounded'
|
787
|
+
operators.each { |op| process_operator(op) }
|
805
788
|
end
|
806
789
|
# remove the procedure because we don't need it anymore
|
807
790
|
object.delete(procedure['_self'])
|
@@ -819,7 +802,14 @@ module Sfp
|
|
819
802
|
return nil
|
820
803
|
end
|
821
804
|
params[k] = Array.new
|
822
|
-
type =
|
805
|
+
type = case v['_context']
|
806
|
+
when 'null', 'any_value'
|
807
|
+
v['_isa']
|
808
|
+
when 'set'
|
809
|
+
"(#{v['_isa']})"
|
810
|
+
else
|
811
|
+
nil
|
812
|
+
end
|
823
813
|
next if type == nil
|
824
814
|
raise TypeNotFoundException, type if not @types.has_key?(type)
|
825
815
|
@types[ type ].each { |val| params[k] << val if not (val.is_a?(Hash) and val.isnull) }
|
@@ -1664,9 +1654,12 @@ module Sfp
|
|
1664
1654
|
|
1665
1655
|
def visit(name, value, obj)
|
1666
1656
|
return if name[0,1] == '_' and name != '_value' and name != '_template'
|
1657
|
+
# substituting left side
|
1667
1658
|
if name[0,1] != '_'
|
1668
1659
|
modified = false
|
1669
1660
|
map.each { |k,v|
|
1661
|
+
#puts k + ',' + name if v.is_a?(Sfp::Undefined) or v.is_a?(Sfp::Unknown)
|
1662
|
+
next if v.is_a?(Sfp::Undefined) or v.is_a?(Sfp::Unknown)
|
1670
1663
|
if name == k
|
1671
1664
|
obj[v] = value
|
1672
1665
|
obj.delete(name)
|
@@ -1675,6 +1668,7 @@ module Sfp
|
|
1675
1668
|
modified = true
|
1676
1669
|
break
|
1677
1670
|
elsif name.length > k.length and name[k.length,1] == '.' and name[0, k.length] == k
|
1671
|
+
#next if v.is_a?(Sfp::Undefined) or v.is_a?(Sfp::Unknown)
|
1678
1672
|
grounded = v + name[k.length, (name.length-k.length)]
|
1679
1673
|
obj[grounded] = value
|
1680
1674
|
obj.delete(name)
|
@@ -1705,12 +1699,15 @@ module Sfp
|
|
1705
1699
|
#puts "==>> " + obj.ref.push(name)
|
1706
1700
|
end
|
1707
1701
|
# ------ END of HACK! ----
|
1702
|
+
|
1703
|
+
# substituting right side
|
1708
1704
|
if value.is_a?(String) and value.isref
|
1709
1705
|
map.each { |k,v|
|
1710
1706
|
if value == k
|
1711
1707
|
obj[name] = v
|
1712
1708
|
break
|
1713
|
-
elsif value.length > k.length and value[k.length,1] == '.' and value[0,k.length] == k
|
1709
|
+
elsif value.length > k.length and value[k.length,1] == '.' and value[0,k.length] == k and
|
1710
|
+
not(v.is_a?(Sfp::Undefined) or v.is_a?(Sfp::Unknown))
|
1714
1711
|
obj[name] = v + value[k.length, (value.length-k.length)]
|
1715
1712
|
break
|
1716
1713
|
end
|
data/sfp.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'sfp'
|
3
|
-
s.version = '0.3.
|
4
|
-
s.date = '2013-
|
3
|
+
s.version = '0.3.6'
|
4
|
+
s.date = '2013-08-05'
|
5
5
|
s.summary = 'SFP Parser'
|
6
6
|
s.description = 'A Ruby API and script for SFP language parser'
|
7
7
|
s.authors = ['Herry']
|
@@ -17,5 +17,5 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.rubyforge_project = 'sfp'
|
18
18
|
|
19
19
|
s.add_dependency 'json', '~> 1.7.5'
|
20
|
-
s.add_dependency 'antlr3', '~> 1.
|
20
|
+
s.add_dependency 'antlr3', '~> 1.9.0'
|
21
21
|
end
|
data/src/SfpLang.g
CHANGED
@@ -38,11 +38,17 @@ TODO:
|
|
38
38
|
|
39
39
|
sfp
|
40
40
|
: { self.init }
|
41
|
-
NL*
|
42
|
-
{ self.expand_classes }
|
43
|
-
(object_def NL* |
|
41
|
+
NL*
|
42
|
+
//{ self.expand_classes }
|
43
|
+
( (object_def | state | constraints) NL* | include | class_def | procedure )*
|
44
|
+
// | goal_constraint | composite)*
|
44
45
|
;
|
45
46
|
|
47
|
+
constraints
|
48
|
+
: goal_constraint
|
49
|
+
| global_constraint
|
50
|
+
| sometime_constraint
|
51
|
+
;
|
46
52
|
|
47
53
|
/*mmutation
|
48
54
|
: reference equals_op value NL+
|
@@ -72,12 +78,12 @@ include_file
|
|
72
78
|
;
|
73
79
|
|
74
80
|
header
|
75
|
-
:
|
81
|
+
: class_def
|
76
82
|
| procedure
|
77
83
|
;
|
78
84
|
|
79
85
|
state
|
80
|
-
: ID 'state'
|
86
|
+
: ID 'state' NL*
|
81
87
|
{
|
82
88
|
@now[$ID.text] = { '_self' => $ID.text,
|
83
89
|
'_context' => 'state',
|
@@ -87,7 +93,7 @@ state
|
|
87
93
|
}
|
88
94
|
'{' NL*
|
89
95
|
attribute*
|
90
|
-
'}'
|
96
|
+
'}'
|
91
97
|
{ self.goto_parent(true) }
|
92
98
|
;
|
93
99
|
|
@@ -104,7 +110,7 @@ composite
|
|
104
110
|
{ self.goto_parent(true) }
|
105
111
|
;
|
106
112
|
|
107
|
-
|
113
|
+
class_def
|
108
114
|
: ('class'|'schema') ID
|
109
115
|
{
|
110
116
|
@now[$ID.text] = { '_self' => $ID.text,
|
@@ -124,6 +130,7 @@ class_definition
|
|
124
130
|
@now['_extends'] = '$.Object'
|
125
131
|
@now['_super'] = ['$.Object']
|
126
132
|
end
|
133
|
+
expand_class(@now)
|
127
134
|
self.goto_parent()
|
128
135
|
}
|
129
136
|
;
|
@@ -263,7 +270,7 @@ object_def
|
|
263
270
|
;
|
264
271
|
|
265
272
|
object_body
|
266
|
-
: '{' NL* ( object_attribute |
|
273
|
+
: '{' NL* ( object_attribute | procedure )* '}'
|
267
274
|
;
|
268
275
|
|
269
276
|
object_attribute
|
@@ -290,27 +297,6 @@ dep_effect
|
|
290
297
|
)
|
291
298
|
;
|
292
299
|
|
293
|
-
operator
|
294
|
-
: 'operator' ID '{' NL*
|
295
|
-
{
|
296
|
-
@now[$ID.text] = { '_self' => $ID.text,
|
297
|
-
'_context' => 'operator',
|
298
|
-
'_parent' => @now,
|
299
|
-
'_cost' => 1,
|
300
|
-
'_condition' => { '_context' => 'constraint' },
|
301
|
-
'_effect' => { '_context' => 'effect' }
|
302
|
-
}
|
303
|
-
@now = @now[$ID.text]
|
304
|
-
}
|
305
|
-
( 'cost' equals_op NUMBER NL+
|
306
|
-
{ @now['_cost'] = $NUMBER.text.to_i }
|
307
|
-
)?
|
308
|
-
/*op_param**/
|
309
|
-
op_conditions? op_effects
|
310
|
-
'}' NL+
|
311
|
-
{ self.goto_parent() }
|
312
|
-
;
|
313
|
-
|
314
300
|
op_param
|
315
301
|
: ID equals_op reference NL+
|
316
302
|
{ @now[$ID.text] = $reference.val }
|
@@ -369,7 +355,13 @@ parameters
|
|
369
355
|
;
|
370
356
|
|
371
357
|
parameter
|
372
|
-
: ID
|
358
|
+
: ID ':' path
|
359
|
+
{
|
360
|
+
@now[$ID.text] = { '_context' => 'any_value',
|
361
|
+
'_isa' => self.to_ref($path.text)
|
362
|
+
}
|
363
|
+
}
|
364
|
+
| ID reference_type
|
373
365
|
{ @now[$ID.text] = $reference_type.val }
|
374
366
|
| ID 'areall' path
|
375
367
|
{
|
@@ -424,10 +416,31 @@ goal_constraint
|
|
424
416
|
}
|
425
417
|
@now = @now['goal']
|
426
418
|
}
|
427
|
-
'{' NL* goal_body* '}'
|
419
|
+
'{' NL* goal_body* '}'
|
420
|
+
{ self.goto_parent() }
|
421
|
+
;
|
422
|
+
|
423
|
+
global_constraint
|
424
|
+
: ('global'|'always') 'constraint'? NL*
|
425
|
+
{
|
426
|
+
@now['global'] = self.create_constraint('global', 'and') if !@now.has_key?('global')
|
427
|
+
@now = @now['global']
|
428
|
+
}
|
429
|
+
'{' NL* constraint_body '}'
|
428
430
|
{ self.goto_parent() }
|
429
431
|
;
|
430
432
|
|
433
|
+
sometime_constraint
|
434
|
+
: 'sometime' 'constraint'? NL*
|
435
|
+
{
|
436
|
+
@now['sometime'] = self.create_constraint('sometime', 'or') if !@now.has_key?('sometime')
|
437
|
+
@now = @now['sometime']
|
438
|
+
}
|
439
|
+
'{' NL* constraint_body '}'
|
440
|
+
{ self.goto_parent() }
|
441
|
+
;
|
442
|
+
|
443
|
+
|
431
444
|
goal_body
|
432
445
|
: (
|
433
446
|
( constraint_statement
|
@@ -439,11 +452,11 @@ goal_body
|
|
439
452
|
| constraint_class_quantification
|
440
453
|
)
|
441
454
|
NL+)
|
442
|
-
| 'always' NL*
|
455
|
+
| ('always'|'global') NL*
|
443
456
|
{
|
444
|
-
@now['
|
445
|
-
not @now.has_key?('
|
446
|
-
@now = @now['
|
457
|
+
@now['global'] = self.create_constraint('global', 'and') if
|
458
|
+
not @now.has_key?('global')
|
459
|
+
@now = @now['global']
|
447
460
|
}
|
448
461
|
'{' NL* constraint_body '}' NL+
|
449
462
|
{ self.goto_parent() }
|
@@ -520,12 +533,12 @@ nested_constraint
|
|
520
533
|
;
|
521
534
|
|
522
535
|
constraint
|
523
|
-
:
|
536
|
+
: 'constraint' ID
|
524
537
|
{
|
525
538
|
@now[$ID.text] = self.create_constraint($ID.text, 'and')
|
526
539
|
@now = @now[$ID.text]
|
527
540
|
}
|
528
|
-
'{' NL* constraint_body '}'
|
541
|
+
'{' NL* constraint_body '}'
|
529
542
|
{ self.goto_parent() }
|
530
543
|
;
|
531
544
|
|
@@ -1015,7 +1028,7 @@ BOOLEAN
|
|
1015
1028
|
| 'no'
|
1016
1029
|
;
|
1017
1030
|
|
1018
|
-
ID : ('a'..'z'|'A'..'Z')
|
1031
|
+
ID : ('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
|
1019
1032
|
;
|
1020
1033
|
|
1021
1034
|
NUMBER
|
@@ -1039,7 +1052,7 @@ MULTILINE_STRING
|
|
1039
1052
|
: 'r"' ( options {greedy=false;} : .)* '"'
|
1040
1053
|
;
|
1041
1054
|
|
1042
|
-
NL : '\r'? '\n'
|
1055
|
+
NL : ('\r'? '\n'|';')
|
1043
1056
|
;
|
1044
1057
|
|
1045
1058
|
WS : ( ' ' | '\t' ) {$channel=HIDDEN;}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sfp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,18 +21,28 @@ dependencies:
|
|
21
21
|
version: 1.7.5
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.7.5
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: antlr3
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ~>
|
31
36
|
- !ruby/object:Gem::Version
|
32
|
-
version: 1.
|
37
|
+
version: 1.9.0
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.9.0
|
36
46
|
description: A Ruby API and script for SFP language parser
|
37
47
|
email: herry13@gmail.com
|
38
48
|
executables:
|
@@ -79,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
79
89
|
version: '0'
|
80
90
|
requirements: []
|
81
91
|
rubyforge_project: sfp
|
82
|
-
rubygems_version: 1.8.
|
92
|
+
rubygems_version: 1.8.23
|
83
93
|
signing_key:
|
84
94
|
specification_version: 3
|
85
95
|
summary: SFP Parser
|