pegarus 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.
Files changed (90) hide show
  1. data/LICENSE +22 -0
  2. data/README +24 -0
  3. data/Rakefile +70 -0
  4. data/lib/pegarus/ast/always.rb +7 -0
  5. data/lib/pegarus/ast/any.rb +13 -0
  6. data/lib/pegarus/ast/any_range.rb +13 -0
  7. data/lib/pegarus/ast/character.rb +13 -0
  8. data/lib/pegarus/ast/character_range.rb +13 -0
  9. data/lib/pegarus/ast/choice.rb +7 -0
  10. data/lib/pegarus/ast/concatenation.rb +7 -0
  11. data/lib/pegarus/ast/difference.rb +7 -0
  12. data/lib/pegarus/ast/grammar.rb +56 -0
  13. data/lib/pegarus/ast/if.rb +9 -0
  14. data/lib/pegarus/ast/never.rb +7 -0
  15. data/lib/pegarus/ast/pattern.rb +127 -0
  16. data/lib/pegarus/ast/product.rb +12 -0
  17. data/lib/pegarus/ast/set.rb +13 -0
  18. data/lib/pegarus/ast/unless.rb +9 -0
  19. data/lib/pegarus/ast/variable.rb +15 -0
  20. data/lib/pegarus/ast.rb +16 -0
  21. data/lib/pegarus/compatibility.rb +25 -0
  22. data/lib/pegarus/evaluator.rb +93 -0
  23. data/lib/pegarus/machine/compiler.rb +18 -0
  24. data/lib/pegarus/machine/generator.rb +8 -0
  25. data/lib/pegarus/machine/instructions.rb +65 -0
  26. data/lib/pegarus/machine/interpreter.rb +31 -0
  27. data/lib/pegarus/machine/state.rb +29 -0
  28. data/lib/pegarus/machine.rb +15 -0
  29. data/lib/pegarus/parser/parse_error.rb +3 -0
  30. data/lib/pegarus/parser.rb +1 -0
  31. data/lib/pegarus/rubinius/compiler.rb +220 -0
  32. data/lib/pegarus/rubinius/generator.rb +48 -0
  33. data/lib/pegarus/rubinius.rb +4 -0
  34. data/lib/pegarus/version.rb +3 -0
  35. data/lib/pegarus.rb +3 -0
  36. data/spec/ast/choice_spec.rb +9 -0
  37. data/spec/ast/concatenation_spec.rb +9 -0
  38. data/spec/ast/difference_spec.rb +9 -0
  39. data/spec/ast/grammar_spec.rb +54 -0
  40. data/spec/ast/if_spec.rb +8 -0
  41. data/spec/ast/pattern_spec.rb +123 -0
  42. data/spec/ast/product_spec.rb +28 -0
  43. data/spec/ast/unless_spec.rb +8 -0
  44. data/spec/ast/variable_spec.rb +4 -0
  45. data/spec/custom/guards/engine.rb +27 -0
  46. data/spec/machine/instructions/call_spec.rb +21 -0
  47. data/spec/machine/instructions/capture_spec.rb +15 -0
  48. data/spec/machine/instructions/char_spec.rb +34 -0
  49. data/spec/machine/instructions/choice_spec.rb +15 -0
  50. data/spec/machine/instructions/commit_spec.rb +21 -0
  51. data/spec/machine/instructions/fail_spec.rb +34 -0
  52. data/spec/machine/instructions/jump_spec.rb +15 -0
  53. data/spec/machine/instructions/return_spec.rb +16 -0
  54. data/spec/matching/evaluator/any_spec.rb +6 -0
  55. data/spec/matching/evaluator/character_spec.rb +6 -0
  56. data/spec/matching/evaluator/choice_spec.rb +6 -0
  57. data/spec/matching/evaluator/concatenation_spec.rb +6 -0
  58. data/spec/matching/evaluator/difference_spec.rb +6 -0
  59. data/spec/matching/evaluator/if_spec.rb +6 -0
  60. data/spec/matching/evaluator/product_spec.rb +6 -0
  61. data/spec/matching/evaluator/setup.rb +4 -0
  62. data/spec/matching/evaluator/unless_spec.rb +6 -0
  63. data/spec/matching/machine/any_spec.rb +6 -0
  64. data/spec/matching/machine/character_spec.rb +6 -0
  65. data/spec/matching/machine/choice_spec.rb +6 -0
  66. data/spec/matching/machine/concatenation_spec.rb +6 -0
  67. data/spec/matching/machine/difference_spec.rb +6 -0
  68. data/spec/matching/machine/if_spec.rb +6 -0
  69. data/spec/matching/machine/product_spec.rb +6 -0
  70. data/spec/matching/machine/setup.rb +4 -0
  71. data/spec/matching/machine/unless_spec.rb +6 -0
  72. data/spec/matching/rubinius/any_spec.rb +8 -0
  73. data/spec/matching/rubinius/character_spec.rb +8 -0
  74. data/spec/matching/rubinius/choice_spec.rb +8 -0
  75. data/spec/matching/rubinius/concatenation_spec.rb +8 -0
  76. data/spec/matching/rubinius/difference_spec.rb +8 -0
  77. data/spec/matching/rubinius/if_spec.rb +8 -0
  78. data/spec/matching/rubinius/product_spec.rb +8 -0
  79. data/spec/matching/rubinius/setup.rb +4 -0
  80. data/spec/matching/rubinius/unless_spec.rb +8 -0
  81. data/spec/matching/shared/any.rb +13 -0
  82. data/spec/matching/shared/character.rb +17 -0
  83. data/spec/matching/shared/choice.rb +16 -0
  84. data/spec/matching/shared/concatenation.rb +16 -0
  85. data/spec/matching/shared/difference.rb +2 -0
  86. data/spec/matching/shared/if.rb +16 -0
  87. data/spec/matching/shared/product.rb +2 -0
  88. data/spec/matching/shared/unless.rb +16 -0
  89. data/spec/spec_helper.rb +12 -0
  90. metadata +166 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Brian Ford. All rights reserved.
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,24 @@
1
+ Pegarus is, broadly, an implementation of LPEG on Rubinius. LPEG implements a
2
+ Parsing Expression Grammar using a parsing machine rather than the Packrat
3
+ algorithm. (See "A Text Pattern-Matching Tool based on Parsing Expression
4
+ Grammars" by Roberto Ierusalimschy.)
5
+
6
+ Pegarus actually implements an abstract syntax tree (AST) for the PEG. There
7
+ are various options to execute the AST against a subject string. One option is
8
+ a simple AST-walking evaluator. A second option is an implementation of the
9
+ LPEG parsing machine. A third option is a compiler that targets Rubinius
10
+ bytecode.
11
+
12
+
13
+ 1. Running the specs
14
+
15
+ Pegarus uses the mspec gem because of the facilities for tags and easily
16
+ defining custom matchers and guards, since Pegarus targets more than one Ruby
17
+ implementation.
18
+
19
+ To run the specs, use the following steps:
20
+
21
+ 1. Install the mspec gem
22
+ 2. If you plan to use Rubinius, ensure 'rbx' is on your path
23
+ 3. Run 'rake' to run the specs with $RUBY or 'rbx'
24
+ 4. Set the environment variable RUBY to the name of the Ruby to use
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+ require 'rake/gempackagetask'
2
+
3
+ task :default => :spec
4
+
5
+ BASE_DIR = File.expand_path('../', __FILE__)
6
+ RUBY = ENV["RUBY"] || "rbx"
7
+
8
+ def spec(target)
9
+ sh("mspec -t #{target} -T -I#{BASE_DIR} spec") { |ok, res| }
10
+ end
11
+
12
+ desc "Run the specs with $RUBY or 'rbx' (default)"
13
+ task :spec do
14
+ spec RUBY
15
+ end
16
+
17
+ namespace :spec do
18
+ desc "Run the specs with Rubinius"
19
+ task :rbx do
20
+ spec "rbx"
21
+ end
22
+
23
+ desc "Run the specs with the 'ruby' on $PATH"
24
+ task :ruby do
25
+ spec "ruby"
26
+ end
27
+
28
+ desc "Run the specs with all engines"
29
+ task :all => [:rbx, :ruby]
30
+ end
31
+
32
+ spec = Gem::Specification.new do |s|
33
+ require File.expand_path('../lib/pegarus/version', __FILE__)
34
+
35
+ s.name = "pegarus"
36
+ s.version = Pegarus::VERSION.to_s
37
+
38
+ s.specification_version = 2 if s.respond_to? :specification_version=
39
+
40
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
41
+ s.authors = ["Brian Ford"]
42
+ s.date = %q{2010-10-24}
43
+ s.email = %q{brixen@gmail.com}
44
+ s.has_rdoc = true
45
+ s.extra_rdoc_files = %w[ README LICENSE ]
46
+ s.executables = []
47
+ s.files = FileList[ '{bin,lib,spec}/**/*.{yaml,txt,rb}', 'Rakefile', *s.extra_rdoc_files ]
48
+ s.homepage = %q{http://github.com/brixen/pegarus}
49
+ s.require_paths = ["lib"]
50
+ s.rubygems_version = %q{1.3.5}
51
+ s.summary = "Pegarus is an implementation of LPEG in Ruby."
52
+ s.description = <<EOS
53
+ Pegarus is, broadly, an implementation of LPEG on Rubinius. LPEG implements a
54
+ Parsing Expression Grammar using a parsing machine rather than the Packrat
55
+ algorithm. (See "A Text Pattern-Matching Tool based on Parsing Expression
56
+ Grammars" by Roberto Ierusalimschy.)
57
+
58
+ Pegarus actually implements an abstract syntax tree (AST) for the PEG. There
59
+ are various options to execute the AST against a subject string. One option is
60
+ a simple AST-walking evaluator. A second option is an implementation of the
61
+ LPEG parsing machine. A third option is a compiler that targets Rubinius
62
+ bytecode.
63
+ EOS
64
+
65
+ s.rdoc_options << '--title' << 'Pegarus Gem' <<
66
+ '--main' << 'README' <<
67
+ '--line-numbers'
68
+ end
69
+
70
+ Rake::GemPackageTask.new(spec){ |pkg| pkg.gem_spec = spec }
@@ -0,0 +1,7 @@
1
+ module Pegarus
2
+ class Always < Pattern
3
+ def visit(visitor)
4
+ visitor.always self
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module Pegarus
2
+ class Any < Pattern
3
+ attr_accessor :count
4
+
5
+ def initialize(count)
6
+ @count = count
7
+ end
8
+
9
+ def visit(visitor)
10
+ visitor.any self
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Pegarus
2
+ class AnyRange < Pattern
3
+ attr_accessor :range
4
+
5
+ def initialize(range)
6
+ @range = range
7
+ end
8
+
9
+ def visit(visitor)
10
+ visitor.any_range self
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Pegarus
2
+ class Character < Pattern
3
+ attr_accessor :string
4
+
5
+ def initialize(string)
6
+ @string = string
7
+ end
8
+
9
+ def visit(visitor)
10
+ visitor.character self
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Pegarus
2
+ class CharacterRange < Pattern
3
+ attr_accessor :range
4
+
5
+ def initialize(range)
6
+ @range = range
7
+ end
8
+
9
+ def visit(visitor)
10
+ visitor.character_range self
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module Pegarus
2
+ class Choice < BinaryOp
3
+ def visit(visitor)
4
+ visitor.choice self
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Pegarus
2
+ class Concatenation < BinaryOp
3
+ def visit(visitor)
4
+ visitor.concatenation self
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Pegarus
2
+ class Difference < BinaryOp
3
+ def visit(visitor)
4
+ visitor.difference self
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,56 @@
1
+ module Pegarus
2
+ def grammar(spec=nil, pattern=nil)
3
+ case spec
4
+ when Symbol
5
+ Grammar.new Variable.new(spec, pattern)
6
+ when Variable
7
+ Grammar.new spec
8
+ when Pattern
9
+ Grammar.new Variable.new(:S, spec)
10
+ when nil
11
+ Grammar.new
12
+ else
13
+ Grammar.new Variable.new(:S, pattern)
14
+ end
15
+ end
16
+ module_function :grammar
17
+
18
+ class Grammar < Pattern
19
+ attr_accessor :start
20
+
21
+ def initialize(variable=nil)
22
+ if variable
23
+ @start = variable.name
24
+ set_variable variable.name, variable.pattern
25
+ end
26
+ end
27
+
28
+ def set_variable(name, *pattern)
29
+ variable = get_variable name
30
+ variable.pattern = *pattern
31
+ variable
32
+ end
33
+
34
+ def get_variable(name)
35
+ if metaclass.method_defined? name
36
+ variable = send name
37
+ else
38
+ vname = name.to_sym
39
+ variable = Variable.new vname
40
+ metaclass.thunk_method vname, variable
41
+ end
42
+
43
+ variable
44
+ end
45
+
46
+ def method_missing(sym, *args)
47
+ name = sym.to_s
48
+
49
+ if name[-1] == ?=
50
+ set_variable name[0..-2], *args
51
+ else
52
+ get_variable name
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,9 @@
1
+ module Pegarus
2
+ # Implements &patt in a PEG. The pattern succeeds if
3
+ # patt matches. Does not consume any input.
4
+ class If < UnaryOp
5
+ def visit(visitor)
6
+ visitor.if self
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Pegarus
2
+ class Never < Pattern
3
+ def visit(visitor)
4
+ visitor.never self
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,127 @@
1
+ module Pegarus
2
+ # Accepts a Ruby object representation of simple PEG "atoms" and returns an
3
+ # AST node.
4
+ def pattern(spec)
5
+ case spec
6
+ when Array
7
+ Set.new spec.join
8
+ when Integer
9
+ Any.new spec
10
+ when String
11
+ Character.new spec
12
+ when Range
13
+ case spec.first
14
+ when Integer
15
+ AnyRange.new spec
16
+ when String
17
+ CharacterRange.new spec
18
+ end
19
+ when Symbol
20
+ variable spec
21
+ when Pattern
22
+ spec
23
+ when true
24
+ Always.new
25
+ when false
26
+ Never.new
27
+ when nil
28
+ nil
29
+ else
30
+ raise ParseError, "unknown specification type for Pattern: #{spec.inspect}"
31
+ end
32
+ end
33
+ module_function :pattern
34
+
35
+
36
+ # Class Pattern is the base class for all nodes used to represent the AST
37
+ # for a PEG. Following LPEG, the base is a pattern and not a grammar.
38
+ class Pattern
39
+ # Executes the PEG pattern on subject. If the pattern matches a prefix of
40
+ # subject, returns the index one character past the last matching
41
+ # character. Otherwise, returns nil.
42
+ #
43
+ # The pattern AST is purely a representation. By default, it includes no
44
+ # machinery to execute the pattern over the subject. All execution is
45
+ # provided by other facilities, for example, the AST evaluator and the
46
+ # parsing machine compiler and interpreter. These facilities are called
47
+ # "engines".
48
+ #
49
+ # The Pattern class defaults to the AST Evaluator engine. The protocol
50
+ # requires the engine class to respond to .new_exector taking the AST root
51
+ # node and the subject as arguments. The default Pattern#match method is
52
+ # essentially a trampoline. It calls new_executor and expects that method
53
+ # to replace #match on the root node and then tail call to the new #match
54
+ # method installed by the engine.
55
+
56
+ def match(subject)
57
+ Pattern.engine.new_executor self, subject
58
+ end
59
+
60
+ def self.engine
61
+ unless @engine
62
+ require 'pegarus/evaluator'
63
+ @engine = Evaluator
64
+ end
65
+
66
+ @engine
67
+ end
68
+
69
+ def self.select_engine(klass)
70
+ @engine = klass
71
+ end
72
+
73
+ def graph
74
+ if defined? Rubinius
75
+ Rubinius::AST::AsciiGrapher.new(self, Pattern).print
76
+ else
77
+ inspect
78
+ end
79
+ end
80
+
81
+ def visit(visitor)
82
+ end
83
+
84
+ # Pattern operators
85
+
86
+ def /(other)
87
+ Choice.new self, other
88
+ end
89
+
90
+ def +(other)
91
+ Concatenation.new self, other
92
+ end
93
+
94
+ def -(other)
95
+ Difference.new self, other
96
+ end
97
+
98
+ def *(other)
99
+ Product.new self, other
100
+ end
101
+
102
+ def +@
103
+ If.new self
104
+ end
105
+
106
+ def -@
107
+ Unless.new self
108
+ end
109
+ end
110
+
111
+ class UnaryOp < Pattern
112
+ attr_accessor :pattern
113
+
114
+ def initialize(pattern)
115
+ @pattern = Pegarus.pattern pattern
116
+ end
117
+ end
118
+
119
+ class BinaryOp < Pattern
120
+ attr_accessor :first, :second
121
+
122
+ def initialize(first, second)
123
+ @first = Pegarus.pattern first
124
+ @second = Pegarus.pattern second
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,12 @@
1
+ module Pegarus
2
+ class Product < BinaryOp
3
+ def initialize(first, second)
4
+ @first = Pegarus.pattern first
5
+ @second = Type.coerce_to second, Integer, :to_int
6
+ end
7
+
8
+ def visit(visitor)
9
+ visitor.product self
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Pegarus
2
+ class Set < Pattern
3
+ attr_accessor :characters
4
+
5
+ def initialize(characters)
6
+ @characters = characters
7
+ end
8
+
9
+ def visit(visitor)
10
+ visitor.set self
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ module Pegarus
2
+ # Implements !patt in a PEG. The pattern succeeds if
3
+ # patt does not match. Does not consume any input.
4
+ class Unless < UnaryOp
5
+ def visit(visitor)
6
+ visitor.unless self
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ module Pegarus
2
+ def variable(name, pattern=nil)
3
+ Pegarus::Variable.new name, pattern
4
+ end
5
+ module_function :variable
6
+
7
+ class Variable < Pattern
8
+ attr_accessor :name, :pattern
9
+
10
+ def initialize(name, pattern=nil)
11
+ @name = name.to_sym
12
+ @pattern = Pegarus.pattern pattern
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ require 'pegarus/ast/pattern'
2
+ require 'pegarus/ast/always'
3
+ require 'pegarus/ast/any'
4
+ require 'pegarus/ast/any_range'
5
+ require 'pegarus/ast/character'
6
+ require 'pegarus/ast/character_range'
7
+ require 'pegarus/ast/choice'
8
+ require 'pegarus/ast/concatenation'
9
+ require 'pegarus/ast/difference'
10
+ require 'pegarus/ast/if'
11
+ require 'pegarus/ast/never'
12
+ require 'pegarus/ast/product'
13
+ require 'pegarus/ast/set'
14
+ require 'pegarus/ast/unless'
15
+ require 'pegarus/ast/grammar'
16
+ require 'pegarus/ast/variable'
@@ -0,0 +1,25 @@
1
+ class Module
2
+ unless method_defined? :thunk_method
3
+ def thunk_method(name, value)
4
+ define_method(name) { return value }
5
+ end
6
+ end
7
+ end
8
+
9
+ unless defined?(Type)
10
+ module Type
11
+ def self.coerce_to(obj, cls, meth)
12
+ return obj if obj.kind_of? cls
13
+
14
+ begin
15
+ ret = obj.__send__(meth)
16
+ rescue Exception
17
+ raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed"
18
+ end
19
+
20
+ return ret if ret.kind_of? cls
21
+
22
+ raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,93 @@
1
+ module Pegarus
2
+ class Evaluator
3
+ def self.new_executor(pattern, subject)
4
+ pattern.instance_variable_set :@evaluator, new
5
+
6
+ class << pattern
7
+ class_eval <<-eval
8
+ def match(subject)
9
+ @evaluator.match self, subject
10
+ end
11
+ eval
12
+ end
13
+
14
+ pattern.match subject
15
+ end
16
+
17
+ def match(pattern, subject)
18
+ @subject = subject
19
+ @failure = false
20
+ @index = 0
21
+
22
+ pattern.visit self
23
+
24
+ failure? ? nil : @index
25
+ end
26
+
27
+ def failure
28
+ @failure = true
29
+ end
30
+
31
+ def failure?
32
+ @failure
33
+ end
34
+
35
+ def always(pattern)
36
+ failure
37
+ end
38
+
39
+ def any(pattern)
40
+ if @subject.size > @index + pattern.count
41
+ @index += pattern.count
42
+ else
43
+ failure
44
+ end
45
+ end
46
+
47
+ def any_range(pattern)
48
+ failure
49
+ end
50
+
51
+ def character(pattern)
52
+ failure
53
+ end
54
+
55
+ def character_range(pattern)
56
+ failure
57
+ end
58
+
59
+ def choice(pattern)
60
+ failure
61
+ end
62
+
63
+ def concatenation(pattern)
64
+ failure
65
+ end
66
+
67
+ def difference(pattern)
68
+ failure
69
+ end
70
+
71
+ def if(pattern)
72
+ failure
73
+ end
74
+
75
+ def never(pattern)
76
+ failure
77
+ end
78
+
79
+ def product(pattern)
80
+ failure
81
+ end
82
+
83
+ def set(pattern)
84
+ failure
85
+ end
86
+
87
+ def unless(pattern)
88
+ failure
89
+ end
90
+ end
91
+ end
92
+
93
+ Pegarus::Pattern.select_engine Pegarus::Evaluator
@@ -0,0 +1,18 @@
1
+ module Pegarus
2
+ module Machine
3
+ class Compiler
4
+ def compile(pattern)
5
+ program = []
6
+ pattern.instance_variable_set :@program, program
7
+
8
+ class << pattern
9
+ class_eval <<-eval
10
+ def match(subject)
11
+ Pegarus::Machine.execute @program, subject
12
+ end
13
+ eval
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ module Pegarus
2
+ module ParsingMachine
3
+ class Generator
4
+ def initialize
5
+ end
6
+ end
7
+ end
8
+ end