ghazel-parslet 1.4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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>")
|