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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -149
  3. data/Gemfile +4 -2
  4. data/LICENSE.txt +1 -1
  5. data/README.md +19 -11
  6. data/Rakefile +5 -3
  7. data/lib/modl/interpreter.rb +38 -0
  8. data/lib/modl/model/model.rb +264 -0
  9. data/lib/modl/parser/parser.rb +272 -59
  10. data/lib/modl/tokeniser/context.rb +113 -0
  11. data/lib/modl/tokeniser/tokeniser.rb +28 -0
  12. data/lib/modl/util/functions.rb +74 -0
  13. data/lib/modl/util/unicode.rb +44 -0
  14. data/lib/modl/version.rb +5 -0
  15. data/lib/modl.rb +7 -32
  16. data/modl.gemspec +8 -11
  17. metadata +16 -75
  18. data/.DS_Store +0 -0
  19. data/.idea/vcs.xml +0 -6
  20. data/.rspec +0 -3
  21. data/.rubocop.yml +0 -5
  22. data/.travis.yml +0 -7
  23. data/bin/console +0 -14
  24. data/bin/setup +0 -8
  25. data/lib/modl/parser/MODLLexer.interp +0 -132
  26. data/lib/modl/parser/MODLLexer.rb +0 -324
  27. data/lib/modl/parser/MODLLexer.tokens +0 -40
  28. data/lib/modl/parser/MODLParser.interp +0 -93
  29. data/lib/modl/parser/MODLParser.rb +0 -2492
  30. data/lib/modl/parser/MODLParser.tokens +0 -40
  31. data/lib/modl/parser/MODLParserBaseListener.rb +0 -164
  32. data/lib/modl/parser/MODLParserBaseVisitor.rb +0 -107
  33. data/lib/modl/parser/MODLParserListener.rb +0 -151
  34. data/lib/modl/parser/MODLParserVisitor.rb +0 -56
  35. data/lib/modl/parser/class_processor.rb +0 -411
  36. data/lib/modl/parser/evaluator.rb +0 -125
  37. data/lib/modl/parser/file_importer.rb +0 -101
  38. data/lib/modl/parser/global_parse_context.rb +0 -318
  39. data/lib/modl/parser/instruction_processor.rb +0 -82
  40. data/lib/modl/parser/interpreter.rb +0 -75
  41. data/lib/modl/parser/modl_class.rb +0 -138
  42. data/lib/modl/parser/modl_index.rb +0 -54
  43. data/lib/modl/parser/modl_keylist.rb +0 -81
  44. data/lib/modl/parser/modl_method.rb +0 -172
  45. data/lib/modl/parser/object_cache.rb +0 -88
  46. data/lib/modl/parser/orphan_handler.rb +0 -98
  47. data/lib/modl/parser/parsed.rb +0 -1469
  48. data/lib/modl/parser/ref_processor.rb +0 -258
  49. data/lib/modl/parser/substitutions.rb +0 -101
  50. data/lib/modl/parser/sutil.rb +0 -108
  51. data/lib/modl/parser/throwing_error_listener.rb +0 -44
  52. data/lib/modl/parser/unicode_escape_replacer.rb +0 -148
  53. data/lib/modl/parser/unicode_escapes.rb +0 -112
  54. data/lib/modl/parser/version.rb +0 -29
@@ -1,72 +1,285 @@
1
1
  # frozen_string_literal: true
2
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/throwing_error_listener'
26
- require 'modl/parser/parsed'
27
-
28
3
  module MODL
4
+ # A Parser module
29
5
  module Parser
6
+ REPLACEMENTS = {
7
+ '\t' => "\t",
8
+ '\n' => "\n",
9
+ '\b' => "\b",
10
+ '\f' => "\f",
11
+ '\r' => "\r",
12
+ '~t' => "\t",
13
+ '~n' => "\n",
14
+ '~b' => "\b",
15
+ '~f' => "\f",
16
+ '~r' => "\r",
17
+ '~\\' => '\\',
18
+ '\\\\' => '\\',
19
+ '~~' => '~',
20
+ '\~' => '~',
21
+ '~(' => '(',
22
+ '\(' => '(',
23
+ '~)' => ')',
24
+ '\)' => ')',
25
+ '~[' => '[',
26
+ '\[' => '[',
27
+ '~]' => ']',
28
+ '\]' => ']',
29
+ '~;' => ';',
30
+ '\;' => ';',
31
+ '~`' => '`',
32
+ '\`' => '`',
33
+ '~"' => '"',
34
+ '"' => '"',
35
+ '~=' => '=',
36
+ '\=' => '='
37
+ }.freeze
38
+
39
+ def self.parse_modl(str)
40
+ tokens = MODL::Tokeniser.tokenise str
41
+ if tokens.nil? || tokens.empty?
42
+ MODL::Model::Modl.new nil
43
+ elsif root_primitive? tokens[0]
44
+ MODL::Model::Modl.new tokens[0].value
45
+ else
46
+ result = parse_structures(tokens)
47
+ return MODL::Model::Modl.new result[0] if result.length == 1
48
+
49
+ MODL::Model::Modl.new ModlArray.new(result)
50
+ end
51
+ end
52
+
53
+ def self.root_primitive?(token)
54
+ %i[string quoted null true false integer float].include?(token)
55
+ end
56
+
57
+ def self.parse_structures(tokens)
58
+ result = []
59
+ until tokens.empty?
60
+ result.push parse_modl_value(tokens)
61
+ expect_separator = tokens.shift
62
+ if !expect_separator.nil? && expect_separator.type == :struct_sep
63
+ raise ParserError, "Expected ';' near #{tokens}"
64
+ end
65
+ end
66
+ result
67
+ end
68
+
69
+ def self.parse_modl_value(tokens)
70
+ first_token = tokens.shift
71
+
72
+ case first_token.type
73
+ when :lbracket
74
+ tokens.unshift first_token
75
+ return parse_modl_array tokens
76
+ when :lparen
77
+ tokens.unshift first_token
78
+ return parse_modl_map tokens
79
+ when :string || :quoted
80
+ peek = tokens[0]
81
+ key = first_token.value
82
+ if !peek.nil? && peek.type == :equals
83
+ tokens.shift
84
+ return MODL::Model::ModlPair.new replace_escapes(unquote(key)), parse_pair_value(tokens)
85
+ end
86
+
87
+ if !peek.nil? && (peek.type == :lbracket || peek.type == :lparen)
88
+ return MODL::Model::ModlPair.new replace_escapes(unquote(key)), parse_pair_value(tokens)
89
+ end
90
+
91
+ if peek.nil? || peek.type == :struct_sep || peek.type == :rparen || peek.type == :rbracket
92
+ return MODL::Model::ModlString.new(replace_escapes(first_token.value)) if first_token.type == :string
93
+
94
+ return MODL::Model::ModlQuoted.new(replace_escapes(unquote(first_token.value)))
95
+ end
96
+ when :integer
97
+ return MODL::Model::ModlInteger.new first_token.value
98
+ when :float
99
+ return MODL::Model::ModlFloat.new first_token.value
100
+ when :null
101
+ return MODL::Model::ModlBoolNull::MODL_NULL
102
+ when true
103
+ return MODL::Model::ModlBoolNull::MODL_TRUE
104
+ when false
105
+ return MODL::Model::ModlBoolNull::MODL_FALSE
106
+ else
107
+ tokens.unshift first_token
108
+ maybe_primitive = parse_primitive tokens
109
+ return maybe_primitive unless maybe_primitive.nil?
110
+ end
111
+ raise ParserError, "Unexpected token: \'#{first_token}\'"
112
+ end
113
+
114
+ def self.parse_pair_value(tokens)
115
+ first_token = tokens.shift
116
+ case first_token.type
117
+ when :lbracket
118
+ tokens.unshift first_token
119
+ return parse_modl_array tokens
120
+ when :lparen
121
+ tokens.unshift first_token
122
+ return parse_modl_map tokens
123
+ when :string || :quoted
124
+ peek = tokens[0]
125
+
126
+ raise ParserError, "Unexpected token: \'#{first_token}\'" if !peek.nil? && peek.type == :equals
127
+
128
+ if !peek.nil? && (peek.type == :lbracket || peek.type == :lparen)
129
+ raise ParserError, "Unexpected token: \'#{first_token}\'"
130
+ end
131
+
132
+ if peek.nil? || peek.type == :struct_sep || peek.type == :rparen || peek.type == :rbracket
133
+ return MODL::Model::ModlString.new replace_escapes(first_token.value) if first_token.type == :string
134
+
135
+ return MODL::Model::ModlQuoted.new replace_escapes(unquote(first_token.value))
136
+ end
137
+ raise ParserError, "Unexpected token: \'#{first_token}\'"
138
+ when :integer
139
+ return MODL::Model::ModlInteger.new first_token.value
140
+ when :float
141
+ return MODL::Model::ModlFloat.new first_token.value
142
+ when :null
143
+ return MODL::Model::ModlBoolNull::MODL_NULL
144
+ when true
145
+ return MODL::Model::ModlBoolNull::MODL_TRUE
146
+ when false
147
+ return MODL::Model::ModlBoolNull::MODL_FALSE
148
+ else
149
+ tokens.unshift first_token
150
+ maybe_primitive = parse_primitive tokens
151
+ return maybe_primitive unless maybe_primitive.nil?
152
+ end
153
+ raise ParserError, "Unexpected token: \'#{first_token}\'"
154
+ end
30
155
 
31
- # This class converts the input string into a Modl:Parser::Parsed object for further processing.
32
- class Parser
33
- def self.parse(str, global = nil)
34
- begin
35
- lexer = MODL::Parser::MODLLexer.new(Antlr4::Runtime::CharStreams.from_string(str, 'String'))
36
- lexer.remove_error_listeners
37
- lexer.add_error_listener ThrowingErrorListener.instance
38
-
39
- tokens = Antlr4::Runtime::CommonTokenStream.new(lexer)
40
-
41
- parser = MODL::Parser::MODLParser.new(tokens)
42
- parser.remove_error_listeners
43
- parser.add_error_listener ThrowingErrorListener.instance
44
-
45
- global = GlobalParseContext.new if global.nil?
46
-
47
- parsed = Parsed.new(global)
48
- parser.modl.enter_rule(parsed)
49
- parsed
50
- rescue Antlr4::Runtime::ParseCancellationException => e
51
- check_modl_version(global, e)
52
- raise ParserError, 'Parser Error: ' + e.message
53
- rescue StandardError => e
54
- check_modl_version(global, e)
55
- raise InterpreterError, 'Interpreter Error: ' + e.message
56
- rescue InterpreterError => e
57
- check_modl_version(global, e)
58
- raise InterpreterError, 'Interpreter Error: ' + e.message
156
+ def self.parse_primitive(tokens)
157
+ result = nil
158
+ tok = tokens.shift
159
+
160
+ case tok.type
161
+ when :lparen || :rparen || :lbracket || :rbracket || :equals
162
+ raise ParserError, "Unexpected token: \'#{tok}\'" if tokens.empty?
163
+
164
+ tokens.unshift tok
165
+ return nil
166
+ when :null
167
+ result = MODL::Model::ModlBoolNull::MODL_NULL
168
+ when true
169
+ result = MODL::Model::ModlBoolNull::MODL_TRUE
170
+ when false
171
+ result = MODL::Model::ModlBoolNull::MODL_FALSE
172
+ when :quoted
173
+ result = MODL::Model::ModlQuoted.new replace_escapes(unquote(tok.value))
174
+ when :string
175
+ result = MODL::Model::ModlString.new replace_escapes(tok.value)
176
+ when :integer
177
+ result = MODL::Model::ModlInteger.new tok.value
178
+ when :float
179
+ result = MODL::Model::ModlFloat.new tok.value
180
+ else
181
+ raise ParserError, "Unknown token type in: \'#{tok}\'"
182
+ end
183
+
184
+ peek = tokens[0]
185
+ raise ParserError, 'Only one primitive allowed at the root.' if !peek.nil? && peek.type == :struct_sep
186
+
187
+ if !peek.nil? && (peek.type == :lparen || peek.type == :lbracket || peek.type == :equals)
188
+ s.unshift tok
189
+ return nil
190
+ elsif !peek.nil?
191
+ raise ParserError, "Unexpected token: \'#{peek}\'"
192
+ end
193
+ result
194
+ end
195
+
196
+ def self.parse_modl_map(tokens)
197
+ first_token = tokens.shift
198
+ entries = []
199
+
200
+ until tokens.empty?
201
+ peek = tokens[0]
202
+ if !peek.nil? && peek.type == :rparen
203
+ tokens.shift
204
+ break
205
+ end
206
+
207
+ mp = parse_modl_value tokens
208
+ entries.push mp
209
+
210
+ peek = tokens[0]
211
+
212
+ raise ParserError, "Expected ')' near #{first_token}" if peek.nil?
213
+
214
+ case peek.type
215
+ when :rparen
216
+ tokens.shift
217
+ break
218
+ when :struct_sep
219
+ tokens.shift
220
+ peek = tokens[0]
221
+ raise ParserError, "Unexpected ; before ] at #{peek}" if !peek.nil? && peek.type == :rparen
222
+ end
223
+ end
224
+ MODL::Model::ModlMap.new entries
225
+ end
226
+
227
+ def self.parse_modl_array(tokens)
228
+ first_token = tokens.shift
229
+ entries = []
230
+
231
+ until tokens.empty?
232
+ peek = tokens[0]
233
+ if !peek.nil? && peek.type == :rbracket
234
+ tokens.shift
235
+ break
236
+ end
237
+
238
+ mp = parse_modl_value tokens
239
+ entries.push mp
240
+
241
+ peek = tokens[0]
242
+
243
+ raise ParserError, "Expected ']' near #{first_token}" if peek.nil?
244
+
245
+ case peek.type
246
+ when :rbracket
247
+ tokens.shift
248
+ break
249
+ when :struct_sep
250
+ tokens.shift
251
+ peek = tokens[0]
252
+ raise ParserError, "Unexpected ; before ] at #{peek}" if !peek.nil? && peek.type == :rparen
59
253
  end
60
254
  end
255
+ MODL::Model::ModlArray.new entries
256
+ end
257
+
258
+ def self.unquote(str)
259
+ return str unless str.instance_of?(String)
260
+
261
+ if (str.start_with?('`') && str.end_with?('`')) || (str.start_with?('"') && str.end_with?('"'))
262
+ str[1..-2]
263
+ else
264
+ str
265
+ end
266
+ end
267
+
268
+ def self.replace_escapes(str)
269
+ return str unless str.instance_of?(String)
61
270
 
62
- def self.check_modl_version(global, e)
63
- if global.syntax_version > global.interpreter_syntax_version
64
- raise InterpreterError, 'Interpreter Error: ' + e.message + ' - MODL Version ' +
65
- global.interpreter_syntax_version.to_s +
66
- ' interpreter cannot process this MODL Version ' +
67
- global.syntax_version.to_s + ' file.'
271
+ result = str
272
+ i = 0
273
+ while i < str.length
274
+ REPLACEMENTS.each_pair do |key, value|
275
+ if result.slice(i..).start_with?(key)
276
+ result = result.sub(key, value)
277
+ break
278
+ end
68
279
  end
280
+ i += 1
69
281
  end
282
+ result
70
283
  end
71
284
  end
72
285
  end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MODL
4
+ module Tokeniser
5
+ # A parsing context for a MODL String
6
+ class Context
7
+ WS = " \t\r\n"
8
+ INTEGER_REGEX = '^-?(?:0|[1-9]\d*)$'
9
+ FLOAT_REGEX = '^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$'
10
+ NON_STRING_TOKENS = '[]();"=`'
11
+
12
+ def initialize(str)
13
+ @str = str
14
+ @tokens = []
15
+ @tok_start = 0
16
+ end
17
+
18
+ def parse
19
+ while next_token
20
+ end
21
+ @tokens
22
+ end
23
+
24
+ def next_token
25
+ while @tok_start < @str.length
26
+ break unless WS.include?(@str[@tok_start])
27
+
28
+ @tok_start += 1
29
+ end
30
+
31
+ return false if @tok_start >= @str.length
32
+
33
+ case @str[@tok_start]
34
+ when '('
35
+ tok_type = :lparen
36
+ tok_end = @tok_start + 1
37
+ when ')'
38
+ tok_type = :rparen
39
+ tok_end = @tok_start + 1
40
+ when '['
41
+ tok_type = :lbracket
42
+ tok_end = @tok_start + 1
43
+ when ']'
44
+ tok_type = :rbracket
45
+ tok_end = @tok_start + 1
46
+ when ';'
47
+ tok_type = :struct_sep
48
+ tok_end = @tok_start + 1
49
+ when '='
50
+ tok_type = :equals
51
+ tok_end = @tok_start + 1
52
+ when '"'
53
+ tok_type = :quoted
54
+ tok_end = scan_to_end_of_quoted(@str, @tok_start, '"')
55
+ when '`'
56
+ tok_type = :quoted
57
+ tok_end = scan_to_end_of_quoted(@str, @tok_start, '`')
58
+ else
59
+ tok_type = :string
60
+ tok_end = scan_to_end_of_string(@str, @tok_start)
61
+ end
62
+
63
+ tok_value = @str[@tok_start..(tok_end - 1)].strip
64
+
65
+ if tok_value.match? INTEGER_REGEX
66
+ number = tok_value.to_i
67
+ @tokens.push Token.new(:integer, number, @tok_start, tok_end)
68
+ elsif tok_value.match? FLOAT_REGEX
69
+ number = tok_value.to_f
70
+ @tokens.push Token.new(:float, number, @tok_start, tok_end)
71
+ elsif tok_value == 'null'
72
+ @tokens.push Token.new(:null, nil, @tok_start, tok_end)
73
+ elsif tok_value == 'true'
74
+ @tokens.push Token.new(true, true, @tok_start, tok_end)
75
+ elsif tok_value == 'false'
76
+ @tokens.push Token.new(false, false, @tok_start, tok_end)
77
+ else
78
+ @tokens.push Token.new(tok_type, tok_value, @tok_start, tok_end)
79
+ end
80
+
81
+ @tok_start = tok_end
82
+ tok_end < @str.length
83
+ end
84
+
85
+ def scan_to_end_of_quoted(str, start, quote_char)
86
+ end_str = start + 1
87
+ while end_str < str.length
88
+ end_char = str[end_str]
89
+ prev_char = str[end_str - 1]
90
+
91
+ break if end_char == quote_char && prev_char != '\\' && prev_char != '~'
92
+
93
+ end_str += 1
94
+ end
95
+ end_str + 1
96
+ end
97
+
98
+ def scan_to_end_of_string(str, start)
99
+ end_str = start + 1
100
+ while end_str < str.length
101
+ break if NON_STRING_TOKENS.include?(str[end_str]) && !escaped?(str, end_str - 1)
102
+
103
+ end_str += 1
104
+ end
105
+ end_str
106
+ end
107
+
108
+ def escaped?(str, pos)
109
+ pos >= 0 && (str[pos] == '~' || str[pos] == '\\')
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'modl/tokeniser/context'
4
+
5
+ module MODL
6
+ # A MODL Tokeniser module
7
+ module Tokeniser
8
+ # A class to represent MODL tokens
9
+ class Token
10
+ attr_reader :type, :value, :from, :to
11
+
12
+ def initialize(type, value, from, to)
13
+ @type = type
14
+ @value = value
15
+ @from = from
16
+ @to = to
17
+ end
18
+
19
+ def to_s
20
+ "type: #{@type}, from: #{@from}, to: #{@to}, value: \"#{@value}\""
21
+ end
22
+ end
23
+
24
+ def self.tokenise(str)
25
+ Context.new(str).parse
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MODL
4
+ # Helper functions for MODL.generate
5
+ module UTIL
6
+ SHOULD_BE_GRAVE_QUOTED = /.*[()\[\];{}="].*/.freeze
7
+ IS_NUMERIC = /^-?[0-9]*\.?[0-9]+(?:[Ee][+-]?[0-9]+)?$/.freeze
8
+
9
+ def self.escape_graves(str)
10
+ return str unless str
11
+
12
+ str.gsub(/`/, '~`')
13
+ end
14
+
15
+ def self.escape_double_quotes(str)
16
+ return str unless str
17
+
18
+ i = str.index('"', 1) # ignore the initial quote
19
+ result = str
20
+ # Don't affect the final quote in the string
21
+ while !i.nil? && i < (result.length - 1)
22
+ result = result.slice(0..(i - 1)) + '~u0022' + result.slice((i + 1)..)
23
+ i = result.index('"', 1)
24
+ end
25
+ result
26
+ end
27
+
28
+ def self.grave_quote_if_necessary(str)
29
+ return str unless str
30
+
31
+ if str.match?(SHOULD_BE_GRAVE_QUOTED) ||
32
+ (str.match?(IS_NUMERIC) && str != '00' && str != '01' && str != '000') ||
33
+ (str.strip.empty? ||
34
+ str.match?(IS_NUMERIC) ||
35
+ str == 'true' ||
36
+ str == 'false' ||
37
+ str == 'null')
38
+ "`#{str}`"
39
+ else
40
+ str
41
+ end
42
+ end
43
+
44
+ def self.double_quote_if_necessary(str)
45
+ if str && str.include?('~`')
46
+ "\"#{str}\""
47
+ else
48
+ str
49
+ end
50
+ end
51
+
52
+ def self.replace_nbsp(str)
53
+ str.gsub('\u00a0', ' ')
54
+ end
55
+
56
+ def self.escape_and_quote(str)
57
+ double_quote_if_necessary(
58
+ grave_quote_if_necessary(
59
+ escape_graves(
60
+ UNICODE.escape(
61
+ replace_nbsp(
62
+ escape_double_quotes(str)
63
+ )
64
+ )
65
+ )
66
+ )
67
+ )
68
+ end
69
+
70
+ def self.non_string_primitive?(str)
71
+ str == 'true' || str == 'false' || str == 'null' || str.match?(IS_NUMERIC)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: false
2
+
3
+ module MODL
4
+ # Handle escaping of unicode characters.
5
+ module UNICODE
6
+ VERTICAL_TAB = 0x0b
7
+ BACKSPACE = 0x08
8
+ FORMFEED = 0x0c
9
+ LINEFEED = 0x0a
10
+ CARRIAGE_RETURN = 0x0d
11
+ TAB = 0x09
12
+
13
+ def self.escape_char(chr)
14
+ return '' unless chr
15
+
16
+ if chr >= 32 && chr <= 127
17
+ '' << chr
18
+ elsif chr == VERTICAL_TAB
19
+ '~u000B'
20
+ elsif chr == BACKSPACE
21
+ '\\b'
22
+ elsif chr == FORMFEED
23
+ '\\f'
24
+ elsif chr == LINEFEED
25
+ '\\n'
26
+ elsif chr == CARRIAGE_RETURN
27
+ '\\r'
28
+ elsif chr == TAB
29
+ '\\t'
30
+ else
31
+ '' << chr
32
+ end
33
+ end
34
+
35
+ def self.escape(str)
36
+ result = ''
37
+
38
+ str.each_codepoint do |c|
39
+ result << escape_char(c)
40
+ end
41
+ result
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MODL
4
+ VERSION = '0.3.27'
5
+ end
data/lib/modl.rb CHANGED
@@ -1,34 +1,9 @@
1
1
  # frozen_string_literal: true
2
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 "antlr4/runtime"
26
- require "modl/parser/version"
27
- require 'modl/parser/MODLParserListener'
28
- require 'modl/parser/MODLParserVisitor'
29
- require 'modl/parser/MODLParserBaseListener'
30
- require 'modl/parser/MODLParserBaseVisitor'
31
- require 'modl/parser/MODLLexer'
32
- require 'modl/parser/MODLParser'
33
- require 'modl/parser/interpreter'
34
- require 'modl/parser/instruction_processor'
3
+ require 'modl/version'
4
+ require 'modl/model/model'
5
+ require 'modl/tokeniser/tokeniser'
6
+ require 'modl/parser/parser'
7
+ require 'modl/util/unicode'
8
+ require 'modl/util/functions'
9
+ require 'modl/interpreter'
data/modl.gemspec CHANGED
@@ -1,30 +1,27 @@
1
-
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'modl/parser/version'
3
+ require 'modl/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = 'modl'
8
- spec.version = MODL::Parser::VERSION
7
+ spec.version = MODL::VERSION
9
8
  spec.authors = ['Tony Walmsley']
10
9
  spec.email = ['tony@aosd.co.uk']
11
10
 
12
- spec.summary = 'The ANTLR4 Lexer and Parser for MODL generated using the Ruby language target.'
13
- spec.description = 'Contains the base Lexer, Parser, and supporting classes for a MODL parser.'
14
- spec.homepage = 'https://github.com/MODLanguage/ruby-interpreter'
11
+ spec.summary = 'A Ruby inretpreter for the MODL data serialisation language.'
12
+ spec.description = 'A command line program for interpreting MODL objects.'
13
+ spec.homepage = 'https://github.com/MODLanguage/ruby-modl'
15
14
  spec.license = 'MIT'
16
15
 
17
16
  # Specify which files should be added to the gem when it is released.
18
17
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
20
19
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
20
  end
22
21
  spec.bindir = 'exe'
23
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
23
  spec.require_paths = ['lib']
25
24
 
26
- spec.add_development_dependency "rake", ">= 12.3.3"
25
+ spec.add_development_dependency 'rake', '>= 12.3.3'
27
26
  spec.add_development_dependency 'rspec', '~> 3.0'
28
- spec.add_runtime_dependency 'antlr4-runtime', '= 0.2.10'
29
- spec.add_runtime_dependency 'punycode4r', '>= 0.2.0'
30
27
  end