parser 2.0.0.pre1 → 2.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7973cc0cb9684725de9513915f651e9a29f92f0d
4
- data.tar.gz: 81a7f321cf682eef0e757d64caec77174bb6235f
3
+ metadata.gz: f4144b03e5cb0074bd4e6a62442b3954365d7ec8
4
+ data.tar.gz: 4276d7b16e60596143e0cc22b19ef0f048446af5
5
5
  SHA512:
6
- metadata.gz: 74b994314eb82cbc91bd82447a44a845feec9b029e486adcd90e877997a8dfac9f7b73f08bb36729cd947e7c36d3d681e8f883e36cef7d977828f9519ba3131f
7
- data.tar.gz: a0fb0601b946660f1f7eaac97d3b48bab9b1838f30e45eb7b10d4eb004949c90adc32a42f071d2dad7f8f2397cf4ea79ae605d6003cfc23dddc7f4d276a258c6
6
+ metadata.gz: 644d1bb91060042670f4602788785bec67c8cc594ffa44d78922e74ba8201d954789e9b8953632b8f2c13b11efe1a2588cdde7bed8b3718c40189dad766104c0
7
+ data.tar.gz: 75a5830a2a534f63663e83caf4333f5d462a2a591bc72adec2a09d61fc90a2f2d3ea106c26d37df225949beb6e6139c2b2033e76d1448ec0f365160bc28d6ba7
@@ -1,6 +1,16 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ v2.0.0.pre2 (2013-07-11)
5
+ ------------------------
6
+
7
+ Features implemented:
8
+ * Allow to differentiate between __FILE__/__LINE__ and literals (closes #89). (Peter Zotov)
9
+ * Add attribute `diagnostic' to Parser::SyntaxError (closes #88). (Peter Zotov)
10
+
11
+ Bugs fixed:
12
+ * Don't treat byte order mark as an identifier (closes #91). (Peter Zotov)
13
+
4
14
  v2.0.0.beta10 (2013-07-02)
5
15
  --------------------------
6
16
 
data/README.md CHANGED
@@ -5,143 +5,194 @@
5
5
  [![Code Climate](https://codeclimate.com/github/whitequark/parser.png)](https://codeclimate.com/github/whitequark/parser)
6
6
  [![Coverage Status](https://coveralls.io/repos/whitequark/parser/badge.png?branch=master)](https://coveralls.io/r/whitequark/parser)
7
7
 
8
- _Parser_ is a production-ready Ruby parser written in pure Ruby. It
9
- performs on par or better than Ripper, Melbourne, JRubyParser or
10
- ruby_parser.
8
+ _Parser_ is a production-ready Ruby parser written in pure Ruby. It performs on
9
+ par or better than Ripper, Melbourne, JRubyParser or ruby\_parser.
11
10
 
12
- You can also use [unparser](https://github.com/mbj/unparser) to produce equivalent source code from Parser's ASTs.
11
+ You can also use [unparser](https://github.com/mbj/unparser) to produce
12
+ equivalent source code from Parser's ASTs.
13
13
 
14
14
  ## Installation
15
15
 
16
- Most recent version of Parser is 2.0; however, per [release schedule](https://github.com/whitequark/parser/issues/51), it stays in the beta status for a while. However, it handles much more input than stable 1.x branch, and for new work it is advisable to use the beta versions.
16
+ Most recent version of Parser is 2.0; however, per
17
+ [release schedule](https://github.com/whitequark/parser/issues/51), it stays in
18
+ the beta status for a while. However, it handles much more input than stable
19
+ 1.x branch, and for new work it is advisable to use the beta versions.
17
20
 
18
- ~~~
19
- $ gem install parser --pre
20
- ~~~
21
+ $ gem install parser --pre
21
22
 
22
23
  ## Usage
23
24
 
24
25
  Parse a chunk of code:
25
26
 
26
- ~~~ ruby
27
- require 'parser/current'
27
+ require 'parser/current'
28
28
 
29
- p Parser::CurrentRuby.parse("2 + 2")
30
- # (send
31
- # (int 2) :+
32
- # (int 2))
33
- ~~~
29
+ p Parser::CurrentRuby.parse("2 + 2")
30
+ # (send
31
+ # (int 2) :+
32
+ # (int 2))
34
33
 
35
34
  Access the AST's source map:
36
35
 
37
- ~~~ ruby
38
- p Parser::CurrentRuby.parse("2 + 2").loc
39
- # #<Parser::Source::Map::Send:0x007fe0ca8a69b8
40
- # @begin=nil,
41
- # @end=nil,
42
- # @expression=#<Source::Range (string) 0...5>,
43
- # @selector=#<Source::Range (string) 2...3>>
36
+ p Parser::CurrentRuby.parse("2 + 2").loc
37
+ # #<Parser::Source::Map::Send:0x007fe0ca8a69b8
38
+ # @begin=nil,
39
+ # @end=nil,
40
+ # @expression=#<Source::Range (string) 0...5>,
41
+ # @selector=#<Source::Range (string) 2...3>>
44
42
 
45
- p Parser::CurrentRuby.parse("2 + 2").loc.selector.to_source
46
- # "+"
47
- ~~~
43
+ p Parser::CurrentRuby.parse("2 + 2").loc.selector.to_source
44
+ # "+"
48
45
 
49
46
  Parse a chunk of code and display all diagnostics:
50
47
 
51
- ~~~ ruby
52
- parser = Parser::CurrentRuby.new
53
- parser.diagnostics.consumer = lambda do |diag|
54
- puts diag.render
55
- end
56
-
57
- buffer = Parser::Source::Buffer.new('(string)')
58
- buffer.source = "foo *bar"
59
-
60
- p parser.parse(buffer)
61
- # (string):1:5: warning: `*' interpreted as argument prefix
62
- # foo *bar
63
- # ^
64
- # (send nil :foo
65
- # (splat
66
- # (send nil :bar)))
67
- ~~~
68
-
69
- If you reuse the same parser object for multiple `#parse` runs, you need to `#reset` it.
70
-
71
- You can also use the `ruby-parse` utility (it's bundled with the gem) to play with Parser:
72
-
73
- ~~~
74
- $ ruby-parse -L -e "2+2"
75
- (send
76
- (int 2) :+
77
- (int 2))
78
- 2+2
79
- ~ selector
80
- ~~~ expression
81
- (int 2)
82
- 2+2
83
- ~ expression
84
- (int 2)
85
- 2+2
86
-
87
- $ ruby-parse -E -e "2+2"
88
- 2+2
89
- ^ tINTEGER 2 expr_end [0 <= cond] [0 <= cmdarg]
90
- 2+2
91
- ^ tPLUS "+" expr_beg [0 <= cond] [0 <= cmdarg]
92
- 2+2
93
- ^ tINTEGER 2 expr_end [0 <= cond] [0 <= cmdarg]
94
- 2+2
95
- ^ false "$eof" expr_end [0 <= cond] [0 <= cmdarg]
96
- (send
97
- (int 2) :+
98
- (int 2))
99
- ~~~
48
+ parser = Parser::CurrentRuby.new
49
+ parser.diagnostics.consumer = lambda do |diag|
50
+ puts diag.render
51
+ end
52
+
53
+ buffer = Parser::Source::Buffer.new('(string)')
54
+ buffer.source = "foo *bar"
55
+
56
+ p parser.parse(buffer)
57
+ # (string):1:5: warning: `*' interpreted as argument prefix
58
+ # foo *bar
59
+ # ^
60
+ # (send nil :foo
61
+ # (splat
62
+ # (send nil :bar)))
63
+
64
+ If you reuse the same parser object for multiple `#parse` runs, you need to
65
+ `#reset` it.
66
+
67
+ You can also use the `ruby-parse` utility (it's bundled with the gem) to play
68
+ with Parser:
69
+
70
+ $ ruby-parse -L -e "2+2"
71
+ (send
72
+ (int 2) :+
73
+ (int 2))
74
+ 2+2
75
+ ~ selector
76
+ ~~~ expression
77
+ (int 2)
78
+ 2+2
79
+ ~ expression
80
+ (int 2)
81
+ 2+2
82
+
83
+ $ ruby-parse -E -e "2+2"
84
+ 2+2
85
+ ^ tINTEGER 2 expr_end [0 <= cond] [0 <= cmdarg]
86
+ 2+2
87
+ ^ tPLUS "+" expr_beg [0 <= cond] [0 <= cmdarg]
88
+ 2+2
89
+ ^ tINTEGER 2 expr_end [0 <= cond] [0 <= cmdarg]
90
+ 2+2
91
+ ^ false "$eof" expr_end [0 <= cond] [0 <= cmdarg]
92
+ (send
93
+ (int 2) :+
94
+ (int 2))
100
95
 
101
96
  ## Features
102
97
 
103
- * Precise source location reporting.
104
- * [Documented](doc/AST_FORMAT.md) AST format which is convenient to work with.
105
- * A simple interface and a powerful, tweakable one.
106
- * Parses 1.8, 1.9, 2.0 and 2.1 (preliminary) syntax with backwards-compatible AST formats.
107
- * Parsing error recovery.
108
- * Improved [clang-like][] diagnostic messages with location information.
109
- * Written in pure Ruby, runs on MRI 1.8.7 or >=1.9.2, JRuby and Rubinius in 1.8 and 1.9 mode.
110
- * Only two runtime dependencies: the gems [ast][] and [slop][].
111
- * [Insane][insane-lexer] Ruby lexer rewritten from scratch in Ragel.
112
- * 100% test coverage for Bison grammars (except error recovery).
113
- * Readable, commented source code.
114
-
115
- [clang-like]: http://clang.llvm.org/diagnostics.html
116
- [ast]: http://rubygems.org/gems/ast
117
- [slop]: http://rubygems.org/gems/slop
118
- [insane-lexer]: http://whitequark.org/blog/2013/04/01/ruby-hacking-guide-ch-11-finite-state-lexer/
98
+ * Precise source location reporting.
99
+ * [Documented](doc/AST_FORMAT.md) AST format which is convenient to work with.
100
+ * A simple interface and a powerful, tweakable one.
101
+ * Parses 1.8, 1.9, 2.0 and 2.1 (preliminary) syntax with backwards-compatible
102
+ AST formats.
103
+ * Parsing error recovery.
104
+ * Improved [clang-like][] diagnostic messages with location information.
105
+ * Written in pure Ruby, runs on MRI 1.8.7 or >=1.9.2, JRuby and Rubinius in 1.8
106
+ and 1.9 mode.
107
+ * Only two runtime dependencies: the gems [ast][] and [slop][].
108
+ * [Insane][insane-lexer] Ruby lexer rewritten from scratch in Ragel.
109
+ * 100% test coverage for Bison grammars (except error recovery).
110
+ * Readable, commented source code.
111
+
112
+ [clang-like]: http://clang.llvm.org/diagnostics.html
113
+ [ast]: http://rubygems.org/gems/ast
114
+ [slop]: http://rubygems.org/gems/slop
115
+ [insane-lexer]: http://whitequark.org/blog/2013/04/01/ruby-hacking-guide-ch-11-finite-state-lexer/
119
116
 
120
117
  ## Documentation
121
118
 
122
- Documentation for parser is available online on [rdoc.info](http://rdoc.info/github/whitequark/parser).
119
+ Documentation for parser is available online on
120
+ [rdoc.info](http://rdoc.info/github/whitequark/parser).
121
+
122
+ ### Node names
123
+
124
+ Several Parser nodes seem to be confusing enough to warrant a dedicated README section.
125
+
126
+ #### (block)
127
+
128
+ The `(block)` node passes a Ruby block, that is, a closure, to a method call represented by its first child, a `send` node. To demonstrate:
129
+
130
+ ```
131
+ $ ruby-parse -e 'foo { |x| x + 2 }'
132
+ (block
133
+ (send nil :foo)
134
+ (args
135
+ (arg :x))
136
+ (send
137
+ (lvar :x) :+
138
+ (int 2)))
139
+ ```
140
+
141
+ #### (begin) and (kwbegin)
142
+
143
+ **TL;DR: Unless you perform rewriting, treat `(begin)` and `(kwbegin)` as the same node type.**
144
+
145
+ Both `(begin)` and `(kwbegin)` nodes represent compound statements, that is, several expressions which are executed sequentally and the value of the last one is the value of entire compound statement. They may take several forms in the source code:
146
+
147
+ * `foo; bar`: without delimiters
148
+ * `(foo; bar)`: parenthesized
149
+ * `begin foo; bar; end`: grouped with `begin` keyword
150
+ * `def x; foo; bar; end`: grouped inside a method definition
151
+
152
+ and so on.
153
+
154
+ Note that, despite its name, `kwbegin` node only has tangential relation to the `begin` keyword. Normally, Parser AST is semantic, that is, if two constructs look differently but behave identically, they get parsed to the same node. However, there exists a peculiar construct called post-loop in Ruby:
155
+
156
+ ```
157
+ begin
158
+ body
159
+ end while condition
160
+ ```
161
+
162
+ This specific syntactic construct, that is, keyword `begin..end` block followed by a postfix `while`, [behaves][postloop] very unlike other similar constructs, e.g. `(body) while condition`. While the body itself is wrapped into a `while-post` node, Parser also supports rewriting, and in that context it is important to not accidentally convert one kind of loop into another.
163
+
164
+ [postloop]: http://rosettacode.org/wiki/Loops/Do-while#Ruby
165
+
166
+ (Parser also needs the `(kwbegin)` node type internally, and it is highly problematic to map it back to `(begin)`.)
123
167
 
124
168
  ## Known issues
125
169
 
126
170
  ### Void value expressions
127
171
 
128
- So-called "void value expressions" are not handled by Parser. For a description of what a void value expression is, see [this gist](https://gist.github.com/JoshCheek/5625007) and [this Parser issue](https://github.com/whitequark/parser/issues/72).
172
+ So-called "void value expressions" are not handled by Parser. For a description
173
+ of what a void value expression is, see [this
174
+ gist](https://gist.github.com/JoshCheek/5625007) and [this Parser
175
+ issue](https://github.com/whitequark/parser/issues/72).
129
176
 
130
- It is not clear which rules this piece of static analysis follows, or which problem does it solve. It is not implemented because there is no clear specification allowing us to verify the behavior.
177
+ It is not clear which rules this piece of static analysis follows, or which
178
+ problem does it solve. It is not implemented because there is no clear
179
+ specification allowing us to verify the behavior.
131
180
 
132
181
  ## Contributors
133
182
 
134
- * Peter Zotov ([whitequark][])
135
- * Magnus Holm ([judofyr][])
183
+ * Peter Zotov ([whitequark][])
184
+ * Magnus Holm ([judofyr][])
136
185
 
137
- [whitequark]: https://github.com/whitequark
138
- [judofyr]: https://github.com/judofyr
186
+ [whitequark]: https://github.com/whitequark
187
+ [judofyr]: https://github.com/judofyr
139
188
 
140
189
  ## Acknowledgements
141
190
 
142
- The lexer testsuite is derived from [ruby_parser](http://github.com/seattlerb/ruby_parser).
191
+ The lexer testsuite is derived from
192
+ [ruby\_parser](http://github.com/seattlerb/ruby_parser).
143
193
 
144
- The Bison parser rules are derived from [Ruby MRI](http://github.com/ruby/ruby) parse.y.
194
+ The Bison parser rules are derived from [Ruby MRI](http://github.com/ruby/ruby)
195
+ parse.y.
145
196
 
146
197
  ## Contributing
147
198
 
@@ -74,7 +74,7 @@ module Parser
74
74
  :no_dot_digit_literal => 'no .<digit> floating literal anymore; put 0 before dot',
75
75
  :bare_backslash => 'bare backslash only allowed before newline',
76
76
  :unexpected => "unexpected `%{character}'",
77
- :embedded_document => 'embedded document meats end of file (and they embark on a romantic journey)',
77
+ :embedded_document => 'embedded document meets end of file (and they embark on a romantic journey)',
78
78
 
79
79
  # Lexer warnings
80
80
  :invalid_escape_use => 'invalid character syntax; use ?%{escape}',
@@ -1,11 +1,28 @@
1
1
  module Parser
2
2
  module AST
3
3
 
4
+ ##
5
+ # {Parser::AST::Node} contains information about a single AST node and its
6
+ # child nodes, it extends the basic `AST::Node` class provided by the "ast"
7
+ # Gem.
8
+ #
9
+ # @!attribute [r] location
10
+ # @return [Parser::Source::Map]
11
+ #
4
12
  class Node < ::AST::Node
5
13
  attr_reader :location
6
14
 
7
15
  alias loc location
8
16
 
17
+ ##
18
+ # Assigns various properties to the current AST node. Currently only the
19
+ # location can be set.
20
+ #
21
+ # @param [Hash] properties
22
+ #
23
+ # @option properties [Parser::Source::Map] :location Location information
24
+ # of the node.
25
+ #
9
26
  def assign_properties(properties)
10
27
  if (location = properties[:location])
11
28
  @location = location
@@ -49,9 +49,19 @@ module Parser
49
49
  end
50
50
 
51
51
  attr_reader :diagnostics
52
+
53
+ attr_reader :builder
54
+
55
+ ##
56
+ # @api internal
57
+ #
52
58
  attr_reader :static_env
53
59
 
60
+ ##
54
61
  # The source file currently being parsed.
62
+ #
63
+ # @api internal
64
+ #
55
65
  attr_reader :source_buffer
56
66
 
57
67
  ##
@@ -2,6 +2,11 @@ module Parser
2
2
 
3
3
  class Builders::Default
4
4
  attr_accessor :parser
5
+ attr_accessor :emit_file_line_as_literals
6
+
7
+ def initialize
8
+ @emit_file_line_as_literals = true
9
+ end
5
10
 
6
11
  #
7
12
  # Literals
@@ -257,12 +262,20 @@ module Parser
257
262
  def accessible(node)
258
263
  case node.type
259
264
  when :__FILE__
260
- n(:str, [ node.loc.expression.source_buffer.name ],
261
- node.loc)
265
+ if @emit_file_line_as_literals
266
+ n(:str, [ node.loc.expression.source_buffer.name ],
267
+ node.loc)
268
+ else
269
+ node
270
+ end
262
271
 
263
272
  when :__LINE__
264
- n(:int, [ node.loc.expression.line ],
265
- node.loc)
273
+ if @emit_file_line_as_literals
274
+ n(:int, [ node.loc.expression.line ],
275
+ node.loc)
276
+ else
277
+ node
278
+ end
266
279
 
267
280
  when :__ENCODING__
268
281
  n(:const, [ n(:const, [ nil, :Encoding], nil), :UTF_8 ],
@@ -1,11 +1,44 @@
1
1
  module Parser
2
2
 
3
+ ##
4
+ # {Parser::Diagnostic::Engine} provides a basic API for dealing with
5
+ # diagnostics by delegating them to registered consumers.
6
+ #
7
+ # Basic usage is as following:
8
+ #
9
+ # buffer = Parser::Source::Buffer.new(__FILE__)
10
+ # buffer.code = 'foobar'
11
+ #
12
+ # consumer = lambda do |diagnostic|
13
+ # puts diagnostic.message
14
+ # end
15
+ #
16
+ # engine = Parser::Diagnostic::Engine.new(consumer)
17
+ # diagnostic = Parser::Diagnostic.new(:warning, 'warning!', buffer, 1..2)
18
+ #
19
+ # engine.process(diagnostic) # => "warning!"
20
+ #
21
+ # @!attribute [rw] consumer
22
+ # @return [#call]
23
+ #
24
+ # @!attribute [rw] all_errors_are_fatal
25
+ # When set to `true` any error that is encountered will result in
26
+ # {Parser::SyntaxError} being raised.
27
+ # @return [TrueClass|FalseClass]
28
+ #
29
+ # @!attribute [rw] ignore_warnings
30
+ # When set to `true` warnings will be ignored.
31
+ # @return [TrueClass|FalseClass]
32
+ #
3
33
  class Diagnostic::Engine
4
34
  attr_accessor :consumer
5
35
 
6
36
  attr_accessor :all_errors_are_fatal
7
37
  attr_accessor :ignore_warnings
8
38
 
39
+ ##
40
+ # @param [#call] consumer
41
+ #
9
42
  def initialize(consumer=nil)
10
43
  @consumer = consumer
11
44
 
@@ -13,6 +46,13 @@ module Parser
13
46
  @ignore_warnings = false
14
47
  end
15
48
 
49
+ ##
50
+ # Processes a diagnostic and optionally raises {Parser::SyntaxError} when
51
+ # `all_errors_are_fatal` is set to true.
52
+ #
53
+ # @param [Parser::Diagnostic] diagnostic
54
+ # @return [Parser::Diagnostic::Engine]
55
+ #
16
56
  def process(diagnostic)
17
57
  if ignore?(diagnostic)
18
58
  # do nothing
@@ -21,7 +61,7 @@ module Parser
21
61
  end
22
62
 
23
63
  if raise?(diagnostic)
24
- raise Parser::SyntaxError, diagnostic.message
64
+ raise Parser::SyntaxError, diagnostic
25
65
  end
26
66
 
27
67
  self
@@ -29,11 +69,19 @@ module Parser
29
69
 
30
70
  protected
31
71
 
72
+ ##
73
+ # @param [Parser::Diagnostic] diagnostic
74
+ # @return [TrueClass|FalseClass]
75
+ #
32
76
  def ignore?(diagnostic)
33
77
  @ignore_warnings &&
34
78
  diagnostic.level == :warning
35
79
  end
36
80
 
81
+ ##
82
+ # @param [Parser::Diagnostic] diagnostic
83
+ # @return [TrueClass|FalseClass]
84
+ #
37
85
  def raise?(diagnostic)
38
86
  (@all_errors_are_fatal &&
39
87
  diagnostic.level == :error) ||
@@ -155,6 +155,11 @@ class Parser::Lexer
155
155
  # Patches accepted.
156
156
  #
157
157
  @source = @source_buffer.source + "\0\0\0"
158
+
159
+ if @source.length > 0 && @source[0].ord == 0xfeff
160
+ # Skip byte order mark.
161
+ @p = 1
162
+ end
158
163
  else
159
164
  @source = nil
160
165
  end
@@ -1,5 +1,54 @@
1
1
  module Parser
2
+ ##
3
+ # {Parser::Rewriter} offers a basic API that makes it easy to rewrite
4
+ # existing ASTs. It's built on top of {Parser::AST::Processor} and
5
+ # {Parser::Source::Rewriter}.
6
+ #
7
+ # For example, assume you want to remove `do` tokens from a while statement.
8
+ # You can do this as following:
9
+ #
10
+ # class RemoveDo < Parser::Rewriter
11
+ # def on_while(node)
12
+ # # Check if the statement starts with "do"
13
+ # if node.location.begin.is?('do')
14
+ # remove(node.location.begin)
15
+ # end
16
+ # end
17
+ # end
18
+ #
19
+ # code = <<-EOF
20
+ # while true do
21
+ # puts 'hello'
22
+ # end
23
+ # EOF
24
+ #
25
+ # buffer = Parser::Source::Buffer.new('(example)')
26
+ # buffer.code = code
27
+ # parser = Parser::CurrentRuby.new
28
+ # ast = parser.parse(buffer)
29
+ # rewriter = RemoveDo.new
30
+ #
31
+ # # Rewrite the AST, returns a String with the new form.
32
+ # puts rewriter.rewrite(buffer, ast)
33
+ #
34
+ # This would result in the following Ruby code:
35
+ #
36
+ # while true
37
+ # puts 'hello'
38
+ # end
39
+ #
40
+ # Keep in mind that {Parser::Rewriter} does not take care of indentation when
41
+ # inserting/replacing code so you'll have to do this yourself.
42
+ #
2
43
  class Rewriter < Parser::AST::Processor
44
+ ##
45
+ # Rewrites the AST/source buffer and returns a String containing the new
46
+ # version.
47
+ #
48
+ # @param [Parser::Source::Buffer] source_buffer
49
+ # @param [Parser::AST::Node] ast
50
+ # @return [String]
51
+ #
3
52
  def rewrite(source_buffer, ast)
4
53
  @source_rewriter = Source::Rewriter.new(source_buffer)
5
54
 
@@ -10,22 +59,52 @@ module Parser
10
59
 
11
60
  private
12
61
 
62
+ ##
63
+ # Returns `true` if the specified node is an assignment node, returns false
64
+ # otherwise.
65
+ #
66
+ # @param [Parser::AST::Node] node
67
+ # @return [TrueClass|FalseClass]
68
+ #
13
69
  def assignment?(node)
14
70
  [:lvasgn, :ivasgn, :gvasgn, :cvasgn, :casgn].include?(node.type)
15
71
  end
16
72
 
73
+ ##
74
+ # Removes the source range.
75
+ #
76
+ # @param [Parser::Source::Range] range
77
+ #
17
78
  def remove(range)
18
79
  @source_rewriter.remove(range)
19
80
  end
20
81
 
82
+ ##
83
+ # Inserts new code before the given source range.
84
+ #
85
+ # @param [Parser::Source::Range] range
86
+ # @param [String] content
87
+ #
21
88
  def insert_before(range, content)
22
89
  @source_rewriter.insert_before(range, content)
23
90
  end
24
91
 
92
+ ##
93
+ # Inserts new code after the given source range.
94
+ #
95
+ # @param [Parser::Source::Range] range
96
+ # @param [String] content
97
+ #
25
98
  def insert_after(range, content)
26
99
  @source_rewriter.insert_after(range, content)
27
100
  end
28
101
 
102
+ ##
103
+ # Replaces the code of the source range `range` with `content`.
104
+ #
105
+ # @param [Parser::Source::Range] range
106
+ # @param [String] content
107
+ #
29
108
  def replace(range, content)
30
109
  @source_rewriter.replace(range, content)
31
110
  end
@@ -1,3 +1,14 @@
1
1
  module Parser
2
- class SyntaxError < StandardError; end
2
+ ##
3
+ # {Parser::SyntaxError} is raised whenever parser detects a syntax error
4
+ # (what a surprise!) similar to the standard SyntaxError class.
5
+ #
6
+ class SyntaxError < StandardError
7
+ attr_reader :diagnostic
8
+
9
+ def initialize(diagnostic)
10
+ @diagnostic = diagnostic
11
+ super(diagnostic.message)
12
+ end
13
+ end
3
14
  end
@@ -1,3 +1,3 @@
1
1
  module Parser
2
- VERSION = '2.0.0.pre1'
2
+ VERSION = '2.0.0.pre2'
3
3
  end
@@ -32,10 +32,12 @@ class TestDiagnosticEngine < Minitest::Test
32
32
 
33
33
  error = Parser::Diagnostic.new(:error, 'foo', @buffer, 1..2)
34
34
 
35
- assert_raises Parser::SyntaxError do
35
+ err = assert_raises Parser::SyntaxError, "foo" do
36
36
  @engine.process(error)
37
37
  end
38
38
 
39
+ assert_equal error, err.diagnostic
40
+
39
41
  assert_equal [error], @queue
40
42
  end
41
43
 
@@ -4315,7 +4315,28 @@ class TestParser < Minitest::Test
4315
4315
  ALL_VERSIONS - %w(1.8 1.9))
4316
4316
  end
4317
4317
 
4318
+ def test_file_line_non_literals
4319
+ with_versions(ALL_VERSIONS) do |_ver, parser|
4320
+ parser.builder.emit_file_line_as_literals = false
4321
+
4322
+ source_file = Parser::Source::Buffer.new('(comments)')
4323
+ source_file.source = "[__FILE__, __LINE__]"
4324
+
4325
+ ast = parser.parse(source_file)
4326
+
4327
+ assert_equal s(:array, s(:__FILE__), s(:__LINE__)), ast
4328
+ end
4329
+ end
4330
+
4318
4331
  if defined?(Encoding)
4332
+ def test_bom
4333
+ assert_parses(
4334
+ s(:int, 1),
4335
+ %Q{\xef\xbb\xbf1}.force_encoding(Encoding::BINARY),
4336
+ %q{},
4337
+ %w(1.9 2.0 2.1))
4338
+ end
4339
+
4319
4340
  def test_magic_encoding_comment
4320
4341
  assert_parses(
4321
4342
  s(:begin,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre1
4
+ version: 2.0.0.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Zotov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-04 00:00:00.000000000 Z
11
+ date: 2013-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast