kpeg 0.8.5 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.autotest +10 -0
  2. data/.gemtest +0 -0
  3. data/Gemfile +11 -3
  4. data/History.txt +21 -0
  5. data/LICENSE +25 -0
  6. data/Manifest.txt +47 -0
  7. data/README.rdoc +222 -0
  8. data/Rakefile +23 -11
  9. data/bin/kpeg +4 -2
  10. data/examples/calculator/calculator.kpeg +17 -0
  11. data/examples/calculator/calculator.rb +7 -0
  12. data/examples/foreign_reference/literals.kpeg +5 -0
  13. data/examples/foreign_reference/matcher.kpeg +9 -0
  14. data/examples/foreign_reference/matcher.rb +5 -0
  15. data/examples/lua_string/driver.rb +21 -0
  16. data/examples/lua_string/lua_string.kpeg +14 -0
  17. data/examples/lua_string/lua_string.kpeg.rb +460 -0
  18. data/examples/phone_number/README.md +3 -0
  19. data/examples/phone_number/phone_number.kpeg +20 -0
  20. data/examples/phone_number/phone_number.rb +6 -0
  21. data/examples/upper/README.md +83 -0
  22. data/examples/upper/upper.kpeg +24 -0
  23. data/examples/upper/upper.rb +9 -0
  24. data/kpeg.gemspec +35 -17
  25. data/lib/hoe/kpeg.rb +94 -0
  26. data/lib/kpeg.rb +3 -0
  27. data/lib/kpeg/code_generator.rb +16 -3
  28. data/lib/kpeg/compiled_parser.rb +18 -28
  29. data/lib/kpeg/format_parser.kpeg +129 -0
  30. data/lib/kpeg/format_parser.rb +88 -49
  31. data/lib/kpeg/grammar.rb +10 -0
  32. data/lib/kpeg/string_escape.kpeg +20 -0
  33. data/test/inputs/comments.kpeg +5 -0
  34. data/test/test_file_parser_roundtrip.rb +3 -3
  35. data/test/test_gen_calc.rb +2 -2
  36. data/test/test_kpeg.rb +2 -2
  37. data/test/test_kpeg_code_generator.rb +65 -2
  38. data/test/test_kpeg_compiled_parser.rb +2 -2
  39. data/test/test_kpeg_format.rb +49 -4
  40. data/test/test_kpeg_grammar_renderer.rb +2 -2
  41. data/test/test_left_recursion.rb +2 -2
  42. data/{doc → vim}/syntax_kpeg/ftdetect/kpeg.vim +0 -0
  43. data/{doc → vim}/syntax_kpeg/syntax/kpeg.vim +0 -0
  44. metadata +89 -26
  45. data/README.md +0 -183
  46. data/lib/kpeg/version.rb +0 -3
@@ -0,0 +1,5 @@
1
+ %% name = Name
2
+ word = /\w+/
3
+ root = word
4
+ # kjkjk
5
+ # asldkjf
@@ -1,12 +1,12 @@
1
+ require 'minitest/autorun'
1
2
  require 'kpeg'
2
3
  require 'kpeg/format_parser'
3
4
  require 'kpeg/grammar_renderer'
4
5
  require 'kpeg/code_generator'
5
6
  require 'stringio'
6
- require 'test/unit'
7
7
 
8
- class TestKPegRoundtrip < Test::Unit::TestCase
9
- PATH = File.expand_path("../../lib/kpeg/format.kpeg", __FILE__)
8
+ class TestKPegRoundtrip < MiniTest::Unit::TestCase
9
+ PATH = File.expand_path("../../lib/kpeg/format_parser.kpeg", __FILE__)
10
10
  def test_roundtrip
11
11
  data = File.read(PATH)
12
12
 
@@ -1,10 +1,10 @@
1
- require 'test/unit'
1
+ require 'minitest/autorun'
2
2
  require 'kpeg'
3
3
  require 'kpeg/format_parser'
4
4
  require 'kpeg/code_generator'
5
5
  require 'stringio'
6
6
 
7
- class TestKPegCodeGenerator < Test::Unit::TestCase
7
+ class TestKPegCodeGenerator < MiniTest::Unit::TestCase
8
8
  GRAMMAR = <<-'STR'
9
9
  Stmt = - Expr:e EOL { @answers << e }
10
10
  | ( !EOL . )* EOL { puts "error" }
data/test/test_kpeg.rb CHANGED
@@ -1,8 +1,8 @@
1
- require 'test/unit'
1
+ require 'minitest/autorun'
2
2
  require 'kpeg'
3
3
  require 'stringio'
4
4
 
5
- class TestKPeg < Test::Unit::TestCase
5
+ class TestKPeg < MiniTest::Unit::TestCase
6
6
  def assert_match(m, str)
7
7
  assert_kind_of KPeg::MatchString, m
8
8
  assert_equal str, m.string
@@ -1,10 +1,10 @@
1
1
  # encoding: utf-8
2
- require 'test/unit'
2
+ require 'minitest/autorun'
3
3
  require 'kpeg'
4
4
  require 'kpeg/code_generator'
5
5
  require 'stringio'
6
6
 
7
- class TestKPegCodeGenerator < Test::Unit::TestCase
7
+ class TestKPegCodeGenerator < MiniTest::Unit::TestCase
8
8
  def test_dot
9
9
  gram = KPeg.grammar do |g|
10
10
  g.root = g.dot
@@ -1370,6 +1370,69 @@ end
1370
1370
  assert_equal 5, code.failing_rule_offset
1371
1371
  end
1372
1372
 
1373
+ def test_directive_footer
1374
+ gram = KPeg.grammar do |g|
1375
+ g.root = g.dot
1376
+ g.directives['footer'] = g.action("\n# require 'some/subclass'\n")
1377
+ end
1378
+
1379
+ str = <<-STR
1380
+ require 'kpeg/compiled_parser'
1381
+
1382
+ class Test < KPeg::CompiledParser
1383
+
1384
+ # root = .
1385
+ def _root
1386
+ _tmp = get_byte
1387
+ set_failed_rule :_root unless _tmp
1388
+ return _tmp
1389
+ end
1390
+
1391
+ Rules = {}
1392
+ Rules[:_root] = rule_info("root", ".")
1393
+ end
1394
+
1395
+ # require 'some/subclass'
1396
+ STR
1397
+
1398
+ cg = KPeg::CodeGenerator.new "Test", gram
1399
+
1400
+ assert_equal str, cg.output
1401
+
1402
+ assert cg.parse("hello")
1403
+ end
1404
+
1405
+ def test_directive_header
1406
+ gram = KPeg.grammar do |g|
1407
+ g.root = g.dot
1408
+ g.directives['header'] = g.action("\n# coding: UTF-8\n")
1409
+ end
1410
+
1411
+ str = <<-STR
1412
+ # coding: UTF-8
1413
+ require 'kpeg/compiled_parser'
1414
+
1415
+ class Test < KPeg::CompiledParser
1416
+
1417
+ # root = .
1418
+ def _root
1419
+ _tmp = get_byte
1420
+ set_failed_rule :_root unless _tmp
1421
+ return _tmp
1422
+ end
1423
+
1424
+ Rules = {}
1425
+ Rules[:_root] = rule_info("root", ".")
1426
+ end
1427
+ STR
1428
+
1429
+ cg = KPeg::CodeGenerator.new "Test", gram
1430
+
1431
+ assert_equal str, cg.output
1432
+
1433
+ assert cg.parse("hello")
1434
+ end
1435
+
1373
1436
  def test_setup_actions
1374
1437
  gram = KPeg.grammar do |g|
1375
1438
  g.root = g.dot
@@ -1,9 +1,9 @@
1
- require 'test/unit'
1
+ require 'minitest/autorun'
2
2
  require 'kpeg'
3
3
  require 'kpeg/compiled_parser'
4
4
  require 'stringio'
5
5
 
6
- class TestKPegCompiledParser < Test::Unit::TestCase
6
+ class TestKPegCompiledParser < MiniTest::Unit::TestCase
7
7
 
8
8
  gram = <<-GRAM
9
9
  letter = [a-z]
@@ -1,14 +1,14 @@
1
- require 'test/unit'
1
+ require 'minitest/autorun'
2
2
  require 'kpeg'
3
3
  require 'kpeg/format_parser'
4
4
  require 'kpeg/grammar_renderer'
5
5
  require 'stringio'
6
6
  require 'rubygems'
7
7
 
8
- class TestKPegFormat < Test::Unit::TestCase
8
+ class TestKPegFormat < MiniTest::Unit::TestCase
9
9
  G = KPeg::Grammar.new
10
10
 
11
- gram = File.read File.expand_path("../../lib/kpeg/format.kpeg", __FILE__)
11
+ gram = File.read File.expand_path("../../lib/kpeg/format_parser.kpeg", __FILE__)
12
12
  KPeg.compile gram, "TestParser", self
13
13
 
14
14
  def match(str, gram=nil, log=false)
@@ -386,6 +386,51 @@ Value = NUMBER:i { i }
386
386
  assert_rule G.seq(G.ref('b'), G.ref("c")), m
387
387
  end
388
388
 
389
+ def test_parser_directive
390
+ m = match <<-GRAMMAR
391
+ %% header {
392
+ # coding: UTF-8
393
+ }
394
+
395
+ a=b
396
+ GRAMMAR
397
+
398
+ assert_rule G.ref("b"), m
399
+
400
+ expected = {
401
+ "header" => KPeg::Action.new("\n# coding: UTF-8\n")
402
+ }
403
+
404
+ assert_equal expected, m.directives
405
+ end
406
+
407
+ def test_parser_directive_duplicate
408
+ m = nil
409
+
410
+ out, err = capture_io do
411
+ m = match <<-GRAMMAR
412
+ %% header {
413
+ # coding: UTF-8
414
+ }
415
+
416
+ a=b
417
+
418
+ %% header {
419
+ # coding: ISO-8859-1
420
+ }
421
+ GRAMMAR
422
+ end
423
+
424
+ assert_empty out
425
+ assert_equal "directive \"header\" appears more than once\n", err
426
+
427
+ expected = {
428
+ "header" => KPeg::Action.new("\n# coding: ISO-8859-1\n")
429
+ }
430
+
431
+ assert_equal expected, m.directives
432
+ end
433
+
389
434
  def test_parser_setup
390
435
  m = match "%% { def initialize; end }\na=b"
391
436
  assert_rule G.ref("b"), m
@@ -469,7 +514,7 @@ fact = fact "*" num
469
514
  end
470
515
 
471
516
  def test_roundtrip
472
- path = File.expand_path("../../lib/kpeg/format.kpeg", __FILE__)
517
+ path = File.expand_path("../../lib/kpeg/format_parser.kpeg", __FILE__)
473
518
  parser = KPeg::FormatParser.new File.read(path)
474
519
  assert parser.parse, "Unable to parse"
475
520
 
@@ -1,9 +1,9 @@
1
- require 'test/unit'
1
+ require 'minitest/autorun'
2
2
  require 'kpeg'
3
3
  require 'kpeg/grammar_renderer'
4
4
  require 'stringio'
5
5
 
6
- class TestKPegGrammarRenderer < Test::Unit::TestCase
6
+ class TestKPegGrammarRenderer < MiniTest::Unit::TestCase
7
7
  def test_escape
8
8
  str = "hello\nbob"
9
9
  assert_equal 'hello\nbob', KPeg::GrammarRenderer.escape(str)
@@ -1,10 +1,10 @@
1
- require 'test/unit'
1
+ require 'minitest/autorun'
2
2
  require 'kpeg'
3
3
  require 'kpeg/format_parser'
4
4
  require 'kpeg/code_generator'
5
5
  require 'stringio'
6
6
 
7
- class TestKPegLeftRecursion < Test::Unit::TestCase
7
+ class TestKPegLeftRecursion < MiniTest::Unit::TestCase
8
8
  GRAMMAR = <<-'STR'
9
9
 
10
10
  name = name:n "[]" { [:array, n] }
File without changes
File without changes
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kpeg
3
3
  version: !ruby/object:Gem::Version
4
- hash: 53
4
+ hash: 59
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 8
9
- - 5
10
- version: 0.8.5
8
+ - 9
9
+ - 0
10
+ version: 0.9.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Evan Phoenix
@@ -15,50 +15,109 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-01-08 00:00:00 Z
18
+ date: 2012-03-07 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: rake
21
+ name: minitest
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
24
  none: false
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- hash: 3
28
+ hash: 37
29
29
  segments:
30
- - 0
31
- version: "0"
30
+ - 2
31
+ - 11
32
+ - 3
33
+ version: 2.11.3
32
34
  type: :development
33
35
  version_requirements: *id001
34
- description: A tool for generating parsers using PEG
36
+ - !ruby/object:Gem::Dependency
37
+ name: rdoc
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 19
45
+ segments:
46
+ - 3
47
+ - 10
48
+ version: "3.10"
49
+ type: :development
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: hoe
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ hash: 27
60
+ segments:
61
+ - 2
62
+ - 12
63
+ version: "2.12"
64
+ type: :development
65
+ version_requirements: *id003
66
+ description: |-
67
+ KPeg is a simple PEG library for Ruby. It provides an API as well as native
68
+ grammar to build the grammar.
69
+
70
+ KPeg strives to provide a simple, powerful API without being too exotic.
71
+
72
+ KPeg supports direct left recursion of rules via the
73
+ {OMeta memoization}[http://www.vpri.org/pdf/tr2008003_experimenting.pdf] trick.
35
74
  email:
36
75
  - evan@fallingsnow.net
37
76
  executables:
38
77
  - kpeg
39
78
  extensions: []
40
79
 
41
- extra_rdoc_files: []
42
-
80
+ extra_rdoc_files:
81
+ - History.txt
82
+ - Manifest.txt
43
83
  files:
84
+ - .autotest
85
+ - Gemfile
86
+ - History.txt
87
+ - LICENSE
88
+ - Manifest.txt
89
+ - README.rdoc
90
+ - Rakefile
91
+ - bin/kpeg
92
+ - examples/calculator/calculator.kpeg
93
+ - examples/calculator/calculator.rb
94
+ - examples/foreign_reference/literals.kpeg
95
+ - examples/foreign_reference/matcher.kpeg
96
+ - examples/foreign_reference/matcher.rb
97
+ - examples/lua_string/driver.rb
98
+ - examples/lua_string/lua_string.kpeg
99
+ - examples/lua_string/lua_string.kpeg.rb
100
+ - examples/phone_number/README.md
101
+ - examples/phone_number/phone_number.kpeg
102
+ - examples/phone_number/phone_number.rb
103
+ - examples/upper/README.md
104
+ - examples/upper/upper.kpeg
105
+ - examples/upper/upper.rb
106
+ - kpeg.gemspec
107
+ - lib/hoe/kpeg.rb
108
+ - lib/kpeg.rb
44
109
  - lib/kpeg/code_generator.rb
45
110
  - lib/kpeg/compiled_parser.rb
111
+ - lib/kpeg/format_parser.kpeg
46
112
  - lib/kpeg/format_parser.rb
47
113
  - lib/kpeg/grammar.rb
48
114
  - lib/kpeg/grammar_renderer.rb
49
115
  - lib/kpeg/match.rb
50
116
  - lib/kpeg/parser.rb
51
117
  - lib/kpeg/position.rb
118
+ - lib/kpeg/string_escape.kpeg
52
119
  - lib/kpeg/string_escape.rb
53
- - lib/kpeg/version.rb
54
- - lib/kpeg.rb
55
- - bin/kpeg
56
- - doc/syntax_kpeg/ftdetect/kpeg.vim
57
- - doc/syntax_kpeg/syntax/kpeg.vim
58
- - README.md
59
- - Rakefile
60
- - kpeg.gemspec
61
- - Gemfile
120
+ - test/inputs/comments.kpeg
62
121
  - test/test_file_parser_roundtrip.rb
63
122
  - test/test_gen_calc.rb
64
123
  - test/test_kpeg.rb
@@ -67,12 +126,16 @@ files:
67
126
  - test/test_kpeg_format.rb
68
127
  - test/test_kpeg_grammar_renderer.rb
69
128
  - test/test_left_recursion.rb
129
+ - vim/syntax_kpeg/ftdetect/kpeg.vim
130
+ - vim/syntax_kpeg/syntax/kpeg.vim
131
+ - .gemtest
70
132
  homepage: https://github.com/evanphx/kpeg
71
133
  licenses: []
72
134
 
73
135
  post_install_message:
74
- rdoc_options: []
75
-
136
+ rdoc_options:
137
+ - --main
138
+ - README.rdoc
76
139
  require_paths:
77
140
  - lib
78
141
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -95,11 +158,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
158
  version: "0"
96
159
  requirements: []
97
160
 
98
- rubyforge_project:
99
- rubygems_version: 1.8.15
161
+ rubyforge_project: kpeg
162
+ rubygems_version: 1.8.17
100
163
  signing_key:
101
164
  specification_version: 3
102
- summary: Peg-based Code Generator
165
+ summary: KPeg is a simple PEG library for Ruby
103
166
  test_files:
104
167
  - test/test_file_parser_roundtrip.rb
105
168
  - test/test_gen_calc.rb
data/README.md DELETED
@@ -1,183 +0,0 @@
1
- KPeg
2
- ====
3
-
4
- KPeg is a simple PEG library for Ruby. It provides an API as well as native grammar to build the grammar.
5
-
6
- KPeg strives to provide a simple, powerful API without being too exotic.
7
-
8
- KPeg supports direct left recursion of rules via the [OMeta memoization](http://www.vpri.org/pdf/tr2008003_experimenting.pdf) trick.
9
-
10
- ## Writing your first grammar
11
-
12
- ### Setting up your grammar
13
-
14
- All grammars start with with the class/module name that will be your parser
15
-
16
- %% name = Example::Parser
17
-
18
- After that a block of ruby code can be defined that will be added into the class body of your parser. Attributes that are defined in this block can be accessed within your parser as instance variables. Methods can also be defined in this block and used in action blocks as well.
19
-
20
- %% {
21
- attr_accessor :something_cool
22
-
23
- def something_awesome
24
- # do something awesome
25
- end
26
- }
27
-
28
- ### Defining literals
29
-
30
- Literals are static declarations of characters or regular expressions designed for reuse in the grammar. These can be constants or variables. Literals can take strings, regular expressions or character ranges
31
-
32
- ALPHA = /[A-Za-z]/
33
- DIGIT = /[0-9]/
34
- period = "."
35
- string = "a string"
36
- regex = /(regexs?)+/
37
- char_range = [b-t]
38
-
39
- Literals can also accept multiple definitions
40
-
41
- vowel = "a" | "e" | "i" | "o" | "u"
42
- alpha = /[A-Z]/ | /[a-z]/
43
-
44
- ### Defining Rules for Values
45
-
46
- Before you can start parsing a string you will need to define rules that you will use to accept or reject that string. There are many different types of rules available in kpeg
47
-
48
- The most basic of these rules is a string capture
49
-
50
- alpha = < /[A-Za-z]/ > { text }
51
-
52
-
53
- While this looks very much like the ALPHA literal defined above it differs in one important way, the text captured by the rule defined between the < and > symbols will be set as the text variable in block that follows. You can also explicitly define the variable that you would like but only with existing rules or literals.
54
-
55
- letter = alpha:a { a }
56
-
57
- Additionally blocks can return true or false values based upon an expression within the block. To return true if a test passes do the following:
58
-
59
- match_greater_than_10 = < num:n > &{ n > 10 }
60
-
61
- To test and return a false value if the test passes do the following:
62
-
63
- do_not_match_greater_than_10 = < num:n > !{ n > 10 }
64
-
65
- Rules can also act like functions and take parameters. An example of this is lifted from the [Email List Validator](https://github.com/larb/email_address_validator), where an ascii value is passed in and the character is evaluated against it returning a true if it matches
66
-
67
- d(num) = <.> &{ text[0] == num }
68
-
69
- Rules support some regular expression syntax for matching
70
-
71
- + maybe ?
72
- + many +
73
- + kleene *
74
- + groupings ()
75
-
76
- Examples
77
-
78
- letters = alpha+
79
- words = alpha+ space* period?
80
- sentence = (letters+ | space+)+
81
-
82
- Kpeg also allows a rule to define the acceptable number of matches in the form of a range. In regular expressions this is often denoted with syntax like {0,3}. Kpeg uses this syntax to accomplish match ranges [min, max].
83
-
84
- matches_3_to_5_times = letter[3,5]
85
- matches_3_to_any_times = letter[3,*]
86
-
87
- ### Defining Actions
88
-
89
- Illustrated above in some of the examples, kpeg allows you to perform actions based upon a match that are described in block provided or in the rule definition itself.
90
-
91
- num = /[1-9][0-9]*/
92
- sum = < num:n1 "+" num:n2 > { n1 + n2 }
93
-
94
- As of version 0.8 an alternate syntax has been added for calling defined methods as actions.
95
-
96
- %% {
97
- def add(n1, n2){
98
- n1 + n2
99
- }
100
- }
101
- num = /[1-9][0-9]*/
102
- sum = < num:n1 "+" num:n2 > ~add(n1, n2)
103
-
104
- ### Referencing an external grammar
105
-
106
- Kpeg allows you to run a rule that is defined in an external grammar. This is useful if there is a defined set of rules that you would like to reuse in another parser. To do this, create your grammar and generate a parser using the kpeg command line tool.
107
-
108
- kpeg literals.kpeg
109
-
110
- Once you have the generated parser, include that file into your new grammar
111
-
112
- %{
113
- require "literals.kpeg.rb"
114
- }
115
-
116
- Then create a variable to hold to foreign interface and pass it the class name of your parser. In this case my parser class name is Literal
117
-
118
- %foreign_grammer = Literal
119
-
120
- You can then use rules defined in the foreign grammar in the local grammar file like so
121
-
122
- sentence = (%foreign_grammer.alpha %foreign_grammer.space*)+ %foreign_grammer.period
123
-
124
- ### Comments
125
-
126
- Kpeg allows comments to be added to the grammar file by using the # symbol
127
-
128
- # This is a comment in my grammar
129
-
130
- ## Generating and running your parser
131
-
132
- Before you can generate your parser you will need to define a root rule. This will be the first rule run against the string provided to the parser
133
-
134
- root = sentence
135
-
136
- To generate the parser run the kpeg command with the kpeg file(s) as an argument. This will generate a ruby file with the same name as your grammar file.
137
-
138
- kpeg example.kpeg
139
-
140
- Include your generated parser file into an application that you want to use the parser in and run it. Create a new instance of the parser and pass in the string you want to evaluate. When parse is called on the parser instance it will return a true if the sting is matched, or false if it doesn't.
141
-
142
- require "example.kpeg.rb"
143
-
144
- parser = Example::Parser.new(string_to_evaluate)
145
- parser.parse
146
-
147
- ## Shortcuts and other techniques
148
-
149
- Per vito, you can get the current line or current column in the following way
150
-
151
- line = { current_line }
152
- column = { current_column }
153
- foo = line:line ... { # use line here }
154
-
155
- ## AST Generation
156
-
157
- As of Kpeg 0.8 a parser can now generate an AST. To define an AST node use the following syntax
158
-
159
- %% assign = ast Assignment(name, value)
160
-
161
- Once you have a defined AST node, it can be used in your grammar like so
162
-
163
- assignment = identifier:i space* = space* value:v ~assign(i,v)
164
-
165
- This will create a new Assign node that you can add into your AST.
166
-
167
- For a good example of usage check out [Talon](https://github.com/evanphx/talon)
168
-
169
- ## Examples
170
-
171
- There are several examples available in the /examples directory. The upper parser has a readme with a step by step description of the grammar.
172
-
173
- ## Projects using kpeg
174
-
175
- [Dang](https://github.com/veganstraightedge/dang)
176
-
177
- [Email Address Validator](https://github.com/larb/email_address_validator)
178
-
179
- [Callisto](https://github.com/dwaite/Callisto)
180
-
181
- [Doodle](https://github.com/vito/doodle)
182
-
183
- [Kanbanpad](https://kanbanpad.com) (uses kpeg for parsing of the 'enter something' bar)