zenml 1.5.1 → 1.6.0

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