parslet-1.5.0/ 0000755 0001750 0001750 00000000000 12270776314 011666 5 ustar mero mero parslet-1.5.0/metadata.yml 0000644 0001750 0001750 00000015544 12270776314 014202 0 ustar mero mero --- !ruby/object:Gem::Specification
name: parslet
version: !ruby/object:Gem::Version
version: 1.5.0
prerelease:
platform: ruby
authors:
- Kaspar Schiess
autorequire:
bindir: bin
cert_chain: []
date: 2012-12-27 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: blankslate
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ~>
- !ruby/object:Gem::Version
version: '2.0'
none: false
type: :runtime
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ~>
- !ruby/object:Gem::Version
version: '2.0'
none: false
- !ruby/object:Gem::Dependency
name: rspec
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
type: :development
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
- !ruby/object:Gem::Dependency
name: flexmock
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
type: :development
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
- !ruby/object:Gem::Dependency
name: rdoc
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
type: :development
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
- !ruby/object:Gem::Dependency
name: sdoc
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
type: :development
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
- !ruby/object:Gem::Dependency
name: guard
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
type: :development
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
- !ruby/object:Gem::Dependency
name: guard-rspec
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
type: :development
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
- !ruby/object:Gem::Dependency
name: rb-fsevent
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
type: :development
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
- !ruby/object:Gem::Dependency
name: growl
prerelease: false
requirement: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
type: :development
version_requirements: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
description:
email: kaspar.schiess@absurd.li
executables: []
extensions: []
extra_rdoc_files:
- README
files:
- HISTORY.txt
- LICENSE
- Rakefile
- README
- lib/parslet/atoms/alternative.rb
- lib/parslet/atoms/base.rb
- lib/parslet/atoms/can_flatten.rb
- lib/parslet/atoms/capture.rb
- lib/parslet/atoms/context.rb
- lib/parslet/atoms/dsl.rb
- lib/parslet/atoms/dynamic.rb
- lib/parslet/atoms/entity.rb
- lib/parslet/atoms/lookahead.rb
- lib/parslet/atoms/named.rb
- lib/parslet/atoms/re.rb
- lib/parslet/atoms/repetition.rb
- lib/parslet/atoms/scope.rb
- lib/parslet/atoms/sequence.rb
- lib/parslet/atoms/str.rb
- lib/parslet/atoms/visitor.rb
- lib/parslet/atoms.rb
- lib/parslet/cause.rb
- lib/parslet/convenience.rb
- lib/parslet/error_reporter/deepest.rb
- lib/parslet/error_reporter/tree.rb
- lib/parslet/error_reporter.rb
- lib/parslet/export.rb
- lib/parslet/expression/treetop.rb
- lib/parslet/expression.rb
- lib/parslet/parser.rb
- lib/parslet/pattern/binding.rb
- lib/parslet/pattern.rb
- lib/parslet/rig/rspec.rb
- lib/parslet/scope.rb
- lib/parslet/slice.rb
- lib/parslet/source/line_cache.rb
- lib/parslet/source.rb
- lib/parslet/transform/context.rb
- lib/parslet/transform.rb
- lib/parslet.rb
- example/boolean_algebra.rb
- example/calc.rb
- example/capture.rb
- example/comments.rb
- example/deepest_errors.rb
- example/documentation.rb
- example/email_parser.rb
- example/empty.rb
- example/erb.rb
- example/ignore.rb
- example/ip_address.rb
- example/json.rb
- example/local.rb
- example/mathn.rb
- example/minilisp.rb
- example/modularity.rb
- example/nested_errors.rb
- example/output/boolean_algebra.out
- example/output/calc.out
- example/output/capture.out
- example/output/comments.out
- example/output/deepest_errors.out
- example/output/documentation.err
- example/output/documentation.out
- example/output/email_parser.out
- example/output/empty.err
- example/output/erb.out
- example/output/ignore.out
- example/output/ignore_whitespace.out
- example/output/ip_address.out
- example/output/json.out
- example/output/local.out
- example/output/mathn.out
- example/output/minilisp.out
- example/output/modularity.out
- example/output/nested_errors.out
- example/output/parens.out
- example/output/readme.out
- example/output/scopes.out
- example/output/seasons.out
- example/output/sentence.out
- example/output/simple_xml.out
- example/output/string_parser.out
- example/parens.rb
- example/readme.rb
- example/scopes.rb
- example/seasons.rb
- example/sentence.rb
- example/simple.lit
- example/simple_xml.rb
- example/string_parser.rb
- example/test.lit
homepage: http://kschiess.github.com/parslet
licenses: []
post_install_message:
rdoc_options:
- --main
- README
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
required_rubygems_version: !ruby/object:Gem::Requirement
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
none: false
requirements: []
rubyforge_project:
rubygems_version: 1.8.24
signing_key:
specification_version: 3
summary: Parser construction library with great error reporting in Ruby.
test_files: []
has_rdoc:
parslet-1.5.0/example/ 0000755 0001750 0001750 00000000000 12270776314 013321 5 ustar mero mero parslet-1.5.0/example/test.lit 0000644 0001750 0001750 00000000210 12270776314 015003 0 ustar mero mero "THis is a string"
"This is another string"
"This string is escaped \"embedded quoted stuff \" "
12 // an integer literal and a comment
parslet-1.5.0/example/string_parser.rb 0000644 0001750 0001750 00000002601 12270776314 016527 0 ustar mero mero # A more complex parser that illustrates how a compiler might be constructed.
# The parser recognizes strings and integer literals and constructs almost a
# useful AST from the file contents.
require 'pp'
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
include Parslet
class LiteralsParser < Parslet::Parser
rule :space do
(match '[ ]').repeat(1)
end
rule :literals do
(literal >> eol).repeat
end
rule :literal do
(integer | string).as(:literal) >> space.maybe
end
rule :string do
str('"') >>
(
(str('\\') >> any) |
(str('"').absent? >> any)
).repeat.as(:string) >>
str('"')
end
rule :integer do
match('[0-9]').repeat(1).as(:integer)
end
rule :eol do
line_end.repeat(1)
end
rule :line_end do
crlf >> space.maybe
end
rule :crlf do
match('[\r\n]').repeat(1)
end
root :literals
end
input_name = File.join(File.dirname(__FILE__), 'simple.lit')
file = File.read(input_name)
parsetree = LiteralsParser.new.parse(file)
class Lit < Struct.new(:text)
def to_s
text.inspect
end
end
class StringLit < Lit
end
class IntLit < Lit
def to_s
text
end
end
transform = Parslet::Transform.new do
rule(:literal => {:integer => simple(:x)}) { IntLit.new(x) }
rule(:literal => {:string => simple(:s)}) { StringLit.new(s) }
end
ast = transform.apply(parsetree)
pp ast
parslet-1.5.0/example/simple_xml.rb 0000644 0001750 0001750 00000002347 12270776314 016025 0 ustar mero mero # A simple xml parser. It is simple in the respect as that it doesn't address
# any of the complexities of XML. This is ruby 1.9.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'pp'
require 'parslet'
class XML < Parslet::Parser
root :document
rule(:document) {
tag(close: false).as(:o) >> document.as(:i) >> tag(close: true).as(:c) |
text
}
# Perhaps we could have some syntax sugar to make this more easy?
#
def tag(opts={})
close = opts[:close] || false
parslet = str('<')
parslet = parslet >> str('/') if close
parslet = parslet >> (str('>').absent? >> match("[a-zA-Z]")).repeat(1).as(:name)
parslet = parslet >> str('>')
parslet
end
rule(:text) {
match('[^<>]').repeat(0)
}
end
def check(xml)
r = XML.new.parse(xml)
# We'll validate the tree by reducing valid pairs of tags into simply the
# string "verified". If the transformation ends on a string, then the
# document was 'valid'.
#
t = Parslet::Transform.new do
rule(
o: {name: simple(:tag)},
c: {name: simple(:tag)},
i: simple(:t)
) { 'verified' }
end
t.apply(r)
end
pp check("some text in the tags")
pp check("some text in the tags")
parslet-1.5.0/example/simple.lit 0000644 0001750 0001750 00000000052 12270776314 015321 0 ustar mero mero 123
12345
" Some String with \"escapes\""
parslet-1.5.0/example/sentence.rb 0000644 0001750 0001750 00000002775 12270776314 015465 0 ustar mero mero # encoding: UTF-8
# A small example contributed by John Mettraux (jmettraux) that demonstrates
# working with Unicode. This only works on Ruby 1.9.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
class Parser < Parslet::Parser
rule(:sentence) { (match('[^。]').repeat(1) >> str("。")).as(:sentence) }
rule(:sentences) { sentence.repeat }
root(:sentences)
end
class Transformer < Parslet::Transform
rule(:sentence => simple(:sen)) { sen.to_s }
end
string =
"RubyKaigi2009のテーマは、「変わる/変える」です。 前回の" +
"RubyKaigi2008のテーマであった「多様性」の言葉の通り、 " +
"2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 " +
"ますます多様化が進みつつあります。RubyKaigi2008は、そのような " +
"Rubyの生態系をあらためて認識する場となりました。 しかし、" +
"こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、" +
"その違いを認識したところであまり意味がありません。 異なる実装、" +
"異なる思想、異なる背景といった、様々な多様性を理解しつつ、 " +
"すり合わせるべきものをすり合わせ、変えていくべきところを " +
"変えていくことが、豊かな未来へとつながる道に違いありません。"
parser = Parser.new
transformer = Transformer.new
tree = parser.parse(string)
p transformer.apply(tree)
parslet-1.5.0/example/seasons.rb 0000644 0001750 0001750 00000001674 12270776314 015331 0 ustar mero mero $:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
require 'pp'
tree = {:bud => {:stem => []}}
class Spring < Parslet::Transform
rule(:stem => sequence(:branches)) {
{:stem => (branches + [{:branch => :leaf}])}
}
end
class Summer < Parslet::Transform
rule(:stem => subtree(:branches)) {
new_branches = branches.map { |b| {:branch => [:leaf, :flower]} }
{:stem => new_branches}
}
end
class Fall < Parslet::Transform
rule(:branch => sequence(:x)) {
x.each { |e| puts "Fruit!" if e==:flower }
x.each { |e| puts "Falling Leaves!" if e==:leaf }
{:branch => []}
}
end
class Winter < Parslet::Transform
rule(:stem => subtree(:x)) {
{:stem => []}
}
end
def do_seasons(tree)
[Spring, Summer, Fall, Winter].each do |season|
p "And when #{season} comes"
tree = season.new.apply(tree)
pp tree
puts
end
tree
end
# What marvel of life!
tree = do_seasons(tree)
tree = do_seasons(tree)
parslet-1.5.0/example/scopes.rb 0000644 0001750 0001750 00000000422 12270776314 015140 0 ustar mero mero
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
include Parslet
parser = str('a').capture(:a) >> scope { str('b').capture(:a) } >>
dynamic { |s,c| str(c.captures[:a]) }
begin
parser.parse('aba')
puts "parses 'aba'"
rescue
puts "exception!"
end parslet-1.5.0/example/readme.rb 0000644 0001750 0001750 00000001627 12270776314 015111 0 ustar mero mero # The example from the readme. With this, I am making sure that the readme
# 'works'. Is this too messy?
$:.unshift File.dirname(__FILE__) + "/../lib"
# cut here -------------------------------------------------------------------
require 'parslet'
include Parslet
# Constructs a parser using a Parser Expression Grammar like DSL:
parser = str('"') >>
(
str('\\') >> any |
str('"').absent? >> any
).repeat.as(:string) >>
str('"')
# Parse the string and capture parts of the interpretation (:string above)
tree = parser.parse('"This is a \\"String\\" in which you can escape stuff"')
tree # => {:string=>"This is a \\\"String\\\" in which you can escape stuff"}
# Here's how you can grab results from that tree:
transform = Parslet::Transform.new do
rule(:string => simple(:x)) {
puts "String contents: #{x}" }
end
transform.apply(tree)
parslet-1.5.0/example/parens.rb 0000644 0001750 0001750 00000001661 12270776314 015142 0 ustar mero mero # A small example that demonstrates the power of tree pattern matching. Also
# uses '.as(:name)' to construct a tree that can reliably be matched
# afterwards.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'pp'
require 'parslet'
module LISP # as in 'lots of insipid and stupid parenthesis'
class Parser < Parslet::Parser
rule(:balanced) {
str('(').as(:l) >> balanced.maybe.as(:m) >> str(')').as(:r)
}
root(:balanced)
end
class Transform < Parslet::Transform
rule(:l => '(', :m => simple(:x), :r => ')') {
# innermost :m will contain nil
x.nil? ? 1 : x+1
}
end
end
parser = LISP::Parser.new
transform = LISP::Transform.new
%w!
()
(())
((((()))))
((())
!.each do |pexp|
begin
result = parser.parse(pexp)
puts "#{"%20s"%pexp}: #{result.inspect} (#{transform.apply(result)} parens)"
rescue Parslet::ParseFailed => m
puts "#{"%20s"%pexp}: #{m}"
end
puts
end
parslet-1.5.0/example/output/ 0000755 0001750 0001750 00000000000 12270776314 014661 5 ustar mero mero parslet-1.5.0/example/output/string_parser.out 0000644 0001750 0001750 00000000204 12270776314 020270 0 ustar mero mero [#,
#,
#]
parslet-1.5.0/example/output/simple_xml.out 0000644 0001750 0001750 00000000105 12270776314 017557 0 ustar mero mero "verified"
{:o=>{:name=>"b"@1}, :i=>"verified", :c=>{:name=>"a"@33}}
parslet-1.5.0/example/output/sentence.out 0000644 0001750 0001750 00000001574 12270776314 017225 0 ustar mero mero ["RubyKaigi2009のテーマは、「変わる/変える」です。", " 前回のRubyKaigi2008のテーマであった「多様性」の言葉の通り、 2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 ますます多様化が進みつつあります。", "RubyKaigi2008は、そのような Rubyの生態系をあらためて認識する場となりました。", " しかし、こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、その違いを認識したところであまり意味がありません。", " 異なる実装、異なる思想、異なる背景といった、様々な多様性を理解しつつ、 すり合わせるべきものをすり合わせ、変えていくべきところを 変えていくことが、豊かな未来へとつながる道に違いありません。"]
parslet-1.5.0/example/output/seasons.out 0000644 0001750 0001750 00000001002 12270776314 017056 0 ustar mero mero "And when Spring comes"
{:bud=>{:stem=>[{:branch=>:leaf}]}}
"And when Summer comes"
{:bud=>{:stem=>[{:branch=>[:leaf, :flower]}]}}
"And when Fall comes"
Fruit!
Falling Leaves!
{:bud=>{:stem=>[{:branch=>[]}]}}
"And when Winter comes"
{:bud=>{:stem=>[]}}
"And when Spring comes"
{:bud=>{:stem=>[{:branch=>:leaf}]}}
"And when Summer comes"
{:bud=>{:stem=>[{:branch=>[:leaf, :flower]}]}}
"And when Fall comes"
Fruit!
Falling Leaves!
{:bud=>{:stem=>[{:branch=>[]}]}}
"And when Winter comes"
{:bud=>{:stem=>[]}}
parslet-1.5.0/example/output/scopes.out 0000644 0001750 0001750 00000000015 12270776314 016702 0 ustar mero mero parses 'aba'
parslet-1.5.0/example/output/readme.out 0000644 0001750 0001750 00000000104 12270776314 016642 0 ustar mero mero String contents: This is a \"String\" in which you can escape stuff
parslet-1.5.0/example/output/parens.out 0000644 0001750 0001750 00000000660 12270776314 016704 0 ustar mero mero (): {:l=>"("@0, :m=>nil, :r=>")"@1} (1 parens)
(()): {:l=>"("@0, :m=>{:l=>"("@1, :m=>nil, :r=>")"@2}, :r=>")"@3} (2 parens)
((((())))): {:l=>"("@0, :m=>{:l=>"("@1, :m=>{:l=>"("@2, :m=>{:l=>"("@3, :m=>{:l=>"("@4, :m=>nil, :r=>")"@5}, :r=>")"@6}, :r=>")"@7}, :r=>")"@8}, :r=>")"@9} (5 parens)
((()): Failed to match sequence (l:'(' m:(BALANCED?) r:')') at line 1 char 6.
parslet-1.5.0/example/output/nested_errors.out 0000644 0001750 0001750 00000007517 12270776314 020302 0 ustar mero mero --------------------------------------------------------------------------------
. 10 . 20
01
02 define f()
03 @res.name
04 end
05
Failed to match sequence (LINE_SEPARATOR? BLOCK LINE_SEPARATOR?) at line 2 char 5.
`- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 2 char 5.
|- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 2 char 15.
| `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 3 char 11.
| `- Expected at least 1 of SPACE? (COMMENT? NEWLINE / ';') SPACE? at line 3 char 11.
| `- Failed to match sequence (SPACE? (COMMENT? NEWLINE / ';') SPACE?) at line 3 char 11.
| `- Expected one of [COMMENT? NEWLINE, ';'] at line 3 char 11.
| |- Failed to match sequence (COMMENT? NEWLINE) at line 3 char 11.
| | `- Failed to match [\\r\\n] at line 3 char 11.
| `- Expected ";", but got "." at line 3 char 11.
`- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 2 char 5.
`- Expected "begin", but got "defin" at line 2 char 5.
--------------------------------------------------------------------------------
. 10 . 20
01
02 define f()
03 begin
04 @res.name
05 end
06 end
07
Failed to match sequence (LINE_SEPARATOR? BLOCK LINE_SEPARATOR?) at line 2 char 5.
`- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 2 char 5.
|- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 2 char 15.
| `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 2 char 15.
| `- Expected at least 1 of LINE_SEPARATOR (BLOCK / EXPRESSION) at line 2 char 15.
| `- Failed to match sequence (LINE_SEPARATOR (BLOCK / EXPRESSION)) at line 3 char 7.
| `- Expected one of [BLOCK, EXPRESSION] at line 3 char 7.
| |- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 3 char 7.
| | |- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 3 char 7.
| | | `- Expected "define", but got "begin\n" at line 3 char 7.
| | `- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 3 char 12.
| | `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 4 char 13.
| | `- Expected at least 1 of SPACE? (COMMENT? NEWLINE / ';') SPACE? at line 4 char 13.
| | `- Failed to match sequence (SPACE? (COMMENT? NEWLINE / ';') SPACE?) at line 4 char 13.
| | `- Expected one of [COMMENT? NEWLINE, ';'] at line 4 char 13.
| | |- Failed to match sequence (COMMENT? NEWLINE) at line 4 char 13.
| | | `- Failed to match [\\r\\n] at line 4 char 13.
| | `- Expected ";", but got "." at line 4 char 13.
| `- Failed to match sequence (RES_ACTIONS res_field:((':' name:IDENTIFIER)?)) at line 3 char 7.
| `- Failed to match sequence (resources:REFERENCE res_actions:(res_action:RES_ACTION_OR_LINK{0, })) at line 3 char 7.
| `- Failed to match sequence ('@'{1, 2} IDENTIFIER) at line 3 char 7.
| `- Expected at least 1 of '@' at line 3 char 7.
| `- Expected "@", but got "b" at line 3 char 7.
`- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 2 char 5.
`- Expected "begin", but got "defin" at line 2 char 5.
--------------------------------------------------------------------------------
parslet-1.5.0/example/output/modularity.out 0000644 0001750 0001750 00000000000 12270776314 017571 0 ustar mero mero parslet-1.5.0/example/output/minilisp.out 0000644 0001750 0001750 00000000155 12270776314 017237 0 ustar mero mero [:define,
:test,
[:lambda,
[],
[:begin, [:display, "something"@54], [:display, 1], [:display, 3.08]]]]
parslet-1.5.0/example/output/mathn.out 0000644 0001750 0001750 00000000155 12270776314 016522 0 ustar mero mero it terminates before we require mathn
requiring mathn now
and trying again (will hang without the fix)
okay!
parslet-1.5.0/example/output/local.out 0000644 0001750 0001750 00000000240 12270776314 016500 0 ustar mero mero {:e=>"a"@0, :rec=>{:e=>"a"@1, :rec=>{:e=>"a"@2, :rec=>{:e=>"a"@3, :rec=>nil}}}}
e2:'aa' !. / e1:'a' rec:B
{:e1=>"a"@0, :rec=>{:e1=>"a"@1, :rec=>{:e2=>"aa"@2}}}
parslet-1.5.0/example/output/json.out 0000644 0001750 0001750 00000001027 12270776314 016363 0 ustar mero mero
{:array=>[{:number=>"1"@5}, {:number=>"2"@8}, {:number=>"3"@11}, {:null=>"null"@14}, {:string=>"asdfasdf asdfds"@25}, {:object=>{:entry=>{:key=>{:string=>"a"@46}, :val=>{:number=>"-1.2"@50}}}}, {:object=>[{:entry=>{:key=>{:string=>"b"@61}, :val=>{:true=>"true"@65}}}, {:entry=>{:key=>{:string=>"c"@72}, :val=>{:false=>"false"@76}}}]}, {:number=>"0.1e24"@89}, {:true=>"true"@97}, {:false=>"false"@103}, {:array=>{:number=>"1"@112}}]}
[1, 2, 3, nil, "asdfasdf asdfds", {"a"=>-1.2}, {"b"=>true, "c"=>false}, 1.0e+23, true, false, [1]]
parslet-1.5.0/example/output/ip_address.out 0000644 0001750 0001750 00000001116 12270776314 017526 0 ustar mero mero 0.0.0.0 -> {:ipv4=>"0.0.0.0"@0}
255.255.255.255 -> {:ipv4=>"255.255.255.255"@0}
255.255.255 -> Failed: Expected one of [IPV4, IPV6] at line 1 char 1.
1:2:3:4:5:6:7:8 -> {:ipv6=>"1:2:3:4:5:6:7:8"@0}
12AD:34FC:A453:1922:: -> {:ipv6=>"12AD:34FC:A453:1922::"@0}
12AD::34FC -> {:ipv6=>"12AD::34FC"@0}
12AD:: -> {:ipv6=>"12AD::"@0}
:: -> {:ipv6=>"::"@0}
1:2 -> Failed: Expected one of [IPV4, IPV6] at line 1 char 1.
parslet-1.5.0/example/output/ignore_whitespace.out 0000644 0001750 0001750 00000000065 12270776314 021112 0 ustar mero mero [{:a=>"a"@0}, {:a=>"a"@1}, {:a=>"a"@5}, {:a=>"a"@7}]
parslet-1.5.0/example/output/ignore.out 0000644 0001750 0001750 00000000007 12270776314 016672 0 ustar mero mero "ac"@0
parslet-1.5.0/example/output/erb.out 0000644 0001750 0001750 00000000537 12270776314 016167 0 ustar mero mero {:text=>[{:text=>"The value of x is "@0}, {:expression=>{:ruby=>" x "@21}}, {:text=>"."@26}]}
{:text=>[{:code=>{:ruby=>" 1 + 2 "@2}}]}
{:text=>[{:comment=>{:ruby=>" commented "@3}}]}
The not printed result of "a = 2".
The not printed non-evaluated comment "a = 1", see the value of a below.
The nicely printed result.
The value of a is 2, and b is 3.
parslet-1.5.0/example/output/empty.err 0000644 0001750 0001750 00000000203 12270776314 016524 0 ustar mero mero example/empty.rb:13:in `': rule(:empty) { ... } returns nil. Still not implemented, but already used? (NotImplementedError)
parslet-1.5.0/example/output/email_parser.out 0000644 0001750 0001750 00000000163 12270776314 020055 0 ustar mero mero since you haven't specified any EMAIL_ADDR, for testing purposes we're using a.b.c.d@gmail.com
"a.b.c.d@gmail.com"
parslet-1.5.0/example/output/documentation.out 0000644 0001750 0001750 00000000011 12270776314 020253 0 ustar mero mero "aaaa"@0
parslet-1.5.0/example/output/documentation.err 0000644 0001750 0001750 00000000511 12270776314 020241 0 ustar mero mero /Users/kaspar/git_work/own/parslet/lib/parslet/atoms/base.rb:326:in `parse_failed': Don't know what to do with bbbb at line 1 char 1. (Parslet::ParseFailed)
from /Users/kaspar/git_work/own/parslet/lib/parslet/atoms/base.rb:55:in `parse'
from example/documentation.rb:13:in `parse'
from example/documentation.rb:18:in `'
parslet-1.5.0/example/output/deepest_errors.out 0000644 0001750 0001750 00000007531 12270776314 020445 0 ustar mero mero --------------------------------------------------------------------------------
. 10 . 20
01
02 define f()
03 @res.name
04 end
05
Failed to match sequence (LINE_SEPARATOR? BLOCK LINE_SEPARATOR?) at line 2 char 5.
`- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 2 char 5.
|- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 2 char 15.
| `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 3 char 11.
| `- Expected at least 1 of SPACE? (COMMENT? NEWLINE / ';') SPACE? at line 3 char 11.
| `- Failed to match sequence (SPACE? (COMMENT? NEWLINE / ';') SPACE?) at line 3 char 11.
| `- Expected one of [COMMENT? NEWLINE, ';'] at line 3 char 11.
| |- Failed to match sequence (COMMENT? NEWLINE) at line 3 char 11.
| | `- Expected "()", but got "\n " at line 3 char 16.
| `- Expected "()", but got "\n " at line 3 char 16.
`- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 2 char 5.
`- Expected "()", but got "\n " at line 3 char 16.
--------------------------------------------------------------------------------
. 10 . 20
01
02 define f()
03 begin
04 @res.name
05 end
06 end
07
Failed to match sequence (LINE_SEPARATOR? BLOCK LINE_SEPARATOR?) at line 2 char 5.
`- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 2 char 5.
|- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 2 char 15.
| `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 2 char 15.
| `- Expected at least 1 of LINE_SEPARATOR (BLOCK / EXPRESSION) at line 2 char 15.
| `- Failed to match sequence (LINE_SEPARATOR (BLOCK / EXPRESSION)) at line 3 char 7.
| `- Expected one of [BLOCK, EXPRESSION] at line 3 char 7.
| |- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 3 char 7.
| | |- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 3 char 7.
| | | `- Expected "define", but got "begin\n" at line 3 char 7.
| | `- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 3 char 12.
| | `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 4 char 13.
| | `- Expected at least 1 of SPACE? (COMMENT? NEWLINE / ';') SPACE? at line 4 char 13.
| | `- Failed to match sequence (SPACE? (COMMENT? NEWLINE / ';') SPACE?) at line 4 char 13.
| | `- Expected one of [COMMENT? NEWLINE, ';'] at line 4 char 13.
| | |- Failed to match sequence (COMMENT? NEWLINE) at line 4 char 13.
| | | `- Expected "()", but got "\n " at line 4 char 18.
| | `- Expected "()", but got "\n " at line 4 char 18.
| `- Failed to match sequence (RES_ACTIONS res_field:((':' name:IDENTIFIER)?)) at line 3 char 7.
| `- Failed to match sequence (resources:REFERENCE res_actions:(res_action:RES_ACTION_OR_LINK{0, })) at line 3 char 7.
| `- Failed to match sequence ('@'{1, 2} IDENTIFIER) at line 3 char 7.
| `- Expected at least 1 of '@' at line 3 char 7.
| `- Expected "()", but got "\n " at line 4 char 18.
`- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 2 char 5.
`- Expected "()", but got "\n " at line 4 char 18.
--------------------------------------------------------------------------------
parslet-1.5.0/example/output/comments.out 0000644 0001750 0001750 00000000434 12270776314 017240 0 ustar mero mero [{:exp=>{:a=>"a"@3}},
{:line=>"// line comment"@7},
{:exp=>{:a=>"a"@25}},
{:exp=>{:a=>"a"@27}},
{:exp=>[{:a=>"a"@29}, {:line=>"// line comment"@31}]},
{:exp=>[{:a=>"a"@49}, {:multi=>"/* inline comment */"@51}]},
{:exp=>{:a=>"a"@72}},
{:multi=>"/* multiline\n comment */"@77}]
parslet-1.5.0/example/output/capture.out 0000644 0001750 0001750 00000000152 12270776314 017053 0 ustar mero mero [{:line=>"Text1\n"@9},
{:doc=>[{:line=>"Text3\n"@23}, {:line=>"Text4\n"@29}]},
{:line=>"\nText2\n"@41}]
parslet-1.5.0/example/output/calc.out 0000644 0001750 0001750 00000000035 12270776314 016312 0 ustar mero mero 123*2 (command line): -> 246
parslet-1.5.0/example/output/boolean_algebra.out 0000644 0001750 0001750 00000000176 12270776314 020512 0 ustar mero mero {:and=>
{:left=>{:var=>"1"@3},
:right=>{:or=>{:left=>{:var=>"2"@13}, :right=>{:var=>"3"@21}}}}}
[["1", "2"], ["1", "3"]]
parslet-1.5.0/example/nested_errors.rb 0000644 0001750 0001750 00000004340 12270776314 016525 0 ustar mero mero $:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
require 'parslet/convenience'
# This example demonstrates tree error reporting in a real life example.
# The parser code has been contributed by John Mettraux.
def prettify(str)
puts " "*3 + " "*4 + "." + " "*4 + "10" + " "*3 + "." + " "*4 + "20"
str.lines.each_with_index do |line, index|
printf "%02d %s\n",
index+1,
line.chomp
end
end
class Parser < Parslet::Parser
# commons
rule(:space) { match('[ \t]').repeat(1) }
rule(:space?) { space.maybe }
rule(:newline) { match('[\r\n]') }
rule(:comment) { str('#') >> match('[^\r\n]').repeat }
rule(:line_separator) {
(space? >> ((comment.maybe >> newline) | str(';')) >> space?).repeat(1)
}
rule(:blank) { line_separator | space }
rule(:blank?) { blank.maybe }
rule(:identifier) { match('[a-zA-Z0-9_]').repeat(1) }
# res_statement
rule(:reference) {
(str('@').repeat(1,2) >> identifier).as(:reference)
}
rule(:res_action_or_link) {
str('.').as(:dot) >> (identifier >> str('?').maybe ).as(:name) >> str('()')
}
rule(:res_actions) {
(
reference
).as(:resources) >>
(
res_action_or_link.as(:res_action)
).repeat(0).as(:res_actions)
}
rule(:res_statement) {
res_actions >>
(str(':') >> identifier.as(:name)).maybe.as(:res_field)
}
# expression
rule(:expression) {
res_statement
}
# body
rule(:body) {
(line_separator >> (block | expression)).repeat(1).as(:body) >>
line_separator
}
# blocks
rule(:begin_block) {
(str('concurrent').as(:type) >> space).maybe.as(:pre) >>
str('begin').as(:begin) >>
body >>
str('end')
}
rule(:define_block) {
str('define').as(:define) >> space >>
identifier.as(:name) >> str('()') >>
body >>
str('end')
}
rule(:block) {
define_block | begin_block
}
# root
rule(:radix) {
line_separator.maybe >> block >> line_separator.maybe
}
root(:radix)
end
ds = [
%{
define f()
@res.name
end
},
%{
define f()
begin
@res.name
end
end
}
]
ds.each do |d|
puts '-' * 80
prettify(d)
parser = Parser.new
begin
parser.parse_with_debug(d)
end
end
puts '-' * 80 parslet-1.5.0/example/modularity.rb 0000644 0001750 0001750 00000002161 12270776314 016037 0 ustar mero mero $:.unshift File.dirname(__FILE__) + "/../lib"
require 'pp'
require "parslet"
# Demonstrates modular parsers, split out over many classes. Please look at
# ip_address.rb as well.
module ALanguage
include Parslet
# Parslet rules are really a special kind of method. Mix them into your
# classes!
rule(:a_language) { str('aaa') }
end
# Parslet parsers are parslet atoms as well. Create an instance and chain them
# to your other rules.
#
class BLanguage < Parslet::Parser
root :blang
rule(:blang) { str('bbb') }
end
# Parslet atoms are really Ruby values, pass them around.
c_language = Parslet.str('ccc')
class Language < Parslet::Parser
def initialize(c_language)
@c_language = c_language
super()
end
root :root
include ALanguage
rule(:root) { str('a(') >> a_language >> str(')') >> space |
str('b(') >> BLanguage.new >> str(')') >> space |
str('c(') >> @c_language >> str(')') >> space }
rule(:space) { str(' ').maybe }
end
Language.new(c_language).parse('a(aaa)')
Language.new(c_language).parse('b(bbb)')
Language.new(c_language).parse('c(ccc)') parslet-1.5.0/example/minilisp.rb 0000644 0001750 0001750 00000004205 12270776314 015473 0 ustar mero mero # Reproduces [1] using parslet.
# [1] http://thingsaaronmade.com/blog/a-quick-intro-to-writing-a-parser-using-treetop.html
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'pp'
require 'parslet'
require 'parslet/convenience'
module MiniLisp
class Parser < Parslet::Parser
root :expression
rule(:expression) {
space? >> str('(') >> space? >> body >> str(')') >> space?
}
rule(:body) {
(expression | identifier | float | integer | string).repeat.as(:exp)
}
rule(:space) {
match('\s').repeat(1)
}
rule(:space?) {
space.maybe
}
rule(:identifier) {
(match('[a-zA-Z=*]') >> match('[a-zA-Z=*_]').repeat).as(:identifier) >> space?
}
rule(:float) {
(
integer >> (
str('.') >> match('[0-9]').repeat(1) |
str('e') >> match('[0-9]').repeat(1)
).as(:e)
).as(:float) >> space?
}
rule(:integer) {
((str('+') | str('-')).maybe >> match("[0-9]").repeat(1)).as(:integer) >> space?
}
rule(:string) {
str('"') >> (
str('\\') >> any |
str('"').absent? >> any
).repeat.as(:string) >> str('"') >> space?
}
end
class Transform
include Parslet
attr_reader :t
def initialize
@t = Parslet::Transform.new
# To understand these, take a look at what comes out of the parser.
t.rule(:identifier => simple(:ident)) { ident.to_sym }
t.rule(:string => simple(:str)) { str }
t.rule(:integer => simple(:int)) { Integer(int) }
t.rule(:float=>{:integer=> simple(:a), :e=> simple(:b)}) { Float(a + b) }
t.rule(:exp => subtree(:exp)) { exp }
end
def do(tree)
t.apply(tree)
end
end
end
parser = MiniLisp::Parser.new
transform = MiniLisp::Transform.new
result = parser.parse_with_debug %Q{
(define test (lambda ()
(begin
(display "something")
(display 1)
(display 3.08))))
}
# Transform the result
pp transform.do(result) if result
# Thereby reducing it to the earlier problem:
# http://github.com/kschiess/toylisp
parslet-1.5.0/example/mathn.rb 0000644 0001750 0001750 00000002123 12270776314 014753 0 ustar mero mero # Demonstrates that we have a compatibility fix to mathn's weird idea of
# integer mathematics.
# This was contributed by Jonathan Hinkle (https://github.com/hynkle). Thanks!
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
require 'parslet/convenience'
include Parslet
def attempt_parse
possible_whitespace = match['\s'].repeat
cephalopod =
str('octopus') |
str('squid')
parenthesized_cephalopod =
str('(') >>
possible_whitespace >>
cephalopod >>
possible_whitespace >>
str(')')
parser =
possible_whitespace >>
parenthesized_cephalopod >>
possible_whitespace
# This parse fails, but that is not the point. When mathn is in the current
# ruby environment, it modifies integer division in a way that makes
# parslet loop indefinitely.
parser.parse %{(\nsqeed)\n}
rescue Parslet::ParseFailed
end
attempt_parse
puts 'it terminates before we require mathn'
puts "requiring mathn now"
require 'mathn'
puts "and trying again (will hang without the fix)"
attempt_parse # but it doesn't terminate after requiring mathn
puts "okay!" parslet-1.5.0/example/local.rb 0000644 0001750 0001750 00000001656 12270776314 014750 0 ustar mero mero
# An exploration of two ideas:
# a) Constructing a whole parser inline, without the artificial class around
# it.
# and:
# b) Constructing non-greedy or non-blind parsers by transforming the
# grammar.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
include Parslet
a = str('a').repeat >> str('aa')
# E1% E2
#
# S = E2 | E1 S
def this(name, &block); return Parslet::Atoms::Entity.new(name, &block) end
def epsilon; any.absent? end
# Traditional repetition will try as long as the pattern can be matched and
# then give up. This is greedy and blind.
a = str('a').as(:e) >> this('a') { a }.as(:rec) | epsilon
# Here's a pattern match that is greedy and non-blind. The first pattern
# 'a'* will be tried as many times as possible, while still matching the
# end pattern 'aa'.
b = str('aa').as(:e2) >> epsilon | str('a').as(:e1) >> this('b') { b }.as(:rec)
p a.parse('aaaa')
p b
p b.parse('aaaa')
parslet-1.5.0/example/json.rb 0000644 0001750 0001750 00000005207 12270776314 014623 0 ustar mero mero $:.unshift File.dirname(__FILE__) + "/../lib"
#
# MIT License - (c) 2011 John Mettraux
#
require 'rubygems'
require 'parslet' # gem install parslet
module MyJson
class Parser < Parslet::Parser
rule(:spaces) { match('\s').repeat(1) }
rule(:spaces?) { spaces.maybe }
rule(:comma) { spaces? >> str(',') >> spaces? }
rule(:digit) { match('[0-9]') }
rule(:number) {
(
str('-').maybe >> (
str('0') | (match('[1-9]') >> digit.repeat)
) >> (
str('.') >> digit.repeat(1)
).maybe >> (
match('[eE]') >> (str('+') | str('-')).maybe >> digit.repeat(1)
).maybe
).as(:number)
}
rule(:string) {
str('"') >> (
str('\\') >> any | str('"').absent? >> any
).repeat.as(:string) >> str('"')
}
rule(:array) {
str('[') >> spaces? >>
(value >> (comma >> value).repeat).maybe.as(:array) >>
spaces? >> str(']')
}
rule(:object) {
str('{') >> spaces? >>
(entry >> (comma >> entry).repeat).maybe.as(:object) >>
spaces? >> str('}')
}
rule(:value) {
string | number |
object | array |
str('true').as(:true) | str('false').as(:false) |
str('null').as(:null)
}
rule(:entry) {
(
string.as(:key) >> spaces? >>
str(':') >> spaces? >>
value.as(:val)
).as(:entry)
}
rule(:attribute) { (entry | value).as(:attribute) }
rule(:top) { spaces? >> value >> spaces? }
root(:top)
end
class Transformer < Parslet::Transform
class Entry < Struct.new(:key, :val); end
rule(:array => subtree(:ar)) {
ar.is_a?(Array) ? ar : [ ar ]
}
rule(:object => subtree(:ob)) {
(ob.is_a?(Array) ? ob : [ ob ]).inject({}) { |h, e| h[e.key] = e.val; h }
}
rule(:entry => { :key => simple(:ke), :val => simple(:va) }) {
Entry.new(ke, va)
}
rule(:string => simple(:st)) {
st.to_s
}
rule(:number => simple(:nb)) {
nb.match(/[eE\.]/) ? Float(nb) : Integer(nb)
}
rule(:null => simple(:nu)) { nil }
rule(:true => simple(:tr)) { true }
rule(:false => simple(:fa)) { false }
end
def self.parse(s)
parser = Parser.new
transformer = Transformer.new
tree = parser.parse(s)
puts; p tree; puts
out = transformer.apply(tree)
out
end
end
s = %{
[ 1, 2, 3, null,
"asdfasdf asdfds", { "a": -1.2 }, { "b": true, "c": false },
0.1e24, true, false, [ 1 ] ]
}
out = MyJson.parse(s)
p out; puts
out == [
1, 2, 3, nil,
"asdfasdf asdfds", { "a" => -1.2 }, { "b" => true, "c" => false },
0.1e24, true, false, [ 1 ]
] || raise("MyJson is a failure")
parslet-1.5.0/example/ip_address.rb 0000644 0001750 0001750 00000006144 12270776314 015770 0 ustar mero mero # This example is heavily inspired by citrus' ip.citrus. Have a look at both
# of these to get some choice!
# The grammars in this file conform to the ABNF given in Appendix A of RFC 3986
# Uniform Resource Identifier (URI): Generic Syntax.
#
# See http://tools.ietf.org/html/rfc3986#appendix-A for more information.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'pp'
require 'parslet'
module IPv4
include Parslet
# A host identified by an IPv4 literal address is represented in
# dotted-decimal notation (a sequence of four decimal numbers in the range 0
# to 255, separated by "."), as described in [RFC1123] by reference to
# [RFC0952]. Note that other forms of dotted notation may be interpreted on
# some platforms, as described in Section 7.4, but only the dotted-decimal
# form of four octets is allowed by this grammar.
rule(:ipv4) {
(dec_octet >> str('.') >> dec_octet >> str('.') >>
dec_octet >> str('.') >> dec_octet).as(:ipv4)
}
rule(:dec_octet) {
str('25') >> match("[0-5]") |
str('2') >> match("[0-4]") >> digit |
str('1') >> digit >> digit |
match('[1-9]') >> digit |
digit
}
rule(:digit) {
match('[0-9]')
}
end
# Must be used in concert with IPv4
module IPv6
include Parslet
rule(:colon) { str(':') }
rule(:dcolon) { colon >> colon }
# h16 :
def h16r(times)
(h16 >> colon).repeat(times, times)
end
# : h16
def h16l(times)
(colon >> h16).repeat(0,times)
end
# A 128-bit IPv6 address is divided into eight 16-bit pieces. Each piece is
# represented numerically in case-insensitive hexadecimal, using one to four
# hexadecimal digits (leading zeroes are permitted). The eight encoded
# pieces are given most-significant first, separated by colon characters.
# Optionally, the least-significant two pieces may instead be represented in
# IPv4 address textual format. A sequence of one or more consecutive
# zero-valued 16-bit pieces within the address may be elided, omitting all
# their digits and leaving exactly two consecutive colons in their place to
# mark the elision.
rule(:ipv6) {
(
(
h16r(6) |
dcolon >> h16r(5) |
h16.maybe >> dcolon >> h16r(4) |
(h16 >> h16l(1)).maybe >> dcolon >> h16r(3) |
(h16 >> h16l(2)).maybe >> dcolon >> h16r(2) |
(h16 >> h16l(3)).maybe >> dcolon >> h16r(1) |
(h16 >> h16l(4)).maybe >> dcolon
) >> ls32 |
(h16 >> h16l(5)).maybe >> dcolon >> h16 |
(h16 >> h16l(6)).maybe >> dcolon
).as(:ipv6)
}
rule(:h16) {
hexdigit.repeat(1,4)
}
rule(:ls32) {
(h16 >> colon >> h16) |
ipv4
}
rule(:hexdigit) {
digit | match("[a-fA-F]")
}
end
class Parser
include IPv4
include IPv6
def parse(str)
(ipv4 | ipv6).parse(str)
end
end
%W(
0.0.0.0
255.255.255.255
255.255.255
1:2:3:4:5:6:7:8
12AD:34FC:A453:1922::
12AD::34FC
12AD::
::
1:2
).each do |address|
parser = Parser.new
printf "%30s -> ", address
begin
result = parser.parse(address)
puts result.inspect
rescue Parslet::ParseFailed => m
puts "Failed: #{m}"
end
end
parslet-1.5.0/example/ignore.rb 0000644 0001750 0001750 00000001234 12270776314 015131 0 ustar mero mero # A small example on how to make parslet ignore parts of the parse tree.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
class IgnoreParslet < Parslet::Atoms::Base
def initialize(parslet)
@parslet = parslet
end
def to_s_inner(prec)
@parslet.to_s(prec)
end
def try(source, context, consume_all)
success, value = result = @parslet.try(source, context, consume_all)
return succ(nil) if success
return result
end
end
module IgnoreDSL
def ignore
IgnoreParslet.new(self)
end
end
class Parslet::Atoms::Base
include IgnoreDSL
end
include Parslet
p (str('a') >> str('b').ignore >> str('c')).
parse('abc') parslet-1.5.0/example/erb.rb 0000644 0001750 0001750 00000002646 12270776314 014426 0 ustar mero mero # Example that demonstrates how a simple erb-like parser could be constructed.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
class ErbParser < Parslet::Parser
rule(:ruby) { (str('%>').absent? >> any).repeat.as(:ruby) }
rule(:expression) { (str('=') >> ruby).as(:expression) }
rule(:comment) { (str('#') >> ruby).as(:comment) }
rule(:code) { ruby.as(:code) }
rule(:erb) { expression | comment | code }
rule(:erb_with_tags) { str('<%') >> erb >> str('%>') }
rule(:text) { (str('<%').absent? >> any).repeat(1) }
rule(:text_with_ruby) { (text.as(:text) | erb_with_tags).repeat.as(:text) }
root(:text_with_ruby)
end
parser = ErbParser.new
p parser.parse "The value of x is <%= x %>."
p parser.parse "<% 1 + 2 %>"
p parser.parse "<%# commented %>"
evaluator = Parslet::Transform.new do
erb_binding = binding
rule(:code => { :ruby => simple(:ruby) }) { eval(ruby, erb_binding); '' }
rule(:expression => { :ruby => simple(:ruby) }) { eval(ruby, erb_binding) }
rule(:comment => { :ruby => simple(:ruby) }) { '' }
rule(:text => simple(:text)) { text }
rule(:text => sequence(:texts)) { texts.join }
end
puts evaluator.apply(parser.parse(<<-ERB
The <% a = 2 %>not printed result of "a = 2".
The <%# a = 1 %>not printed non-evaluated comment "a = 1", see the value of a below.
The <%= 'nicely' %> printed result.
The <% b = 3 %>value of a is <%= a %>, and b is <%= b %>.
ERB
))
parslet-1.5.0/example/empty.rb 0000644 0001750 0001750 00000000444 12270776314 015006 0 ustar mero mero # Basically just demonstrates that you can leave rules empty and get a nice
# NotImplementedError. A way to quickly spec out your parser rules?
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
class Parser < Parslet::Parser
rule(:empty) { }
end
Parser.new.empty.parslet
parslet-1.5.0/example/email_parser.rb 0000644 0001750 0001750 00000002615 12270776314 016315 0 ustar mero mero #!/usr/bin/env ruby
# Example contributed by Hal Brodigan (postmodern). Thanks!
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
require 'parslet/convenience'
class EmailParser < Parslet::Parser
rule(:space) { match('\s').repeat(1) }
rule(:space?) { space.maybe }
rule(:dash?) { match['_-'].maybe }
rule(:at) {
str('@') |
(dash? >> (str('at') | str('AT')) >> dash?)
}
rule(:dot) {
str('.') |
(dash? >> (str('dot') | str('DOT')) >> dash?)
}
rule(:word) { match('[a-z0-9]').repeat(1).as(:word) >> space? }
rule(:separator) { dot.as(:dot) >> space? | space }
rule(:words) { word >> (separator >> word).repeat }
rule(:email) {
(words.as(:username) >> space? >> at >> space? >> words).as(:email)
}
root(:email)
end
class EmailSanitizer < Parslet::Transform
rule(:dot => simple(:dot), :word => simple(:word)) { ".#{word}" }
rule(:word => simple(:word)) { word }
rule(:username => sequence(:username)) { username.join + "@" }
rule(:username => simple(:username)) { username.to_s + "@" }
rule(:email => sequence(:email)) { email.join }
end
parser = EmailParser.new
sanitizer = EmailSanitizer.new
unless ARGV[0]
STDERR.puts "usage: #{$0} \"EMAIL_ADDR\""
STDOUT.puts "since you haven't specified any EMAIL_ADDR, for testing purposes we're using a.b.c.d@gmail.com"
end
p sanitizer.apply(parser.parse_with_debug(ARGV[0] || 'a.b.c.d@gmail.com'))
parslet-1.5.0/example/documentation.rb 0000644 0001750 0001750 00000000525 12270776314 016521 0 ustar mero mero # A small example that shows a really small parser and what happens on parser
# errors.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'pp'
require 'parslet'
class MyParser < Parslet::Parser
rule(:a) { str('a').repeat }
def parse(str)
a.parse(str)
end
end
pp MyParser.new.parse('aaaa')
pp MyParser.new.parse('bbbb')
parslet-1.5.0/example/deepest_errors.rb 0000644 0001750 0001750 00000004400 12270776314 016671 0 ustar mero mero $:.unshift File.dirname(__FILE__) + "/../lib"
# This example demonstrates how to do deepest error reporting, as invented
# by John Mettraux (issue #64).
require 'parslet'
require 'parslet/convenience'
def prettify(str)
puts " "*3 + " "*4 + "." + " "*4 + "10" + " "*3 + "." + " "*4 + "20"
str.lines.each_with_index do |line, index|
printf "%02d %s\n",
index+1,
line.chomp
end
end
class Parser < Parslet::Parser
# commons
rule(:space) { match('[ \t]').repeat(1) }
rule(:space?) { space.maybe }
rule(:newline) { match('[\r\n]') }
rule(:comment) { str('#') >> match('[^\r\n]').repeat }
rule(:line_separator) {
(space? >> ((comment.maybe >> newline) | str(';')) >> space?).repeat(1)
}
rule(:blank) { line_separator | space }
rule(:blank?) { blank.maybe }
rule(:identifier) { match('[a-zA-Z0-9_]').repeat(1) }
# res_statement
rule(:reference) {
(str('@').repeat(1,2) >> identifier).as(:reference)
}
rule(:res_action_or_link) {
str('.').as(:dot) >> (identifier >> str('?').maybe ).as(:name) >> str('()')
}
rule(:res_actions) {
(
reference
).as(:resources) >>
(
res_action_or_link.as(:res_action)
).repeat(0).as(:res_actions)
}
rule(:res_statement) {
res_actions >>
(str(':') >> identifier.as(:name)).maybe.as(:res_field)
}
# expression
rule(:expression) {
res_statement
}
# body
rule(:body) {
(line_separator >> (block | expression)).repeat(1).as(:body) >>
line_separator
}
# blocks
rule(:begin_block) {
(str('concurrent').as(:type) >> space).maybe.as(:pre) >>
str('begin').as(:begin) >>
body >>
str('end')
}
rule(:define_block) {
str('define').as(:define) >> space >>
identifier.as(:name) >> str('()') >>
body >>
str('end')
}
rule(:block) {
define_block | begin_block
}
# root
rule(:radix) {
line_separator.maybe >> block >> line_separator.maybe
}
root(:radix)
end
ds = [
%{
define f()
@res.name
end
},
%{
define f()
begin
@res.name
end
end
}
]
ds.each do |d|
puts '-' * 80
prettify(d)
parser = Parser.new
begin
parser.parse_with_debug(d,
:reporter => Parslet::ErrorReporter::Deepest.new)
end
end
puts '-' * 80 parslet-1.5.0/example/comments.rb 0000644 0001750 0001750 00000001652 12270776314 015477 0 ustar mero mero # A small example on how to parse common types of comments. The example
# started out with parser code from Stephen Waits.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'pp'
require 'parslet'
require 'parslet/convenience'
class ALanguage < Parslet::Parser
root(:lines)
rule(:lines) { line.repeat }
rule(:line) { spaces >> expression.repeat >> newline }
rule(:newline) { str("\n") >> str("\r").maybe }
rule(:expression) { (str('a').as(:a) >> spaces).as(:exp) }
rule(:spaces) { space.repeat }
rule(:space) { multiline_comment | line_comment | str(' ') }
rule(:line_comment) { (str('//') >> (newline.absent? >> any).repeat).as(:line) }
rule(:multiline_comment) { (str('/*') >> (str('*/').absent? >> any).repeat >> str('*/')).as(:multi) }
end
code = %q(
a
// line comment
a a a // line comment
a /* inline comment */ a
/* multiline
comment */
)
pp ALanguage.new.parse_with_debug(code)
parslet-1.5.0/example/capture.rb 0000644 0001750 0001750 00000002624 12270776314 015315 0 ustar mero mero
# This example demonstrates how pieces of input can be captured and matched
# against later on. Without this, you cannot match here-documents and other
# self-dependent grammars.
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'parslet'
require 'parslet/convenience'
require 'pp'
class CapturingParser < Parslet::Parser
root :document
# Introduce a scope for each document. This ensures that documents can be
# nested.
rule(:document) { scope { doc_start >> text >> doc_end } }
# Start of a document is a heredoc marker. This is captured in :marker
rule(:doc_start) { str('<') >> marker >> newline }
rule(:marker) { match['A-Z'].repeat(1).capture(:marker) }
# The content of a document can be either lines of text or another
# document, introduced by > any >>
(newline.absent? >> any).repeat >> newline }
# The end of the document is marked by the marker that was at the beginning
# of the document, by itself on a line.
rule(:doc_end) { captured_marker }
rule(:captured_marker) {
dynamic { |source, context|
str(context.captures[:marker])
}
}
rule(:newline) { match["\n"] }
end
parser = CapturingParser.new
pp parser.parse_with_debug %Q(