modl 0.3.26 → 0.3.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -149
- data/Gemfile +4 -2
- data/LICENSE.txt +1 -1
- data/README.md +19 -11
- data/Rakefile +5 -3
- data/lib/modl/interpreter.rb +38 -0
- data/lib/modl/model/model.rb +264 -0
- data/lib/modl/parser/parser.rb +272 -59
- data/lib/modl/tokeniser/context.rb +113 -0
- data/lib/modl/tokeniser/tokeniser.rb +28 -0
- data/lib/modl/util/functions.rb +74 -0
- data/lib/modl/util/unicode.rb +44 -0
- data/lib/modl/version.rb +5 -0
- data/lib/modl.rb +7 -32
- data/modl.gemspec +8 -11
- metadata +16 -75
- data/.DS_Store +0 -0
- data/.idea/vcs.xml +0 -6
- data/.rspec +0 -3
- data/.rubocop.yml +0 -5
- data/.travis.yml +0 -7
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/lib/modl/parser/MODLLexer.interp +0 -132
- data/lib/modl/parser/MODLLexer.rb +0 -324
- data/lib/modl/parser/MODLLexer.tokens +0 -40
- data/lib/modl/parser/MODLParser.interp +0 -93
- data/lib/modl/parser/MODLParser.rb +0 -2492
- data/lib/modl/parser/MODLParser.tokens +0 -40
- data/lib/modl/parser/MODLParserBaseListener.rb +0 -164
- data/lib/modl/parser/MODLParserBaseVisitor.rb +0 -107
- data/lib/modl/parser/MODLParserListener.rb +0 -151
- data/lib/modl/parser/MODLParserVisitor.rb +0 -56
- data/lib/modl/parser/class_processor.rb +0 -411
- data/lib/modl/parser/evaluator.rb +0 -125
- data/lib/modl/parser/file_importer.rb +0 -101
- data/lib/modl/parser/global_parse_context.rb +0 -318
- data/lib/modl/parser/instruction_processor.rb +0 -82
- data/lib/modl/parser/interpreter.rb +0 -75
- data/lib/modl/parser/modl_class.rb +0 -138
- data/lib/modl/parser/modl_index.rb +0 -54
- data/lib/modl/parser/modl_keylist.rb +0 -81
- data/lib/modl/parser/modl_method.rb +0 -172
- data/lib/modl/parser/object_cache.rb +0 -88
- data/lib/modl/parser/orphan_handler.rb +0 -98
- data/lib/modl/parser/parsed.rb +0 -1469
- data/lib/modl/parser/ref_processor.rb +0 -258
- data/lib/modl/parser/substitutions.rb +0 -101
- data/lib/modl/parser/sutil.rb +0 -108
- data/lib/modl/parser/throwing_error_listener.rb +0 -44
- data/lib/modl/parser/unicode_escape_replacer.rb +0 -148
- data/lib/modl/parser/unicode_escapes.rb +0 -112
- data/lib/modl/parser/version.rb +0 -29
@@ -1,318 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# The MIT License (MIT)
|
4
|
-
#
|
5
|
-
# Copyright (c) 2019 NUM Technology Ltd
|
6
|
-
#
|
7
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
-
# of this software and associated documentation files (the "Software"), to deal
|
9
|
-
# in the Software without restriction, including without limitation the rights
|
10
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
-
# copies of the Software, and to permit persons to whom the Software is
|
12
|
-
# furnished to do so, subject to the following conditions:
|
13
|
-
#
|
14
|
-
# The above copyright notice and this permission notice shall be included in
|
15
|
-
# all copies or substantial portions of the Software.
|
16
|
-
#
|
17
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
-
# THE SOFTWARE.
|
24
|
-
|
25
|
-
module MODL
|
26
|
-
module Parser
|
27
|
-
# Each time we run the parser on a MODL file we need to keep track of a few things so they can be made available
|
28
|
-
# to other areas of the code. This class is the container for that contextual information, which is gathered
|
29
|
-
# as the MODL::Parser:Parsed object processes the parse tree.
|
30
|
-
class GlobalParseContext
|
31
|
-
|
32
|
-
attr_accessor :syntax_version
|
33
|
-
attr_accessor :max_files_allowed
|
34
|
-
attr_accessor :structures
|
35
|
-
attr_reader :interpreter_syntax_version
|
36
|
-
attr_reader :loaded_files
|
37
|
-
|
38
|
-
def initialize
|
39
|
-
# This keeps track of all loaded structures from parsed files.
|
40
|
-
@structures = []
|
41
|
-
# This is set to true if we encounter a *L[OAD] instruction
|
42
|
-
@max_files_allowed = 2147483647
|
43
|
-
# Holds the index array from a MODL file, e.g. '?=a:b:c:d'
|
44
|
-
@index = []
|
45
|
-
# Contains all pairs as they are encountered in the parsing process.
|
46
|
-
@pairs = {}
|
47
|
-
# Contains all defined and loaded classes for the current MODL document.
|
48
|
-
@classes_by_id = {}
|
49
|
-
@classes_by_name = {}
|
50
|
-
# Hold the user-defined methods.
|
51
|
-
@methods_hash = {}
|
52
|
-
@methods_by_id = {}
|
53
|
-
# Tracks the nesting depth for conditional clauses.
|
54
|
-
@conditional = 0
|
55
|
-
# Defaults to 1 and can be overridden by the *version command.
|
56
|
-
@syntax_version = 1
|
57
|
-
@interpreter_syntax_version = 1
|
58
|
-
@loaded_files = []
|
59
|
-
# Arrays
|
60
|
-
@arrays_by_id = {}
|
61
|
-
@arrays_by_name = {}
|
62
|
-
end
|
63
|
-
|
64
|
-
def loaded_file(str)
|
65
|
-
@loaded_files << str unless str.nil?
|
66
|
-
raise InterpreterError, 'Cannot load multiple files after *LOAD instruction' if @loaded_files.length > @max_files_allowed
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
def index_value(n, default)
|
71
|
-
return default if n > @index.length
|
72
|
-
|
73
|
-
@index[n]
|
74
|
-
end
|
75
|
-
|
76
|
-
def in_condition?
|
77
|
-
@conditional.positive?
|
78
|
-
end
|
79
|
-
|
80
|
-
def freeze_max_files(plus)
|
81
|
-
@max_files_allowed = @loaded_files.length + plus
|
82
|
-
end
|
83
|
-
|
84
|
-
def enter_condition
|
85
|
-
@conditional += 1
|
86
|
-
end
|
87
|
-
|
88
|
-
def exit_condition
|
89
|
-
@conditional -= 1
|
90
|
-
end
|
91
|
-
|
92
|
-
def pair(key, val = nil)
|
93
|
-
return @pairs[key] unless val
|
94
|
-
|
95
|
-
@pairs[key] = val
|
96
|
-
end
|
97
|
-
|
98
|
-
def classs(key)
|
99
|
-
if key.is_a? String
|
100
|
-
result = @classes_by_id[key]
|
101
|
-
result = @classes_by_name[key] if result.nil?
|
102
|
-
result
|
103
|
-
elsif key.is_a? MODLClass
|
104
|
-
@classes_by_id[key.id] = key if key.id
|
105
|
-
@classes_by_name[key.name] = key if key.name
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def arrays(key)
|
110
|
-
if key.is_a? String
|
111
|
-
result = @arrays_by_id[key]
|
112
|
-
result = @arrays_by_name[key] if result.nil?
|
113
|
-
result
|
114
|
-
elsif key.is_a? MODLArray
|
115
|
-
@arrays_by_id[key.id] = key if key.id
|
116
|
-
@arrays_by_name[key.name] = key if key.name
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def merge_pairs(other)
|
121
|
-
@pairs.merge!(other.all_pairs)
|
122
|
-
end
|
123
|
-
|
124
|
-
def merge_classes(other)
|
125
|
-
@classes_by_id.merge!(other.all_classes_by_id)
|
126
|
-
@classes_by_name.merge!(other.all_classes_by_name)
|
127
|
-
end
|
128
|
-
|
129
|
-
def merge_loaded_files(other)
|
130
|
-
@loaded_files.concat(other.loaded_files)
|
131
|
-
raise InterpreterError, 'Cannot load multiple files after *LOAD instruction' if @loaded_files.length > @max_files_allowed
|
132
|
-
end
|
133
|
-
|
134
|
-
def has_pairs?
|
135
|
-
@pairs.length.positive?
|
136
|
-
end
|
137
|
-
|
138
|
-
def has_class?(key)
|
139
|
-
@classes_by_id.keys.include?(key) || @classes_by_name.keys.include?(key)
|
140
|
-
end
|
141
|
-
|
142
|
-
def has_array?(key)
|
143
|
-
@arrays_by_id.keys.include?(key) || @arrays_by_name.keys.include?(key)
|
144
|
-
end
|
145
|
-
|
146
|
-
def has_user_method?(key)
|
147
|
-
@methods_hash.keys.include?(key)
|
148
|
-
end
|
149
|
-
|
150
|
-
def add_to_index(item)
|
151
|
-
@index << item
|
152
|
-
end
|
153
|
-
|
154
|
-
def user_method(key, val = nil)
|
155
|
-
return @methods_hash[key] unless val
|
156
|
-
|
157
|
-
@methods_hash[key] = val
|
158
|
-
end
|
159
|
-
|
160
|
-
def user_method_id(key, val)
|
161
|
-
@methods_hash[key] = val
|
162
|
-
@methods_by_id[key] = val
|
163
|
-
end
|
164
|
-
|
165
|
-
def class_list
|
166
|
-
result = []
|
167
|
-
@classes_by_id.values.each do |clazz|
|
168
|
-
new_item = {}
|
169
|
-
new_item[clazz.id] = class_to_hash(clazz)
|
170
|
-
result << new_item
|
171
|
-
end
|
172
|
-
result
|
173
|
-
end
|
174
|
-
|
175
|
-
def method_list
|
176
|
-
result = []
|
177
|
-
@methods_by_id.values.each do |m|
|
178
|
-
new_item = {}
|
179
|
-
new_item[m.id] = method_to_hash(m)
|
180
|
-
result << new_item
|
181
|
-
end
|
182
|
-
result
|
183
|
-
end
|
184
|
-
|
185
|
-
def file_list
|
186
|
-
@loaded_files.dup
|
187
|
-
end
|
188
|
-
|
189
|
-
def id_list
|
190
|
-
ids = {}
|
191
|
-
ids['methods'] = @methods_by_id.keys.dup.sort!
|
192
|
-
ids['classes'] = @classes_by_id.keys.dup.sort!
|
193
|
-
ids
|
194
|
-
end
|
195
|
-
|
196
|
-
def name_list
|
197
|
-
names = {}
|
198
|
-
names['methods'] = @methods_hash.keys.dup.sort!
|
199
|
-
names['classes'] = @classes_by_name.keys.dup.sort!
|
200
|
-
names
|
201
|
-
end
|
202
|
-
|
203
|
-
def superclass_list
|
204
|
-
result = {}
|
205
|
-
@classes_by_id.each do |c|
|
206
|
-
result[c[0]] = c[1].superclass
|
207
|
-
end
|
208
|
-
result
|
209
|
-
end
|
210
|
-
|
211
|
-
def assign_list
|
212
|
-
result = {}
|
213
|
-
@classes_by_id.each do |c|
|
214
|
-
result[c[0]] = c[1].assign
|
215
|
-
end
|
216
|
-
result
|
217
|
-
end
|
218
|
-
|
219
|
-
def transform_list
|
220
|
-
result = {}
|
221
|
-
@methods_by_id.each do |c|
|
222
|
-
result[c[0]] = c[1].transform
|
223
|
-
end
|
224
|
-
result
|
225
|
-
end
|
226
|
-
|
227
|
-
def allow_list
|
228
|
-
result = {}
|
229
|
-
@classes_by_id.each do |c|
|
230
|
-
result[c[0]] = c[1].allow.nil? ? nil : c[1].allow.extract_hash
|
231
|
-
end
|
232
|
-
result
|
233
|
-
end
|
234
|
-
|
235
|
-
protected
|
236
|
-
|
237
|
-
def all_classes_by_id
|
238
|
-
@classes_by_id
|
239
|
-
end
|
240
|
-
|
241
|
-
def all_classes_by_name
|
242
|
-
@classes_by_name
|
243
|
-
end
|
244
|
-
|
245
|
-
def all_pairs
|
246
|
-
result = {}
|
247
|
-
@pairs.keys.each do |k|
|
248
|
-
result[k] = @pairs[k] unless k.start_with?('*')
|
249
|
-
end
|
250
|
-
result
|
251
|
-
end
|
252
|
-
|
253
|
-
private
|
254
|
-
|
255
|
-
def class_to_hash(clazz)
|
256
|
-
map = {}
|
257
|
-
# name
|
258
|
-
map['name'] = clazz.name
|
259
|
-
|
260
|
-
# superclass
|
261
|
-
map['superclass'] = clazz.superclass
|
262
|
-
|
263
|
-
# assign
|
264
|
-
if clazz.assign
|
265
|
-
map['assign'] = clazz.assign
|
266
|
-
end
|
267
|
-
|
268
|
-
# allow
|
269
|
-
if clazz.allow
|
270
|
-
map['allow'] = clazz.allow.extract_hash
|
271
|
-
end
|
272
|
-
|
273
|
-
# expect
|
274
|
-
if clazz.expect
|
275
|
-
map['expect'] = clazz.expect.extract_hash
|
276
|
-
end
|
277
|
-
|
278
|
-
# content
|
279
|
-
if clazz.content.length.positive?
|
280
|
-
clazz.content.each do |item|
|
281
|
-
map[item[0]] = item[1].extract_hash
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
map
|
286
|
-
end
|
287
|
-
|
288
|
-
def method_to_hash(mthd)
|
289
|
-
map = {}
|
290
|
-
# name
|
291
|
-
map['name'] = mthd.name
|
292
|
-
|
293
|
-
# superclass
|
294
|
-
map['transform'] = mthd.transform
|
295
|
-
|
296
|
-
map
|
297
|
-
end
|
298
|
-
|
299
|
-
def new_map_item(key, value)
|
300
|
-
map_item = Parsed::ParsedMapItem.new(self)
|
301
|
-
map_item.pair = Parsed::ParsedPair.new(self)
|
302
|
-
map_item.pair.key = key
|
303
|
-
map_item.pair.valueItem = Parsed::ParsedValueItem.new(self)
|
304
|
-
if value.is_a? Parsed::ParsedValue
|
305
|
-
map_item.pair.valueItem.value = value
|
306
|
-
else
|
307
|
-
map_item.pair.valueItem.value = Parsed::ParsedValue.new(self)
|
308
|
-
map_item.pair.valueItem.value.primitive = Parsed::ParsedPrimitive.new(self)
|
309
|
-
map_item.pair.valueItem.value.primitive = Parsed::ParsedPrimitive.new(self)
|
310
|
-
map_item.pair.valueItem.value.primitive.string = Parsed::ParsedString.new(value)
|
311
|
-
map_item.pair.valueItem.value.primitive.text = value
|
312
|
-
map_item.pair.valueItem.value.text = value
|
313
|
-
end
|
314
|
-
map_item
|
315
|
-
end
|
316
|
-
end
|
317
|
-
end
|
318
|
-
end
|
@@ -1,82 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# The MIT License (MIT)
|
4
|
-
#
|
5
|
-
# Copyright (c) 2019 NUM Technology Ltd
|
6
|
-
#
|
7
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
-
# of this software and associated documentation files (the "Software"), to deal
|
9
|
-
# in the Software without restriction, including without limitation the rights
|
10
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
-
# copies of the Software, and to permit persons to whom the Software is
|
12
|
-
# furnished to do so, subject to the following conditions:
|
13
|
-
#
|
14
|
-
# The above copyright notice and this permission notice shall be included in
|
15
|
-
# all copies or substantial portions of the Software.
|
16
|
-
#
|
17
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
-
# THE SOFTWARE.
|
24
|
-
|
25
|
-
module MODL
|
26
|
-
module Parser
|
27
|
-
# This class handles the conversion of objects that refer to classes into instances of those classes.
|
28
|
-
# It works recursively since class usage can be nested.
|
29
|
-
class InstructionProcessor
|
30
|
-
def self.process(global, obj)
|
31
|
-
if obj.is_a? Hash
|
32
|
-
nvals = {}
|
33
|
-
obj.keys.each do |k|
|
34
|
-
o = obj[k]
|
35
|
-
if o.is_a? String
|
36
|
-
nv = process_instruction(global, o)
|
37
|
-
nvals[k] = nv unless nv.nil?
|
38
|
-
else
|
39
|
-
process(global, o)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
obj.merge!(nvals)
|
43
|
-
elsif obj.is_a? Array
|
44
|
-
i = 0
|
45
|
-
while i < obj.length
|
46
|
-
o = obj[i]
|
47
|
-
if o.is_a? String
|
48
|
-
nv = process_instruction(global, o)
|
49
|
-
obj[i] = nv unless nv.nil?
|
50
|
-
else
|
51
|
-
process(global, o)
|
52
|
-
end
|
53
|
-
i += 1
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.process_instruction(global, str)
|
59
|
-
case str
|
60
|
-
when '%*class'
|
61
|
-
return global.class_list
|
62
|
-
when '%*method'
|
63
|
-
return global.method_list
|
64
|
-
when '%*load'
|
65
|
-
return global.file_list
|
66
|
-
when '%*id'
|
67
|
-
return global.id_list
|
68
|
-
when '%*name'
|
69
|
-
return global.name_list
|
70
|
-
when '%*superclass'
|
71
|
-
return global.superclass_list
|
72
|
-
when '%*assign'
|
73
|
-
return global.assign_list
|
74
|
-
when '%*transform'
|
75
|
-
return global.transform_list
|
76
|
-
when '%*allow'
|
77
|
-
return global.allow_list
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# The MIT License (MIT)
|
4
|
-
#
|
5
|
-
# Copyright (c) 2019 NUM Technology Ltd
|
6
|
-
#
|
7
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
-
# of this software and associated documentation files (the "Software"), to deal
|
9
|
-
# in the Software without restriction, including without limitation the rights
|
10
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
-
# copies of the Software, and to permit persons to whom the Software is
|
12
|
-
# furnished to do so, subject to the following conditions:
|
13
|
-
#
|
14
|
-
# The above copyright notice and this permission notice shall be included in
|
15
|
-
# all copies or substantial portions of the Software.
|
16
|
-
#
|
17
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
-
# THE SOFTWARE.
|
24
|
-
|
25
|
-
require 'modl/parser/MODLParserListener'
|
26
|
-
require 'modl/parser/MODLParserVisitor'
|
27
|
-
require 'modl/parser/MODLLexer'
|
28
|
-
require 'modl/parser/MODLParser'
|
29
|
-
require 'modl/parser/class_processor'
|
30
|
-
require 'modl/parser/orphan_handler'
|
31
|
-
require 'modl/parser/parser'
|
32
|
-
require 'json'
|
33
|
-
|
34
|
-
module MODL
|
35
|
-
# Interpreter-specific errors
|
36
|
-
class InterpreterError < StandardError
|
37
|
-
end
|
38
|
-
|
39
|
-
class ParserError < StandardError
|
40
|
-
end
|
41
|
-
|
42
|
-
# This is the main Ruby Interpreter entry point. Supply a String containing MODL text and it will return a String
|
43
|
-
# containing the JSON equivalent. The JSON isn't pretty-printed unless pretty is true
|
44
|
-
class Interpreter
|
45
|
-
def self.interpret(str, pretty = false)
|
46
|
-
interpreted = MODL.parse(str)
|
47
|
-
return interpreted if interpreted.is_a? String
|
48
|
-
|
49
|
-
# Otherwise generate a JSON string.
|
50
|
-
if pretty
|
51
|
-
JSON.pretty_generate interpreted
|
52
|
-
else
|
53
|
-
JSON.generate interpreted
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Parse a MODL string and return a hash, array, or String depending on how the MODL is structured.
|
59
|
-
def self.parse(string)
|
60
|
-
# Parse the MODL string into a MODL::Parser::Parsed object.
|
61
|
-
parsed = MODL::Parser::Parser.parse(string)
|
62
|
-
|
63
|
-
# Check for orphan pairs and adopt them.
|
64
|
-
parsed.structures = MODL::Parser::OrphanHandler.adopt(parsed.global, parsed.structures)
|
65
|
-
|
66
|
-
# Convert the Parsed object into a simpler structure of and Array or Hash
|
67
|
-
interpreted = parsed.extract_hash
|
68
|
-
|
69
|
-
# Process any class definitions used by the MODL file.
|
70
|
-
interpreted = MODL::Parser::ClassProcessor.process(parsed.global, interpreted)
|
71
|
-
MODL::Parser::InstructionProcessor.process(parsed.global, interpreted)
|
72
|
-
# If the result is a simple string then just return it.
|
73
|
-
interpreted
|
74
|
-
end
|
75
|
-
end
|
@@ -1,138 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# The MIT License (MIT)
|
4
|
-
#
|
5
|
-
# Copyright (c) 2019 NUM Technology Ltd
|
6
|
-
#
|
7
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
-
# of this software and associated documentation files (the "Software"), to deal
|
9
|
-
# in the Software without restriction, including without limitation the rights
|
10
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
-
# copies of the Software, and to permit persons to whom the Software is
|
12
|
-
# furnished to do so, subject to the following conditions:
|
13
|
-
#
|
14
|
-
# The above copyright notice and this permission notice shall be included in
|
15
|
-
# all copies or substantial portions of the Software.
|
16
|
-
#
|
17
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
-
# THE SOFTWARE.
|
24
|
-
|
25
|
-
module MODL
|
26
|
-
module Parser
|
27
|
-
# Represents a *class defined, or loaded by, a MODL document.
|
28
|
-
class MODLClass
|
29
|
-
attr_accessor :id
|
30
|
-
attr_accessor :name
|
31
|
-
attr_accessor :superclass
|
32
|
-
attr_accessor :assign
|
33
|
-
attr_accessor :content
|
34
|
-
attr_accessor :allow
|
35
|
-
attr_accessor :expect
|
36
|
-
|
37
|
-
def initialize
|
38
|
-
@content = {}
|
39
|
-
end
|
40
|
-
|
41
|
-
# Find a keylist of the right length from the *assign array of arrays.
|
42
|
-
def keylist_of_length(len)
|
43
|
-
return nil if @assign.nil?
|
44
|
-
|
45
|
-
# *assign can support iteration, e.g. *assign=[[person*]]
|
46
|
-
# so return a list of the right length in this case
|
47
|
-
if @assign.length == 1 && @assign[0].length == 1 && @assign[0][0].end_with?('*')
|
48
|
-
key = Sutil.head @assign[0][0]
|
49
|
-
return Array.new(len, key)
|
50
|
-
end
|
51
|
-
|
52
|
-
@assign.each do |kl|
|
53
|
-
return kl if kl.length == len
|
54
|
-
end
|
55
|
-
|
56
|
-
raise InterpreterError,
|
57
|
-
'Interpreter Error: No key list of the correct length in class ' + @id + ' - looking for one of length ' + len.to_s
|
58
|
-
end
|
59
|
-
|
60
|
-
def merge_content(new_value)
|
61
|
-
@content.each do |k, v|
|
62
|
-
new_value[k] = v.extract_hash unless new_value[k]
|
63
|
-
end
|
64
|
-
new_value
|
65
|
-
end
|
66
|
-
|
67
|
-
def name_or_id
|
68
|
-
@name.nil? ? @id : @name
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# Extract a class from a ParsedPair object
|
73
|
-
class ClassExtractor
|
74
|
-
def self.extract(pair, global)
|
75
|
-
return unless pair.type == 'class'
|
76
|
-
|
77
|
-
clazz = MODLClass.new
|
78
|
-
map = pair.map if pair.map
|
79
|
-
map = pair.valueItem&.value&.map if pair.valueItem&.value&.map
|
80
|
-
|
81
|
-
map.mapItems.each do |item|
|
82
|
-
next unless item&.pair&.type
|
83
|
-
|
84
|
-
case item&.pair&.type
|
85
|
-
when 'id'
|
86
|
-
str_value = item.pair.valueItem.value.primitive.string.string
|
87
|
-
raise InterpreterError, 'Reserved class id - cannot redefine: ' + str_value if reserved?(str_value)
|
88
|
-
|
89
|
-
clazz.id = str_value
|
90
|
-
when 'name'
|
91
|
-
str_value = item.pair.valueItem.value.primitive.string.string
|
92
|
-
raise InterpreterError, 'Reserved class name - cannot redefine: ' + str_value if reserved?(str_value)
|
93
|
-
|
94
|
-
clazz.name = str_value
|
95
|
-
when 'superclass'
|
96
|
-
str_value = item.pair.valueItem.value.primitive.string.string
|
97
|
-
clazz.superclass = str_value
|
98
|
-
when 'keylist'
|
99
|
-
clazz.assign = item.pair.key_lists
|
100
|
-
when 'allow'
|
101
|
-
clazz.allow = item.pair.array if item.pair.array
|
102
|
-
clazz.allow = item.pair.valueItem.value.array if item.pair.valueItem.value.array
|
103
|
-
when 'expect'
|
104
|
-
clazz.expect = item.pair.array if item.pair.array
|
105
|
-
clazz.expect = item.pair.valueItem.value.array if item.pair.valueItem.value.array
|
106
|
-
else
|
107
|
-
clazz.content[item.pair.key] = item.pair.array if item.pair.array
|
108
|
-
clazz.content[item.pair.key] = item.pair.map if item.pair.map
|
109
|
-
clazz.content[item.pair.key] = item.pair.valueItem.value if item.pair.valueItem.value
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
superclass = clazz.superclass
|
114
|
-
|
115
|
-
if superclass && !reserved?(superclass) && !global.has_class?(superclass)
|
116
|
-
raise InterpreterError, 'Invalid superclass: ' + superclass.to_s
|
117
|
-
end
|
118
|
-
raise InterpreterError, 'Missing id for class' if clazz.id.nil?
|
119
|
-
|
120
|
-
# Make sure the class name isn't redefining an existing class
|
121
|
-
if !global.has_class?(clazz.id) && !global.has_class?(clazz.name)
|
122
|
-
|
123
|
-
# store the classes by id and name to make them easier to find later
|
124
|
-
global.classs(clazz)
|
125
|
-
else
|
126
|
-
id = clazz.id.nil? ? 'undefined' : clazz.id
|
127
|
-
name = clazz.name.nil? ? 'undefined' : clazz.name
|
128
|
-
raise InterpreterError, 'Class name or id already defined - cannot redefine: ' + id + ', ' + name
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
# Check for a reserved class name
|
133
|
-
def self.reserved?(str)
|
134
|
-
%w[map str arr num].include?(str)
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# The MIT License (MIT)
|
4
|
-
#
|
5
|
-
# Copyright (c) 2019 NUM Technology Ltd
|
6
|
-
#
|
7
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
-
# of this software and associated documentation files (the "Software"), to deal
|
9
|
-
# in the Software without restriction, including without limitation the rights
|
10
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
-
# copies of the Software, and to permit persons to whom the Software is
|
12
|
-
# furnished to do so, subject to the following conditions:
|
13
|
-
#
|
14
|
-
# The above copyright notice and this permission notice shall be included in
|
15
|
-
# all copies or substantial portions of the Software.
|
16
|
-
#
|
17
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
20
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
23
|
-
# THE SOFTWARE.
|
24
|
-
|
25
|
-
module MODL
|
26
|
-
module Parser
|
27
|
-
# Extracts an index definition from a ParsedPair
|
28
|
-
class IndexExtractor
|
29
|
-
def self.extract(pair, global)
|
30
|
-
item = pair.valueItem if pair.valueItem
|
31
|
-
item = pair.array if pair.array
|
32
|
-
|
33
|
-
# collect all values from the object
|
34
|
-
if item.is_a? Parsed::ParsedValueItem
|
35
|
-
if item&.value&.text
|
36
|
-
global.add_to_index(item.value.text)
|
37
|
-
elsif item&.value&.array
|
38
|
-
item.value.array.abstractArrayItems.each do |avi|
|
39
|
-
global.add_to_index(avi.arrayValueItem)
|
40
|
-
end
|
41
|
-
elsif item&.value&.nbArray
|
42
|
-
item.value.nbArray.arrayItems.each do |avi|
|
43
|
-
global.add_to_index(avi.arrayValueItem)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
elsif item.is_a? Parsed::ParsedArray
|
47
|
-
item.abstractArrayItems.each do |avi|
|
48
|
-
global.add_to_index(avi.arrayValueItem)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|