Skip to content
Browse files

+ Parslet::Parser is now also a parslet atom

This allows reuse of grammars in other grammars as if they were simple
grammar atoms
  • Loading branch information...
1 parent 8d37204 commit 1080d75b1e51a861c1429d8cfeb80880a591dfaf @kschiess kschiess committed Feb 16, 2011
Showing with 66 additions and 43 deletions.
  1. +9 −0 HISTORY.txt
  2. +0 −28 lib/parslet.rb
  3. +1 −1 lib/parslet/atoms/visitor.rb
  4. +36 −1 lib/parslet/parser.rb
  5. +1 −1 parslet.gemspec
  6. +19 −0 spec/parslet/parser_spec.rb
  7. +0 −12 spec/parslet/parslet_spec.rb
View
9 HISTORY.txt
@@ -1,3 +1,12 @@
+= 1.2.0 / ???
+
+ + Parslet::Parser is now also a grammar atom, it can be composed freely with
+ other atoms. (str('f') >> MiniLispParser.new >> str('b'))
+
+ + No strings, only slices are returned as part of the parser result.
+ Parslet::Slice is almost a string class, but one that remembers the
+ source offset. This has also bought us a slight speedup.
+
= 1.1.1 / 4Feb2011
! FIX: Line counting was broken by performance optimisations.
View
28 lib/parslet.rb
@@ -68,34 +68,6 @@ class ParseFailed < StandardError
end
module ClassMethods
- # Define the parsers #root function. This is the place where you start
- # parsing; if you have a rule for 'file' that describes what should be
- # in a file, this would be your root declaration:
- #
- # class Parser
- # root :file
- # rule(:file) { ... }
- # end
- #
- # #root declares a 'parse' function that works just like the parse
- # function that you can call on a simple parslet, taking a string as input
- # and producing parse output.
- #
- # In a way, #root is a shorthand for:
- #
- # def parse(str)
- # your_parser_root.parse(str)
- # end
- #
- def root(name)
- define_method(:root) do
- self.send(name)
- end
- define_method(:parse) do |str|
- root.parse(str)
- end
- end
-
# Define an entity for the parser. This generates a method of the same
# name that can be used as part of other patterns. Those methods can be
# freely mixed in your parser class with real ruby methods.
View
2 lib/parslet/atoms/visitor.rb
@@ -5,7 +5,7 @@
module Parslet::Atoms
class Base
def accept(visitor)
- raise NotImplementedError, "No visit method on #{self.class.name}."
+ raise NotImplementedError, "No #accept method on #{self.class.name}."
end
end
View
37 lib/parslet/parser.rb
@@ -12,6 +12,41 @@
# pp MyParser.new.parse('bbbb') # => Parslet::Atoms::ParseFailed:
# # Don't know what to do with bbbb at line 1 char 1.
#
-class Parslet::Parser
+class Parslet::Parser < Parslet::Atoms::Base
include Parslet
+
+ class <<self # class methods
+ # Define the parsers #root function. This is the place where you start
+ # parsing; if you have a rule for 'file' that describes what should be
+ # in a file, this would be your root declaration:
+ #
+ # class Parser
+ # root :file
+ # rule(:file) { ... }
+ # end
+ #
+ # #root declares a 'parse' function that works just like the parse
+ # function that you can call on a simple parslet, taking a string as input
+ # and producing parse output.
+ #
+ # In a way, #root is a shorthand for:
+ #
+ # def parse(str)
+ # your_parser_root.parse(str)
+ # end
+ #
+ def root(name)
+ define_method(:root) do
+ self.send(name)
+ end
+ end
+ end
+
+ def try(source, context) # :nodoc:
+ root.try(source, context)
+ end
+
+ def to_s_inner(prec) # :nodoc:
+ root.to_s(prec)
+ end
end
View
2 parslet.gemspec
@@ -2,7 +2,7 @@
Gem::Specification.new do |s|
s.name = 'parslet'
- s.version = '1.1.1'
+ s.version = '1.2.0'
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
s.authors = ['Kaspar Schiess']
View
19 spec/parslet/parser_spec.rb
@@ -1,12 +1,31 @@
require 'spec_helper'
describe Parslet::Parser do
+ include Parslet
class FooParser < Parslet::Parser
rule(:foo) { str('foo') }
root(:foo)
end
+ describe "<- .root" do
+ parser = Class.new(Parslet::Parser)
+ parser.root :root_parslet
+
+ it "should have defined a 'root' method, returning the root" do
+ parser_instance = parser.new
+ flexmock(parser_instance).should_receive(:root_parslet => :answer)
+
+ parser_instance.root.should == :answer
+ end
+ end
it "should parse 'foo'" do
FooParser.new.parse('foo').should == 'foo'
end
+ context "composition" do
+ let(:parser) { FooParser.new }
+ it "should allow concatenation" do
+ composite = parser >> str('bar')
+ composite.should parse('foobar')
+ end
+ end
end
View
12 spec/parslet/parslet_spec.rb
@@ -12,18 +12,6 @@
end
end
end
- describe "<- .root" do
- let(:root_parslet) { flexmock() }
- root :root_parslet
-
- it "should have defined a 'parse' method in the current context" do
- root_parslet.should_receive(:parse).with('snaf').once
- parse('snaf')
- end
- it "should have defined a 'root' method, returning the root" do
- root.should == root_parslet
- end
- end
describe "<- .rule" do
# Rules define methods. This can be easily tested by defining them right
# here.

0 comments on commit 1080d75

Please sign in to comment.
Something went wrong with that request. Please try again.