chomsky 0.1.0
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/lib/chomsky/action.rb +15 -0
- data/lib/chomsky/grammar.rb +20 -0
- data/lib/chomsky/parser.rb +29 -0
- data/lib/chomsky/parser_generator.rb +35 -0
- data/lib/chomsky/parser_generators/and.rb +25 -0
- data/lib/chomsky/parser_generators/backreference.rb +19 -0
- data/lib/chomsky/parser_generators/capture.rb +18 -0
- data/lib/chomsky/parser_generators/combinators.rb +83 -0
- data/lib/chomsky/parser_generators/compose.rb +25 -0
- data/lib/chomsky/parser_generators/not.rb +16 -0
- data/lib/chomsky/parser_generators/or.rb +25 -0
- data/lib/chomsky/parser_generators/peek.rb +16 -0
- data/lib/chomsky/parser_generators/perhaps.rb +12 -0
- data/lib/chomsky/parser_generators/repeat.rb +24 -0
- data/lib/chomsky/parser_generators/skip.rb +17 -0
- data/lib/chomsky/parser_generators/some.rb +21 -0
- data/lib/chomsky/parsers/anything.rb +21 -0
- data/lib/chomsky/parsers/basic_parsers.rb +36 -0
- data/lib/chomsky/parsers/blank.rb +11 -0
- data/lib/chomsky/parsers/literal.rb +19 -0
- data/lib/chomsky/parsers/nothing.rb +15 -0
- data/lib/chomsky/parsers/regexp.rb +19 -0
- data/lib/chomsky/rule.rb +25 -0
- data/lib/chomsky.rb +7 -0
- metadata +72 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'chomsky'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class Grammar
|
5
|
+
include Parser::BasicParsers
|
6
|
+
include ParserGenerator::Combinators
|
7
|
+
|
8
|
+
def self.rule name, &pg
|
9
|
+
define_method(name) { Rule.new(self, pg) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.action name, &block
|
13
|
+
define_method(name) { Action.new(self, block) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'chomsky'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class Parser
|
5
|
+
autoload :Anything, "chomsky/parsers/anything"
|
6
|
+
autoload :BasicParsers, "chomsky/parsers/basic_parsers"
|
7
|
+
autoload :Blank, "chomsky/parsers/blank"
|
8
|
+
autoload :Literal, "chomsky/parsers/literal"
|
9
|
+
autoload :Nothing, "chomsky/parsers/nothing"
|
10
|
+
autoload :Regexp, "chomsky/parsers/regexp"
|
11
|
+
|
12
|
+
include ParserGenerator::Combinators
|
13
|
+
|
14
|
+
def self.call *args
|
15
|
+
new(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
end
|
20
|
+
|
21
|
+
def call string
|
22
|
+
[nil, string]
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_pg
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'chomsky/parser_generators/combinators'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
autoload :And, "chomsky/parser_generators/and"
|
6
|
+
autoload :Compose, "chomsky/parser_generators/compose"
|
7
|
+
autoload :Repeat, "chomsky/parser_generators/repeat"
|
8
|
+
autoload :Not, "chomsky/parser_generators/not"
|
9
|
+
autoload :Or, "chomsky/parser_generators/or"
|
10
|
+
autoload :Peek, "chomsky/parser_generators/peek"
|
11
|
+
autoload :Perhaps, "chomsky/parser_generators/perhaps"
|
12
|
+
autoload :Skip, "chomsky/parser_generators/skip"
|
13
|
+
autoload :Some, "chomsky/parser_generators/some"
|
14
|
+
autoload :Capture, "chomsky/parser_generators/capture"
|
15
|
+
autoload :Backreference, "chomsky/parser_generators/backreference"
|
16
|
+
|
17
|
+
include Chomsky::ParserGenerator::Combinators
|
18
|
+
|
19
|
+
def self.call *args
|
20
|
+
new(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize parser
|
24
|
+
@parser = parser
|
25
|
+
end
|
26
|
+
|
27
|
+
def call string
|
28
|
+
@parser.call(string)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_pg
|
32
|
+
self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'chomsky/parser_generator'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
class And < ParserGenerator
|
6
|
+
def initialize left, right
|
7
|
+
@left, @right = left, right
|
8
|
+
end
|
9
|
+
|
10
|
+
def call string
|
11
|
+
head, rest = @left.(string)
|
12
|
+
if head
|
13
|
+
more, rest = @right.(rest)
|
14
|
+
if more
|
15
|
+
[head + more, rest]
|
16
|
+
else
|
17
|
+
[nil, string]
|
18
|
+
end
|
19
|
+
else
|
20
|
+
[nil, string]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'chomsky'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
class Backreference < ParserGenerator
|
6
|
+
def initialize capture
|
7
|
+
@capture = capture
|
8
|
+
end
|
9
|
+
|
10
|
+
def call string
|
11
|
+
if parser = @capture.parser
|
12
|
+
parser.(string)
|
13
|
+
else
|
14
|
+
[nil, string]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'chomsky'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
class Capture < ParserGenerator
|
6
|
+
attr_reader :parser
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@parser = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def call string
|
13
|
+
@parser = Parser::Literal.(string)
|
14
|
+
[string, ""]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'chomsky'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
module Combinators
|
6
|
+
def !
|
7
|
+
Not.(self.to_pg)
|
8
|
+
end
|
9
|
+
|
10
|
+
def _?
|
11
|
+
Perhaps.(self.to_pg)
|
12
|
+
end
|
13
|
+
|
14
|
+
def & other
|
15
|
+
And.(self.to_pg, other.to_pg)
|
16
|
+
end
|
17
|
+
|
18
|
+
def | other
|
19
|
+
Or.(self.to_pg, other.to_pg)
|
20
|
+
end
|
21
|
+
|
22
|
+
def < other
|
23
|
+
Skip.(self.to_pg) & other.to_pg
|
24
|
+
end
|
25
|
+
|
26
|
+
def > other
|
27
|
+
self.to_pg & Skip.(other.to_pg)
|
28
|
+
end
|
29
|
+
|
30
|
+
def % other
|
31
|
+
self.to_pg & Peek.(other.to_pg)
|
32
|
+
end
|
33
|
+
|
34
|
+
def - other
|
35
|
+
self.to_pg >> !(other.to_pg)
|
36
|
+
end
|
37
|
+
|
38
|
+
def +
|
39
|
+
Some.(self.to_pg)
|
40
|
+
end
|
41
|
+
|
42
|
+
def *
|
43
|
+
self.+()._?
|
44
|
+
end
|
45
|
+
|
46
|
+
def [] min, max = nil
|
47
|
+
if max
|
48
|
+
p = Repeat.(self._?, max)
|
49
|
+
min ? Repeat.(self.to_pg, min) & p : p
|
50
|
+
else
|
51
|
+
case min
|
52
|
+
when 0
|
53
|
+
self.*()
|
54
|
+
when 1
|
55
|
+
self.+()
|
56
|
+
else
|
57
|
+
Repeat.(self.to_pg, min) & self._?.*()
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def >> other
|
63
|
+
Compose.(self.to_pg, other.to_pg)
|
64
|
+
end
|
65
|
+
|
66
|
+
def capture name
|
67
|
+
captures[name] = Capture.new
|
68
|
+
end
|
69
|
+
alias_method :cap, :capture
|
70
|
+
|
71
|
+
def reference name
|
72
|
+
Backreference.new(captures[name])
|
73
|
+
end
|
74
|
+
alias_method :ref, :reference
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def captures
|
79
|
+
@captures ||= {}
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'chomsky/parser_generator'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
class Compose < ParserGenerator
|
6
|
+
def initialize left, right
|
7
|
+
@left, @right = left, right
|
8
|
+
end
|
9
|
+
|
10
|
+
def call string
|
11
|
+
head, rest = @left.(string)
|
12
|
+
if head
|
13
|
+
more, _ = @right.(head)
|
14
|
+
if more
|
15
|
+
[more, rest]
|
16
|
+
else
|
17
|
+
[nil, string]
|
18
|
+
end
|
19
|
+
else
|
20
|
+
[nil, string]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'chomsky/parser_generator'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
class Or < ParserGenerator
|
6
|
+
def initialize left, right
|
7
|
+
@left, @right = left, right
|
8
|
+
end
|
9
|
+
|
10
|
+
def call string
|
11
|
+
head, rest = @left.(string)
|
12
|
+
if head
|
13
|
+
[head, rest]
|
14
|
+
else
|
15
|
+
more, rest = @right.(string)
|
16
|
+
if more
|
17
|
+
[more, rest]
|
18
|
+
else
|
19
|
+
[nil, string]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'chomsky/parser_generator'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
class Repeat < ParserGenerator
|
6
|
+
def initialize parser, n
|
7
|
+
super(parser)
|
8
|
+
@n = n
|
9
|
+
end
|
10
|
+
|
11
|
+
def call string
|
12
|
+
head, rest = "", string
|
13
|
+
@n.times do
|
14
|
+
more, rest = @parser.(rest)
|
15
|
+
if more
|
16
|
+
head += more
|
17
|
+
else
|
18
|
+
return [nil, string]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'chomsky/parser_generator'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class ParserGenerator
|
5
|
+
class Some < ParserGenerator
|
6
|
+
def call string
|
7
|
+
head, rest = @parser.(string)
|
8
|
+
if head
|
9
|
+
more = ""
|
10
|
+
until more.nil?
|
11
|
+
more, rest = @parser.(rest)
|
12
|
+
head += more if more
|
13
|
+
end
|
14
|
+
[head, rest]
|
15
|
+
else
|
16
|
+
[nil, string]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'chomsky'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class Parser
|
5
|
+
class Anything < Parser
|
6
|
+
attr_reader :length
|
7
|
+
|
8
|
+
def initialize length = 1
|
9
|
+
@length = length
|
10
|
+
end
|
11
|
+
|
12
|
+
def call string
|
13
|
+
if string.length < @length
|
14
|
+
[nil, string]
|
15
|
+
else
|
16
|
+
[string[0,@length], string[@length..-1]]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'chomsky/parser'
|
2
|
+
require 'chomsky/parser_generators/perhaps'
|
3
|
+
|
4
|
+
module Chomsky
|
5
|
+
class Parser
|
6
|
+
module BasicParsers
|
7
|
+
# Any single character
|
8
|
+
def _
|
9
|
+
Anything.()
|
10
|
+
end
|
11
|
+
|
12
|
+
# Only matches an empty string
|
13
|
+
def eos
|
14
|
+
Nothing.()
|
15
|
+
end
|
16
|
+
|
17
|
+
# Matches one or more whitespace characters
|
18
|
+
def ___
|
19
|
+
Blank.()
|
20
|
+
end
|
21
|
+
|
22
|
+
# optional whitespace
|
23
|
+
def ___?
|
24
|
+
ParserGenerator::Perhaps.(Blank.())
|
25
|
+
end
|
26
|
+
|
27
|
+
def ` string
|
28
|
+
Literal.(string)
|
29
|
+
end
|
30
|
+
|
31
|
+
def r regexp
|
32
|
+
Parser::Regexp.(regexp)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'chomsky/parser'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class Parser
|
5
|
+
class Literal < Parser
|
6
|
+
def initialize string
|
7
|
+
@value = string
|
8
|
+
end
|
9
|
+
|
10
|
+
def call string
|
11
|
+
if string.start_with?(@value)
|
12
|
+
[@value, string[@value.length..-1]]
|
13
|
+
else
|
14
|
+
[nil, string]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'chomsky/parser'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class Parser
|
5
|
+
class Regexp < Parser
|
6
|
+
def initialize pattern
|
7
|
+
@pattern = ::Regexp.new("\\A" + pattern.source)
|
8
|
+
end
|
9
|
+
|
10
|
+
def call string
|
11
|
+
if mdata = @pattern.match(string)
|
12
|
+
[mdata.to_s, string[mdata.to_s.length..-1]]
|
13
|
+
else
|
14
|
+
[nil, string]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/chomsky/rule.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'chomsky/parser_generator'
|
2
|
+
|
3
|
+
module Chomsky
|
4
|
+
class Rule < ParserGenerator
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
def initialize grammar, pg
|
8
|
+
@grammar = grammar
|
9
|
+
@pg = pg
|
10
|
+
end
|
11
|
+
|
12
|
+
def call string
|
13
|
+
if parser = @grammar.instance_exec(&@pg)
|
14
|
+
tok, rest = parser.(string)
|
15
|
+
if tok
|
16
|
+
[tok, rest]
|
17
|
+
else
|
18
|
+
[nil, string]
|
19
|
+
end
|
20
|
+
else
|
21
|
+
[nil, string]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/chomsky.rb
ADDED
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chomsky
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sander Hartlage
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-16 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Chomsky generates parsing expression grammars with a nice pure-Ruby DSL,
|
15
|
+
eliminating the need for secondary grammar definition files or out-of-band compilation,
|
16
|
+
and allowing a grammar's rules to grow dynamically or be manipulated as easy-to-understand
|
17
|
+
Ruby objects.
|
18
|
+
email: sander.hartlage@gmail.com
|
19
|
+
executables: []
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- lib/chomsky/action.rb
|
24
|
+
- lib/chomsky/grammar.rb
|
25
|
+
- lib/chomsky/parser.rb
|
26
|
+
- lib/chomsky/parser_generator.rb
|
27
|
+
- lib/chomsky/parser_generators/and.rb
|
28
|
+
- lib/chomsky/parser_generators/backreference.rb
|
29
|
+
- lib/chomsky/parser_generators/capture.rb
|
30
|
+
- lib/chomsky/parser_generators/combinators.rb
|
31
|
+
- lib/chomsky/parser_generators/compose.rb
|
32
|
+
- lib/chomsky/parser_generators/not.rb
|
33
|
+
- lib/chomsky/parser_generators/or.rb
|
34
|
+
- lib/chomsky/parser_generators/peek.rb
|
35
|
+
- lib/chomsky/parser_generators/perhaps.rb
|
36
|
+
- lib/chomsky/parser_generators/repeat.rb
|
37
|
+
- lib/chomsky/parser_generators/skip.rb
|
38
|
+
- lib/chomsky/parser_generators/some.rb
|
39
|
+
- lib/chomsky/parsers/anything.rb
|
40
|
+
- lib/chomsky/parsers/basic_parsers.rb
|
41
|
+
- lib/chomsky/parsers/blank.rb
|
42
|
+
- lib/chomsky/parsers/literal.rb
|
43
|
+
- lib/chomsky/parsers/nothing.rb
|
44
|
+
- lib/chomsky/parsers/regexp.rb
|
45
|
+
- lib/chomsky/rule.rb
|
46
|
+
- lib/chomsky.rb
|
47
|
+
homepage: http://github.com/sander6/chomsky
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.8.23
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Pure-Ruby parsing expression grammar generator
|
71
|
+
test_files: []
|
72
|
+
has_rdoc:
|