bibtex-ruby 2.0.3 → 2.0.4

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.
Files changed (52) hide show
  1. data/Gemfile.lock +2 -2
  2. data/History.txt +7 -0
  3. data/Manifest +3 -37
  4. data/Rakefile +1 -1
  5. data/features/issues/multiline_strings.feature +14 -0
  6. data/lib/bibtex/bibtex.y +9 -6
  7. data/lib/bibtex/filters.rb +5 -3
  8. data/lib/bibtex/filters/latex.rb +1 -1
  9. data/lib/bibtex/filters/linebreaks.rb +11 -0
  10. data/lib/bibtex/lexer.rb +254 -236
  11. data/lib/bibtex/parser.rb +9 -6
  12. data/lib/bibtex/version.rb +1 -1
  13. data/test/benchmark.rb +4 -1
  14. data/test/bibtex/test_lexer.rb +12 -2
  15. data/test/bibtex/test_parser.rb +21 -0
  16. metadata +14 -48
  17. data/Rakefile.compiled.rbc +0 -1994
  18. data/features/step_definitions/bibtex_steps.rbc +0 -2996
  19. data/features/step_definitions/name_steps.rbc +0 -544
  20. data/features/support/env.rbc +0 -144
  21. data/lib/bibtex.rbc +0 -725
  22. data/lib/bibtex/bibliography.rbc +0 -6729
  23. data/lib/bibtex/compatibility.rbc +0 -290
  24. data/lib/bibtex/elements.rbc +0 -5966
  25. data/lib/bibtex/entry.rbc +0 -11305
  26. data/lib/bibtex/error.rbc +0 -1000
  27. data/lib/bibtex/extensions.rbc +0 -127
  28. data/lib/bibtex/filters.rbc +0 -1178
  29. data/lib/bibtex/filters/latex.rbc +0 -361
  30. data/lib/bibtex/lexer.rbc +0 -5559
  31. data/lib/bibtex/name_parser.rbc +0 -2510
  32. data/lib/bibtex/names.rbc +0 -4710
  33. data/lib/bibtex/parser.rbc +0 -3336
  34. data/lib/bibtex/replaceable.rbc +0 -593
  35. data/lib/bibtex/utilities.rbc +0 -743
  36. data/lib/bibtex/value.rbc +0 -4291
  37. data/lib/bibtex/version.rbc +0 -209
  38. data/test/bibtex/test_bibliography.rbc +0 -4268
  39. data/test/bibtex/test_elements.rbc +0 -1554
  40. data/test/bibtex/test_entry.rbc +0 -11767
  41. data/test/bibtex/test_filters.rbc +0 -1017
  42. data/test/bibtex/test_lexer.rbc +0 -373
  43. data/test/bibtex/test_name_parser.rbc +0 -608
  44. data/test/bibtex/test_names.rbc +0 -797
  45. data/test/bibtex/test_parser.rbc +0 -2819
  46. data/test/bibtex/test_string.rbc +0 -706
  47. data/test/bibtex/test_utilities.rbc +0 -851
  48. data/test/bibtex/test_value.rbc +0 -4993
  49. data/test/helper.rbc +0 -430
  50. data/test/profile.dot +0 -191
  51. data/test/test_bibtex.rbc +0 -1785
  52. data/test/test_export.rbc +0 -908
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bibtex-ruby (2.0.2)
4
+ bibtex-ruby (2.0.4)
5
5
  latex-decode (>= 0.0.6)
6
6
  multi_json (~> 1.0)
7
7
 
@@ -34,7 +34,7 @@ GEM
34
34
  linecache19 (0.5.12)
35
35
  ruby_core_source (>= 0.1.4)
36
36
  minitest (2.3.1)
37
- multi_json (1.0.3)
37
+ multi_json (1.0.4)
38
38
  mynyml-redgreen (0.7.1)
39
39
  term-ansicolor (>= 1.0.4)
40
40
  racc (1.4.6)
@@ -1,3 +1,10 @@
1
+ 2.0.4 / 2011-12-20
2
+ ==================
3
+
4
+ * Added lexer option :strip to strip newlines from literals (thanks to @JLimperg)
5
+ * Added :linebreaks filter
6
+
7
+
1
8
  2.0.3 / 2011-12-13
2
9
  ==================
3
10
 
data/Manifest CHANGED
@@ -5,7 +5,6 @@ LICENSE
5
5
  Manifest
6
6
  README.md
7
7
  Rakefile
8
- Rakefile.compiled.rbc
9
8
  auto.watchr
10
9
  bibtex-ruby.gemspec
11
10
  examples
@@ -19,6 +18,7 @@ features/issues
19
18
  features/issues/braced_strings.feature
20
19
  features/issues/crossref.feature
21
20
  features/issues/latex_filter.feature
21
+ features/issues/multiline_strings.feature
22
22
  features/issues/number_keys.feature
23
23
  features/issues/parse_months.feature
24
24
  features/issues/slash_keys.feature
@@ -29,78 +29,48 @@ features/query.feature
29
29
  features/replacement.feature
30
30
  features/step_definitions
31
31
  features/step_definitions/bibtex_steps.rb
32
- features/step_definitions/bibtex_steps.rbc
33
32
  features/step_definitions/name_steps.rb
34
- features/step_definitions/name_steps.rbc
35
33
  features/strings.feature
36
34
  features/support
37
35
  features/support/env.rb
38
- features/support/env.rbc
39
36
  lib
40
37
  lib/bibtex
41
38
  lib/bibtex/bibliography.rb
42
- lib/bibtex/bibliography.rbc
43
39
  lib/bibtex/bibtex.y
44
40
  lib/bibtex/compatibility.rb
45
- lib/bibtex/compatibility.rbc
46
41
  lib/bibtex/elements.rb
47
- lib/bibtex/elements.rbc
48
42
  lib/bibtex/entry.rb
49
- lib/bibtex/entry.rbc
50
43
  lib/bibtex/error.rb
51
- lib/bibtex/error.rbc
52
44
  lib/bibtex/extensions.rb
53
- lib/bibtex/extensions.rbc
54
45
  lib/bibtex/filters
55
46
  lib/bibtex/filters/latex.rb
56
- lib/bibtex/filters/latex.rbc
47
+ lib/bibtex/filters/linebreaks.rb
57
48
  lib/bibtex/filters.rb
58
- lib/bibtex/filters.rbc
59
49
  lib/bibtex/lexer.rb
60
- lib/bibtex/lexer.rbc
61
50
  lib/bibtex/name_parser.rb
62
- lib/bibtex/name_parser.rbc
63
51
  lib/bibtex/names.rb
64
- lib/bibtex/names.rbc
65
52
  lib/bibtex/names.y
66
53
  lib/bibtex/parser.rb
67
- lib/bibtex/parser.rbc
68
54
  lib/bibtex/replaceable.rb
69
- lib/bibtex/replaceable.rbc
70
55
  lib/bibtex/ruby.rb
71
56
  lib/bibtex/utilities.rb
72
- lib/bibtex/utilities.rbc
73
57
  lib/bibtex/value.rb
74
- lib/bibtex/value.rbc
75
58
  lib/bibtex/version.rb
76
- lib/bibtex/version.rbc
77
59
  lib/bibtex.rb
78
- lib/bibtex.rbc
79
60
  test
80
61
  test/benchmark.rb
81
62
  test/bibtex
82
63
  test/bibtex/test_bibliography.rb
83
- test/bibtex/test_bibliography.rbc
84
64
  test/bibtex/test_elements.rb
85
- test/bibtex/test_elements.rbc
86
65
  test/bibtex/test_entry.rb
87
- test/bibtex/test_entry.rbc
88
66
  test/bibtex/test_filters.rb
89
- test/bibtex/test_filters.rbc
90
67
  test/bibtex/test_lexer.rb
91
- test/bibtex/test_lexer.rbc
92
68
  test/bibtex/test_name_parser.rb
93
- test/bibtex/test_name_parser.rbc
94
69
  test/bibtex/test_names.rb
95
- test/bibtex/test_names.rbc
96
70
  test/bibtex/test_parser.rb
97
- test/bibtex/test_parser.rbc
98
71
  test/bibtex/test_string.rb
99
- test/bibtex/test_string.rbc
100
72
  test/bibtex/test_utilities.rb
101
- test/bibtex/test_utilities.rbc
102
73
  test/bibtex/test_value.rb
103
- test/bibtex/test_value.rbc
104
74
  test/fixtures
105
75
  test/fixtures/bibdesk.bib
106
76
  test/fixtures/comment.bib
@@ -112,10 +82,6 @@ test/fixtures/no_bibtex.bib
112
82
  test/fixtures/preamble.bib
113
83
  test/fixtures/roundtrip.bib
114
84
  test/helper.rb
115
- test/helper.rbc
116
- test/profile.dot
117
85
  test/profile.rb
118
86
  test/test_bibtex.rb
119
- test/test_bibtex.rbc
120
- test/test_export.rb
121
- test/test_export.rbc
87
+ test/test_export.rb
data/Rakefile CHANGED
@@ -69,7 +69,7 @@ end
69
69
  desc 'Updates the Manifest file'
70
70
  task :manifest => ['clean', 'racc'] do
71
71
  m = File.open('Manifest', 'w')
72
- m.print FileList['**/*'].join("\n")
72
+ m.print FileList['**/*'].reject{ |f| f.end_with?('rbc') }.join("\n")
73
73
  m.close
74
74
  end
75
75
 
@@ -0,0 +1,14 @@
1
+ Feature: Multiline values on single lines
2
+ As a hacker who works with bibliographies
3
+ I would find it practical to have multiline values turned to single lines by default
4
+ Because this is what most BibTeX files will assume.
5
+
6
+ Scenario: Multiline value
7
+ When I parse the following file:
8
+ """
9
+ @article{stuff,
10
+ title = "This very long title must be wrapped and continues
11
+ on the next line."
12
+ }
13
+ """
14
+ Then the entry with key "stuff" should have a field "title" with the value "This very long title must be wrapped and continues on the next line."
@@ -90,10 +90,10 @@ require 'bibtex/lexer'
90
90
 
91
91
  attr_reader :lexer, :options
92
92
 
93
- DEFAULTS = { :include => [:errors], :debug => ENV['DEBUG'] == true }.freeze
94
-
93
+ DEFAULTS = { :include => [:errors], :debug => ENV['DEBUG'] == true }.freeze
94
+
95
95
  def initialize(options = {})
96
- @options = DEFAULTS.merge(options)
96
+ @options = DEFAULTS.merge(options)
97
97
  @lexer = Lexer.new(@options)
98
98
  end
99
99
 
@@ -102,7 +102,7 @@ require 'bibtex/lexer'
102
102
  @lexer.analyse(input)
103
103
 
104
104
  do_parse
105
- #yyparse(@lexer,:each)
105
+ #yyparse(@lexer,:each)
106
106
  end
107
107
 
108
108
  def next_token
@@ -114,8 +114,11 @@ require 'bibtex/lexer'
114
114
  end
115
115
 
116
116
  def on_error(tid, val, vstack)
117
- Log.error("Failed to parse BibTeX on value %s (%s) %s" % [val.inspect, token_to_str(tid) || '?', vstack.inspect])
118
- #raise(ParseError, "Failed to parse BibTeX on value %s (%s) %s" % [val.inspect, token_to_str(tid) || '?', vstack.inspect])
117
+ message =
118
+ "Failed to parse BibTeX on value #{val.inspect} (#{token_to_str(tid) || '?'}) #{ vstack.inspect}"
119
+
120
+ BibTeX.log.error message
121
+ raise ParseError, message
119
122
  end
120
123
 
121
124
  # -*- racc -*-
@@ -6,7 +6,7 @@ module BibTeX
6
6
 
7
7
  class << self
8
8
  # Hook called by Ruby if Filter is subclassed
9
- def inherited (base)
9
+ def inherited(base)
10
10
  base.class_eval { include Singleton }
11
11
  subclasses << base
12
12
  end
@@ -17,7 +17,9 @@ module BibTeX
17
17
  end
18
18
  end
19
19
 
20
- def apply (value); value; end
20
+ def apply(value)
21
+ value
22
+ end
21
23
 
22
24
  alias convert apply
23
25
  alias << apply
@@ -31,7 +33,7 @@ module BibTeX
31
33
  require filter
32
34
  end
33
35
 
34
- def self.resolve (filter)
36
+ def self.resolve(filter)
35
37
  case
36
38
  when filter.respond_to?(:apply)
37
39
  filter
@@ -4,7 +4,7 @@ module BibTeX
4
4
  module Filters
5
5
 
6
6
  class LaTeX < Filter
7
- def apply (value)
7
+ def apply(value)
8
8
  ::LaTeX.decode(value)
9
9
  end
10
10
  end
@@ -0,0 +1,11 @@
1
+ module BibTeX
2
+ module Filters
3
+
4
+ class LineBreaks < Filter
5
+ def apply(value)
6
+ value.to_s.gsub(/\n\s*/, ' ')
7
+ end
8
+ end
9
+
10
+ end
11
+ end
@@ -9,280 +9,298 @@
9
9
  #
10
10
  # This program is distributed in the hope that it will be useful,
11
11
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
13
  # GNU General Public License for more details.
14
14
  #
15
15
  # You should have received a copy of the GNU General Public License
16
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
  #++
18
18
 
19
19
  require 'strscan'
20
20
 
21
21
  module BibTeX
22
-
23
- #
24
- # The BibTeX::Lexer handles the lexical analysis of BibTeX bibliographies.
25
- #
26
- class Lexer
27
- extend Forwardable
22
+
23
+ #
24
+ # The BibTeX::Lexer handles the lexical analysis of BibTeX bibliographies.
25
+ #
26
+ class Lexer
27
+ extend Forwardable
28
28
 
29
- attr_reader :options, :stack, :mode, :scanner
30
- attr_writer :mode
31
-
29
+ attr_reader :options, :stack, :mode, :scanner
30
+ attr_writer :mode
31
+
32
32
  def_delegator :@scanner, :string, :data
33
33
 
34
- DEFAULTS = { :include => [:errors], :strict => true }.freeze
34
+ @defaults = {
35
+ :include => [:errors],
36
+ :strict => true,
37
+ :strip => true
38
+ }.freeze
39
+
40
+ MODE = Hash.new(:meta).merge({
41
+ :bibtex => :bibtex, :entry => :bibtex,
42
+ :string => :bibtex, :preamble => :bibtex,
43
+ :comment => :bibtex, :meta => :meta,
44
+ :literal => :literal, :content => :content
45
+ }).freeze
35
46
 
36
- MODE = Hash.new(:meta).merge(:bibtex => :bibtex, :entry => :bibtex, :string => :bibtex, :preamble => :bibtex, :comment => :bibtex, :meta => :meta, :literal => :literal, :content => :content).freeze
47
+ class << self
48
+ attr_accessor :defaults
49
+ end
37
50
 
38
- #
39
- # Creates a new instance. Possible options and their respective
40
- # default values are:
41
- #
42
- # - :include => [:errors] A list that may contain :meta_content, and
43
- # :errors; depending on whether or not these are present, the respective
44
- # tokens are included in the parse tree.
45
- # - :strict => true In strict mode objects can start anywhere; therefore
46
- # the `@' symbol is not possible except inside literals or @comment
47
- # objects; for a more lenient lexer set to false and objects are
48
- # expected to start after a new line (leading white space is permitted).
49
- #
50
- def initialize(options = {})
51
- @options = DEFAULTS.merge(options)
51
+ #
52
+ # Creates a new instance. Possible options and their respective
53
+ # default values are:
54
+ #
55
+ # - :include => [:errors] A list that may contain :meta_content, and
56
+ # :errors; depending on whether or not these are present, the respective
57
+ # tokens are included in the parse tree.
58
+ # - :strict => true In strict mode objects can start anywhere; therefore
59
+ # the `@' symbol is not possible except inside literals or @comment
60
+ # objects; for a more lenient lexer set to false and objects are
61
+ # expected to start after a new line (leading white space is permitted).
62
+ # - :strip => true When enabled, newlines will be stripped from quoted
63
+ # string values.
64
+ #
65
+ def initialize(options = {})
66
+ @options = Lexer.defaults.merge(options)
52
67
  reset
53
- end
68
+ end
54
69
 
55
70
  def reset
56
- @stack, @brace_level, @mode, @active_object = [], 0, :meta, nil
57
- @scanner.reset if @scanner
58
-
59
- # cache options for speed
60
- @include_meta_content = @options[:include].include?(:meta_content)
61
- @include_errors = @options[:include].include?(:errors)
62
-
63
- self
71
+ @stack, @brace_level, @mode, @active_object = [], 0, :meta, nil
72
+ @scanner.reset if @scanner
73
+
74
+ # cache options for speed
75
+ @include_meta_content = @options[:include].include?(:meta_content)
76
+ @include_errors = @options[:include].include?(:errors)
77
+
78
+ self
64
79
  end
65
80
 
66
- # Sets the source for the lexical analysis and resets the internal state.
67
- def data=(data)
68
- @scanner = StringScanner.new(data)
69
- reset
70
- end
81
+ # Sets the source for the lexical analysis and resets the internal state.
82
+ def data=(data)
83
+ @scanner = StringScanner.new(data)
84
+ reset
85
+ end
71
86
 
72
87
  def symbols; @stack.map(&:first); end
73
88
 
74
- # Returns the next token from the parse stack.
75
- def next_token; @stack.shift; end
89
+ # Returns the next token from the parse stack.
90
+ def next_token; @stack.shift; end
76
91
 
77
- # Returns true if the lexer is currenty parsing a BibTeX object.
78
- def bibtex_mode?
79
- MODE[@mode] == :bibtex
80
- end
81
-
82
- [:meta, :literal, :content].each do |m|
92
+ # Returns true if the lexer is currenty parsing a BibTeX object.
93
+ def bibtex_mode?
94
+ MODE[@mode] == :bibtex
95
+ end
96
+
97
+ [:meta, :literal, :content].each do |m|
83
98
  define_method("#{m}_mode?") { @mode == m }
84
- end
99
+ end
85
100
 
86
- # Returns true if the lexer is currently parsing the given object type.
87
- def active?(object)
88
- @active_object == object
89
- end
90
-
91
- # Returns true if the lexer is currently in strict mode.
92
- def strict?; !!(@options[:strict]); end
93
-
94
- # Pushes a value onto the parse stack. Returns the Lexer.
95
- def push(value)
96
- case value[0]
101
+ # Returns true if the lexer is currently parsing the given object type.
102
+ def active?(object)
103
+ @active_object == object
104
+ end
105
+
106
+ # Returns true if the lexer is currently in strict mode.
107
+ def strict?; !!(@options[:strict]); end
108
+
109
+ def strip_line_breaks?
110
+ !!options[:strip] && !active?(:comment)
111
+ end
112
+
113
+ # Pushes a value onto the parse stack. Returns the Lexer.
114
+ def push(value)
115
+ case value[0]
97
116
  when :CONTENT, :STRING_LITERAL
98
- if !@stack.empty? && value[0] == @stack[-1][0]
99
- @stack[-1][1] << value[1]
100
- else
101
- @stack.push(value)
102
- end
103
- when :ERROR
104
- @stack.push(value) if @include_errors
105
- leave_object
106
- when :META_CONTENT
117
+ value[1].gsub!(/\n\s*/, ' ') if strip_line_breaks?
118
+
119
+ if !@stack.empty? && value[0] == @stack[-1][0]
120
+ @stack[-1][1] << value[1]
121
+ else
122
+ @stack.push(value)
123
+ end
124
+ when :ERROR
125
+ @stack.push(value) if @include_errors
126
+ leave_object
127
+ when :META_CONTENT
107
128
  @stack.push(value) if @include_meta_content
108
- else
109
- @stack.push(value)
110
- end
111
-
112
- self
113
- end
129
+ else
130
+ @stack.push(value)
131
+ end
132
+
133
+ self
134
+ end
114
135
 
115
- # Start the lexical analysis.
116
- def analyse(string = nil)
117
- raise(ArgumentError, 'Lexer: failed to start analysis: no source given!') unless
118
- string || @scanner
136
+ # Start the lexical analysis.
137
+ def analyse(string = nil)
138
+ raise(ArgumentError, 'Lexer: failed to start analysis: no source given!') unless
139
+ string || @scanner
119
140
 
120
- self.data = string || @scanner.string
121
-
122
- until @scanner.eos?
123
- send("parse_#{MODE[@mode]}")
124
- end
141
+ self.data = string || @scanner.string
142
+
143
+ until @scanner.eos?
144
+ send("parse_#{MODE[@mode]}")
145
+ end
125
146
 
126
- push([false, '$end'])
127
- end
147
+ push([false, '$end'])
148
+ end
128
149
 
129
150
  private
130
151
 
131
- def parse_bibtex
132
- case
133
- when @scanner.scan(/[\s]+/o)
134
- when @scanner.scan(/\{/o)
135
- @brace_level += 1
136
- push([:LBRACE,'{'])
137
- @mode = :content if @brace_level > 1 || @brace_level == 1 && active?(:comment)
138
- when @scanner.scan(/\}/o)
139
- @brace_level -= 1
140
- push([:RBRACE,'}'])
141
- return leave_object if @brace_level == 0
142
- return error_unbalanced_braces if @brace_level < 0
143
- when @scanner.scan( /=/o)
144
- push([:EQ,'='])
145
- when @scanner.scan(/,/o)
146
- push([:COMMA,','])
147
- when @scanner.scan(/\d+/o)
148
- push([:NUMBER,@scanner.matched])
149
- when @scanner.scan(/[[:alpha:]\d \/:_!$\.%&*-]+/io)
150
- push([:NAME,@scanner.matched.rstrip])
151
- when @scanner.scan(/"/o)
152
- @mode = :literal
153
- when @scanner.scan(/#/o)
154
- push([:SHARP,'#'])
155
- when @scanner.scan(/@/o)
156
- enter_object
157
- when @scanner.scan(/./o)
158
- error_unexpected_token
159
- end
160
- end
161
-
162
- def parse_meta
163
- match = @scanner.scan_until(strict? ? /@[\t ]*/o : /(^|\n)[\t ]*@[\t ]*/o)
164
- if @scanner.matched
165
- push([:META_CONTENT,match.chop])
166
- enter_object
167
- else
168
- push([:META_CONTENT,@scanner.rest])
169
- @scanner.terminate
170
- end
171
- end
152
+ def parse_bibtex
153
+ case
154
+ when @scanner.scan(/[\s]+/o)
155
+ when @scanner.scan(/\{/o)
156
+ @brace_level += 1
157
+ push([:LBRACE,'{'])
158
+ @mode = :content if @brace_level > 1 || @brace_level == 1 && active?(:comment)
159
+ when @scanner.scan(/\}/o)
160
+ @brace_level -= 1
161
+ push([:RBRACE,'}'])
162
+ return leave_object if @brace_level == 0
163
+ return error_unbalanced_braces if @brace_level < 0
164
+ when @scanner.scan( /=/o)
165
+ push([:EQ,'='])
166
+ when @scanner.scan(/,/o)
167
+ push([:COMMA,','])
168
+ when @scanner.scan(/\d+/o)
169
+ push([:NUMBER,@scanner.matched])
170
+ when @scanner.scan(/[[:alpha:]\d \/:_!$\.%&*-]+/io)
171
+ push([:NAME,@scanner.matched.rstrip])
172
+ when @scanner.scan(/"/o)
173
+ @mode = :literal
174
+ when @scanner.scan(/#/o)
175
+ push([:SHARP,'#'])
176
+ when @scanner.scan(/@/o)
177
+ enter_object
178
+ when @scanner.scan(/./o)
179
+ error_unexpected_token
180
+ end
181
+ end
182
+
183
+ def parse_meta
184
+ match = @scanner.scan_until(strict? ? /@[\t ]*/o : /(^|\n)[\t ]*@[\t ]*/o)
185
+ if @scanner.matched
186
+ push([:META_CONTENT,match.chop])
187
+ enter_object
188
+ else
189
+ push([:META_CONTENT,@scanner.rest])
190
+ @scanner.terminate
191
+ end
192
+ end
172
193
 
173
- def parse_content
174
- match = @scanner.scan_until(/\{|\}/o)
175
- case @scanner.matched
176
- when '{'
177
- @brace_level += 1
178
- push([:CONTENT,match])
179
- when '}'
180
- @brace_level -= 1
181
- case
182
- when @brace_level == 0
183
- push([:CONTENT,match.chop])
184
- push([:RBRACE,'}'])
185
- leave_object
186
- when @brace_level == 1 && !active?(:comment)
187
- push([:CONTENT,match.chop])
188
- push([:RBRACE,'}'])
189
- @mode = :bibtex
190
- when @brace_level < 0
191
- push([:CONTENT,match.chop])
192
- error_unbalanced_braces
193
- else
194
- push([:CONTENT,match])
195
- end
196
- else
197
- push([:CONTENT,@scanner.rest])
198
- @scanner.terminate
199
- error_unterminated_content
200
- end
201
- end
202
-
203
- def parse_literal
204
- match = @scanner.scan_until(/[\{\}"]/o)
205
- case @scanner.matched
206
- when '{'
207
- @brace_level += 1
208
- push([:STRING_LITERAL,match])
209
- when '}'
210
- @brace_level -= 1
211
- if @brace_level < 1
212
- push([:STRING_LITERAL,match.chop])
213
- error_unbalanced_braces
214
- else
215
- push([:STRING_LITERAL,match])
216
- end
217
- when '"'
218
- if @brace_level == 1
219
- push([:STRING_LITERAL,match.chop])
220
- @mode = :bibtex
221
- else
222
- push([:STRING_LITERAL,match])
223
- end
224
- when "\n"
225
- push([:STRING_LITERAL,match.chop])
226
- error_unterminated_string
227
- else
228
- push([:STRING_LITERAL,@scanner.rest])
229
- @scanner.terminate
230
- error_unterminated_string
231
- end
232
- end
233
-
234
- # Called when the lexer encounters a new BibTeX object.
235
- def enter_object
236
- @brace_level = 0
237
- push [:AT,'@']
194
+ def parse_content
195
+ match = @scanner.scan_until(/\{|\}/o)
196
+ case @scanner.matched
197
+ when '{'
198
+ @brace_level += 1
199
+ push([:CONTENT,match])
200
+ when '}'
201
+ @brace_level -= 1
202
+ case
203
+ when @brace_level == 0
204
+ push([:CONTENT,match.chop])
205
+ push([:RBRACE,'}'])
206
+ leave_object
207
+ when @brace_level == 1 && !active?(:comment)
208
+ push([:CONTENT,match.chop])
209
+ push([:RBRACE,'}'])
210
+ @mode = :bibtex
211
+ when @brace_level < 0
212
+ push([:CONTENT,match.chop])
213
+ error_unbalanced_braces
214
+ else
215
+ push([:CONTENT,match])
216
+ end
217
+ else
218
+ push([:CONTENT,@scanner.rest])
219
+ @scanner.terminate
220
+ error_unterminated_content
221
+ end
222
+ end
223
+
224
+ def parse_literal
225
+ match = @scanner.scan_until(/[\{\}"]/o)
226
+ case @scanner.matched
227
+ when '{'
228
+ @brace_level += 1
229
+ push([:STRING_LITERAL,match])
230
+ when '}'
231
+ @brace_level -= 1
232
+ if @brace_level < 1
233
+ push([:STRING_LITERAL,match.chop])
234
+ error_unbalanced_braces
235
+ else
236
+ push([:STRING_LITERAL,match])
237
+ end
238
+ when '"'
239
+ if @brace_level == 1
240
+ push([:STRING_LITERAL,match.chop])
241
+ @mode = :bibtex
242
+ else
243
+ push([:STRING_LITERAL,match])
244
+ end
245
+ else
246
+ push([:STRING_LITERAL,@scanner.rest])
247
+ @scanner.terminate
248
+ error_unterminated_string
249
+ end
250
+ end
251
+
252
+ # Called when the lexer encounters a new BibTeX object.
253
+ def enter_object
254
+ @brace_level = 0
255
+ push [:AT,'@']
238
256
 
239
- case
240
- when @scanner.scan(/string/io)
241
- @mode = @active_object = :string
242
- push [:STRING, @scanner.matched]
243
- when @scanner.scan(/preamble/io)
244
- @mode = @active_object = :preamble
245
- push [:PREAMBLE, @scanner.matched]
246
- when @scanner.scan(/comment/io)
247
- @mode = @active_object = :comment
248
- push [:COMMENT, @scanner.matched]
249
- when @scanner.scan(/[a-z\d:_!\.$%&*-]+/io)
250
- @mode = @active_object = :entry
251
- push [:NAME, @scanner.matched]
257
+ case
258
+ when @scanner.scan(/string/io)
259
+ @mode = @active_object = :string
260
+ push [:STRING, @scanner.matched]
261
+ when @scanner.scan(/preamble/io)
262
+ @mode = @active_object = :preamble
263
+ push [:PREAMBLE, @scanner.matched]
264
+ when @scanner.scan(/comment/io)
265
+ @mode = @active_object = :comment
266
+ push [:COMMENT, @scanner.matched]
267
+ when @scanner.scan(/[a-z\d:_!\.$%&*-]+/io)
268
+ @mode = @active_object = :entry
269
+ push [:NAME, @scanner.matched]
252
270
  else
253
271
  error_unexpected_object
254
- end
255
- end
272
+ end
273
+ end
256
274
 
257
- # Called when parser leaves a BibTeX object.
258
- def leave_object
259
- @mode, @active_object, @brace_level = :meta, nil, 0
260
- end
275
+ # Called when parser leaves a BibTeX object.
276
+ def leave_object
277
+ @mode, @active_object, @brace_level = :meta, nil, 0
278
+ end
261
279
 
262
- def error_unbalanced_braces
263
- BibTeX.log.warn("Lexer: unbalanced braces at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
264
- backtrace [:E_UNBALANCED, @scanner.matched]
265
- end
266
-
267
- def error_unterminated_string
268
- BibTeX.log.warn("Lexer: unterminated string at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
269
- backtrace [:E_UNTERMINATED_STRING, @scanner.matched]
270
- end
280
+ def error_unbalanced_braces
281
+ BibTeX.log.warn("Lexer: unbalanced braces at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
282
+ backtrace [:E_UNBALANCED, @scanner.matched]
283
+ end
284
+
285
+ def error_unterminated_string
286
+ BibTeX.log.warn("Lexer: unterminated string at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
287
+ backtrace [:E_UNTERMINATED_STRING, @scanner.matched]
288
+ end
271
289
 
272
- def error_unterminated_content
273
- BibTeX.log.warn("Lexer: unterminated content at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
274
- backtrace [:E_UNTERMINATED_CONTENT, @scanner.matched]
275
- end
276
-
277
- def error_unexpected_token
278
- BibTeX.log.warn("Lexer: unexpected token `#{@scanner.matched}' at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
279
- backtrace [:E_UNEXPECTED_TOKEN, @scanner.matched]
280
- end
290
+ def error_unterminated_content
291
+ BibTeX.log.warn("Lexer: unterminated content at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
292
+ backtrace [:E_UNTERMINATED_CONTENT, @scanner.matched]
293
+ end
294
+
295
+ def error_unexpected_token
296
+ BibTeX.log.warn("Lexer: unexpected token `#{@scanner.matched}' at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
297
+ backtrace [:E_UNEXPECTED_TOKEN, @scanner.matched]
298
+ end
281
299
 
282
- def error_unexpected_object
283
- BibTeX.log.warn("Lexer: unexpected object at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
284
- backtrace [:E_UNEXPECTED_OBJECT, '@']
285
- end
300
+ def error_unexpected_object
301
+ BibTeX.log.warn("Lexer: unexpected object at #{@scanner.pos}; brace level #{@brace_level}; mode #{@mode.inspect}.")
302
+ backtrace [:E_UNEXPECTED_OBJECT, '@']
303
+ end
286
304
 
287
305
  def backtrace(error)
288
306
  bt = []
@@ -291,6 +309,6 @@ module BibTeX
291
309
  push [:ERROR,bt]
292
310
  end
293
311
 
294
- end
295
-
312
+ end
313
+
296
314
  end