modl 0.3.26 → 0.3.27

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