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.
@@ -0,0 +1,15 @@
1
+ require 'chomsky'
2
+
3
+ module Chomsky
4
+ class Action < ParserGenerator
5
+ def initialize grammar, action
6
+ @grammar = grammar
7
+ @action = action
8
+ end
9
+
10
+ def call string
11
+ @grammar.instance_exec(string, &@action)
12
+ [string, ""]
13
+ end
14
+ end
15
+ end
@@ -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,16 @@
1
+ require 'chomsky/parser_generator'
2
+
3
+ module Chomsky
4
+ class ParserGenerator
5
+ class Not < ParserGenerator
6
+ def call string
7
+ head, rest = @parser.(string)
8
+ if head
9
+ [nil, string]
10
+ else
11
+ ["", rest]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ 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,16 @@
1
+ require 'chomsky/parser_generator'
2
+
3
+ module Chomsky
4
+ class ParserGenerator
5
+ class Peek < ParserGenerator
6
+ def call string
7
+ head, rest = @parser.(string)
8
+ if head
9
+ ["", string]
10
+ else
11
+ [nil, string]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ require 'chomsky/parser_generator'
2
+
3
+ module Chomsky
4
+ class ParserGenerator
5
+ class Perhaps < ParserGenerator
6
+ def call string
7
+ head, rest = @parser.(string)
8
+ [head || "", rest]
9
+ end
10
+ end
11
+ end
12
+ 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,17 @@
1
+ require 'chomsky/parser_generator'
2
+
3
+ module Chomsky
4
+ class ParserGenerator
5
+ class Skip < ParserGenerator
6
+ def call string
7
+ head, rest = @parser.(string)
8
+ if head
9
+ ["", rest]
10
+ else
11
+ [nil, rest]
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+
@@ -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,11 @@
1
+ require 'chomsky'
2
+
3
+ module Chomsky
4
+ class Parser
5
+ class Blank < Regexp
6
+ def initialize
7
+ super(%r{\s+})
8
+ end
9
+ end
10
+ end
11
+ 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,15 @@
1
+ require 'chomsky'
2
+
3
+ module Chomsky
4
+ class Parser
5
+ class Nothing < Parser
6
+ def call string
7
+ if string.empty?
8
+ ["", string]
9
+ else
10
+ [nil, string]
11
+ end
12
+ end
13
+ end
14
+ end
15
+ 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
@@ -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
@@ -0,0 +1,7 @@
1
+ module Chomsky
2
+ autoload :Grammar, "chomsky/grammar"
3
+ autoload :Rule, "chomsky/rule"
4
+ autoload :Action, "chomsky/action"
5
+ autoload :Parser, "chomsky/parser"
6
+ autoload :ParserGenerator, "chomsky/parser_generator"
7
+ end
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: