File: grammar_test.rb

package info (click to toggle)
ruby-citrus 3.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 420 kB
  • sloc: ruby: 3,417; makefile: 5
file content (164 lines) | stat: -rw-r--r-- 3,582 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
require File.expand_path('../helper', __FILE__)

class GrammarTest < Test::Unit::TestCase
  def test_new
    grammar = Grammar.new
    assert_kind_of(Module, grammar)
    assert(grammar.include?(Grammar))
  end

  def test_name
    assert_equal("Test::Unit::TestCase::TestGrammar", TestGrammar.name)
  end

  def test_no_name
    grammar = Grammar.new
    assert_equal('', grammar.name)
  end

  def test_rule_names
    assert_equal([:alpha, :num, :alphanum], TestGrammar.rule_names)
  end

  def test_has_name
    assert(TestGrammar.has_rule?('alpha'))
    assert(TestGrammar.has_rule?(:alpha))
  end

  def test_doesnt_have_name
    assert_equal(false, TestGrammar.has_rule?(:value))
  end

  def test_parse_fixed_width
    grammar = Grammar.new {
      rule(:abc) { 'abc' }
    }
    match = grammar.parse('abc')
    assert(match)
    assert_equal('abc', match)
    assert_equal(3, match.length)
  end

  def test_parse_expression
    grammar = Grammar.new {
      rule(:alpha) { /[a-z]+/i }
    }
    match = grammar.parse('abc')
    assert(match)
    assert_equal('abc', match)
    assert_equal(3, match.length)
  end

  def test_parse_sequence
    grammar = Grammar.new {
      rule(:num) { all(1, 2, 3) }
    }
    match = grammar.parse('123')
    assert(match)
    assert_equal('123', match)
    assert_equal(3, match.length)
  end

  def test_parse_sequence_long
    grammar = Grammar.new {
      rule(:num) { all(1, 2, 3) }
    }
    match = grammar.parse('1234', :consume => false)
    assert(match)
    assert_equal('123', match)
    assert_equal(3, match.length)
  end

  def test_parse_sequence_short
    grammar = Grammar.new {
      rule(:num) { all(1, 2, 3) }
    }
    assert_raise ParseError do
      grammar.parse('12')
    end
  end

  def test_parse_choice
    grammar = Grammar.new {
      rule(:alphanum) { any(/[a-z]/i, 0..9) }
    }

    match = grammar.parse('a')
    assert(match)
    assert_equal('a', match)
    assert_equal(1, match.length)

    match = grammar.parse('1')
    assert(match)
    assert_equal('1', match)
    assert_equal(1, match.length)
  end

  def test_parse_choice_miss
    grammar = Grammar.new {
      rule(:alphanum) { any(/[a-z]/, 0..9) }
    }
    assert_raise ParseError do
      grammar.parse('A')
    end
  end

  def test_parse_recurs
    grammar = Grammar.new {
      rule(:paren) { any(['(', :paren, ')'], /[a-z]/) }
    }

    match = grammar.parse('a')
    assert(match)
    assert_equal('a', match)
    assert_equal(1, match.length)

    match = grammar.parse('((a))')
    assert(match)
    assert_equal('((a))', match)
    assert_equal(5, match.length)

    n = 100
    str = ('(' * n) + 'a' + (')' * n)
    match = grammar.parse(str)
    assert(match)
    assert_equal(str, match)
    assert_equal(str.length, match.length)
  end

  def test_parse_file
    grammar = Grammar.new {
      rule("words"){ rep(any(" ", /[a-z]+/)) }
    }

    require 'tempfile'
    Tempfile.open('citrus') do |tmp|
      tmp << "abd def"
      tmp.close

      match = grammar.parse_file(tmp.path)

      assert(match)
      assert_instance_of(Input, match.input)
      assert_instance_of(Pathname, match.source)

      match.matches.each do |m|
        assert_instance_of(Input, m.input)
        assert_instance_of(Pathname, m.source)
      end
    end
  end

  def test_labeled_production
    grammar = Grammar.new {
      rule(:abc) { label('abc', :p){ capture(:p) } }
    }
    assert_equal('abc', grammar.parse('abc').value)
  end

  def test_global_grammar
    assert_raise ArgumentError do
      grammar(:abc)
    end
  end
end