term_utils 0.3.2 → 0.5.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/CHANGELOG.md +16 -2
- data/COPYING +3 -3
- data/README.md +51 -16
- data/Rakefile +6 -0
- data/doc/TermUtils/AP/Article.html +57 -55
- data/doc/TermUtils/AP/ArticleResult.html +584 -0
- data/doc/TermUtils/AP/Flag.html +295 -78
- data/doc/TermUtils/AP/Parameter.html +891 -103
- data/doc/TermUtils/AP/ParameterResult.html +980 -0
- data/doc/TermUtils/{FF/Cursor/Context.html → AP/ParameterWalkerHooks.html} +60 -60
- data/doc/TermUtils/AP/ParseError.html +651 -19
- data/doc/TermUtils/AP/Parser.html +181 -121
- data/doc/TermUtils/AP/Result.html +201 -528
- data/doc/TermUtils/AP/Syntax.html +103 -393
- data/doc/TermUtils/AP/SyntaxError.html +9 -91
- data/doc/TermUtils/AP/Walker.html +686 -0
- data/doc/TermUtils/AP.html +49 -160
- data/doc/TermUtils/FF/Config.html +203 -35
- data/doc/TermUtils/FF/Context.html +585 -0
- data/doc/TermUtils/FF/Entry.html +626 -0
- data/doc/TermUtils/FF/Finder.html +850 -0
- data/doc/TermUtils/FF/{Cursor.html → FinderEntry.html} +473 -211
- data/doc/TermUtils/FF/FinderQuery.html +946 -0
- data/doc/TermUtils/FF/Query.html +402 -70
- data/doc/TermUtils/FF.html +135 -11
- data/doc/TermUtils/PropertyTreeNode.html +304 -190
- data/doc/TermUtils/Tab/Column.html +98 -96
- data/doc/TermUtils/Tab/Header.html +30 -30
- data/doc/TermUtils/Tab/Holder.html +81 -81
- data/doc/TermUtils/Tab/Printer.html +43 -43
- data/doc/TermUtils/Tab/Table.html +124 -128
- data/doc/TermUtils/Tab/TableError.html +7 -89
- data/doc/TermUtils/Tab.html +93 -86
- data/doc/TermUtils.html +10 -10
- data/doc/_index.html +62 -42
- data/doc/class_list.html +3 -3
- data/doc/css/style.css +3 -2
- data/doc/file.README.html +63 -26
- data/doc/file_list.html +2 -2
- data/doc/frames.html +2 -2
- data/doc/index.html +63 -26
- data/doc/js/app.js +14 -3
- data/doc/method_list.html +708 -236
- data/doc/top-level-namespace.html +7 -7
- data/lib/term_utils/ap/article.rb +15 -9
- data/lib/term_utils/ap/flag.rb +37 -20
- data/lib/term_utils/ap/parameter.rb +88 -19
- data/lib/term_utils/ap/parser.rb +143 -116
- data/lib/term_utils/ap/result.rb +208 -161
- data/lib/term_utils/ap/syntax.rb +53 -69
- data/lib/term_utils/ap.rb +79 -24
- data/lib/term_utils/ff/config.rb +22 -10
- data/lib/term_utils/{ap/no_such_value_error.rb → ff/entry.rb} +26 -8
- data/lib/term_utils/ff/finder.rb +255 -0
- data/lib/term_utils/ff/query.rb +94 -17
- data/lib/term_utils/ff.rb +12 -2
- data/lib/term_utils/property_tree_node.rb +47 -19
- data/lib/term_utils/tab.rb +106 -61
- data/lib/term_utils.rb +8 -1
- data/term_utils.gemspec +4 -4
- metadata +18 -17
- data/doc/TermUtils/AP/Element.html +0 -1025
- data/doc/TermUtils/AP/Level.html +0 -638
- data/doc/TermUtils/AP/NoSuchValueError.html +0 -217
- data/lib/term_utils/ap/element.rb +0 -78
- data/lib/term_utils/ap/level.rb +0 -57
- data/lib/term_utils/ap/parse_error.rb +0 -27
- data/lib/term_utils/ap/syntax_error.rb +0 -27
- data/lib/term_utils/ff/cursor.rb +0 -153
@@ -6,15 +6,15 @@
|
|
6
6
|
<title>
|
7
7
|
Top Level Namespace
|
8
8
|
|
9
|
-
— Documentation by YARD 0.9.
|
9
|
+
— Documentation by YARD 0.9.34
|
10
10
|
|
11
11
|
</title>
|
12
12
|
|
13
|
-
<link rel="stylesheet" href="css/style.css" type="text/css"
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" />
|
14
14
|
|
15
|
-
<link rel="stylesheet" href="css/common.css" type="text/css"
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" />
|
16
16
|
|
17
|
-
<script type="text/javascript"
|
17
|
+
<script type="text/javascript">
|
18
18
|
pathId = "";
|
19
19
|
relpath = '';
|
20
20
|
</script>
|
@@ -100,9 +100,9 @@
|
|
100
100
|
</div>
|
101
101
|
|
102
102
|
<div id="footer">
|
103
|
-
Generated on
|
104
|
-
<a href="
|
105
|
-
0.9.
|
103
|
+
Generated on Wed Aug 9 17:34:25 2023 by
|
104
|
+
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
|
+
0.9.34 (ruby-3.2.2).
|
106
106
|
</div>
|
107
107
|
|
108
108
|
</div>
|
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (C)
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2023 Thomas Baron
|
4
4
|
#
|
5
5
|
# This file is part of term_utils.
|
6
6
|
#
|
@@ -15,6 +15,7 @@
|
|
15
15
|
#
|
16
16
|
# You should have received a copy of the GNU General Public License
|
17
17
|
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
|
18
19
|
module TermUtils
|
19
20
|
module AP
|
20
21
|
# Represents a Article.
|
@@ -29,6 +30,7 @@ module TermUtils
|
|
29
30
|
attr_accessor :type
|
30
31
|
# @return [String] `%d`, `%s`.
|
31
32
|
attr_accessor :format
|
33
|
+
|
32
34
|
# Constructs a new Article.
|
33
35
|
# @param opts [Hash]
|
34
36
|
# @option opts [Symbol] :id
|
@@ -41,27 +43,31 @@ module TermUtils
|
|
41
43
|
@min_occurs = opts.fetch(:min_occurs, 1)
|
42
44
|
@max_occurs = opts.fetch(:max_occurs, 1)
|
43
45
|
@type = opts.fetch(:type, :string)
|
44
|
-
@format = opts.fetch(:format,
|
46
|
+
@format = opts.fetch(:format, '%s')
|
45
47
|
end
|
48
|
+
|
46
49
|
# Finalizes this one. Internal use.
|
47
50
|
# @return [nil]
|
48
51
|
def finalize!(opts = {})
|
49
|
-
raise TermUtils::AP::SyntaxError,
|
50
|
-
raise TermUtils::AP::SyntaxError,
|
52
|
+
raise TermUtils::AP::SyntaxError, 'min_occurs must be equal or greater than 0' if !@min_occurs.is_a?(Integer) || (@min_occurs < 0)
|
53
|
+
raise TermUtils::AP::SyntaxError, 'max_occurs must be equal or greater than min_occurs' if occur_bounded? && (@max_occurs < @min_occurs)
|
54
|
+
|
51
55
|
unless @id
|
52
56
|
opts[:anonymous] += 1
|
53
57
|
@id = "anonymous#{opts[:anonymous]}".intern
|
54
58
|
end
|
55
59
|
end
|
60
|
+
|
56
61
|
# Tests whether this one has mutiple occurs.
|
57
62
|
# @return [Boolean]
|
58
63
|
def multiple_occurs?
|
59
|
-
(@max_occurs == nil) || (@max_occurs
|
64
|
+
(@max_occurs == nil) || (@max_occurs.is_a?(Integer) && (@max_occurs > 1))
|
60
65
|
end
|
61
|
-
|
66
|
+
|
67
|
+
# Tests whether the number of occurs is fixed.
|
62
68
|
# @return [Boolean]
|
63
69
|
def occur_bounded?
|
64
|
-
(@max_occurs != nil) &&
|
70
|
+
(@max_occurs != nil) && @max_occurs.is_a?(Integer)
|
65
71
|
end
|
66
72
|
end
|
67
73
|
end
|
data/lib/term_utils/ap/flag.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (C)
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2023 Thomas Baron
|
4
4
|
#
|
5
5
|
# This file is part of term_utils.
|
6
6
|
#
|
@@ -15,33 +15,50 @@
|
|
15
15
|
#
|
16
16
|
# You should have received a copy of the GNU General Public License
|
17
17
|
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
|
18
19
|
module TermUtils
|
19
20
|
module AP
|
20
21
|
# Represents a Flag.
|
21
22
|
class Flag
|
22
23
|
# @return [String]
|
23
|
-
|
24
|
-
# @return [Symbol] `:
|
25
|
-
|
24
|
+
attr_reader :label
|
25
|
+
# @return [Symbol] `:long`, `:short`.
|
26
|
+
attr_reader :flavor
|
27
|
+
|
26
28
|
# Constructs a new Flag.
|
27
|
-
# @param
|
28
|
-
# @
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
# @param label [String]
|
30
|
+
# @param flavor [Symbol] `:short`, `:long`.
|
31
|
+
def initialize(label, flavor)
|
32
|
+
raise TermUtils::AP::SyntaxError, 'wrong flag label' if !label.is_a?(String) || /^-+$/.match?(label) || !/^-[0-9A-Za-z_-]+$/.match?(label)
|
33
|
+
raise TermUtils::AP::SyntaxError, '' unless %i[short long].include?(flavor)
|
34
|
+
|
35
|
+
@label = label
|
36
|
+
@flavor = flavor
|
37
|
+
end
|
38
|
+
|
39
|
+
# Tests whether this one is equal to a given Flag.
|
40
|
+
def ==(other)
|
41
|
+
return false unless other.is_a?(TermUtils::AP::Flag)
|
42
|
+
|
43
|
+
@label == other.label
|
44
|
+
end
|
45
|
+
|
46
|
+
# Tests whether this one represents a long flag.
|
47
|
+
# @return [Boolean]
|
48
|
+
def long?
|
49
|
+
@flavor == :long
|
50
|
+
end
|
51
|
+
|
52
|
+
# Tests whether this one represents a short flag.
|
53
|
+
# @return [Boolean]
|
54
|
+
def short?
|
55
|
+
@flavor == :short
|
33
56
|
end
|
57
|
+
|
34
58
|
# Returns the string representation of this one.
|
35
59
|
# @return [String]
|
36
60
|
def to_s
|
37
|
-
|
38
|
-
when :anchor
|
39
|
-
@label
|
40
|
-
when :long
|
41
|
-
"--%s" % @label
|
42
|
-
when :short
|
43
|
-
"-%s" % @label
|
44
|
-
end
|
61
|
+
@label
|
45
62
|
end
|
46
63
|
end
|
47
64
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (C)
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2023 Thomas Baron
|
4
4
|
#
|
5
5
|
# This file is part of term_utils.
|
6
6
|
#
|
@@ -15,12 +15,22 @@
|
|
15
15
|
#
|
16
16
|
# You should have received a copy of the GNU General Public License
|
17
17
|
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
|
18
19
|
module TermUtils
|
19
20
|
module AP
|
20
21
|
# Represents a Parameter.
|
21
|
-
class Parameter
|
22
|
-
# @return [
|
22
|
+
class Parameter
|
23
|
+
# @return [Symbol]
|
24
|
+
attr_accessor :id
|
25
|
+
# @return [Integer]
|
26
|
+
attr_accessor :min_occurs
|
27
|
+
# @return [Integer]
|
28
|
+
attr_accessor :max_occurs
|
29
|
+
# @return [Array<Flag>]
|
30
|
+
attr_accessor :flags
|
31
|
+
# @return [Array<Article>]
|
23
32
|
attr_accessor :articles
|
33
|
+
|
24
34
|
# Constructs a new Parameter.
|
25
35
|
# @param opts [Hash]
|
26
36
|
# @option opts [Symbol] :id
|
@@ -33,42 +43,101 @@ module TermUtils
|
|
33
43
|
@flags = []
|
34
44
|
@articles = []
|
35
45
|
end
|
46
|
+
|
36
47
|
# For dup method.
|
37
48
|
def initialize_dup(other)
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
@articles << a.dup
|
42
|
-
end
|
43
|
-
end
|
44
|
-
super
|
49
|
+
super(other)
|
50
|
+
@flags = other.flags.map(&:dup) if other.flags
|
51
|
+
@articles = other.articles.map(&:dup) if other.articles
|
45
52
|
end
|
53
|
+
|
46
54
|
# Finalizes this one. Internal use.
|
47
55
|
# @return [nil]
|
56
|
+
# @raise [SyntaxError]
|
48
57
|
def finalize!(opts = {})
|
49
|
-
|
50
|
-
@
|
51
|
-
|
58
|
+
raise TermUtils::AP::SyntaxError, 'min_occurs must be equal or greater than 0' if !@min_occurs.is_a?(Integer) || (@min_occurs < 0)
|
59
|
+
raise TermUtils::AP::SyntaxError, 'max_occurs must be equal or greater than min_occurs' if occur_bounded? && (@max_occurs < @min_occurs)
|
60
|
+
raise TermUtils::AP::SyntaxError, 'empty' if @flags.empty? && @articles.empty?
|
61
|
+
|
62
|
+
unless @id
|
63
|
+
opts[:anonymous] += 1
|
64
|
+
@id = "anonymous#{opts[:anonymous]}".intern
|
52
65
|
end
|
66
|
+
@flags.each do |f|
|
67
|
+
raise TermUtils::AP::SyntaxError, 'duplicate flag label' if opts[:flag_labels].include?(f.to_s)
|
68
|
+
|
69
|
+
opts[:flag_labels] << f.to_s
|
70
|
+
end
|
71
|
+
@articles.each { |a| a.finalize!(opts) }
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
# Tests whether this one has mutiple occurs.
|
76
|
+
# @return [Boolean]
|
77
|
+
def multiple_occurs?
|
78
|
+
(@max_occurs == nil) || (@max_occurs.is_a?(Integer) && (@max_occurs > 1))
|
79
|
+
end
|
80
|
+
|
81
|
+
# Tests whether the number of occurs is fixed.
|
82
|
+
# @return [Boolean]
|
83
|
+
def occur_bounded?
|
84
|
+
(@max_occurs != nil) && @max_occurs.is_a?(Integer)
|
53
85
|
end
|
86
|
+
|
87
|
+
# Tests whether this one is flagged.
|
88
|
+
# @return [Boolean]
|
89
|
+
def flagged?
|
90
|
+
!@flags.empty?
|
91
|
+
end
|
92
|
+
|
93
|
+
# Adds a new Flag to this one.
|
94
|
+
# @param label [String]
|
95
|
+
# @return [Flag]
|
96
|
+
def define_flag(label, &block)
|
97
|
+
flavor = (label.length == 2) ? :short : :long
|
98
|
+
new_flag = TermUtils::AP::Flag.new(label, flavor)
|
99
|
+
raise TermUtils::AP::SyntaxError, 'duplicate flag label' if @flags.include? new_flag
|
100
|
+
|
101
|
+
@flags << new_flag
|
102
|
+
block.call(new_flag) if block
|
103
|
+
new_flag
|
104
|
+
end
|
105
|
+
|
54
106
|
# Adds a new Article to this one.
|
107
|
+
# @param id [Symbol, nil]
|
55
108
|
# @param opts [Hash]
|
56
109
|
# @option opts [Symbol] :id
|
57
110
|
# @option opts [Integer] :min_occurs Default value is `1`.
|
58
111
|
# @option opts [Integer] :max_occurs Default value is `1`.
|
59
112
|
# @option opts [Symbol] :type `:integer`, `:string`.
|
60
113
|
# @option opts [Symbol] :format
|
61
|
-
# @return [
|
62
|
-
def define_article(opts = {}, &block)
|
114
|
+
# @return [Article]
|
115
|
+
def define_article(id = nil, opts = {}, &block)
|
116
|
+
if id
|
117
|
+
art = @articles.find { |p| p.id == id }
|
118
|
+
if art
|
119
|
+
block.call(art) if block
|
120
|
+
return art
|
121
|
+
end
|
122
|
+
|
123
|
+
opts[:id] = id
|
124
|
+
end
|
63
125
|
new_article = TermUtils::AP::Article.new(opts)
|
64
126
|
@articles << new_article
|
65
127
|
block.call(new_article) if block
|
66
128
|
new_article
|
67
129
|
end
|
130
|
+
|
131
|
+
# Fetches all flags.
|
132
|
+
# @return [Array<Flag>]
|
133
|
+
def fetch_flags
|
134
|
+
@flags.dup
|
135
|
+
end
|
136
|
+
|
68
137
|
# Fetches all articles.
|
69
|
-
# @return [Array<
|
138
|
+
# @return [Array<Article>]
|
70
139
|
def fetch_articles
|
71
|
-
@articles.collect
|
140
|
+
@articles.collect(&:dup)
|
72
141
|
end
|
73
142
|
end
|
74
143
|
end
|
data/lib/term_utils/ap/parser.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Copyright (C)
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (C) 2023 Thomas Baron
|
4
4
|
#
|
5
5
|
# This file is part of term_utils.
|
6
6
|
#
|
@@ -15,170 +15,197 @@
|
|
15
15
|
#
|
16
16
|
# You should have received a copy of the GNU General Public License
|
17
17
|
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
|
18
19
|
module TermUtils
|
19
20
|
module AP
|
20
21
|
# Represents the argument list parser.
|
21
22
|
class Parser
|
23
|
+
# Constructs a new Parser.
|
22
24
|
def initialize
|
23
25
|
end
|
24
|
-
|
25
|
-
# @param syntax [TermUtils::AP::Syntax]
|
26
|
-
# @param command [String]
|
27
|
-
# @param opts [Hash] `:program`.
|
28
|
-
# @option opts [Boolean] :program Whether the first argument is the program name.
|
29
|
-
# @return [TermUtils::AP::Result]
|
30
|
-
# @raise [TermUtils::AP::ParseError]
|
31
|
-
# @raise [TermUtils::AP::SyntaxError]
|
32
|
-
def parse_command(syntax, command, opts = {})
|
33
|
-
parse_arguments(syntax, command.split(" "), opts)
|
34
|
-
end
|
26
|
+
|
35
27
|
# Parses a given list of arguments.
|
36
|
-
# @param syntax [
|
28
|
+
# @param syntax [Syntax]
|
37
29
|
# @param arguments [Array<String>]
|
38
|
-
# @param opts [Hash]
|
39
|
-
# @option opts [Boolean] :
|
40
|
-
# @return [
|
41
|
-
# @raise [
|
42
|
-
# @raise [
|
43
|
-
def parse_arguments(syntax, arguments, opts = {})
|
30
|
+
# @param opts [Hash<Symbol, Object>]
|
31
|
+
# @option opts [Boolean] :strict Whether the Syntax must be considered as strict.
|
32
|
+
# @return [Result]
|
33
|
+
# @raise [ParseError]
|
34
|
+
# @raise [SyntaxError]
|
35
|
+
def parse_arguments(syntax, arguments, opts = {}, &block)
|
44
36
|
syntax = syntax.dup
|
45
37
|
syntax.finalize!
|
46
38
|
arguments = arguments.dup
|
47
39
|
res = TermUtils::AP::Result.new(syntax)
|
48
40
|
catch :done do
|
49
|
-
parse0(res
|
41
|
+
parse0(res, syntax, arguments, opts)
|
50
42
|
end
|
43
|
+
res.remaining_arguments = arguments
|
44
|
+
res.walk(&block) if block
|
51
45
|
res
|
52
46
|
end
|
47
|
+
|
48
|
+
# Tests whether a given sample matches a shortcut flag.
|
49
|
+
# @param shortcut_flags [Hash<String, Flag>]
|
50
|
+
# @param arg [String]
|
51
|
+
# @return [Array<String>, nil] Replacements on success, nil otherwise.
|
52
|
+
def self.match_shortcut_flag(shortcut_flags, arg)
|
53
|
+
shortcut_flags.each do |label, flag|
|
54
|
+
next unless arg.start_with? label
|
55
|
+
|
56
|
+
return [flag.label, arg[label.length..]]
|
57
|
+
end
|
58
|
+
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
# Evaluates the added number of min occurs of a given array of articles.
|
63
|
+
# @param articles [Array<TermUtils::AP::Article>]
|
64
|
+
# @return [Integer]
|
65
|
+
def self.eval_article_min_occurs(articles)
|
66
|
+
articles.inject(0) { |acc, a| acc + a.min_occurs }
|
67
|
+
end
|
68
|
+
|
53
69
|
private
|
70
|
+
|
54
71
|
# Parses a given argument list.
|
55
|
-
# @param
|
56
|
-
# @param syntax [
|
72
|
+
# @param result [Result]
|
73
|
+
# @param syntax [Syntax]
|
57
74
|
# @param arguments [Array<String>]
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
if opts[:program]
|
62
|
-
arguments.shift
|
63
|
-
opts.delete :program
|
64
|
-
end
|
65
|
-
throw :done if arguments.empty?
|
66
|
-
flagged_elems, unflagged_params = syntax.fetch_elements
|
75
|
+
# @raise [ParseError]
|
76
|
+
def parse0(result, syntax, arguments, opts = {})
|
77
|
+
unflagged_params, flagged_params, shortcut_flags = syntax.fetch_parameters
|
67
78
|
fp_occ = {}
|
68
|
-
syntax.
|
79
|
+
syntax.parameters.each { |p| fp_occ[p.id] = 0 if p.flagged? }
|
69
80
|
up_occ = 0
|
70
81
|
loop do
|
71
82
|
break if arguments.empty?
|
72
|
-
|
73
|
-
if arguments.first
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
sub_node = node.child_node(elem.id)
|
85
|
-
sub_node = node.define_node(:key => elem.id) unless sub_node
|
86
|
-
if elem.multiple_occurs?
|
87
|
-
sub_node.child_nodes = [] if sub_node.leaf?
|
88
|
-
idx = sub_node.child_nodes.length
|
89
|
-
sub_node = sub_node.define_node(:key => idx)
|
90
|
-
end
|
91
|
-
catch :param_done do
|
92
|
-
parse0_param(sub_node, elem, arguments, opts)
|
83
|
+
|
84
|
+
if arguments.first.start_with?('-') && !%w[- --].include?(arguments.first)
|
85
|
+
# Flagged
|
86
|
+
unless flagged_params.key? arguments.first
|
87
|
+
# Unknown flag
|
88
|
+
# Try shortcut flag
|
89
|
+
flag, arg = self.class.match_shortcut_flag(shortcut_flags, arguments.first)
|
90
|
+
if flag && arg
|
91
|
+
# Shortcut match
|
92
|
+
arguments.shift
|
93
|
+
arguments.unshift arg
|
94
|
+
arguments.unshift flag
|
93
95
|
end
|
94
|
-
elsif elem.is_a? TermUtils::AP::Level
|
95
|
-
arguments.shift
|
96
|
-
sub_node = node.child_node(elem.id)
|
97
|
-
sub_node = node.define_node(:key => elem.id) unless sub_node
|
98
|
-
if elem.multiple_occurs?
|
99
|
-
sub_node.child_nodes = [] if sub_node.leaf?
|
100
|
-
idx = sub_node.child_nodes.length
|
101
|
-
sub_node = sub_node.define_node(:key => idx)
|
102
|
-
end
|
103
|
-
parse0(sub_node, elem.syntax, arguments, opts)
|
104
|
-
else
|
105
|
-
raise TermUtils::AP::ParseError, "internal error - wrong kind of syntax element"
|
106
96
|
end
|
97
|
+
unless flagged_params.key? arguments.first
|
98
|
+
# Unknown flag
|
99
|
+
# End of parsing
|
100
|
+
raise TermUtils::AP::ParseError.new(message: 'flagged parameter unexpected', fault: arguments.first) if opts.fetch(:strict, false)
|
101
|
+
|
102
|
+
break
|
103
|
+
end
|
104
|
+
|
105
|
+
param = flagged_params[arguments.first]
|
106
|
+
if param.occur_bounded? && (fp_occ[param.id] >= param.max_occurs)
|
107
|
+
# Max occurs reached
|
108
|
+
raise TermUtils::AP::ParseError.new(message: 'occur limit reached', parameter: param.id, fault: arguments.first) if opts.fetch(:strict, false)
|
109
|
+
|
110
|
+
break
|
111
|
+
end
|
112
|
+
|
113
|
+
fp_occ[param.id] += 1
|
114
|
+
arguments.shift
|
115
|
+
param_res = TermUtils::AP::ParameterResult.new(result, param)
|
116
|
+
parse0_param(param_res, param, arguments)
|
107
117
|
else
|
108
|
-
# Unflagged
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
if elem.multiple_occurs?
|
115
|
-
sub_node.child_nodes = [] if sub_node.leaf?
|
116
|
-
idx = sub_node.child_nodes.length
|
117
|
-
sub_node = sub_node.define_node(:key => idx)
|
118
|
+
# Unflagged
|
119
|
+
if unflagged_params.empty?
|
120
|
+
# End of parsing
|
121
|
+
raise TermUtils::AP::ParseError.new(message: 'unflagged parameter unexpected', fault: arguments.first) if opts.fetch(:strict, false)
|
122
|
+
|
123
|
+
break
|
118
124
|
end
|
119
|
-
|
120
|
-
|
125
|
+
|
126
|
+
param = unflagged_params.first
|
127
|
+
if arguments.first == '--'
|
128
|
+
# End of parameter
|
129
|
+
raise TermUtils::AP::ParseError.new(message: 'parameter not consumed', parameter: param.id) if up_occ < param.min_occurs
|
130
|
+
|
131
|
+
arguments.shift
|
132
|
+
unflagged_params.shift
|
121
133
|
up_occ = 0
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
134
|
+
next
|
135
|
+
end
|
136
|
+
|
137
|
+
up_occ += 1
|
138
|
+
param_res = TermUtils::AP::ParameterResult.new(result, param)
|
139
|
+
case parse0_param(param_res, param, arguments)
|
140
|
+
when :esc_param
|
141
|
+
raise TermUtils::AP::ParseError.new(message: 'parameter not consumed', parameter: param.id) if up_occ < param.min_occurs
|
142
|
+
|
143
|
+
unflagged_params.shift
|
144
|
+
up_occ = 0
|
145
|
+
else
|
146
|
+
if !param.multiple_occurs? || (param.occur_bounded? && (up_occ >= param.max_occurs))
|
147
|
+
unflagged_params.shift
|
128
148
|
up_occ = 0
|
129
149
|
end
|
130
150
|
end
|
131
151
|
end
|
132
152
|
end # loop
|
153
|
+
# Check min occurs
|
154
|
+
syntax.parameters.each do |p|
|
155
|
+
next if result.find_parameters(p.id).length >= p.min_occurs
|
156
|
+
|
157
|
+
raise TermUtils::AP::ParseError.new(message: 'parameter not consumed', parameter: p.id)
|
158
|
+
end
|
133
159
|
end
|
134
|
-
|
160
|
+
|
161
|
+
# Parses with a given Parameter.
|
162
|
+
# @param result [ParameterResult]
|
163
|
+
# @param param [Parameter]
|
164
|
+
# @param arguments [Array<String>]
|
165
|
+
# @return [Symbol, nil] `:esc_param`, or nil.
|
166
|
+
def parse0_param(result, param, arguments)
|
135
167
|
arts = param.fetch_articles
|
136
168
|
occ = 0
|
137
169
|
loop do
|
170
|
+
break if arts.empty?
|
171
|
+
|
138
172
|
if arguments.empty?
|
139
|
-
|
140
|
-
raise TermUtils::AP::ParseError
|
141
|
-
|
173
|
+
# End of arguments
|
174
|
+
raise TermUtils::AP::ParseError.new(message: 'article not consumed', parameter: param.id) if occ < arts.first.min_occurs
|
175
|
+
raise TermUtils::AP::ParseError.new(message: 'article not consumed', parameter: param.id) if self.class.eval_article_min_occurs(arts[1..]) > 0
|
176
|
+
|
177
|
+
break
|
142
178
|
end
|
143
|
-
|
144
|
-
if arguments.first ==
|
145
|
-
# End of
|
146
|
-
raise TermUtils::AP::ParseError
|
147
|
-
|
148
|
-
arguments.shift
|
149
|
-
throw :param_done
|
150
|
-
elsif arguments.first == "-"
|
151
|
-
# End of article.
|
152
|
-
raise TermUtils::AP::ParseError, "unexpected article escape" if arts.empty?
|
153
|
-
raise TermUtils::AP::ParseError, "unexpected end of parameter" if !arts.empty? && (occ < arts.first.min_occurs)
|
179
|
+
|
180
|
+
if arguments.first == '-'
|
181
|
+
# End of article
|
182
|
+
raise TermUtils::AP::ParseError.new(message: 'article not consumed', parameter: param.id) if occ < arts.first.min_occurs
|
183
|
+
|
154
184
|
arguments.shift
|
155
185
|
arts.shift
|
156
186
|
occ = 0
|
157
187
|
next
|
188
|
+
elsif arguments.first.start_with? '-'
|
189
|
+
# End of parameter
|
190
|
+
raise TermUtils::AP::ParseError.new(message: 'article not consumed', parameter: param.id) if occ < arts.first.min_occurs
|
191
|
+
raise TermUtils::AP::ParseError.new(message: 'article not consumed', parameter: param.id) if self.class.eval_article_min_occurs(arts[1..]) > 0
|
192
|
+
|
193
|
+
if arguments.first == '--'
|
194
|
+
arguments.shift
|
195
|
+
return :esc_param
|
196
|
+
end
|
197
|
+
|
198
|
+
break
|
158
199
|
end
|
159
200
|
art = arts.first
|
160
|
-
|
161
|
-
sub_node = node.define_node(:key => art.id) unless sub_node
|
162
|
-
if art.multiple_occurs?
|
163
|
-
sub_node.child_nodes = [] if sub_node.leaf?
|
164
|
-
idx = sub_node.child_nodes.length
|
165
|
-
sub_node = sub_node.define_node(:key => idx)
|
166
|
-
end
|
167
|
-
sub_node.value = arguments.shift
|
201
|
+
TermUtils::AP::ArticleResult.new(result, art, arguments.shift)
|
168
202
|
occ += 1
|
169
203
|
if !art.multiple_occurs? || (art.occur_bounded? && (occ >= art.max_occurs))
|
170
204
|
arts.shift
|
171
205
|
occ = 0
|
172
206
|
end
|
173
207
|
end # loop
|
174
|
-
|
175
|
-
# Evaluates the added number of min occurs of a given array of articles.
|
176
|
-
# @param articles [Array<TermUtils::AP::Article>]
|
177
|
-
# @return [Integer]
|
178
|
-
def self.eval_article_min_occurs(articles)
|
179
|
-
occs = 0
|
180
|
-
articles.each { |a| occs += a.min_occurs }
|
181
|
-
occs
|
208
|
+
nil
|
182
209
|
end
|
183
210
|
end
|
184
211
|
end
|