zenml 1.5.1 → 1.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc8d8a0fee635054ffabb1fc90ba5b8ed78e6225f7932e2aa777a79274a5d502
4
- data.tar.gz: 37c86142fdae037d59d5a27b661fdd5c0689a9bd8a652b910bdc30e82e2d63f0
3
+ metadata.gz: eeb3297631724f74bcfbcea67c59f71f4131a6d142f3b98c86cbb0836368d1ad
4
+ data.tar.gz: '029b4e2b8eadea4a68b23b721d46ed3546d25269fb927ddd729781f7a67ae02f'
5
5
  SHA512:
6
- metadata.gz: ecc6096ee7aca2992e8e3eb2f9d8d6dd703bca5d00a53c8d5b1eba2ccf256ac466c41ee97a795eb4afea9d55bdb576cc5d0133314e788a3ed8cf0d82aa8ea69b
7
- data.tar.gz: e9aa413207a31753012f8e814fc63ac7ec7d7fdd4ea4a57312d2b4698d221fd3e0377556902367328dc4dd64ee4495d59461bcc01ebd077a8062cec90e80b120
6
+ metadata.gz: 3ccb7bae3fc78b5361aa8f951eaca5f34bcd0c3a96fcf59a63a87931fdbdccdd784ed7174deaa3db2f87aa917383ed8f056150f342813eb1e1b5950ce4bde91e
7
+ data.tar.gz: d725803a7cd455c0a6e2fa1bdabe0ffb37c3e37620252703dda7261fa8c58652f3e67cbb2a75b00ec00d113f90e1d8b73a456cb9d18dd0a3f7658e7dd033006a
@@ -3,7 +3,7 @@
3
3
 
4
4
  module Zenithal
5
5
 
6
- VERSION = "1.5.1"
6
+ VERSION = "1.6.0"
7
7
  VERSION_ARRAY = VERSION.split(/\./).map(&:to_i)
8
8
 
9
9
  end
@@ -14,12 +14,13 @@ module Zenithal::ZenithalParserMethod
14
14
  STRING_END = "\""
15
15
  CONTENT_START = "<"
16
16
  CONTENT_END = ">"
17
+ CONTENT_DELIMITER = ";"
17
18
  SPECIAL_ELEMENT_STARTS = {:brace => "{", :bracket => "[", :slash => "/"}
18
19
  SPECIAL_ELEMENT_ENDS = {:brace => "}", :bracket => "]", :slash => "/"}
19
20
  COMMENT_DELIMITER = "#"
20
21
  SYSTEM_INSTRUCTION_NAME = "zml"
21
22
  MARK_CHARS = {:instruction => "?", :trim => "*", :verbal => "~", :multiple => "+"}
22
- ESCAPE_CHARS = ["&", "<", ">", "'", "\"", "{", "}", "[", "]", "/", "\\", "|", "`", "#"]
23
+ ESCAPE_CHARS = ["&", "<", ">", "'", "\"", "{", "}", "[", "]", "/", "\\", "|", "`", "#", ";"]
23
24
  SPACE_CHARS = [0x20, 0x9, 0xD, 0xA]
24
25
  VALID_FIRST_IDENTIFIER_CHARS = [
25
26
  0x3A, 0x5F,
@@ -39,10 +40,9 @@ module Zenithal::ZenithalParserMethod
39
40
  0x3001..0xD7FF, 0xF900..0xFDCF, 0xFDF0..0xFFFD, 0x10000..0xEFFFF
40
41
  ]
41
42
 
43
+ private
44
+
42
45
  def parse
43
- unless @inside_run
44
- warn("This method is now only for internal use. Use 'run' instead.", uplevel: 1)
45
- end
46
46
  if @whole
47
47
  parse_document
48
48
  else
@@ -50,10 +50,9 @@ module Zenithal::ZenithalParserMethod
50
50
  end
51
51
  end
52
52
 
53
- private
54
-
55
53
  def parse_document
56
54
  document = REXML::Document.new
55
+ check_version
57
56
  children = parse_nodes({})
58
57
  if @exact
59
58
  parse_eof
@@ -67,7 +66,7 @@ module Zenithal::ZenithalParserMethod
67
66
  def parse_nodes(options)
68
67
  nodes = nil
69
68
  if options[:plugin]
70
- nodes = options[:plugin].parse
69
+ nodes = options[:plugin].send(:parse)
71
70
  elsif options[:verbal]
72
71
  raw_nodes = many(->{parse_text(options)})
73
72
  nodes = raw_nodes.inject(REXML::Nodes[], :<<)
@@ -94,17 +93,13 @@ module Zenithal::ZenithalParserMethod
94
93
  end
95
94
 
96
95
  def parse_element(options)
97
- start_char = parse_char_any([ELEMENT_START, MACRO_START])
98
- name = parse_identifier(options)
99
- marks = parse_marks(options)
100
- attributes = maybe(->{parse_attributes(options)}) || {}
101
- macro = start_char == MACRO_START
96
+ name, marks, attributes, macro = parse_tag(options)
102
97
  next_options = determine_options(name, marks, attributes, macro, options)
103
98
  children_list = parse_children_list(next_options)
104
99
  if name == SYSTEM_INSTRUCTION_NAME
105
100
  parse_space
106
101
  end
107
- if start_char == MACRO_START
102
+ if macro
108
103
  element = process_macro(name, marks, attributes, children_list, options)
109
104
  else
110
105
  element = create_element(name, marks, attributes, children_list, options)
@@ -126,6 +121,15 @@ module Zenithal::ZenithalParserMethod
126
121
  return element
127
122
  end
128
123
 
124
+ def parse_tag(options)
125
+ start_char = parse_char_any([ELEMENT_START, MACRO_START])
126
+ name = parse_identifier(options)
127
+ marks = parse_marks(options)
128
+ attributes = maybe(->{parse_attributes(options)}) || {}
129
+ macro = start_char == MACRO_START
130
+ return name, marks, attributes, macro
131
+ end
132
+
129
133
  def parse_marks(options)
130
134
  marks = many(->{parse_mark(options)})
131
135
  return marks
@@ -188,9 +192,28 @@ module Zenithal::ZenithalParserMethod
188
192
  end
189
193
 
190
194
  def parse_children_list(options)
191
- first_children = choose(->{parse_empty_children(options)}, ->{parse_children(options)})
192
- rest_children_list = many(->{parse_children(options)})
193
- children_list = [first_children] + rest_children_list
195
+ if @version == "1.0"
196
+ children_list = parse_children_chain(options)
197
+ else
198
+ children_list = choose(->{parse_empty_children_chain(options)}, ->{parse_children_chain(options)})
199
+ end
200
+ return children_list
201
+ end
202
+
203
+ def parse_children_chain(options)
204
+ if @version == "1.0"
205
+ first_children = choose(->{parse_empty_children(options)}, ->{parse_children(options)})
206
+ rest_children_list = many(->{parse_children(options)})
207
+ children_list = [first_children] + rest_children_list
208
+ else
209
+ children_list = many(->{parse_children(options)})
210
+ end
211
+ return children_list
212
+ end
213
+
214
+ def parse_empty_children_chain(options)
215
+ children = parse_empty_children(options)
216
+ children_list = [children]
194
217
  return children_list
195
218
  end
196
219
 
@@ -202,8 +225,13 @@ module Zenithal::ZenithalParserMethod
202
225
  end
203
226
 
204
227
  def parse_empty_children(options)
205
- parse_char(CONTENT_END)
206
- children = REXML::Nodes[]
228
+ if @version == "1.0"
229
+ parse_char(CONTENT_END)
230
+ children = REXML::Nodes[]
231
+ else
232
+ parse_char(CONTENT_DELIMITER)
233
+ children = REXML::Nodes[]
234
+ end
207
235
  return children
208
236
  end
209
237
 
@@ -217,6 +245,9 @@ module Zenithal::ZenithalParserMethod
217
245
  out_chars = [ESCAPE_START, CONTENT_END]
218
246
  unless options[:verbal]
219
247
  out_chars.push(ELEMENT_START, MACRO_START, CONTENT_START, COMMENT_DELIMITER)
248
+ if @version == "1.1"
249
+ out_chars.push(CONTENT_DELIMITER)
250
+ end
220
251
  @special_element_names.each do |kind, name|
221
252
  out_chars.push(SPECIAL_ELEMENT_STARTS[kind], SPECIAL_ELEMENT_ENDS[kind])
222
253
  end
@@ -255,7 +286,9 @@ module Zenithal::ZenithalParserMethod
255
286
  parse_char(CONTENT_START)
256
287
  content = parse_block_comment_content(options)
257
288
  parse_char(CONTENT_END)
258
- parse_char(COMMENT_DELIMITER)
289
+ if @version == "1.0"
290
+ parse_char(COMMENT_DELIMITER)
291
+ end
259
292
  comment = create_comment(:block, content, options)
260
293
  return comment
261
294
  end
@@ -316,12 +349,12 @@ module Zenithal::ZenithalParserMethod
316
349
  end
317
350
  if marks.include?(:instruction)
318
351
  unless children_list.size <= 1
319
- throw_custom(error_message("Processing instruction cannot have more than one argument"))
352
+ throw_custom("Processing instruction cannot have more than one argument")
320
353
  end
321
354
  nodes = create_instruction(name, attributes, children_list.first, options)
322
355
  else
323
356
  unless marks.include?(:multiple) || children_list.size <= 1
324
- throw_custom(error_message("Normal element cannot have more than one argument"))
357
+ throw_custom("Normal element cannot have more than one argument")
325
358
  end
326
359
  nodes = create_normal_element(name, attributes, children_list, options)
327
360
  end
@@ -376,7 +409,7 @@ module Zenithal::ZenithalParserMethod
376
409
  if name
377
410
  nodes = create_element(name, [], {}, [children], options)
378
411
  else
379
- throw_custom(error_message("No name specified for #{kind} elements"))
412
+ throw_custom("No name specified for #{kind} elements")
380
413
  end
381
414
  return nodes
382
415
  end
@@ -393,7 +426,7 @@ module Zenithal::ZenithalParserMethod
393
426
 
394
427
  def create_escape(place, char, options)
395
428
  unless ESCAPE_CHARS.include?(char)
396
- throw_custom(error_message("Invalid escape"))
429
+ throw_custom("Invalid escape")
397
430
  end
398
431
  return char
399
432
  end
@@ -408,11 +441,18 @@ module Zenithal::ZenithalParserMethod
408
441
  elsif @plugins.key?(name)
409
442
  elements = children_list.first
410
443
  else
411
- throw_custom(error_message("No such macro '#{name}'"))
444
+ throw_custom("No such macro '#{name}'")
412
445
  end
413
446
  return elements
414
447
  end
415
448
 
449
+ def check_version
450
+ string = @source.string
451
+ if match = string.match(/\\zml\?\s*\|.*version\s*=\s*"(\d+\.\d+)".*\|/)
452
+ @version = match[1]
453
+ end
454
+ end
455
+
416
456
  end
417
457
 
418
458
 
@@ -425,9 +465,11 @@ class Zenithal::ZenithalParser < Zenithal::Parser
425
465
 
426
466
  def initialize(source)
427
467
  super(source)
428
- @version = nil
429
468
  @exact = true
430
469
  @whole = true
470
+ @fallback_version = "1.0"
471
+ @version = "1.0"
472
+ @fallback_special_element_names = {:brace => nil, :bracket => nil, :slash => nil}
431
473
  @special_element_names = {:brace => nil, :bracket => nil, :slash => nil}
432
474
  @macros = {}
433
475
  @plugins = {}
@@ -435,7 +477,8 @@ class Zenithal::ZenithalParser < Zenithal::Parser
435
477
 
436
478
  def update(source)
437
479
  super(source)
438
- @version = nil
480
+ @version = @fallback_version
481
+ @special_element_names = @fallback_special_element_names
439
482
  end
440
483
 
441
484
  # Registers a macro.
@@ -463,15 +506,23 @@ class Zenithal::ZenithalParser < Zenithal::Parser
463
506
  @plugins.delete(name)
464
507
  end
465
508
 
509
+ def version=(version)
510
+ @version = version
511
+ @fallback_version = version
512
+ end
513
+
466
514
  def brace_name=(name)
515
+ @fallback_special_element_names[:brace] = name
467
516
  @special_element_names[:brace] = name
468
517
  end
469
518
 
470
519
  def bracket_name=(name)
520
+ @fallback_special_element_names[:bracket] = name
471
521
  @special_element_names[:bracket] = name
472
522
  end
473
523
 
474
524
  def slash_name=(name)
525
+ @fallback_special_element_names[:slash] = name
475
526
  @special_element_names[:slash] = name
476
527
  end
477
528
 
@@ -16,7 +16,6 @@ class Zenithal::Parser
16
16
  else
17
17
  @source = Zenithal::StringReader.new(source.to_s)
18
18
  end
19
- @inside_run = false
20
19
  end
21
20
 
22
21
  def update(source)
@@ -28,18 +27,12 @@ class Zenithal::Parser
28
27
  else
29
28
  @source = Zenithal::StringReader.new(source.to_s)
30
29
  end
31
- @inside_run = false
32
30
  end
33
31
 
34
32
  def run
35
33
  value = nil
36
34
  message = catch(ERROR_TAG) do
37
- begin
38
- @inside_run = true
39
- value = parse
40
- ensure
41
- @inside_run = false
42
- end
35
+ value = parse
43
36
  end
44
37
  unless value
45
38
  raise Zenithal::ZenithalParseError.new(message)
@@ -47,6 +40,8 @@ class Zenithal::Parser
47
40
  return value
48
41
  end
49
42
 
43
+ private
44
+
50
45
  # Parses a whole data.
51
46
  # This method is intended to be overridden in subclasses.
52
47
  def parse
@@ -54,8 +49,6 @@ class Zenithal::Parser
54
49
  return nil
55
50
  end
56
51
 
57
- private
58
-
59
52
  # Parses a single character which matches the specified query.
60
53
  # If the next character does not match the query or the end of file is reached, then an error occurs and no input is consumed.
61
54
  # Otherwise, a string which consists of the matched single chracter is returned.
@@ -82,10 +75,10 @@ class Zenithal::Parser
82
75
  message = ""
83
76
  end
84
77
  unless predicate
85
- throw_custom(error_message(message))
78
+ throw_custom(message)
86
79
  end
87
80
  else
88
- throw_custom(error_message("Unexpected end of file"))
81
+ throw_custom("Unexpected end of file")
89
82
  end
90
83
  char = @source.read
91
84
  return char
@@ -109,10 +102,10 @@ class Zenithal::Parser
109
102
  if char
110
103
  if chars.any?{|s| s == char}
111
104
  chars_string = chars.map{|s| "'#{s}'"}.join(", ")
112
- throw_custom(error_message("Expected other than #{chars_string} but got '#{char}'"))
105
+ throw_custom("Expected other than #{chars_string} but got '#{char}'")
113
106
  end
114
107
  else
115
- throw_custom(error_message("Unexpected end of file"))
108
+ throw_custom("Unexpected end of file")
116
109
  end
117
110
  char = @source.read
118
111
  return char
@@ -121,7 +114,7 @@ class Zenithal::Parser
121
114
  def parse_eof
122
115
  char = @source.peek
123
116
  if char
124
- throw_custom(error_message("Document ends before reaching end of file"))
117
+ throw_custom("Document ends before reaching end of file")
125
118
  end
126
119
  char = @source.read
127
120
  return true
@@ -129,7 +122,7 @@ class Zenithal::Parser
129
122
 
130
123
  # Parses nothing; thus an error always occur.
131
124
  def parse_none
132
- throw_custom(error_message("This cannot happen"))
125
+ throw_custom("This cannot happen")
133
126
  return nil
134
127
  end
135
128
 
@@ -144,7 +137,7 @@ class Zenithal::Parser
144
137
  end
145
138
  unless value
146
139
  @source.reset(mark)
147
- throw_custom(message)
140
+ throw_custom(message, true)
148
141
  end
149
142
  return value
150
143
  end
@@ -165,7 +158,7 @@ class Zenithal::Parser
165
158
  end
166
159
  end
167
160
  unless value
168
- throw_custom(message)
161
+ throw_custom(message, true)
169
162
  end
170
163
  return value
171
164
  end
@@ -190,13 +183,13 @@ class Zenithal::Parser
190
183
  end
191
184
  else
192
185
  if mark != @source.mark
193
- throw_custom(message)
186
+ throw_custom(message, true)
194
187
  end
195
188
  break
196
189
  end
197
190
  end
198
191
  unless count >= lower_limit
199
- throw_custom(message)
192
+ throw_custom(message, true)
200
193
  end
201
194
  return values
202
195
  end
@@ -214,7 +207,10 @@ class Zenithal::Parser
214
207
 
215
208
  # Raises a parse error.
216
209
  # Do not use the standard exception mechanism during parsing, and always use this method to avoid creating an unnecessary stacktrace.
217
- def throw_custom(message)
210
+ def throw_custom(message, raw = false)
211
+ unless raw
212
+ message = error_message(message)
213
+ end
218
214
  throw(ERROR_TAG, message)
219
215
  end
220
216
 
@@ -3,11 +3,13 @@
3
3
 
4
4
  class Zenithal::StringReader
5
5
 
6
+ attr_reader :string
6
7
  attr_reader :lineno
7
8
  attr_reader :columnno
8
9
 
9
10
  def initialize(string)
10
- @string = string.chars
11
+ @string = string
12
+ @chars = string.chars
11
13
  @pos = -1
12
14
  @lineno = 1
13
15
  @columnno = 1
@@ -16,7 +18,7 @@ class Zenithal::StringReader
16
18
  def read
17
19
  @pos += 1
18
20
  @columnno += 1
19
- char = @string[@pos]
21
+ char = @chars[@pos]
20
22
  if char == "\n"
21
23
  @lineno += 1
22
24
  @columnno = 1
@@ -25,7 +27,7 @@ class Zenithal::StringReader
25
27
  end
26
28
 
27
29
  def peek
28
- char = @string[@pos + 1]
30
+ char = @chars[@pos + 1]
29
31
  return char
30
32
  end
31
33
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zenml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ziphil
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-15 00:00:00.000000000 Z
11
+ date: 2020-04-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  This gem serves a tool for parsing a document written in ZenML, an alternative new syntax for XML, to an XML node tree.