ghazel-parslet 1.4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.txt +195 -0
- data/LICENSE +23 -0
- data/README +70 -0
- data/Rakefile +49 -0
- data/example/boolean_algebra.rb +70 -0
- data/example/calc.rb +153 -0
- data/example/comments.rb +35 -0
- data/example/deepest_errors.rb +131 -0
- data/example/documentation.rb +18 -0
- data/example/email_parser.rb +52 -0
- data/example/empty.rb +13 -0
- data/example/erb.rb +47 -0
- data/example/ignore.rb +33 -0
- data/example/ip_address.rb +125 -0
- data/example/json.rb +128 -0
- data/example/local.rb +34 -0
- data/example/mathn.rb +44 -0
- data/example/minilisp.rb +94 -0
- data/example/modularity.rb +47 -0
- data/example/nested_errors.rb +132 -0
- data/example/output/boolean_algebra.out +4 -0
- data/example/output/calc.out +1 -0
- data/example/output/comments.out +8 -0
- data/example/output/deepest_errors.out +54 -0
- data/example/output/documentation.err +4 -0
- data/example/output/documentation.out +1 -0
- data/example/output/email_parser.out +2 -0
- data/example/output/empty.err +1 -0
- data/example/output/erb.out +7 -0
- data/example/output/ignore.out +1 -0
- data/example/output/ignore_whitespace.out +1 -0
- data/example/output/ip_address.out +9 -0
- data/example/output/json.out +5 -0
- data/example/output/local.out +3 -0
- data/example/output/mathn.out +4 -0
- data/example/output/minilisp.out +5 -0
- data/example/output/modularity.out +0 -0
- data/example/output/nested_errors.out +54 -0
- data/example/output/parens.out +8 -0
- data/example/output/readme.out +1 -0
- data/example/output/seasons.out +28 -0
- data/example/output/sentence.out +1 -0
- data/example/output/simple_xml.out +2 -0
- data/example/output/string_parser.out +3 -0
- data/example/parens.rb +42 -0
- data/example/readme.rb +30 -0
- data/example/seasons.rb +46 -0
- data/example/sentence.rb +36 -0
- data/example/simple.lit +3 -0
- data/example/simple_xml.rb +54 -0
- data/example/string_parser.rb +77 -0
- data/example/test.lit +4 -0
- data/lib/parslet.rb +254 -0
- data/lib/parslet/atoms.rb +32 -0
- data/lib/parslet/atoms/alternative.rb +50 -0
- data/lib/parslet/atoms/base.rb +124 -0
- data/lib/parslet/atoms/can_flatten.rb +137 -0
- data/lib/parslet/atoms/context.rb +94 -0
- data/lib/parslet/atoms/dsl.rb +98 -0
- data/lib/parslet/atoms/entity.rb +41 -0
- data/lib/parslet/atoms/lookahead.rb +49 -0
- data/lib/parslet/atoms/named.rb +32 -0
- data/lib/parslet/atoms/re.rb +38 -0
- data/lib/parslet/atoms/repetition.rb +63 -0
- data/lib/parslet/atoms/rule.rb +12 -0
- data/lib/parslet/atoms/rule/position.rb +143 -0
- data/lib/parslet/atoms/sequence.rb +38 -0
- data/lib/parslet/atoms/str.rb +37 -0
- data/lib/parslet/atoms/visitor.rb +89 -0
- data/lib/parslet/cause.rb +94 -0
- data/lib/parslet/convenience.rb +35 -0
- data/lib/parslet/error_reporter.rb +7 -0
- data/lib/parslet/error_reporter/deepest.rb +95 -0
- data/lib/parslet/error_reporter/tree.rb +57 -0
- data/lib/parslet/export.rb +162 -0
- data/lib/parslet/expression.rb +51 -0
- data/lib/parslet/expression/treetop.rb +92 -0
- data/lib/parslet/parser.rb +67 -0
- data/lib/parslet/pattern.rb +114 -0
- data/lib/parslet/pattern/binding.rb +49 -0
- data/lib/parslet/rig/rspec.rb +51 -0
- data/lib/parslet/slice.rb +101 -0
- data/lib/parslet/source.rb +62 -0
- data/lib/parslet/source/line_cache.rb +95 -0
- data/lib/parslet/transform.rb +236 -0
- data/lib/parslet/transform/context.rb +32 -0
- metadata +264 -0
@@ -0,0 +1 @@
|
|
1
|
+
123*2 (command line): -> 246
|
@@ -0,0 +1,8 @@
|
|
1
|
+
[{:exp=>{:a=>"a"@3}},
|
2
|
+
{:line=>"// line comment"@7},
|
3
|
+
{:exp=>{:a=>"a"@25}},
|
4
|
+
{:exp=>{:a=>"a"@27}},
|
5
|
+
{:exp=>[{:a=>"a"@29}, {:line=>"// line comment"@31}]},
|
6
|
+
{:exp=>[{:a=>"a"@49}, {:multi=>"/* inline comment */"@51}]},
|
7
|
+
{:exp=>{:a=>"a"@72}},
|
8
|
+
{:multi=>"/* multiline\n comment */"@77}]
|
@@ -0,0 +1,54 @@
|
|
1
|
+
--------------------------------------------------------------------------------
|
2
|
+
. 10 . 20
|
3
|
+
01
|
4
|
+
02 define f()
|
5
|
+
03 @res.name
|
6
|
+
04 end
|
7
|
+
05
|
8
|
+
Failed to match sequence (LINE_SEPARATOR? BLOCK LINE_SEPARATOR?) at line 2 char 5.
|
9
|
+
`- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 2 char 5.
|
10
|
+
|- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 2 char 15.
|
11
|
+
| `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 3 char 11.
|
12
|
+
| `- Expected at least 1 of SPACE? (COMMENT? NEWLINE / ';') SPACE? at line 3 char 11.
|
13
|
+
| `- Failed to match sequence (SPACE? (COMMENT? NEWLINE / ';') SPACE?) at line 3 char 11.
|
14
|
+
| `- Expected one of [COMMENT? NEWLINE, ';'] at line 3 char 11.
|
15
|
+
| |- Failed to match sequence (COMMENT? NEWLINE) at line 3 char 11.
|
16
|
+
| | `- Expected "()", but got "\n " at line 3 char 16.
|
17
|
+
| `- Expected "()", but got "\n " at line 3 char 16.
|
18
|
+
`- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 2 char 5.
|
19
|
+
`- Expected "()", but got "\n " at line 3 char 16.
|
20
|
+
--------------------------------------------------------------------------------
|
21
|
+
. 10 . 20
|
22
|
+
01
|
23
|
+
02 define f()
|
24
|
+
03 begin
|
25
|
+
04 @res.name
|
26
|
+
05 end
|
27
|
+
06 end
|
28
|
+
07
|
29
|
+
Failed to match sequence (LINE_SEPARATOR? BLOCK LINE_SEPARATOR?) at line 2 char 5.
|
30
|
+
`- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 2 char 5.
|
31
|
+
|- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 2 char 15.
|
32
|
+
| `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 2 char 15.
|
33
|
+
| `- Expected at least 1 of LINE_SEPARATOR (BLOCK / EXPRESSION) at line 2 char 15.
|
34
|
+
| `- Failed to match sequence (LINE_SEPARATOR (BLOCK / EXPRESSION)) at line 3 char 7.
|
35
|
+
| `- Expected one of [BLOCK, EXPRESSION] at line 3 char 7.
|
36
|
+
| |- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 3 char 7.
|
37
|
+
| | |- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 3 char 7.
|
38
|
+
| | | `- Expected "define", but got "begin\n" at line 3 char 7.
|
39
|
+
| | `- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 3 char 12.
|
40
|
+
| | `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 4 char 13.
|
41
|
+
| | `- Expected at least 1 of SPACE? (COMMENT? NEWLINE / ';') SPACE? at line 4 char 13.
|
42
|
+
| | `- Failed to match sequence (SPACE? (COMMENT? NEWLINE / ';') SPACE?) at line 4 char 13.
|
43
|
+
| | `- Expected one of [COMMENT? NEWLINE, ';'] at line 4 char 13.
|
44
|
+
| | |- Failed to match sequence (COMMENT? NEWLINE) at line 4 char 13.
|
45
|
+
| | | `- Expected "()", but got "\n " at line 4 char 18.
|
46
|
+
| | `- Expected "()", but got "\n " at line 4 char 18.
|
47
|
+
| `- Failed to match sequence (RES_ACTIONS res_field:((':' name:IDENTIFIER)?)) at line 3 char 7.
|
48
|
+
| `- Failed to match sequence (resources:REFERENCE res_actions:(res_action:RES_ACTION_OR_LINK{0, })) at line 3 char 7.
|
49
|
+
| `- Failed to match sequence ('@'{1, 2} IDENTIFIER) at line 3 char 7.
|
50
|
+
| `- Expected at least 1 of '@' at line 3 char 7.
|
51
|
+
| `- Expected "()", but got "\n " at line 4 char 18.
|
52
|
+
`- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 2 char 5.
|
53
|
+
`- Expected "()", but got "\n " at line 4 char 18.
|
54
|
+
--------------------------------------------------------------------------------
|
@@ -0,0 +1,4 @@
|
|
1
|
+
/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)
|
2
|
+
from /Users/kaspar/git_work/own/parslet/lib/parslet/atoms/base.rb:55:in `parse'
|
3
|
+
from example/documentation.rb:13:in `parse'
|
4
|
+
from example/documentation.rb:18:in `<main>'
|
@@ -0,0 +1 @@
|
|
1
|
+
"aaaa"@0
|
@@ -0,0 +1 @@
|
|
1
|
+
example/empty.rb:13:in `<main>': rule(:empty) { ... } returns nil. Still not implemented, but already used? (NotImplementedError)
|
@@ -0,0 +1,7 @@
|
|
1
|
+
{:text=>[{:text=>"The value of x is "@0}, {:expression=>{:ruby=>" x "@21}}, {:text=>"."@26}]}
|
2
|
+
{:text=>[{:code=>{:ruby=>" 1 + 2 "@2}}]}
|
3
|
+
{:text=>[{:comment=>{:ruby=>" commented "@3}}]}
|
4
|
+
The not printed result of "a = 2".
|
5
|
+
The not printed non-evaluated comment "a = 1", see the value of a below.
|
6
|
+
The nicely printed result.
|
7
|
+
The value of a is 2, and b is 3.
|
@@ -0,0 +1 @@
|
|
1
|
+
"ac"@0
|
@@ -0,0 +1 @@
|
|
1
|
+
[{:a=>"a"@0}, {:a=>"a"@1}, {:a=>"a"@5}, {:a=>"a"@7}]
|
@@ -0,0 +1,9 @@
|
|
1
|
+
0.0.0.0 -> {:ipv4=>"0.0.0.0"@0}
|
2
|
+
255.255.255.255 -> {:ipv4=>"255.255.255.255"@0}
|
3
|
+
255.255.255 -> Failed: Expected one of [IPV4, IPV6] at line 1 char 1.
|
4
|
+
1:2:3:4:5:6:7:8 -> {:ipv6=>"1:2:3:4:5:6:7:8"@0}
|
5
|
+
12AD:34FC:A453:1922:: -> {:ipv6=>"12AD:34FC:A453:1922::"@0}
|
6
|
+
12AD::34FC -> {:ipv6=>"12AD::34FC"@0}
|
7
|
+
12AD:: -> {:ipv6=>"12AD::"@0}
|
8
|
+
:: -> {:ipv6=>"::"@0}
|
9
|
+
1:2 -> Failed: Expected one of [IPV4, IPV6] at line 1 char 1.
|
@@ -0,0 +1,5 @@
|
|
1
|
+
|
2
|
+
{: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}}]}
|
3
|
+
|
4
|
+
[1, 2, 3, nil, "asdfasdf asdfds", {"a"=>-1.2}, {"b"=>true, "c"=>false}, 1.0e+23, true, false, [1]]
|
5
|
+
|
File without changes
|
@@ -0,0 +1,54 @@
|
|
1
|
+
--------------------------------------------------------------------------------
|
2
|
+
. 10 . 20
|
3
|
+
01
|
4
|
+
02 define f()
|
5
|
+
03 @res.name
|
6
|
+
04 end
|
7
|
+
05
|
8
|
+
Failed to match sequence (LINE_SEPARATOR? BLOCK LINE_SEPARATOR?) at line 2 char 5.
|
9
|
+
`- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 2 char 5.
|
10
|
+
|- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 2 char 15.
|
11
|
+
| `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 3 char 11.
|
12
|
+
| `- Expected at least 1 of SPACE? (COMMENT? NEWLINE / ';') SPACE? at line 3 char 11.
|
13
|
+
| `- Failed to match sequence (SPACE? (COMMENT? NEWLINE / ';') SPACE?) at line 3 char 11.
|
14
|
+
| `- Expected one of [COMMENT? NEWLINE, ';'] at line 3 char 11.
|
15
|
+
| |- Failed to match sequence (COMMENT? NEWLINE) at line 3 char 11.
|
16
|
+
| | `- Failed to match [\\r\\n] at line 3 char 11.
|
17
|
+
| `- Expected ";", but got "." at line 3 char 11.
|
18
|
+
`- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 2 char 5.
|
19
|
+
`- Expected "begin", but got "defin" at line 2 char 5.
|
20
|
+
--------------------------------------------------------------------------------
|
21
|
+
. 10 . 20
|
22
|
+
01
|
23
|
+
02 define f()
|
24
|
+
03 begin
|
25
|
+
04 @res.name
|
26
|
+
05 end
|
27
|
+
06 end
|
28
|
+
07
|
29
|
+
Failed to match sequence (LINE_SEPARATOR? BLOCK LINE_SEPARATOR?) at line 2 char 5.
|
30
|
+
`- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 2 char 5.
|
31
|
+
|- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 2 char 15.
|
32
|
+
| `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 2 char 15.
|
33
|
+
| `- Expected at least 1 of LINE_SEPARATOR (BLOCK / EXPRESSION) at line 2 char 15.
|
34
|
+
| `- Failed to match sequence (LINE_SEPARATOR (BLOCK / EXPRESSION)) at line 3 char 7.
|
35
|
+
| `- Expected one of [BLOCK, EXPRESSION] at line 3 char 7.
|
36
|
+
| |- Expected one of [DEFINE_BLOCK, BEGIN_BLOCK] at line 3 char 7.
|
37
|
+
| | |- Failed to match sequence (define:'define' SPACE name:IDENTIFIER '()' BODY 'end') at line 3 char 7.
|
38
|
+
| | | `- Expected "define", but got "begin\n" at line 3 char 7.
|
39
|
+
| | `- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 3 char 12.
|
40
|
+
| | `- Failed to match sequence (body:((LINE_SEPARATOR (BLOCK / EXPRESSION)){1, }) LINE_SEPARATOR) at line 4 char 13.
|
41
|
+
| | `- Expected at least 1 of SPACE? (COMMENT? NEWLINE / ';') SPACE? at line 4 char 13.
|
42
|
+
| | `- Failed to match sequence (SPACE? (COMMENT? NEWLINE / ';') SPACE?) at line 4 char 13.
|
43
|
+
| | `- Expected one of [COMMENT? NEWLINE, ';'] at line 4 char 13.
|
44
|
+
| | |- Failed to match sequence (COMMENT? NEWLINE) at line 4 char 13.
|
45
|
+
| | | `- Failed to match [\\r\\n] at line 4 char 13.
|
46
|
+
| | `- Expected ";", but got "." at line 4 char 13.
|
47
|
+
| `- Failed to match sequence (RES_ACTIONS res_field:((':' name:IDENTIFIER)?)) at line 3 char 7.
|
48
|
+
| `- Failed to match sequence (resources:REFERENCE res_actions:(res_action:RES_ACTION_OR_LINK{0, })) at line 3 char 7.
|
49
|
+
| `- Failed to match sequence ('@'{1, 2} IDENTIFIER) at line 3 char 7.
|
50
|
+
| `- Expected at least 1 of '@' at line 3 char 7.
|
51
|
+
| `- Expected "@", but got "b" at line 3 char 7.
|
52
|
+
`- Failed to match sequence (pre:((type:'concurrent' SPACE)?) begin:'begin' BODY 'end') at line 2 char 5.
|
53
|
+
`- Expected "begin", but got "defin" at line 2 char 5.
|
54
|
+
--------------------------------------------------------------------------------
|
@@ -0,0 +1,8 @@
|
|
1
|
+
(): {:l=>"("@0, :m=>nil, :r=>")"@1} (1 parens)
|
2
|
+
|
3
|
+
(()): {:l=>"("@0, :m=>{:l=>"("@1, :m=>nil, :r=>")"@2}, :r=>")"@3} (2 parens)
|
4
|
+
|
5
|
+
((((())))): {: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)
|
6
|
+
|
7
|
+
((()): Failed to match sequence (l:'(' m:(BALANCED?) r:')') at line 1 char 6.
|
8
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
String contents: This is a \"String\" in which you can escape stuff
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"And when Spring comes"
|
2
|
+
{:bud=>{:stem=>[{:branch=>:leaf}]}}
|
3
|
+
|
4
|
+
"And when Summer comes"
|
5
|
+
{:bud=>{:stem=>[{:branch=>[:leaf, :flower]}]}}
|
6
|
+
|
7
|
+
"And when Fall comes"
|
8
|
+
Fruit!
|
9
|
+
Falling Leaves!
|
10
|
+
{:bud=>{:stem=>[{:branch=>[]}]}}
|
11
|
+
|
12
|
+
"And when Winter comes"
|
13
|
+
{:bud=>{:stem=>[]}}
|
14
|
+
|
15
|
+
"And when Spring comes"
|
16
|
+
{:bud=>{:stem=>[{:branch=>:leaf}]}}
|
17
|
+
|
18
|
+
"And when Summer comes"
|
19
|
+
{:bud=>{:stem=>[{:branch=>[:leaf, :flower]}]}}
|
20
|
+
|
21
|
+
"And when Fall comes"
|
22
|
+
Fruit!
|
23
|
+
Falling Leaves!
|
24
|
+
{:bud=>{:stem=>[{:branch=>[]}]}}
|
25
|
+
|
26
|
+
"And when Winter comes"
|
27
|
+
{:bud=>{:stem=>[]}}
|
28
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
["RubyKaigi2009のテーマは、「変わる/変える」です。", " 前回のRubyKaigi2008のテーマであった「多様性」の言葉の通り、 2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 ますます多様化が進みつつあります。", "RubyKaigi2008は、そのような Rubyの生態系をあらためて認識する場となりました。", " しかし、こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、その違いを認識したところであまり意味がありません。", " 異なる実装、異なる思想、異なる背景といった、様々な多様性を理解しつつ、 すり合わせるべきものをすり合わせ、変えていくべきところを 変えていくことが、豊かな未来へとつながる道に違いありません。"]
|
data/example/parens.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# A small example that demonstrates the power of tree pattern matching. Also
|
2
|
+
# uses '.as(:name)' to construct a tree that can reliably be matched
|
3
|
+
# afterwards.
|
4
|
+
|
5
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
6
|
+
|
7
|
+
require 'pp'
|
8
|
+
require 'parslet'
|
9
|
+
|
10
|
+
module LISP # as in 'lots of insipid and stupid parenthesis'
|
11
|
+
class Parser < Parslet::Parser
|
12
|
+
rule(:balanced) {
|
13
|
+
str('(').as(:l) >> balanced.maybe.as(:m) >> str(')').as(:r)
|
14
|
+
}
|
15
|
+
|
16
|
+
root(:balanced)
|
17
|
+
end
|
18
|
+
|
19
|
+
class Transform < Parslet::Transform
|
20
|
+
rule(:l => '(', :m => simple(:x), :r => ')') {
|
21
|
+
# innermost :m will contain nil
|
22
|
+
x.nil? ? 1 : x+1
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
parser = LISP::Parser.new
|
28
|
+
transform = LISP::Transform.new
|
29
|
+
%w!
|
30
|
+
()
|
31
|
+
(())
|
32
|
+
((((()))))
|
33
|
+
((())
|
34
|
+
!.each do |pexp|
|
35
|
+
begin
|
36
|
+
result = parser.parse(pexp)
|
37
|
+
puts "#{"%20s"%pexp}: #{result.inspect} (#{transform.apply(result)} parens)"
|
38
|
+
rescue Parslet::ParseFailed => m
|
39
|
+
puts "#{"%20s"%pexp}: #{m}"
|
40
|
+
end
|
41
|
+
puts
|
42
|
+
end
|
data/example/readme.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# The example from the readme. With this, I am making sure that the readme
|
2
|
+
# 'works'. Is this too messy?
|
3
|
+
|
4
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
5
|
+
|
6
|
+
# cut here -------------------------------------------------------------------
|
7
|
+
require 'parslet'
|
8
|
+
include Parslet
|
9
|
+
|
10
|
+
# Constructs a parser using a Parser Expression Grammar like DSL:
|
11
|
+
parser = str('"') >>
|
12
|
+
(
|
13
|
+
str('\\') >> any |
|
14
|
+
str('"').absent? >> any
|
15
|
+
).repeat.as(:string) >>
|
16
|
+
str('"')
|
17
|
+
|
18
|
+
# Parse the string and capture parts of the interpretation (:string above)
|
19
|
+
tree = parser.parse('"This is a \\"String\\" in which you can escape stuff"')
|
20
|
+
|
21
|
+
tree # => {:string=>"This is a \\\"String\\\" in which you can escape stuff"}
|
22
|
+
|
23
|
+
# Here's how you can grab results from that tree:
|
24
|
+
|
25
|
+
transform = Parslet::Transform.new do
|
26
|
+
rule(:string => simple(:x)) {
|
27
|
+
puts "String contents: #{x}" }
|
28
|
+
end
|
29
|
+
transform.apply(tree)
|
30
|
+
|
data/example/seasons.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
|
3
|
+
require 'parslet'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
tree = {:bud => {:stem => []}}
|
7
|
+
|
8
|
+
class Spring < Parslet::Transform
|
9
|
+
rule(:stem => sequence(:branches)) {
|
10
|
+
{:stem => (branches + [{:branch => :leaf}])}
|
11
|
+
}
|
12
|
+
end
|
13
|
+
class Summer < Parslet::Transform
|
14
|
+
rule(:stem => subtree(:branches)) {
|
15
|
+
new_branches = branches.map { |b| {:branch => [:leaf, :flower]} }
|
16
|
+
{:stem => new_branches}
|
17
|
+
}
|
18
|
+
end
|
19
|
+
class Fall < Parslet::Transform
|
20
|
+
rule(:branch => sequence(:x)) {
|
21
|
+
x.each { |e| puts "Fruit!" if e==:flower }
|
22
|
+
x.each { |e| puts "Falling Leaves!" if e==:leaf }
|
23
|
+
{:branch => []}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
class Winter < Parslet::Transform
|
27
|
+
rule(:stem => subtree(:x)) {
|
28
|
+
{:stem => []}
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def do_seasons(tree)
|
33
|
+
[Spring, Summer, Fall, Winter].each do |season|
|
34
|
+
p "And when #{season} comes"
|
35
|
+
tree = season.new.apply(tree)
|
36
|
+
pp tree
|
37
|
+
puts
|
38
|
+
end
|
39
|
+
tree
|
40
|
+
end
|
41
|
+
|
42
|
+
# What marvel of life!
|
43
|
+
tree = do_seasons(tree)
|
44
|
+
tree = do_seasons(tree)
|
45
|
+
|
46
|
+
|
data/example/sentence.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# A small example contributed by John Mettraux (jmettraux) that demonstrates
|
4
|
+
# working with Unicode. This only works on Ruby 1.9.
|
5
|
+
|
6
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
7
|
+
|
8
|
+
require 'parslet'
|
9
|
+
|
10
|
+
class Parser < Parslet::Parser
|
11
|
+
rule(:sentence) { (match('[^。]').repeat(1) >> str("。")).as(:sentence) }
|
12
|
+
rule(:sentences) { sentence.repeat }
|
13
|
+
root(:sentences)
|
14
|
+
end
|
15
|
+
|
16
|
+
class Transformer < Parslet::Transform
|
17
|
+
rule(:sentence => simple(:sen)) { sen.to_s }
|
18
|
+
end
|
19
|
+
|
20
|
+
string =
|
21
|
+
"RubyKaigi2009のテーマは、「変わる/変える」です。 前回の" +
|
22
|
+
"RubyKaigi2008のテーマであった「多様性」の言葉の通り、 " +
|
23
|
+
"2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 " +
|
24
|
+
"ますます多様化が進みつつあります。RubyKaigi2008は、そのような " +
|
25
|
+
"Rubyの生態系をあらためて認識する場となりました。 しかし、" +
|
26
|
+
"こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、" +
|
27
|
+
"その違いを認識したところであまり意味がありません。 異なる実装、" +
|
28
|
+
"異なる思想、異なる背景といった、様々な多様性を理解しつつ、 " +
|
29
|
+
"すり合わせるべきものをすり合わせ、変えていくべきところを " +
|
30
|
+
"変えていくことが、豊かな未来へとつながる道に違いありません。"
|
31
|
+
|
32
|
+
parser = Parser.new
|
33
|
+
transformer = Transformer.new
|
34
|
+
|
35
|
+
tree = parser.parse(string)
|
36
|
+
p transformer.apply(tree)
|
data/example/simple.lit
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# A simple xml parser. It is simple in the respect as that it doesn't address
|
2
|
+
# any of the complexities of XML. This is ruby 1.9.
|
3
|
+
|
4
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
5
|
+
|
6
|
+
require 'pp'
|
7
|
+
require 'parslet'
|
8
|
+
|
9
|
+
class XML < Parslet::Parser
|
10
|
+
root :document
|
11
|
+
|
12
|
+
rule(:document) {
|
13
|
+
tag(close: false).as(:o) >> document.as(:i) >> tag(close: true).as(:c) |
|
14
|
+
text
|
15
|
+
}
|
16
|
+
|
17
|
+
# Perhaps we could have some syntax sugar to make this more easy?
|
18
|
+
#
|
19
|
+
def tag(opts={})
|
20
|
+
close = opts[:close] || false
|
21
|
+
|
22
|
+
parslet = str('<')
|
23
|
+
parslet = parslet >> str('/') if close
|
24
|
+
parslet = parslet >> (str('>').absent? >> match("[a-zA-Z]")).repeat(1).as(:name)
|
25
|
+
parslet = parslet >> str('>')
|
26
|
+
|
27
|
+
parslet
|
28
|
+
end
|
29
|
+
|
30
|
+
rule(:text) {
|
31
|
+
match('[^<>]').repeat(0)
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def check(xml)
|
36
|
+
r = XML.new.parse(xml)
|
37
|
+
|
38
|
+
# We'll validate the tree by reducing valid pairs of tags into simply the
|
39
|
+
# string "verified". If the transformation ends on a string, then the
|
40
|
+
# document was 'valid'.
|
41
|
+
#
|
42
|
+
t = Parslet::Transform.new do
|
43
|
+
rule(
|
44
|
+
o: {name: simple(:tag)},
|
45
|
+
c: {name: simple(:tag)},
|
46
|
+
i: simple(:t)
|
47
|
+
) { 'verified' }
|
48
|
+
end
|
49
|
+
|
50
|
+
t.apply(r)
|
51
|
+
end
|
52
|
+
|
53
|
+
pp check("<a><b>some text in the tags</b></a>")
|
54
|
+
pp check("<b><b>some text in the tags</b></a>")
|