Skip to content

Commit

Permalink
Escape carriage return when round-tripping
Browse files Browse the repository at this point in the history
Previously the carriage return character ("\r") was not round-tripped
properly.

This will cause a warning on the (upcoming) Ruby 2.1.0 as a plain
carriage return that is not at end-of-line is treated as a space.
  • Loading branch information
drbrain committed Sep 18, 2013
1 parent 20bfe5c commit a88bcbc
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 10 deletions.
1 change: 1 addition & 0 deletions lib/kpeg/string_escape.kpeg
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
segment = < /[\w ]+/ > { text } # Don't use \s because that matchs \n segment = < /[\w ]+/ > { text } # Don't use \s because that matchs \n
| "\\" { "\\\\" } | "\\" { "\\\\" }
| "\n" { "\\n" } | "\n" { "\\n" }
| "\r" { "\\r" }
| "\t" { "\\t" } | "\t" { "\\t" }
| "\b" { "\\b" } | "\b" { "\\b" }
| "\"" { "\\\"" } | "\"" { "\\\"" }
Expand Down
38 changes: 28 additions & 10 deletions lib/kpeg/string_escape.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def self.rule_info(name, rendered)
# :stopdoc: # :stopdoc:
def setup_foreign_grammar; end def setup_foreign_grammar; end


# segment = (< /[\w ]+/ > { text } | "\\" { "\\\\" } | "\n" { "\\n" } | "\t" { "\\t" } | "\b" { "\\b" } | "\"" { "\\\"" } | < . > { text }) # segment = (< /[\w ]+/ > { text } | "\\" { "\\\\" } | "\n" { "\\n" } | "\r" { "\\r" } | "\t" { "\\t" } | "\b" { "\\b" } | "\"" { "\\\"" } | < . > { text })
def _segment def _segment


_save = self.pos _save = self.pos
Expand Down Expand Up @@ -429,12 +429,12 @@ def _segment


_save4 = self.pos _save4 = self.pos
while true # sequence while true # sequence
_tmp = match_string("\t") _tmp = match_string("\r")
unless _tmp unless _tmp
self.pos = _save4 self.pos = _save4
break break
end end
@result = begin; "\\t" ; end @result = begin; "\\r" ; end
_tmp = true _tmp = true
unless _tmp unless _tmp
self.pos = _save4 self.pos = _save4
Expand All @@ -447,12 +447,12 @@ def _segment


_save5 = self.pos _save5 = self.pos
while true # sequence while true # sequence
_tmp = match_string("\b") _tmp = match_string("\t")
unless _tmp unless _tmp
self.pos = _save5 self.pos = _save5
break break
end end
@result = begin; "\\b" ; end @result = begin; "\\t" ; end
_tmp = true _tmp = true
unless _tmp unless _tmp
self.pos = _save5 self.pos = _save5
Expand All @@ -465,12 +465,12 @@ def _segment


_save6 = self.pos _save6 = self.pos
while true # sequence while true # sequence
_tmp = match_string("\"") _tmp = match_string("\b")
unless _tmp unless _tmp
self.pos = _save6 self.pos = _save6
break break
end end
@result = begin; "\\\"" ; end @result = begin; "\\b" ; end
_tmp = true _tmp = true
unless _tmp unless _tmp
self.pos = _save6 self.pos = _save6
Expand All @@ -482,20 +482,38 @@ def _segment
self.pos = _save self.pos = _save


_save7 = self.pos _save7 = self.pos
while true # sequence
_tmp = match_string("\"")
unless _tmp
self.pos = _save7
break
end
@result = begin; "\\\"" ; end
_tmp = true
unless _tmp
self.pos = _save7
end
break
end # end sequence

break if _tmp
self.pos = _save

_save8 = self.pos
while true # sequence while true # sequence
_text_start = self.pos _text_start = self.pos
_tmp = get_byte _tmp = get_byte
if _tmp if _tmp
text = get_text(_text_start) text = get_text(_text_start)
end end
unless _tmp unless _tmp
self.pos = _save7 self.pos = _save8
break break
end end
@result = begin; text ; end @result = begin; text ; end
_tmp = true _tmp = true
unless _tmp unless _tmp
self.pos = _save7 self.pos = _save8
end end
break break
end # end sequence end # end sequence
Expand Down Expand Up @@ -603,7 +621,7 @@ def _embed
end end


Rules = {} Rules = {}
Rules[:_segment] = rule_info("segment", "(< /[\\w ]+/ > { text } | \"\\\\\" { \"\\\\\\\\\" } | \"\\n\" { \"\\\\n\" } | \"\\t\" { \"\\\\t\" } | \"\\b\" { \"\\\\b\" } | \"\\\"\" { \"\\\\\\\"\" } | < . > { text })") Rules[:_segment] = rule_info("segment", "(< /[\\w ]+/ > { text } | \"\\\\\" { \"\\\\\\\\\" } | \"\\n\" { \"\\\\n\" } | \"\\r\" { \"\\\\r\" } | \"\\t\" { \"\\\\t\" } | \"\\b\" { \"\\\\b\" } | \"\\\"\" { \"\\\\\\\"\" } | < . > { text })")
Rules[:_root] = rule_info("root", "segment*:s { @text = s.join }") Rules[:_root] = rule_info("root", "segment*:s { @text = s.join }")
Rules[:_embed_seg] = rule_info("embed_seg", "(\"\#\" { \"\\\\\#\" } | segment)") Rules[:_embed_seg] = rule_info("embed_seg", "(\"\#\" { \"\\\\\#\" } | segment)")
Rules[:_embed] = rule_info("embed", "embed_seg*:s { @text = s.join }") Rules[:_embed] = rule_info("embed", "embed_seg*:s { @text = s.join }")
Expand Down
42 changes: 42 additions & 0 deletions test/test_kpeg_string_escape.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'minitest/autorun'
require 'kpeg'
require 'kpeg/string_escape'

class TestKPegStringEscape < Minitest::Test

def test_bell
assert_equal '\b', parse("\b")
end

def test_carriage_return
assert_equal '\r', parse("\r")
end

def test_newline
assert_equal '\n', parse("\n")
end

def test_quote
assert_equal '\\\\\"', parse('\\"')
end

def test_slash
assert_equal '\\\\', parse('\\')
end

def test_tab
assert_equal '\t', parse("\t")
end

def parse(str, embed = false)
se = KPeg::StringEscape.new(str)

rule = (embed ? 'embed' : nil)

se.raise_error unless se.parse(rule)

se.text
end

end

0 comments on commit a88bcbc

Please sign in to comment.