walrus 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/bin/walrus +19 -12
  2. data/lib/walrus.rb +27 -70
  3. data/lib/walrus/additions/string.rb +21 -35
  4. data/lib/walrus/compile_error.rb +19 -16
  5. data/lib/walrus/compiler.rb +66 -55
  6. data/lib/walrus/contrib/spec/walruscloth_spec.rb +21 -17
  7. data/lib/walrus/contrib/walruscloth.rb +19 -11
  8. data/lib/walrus/document.rb +41 -33
  9. data/lib/walrus/grammar.rb +474 -162
  10. data/lib/walrus/grammar/assignment_expression.rb +33 -0
  11. data/lib/walrus/grammar/block_directive.rb +37 -0
  12. data/lib/walrus/grammar/comment.rb +33 -0
  13. data/lib/walrus/grammar/def_directive.rb +80 -0
  14. data/lib/walrus/grammar/echo_directive.rb +56 -0
  15. data/lib/walrus/grammar/escape_sequence.rb +33 -0
  16. data/lib/walrus/grammar/import_directive.rb +54 -0
  17. data/lib/walrus/grammar/include_directive.rb +36 -0
  18. data/lib/walrus/grammar/instance_variable.rb +33 -0
  19. data/lib/walrus/grammar/literal.rb +33 -0
  20. data/lib/walrus/grammar/message_expression.rb +34 -0
  21. data/lib/walrus/grammar/multiline_comment.rb +70 -0
  22. data/lib/walrus/grammar/placeholder.rb +47 -0
  23. data/lib/walrus/grammar/raw_directive.rb +50 -0
  24. data/lib/walrus/grammar/raw_text.rb +56 -0
  25. data/lib/walrus/grammar/ruby_directive.rb +41 -0
  26. data/lib/walrus/grammar/ruby_expression.rb +42 -0
  27. data/lib/walrus/grammar/set_directive.rb +34 -0
  28. data/lib/walrus/grammar/silent_directive.rb +51 -0
  29. data/lib/walrus/grammar/slurp_directive.rb +36 -0
  30. data/lib/walrus/grammar/super_directive.rb +34 -0
  31. data/lib/walrus/parser.rb +26 -408
  32. data/lib/walrus/runner.rb +37 -20
  33. data/lib/walrus/template.rb +34 -25
  34. data/lib/walrus/version.rb +24 -1
  35. metadata +57 -71
  36. data/ext/extconf.rb +0 -16
  37. data/ext/jindex.c +0 -92
  38. data/lib/walrus/diff.rb +0 -95
  39. data/lib/walrus/grammar/additions/proc.rb +0 -26
  40. data/lib/walrus/grammar/additions/regexp.rb +0 -27
  41. data/lib/walrus/grammar/additions/string.rb +0 -58
  42. data/lib/walrus/grammar/additions/symbol.rb +0 -49
  43. data/lib/walrus/grammar/and_predicate.rb +0 -46
  44. data/lib/walrus/grammar/array_result.rb +0 -25
  45. data/lib/walrus/grammar/continuation_wrapper_exception.rb +0 -34
  46. data/lib/walrus/grammar/left_recursion_exception.rb +0 -33
  47. data/lib/walrus/grammar/location_tracking.rb +0 -115
  48. data/lib/walrus/grammar/match_data_wrapper.rb +0 -71
  49. data/lib/walrus/grammar/memoizing.rb +0 -47
  50. data/lib/walrus/grammar/memoizing_cache.rb +0 -103
  51. data/lib/walrus/grammar/node.rb +0 -66
  52. data/lib/walrus/grammar/not_predicate.rb +0 -46
  53. data/lib/walrus/grammar/parse_error.rb +0 -45
  54. data/lib/walrus/grammar/parser_state.rb +0 -187
  55. data/lib/walrus/grammar/parslet.rb +0 -34
  56. data/lib/walrus/grammar/parslet_choice.rb +0 -128
  57. data/lib/walrus/grammar/parslet_combination.rb +0 -32
  58. data/lib/walrus/grammar/parslet_combining.rb +0 -160
  59. data/lib/walrus/grammar/parslet_merge.rb +0 -94
  60. data/lib/walrus/grammar/parslet_omission.rb +0 -63
  61. data/lib/walrus/grammar/parslet_repetition.rb +0 -106
  62. data/lib/walrus/grammar/parslet_repetition_default.rb +0 -64
  63. data/lib/walrus/grammar/parslet_sequence.rb +0 -214
  64. data/lib/walrus/grammar/predicate.rb +0 -63
  65. data/lib/walrus/grammar/proc_parslet.rb +0 -58
  66. data/lib/walrus/grammar/regexp_parslet.rb +0 -79
  67. data/lib/walrus/grammar/skipped_substring_exception.rb +0 -42
  68. data/lib/walrus/grammar/string_enumerator.rb +0 -53
  69. data/lib/walrus/grammar/string_parslet.rb +0 -81
  70. data/lib/walrus/grammar/string_result.rb +0 -30
  71. data/lib/walrus/grammar/symbol_parslet.rb +0 -69
  72. data/lib/walrus/no_parameter_marker.rb +0 -25
  73. data/lib/walrus/walrus_grammar/assignment_expression.rb +0 -30
  74. data/lib/walrus/walrus_grammar/block_directive.rb +0 -34
  75. data/lib/walrus/walrus_grammar/comment.rb +0 -30
  76. data/lib/walrus/walrus_grammar/def_directive.rb +0 -72
  77. data/lib/walrus/walrus_grammar/echo_directive.rb +0 -50
  78. data/lib/walrus/walrus_grammar/escape_sequence.rb +0 -30
  79. data/lib/walrus/walrus_grammar/import_directive.rb +0 -50
  80. data/lib/walrus/walrus_grammar/include_directive.rb +0 -33
  81. data/lib/walrus/walrus_grammar/instance_variable.rb +0 -30
  82. data/lib/walrus/walrus_grammar/literal.rb +0 -30
  83. data/lib/walrus/walrus_grammar/message_expression.rb +0 -31
  84. data/lib/walrus/walrus_grammar/multiline_comment.rb +0 -60
  85. data/lib/walrus/walrus_grammar/placeholder.rb +0 -46
  86. data/lib/walrus/walrus_grammar/raw_directive.rb +0 -48
  87. data/lib/walrus/walrus_grammar/raw_text.rb +0 -51
  88. data/lib/walrus/walrus_grammar/ruby_directive.rb +0 -35
  89. data/lib/walrus/walrus_grammar/ruby_expression.rb +0 -37
  90. data/lib/walrus/walrus_grammar/set_directive.rb +0 -30
  91. data/lib/walrus/walrus_grammar/silent_directive.rb +0 -50
  92. data/lib/walrus/walrus_grammar/slurp_directive.rb +0 -31
  93. data/lib/walrus/walrus_grammar/super_directive.rb +0 -33
@@ -1,63 +0,0 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # This program is free software: you can redistribute it and/or modify
3
- # it under the terms of the GNU General Public License as published by
4
- # the Free Software Foundation, either version 3 of the License, or
5
- # (at your option) any later version.
6
- #
7
- # This program is distributed in the hope that it will be useful,
8
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- # GNU General Public License for more details.
11
- #
12
- # You should have received a copy of the GNU General Public License
13
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
-
15
- require 'walrus'
16
-
17
- module Walrus
18
- class Grammar
19
-
20
- # Predicates parse input without consuming it.
21
- # On success they throw a subclass-specific symbol (see the AndPredicate and NotPredicate classes).
22
- # On failure they raise a ParseError.
23
- class Predicate
24
-
25
- include Walrus::Grammar::ParsletCombining
26
- include Walrus::Grammar::Memoizing
27
-
28
- attr_reader :hash
29
-
30
- # Raises if parseable is nil.
31
- def initialize(parseable)
32
- raise ArgumentError if parseable.nil?
33
- @parseable = parseable
34
- @hash = @parseable.hash + hash_offset # fixed offset to avoid collisions with @parseable objects
35
- end
36
-
37
- def to_parseable
38
- self
39
- end
40
-
41
- def parse(string, options = {})
42
- raise NotImplementedError # subclass responsibility
43
- end
44
-
45
- def eql?(other)
46
- other.instance_of? self.class and other.parseable.eql? @parseable
47
- end
48
-
49
- protected
50
-
51
- # for equality comparisons
52
- attr_reader :parseable
53
-
54
- private
55
-
56
- def hash_offset
57
- 10
58
- end
59
-
60
- end
61
-
62
- end # class Grammar
63
- end # module Walrus
@@ -1,58 +0,0 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # This program is free software: you can redistribute it and/or modify
3
- # it under the terms of the GNU General Public License as published by
4
- # the Free Software Foundation, either version 3 of the License, or
5
- # (at your option) any later version.
6
- #
7
- # This program is distributed in the hope that it will be useful,
8
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- # GNU General Public License for more details.
11
- #
12
- # You should have received a copy of the GNU General Public License
13
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
-
15
- require 'walrus'
16
-
17
- module Walrus
18
- class Grammar
19
-
20
- class ProcParslet < Parslet
21
-
22
- attr_reader :hash
23
-
24
- def initialize(proc)
25
- raise ArgumentError if proc.nil?
26
- self.expected_proc = proc
27
- end
28
-
29
- def parse(string, options = {})
30
- raise ArgumentError if string.nil?
31
- @expected_proc.call string, options
32
- end
33
-
34
- def eql?(other)
35
- other.instance_of? ProcParslet and other.expected_proc == @expected_proc
36
- end
37
-
38
- protected
39
-
40
- # For equality comparisons.
41
- attr_reader :expected_proc
42
-
43
- private
44
-
45
- def expected_proc=(proc)
46
- @expected_proc = ( proc.clone rescue proc )
47
- update_hash
48
- end
49
-
50
- def update_hash
51
- @hash = @expected_proc.hash + 105 # fixed offset to avoid collisions with @parseable objects
52
- end
53
-
54
- end # class ProcParslet
55
-
56
- end # class Grammar
57
- end # module Walrus
58
-
@@ -1,79 +0,0 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # This program is free software: you can redistribute it and/or modify
3
- # it under the terms of the GNU General Public License as published by
4
- # the Free Software Foundation, either version 3 of the License, or
5
- # (at your option) any later version.
6
- #
7
- # This program is distributed in the hope that it will be useful,
8
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- # GNU General Public License for more details.
11
- #
12
- # You should have received a copy of the GNU General Public License
13
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
-
15
- require 'walrus'
16
-
17
- module Walrus
18
- class Grammar
19
-
20
- class RegexpParslet < Parslet
21
-
22
- attr_reader :hash
23
-
24
- def initialize(regexp)
25
- raise ArgumentError if regexp.nil?
26
- self.expected_regexp = /\A#{regexp}/ # for efficiency, anchor all regexps to the start of the string
27
- end
28
-
29
- def parse(string, options = {})
30
- raise ArgumentError if string.nil?
31
- if (string =~ @expected_regexp)
32
- wrapper = MatchDataWrapper.new($~)
33
- match = $~[0]
34
-
35
- if (line_count = match.scan(/\r\n|\r|\n/).length) != 0 # count number of newlines in match
36
- column_end = match.jlength - match.jrindex(/\r|\n/) - 1 # calculate characters on last line
37
- else # no newlines in match
38
- column_end = match.jlength + (options[:column_start] || 0)
39
- end
40
-
41
- wrapper.start = [options[:line_start], options[:column_start]]
42
- wrapper.end = [wrapper.line_start + line_count, column_end]
43
- wrapper.source_text = match.to_s.clone
44
- wrapper
45
- else
46
- raise ParseError.new('non-matching characters "%s" while parsing regular expression "%s"' % [string, @expected_regexp.inspect],
47
- :line_end => (options[:line_start] || 0), :column_end => (options[:column_start] || 0))
48
- end
49
- end
50
-
51
- def eql?(other)
52
- other.instance_of? RegexpParslet and other.expected_regexp == @expected_regexp
53
- end
54
-
55
- def inspect
56
- '#<%s:0x%x @expected_regexp=%s>' % [self.class.to_s, self.object_id, @expected_regexp.inspect]
57
- end
58
-
59
- protected
60
-
61
- # For equality comparisons.
62
- attr_reader :expected_regexp
63
-
64
- private
65
-
66
- def expected_regexp=(regexp)
67
- @expected_regexp = ( regexp.clone rescue regexp )
68
- update_hash
69
- end
70
-
71
- def update_hash
72
- @hash = @expected_regexp.hash + 15 # fixed offset to avoid collisions with @parseable objects
73
- end
74
-
75
- end # class RegexpParslet
76
-
77
- end # class Grammar
78
- end # module Walrus
79
-
@@ -1,42 +0,0 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # This program is free software: you can redistribute it and/or modify
3
- # it under the terms of the GNU General Public License as published by
4
- # the Free Software Foundation, either version 3 of the License, or
5
- # (at your option) any later version.
6
- #
7
- # This program is distributed in the hope that it will be useful,
8
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- # GNU General Public License for more details.
11
- #
12
- # You should have received a copy of the GNU General Public License
13
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
-
15
- require 'walrus'
16
-
17
- module Walrus
18
- class Grammar
19
-
20
- # I don't really like using Exceptions for non-error situations, but it seems that using throw/catch here would not be adequate (not possible to embed information in the thrown symbol).
21
- class SkippedSubstringException < Exception
22
-
23
- include Walrus::Grammar::LocationTracking
24
-
25
- def initialize(substring, info = {})
26
- super substring
27
-
28
- # TODO: this code is just like the code in ParseError. could save repeating it by setting up inheritance
29
- # but would need to pay careful attention to the ordering of my rescue blocks
30
- # and also change many instances of "kind_of" in my specs to "instance_of "
31
- # alternatively, could look at using a mix-in
32
- self.line_start = info[:line_start]
33
- self.column_start = info[:column_start]
34
- self.line_end = info[:line_end]
35
- self.column_end = info[:column_end]
36
- end
37
-
38
- end # class SkippedSubstringException
39
-
40
- end # class Grammar
41
- end # module Walrus
42
-
@@ -1,53 +0,0 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # This program is free software: you can redistribute it and/or modify
3
- # it under the terms of the GNU General Public License as published by
4
- # the Free Software Foundation, either version 3 of the License, or
5
- # (at your option) any later version.
6
- #
7
- # This program is distributed in the hope that it will be useful,
8
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- # GNU General Public License for more details.
11
- #
12
- # You should have received a copy of the GNU General Public License
13
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
-
15
- require 'strscan'
16
- require 'walrus'
17
-
18
- module Walrus
19
- class Grammar
20
-
21
- # Unicode-aware (UTF-8) string enumerator.
22
- # For Unicode support $KCODE must be set to 'U' (UTF-8).
23
- class StringEnumerator
24
-
25
- # Returns the char most recently scanned before the last "next" call, or nil if nothing previously scanned.
26
- attr_reader :last
27
-
28
- def initialize(string)
29
- raise ArgumentError if string.nil?
30
- @scanner = StringScanner.new(string)
31
- @current = nil
32
- @last = nil
33
- end
34
-
35
- # This method will only work as expected if $KCODE is set to 'U' (UTF-8).
36
- def next
37
- @last = @current
38
- @current = @scanner.scan(/./m) # must use multiline mode or "." won't match newlines
39
- end
40
-
41
- # Take a peek at the next character without actually consuming it. Returns nil if there is no next character.
42
- # TODO: consider deleting this method as it's not currently used.
43
- def peek
44
- if char = self.next
45
- @scanner.unscan
46
- end
47
- char
48
- end
49
-
50
- end # class StringEnumerator
51
-
52
- end # class Grammar
53
- end # module Walrus
@@ -1,81 +0,0 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # This program is free software: you can redistribute it and/or modify
3
- # it under the terms of the GNU General Public License as published by
4
- # the Free Software Foundation, either version 3 of the License, or
5
- # (at your option) any later version.
6
- #
7
- # This program is distributed in the hope that it will be useful,
8
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- # GNU General Public License for more details.
11
- #
12
- # You should have received a copy of the GNU General Public License
13
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
-
15
- require 'walrus'
16
-
17
- module Walrus
18
- class Grammar
19
-
20
- class StringParslet < Parslet
21
-
22
- attr_reader :hash
23
-
24
- def initialize(string)
25
- raise ArgumentError if string.nil?
26
- self.expected_string = string
27
- end
28
-
29
- def parse(string, options = {})
30
- raise ArgumentError if string.nil?
31
- chars = StringEnumerator.new(string)
32
- parsed = StringResult.new
33
- parsed.start = [options[:line_start], options[:column_start]]
34
- parsed.end = parsed.start
35
- expected_string.each_char do |expected_char|
36
- actual_char = chars.next
37
- if actual_char.nil?
38
- raise ParseError.new('unexpected end-of-string (expected "%s") while parsing "%s"' % [ expected_char, expected_string ],
39
- :line_end => parsed.line_end, :column_end => parsed.column_end)
40
- elsif actual_char != expected_char
41
- raise ParseError.new('unexpected character "%s" (expected "%s") while parsing "%s"' % [ actual_char, expected_char, expected_string],
42
- :line_end => parsed.line_end, :column_end => parsed.column_end)
43
- else
44
- if actual_char == "\r" or (actual_char == "\n" and chars.last != "\r") # catches Mac, Windows and UNIX end-of-line markers
45
- parsed.column_end = 0
46
- parsed.line_end = parsed.line_end + 1
47
- elsif actual_char != "\n" # \n is ignored if it is preceded by an \r (already counted above)
48
- parsed.column_end = parsed.column_end + 1 # everything else gets counted
49
- end
50
- parsed << actual_char
51
- end
52
- end
53
- parsed.source_text = parsed.to_s.clone
54
- parsed
55
- end
56
-
57
- def eql?(other)
58
- other.instance_of? StringParslet and other.expected_string == @expected_string
59
- end
60
-
61
- protected
62
-
63
- # For equality comparisons.
64
- attr_reader :expected_string
65
-
66
- private
67
-
68
- def expected_string=(string)
69
- @expected_string = ( string.clone rescue string )
70
- update_hash
71
- end
72
-
73
- def update_hash
74
- @hash = @expected_string.hash + 20 # fixed offset to avoid collisions with @parseable objects
75
- end
76
-
77
- end # class StringParslet
78
-
79
- end # class Grammar
80
- end # module Walrus
81
-
@@ -1,30 +0,0 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # This program is free software: you can redistribute it and/or modify
3
- # it under the terms of the GNU General Public License as published by
4
- # the Free Software Foundation, either version 3 of the License, or
5
- # (at your option) any later version.
6
- #
7
- # This program is distributed in the hope that it will be useful,
8
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- # GNU General Public License for more details.
11
- #
12
- # You should have received a copy of the GNU General Public License
13
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
-
15
- require 'walrus'
16
-
17
- module Walrus
18
- class Grammar
19
- class StringResult < String
20
-
21
- include Walrus::Grammar::LocationTracking
22
-
23
- def initialize(string = "")
24
- self.source_text = string
25
- super
26
- end
27
-
28
- end # class StringResult
29
- end # class Grammar
30
- end # module Walrus
@@ -1,69 +0,0 @@
1
- # Copyright 2007 Wincent Colaiuta
2
- # This program is free software: you can redistribute it and/or modify
3
- # it under the terms of the GNU General Public License as published by
4
- # the Free Software Foundation, either version 3 of the License, or
5
- # (at your option) any later version.
6
- #
7
- # This program is distributed in the hope that it will be useful,
8
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- # GNU General Public License for more details.
11
- #
12
- # You should have received a copy of the GNU General Public License
13
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
-
15
- require 'walrus'
16
-
17
- module Walrus
18
- class Grammar
19
-
20
- # A SymbolParslet allows for evaluation of a parslet to be deferred until runtime (or parse time, to be more precise).
21
- class SymbolParslet < Parslet
22
-
23
- attr_reader :hash
24
-
25
- def initialize(symbol)
26
- raise ArgumentError if symbol.nil?
27
- @symbol = symbol
28
- @hash = @symbol.hash + 20 # fixed offset to avoid collisions with @parseable objects
29
- end
30
-
31
- # SymbolParslets don't actually know what Grammar they are associated with at the time of their definition. They expect the Grammar to be passed in with the options hash under the ":grammar" key.
32
- # Raises if string is nil, or if the options hash does not include a :grammar key.
33
- def parse(string, options = {})
34
- raise ArgumentError if string.nil?
35
- raise ArgumentError unless options.has_key?(:grammar)
36
- grammar = options[:grammar]
37
- augmented_options = options.clone
38
- augmented_options[:rule_name] = @symbol
39
- augmented_options[:skipping_override] = grammar.skipping_overrides[@symbol] if grammar.skipping_overrides.has_key?(@symbol)
40
- result = grammar.rules[@symbol].memoizing_parse(string, augmented_options)
41
- grammar.wrap(result, @symbol)
42
- end
43
-
44
- # We override the to_s method as it can make parsing error messages more readable. Instead of messages like this:
45
- # predicate not satisfied (expected "#<Walrus::Grammar::SymbolParslet:0x10cd504>") while parsing "hello world"
46
- # We can print messages like this:
47
- # predicate not satisfied (expected "rule: end_of_input") while parsing "hello world"
48
- def to_s
49
- 'rule: ' + @symbol.to_s
50
- end
51
-
52
- def ==(other)
53
- eql?(other)
54
- end
55
-
56
- def eql?(other)
57
- other.instance_of? SymbolParslet and other.symbol == @symbol
58
- end
59
-
60
- protected
61
-
62
- # For equality comparisons.
63
- attr_reader :symbol
64
-
65
- end # class SymbolParslet
66
-
67
- end # class Grammar
68
- end # module Walrus
69
-