peglite 0.0.1 → 0.0.2

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/.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  GemSpec = Gem::Specification.new do |gem|
4
4
  gem.name = 'peglite'
5
- gem.version = '0.0.1'
5
+ gem.version = '0.0.2'
6
6
  gem.license = 'MIT'
7
7
  gem.required_ruby_version = '>= 1.9.1'
8
8
 
data/CHANGELOG.yaml CHANGED
@@ -1,3 +1,9 @@
1
+ - version: 0.0.2
2
+ date: Wed Jan 2 18:05:30 PST 2013
3
+ changes:
4
+ - Add examples
5
+ - Add \A to regexes automatically
6
+ - Test an extended grammar
1
7
  - version: 0.0.1
2
8
  date: Wed Jan 2 14:51:35 PST 2013
3
9
  changes: Ported from Pegex.pm CPAN module.
data/ToDo ADDED
@@ -0,0 +1,2 @@
1
+ + Add \A automatically
2
+ + Add accessor for @input
@@ -0,0 +1,23 @@
1
+ require 'peglite'
2
+
3
+ class Mini < PegLite
4
+ rule integer: (/(\d+)/)
5
+ end
6
+
7
+ p Mini.new.parse "132432" # => "132432"
8
+
9
+ __END__
10
+ This is the PegLite version of the "simplest Parselet" example from here:
11
+
12
+ http://kschiess.github.com/parslet/get-started.html
13
+
14
+ Here is the original:
15
+
16
+ require 'parslet'
17
+
18
+ class Mini < Parslet::Parser
19
+ rule(:integer) { match('[0-9]').repeat(1) }
20
+ root(:integer)
21
+ end
22
+
23
+ Mini.new.parse("132432") # => "132432"@0
@@ -0,0 +1,51 @@
1
+ require 'peglite'
2
+
3
+ class Mini < PegLite
4
+ rule expression: "sum | integer"
5
+ rule integer: /(\d+)/
6
+ rule operator: /([+])/
7
+ rule sum: "integer _ operator _ expression"
8
+ end
9
+
10
+ def parse str
11
+ mini = Mini.new
12
+ mini.parse str
13
+ rescue PegLite::PegexParseError => failure
14
+ Mini.new(debug: true).parse str
15
+ end
16
+
17
+ p parse "1 + 2 + 3" # => ["1", "+", ["2", "+", "3"]]
18
+ p parse "a + 2" # => Print debug trace and error analysis
19
+
20
+ __END__
21
+ This is the PegLite version of the "Parselet expression parser" example from
22
+ here:
23
+
24
+ http://kschiess.github.com/parslet/get-started.html
25
+
26
+ Here is the original:
27
+
28
+ class Mini < Parslet::Parser
29
+ rule(:integer) { match('[0-9]').repeat(1) >> space? }
30
+
31
+ rule(:space) { match('\s').repeat(1) }
32
+ rule(:space?) { space.maybe }
33
+
34
+ rule(:operator) { match('[+]') >> space? }
35
+
36
+ rule(:sum) { integer >> operator >> expression }
37
+ rule(:expression) { sum | integer }
38
+
39
+ root :expression
40
+ end
41
+
42
+ def parse(str)
43
+ mini = Mini.new
44
+
45
+ mini.parse(str)
46
+ rescue Parslet::ParseFailed => failure
47
+ puts failure.cause.ascii_tree
48
+ end
49
+
50
+ parse "1 + 2 + 3" # => "1 + 2 + 3"@0
51
+ parse "a + 2" # fails, see below
data/lib/peglite.rb CHANGED
@@ -7,17 +7,18 @@ require 'yaml'; def YYY *args; args.each \
7
7
 
8
8
  #------------------------------------------------------------------------------
9
9
  class PegLite
10
- $PegLiteRules = {} # XXX global variable smell
10
+ VERSION = '0.0.2'
11
+
12
+ $PegLiteRules = {} # TODO get rid of global variable smell
11
13
  def self.rule args
12
14
  name, rule = args.first
13
15
  name = name.to_s
14
16
  $PegLiteTopRule ||= name
15
17
  if rule.kind_of? Regexp
16
- fail "Regexp for '#{name}' must begin with '\\A'" \
17
- unless rule.to_s.match /\A\(\?-mix:\\A/
18
+ regex = Regexp.new(rule.to_s.sub(/:/, ':\\A'))
18
19
  $PegLiteRules[name] = {
19
20
  'type' => 'rgx',
20
- 'rule' => rule,
21
+ 'rule' => regex,
21
22
  'min' => 1,
22
23
  'max' => 1,
23
24
  }
@@ -28,20 +29,25 @@ class PegLite
28
29
  end
29
30
  end
30
31
 
31
- rule _: (/\A\s*/)
32
- rule __: (/\A\s+/)
33
- rule EQUAL: (/\A=/)
34
- rule COMMA: (/\A,/)
35
- rule NL: (/\A\n/)
32
+ # TODO define all the Pegex Atoms here
33
+ rule _: (/\s*/)
34
+ rule __: (/\s+/)
35
+ rule EQUAL: (/=/)
36
+ rule COMMA: (/,/)
37
+ rule PLUS: (/\+/)
38
+ rule NL: (/\n/)
39
+ rule EOL: (/\r?\n/)
36
40
  $PegLiteTopRule = nil
37
41
 
38
42
  attr_accessor :got
39
43
  attr_accessor :wrap
40
44
  attr_accessor :debug
45
+ attr_accessor :input
41
46
  def initialize attrs={}
42
47
  @got = nil
43
48
  @wrap = false
44
49
  @debug = false
50
+ @input = nil
45
51
 
46
52
  attrs.each { |k,v| self.send "#{k}=", v }
47
53
 
@@ -51,7 +57,7 @@ class PegLite
51
57
  yield self if block_given?
52
58
  end
53
59
 
54
- def parse input, top=($PegLiteTopRule || 'top')
60
+ def parse input=@input, top=($PegLiteTopRule || 'top')
55
61
  fail "PegLite parse() method requires an input string" \
56
62
  unless input.kind_of? String
57
63
  @input = input
data/test/address.rb CHANGED
@@ -1,12 +1,18 @@
1
+ # This PegLite test shows an address grammar parsing an street address.
2
+ # We parse it 3 different ways, to get different desired results.
3
+
4
+
1
5
  require 'test/unit'
2
6
  require 'peglite'
3
7
 
4
- $address1 = <<'...'
8
+ # A sample street address
9
+ $address = <<'...'
5
10
  John Doe
6
11
  123 Main St
7
12
  Los Angeles, CA 90009
8
13
  ...
9
14
 
15
+ # Expected result tree for default/plain parsing
10
16
  $parse_plain = <<'...'
11
17
  ---
12
18
  - John Doe
@@ -16,6 +22,7 @@ $parse_plain = <<'...'
16
22
  - '90009'
17
23
  ...
18
24
 
25
+ # Expected result tree using the 'wrap' option
19
26
  $parse_wrap = <<'...'
20
27
  ---
21
28
  address:
@@ -32,25 +39,67 @@ address:
32
39
  - '90009'
33
40
  ...
34
41
 
42
+ # Expected result tree from our Custom parser extension
43
+ $parse_custom = <<'...'
44
+ ---
45
+ name: John Doe
46
+ street: 123 Main St
47
+ city: Los Angeles
48
+ state: CA
49
+ zipcode: '90008'
50
+ ...
51
+
52
+ # Run 3 tests
35
53
  class Test::Unit::TestCase
54
+ # Parse address to an array of arrays
36
55
  def test_plain
37
56
  parser = AddressParser.new
38
- result = parser.parse $address1
57
+ result = parser.parse $address
39
58
  assert_equal YAML.dump(result), $parse_plain, "Plain parse works"
40
59
  end
60
+ # Turn on 'wrap' to add rule name to each result
41
61
  def test_wrap
42
62
  parser = AddressParser.new wrap: true
43
- result = parser.parse $address1
63
+ result = parser.parse $address
44
64
  assert_equal YAML.dump(result), $parse_wrap, "Wrapping parse works"
45
65
  end
66
+ # Return a custom AST
67
+ def test_custom
68
+ parser = AddressParserCustom.new
69
+ result = parser.parse $address
70
+ assert_equal YAML.dump(result), $parse_custom, "Custom parse works"
71
+ end
46
72
  end
47
73
 
74
+ # This class defines a complete address parser using PegLite
48
75
  class AddressParser < PegLite
49
76
  rule address: "name street place"
50
- rule name: (/\A(.*?)\n/)
51
- rule street: (/\A(.*?)\n/)
77
+ rule name: (/(.*?)\n/)
78
+ rule street: (/(.*?)\n/)
52
79
  rule place: "city COMMA _ state __ zip NL"
53
- rule city: (/\A(\w+(?: \w+)?)/)
54
- rule state: (/\A(WA|OR|CA)/) # Left Coast Rulez
55
- rule zip: (/\A(\d{5})/)
80
+ rule city: (/(\w+(?: \w+)?)/)
81
+ rule state: (/(WA|OR|CA)/) # Left Coast Rulez
82
+ rule zip: (/(\d{5})/)
83
+ end
84
+
85
+ # Extend AddressParser
86
+ class AddressParserCustom < AddressParser
87
+ def address
88
+ name, street, place = match.first
89
+ city, state, zip = place
90
+ # Make the final AST from the parts collected.
91
+ @got = {
92
+ 'name' => name,
93
+ 'street' => street,
94
+ 'city' => city,
95
+ 'state' => state,
96
+ # Show as 'zipcode' instead of 'zip'
97
+ 'zipcode' => zip,
98
+ }
99
+ end
100
+
101
+ # Subtract 1 from the zipcode for fun
102
+ def zip
103
+ (match.first.to_i - 1).to_s
104
+ end
56
105
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peglite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-02 00:00:00.000000000 Z
12
+ date: 2013-01-03 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'PegLite is a very simple framework for creating your own PEG parsers.
15
15
 
@@ -25,6 +25,9 @@ files:
25
25
  - LICENSE
26
26
  - README.rdoc
27
27
  - Rakefile
28
+ - ToDo
29
+ - examples/parslet1.rb
30
+ - examples/parslet2.rb
28
31
  - lib/peglite.rb
29
32
  - lib/peglite/compiler.rb
30
33
  - test/address.rb