citrus 1.0.0 → 1.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/citrus.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'citrus'
3
- s.version = '1.0.0'
4
- s.date = '2010-05-13'
3
+ s.version = '1.1.0'
4
+ s.date = '2010-05-18'
5
5
 
6
6
  s.summary = 'Parsing Expressions for Ruby'
7
7
  s.description = 'Parsing Expressions for Ruby'
@@ -13,6 +13,7 @@ Gem::Specification.new do |s|
13
13
 
14
14
  s.files = Dir['lib/**/*.rb'] +
15
15
  Dir['examples/**/*'] +
16
+ Dir['extras/**/*'] +
16
17
  Dir['test/*.rb'] +
17
18
  %w< citrus.gemspec Rakefile README >
18
19
 
@@ -4,7 +4,6 @@ require 'citrus/sugar'
4
4
  # non-negative numbers (integers and floats), respecting operator precedence and
5
5
  # ignoring whitespace.
6
6
  Calc = Citrus::Grammar.new {
7
-
8
7
  module FirstValue
9
8
  def value
10
9
  first.value
data/extras/citrus.vim ADDED
@@ -0,0 +1,92 @@
1
+ " Vim syntax file for Citrus grammars.
2
+ "
3
+ " Language: Citrus
4
+ " Author: Michael Jackson
5
+
6
+ if version < 600
7
+ syntax clear
8
+ elseif exists("b:current_syntax")
9
+ finish
10
+ endif
11
+
12
+ syn include @rubyTop syntax/ruby.vim
13
+
14
+ syn case match
15
+
16
+ syn match ctDoubleColon "::" contained
17
+ syn match ctConstant "\u\w*" contained
18
+ syn match ctVariable "\l\w*" contained
19
+ syn match ctModule "\(\(::\)\?\u\w*\)\+" contains=ctDoubleColon,ctConstant contained
20
+
21
+ " Comments
22
+ syn match ctComment "#.*" contains=@Spell
23
+
24
+ " Keywords
25
+ syn match ctKeyword "\<super\>" contained
26
+
27
+ " Terminals
28
+ syn region ctString matchgroup=ctStringDelimiter start="\"" end="\"" skip="\\\\\|\\\"" contains=@ctStringSpecial
29
+ syn region ctString matchgroup=ctStringDelimiter start="'" end="'" skip="\\\\\|\\'"
30
+ syn region ctRegexp matchgroup=ctRegexpDelimiter start="/" end="/[iomxneus]*" skip="\\\\\|\\/" contains=@ctRegexpSpecial contained display
31
+ syn region ctCharClass matchgroup=ctRegexpDelimiter start="\[" end="\]" skip="\\\\\|\\\[" contains=@ctRegexpSpecial contained display
32
+ syn match ctAnything "\." contained display
33
+
34
+ syn cluster ctStringSpecial contains=rubyStringEscape
35
+ syn cluster ctRegexpSpecial contains=rubyStringEscape,rubyRegexpSpecial,rubyRegexpEscape,rubyRegexpBrackets,rubyRegexpCharClass,rubyRegexpDot,rubyRegexpQuantifier,rubyRegexpAnchor,rubyRegexpParens,rubyRegexpComment
36
+
37
+ " Quantifiers
38
+ syn match ctQuantifier "+" contained display
39
+ syn match ctQuantifier "?" contained display
40
+ syn match ctQuantifier "\d*\*\d*" contained display
41
+
42
+ " Operators
43
+ syn match ctOperator "|" contained
44
+ syn match ctOperator "\l\w*:"me=e-1 contained
45
+
46
+ " Extensions
47
+ syn region ctRubyBlock start="{"ms=e+1 end="}"me=s-1 contains=@rubyTop contained
48
+ syn match ctTag "<\s*\(\(::\)\?\u\w*\)\+\s*>" contains=ctModule contained
49
+
50
+ " Declarations
51
+ syn match ctRequire "\<require\>" nextgroup=ctString skipwhite skipnl
52
+ syn match ctGrammar "\<grammar\>" nextgroup=ctModule skipwhite skipnl
53
+ syn match ctInclude "\<include\>" nextgroup=ctModule skipwhite skipnl contained
54
+ syn match ctRoot "\<root\>" nextgroup=ctVariable skipwhite skipnl contained
55
+ syn match ctRule "\<rule\>" nextgroup=ctVariable skipwhite skipnl contained
56
+
57
+ " Blocks
58
+ syn region ctGrammarBlock start="\<grammar\>" matchgroup=ctGrammar end="\<end\>" contains=ctComment,ctGrammar,ctInclude,ctRoot,ctRuleBlock fold
59
+ syn region ctRuleBlock start="\<rule\>" matchgroup=ctRule end="\<end\>" contains=ALLBUT,ctRequire,ctGrammar,ctInclude,ctRoot,ctConstant,ctVariable fold
60
+
61
+ " Groups
62
+ hi def link ctComment Comment
63
+
64
+ hi def link ctRequire Include
65
+ hi def link ctInclude Include
66
+ hi def link ctGrammar ctDefine
67
+ hi def link ctRoot ctDefine
68
+ hi def link ctRule ctDefine
69
+ hi def link ctDefine Define
70
+
71
+ hi def link ctConstant Type
72
+ hi def link ctVariable Function
73
+ hi def link ctKeyword Keyword
74
+
75
+ hi def link ctString ctTerminal
76
+ hi def link ctRegexp ctTerminal
77
+ hi def link ctCharClass ctTerminal
78
+ hi def link ctAnything ctTerminal
79
+ hi def link ctTerminal String
80
+
81
+ hi def link ctRegexpDelimiter ctStringDelimiter
82
+ hi def link ctStringDelimiter Delimiter
83
+
84
+ hi def link ctRegexpSpecial ctStringSpecial
85
+ hi def link ctStringSpecial Special
86
+
87
+ hi def link ctQuantifier ctOperator
88
+ hi def link ctOperator Operator
89
+
90
+ let b:current_syntax = "citrus"
91
+
92
+ " vim: nowrap:
data/lib/citrus.rb CHANGED
@@ -4,29 +4,31 @@
4
4
  #
5
5
  # http://github.com/mjijackson/citrus
6
6
  module Citrus
7
- VERSION = [1, 0, 0]
7
+ VERSION = [1, 1, 0]
8
8
 
9
9
  Infinity = 1.0 / 0
10
10
 
11
- autoload 'PEG', 'citrus/peg'
11
+ autoload 'File', 'citrus/file'
12
12
 
13
13
  # Returns the current version of Citrus as a string.
14
14
  def self.version
15
15
  VERSION.join('.')
16
16
  end
17
17
 
18
+ F = ::File
19
+
18
20
  # Loads the grammar from the given +file+ into the global scope using #eval.
19
21
  def self.load(file)
20
- file << '.citrus' unless File.file?(file)
21
- raise "Cannot find file #{file}" unless File.file?(file)
22
- raise "Cannot read file #{file}" unless File.readable?(file)
23
- self.eval(File.read(file))
22
+ file << '.citrus' unless F.file?(file)
23
+ raise "Cannot find file #{file}" unless F.file?(file)
24
+ raise "Cannot read file #{file}" unless F.readable?(file)
25
+ self.eval(F.read(file))
24
26
  end
25
27
 
26
28
  # Evaluates the given Citrus parsing expression grammar +code+ in the global
27
29
  # scope. Returns an array of any grammar modules that were created.
28
30
  def self.eval(code)
29
- file = PEG.parse(code)
31
+ file = File.parse(code)
30
32
  file.value
31
33
  end
32
34
 
@@ -63,19 +65,15 @@ module Citrus
63
65
  # module is in fact a grammar.
64
66
  module Grammar
65
67
  # Creates a new anonymous module that includes Grammar. If a +block+ is
66
- # provided, it will be called with the new module as its first argument if
67
- # its +arity+ is 1 or +instance_eval+'d in the context of the new module
68
- # otherwise. See http://blog.grayproductions.net/articles/dsl_block_styles
69
- # for the rationale behind this decision.
70
- #
71
- # Grammars created with this method may be assigned a name by being assigned
72
- # to some constant, e.g.:
68
+ # provided, it is +module_eval+'d in the context of the new module. Grammars
69
+ # created with this method may be assigned a name by being assigned to some
70
+ # constant, e.g.:
73
71
  #
74
72
  # Calc = Grammar.new {}
75
73
  #
76
74
  def self.new(&block)
77
75
  mod = Module.new { include Grammar }
78
- block.arity == 1 ? block[mod] : mod.instance_eval(&block) if block
76
+ mod.module_eval(&block) if block
79
77
  mod
80
78
  end
81
79
 
@@ -888,7 +886,7 @@ module Citrus
888
886
 
889
887
  # Checks equality by comparing this match's #text value to +obj+.
890
888
  def ==(obj)
891
- text == obj
889
+ obj == text
892
890
  end
893
891
 
894
892
  alias eql? ==
@@ -1,11 +1,10 @@
1
1
  require 'citrus'
2
2
 
3
3
  module Citrus
4
- # A grammar for Citrus-flavored parsing expression grammars. This module is
5
- # used in Citrus#eval to parse and evaluate Citrus PEG's and serves as a prime
6
- # example of how to create a complex grammar complete with semantic
7
- # interpretation in pure Ruby.
8
- module PEG
4
+ # A grammar for Citrus grammar files. This module is used in Citrus#eval to
5
+ # parse and evaluate Citrus grammars and serves as a prime example of how to
6
+ # create a complex grammar complete with semantic interpretation in pure Ruby.
7
+ module File
9
8
  include Grammar
10
9
 
11
10
  ## Hierarchical syntax
@@ -356,7 +355,6 @@ module Citrus
356
355
  rule :require_keyword, [ 'require', :space ]
357
356
  rule :include_keyword, [ 'include', :space ]
358
357
  rule :grammar_keyword, [ 'grammar', :space ]
359
- rule :super_keyword, [ 'super', :space ]
360
358
  rule :root_keyword, [ 'root', :space ]
361
359
  rule :rule_keyword, [ 'rule', :space ]
362
360
  rule :end_keyword, [ 'end', :space ]
@@ -1,4 +1,9 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
+
3
+ if defined?(Calc)
4
+ Object.__send__(:remove_const, :Calc)
5
+ end
6
+
2
7
  Citrus.load(File.dirname(__FILE__) + '/../examples/calc')
3
8
 
4
9
  class CalcPEGTest < Test::Unit::TestCase
@@ -1,4 +1,9 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
+
3
+ if defined?(Calc)
4
+ Object.__send__(:remove_const, :Calc)
5
+ end
6
+
2
7
  require File.dirname(__FILE__) + '/../examples/calc_sugar'
3
8
 
4
9
  class CalcSugarTest < Test::Unit::TestCase
data/test/calc_test.rb CHANGED
@@ -1,4 +1,9 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
+
3
+ if defined?(Calc)
4
+ Object.__send__(:remove_const, :Calc)
5
+ end
6
+
2
7
  require File.dirname(__FILE__) + '/../examples/calc'
3
8
 
4
9
  class CalcTest < Test::Unit::TestCase
@@ -1,42 +1,40 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
- require 'citrus/peg'
2
+ require 'citrus/file'
3
3
 
4
- class PEGTest < Test::Unit::TestCase
4
+ class CitrusFileTest < Test::Unit::TestCase
5
5
 
6
6
  # A shortcut for creating a grammar that includes Citrus::PEG but uses a
7
7
  # different root.
8
8
  def peg(root_rule)
9
9
  Grammar.new {
10
- include Citrus::PEG
10
+ include Citrus::File
11
11
  root root_rule
12
12
  }
13
13
  end
14
14
 
15
-
16
15
  ## File tests
17
16
 
17
+ F = ::File
18
18
 
19
19
  def run_file_test(file, root)
20
20
  grammar = peg(root)
21
- code = File.read(file)
21
+ code = F.read(file)
22
22
  match = grammar.parse(code)
23
23
  assert(match)
24
24
  end
25
25
 
26
26
  %w< rule grammar >.each do |type|
27
- Dir[File.dirname(__FILE__) + "/_files/#{type}*.citrus"].each do |path|
27
+ Dir[F.dirname(__FILE__) + "/_files/#{type}*.citrus"].each do |path|
28
28
  module_eval(<<-RUBY.gsub(/^ /, ''), __FILE__, __LINE__ + 1)
29
- def test_#{File.basename(path, '.citrus')}
29
+ def test_#{F.basename(path, '.citrus')}
30
30
  run_file_test("#{path}", :#{type})
31
31
  end
32
32
  RUBY
33
33
  end
34
34
  end
35
35
 
36
-
37
36
  ## Hierarchical syntax
38
37
 
39
-
40
38
  def test_rule_body
41
39
  grammar = peg(:rule_body)
42
40
 
data/test/grammar_test.rb CHANGED
@@ -3,9 +3,9 @@ require File.dirname(__FILE__) + '/helper'
3
3
  class GrammarTest < Test::Unit::TestCase
4
4
 
5
5
  def test_new
6
- Grammar.new do |g|
7
- assert_kind_of(Module, g)
8
- assert(g.include?(Grammar))
6
+ Grammar.new do
7
+ assert_kind_of(Module, self)
8
+ assert(include?(Grammar))
9
9
  end
10
10
  end
11
11
 
data/test/match_test.rb CHANGED
@@ -49,6 +49,18 @@ class MatchTest < Test::Unit::TestCase
49
49
  assert_equal(11, match.length)
50
50
  end
51
51
 
52
+ def test_equality
53
+ match1 = Match.new('a')
54
+ match2 = Match.new('a')
55
+ assert(match1 == 'a')
56
+ assert(match1 == match2)
57
+ assert(match2 == match1)
58
+
59
+ match3 = Match.new('b')
60
+ assert_equal(false, match1 == match3)
61
+ assert_equal(false, match3 == match1)
62
+ end
63
+
52
64
  def test_matches
53
65
  match = Double.parse('123')
54
66
  assert(match)
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
+ - 1
7
8
  - 0
8
- - 0
9
- version: 1.0.0
9
+ version: 1.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Michael Jackson
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-13 00:00:00 -06:00
17
+ date: 2010-05-18 00:00:00 -06:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -51,12 +51,13 @@ extra_rdoc_files:
51
51
  - README
52
52
  files:
53
53
  - lib/citrus/debug.rb
54
- - lib/citrus/peg.rb
54
+ - lib/citrus/file.rb
55
55
  - lib/citrus/sugar.rb
56
56
  - lib/citrus.rb
57
57
  - examples/calc.citrus
58
58
  - examples/calc.rb
59
59
  - examples/calc_sugar.rb
60
+ - extras/citrus.vim
60
61
  - test/alias_test.rb
61
62
  - test/and_predicate_test.rb
62
63
  - test/calc_peg_test.rb
@@ -64,13 +65,13 @@ files:
64
65
  - test/calc_test.rb
65
66
  - test/choice_test.rb
66
67
  - test/expression_test.rb
68
+ - test/file_test.rb
67
69
  - test/fixed_width_test.rb
68
70
  - test/grammar_test.rb
69
71
  - test/helper.rb
70
72
  - test/label_test.rb
71
73
  - test/match_test.rb
72
74
  - test/not_predicate_test.rb
73
- - test/peg_test.rb
74
75
  - test/repeat_test.rb
75
76
  - test/rule_test.rb
76
77
  - test/sequence_test.rb
@@ -121,12 +122,12 @@ test_files:
121
122
  - test/calc_test.rb
122
123
  - test/choice_test.rb
123
124
  - test/expression_test.rb
125
+ - test/file_test.rb
124
126
  - test/fixed_width_test.rb
125
127
  - test/grammar_test.rb
126
128
  - test/label_test.rb
127
129
  - test/match_test.rb
128
130
  - test/not_predicate_test.rb
129
- - test/peg_test.rb
130
131
  - test/repeat_test.rb
131
132
  - test/rule_test.rb
132
133
  - test/sequence_test.rb