citrus 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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