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 +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.
|