bibtex-ruby 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bibtex-ruby might be problematic. Click here for more details.

Files changed (67) hide show
  1. data/Gemfile +6 -1
  2. data/Gemfile.lock +48 -5
  3. data/History.txt +16 -1
  4. data/Manifest +43 -19
  5. data/README.md +178 -167
  6. data/Rakefile +26 -5
  7. data/auto.watchr +6 -0
  8. data/bibtex-ruby.gemspec +8 -5
  9. data/examples/bib2html.rb +28 -18
  10. data/features/bibtex.feature +96 -0
  11. data/features/entries.feature +67 -0
  12. data/features/issues/slash_keys.feature +21 -0
  13. data/features/names.feature +72 -0
  14. data/features/preambles.feature +27 -0
  15. data/features/query.feature +56 -0
  16. data/features/replacement.feature +68 -0
  17. data/features/step_definitions/bibtex_steps.rb +74 -0
  18. data/features/step_definitions/name_steps.rb +13 -0
  19. data/features/strings.feature +52 -0
  20. data/features/support/env.rb +7 -0
  21. data/lib/bibtex.rb +5 -1
  22. data/lib/bibtex/bibliography.rb +218 -95
  23. data/lib/bibtex/bibtex.y +18 -15
  24. data/lib/bibtex/elements.rb +130 -136
  25. data/lib/bibtex/entry.rb +133 -69
  26. data/lib/bibtex/extensions.rb +0 -35
  27. data/lib/bibtex/lexer.rb +9 -9
  28. data/lib/bibtex/name_parser.output +464 -0
  29. data/lib/bibtex/name_parser.rb +490 -0
  30. data/lib/bibtex/names.rb +162 -0
  31. data/lib/bibtex/names.y +196 -0
  32. data/lib/bibtex/parser.output +5 -5
  33. data/lib/bibtex/parser.rb +19 -16
  34. data/lib/bibtex/replaceable.rb +52 -0
  35. data/lib/bibtex/utilities.rb +23 -5
  36. data/lib/bibtex/value.rb +201 -0
  37. data/lib/bibtex/version.rb +1 -1
  38. data/test/benchmark.rb +52 -0
  39. data/test/bibtex/test_bibliography.rb +141 -0
  40. data/test/bibtex/test_elements.rb +40 -0
  41. data/test/bibtex/test_entry.rb +99 -0
  42. data/test/bibtex/test_names.rb +23 -0
  43. data/test/bibtex/test_parser.rb +79 -0
  44. data/test/bibtex/test_string.rb +83 -0
  45. data/test/bibtex/test_utilities.rb +34 -0
  46. data/test/bibtex/test_value.rb +70 -0
  47. data/test/{bib/10_bibdesk.bib → fixtures/bibdesk.bib} +1 -1
  48. data/test/{bib/05_comment.bib → fixtures/comment.bib} +0 -0
  49. data/test/{bib/08_decoret.bib → fixtures/decoret.bib} +0 -0
  50. data/test/{bib/00_empty.bib → fixtures/empty.bib} +0 -0
  51. data/test/{bib/07_entry.bib → fixtures/entry.bib} +0 -0
  52. data/test/{bib/09_errors.bib → fixtures/errors.bib} +0 -0
  53. data/test/{bib/01_no_bibtex.bib → fixtures/no_bibtex.bib} +0 -0
  54. data/test/{bib/06_preamble.bib → fixtures/preamble.bib} +1 -1
  55. data/test/{bib/11_roundtrip.bib → fixtures/roundtrip.bib} +1 -1
  56. data/test/helper.rb +17 -2
  57. data/test/test_bibtex.rb +87 -93
  58. data/test/test_export.rb +18 -22
  59. metadata +85 -30
  60. data/test/bib/02_string.bib +0 -1
  61. data/test/bib/03_string.bib +0 -25
  62. data/test/bib/04_string_replacement.bib +0 -16
  63. data/test/test_comment.rb +0 -21
  64. data/test/test_entry.rb +0 -98
  65. data/test/test_preamble.rb +0 -39
  66. data/test/test_string.rb +0 -97
  67. data/test/test_utilities.rb +0 -36
@@ -1,6 +1,6 @@
1
1
  #--
2
2
  # BibTeX-Ruby
3
- # Copyright (C) 2010 Sylvester Keil <sylvester.keil.or.at>
3
+ # Copyright (C) 2010-2011 Sylvester Keil <sylvester.keil.or.at>
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -16,57 +16,80 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  #++
18
18
 
19
+ require 'forwardable'
20
+
19
21
  module BibTeX
20
22
  #
21
23
  # Represents a regular BibTeX entry.
22
24
  #
23
25
  class Entry < Element
24
-
25
- attr_reader :key, :type, :fields
26
-
26
+ extend Forwardable
27
+ include Enumerable
28
+
27
29
  # Hash containing the required fields of the standard entry types
28
- @@RequiredFields = Hash.new([])
29
- @@RequiredFields.merge!({
30
- :article => [:author,:title,:journal,:year],
31
- :book => [[:author,:editor],:title,:publisher,:year],
32
- :booklet => [:title],
33
- :conference => [:author,:title,:booktitle,:year],
34
- :inbook => [[:author,:editor],:title,[:chapter,:pages],:publisher,:year],
35
- :incollection => [:author,:title,:booktitle,:publisher,:year],
30
+ REQUIRED_FIELDS = Hash.new([]).merge({
31
+ :article => [:author,:title,:journal,:year],
32
+ :book => [[:author,:editor],:title,:publisher,:year],
33
+ :booklet => [:title],
34
+ :conference => [:author,:title,:booktitle,:year],
35
+ :inbook => [[:author,:editor],:title,[:chapter,:pages],:publisher,:year],
36
+ :incollection => [:author,:title,:booktitle,:publisher,:year],
36
37
  :inproceedings => [:author,:title,:booktitle,:year],
37
- :manual => [:title],
38
+ :manual => [:title],
38
39
  :mastersthesis => [:author,:title,:school,:year],
39
- :misc => [],
40
- :phdthesis => [:author,:title,:school,:year],
41
- :proceedings => [:title,:year],
42
- :techreport => [:author,:title,:institution,:year],
43
- :unpublished => [:author,:title,:note]
44
- })
40
+ :misc => [],
41
+ :phdthesis => [:author,:title,:school,:year],
42
+ :proceedings => [:title,:year],
43
+ :techreport => [:author,:title,:institution,:year],
44
+ :unpublished => [:author,:title,:note]
45
+ }).freeze
46
+
47
+ NAME_FIELDS = [:author, :editor, :translator].freeze
48
+
49
+ attr_reader :type, :fields
50
+ def_delegators :@fields, :empty?, :each
45
51
 
46
52
  # Creates a new instance. If a hash is given, the entry is populated accordingly.
47
- def initialize(hash={})
53
+ def initialize(attributes = {})
48
54
  @fields = {}
49
55
 
50
- self.type = hash.delete(:type) if hash.has_key?(:type)
51
- self.key = hash.delete(:key) if hash.has_key?(:key)
52
-
53
- hash.each { |k, v| add(k.to_sym, v) }
56
+ self.type = attributes.delete(:type) if attributes.has_key?(:type)
57
+ self.key = attributes.delete(:key) if attributes.has_key?(:key)
58
+
59
+ add(attributes)
54
60
 
55
61
  yield self if block_given?
56
62
  end
57
63
 
58
64
  # Sets the key of the entry
59
65
  def key=(key)
60
- raise(ArgumentError, "BibTeX::Entry key must be of type String; was: #{key.class.name}.") unless key.is_a?(::String)
61
- @key = key
66
+ raise(ArgumentError, "keys must be convertible to Symbol; was: #{type.class.name}.") unless type.respond_to?(:to_sym)
67
+
68
+ unless @bibliography.nil?
69
+ @bibliography.entries.delete(@key)
70
+ @bibliography.entries[key] = self
71
+ end
72
+
73
+ @key = key.to_sym
74
+ end
75
+
76
+ def key
77
+ @key ||= default_key
62
78
  end
63
79
 
80
+ alias :id :key
81
+ alias :id= :key=
82
+
64
83
  # Sets the type of the entry.
65
84
  def type=(type)
66
- raise(ArgumentError, "BibTeX::Entry type must be convertible to Symbol; was: #{type.class.name}.") unless type.respond_to?(:to_sym)
85
+ raise(ArgumentError, "types must be convertible to Symbol; was: #{type.class.name}.") unless type.respond_to?(:to_sym)
67
86
  @type = type.to_sym
68
87
  end
69
88
 
89
+ def has_type?(type)
90
+ type.to_s.match(/^entry$/i) || @type == type.to_sym || super
91
+ end
92
+
70
93
  def method_missing(name, *args)
71
94
  return self[name] if @fields.has_key?(name)
72
95
  return self.send(:add, name.to_s.chop.to_sym, args[0]) if name.to_s.match(/=$/)
@@ -77,9 +100,23 @@ module BibTeX
77
100
  @fields.has_key?(method.to_sym) || method.to_s.match(/=$/) || super
78
101
  end
79
102
 
103
+ # Renames the given field names unless a field with the new name already
104
+ # exists.
105
+ def rename(*arguments)
106
+ Hash[*arguments.flatten].each_pair do |from,to|
107
+ if @field.has_key?(from) && !@field.has_key?(to)
108
+ @field[to] = @field[from]
109
+ @field.delete(from)
110
+ end
111
+ end
112
+ self
113
+ end
114
+
115
+ alias :rename_fields :rename
116
+
80
117
  # Returns the value of the field with the given name.
81
118
  def [](name)
82
- @fields[name.to_sym].to_s
119
+ @fields[name.to_sym]
83
120
  end
84
121
 
85
122
  # Adds a new field (name-value pair) to the entry.
@@ -88,13 +125,23 @@ module BibTeX
88
125
  add(name.to_sym, value)
89
126
  end
90
127
 
91
- # Adds a new field (name-value pair) to the entry.
92
- # Returns the new value.
93
- def add(name, value)
94
- raise(ArgumentError, "BibTeX::Entry field name must be of type Symbol; was: #{name.class.name}.") unless name.is_a?(Symbol)
95
- raise(ArgumentError, "BibTeX::Entry field value must be of type Array, Symbol, or String; was: #{value.class.name}.") unless [Array,::String,Symbol].map { |k| value.is_a?(k) }.inject { |sum,n| sum || n }
96
- @fields[name] = Extensions.string_replacement(value.is_a?(Array) ? value : [value])
128
+ # Adds a new field (name-value pair) or multiple fields to the entry.
129
+ # Returns the entry for chainability.
130
+ #
131
+ # call-seq:
132
+ # add(:author, "Edgar A. Poe")
133
+ # add(:author, "Edgar A. Poe", :title, "The Raven")
134
+ # add([:author, "Edgar A. Poe", :title, "The Raven"])
135
+ # add(:author => "Edgar A. Poe", :title => "The Raven")
136
+ #
137
+ def add(*arguments)
138
+ Hash[*arguments.flatten].each_pair do |name, value|
139
+ @fields[name.to_sym] = Value.new(value)
140
+ end
141
+ self
97
142
  end
143
+
144
+ alias :<< :add
98
145
 
99
146
  # Removes the field with a given name from the entry.
100
147
  # Returns the value of the deleted field; nil if the field was not set.
@@ -102,77 +149,94 @@ module BibTeX
102
149
  @fields.delete(name.to_sym)
103
150
  end
104
151
 
105
- # Adds all the fields contained in a given hash to the entry.
106
- def <<(fields)
107
- raise(ArgumentError, "BibTeX::Entry fields must be of type Hash; was: #{fields.class.name}.") unless fields.is_a?(Hash)
108
- fields.each { |n,v| add(n,v) }
109
- self
110
- end
111
-
112
- # Returns true if the entry currently contains no field.
113
- def empty?
114
- @fields.empty?
115
- end
116
-
117
152
  # Returns false if the entry is one of the standard entry types and does not have
118
153
  # definitions of all the required fields for that type.
119
154
  def valid?
120
- !@@RequiredFields[@type].map { |f|
155
+ REQUIRED_FIELDS[@type].all? do |f|
121
156
  f.is_a?(Array) ? !(f & @fields.keys).empty? : !@fields[f].nil?
122
- }.include?(false)
157
+ end
123
158
  end
124
159
 
125
160
  # Called when the element was added to a bibliography.
126
161
  def added_to_bibliography(bibliography)
127
- super(bibliography)
128
- bibliography.entries[@key] = self
162
+ super
163
+ bibliography.entries[key] = self
129
164
  self
130
165
  end
131
-
166
+
132
167
  # Called when the element was removed from a bibliography.
133
168
  def removed_from_bibliography(bibliography)
134
- super(bibliography)
135
- bibliography.entries[@key] = nil
169
+ super
170
+ bibliography.entries[key] = nil
136
171
  self
137
172
  end
138
173
 
139
- # Replaces all constants in this entry's field values which are defined in +hash+.
140
- def replace!(hash)
141
- @fields.keys.each { |k| @fields[k] = @fields[k].replace_strings(hash) }
174
+ def replace(*arguments)
175
+ arguments = bibliography.q('@string') if arguments.empty?
176
+ @fields.values.each { |v| v.replace(*arguments) }
177
+ self
142
178
  end
143
179
 
144
- def join!
145
- @fields.keys.each { |k| @fields[k] = @fields[k].join_strings }
180
+ def join
181
+ @fields.values.each(&:join)
182
+ self
146
183
  end
147
184
 
185
+ # Parses all name values of the entry. Tries to replace and join the
186
+ # value prior to parsing.
187
+ def parse_names
188
+ NAME_FIELDS.each do |key|
189
+ if name = @fields[key]
190
+ name.replace(bibliography.q('@string')) unless bibliography.nil?
191
+ name.join
192
+ name = name.to_name
193
+ @fields[key] = name
194
+ end
195
+ end
196
+ self
197
+ end
198
+
148
199
  # Returns a string of all the entry's fields.
149
- def content
150
- @fields.keys.map { |k| "#{k} = #{ @fields[k].to_s(:quotes => %w({ })) }" }.join(",\n")
200
+ def content(options = {})
201
+ @fields.map { |k,v| "#{k} = #{ @fields[k].to_s(options) }" }.join(",\n")
151
202
  end
152
203
 
153
204
  # Returns a string representation of the entry.
154
- def to_s
155
- ["@#{type}{#{key},",content.gsub(/^/,' '),"}\n"].join("\n")
205
+ def to_s(options = {})
206
+ options[:quotes] ||= %w({ })
207
+ ["@#{type}{#{key},", content(options).gsub(/^/,' '), "}\n"].join("\n")
156
208
  end
157
209
 
158
- def to_hash(options={})
210
+ def to_hash(options = {})
159
211
  options[:quotes] ||= %w({ })
160
- @fields.keys.map { |k| { k.to_s => @fields[k].to_s(options) } }.inject({ 'key' => @key, 'type' => @type.to_s }) { |sum,n| sum.merge(n) }
212
+ Hash[*([:key, key, :type, type] + @fields.map { |k,v| [k, v.to_s(options)] }.flatten)]
213
+ end
214
+
215
+ def to_citeproc(options = {})
216
+ to_hash(options)
161
217
  end
162
218
 
163
- def to_xml
164
- xml = REXML::Element.new(@type.to_s)
165
- xml.attributes['key'] = @key
219
+ def to_xml(options = {})
220
+ require 'rexml/document'
221
+
222
+ xml = REXML::Element.new(type)
223
+ xml.attributes['key'] = key
166
224
  @fields.each do |k,v|
167
225
  e = REXML::Element.new(k.to_s)
168
- e.text = v.to_s
226
+ e.text = v.to_s(options)
169
227
  xml.add_element(e)
170
228
  end
171
229
  xml
172
230
  end
173
231
 
174
232
  def <=>(other)
175
- self.type != other.type ? self.type <=> other.type : self.key != other.key ? self.key <=> other.key : self.to_s <=> other.to_s
233
+ type != other.type ? type <=> other.type : key != other.key ? key <=> other.key : to_s <=> other.to_s
234
+ end
235
+
236
+ protected
237
+
238
+ def default_key
239
+ object_id.to_s.to_sym
176
240
  end
177
241
 
178
242
  end
@@ -18,43 +18,8 @@
18
18
 
19
19
  module BibTeX
20
20
 
21
- # This module contains functions to manipulate BibTeX string literals.
22
- # It is intended to be injected in an Array that represents either the
23
- # content of a BibTeX @string or an rvalue of a field in a BibTeX entry.
24
21
  module Extensions
25
-
26
- def self.string_replacement(obj)
27
- raise(ArgumentError, "StringReplacement should only be injected into instances of Array, not #{obj.class}.") unless obj.is_a?(::Array)
28
- class << obj; include ::BibTeX::Extensions::StringReplacement end
29
- obj
30
- end
31
-
32
- module StringReplacement
33
- # Returns a string representation of the literal.
34
- def to_s(options={})
35
- return '' if self.empty?
36
-
37
- options[:quotes] ||= [nil,nil]
38
-
39
- if self.length == 1 && !self[0].is_a?(::Symbol)
40
- [options[:quotes][0], self[0], options[:quotes][1]].join
41
- else
42
- self.map { |s| s.is_a?(::Symbol) ? s.to_s : %Q("#{ s }") }.join(' # ')
43
- end
44
- end
45
22
 
46
- # Replaces all string constants which are defined in +hash+.
47
- def replace_strings(hash)
48
- Extensions.string_replacement(self.map { |s| s.is_a?(::Symbol) && hash.has_key?(s) ? hash[s] : s }.flatten)
49
- end
50
-
51
- # Joins consecutive strings separated by '#'.
52
- def join_strings
53
- Extensions.string_replacement(self.inject([]) { |a,b|
54
- a << (a.last.is_a?(::String) && b.is_a?(::String) ? (a.pop + b) : b )
55
- })
56
- end
57
- end
58
23
  end
59
24
 
60
25
  end
@@ -1,6 +1,6 @@
1
1
  #--
2
2
  # BibTeX-Ruby
3
- # Copyright (C) 2010 Sylvester Keil <http://sylvester.keil.or.at>
3
+ # Copyright (C) 2010-2011 Sylvester Keil <http://sylvester.keil.or.at>
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -32,7 +32,7 @@ module BibTeX
32
32
  # Creates a new instance. Possible options and their respective
33
33
  # default values are:
34
34
  #
35
- # - :include => [:errors] A list that may contain :meta_comments, and
35
+ # - :include => [:errors] A list that may contain :meta_content, and
36
36
  # :errors; depending on whether or not these are present, the respective
37
37
  # tokens are included in the parse tree.
38
38
  # - :strict => true In strict mode objects can start anywhere; therefore
@@ -40,7 +40,7 @@ module BibTeX
40
40
  # objects; for a more lenient lexer set to false and objects are
41
41
  # expected to start after a new line (leading white space is permitted).
42
42
  #
43
- def initialize(options={})
43
+ def initialize(options = {})
44
44
  @options = options
45
45
  @options[:include] ||= [:errors]
46
46
  @options[:strict] = true unless @options.has_key?(:strict)
@@ -90,7 +90,7 @@ module BibTeX
90
90
  [:bibtex,:comment,:string,:preamble,:entry].include?(self.mode)
91
91
  end
92
92
 
93
- # Returns true if the lexer is currently parsing meta comments.
93
+ # Returns true if the lexer is currently parsing meta content.
94
94
  def meta_mode?
95
95
  self.mode == :meta
96
96
  end
@@ -119,8 +119,8 @@ module BibTeX
119
119
  when value[0] == :ERROR
120
120
  @stack.push(value) if @options[:include].include?(:errors)
121
121
  leave_object
122
- when value[0] == :META_COMMENT
123
- if @options[:include].include?(:meta_comments)
122
+ when value[0] == :META_CONTENT
123
+ if @options[:include].include?(:meta_content)
124
124
  value[1] = [value[1], line_number_at(@src.pos)]
125
125
  @stack.push(value)
126
126
  end
@@ -194,10 +194,10 @@ module BibTeX
194
194
  def parse_meta
195
195
  match = self.src.scan_until(@options[:strict] ? /@[\t ]*/o : /(^|\n)[\t ]*@[\t ]*/o)
196
196
  unless self.src.matched.nil?
197
- push [:META_COMMENT, match.chop]
197
+ push [:META_CONTENT, match.chop]
198
198
  enter_object
199
199
  else
200
- push [:META_COMMENT,self.src.rest]
200
+ push [:META_CONTENT,self.src.rest]
201
201
  self.src.terminate
202
202
  end
203
203
  end
@@ -318,7 +318,7 @@ module BibTeX
318
318
 
319
319
  def backtrace(error)
320
320
  trace = []
321
- trace.unshift(@stack.pop) until @stack.empty? || (!trace.empty? && [:AT,:META_COMMENT].include?(trace[0][0]))
321
+ trace.unshift(@stack.pop) until @stack.empty? || (!trace.empty? && [:AT,:META_CONTENT].include?(trace[0][0]))
322
322
  trace << error
323
323
  push [:ERROR,trace]
324
324
  end
@@ -0,0 +1,464 @@
1
+
2
+
3
+ -------- Grammar --------
4
+
5
+ rule 1 result:
6
+ rule 2 result: names
7
+ rule 3 names: name
8
+ rule 4 names: names AND name
9
+ rule 5 name: last
10
+ rule 6 name: u_words last
11
+ rule 7 name: sort COMMA first
12
+ rule 8 sort: u_words
13
+ rule 9 sort: LWORD
14
+ rule 10 sort: von LWORD
15
+ rule 11 sort: von u_words
16
+ rule 12 last: word
17
+ rule 13 last: von LWORD
18
+ rule 14 last: von u_words
19
+ rule 15 first: opt_words
20
+ rule 16 first: opt_words COMMA opt_words
21
+ rule 17 u_words: u_word
22
+ rule 18 u_words: u_words u_word
23
+ rule 19 u_word: UWORD
24
+ rule 20 u_word: PWORD
25
+ rule 21 von: LWORD
26
+ rule 22 von: von u_words LWORD
27
+ rule 23 von: von LWORD
28
+ rule 24 words: word
29
+ rule 25 words: words word
30
+ rule 26 opt_words:
31
+ rule 27 opt_words: words
32
+ rule 28 word: LWORD
33
+ rule 29 word: UWORD
34
+ rule 30 word: PWORD
35
+
36
+ ------- Symbols -------
37
+
38
+ **Nonterminals, with rules where they appear
39
+
40
+ $start (8)
41
+ on right:
42
+ on left :
43
+ result (9)
44
+ on right:
45
+ on left : 1 2
46
+ names (10)
47
+ on right: 2 4
48
+ on left : 3 4
49
+ name (11)
50
+ on right: 3 4
51
+ on left : 5 6 7
52
+ last (12)
53
+ on right: 5 6
54
+ on left : 12 13 14
55
+ u_words (13)
56
+ on right: 6 8 11 14 18 22
57
+ on left : 17 18
58
+ sort (14)
59
+ on right: 7
60
+ on left : 8 9 10 11
61
+ first (15)
62
+ on right: 7
63
+ on left : 15 16
64
+ von (16)
65
+ on right: 10 11 13 14 22 23
66
+ on left : 21 22 23
67
+ word (17)
68
+ on right: 12 24 25
69
+ on left : 28 29 30
70
+ opt_words (18)
71
+ on right: 15 16
72
+ on left : 26 27
73
+ u_word (19)
74
+ on right: 17 18
75
+ on left : 19 20
76
+ words (20)
77
+ on right: 25 27
78
+ on left : 24 25
79
+
80
+ **Terminals, with rules where they appear
81
+
82
+ $end (0)
83
+ error (1)
84
+ COMMA (2) 7 16
85
+ UWORD (3) 19 29
86
+ LWORD (4) 9 10 13 21 22 23 28
87
+ PWORD (5) 20 30
88
+ AND (6) 4
89
+ ERROR (7)
90
+
91
+ --------- State ---------
92
+
93
+ state 0
94
+
95
+
96
+ UWORD shift, and go to state 11
97
+ LWORD shift, and go to state 7
98
+ PWORD shift, and go to state 12
99
+ $default reduce using rule 1 (result)
100
+
101
+ result go to state 1
102
+ names go to state 2
103
+ name go to state 3
104
+ last go to state 4
105
+ u_words go to state 5
106
+ sort go to state 6
107
+ von go to state 8
108
+ word go to state 9
109
+ u_word go to state 10
110
+
111
+ state 1
112
+
113
+
114
+ $end shift, and go to state 13
115
+
116
+
117
+ state 2
118
+
119
+ 2) result : names _
120
+ 4) names : names _ AND name
121
+
122
+ AND shift, and go to state 14
123
+ $default reduce using rule 2 (result)
124
+
125
+
126
+ state 3
127
+
128
+ 3) names : name _
129
+
130
+ $default reduce using rule 3 (names)
131
+
132
+
133
+ state 4
134
+
135
+ 5) name : last _
136
+
137
+ $default reduce using rule 5 (name)
138
+
139
+
140
+ state 5
141
+
142
+ 6) name : u_words _ last
143
+ 8) sort : u_words _
144
+ 18) u_words : u_words _ u_word
145
+
146
+ UWORD shift, and go to state 11
147
+ LWORD shift, and go to state 18
148
+ PWORD shift, and go to state 12
149
+ $default reduce using rule 8 (sort)
150
+
151
+ last go to state 15
152
+ word go to state 9
153
+ von go to state 16
154
+ u_word go to state 17
155
+
156
+ state 6
157
+
158
+ 7) name : sort _ COMMA first
159
+
160
+ COMMA shift, and go to state 19
161
+
162
+
163
+ state 7
164
+
165
+ 9) sort : LWORD _
166
+ 21) von : LWORD _
167
+ 28) word : LWORD _
168
+
169
+ $end reduce using rule 28 (word)
170
+ COMMA reduce using rule 9 (sort)
171
+ AND reduce using rule 28 (word)
172
+ $default reduce using rule 21 (von)
173
+
174
+
175
+ state 8
176
+
177
+ 10) sort : von _ LWORD
178
+ 11) sort : von _ u_words
179
+ 13) last : von _ LWORD
180
+ 14) last : von _ u_words
181
+ 22) von : von _ u_words LWORD
182
+ 23) von : von _ LWORD
183
+
184
+ UWORD shift, and go to state 22
185
+ LWORD shift, and go to state 20
186
+ PWORD shift, and go to state 23
187
+
188
+ u_words go to state 21
189
+ u_word go to state 10
190
+
191
+ state 9
192
+
193
+ 12) last : word _
194
+
195
+ $default reduce using rule 12 (last)
196
+
197
+
198
+ state 10
199
+
200
+ 17) u_words : u_word _
201
+
202
+ $default reduce using rule 17 (u_words)
203
+
204
+
205
+ state 11
206
+
207
+ 19) u_word : UWORD _
208
+ 29) word : UWORD _
209
+
210
+ $end reduce using rule 29 (word)
211
+ AND reduce using rule 29 (word)
212
+ $default reduce using rule 19 (u_word)
213
+
214
+
215
+ state 12
216
+
217
+ 20) u_word : PWORD _
218
+ 30) word : PWORD _
219
+
220
+ $end reduce using rule 30 (word)
221
+ AND reduce using rule 30 (word)
222
+ $default reduce using rule 20 (u_word)
223
+
224
+
225
+ state 13
226
+
227
+
228
+ $end shift, and go to state 24
229
+
230
+
231
+ state 14
232
+
233
+ 4) names : names AND _ name
234
+
235
+ UWORD shift, and go to state 11
236
+ LWORD shift, and go to state 7
237
+ PWORD shift, and go to state 12
238
+
239
+ name go to state 25
240
+ last go to state 4
241
+ u_words go to state 5
242
+ sort go to state 6
243
+ von go to state 8
244
+ word go to state 9
245
+ u_word go to state 10
246
+
247
+ state 15
248
+
249
+ 6) name : u_words last _
250
+
251
+ $default reduce using rule 6 (name)
252
+
253
+
254
+ state 16
255
+
256
+ 13) last : von _ LWORD
257
+ 14) last : von _ u_words
258
+ 22) von : von _ u_words LWORD
259
+ 23) von : von _ LWORD
260
+
261
+ UWORD shift, and go to state 22
262
+ LWORD shift, and go to state 26
263
+ PWORD shift, and go to state 23
264
+
265
+ u_words go to state 27
266
+ u_word go to state 10
267
+
268
+ state 17
269
+
270
+ 18) u_words : u_words u_word _
271
+
272
+ $default reduce using rule 18 (u_words)
273
+
274
+
275
+ state 18
276
+
277
+ 21) von : LWORD _
278
+ 28) word : LWORD _
279
+
280
+ $end reduce using rule 28 (word)
281
+ AND reduce using rule 28 (word)
282
+ $default reduce using rule 21 (von)
283
+
284
+
285
+ state 19
286
+
287
+ 7) name : sort COMMA _ first
288
+
289
+ UWORD shift, and go to state 33
290
+ LWORD shift, and go to state 32
291
+ PWORD shift, and go to state 34
292
+ $default reduce using rule 26 (opt_words)
293
+
294
+ first go to state 28
295
+ opt_words go to state 29
296
+ word go to state 30
297
+ words go to state 31
298
+
299
+ state 20
300
+
301
+ 10) sort : von LWORD _
302
+ 13) last : von LWORD _
303
+ 23) von : von LWORD _
304
+
305
+ $end reduce using rule 13 (last)
306
+ COMMA reduce using rule 10 (sort)
307
+ AND reduce using rule 13 (last)
308
+ $default reduce using rule 23 (von)
309
+
310
+
311
+ state 21
312
+
313
+ 11) sort : von u_words _
314
+ 14) last : von u_words _
315
+ 18) u_words : u_words _ u_word
316
+ 22) von : von u_words _ LWORD
317
+
318
+ UWORD shift, and go to state 22
319
+ LWORD shift, and go to state 35
320
+ PWORD shift, and go to state 23
321
+ COMMA reduce using rule 11 (sort)
322
+ $default reduce using rule 14 (last)
323
+
324
+ u_word go to state 17
325
+
326
+ state 22
327
+
328
+ 19) u_word : UWORD _
329
+
330
+ $default reduce using rule 19 (u_word)
331
+
332
+
333
+ state 23
334
+
335
+ 20) u_word : PWORD _
336
+
337
+ $default reduce using rule 20 (u_word)
338
+
339
+
340
+ state 24
341
+
342
+
343
+ $default accept
344
+
345
+
346
+ state 25
347
+
348
+ 4) names : names AND name _
349
+
350
+ $default reduce using rule 4 (names)
351
+
352
+
353
+ state 26
354
+
355
+ 13) last : von LWORD _
356
+ 23) von : von LWORD _
357
+
358
+ $end reduce using rule 13 (last)
359
+ AND reduce using rule 13 (last)
360
+ $default reduce using rule 23 (von)
361
+
362
+
363
+ state 27
364
+
365
+ 14) last : von u_words _
366
+ 18) u_words : u_words _ u_word
367
+ 22) von : von u_words _ LWORD
368
+
369
+ UWORD shift, and go to state 22
370
+ LWORD shift, and go to state 35
371
+ PWORD shift, and go to state 23
372
+ $default reduce using rule 14 (last)
373
+
374
+ u_word go to state 17
375
+
376
+ state 28
377
+
378
+ 7) name : sort COMMA first _
379
+
380
+ $default reduce using rule 7 (name)
381
+
382
+
383
+ state 29
384
+
385
+ 15) first : opt_words _
386
+ 16) first : opt_words _ COMMA opt_words
387
+
388
+ COMMA shift, and go to state 36
389
+ $default reduce using rule 15 (first)
390
+
391
+
392
+ state 30
393
+
394
+ 24) words : word _
395
+
396
+ $default reduce using rule 24 (words)
397
+
398
+
399
+ state 31
400
+
401
+ 25) words : words _ word
402
+ 27) opt_words : words _
403
+
404
+ UWORD shift, and go to state 33
405
+ LWORD shift, and go to state 32
406
+ PWORD shift, and go to state 34
407
+ $default reduce using rule 27 (opt_words)
408
+
409
+ word go to state 37
410
+
411
+ state 32
412
+
413
+ 28) word : LWORD _
414
+
415
+ $default reduce using rule 28 (word)
416
+
417
+
418
+ state 33
419
+
420
+ 29) word : UWORD _
421
+
422
+ $default reduce using rule 29 (word)
423
+
424
+
425
+ state 34
426
+
427
+ 30) word : PWORD _
428
+
429
+ $default reduce using rule 30 (word)
430
+
431
+
432
+ state 35
433
+
434
+ 22) von : von u_words LWORD _
435
+
436
+ $default reduce using rule 22 (von)
437
+
438
+
439
+ state 36
440
+
441
+ 16) first : opt_words COMMA _ opt_words
442
+
443
+ UWORD shift, and go to state 33
444
+ LWORD shift, and go to state 32
445
+ PWORD shift, and go to state 34
446
+ $default reduce using rule 26 (opt_words)
447
+
448
+ opt_words go to state 38
449
+ word go to state 30
450
+ words go to state 31
451
+
452
+ state 37
453
+
454
+ 25) words : words word _
455
+
456
+ $default reduce using rule 25 (words)
457
+
458
+
459
+ state 38
460
+
461
+ 16) first : opt_words COMMA opt_words _
462
+
463
+ $default reduce using rule 16 (first)
464
+