/scalate-core/src/main/scala/org/fusesource/scalate/support/ScalaParseSupport.scala

http://github.com/scalate/scalate · Scala · 118 lines · 75 code · 23 blank · 20 comment · 2 complexity · ff825c04b13633537fb6d641997f9751 MD5 · raw file

  1. /**
  2. * Copyright (C) 2009-2011 the original author or authors.
  3. * See the notice.md file distributed with this work for additional
  4. * information regarding copyright ownership.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. package org.fusesource.scalate.support
  19. import java.lang.Integer._
  20. import org.fusesource.scalate.support.CharData._
  21. import scala.language.postfixOps
  22. import scala.util.parsing.combinator.RegexParsers
  23. import scala.util.parsing.input.CharArrayReader
  24. /**
  25. * @version $Revision : 1.1 $
  26. */
  27. trait ScalaParseSupport extends RegexParsers {
  28. val scalaTypeChar = """a-zA-Z0-9\$_\[\]\.\(\)\#\:\<\>\+\-"""
  29. val scalaType = ("[" + scalaTypeChar + """]+([ \t\,]+[""" + scalaTypeChar + """]+)*""").r
  30. val EofCh = CharArrayReader.EofCh
  31. lazy val tripleQuote: Parser[Unit] = "\"" + "\"" + "\"" ^^^ (())
  32. lazy val anyChar: Parser[Char] = chrExcept(EofCh)
  33. def chrExcept(cs: Char*): Parser[Char] = elem("chrExcept", ch => (ch != EofCh) && (cs forall (ch !=)))
  34. def chrOf(cs: Char*): Parser[Char] = elem("chrOf", ch => (cs exists (ch ==)))
  35. def chrOf(cs: String): Parser[Char] = chrOf(cs.toIndexedSeq: _*)
  36. def takeUntil(cond: Parser[Any]): Parser[String] = takeUntil(cond, anyChar)
  37. def takeUntil(cond: Parser[Any], p: Parser[Char]): Parser[String] = rep(not(cond) ~> p) ^^ { _.mkString }
  38. def takeWhile(p: Parser[Char]): Parser[String] = rep(p) ^^ { _.mkString }
  39. def surround[T](c: Char, p: Parser[T]): Parser[T] = c ~> p <~ c
  40. def surround[T](delim: Parser[Any], p: Parser[T]): Parser[T] = delim ~> p <~ delim
  41. def squoted[T](p: Parser[T]): Parser[T] = surround('\'', p)
  42. def dquoted[T](p: Parser[T]): Parser[T] = surround('"', p)
  43. def tquoted[T](p: Parser[T]): Parser[T] = surround(tripleQuote, p)
  44. /**Once p1 is matched, disable backtracking. Consumes p1 and yields the result of p2 */
  45. def prefixed[T, U](p1: Parser[T], p2: Parser[U]) = p1.~!(p2) ^^ { case _ ~ x => x }
  46. /**Once p1 is matched, disable backtracking. Does not consume p1 and yields the result of p2 */
  47. def guarded[T, U](p1: Parser[T], p2: Parser[U]) = guard(p1) ~! p2 ^^ { case _ ~ x => x }
  48. def text(p1: Parser[String]): Parser[Text] = {
  49. positioned(p1 ^^ { Text(_) })
  50. }
  51. def wrapped[T, U](prefix: Parser[T], postfix: Parser[U]): Parser[Text] = {
  52. prefixed(prefix, upto(postfix) <~ postfix)
  53. }
  54. def upto[T](p: Parser[T]): Parser[Text] = {
  55. text(
  56. text("""\z""".r) ~ failure("end of file") ^^ { null } |
  57. guard(p) ^^ { _ => "" } |
  58. rep1(not(p) ~> ".|\r|\n".r) ^^ { _.mkString("") })
  59. }
  60. def someUpto[T](p: Parser[T]): Parser[Text] = {
  61. text(
  62. text("""\z""".r) ~ failure("end of file") ^^ { null } |
  63. guard(p) ~ failure("expected any text before " + p) ^^ { null } |
  64. rep1(not(p) ~> ".|\r|\n".r) ^^ { _.mkString("") })
  65. }
  66. lazy val octalDigit: Parser[Char] = accept("octalDigit", isOctalDigit)
  67. lazy val hexDigit: Parser[Char] = accept("hexDigit", isHexDigit)
  68. override def accept[U](expected: String, f: PartialFunction[Elem, U]): Parser[U] =
  69. ('\\' ~> 'u' ~> uniEscapeSeq ^? f) | super.accept(expected, f)
  70. private[this] lazy val printableChar: Parser[Char] = elem("printable", !isControl(_))
  71. private[this] lazy val printableCharNoDoubleQuote: Parser[Char] = elem("nodq", ch => !isControl(ch) && ch != '"')
  72. lazy val charEscapeSeq: Parser[Char] = '\\' ~> (
  73. (accept("escape", simpleEscape))
  74. | (octalEscapeSeq)
  75. | ('u' ~> uniEscapeSeq))
  76. lazy val uniEscapeSeq: Parser[Char] = (repN(4, hexDigit)) ^^ (x => parseInt(x.mkString, 16).toChar)
  77. lazy val octalEscapeSeq: Parser[Char] = octalDigit ~ opt(octalDigit) ~ opt(octalDigit) ^^ {
  78. case x ~ y ~ z => val digits = x :: List(y, z).flatMap(x => x); parseInt(digits.mkString, 8).toChar // 0377
  79. }
  80. lazy val characterLiteral: Parser[String] = squoted(charEscapeSeq | printableChar) ^^ { case x => "'" + x + "'" }
  81. lazy val stringLiteral: Parser[String] = (tquoted(multiLineChars) ^^ { case x => "\"\"\"" + x + "\"\"\"" }) |
  82. (dquoted(doubleQuotedChars) ^^ { case x => "\"" + x + "\"" })
  83. lazy val doubleQuotedChars: Parser[String] = takeWhile(charEscapeSeq | printableCharNoDoubleQuote)
  84. lazy val multiLineChars: Parser[String] = takeUntil(tripleQuote)
  85. }