term_utils 0.2.0 → 0.3.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 +6 -0
- data/COPYING +3 -3
- data/README.md +7 -1
- data/doc/TermUtils/AP/Article.html +991 -0
- data/doc/TermUtils/AP/Element.html +1025 -0
- data/doc/TermUtils/AP/Flag.html +539 -0
- data/doc/TermUtils/AP/Level.html +638 -0
- data/doc/TermUtils/AP/NoSuchValueError.html +217 -0
- data/doc/TermUtils/AP/Parameter.html +804 -0
- data/doc/TermUtils/AP/ParseError.html +217 -0
- data/doc/TermUtils/AP/Parser.html +572 -0
- data/doc/TermUtils/AP/Result.html +1029 -0
- data/doc/TermUtils/AP/ResultView.html +597 -0
- data/doc/TermUtils/AP/Syntax.html +1051 -0
- data/doc/TermUtils/AP/SyntaxError.html +217 -0
- data/doc/TermUtils/AP.html +505 -0
- data/doc/TermUtils/FF/Config.html +1 -1
- data/doc/TermUtils/FF/Cursor/Context.html +1 -1
- data/doc/TermUtils/FF/Cursor.html +1 -1
- data/doc/TermUtils/FF/Query.html +1 -1
- data/doc/TermUtils/FF.html +1 -1
- data/doc/TermUtils/PropertyTreeNode.html +1999 -0
- data/doc/TermUtils/Tab/Column.html +1 -1
- data/doc/TermUtils/Tab/Holder.html +1 -1
- data/doc/TermUtils/Tab/Printer.html +1 -1
- data/doc/TermUtils/Tab/Table.html +1 -1
- data/doc/TermUtils/Tab.html +1 -1
- data/doc/TermUtils.html +5 -3
- data/doc/_index.html +143 -1
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +8 -2
- data/doc/index.html +8 -2
- data/doc/method_list.html +638 -22
- data/doc/top-level-namespace.html +1 -1
- data/lib/term_utils/ap/article.rb +68 -0
- data/lib/term_utils/ap/element.rb +78 -0
- data/lib/term_utils/ap/flag.rb +48 -0
- data/lib/term_utils/ap/level.rb +57 -0
- data/lib/term_utils/ap/no_such_value_error.rb +27 -0
- data/lib/term_utils/ap/parameter.rb +75 -0
- data/lib/term_utils/ap/parse_error.rb +27 -0
- data/lib/term_utils/ap/parser.rb +185 -0
- data/lib/term_utils/ap/result.rb +175 -0
- data/lib/term_utils/ap/syntax.rb +112 -0
- data/lib/term_utils/ap/syntax_error.rb +27 -0
- data/lib/term_utils/ap.rb +59 -0
- data/lib/term_utils/property_tree_node.rb +200 -0
- data/lib/term_utils.rb +1 -0
- data/term_utils.gemspec +2 -2
- metadata +29 -2
@@ -100,7 +100,7 @@
|
|
100
100
|
</div>
|
101
101
|
|
102
102
|
<div id="footer">
|
103
|
-
Generated on
|
103
|
+
Generated on Sun Nov 10 18:36:19 2019 by
|
104
104
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
105
|
0.9.20 (ruby-2.6.5).
|
106
106
|
</div>
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Represents a Article.
|
21
|
+
class Article
|
22
|
+
# @return [Symbol]
|
23
|
+
attr_accessor :id
|
24
|
+
# @return [Integer]
|
25
|
+
attr_accessor :min_occurs
|
26
|
+
# @return [Integer]
|
27
|
+
attr_accessor :max_occurs
|
28
|
+
# @return [Symbol] `:integer`, `:string`
|
29
|
+
attr_accessor :type
|
30
|
+
# @return [String] `%d`, `%s`.
|
31
|
+
attr_accessor :format
|
32
|
+
# Constructs a new Article.
|
33
|
+
# @param opts [Hash]
|
34
|
+
# @option opts [Symbol] :id
|
35
|
+
# @option opts [Integer] :min_occurs Default value is `1`.
|
36
|
+
# @option opts [Integer] :max_occurs Default value is `1`.
|
37
|
+
# @option opts [Symbol] :type `:integer`, `:string`.
|
38
|
+
# @option opts [Symbol] :format
|
39
|
+
def initialize(opts = {})
|
40
|
+
@id = opts.fetch(:id, nil)
|
41
|
+
@min_occurs = opts.fetch(:min_occurs, 1)
|
42
|
+
@max_occurs = opts.fetch(:max_occurs, 1)
|
43
|
+
@type = opts.fetch(:type, :string)
|
44
|
+
@format = opts.fetch(:format, "%s")
|
45
|
+
end
|
46
|
+
# Finalizes this one. Internal use.
|
47
|
+
# @return [nil]
|
48
|
+
def finalize!(opts = {})
|
49
|
+
raise TermUtils::AP::SyntaxError, "min_occurs must be equal or greater than 0" unless (@min_occurs.is_a? Integer) && (@min_occurs >= 0)
|
50
|
+
raise TermUtils::AP::SyntaxError, "max_occurs must be equal or greater than min_occurs" unless !occur_bounded? || (@max_occurs >= @min_occurs)
|
51
|
+
unless @id
|
52
|
+
opts[:anonymous] += 1
|
53
|
+
@id = "anonymous#{opts[:anonymous]}".intern
|
54
|
+
end
|
55
|
+
end
|
56
|
+
# Tests whether this one has mutiple occurs.
|
57
|
+
# @return [Boolean]
|
58
|
+
def multiple_occurs?
|
59
|
+
(@max_occurs == nil) || (@max_occurs == :infinity) || ((@max_occurs.is_a? Integer) && (@max_occurs > 1))
|
60
|
+
end
|
61
|
+
# Tests whether the number of occurs are fixed.
|
62
|
+
# @return [Boolean]
|
63
|
+
def occur_bounded?
|
64
|
+
(@max_occurs != nil) && (@max_occurs != :infinity) && (@max_occurs.is_a? Integer)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Represents a syntax element (abstract).
|
21
|
+
class Element
|
22
|
+
# @return [Symbol]
|
23
|
+
attr_accessor :id
|
24
|
+
# @return [Integer]
|
25
|
+
attr_accessor :min_occurs
|
26
|
+
# @return [Integer]
|
27
|
+
attr_accessor :max_occurs
|
28
|
+
# @return [Array<TermUtils::AP::Flag>]
|
29
|
+
attr_accessor :flags
|
30
|
+
# For dup method.
|
31
|
+
def initialize_dup(other)
|
32
|
+
if other.flags
|
33
|
+
@flags = []
|
34
|
+
other.flags.each do |f|
|
35
|
+
@flags << f.dup
|
36
|
+
end
|
37
|
+
end
|
38
|
+
super
|
39
|
+
end
|
40
|
+
# Finalizes this one. Internal use.
|
41
|
+
# @return [nil]
|
42
|
+
def finalize!(opts = {})
|
43
|
+
raise TermUtils::AP::SyntaxError, "min_occurs must be equal or greater than 0" unless (@min_occurs.is_a? Integer) && (@min_occurs >= 0)
|
44
|
+
raise TermUtils::AP::SyntaxError, "max_occurs must be equal or greater than min_occurs" unless !occur_bounded? || (@max_occurs >= @min_occurs)
|
45
|
+
unless @id
|
46
|
+
opts[:anonymous] += 1
|
47
|
+
@id = "anonymous#{opts[:anonymous]}".intern
|
48
|
+
end
|
49
|
+
end
|
50
|
+
# Tests whether this one has mutiple occurs.
|
51
|
+
# @return [Boolean]
|
52
|
+
def multiple_occurs?
|
53
|
+
(@max_occurs == nil) || (@max_occurs == :infinity) || ((@max_occurs.is_a? Integer) && (@max_occurs > 1))
|
54
|
+
end
|
55
|
+
# Tests whether the number of occurs are fixed.
|
56
|
+
# @return [Boolean]
|
57
|
+
def occur_bounded?
|
58
|
+
(@max_occurs != nil) && (@max_occurs != :infinity) && (@max_occurs.is_a? Integer)
|
59
|
+
end
|
60
|
+
# Tests whether this one is flagged.
|
61
|
+
# @return [Boolean]
|
62
|
+
def flagged?
|
63
|
+
!@flags.empty?
|
64
|
+
end
|
65
|
+
# Adds a new Flag to this one.
|
66
|
+
# @param opts [Hash]
|
67
|
+
# @option opts [String] :label
|
68
|
+
# @option opts [Symbol] :flavor `:anchor`, `:long`, `:short`.
|
69
|
+
# @return [TermUtils::AP::Flag]
|
70
|
+
def define_flag(opts = {}, &block)
|
71
|
+
new_flag = TermUtils::AP::Flag.new(opts)
|
72
|
+
@flags << new_flag
|
73
|
+
block.call(new_flag) if block
|
74
|
+
new_flag
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Represents a Flag.
|
21
|
+
class Flag
|
22
|
+
# @return [String]
|
23
|
+
attr_accessor :label
|
24
|
+
# @return [Symbol] `:anchor`, `:long`, `:short`.
|
25
|
+
attr_accessor :flavor
|
26
|
+
# Constructs a new Flag.
|
27
|
+
# @param opts [Hash]
|
28
|
+
# @option opts [String] :label
|
29
|
+
# @option opts [Symbol] :flavor `:anchor`, `:long`, `:short`.
|
30
|
+
def initialize(opts = {})
|
31
|
+
@label = opts.fetch(:label, nil)
|
32
|
+
@flavor = opts.fetch(:flavor, nil)
|
33
|
+
end
|
34
|
+
# Returns the string representation of this one.
|
35
|
+
# @return [String]
|
36
|
+
def to_s
|
37
|
+
case @flavor
|
38
|
+
when :anchor
|
39
|
+
@label
|
40
|
+
when :long
|
41
|
+
"--%s" % @label
|
42
|
+
when :short
|
43
|
+
"-%s" % @label
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Represents an argument list subset. It must lead with a Flag. It has its
|
21
|
+
# own syntax.
|
22
|
+
class Level < TermUtils::AP::Element
|
23
|
+
# @return [TermUtils::AP::Syntax]
|
24
|
+
attr_accessor :syntax
|
25
|
+
# Constructs a new Level.
|
26
|
+
# @param opts [Hash]
|
27
|
+
# @option opts [Symbol] :id
|
28
|
+
# @option opts [Integer] :min_occurs Default value is `0`.
|
29
|
+
# @option opts [Integer] :max_occurs Default value is `1`.
|
30
|
+
def initialize(opts = {})
|
31
|
+
@id = opts.fetch(:id, nil)
|
32
|
+
@min_occurs = opts.fetch(:min_occurs, 0)
|
33
|
+
@max_occurs = opts.fetch(:max_occurs, 1)
|
34
|
+
@flags = []
|
35
|
+
@syntax = TermUtils::AP::Syntax.new
|
36
|
+
end
|
37
|
+
# For dup method.
|
38
|
+
def initialize_dup(other)
|
39
|
+
@syntax = other.syntax.dup
|
40
|
+
super
|
41
|
+
end
|
42
|
+
# Finalizes this one. Internal use.
|
43
|
+
# @return [nil]
|
44
|
+
def finalize!(opts = {})
|
45
|
+
super
|
46
|
+
raise TermUtils::AP::SyntaxError, "level must contain at least one flag" if @flags.empty?
|
47
|
+
@syntax.finalize!(opts)
|
48
|
+
end
|
49
|
+
# Defines the syntax.
|
50
|
+
# @return [TermUtils::AP::Syntax]
|
51
|
+
def define_syntax(&block)
|
52
|
+
block.call(@syntax) if block
|
53
|
+
@syntax
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# No such value error.
|
21
|
+
class NoSuchValueError < StandardError
|
22
|
+
def initialize(msg)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Represents a Parameter.
|
21
|
+
class Parameter < TermUtils::AP::Element
|
22
|
+
# @return [Array<TermUtils::AP::Article>]
|
23
|
+
attr_accessor :articles
|
24
|
+
# Constructs a new Parameter.
|
25
|
+
# @param opts [Hash]
|
26
|
+
# @option opts [Symbol] :id
|
27
|
+
# @option opts [Integer] :min_occurs Default value is `0`.
|
28
|
+
# @option opts [Integer] :max_occurs Default value is `1`.
|
29
|
+
def initialize(opts = {})
|
30
|
+
@id = opts.fetch(:id, nil)
|
31
|
+
@min_occurs = opts.fetch(:min_occurs, 0)
|
32
|
+
@max_occurs = opts.fetch(:max_occurs, 1)
|
33
|
+
@flags = []
|
34
|
+
@articles = []
|
35
|
+
end
|
36
|
+
# For dup method.
|
37
|
+
def initialize_dup(other)
|
38
|
+
if other.articles
|
39
|
+
@articles = []
|
40
|
+
other.articles.each do |a|
|
41
|
+
@articles << a.dup
|
42
|
+
end
|
43
|
+
end
|
44
|
+
super
|
45
|
+
end
|
46
|
+
# Finalizes this one. Internal use.
|
47
|
+
# @return [nil]
|
48
|
+
def finalize!(opts = {})
|
49
|
+
super
|
50
|
+
@articles.each do |a|
|
51
|
+
a.finalize!(opts)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
# Adds a new Article to this one.
|
55
|
+
# @param opts [Hash]
|
56
|
+
# @option opts [Symbol] :id
|
57
|
+
# @option opts [Integer] :min_occurs Default value is `1`.
|
58
|
+
# @option opts [Integer] :max_occurs Default value is `1`.
|
59
|
+
# @option opts [Symbol] :type `:integer`, `:string`.
|
60
|
+
# @option opts [Symbol] :format
|
61
|
+
# @return [TermUtils::AP::Article]
|
62
|
+
def define_article(opts = {}, &block)
|
63
|
+
new_article = TermUtils::AP::Article.new(opts)
|
64
|
+
@articles << new_article
|
65
|
+
block.call(new_article) if block
|
66
|
+
new_article
|
67
|
+
end
|
68
|
+
# Fetches all articles.
|
69
|
+
# @return [Array<TermUtils::AP::Article>]
|
70
|
+
def fetch_articles
|
71
|
+
@articles.collect { |a| a.dup }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Parse error.
|
21
|
+
class ParseError < StandardError
|
22
|
+
def initialize(msg)
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
#
|
3
|
+
# Copyright (C) 2019 Thomas Baron
|
4
|
+
#
|
5
|
+
# This file is part of term_utils.
|
6
|
+
#
|
7
|
+
# term_utils is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, version 3 of the License.
|
10
|
+
#
|
11
|
+
# term_utils is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with term_utils. If not, see <https://www.gnu.org/licenses/>.
|
18
|
+
module TermUtils
|
19
|
+
module AP
|
20
|
+
# Represents the argument list parser.
|
21
|
+
class Parser
|
22
|
+
def initialize
|
23
|
+
end
|
24
|
+
# Parses a given command.
|
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
|
35
|
+
# Parses a given list of arguments.
|
36
|
+
# @param syntax [TermUtils::AP::Syntax]
|
37
|
+
# @param arguments [Array<String>]
|
38
|
+
# @param opts [Hash] `:program`.
|
39
|
+
# @option opts [Boolean] :program Whether the first argument is the program name.
|
40
|
+
# @return [TermUtils::AP::Result]
|
41
|
+
# @raise [TermUtils::AP::ParseError]
|
42
|
+
# @raise [TermUtils::AP::SyntaxError]
|
43
|
+
def parse_arguments(syntax, arguments, opts = {})
|
44
|
+
syntax = syntax.dup
|
45
|
+
syntax.finalize!
|
46
|
+
arguments = arguments.dup
|
47
|
+
res = TermUtils::AP::Result.new(syntax)
|
48
|
+
catch :done do
|
49
|
+
parse0(res.value, syntax, arguments, opts)
|
50
|
+
end
|
51
|
+
res
|
52
|
+
end
|
53
|
+
private
|
54
|
+
# Parses a given argument list.
|
55
|
+
# @param node [TermUtils::PropertyTreeNode]
|
56
|
+
# @param syntax [TermUtils::AP::Syntax]
|
57
|
+
# @param arguments [Array<String>]
|
58
|
+
def parse0(node, syntax, arguments, opts = {})
|
59
|
+
# puts "parse0"
|
60
|
+
opts = opts.dup
|
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
|
67
|
+
fp_occ = {}
|
68
|
+
syntax.elements.each { |e| fp_occ[e.id] = 0 if e.flagged? }
|
69
|
+
up_occ = 0
|
70
|
+
loop do
|
71
|
+
break if arguments.empty?
|
72
|
+
# puts "# %s" % arguments.first
|
73
|
+
if arguments.first === "---"
|
74
|
+
arguments.shift
|
75
|
+
break
|
76
|
+
end
|
77
|
+
if flagged_elems.has_key? arguments.first
|
78
|
+
# Flagged parameter/level.
|
79
|
+
elem = flagged_elems[arguments.first]
|
80
|
+
raise TermUtils::AP::ParseError, "parameter reached its occur limit" if elem.occur_bounded? && (fp_occ[elem.id] >= elem.max_occurs)
|
81
|
+
fp_occ[elem.id] += 1
|
82
|
+
if elem.is_a? TermUtils::AP::Parameter
|
83
|
+
arguments.shift
|
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)
|
93
|
+
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
|
+
end
|
107
|
+
else
|
108
|
+
# Unflagged parameter.
|
109
|
+
raise TermUtils::AP::ParseError, "unexpected unflagged parameter" if unflagged_params.empty?
|
110
|
+
raise TermUtils::AP::ParseError, "unexpected flagged parameter" if arguments.first.start_with? "-"
|
111
|
+
elem = unflagged_params.shift
|
112
|
+
sub_node = node.child_node(elem.id)
|
113
|
+
sub_node = node.define_node(:key => elem.id) unless sub_node
|
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
|
+
end
|
119
|
+
catch :param_done do
|
120
|
+
occ = up_occ
|
121
|
+
up_occ = 0
|
122
|
+
parse0_param(sub_node, elem, arguments, opts)
|
123
|
+
up_occ = occ
|
124
|
+
up_occ += 1
|
125
|
+
if elem.multiple_occurs? && (!elem.occur_bounded? || (up_occ < elem.max_occurs))
|
126
|
+
unflagged_params.unshift elem
|
127
|
+
else
|
128
|
+
up_occ = 0
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end # loop
|
133
|
+
end
|
134
|
+
def parse0_param(node, param, arguments, opts = {})
|
135
|
+
arts = param.fetch_articles
|
136
|
+
occ = 0
|
137
|
+
loop do
|
138
|
+
if arguments.empty?
|
139
|
+
raise TermUtils::AP::ParseError, "unexpected end of parameter" if !arts.empty? && (occ < arts.first.min_occurs)
|
140
|
+
raise TermUtils::AP::ParseError, "unexpected end of parameter" if !arts.empty? && (self.class.eval_article_min_occurs(arts[1..-1]) > 0)
|
141
|
+
throw :done
|
142
|
+
end
|
143
|
+
break if arts.empty?
|
144
|
+
if arguments.first == "--"
|
145
|
+
# End of parameter.
|
146
|
+
raise TermUtils::AP::ParseError, "unexpected end of parameter" if !arts.empty? && (occ < arts.first.min_occurs)
|
147
|
+
raise TermUtils::AP::ParseError, "unexpected end of parameter" if !arts.empty? && (self.class.eval_article_min_occurs(arts[1..-1]) > 0)
|
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)
|
154
|
+
arguments.shift
|
155
|
+
arts.shift
|
156
|
+
occ = 0
|
157
|
+
next
|
158
|
+
end
|
159
|
+
art = arts.first
|
160
|
+
sub_node = node.child_node(art.id)
|
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
|
168
|
+
occ += 1
|
169
|
+
if !art.multiple_occurs? || (art.occur_bounded? && (occ >= art.max_occurs))
|
170
|
+
arts.shift
|
171
|
+
occ = 0
|
172
|
+
end
|
173
|
+
end # loop
|
174
|
+
end
|
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
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|