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 +4 -4
- data/source/zenml.rb +1 -1
- data/source/zenml/parser.rb +77 -26
- data/source/zenml/parser_utility.rb +17 -21
- data/source/zenml/reader.rb +5 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eeb3297631724f74bcfbcea67c59f71f4131a6d142f3b98c86cbb0836368d1ad
|
4
|
+
data.tar.gz: '029b4e2b8eadea4a68b23b721d46ed3546d25269fb927ddd729781f7a67ae02f'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ccb7bae3fc78b5361aa8f951eaca5f34bcd0c3a96fcf59a63a87931fdbdccdd784ed7174deaa3db2f87aa917383ed8f056150f342813eb1e1b5950ce4bde91e
|
7
|
+
data.tar.gz: d725803a7cd455c0a6e2fa1bdabe0ffb37c3e37620252703dda7261fa8c58652f3e67cbb2a75b00ec00d113f90e1d8b73a456cb9d18dd0a3f7658e7dd033006a
|
data/source/zenml.rb
CHANGED
data/source/zenml/parser.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
-
|
192
|
-
|
193
|
-
|
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
|
-
|
206
|
-
|
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
|
-
|
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(
|
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(
|
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(
|
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(
|
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(
|
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 =
|
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
|
-
|
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(
|
78
|
+
throw_custom(message)
|
86
79
|
end
|
87
80
|
else
|
88
|
-
throw_custom(
|
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(
|
105
|
+
throw_custom("Expected other than #{chars_string} but got '#{char}'")
|
113
106
|
end
|
114
107
|
else
|
115
|
-
throw_custom(
|
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(
|
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(
|
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
|
|
data/source/zenml/reader.rb
CHANGED
@@ -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
|
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 = @
|
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 = @
|
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.
|
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-
|
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.
|