Skip to content

Commit

Permalink
Merge pull request #364 from Mats-SX/no-antlr-in-tck
Browse files Browse the repository at this point in the history
Support escaping in string literals
  • Loading branch information
Mats-SX authored Apr 11, 2019
2 parents 0f580ef + 8f23266 commit d38d6ff
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import fastparse.Parsed.{Failure, Success}
import fastparse._
import org.opencypher.tools.tck.values.Connection.{backward, forward}

case class CypherValueParseException(msg: String) extends Exception(msg)
case class CypherValueParseException(msg: String, expected: String) extends Exception(msg)

class CypherValueParser(val orderedLists: Boolean) {
def parse(s: String): CypherValue = {
Expand All @@ -50,7 +50,7 @@ class CypherValueParser(val orderedLists: Boolean) {
|$locationPointer
|
|${extra.trace().msg}""".stripMargin
throw CypherValueParseException(msg)
throw CypherValueParseException(msg, expected)
}
}

Expand Down Expand Up @@ -102,7 +102,10 @@ class CypherValueParser(val orderedLists: Boolean) {
}

private def string[_: P]: P[CypherString] =
P("'" ~ CharsWhile(_ != ''', 0).!.map(CypherString) ~ "'")
P("'" ~/ (stringChunk | backslash | escape).rep.!.map { s =>
val escaped = s.replaceAllLiterally("\\'", "'").replaceAllLiterally("\\\\", "\\")
CypherString(escaped)
} ~ "'")

private def float[_: P]: P[CypherFloat] =
P("-".? ~ floatRepr).!.map { s =>
Expand Down Expand Up @@ -136,6 +139,25 @@ class CypherValueParser(val orderedLists: Boolean) {

private def symbolicName[_: P]: P[String] = CharsWhileIn("a-zA-Z0-9$_").!

/**
* A 'simple' string chunk; without apostrophes or backslash (escape sequence)
*/
private def stringChunk[_: P]: P[Unit] = {
CharsWhile(c => c != ''' && c != '\\')
}
/**
* We escape apostrophes inside strings using a backslash
*/
private def escape[_: P]: P[Unit] = {
P("\\") ~/ P("'")
}
/**
* Since backslash is used
*/
private def backslash[_: P]: P[Unit] = {
P("\\\\")
}

private def digits[_: P]: P[Unit] = CharsWhileIn("0-9")
private def floatRepr[_: P]: P[Unit] =
(digits ~~ "." ~~ digits ~~ exponent.?) |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ class CypherValueParserTest extends FunSuite with Matchers {
CypherValue("null") should equal(CypherNull)
}

test("string escaping") {
CypherValue("'The Devil\\'s Advocate'") should equal(CypherString("The Devil's Advocate"))
CypherValue("'\\\\'") should equal(CypherString("\\"))
CypherValue("'\\''") should equal(CypherString("'"))
CypherValue("'\\'\\''") should equal(CypherString("''"))
}

test("incorrect escaping") {
(the[CypherValueParseException] thrownBy CypherValue("'\\'")).expected should equal("\"'\"")
(the[CypherValueParseException] thrownBy CypherValue("'''")).expected should equal("end-of-input")
}

test("floats in exponent form") {
CypherValue(".4e10") should equal(CypherFloat(.4e10))
CypherValue(".4e-10") should equal(CypherFloat(.4e-10))
Expand Down

0 comments on commit d38d6ff

Please sign in to comment.