PageRenderTime 27ms CodeModel.GetById 14ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/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 */
 18package org.fusesource.scalate.support
 19
 20import java.lang.Integer._
 21
 22import org.fusesource.scalate.support.CharData._
 23
 24import scala.language.postfixOps
 25import scala.util.parsing.combinator.RegexParsers
 26import scala.util.parsing.input.CharArrayReader
 27
 28/**
 29 * @version $Revision : 1.1 $
 30 */
 31trait ScalaParseSupport extends RegexParsers {
 32
 33  val scalaTypeChar = """a-zA-Z0-9\$_\[\]\.\(\)\#\:\<\>\+\-"""
 34  val scalaType = ("[" + scalaTypeChar + """]+([ \t\,]+[""" + scalaTypeChar + """]+)*""").r
 35
 36  val EofCh = CharArrayReader.EofCh
 37
 38  lazy val tripleQuote: Parser[Unit] = "\"" + "\"" + "\"" ^^^ (())
 39  lazy val anyChar: Parser[Char] = chrExcept(EofCh)
 40
 41  def chrExcept(cs: Char*): Parser[Char] = elem("chrExcept", ch => (ch != EofCh) && (cs forall (ch !=)))
 42
 43  def chrOf(cs: Char*): Parser[Char] = elem("chrOf", ch => (cs exists (ch ==)))
 44
 45  def chrOf(cs: String): Parser[Char] = chrOf(cs.toIndexedSeq: _*)
 46
 47  def takeUntil(cond: Parser[Any]): Parser[String] = takeUntil(cond, anyChar)
 48
 49  def takeUntil(cond: Parser[Any], p: Parser[Char]): Parser[String] = rep(not(cond) ~> p) ^^ { _.mkString }
 50
 51  def takeWhile(p: Parser[Char]): Parser[String] = rep(p) ^^ { _.mkString }
 52
 53  def surround[T](c: Char, p: Parser[T]): Parser[T] = c ~> p <~ c
 54
 55  def surround[T](delim: Parser[Any], p: Parser[T]): Parser[T] = delim ~> p <~ delim
 56
 57  def squoted[T](p: Parser[T]): Parser[T] = surround('\'', p)
 58
 59  def dquoted[T](p: Parser[T]): Parser[T] = surround('"', p)
 60
 61  def tquoted[T](p: Parser[T]): Parser[T] = surround(tripleQuote, p)
 62
 63  /**Once p1 is matched, disable backtracking. Consumes p1 and yields the result of p2 */
 64  def prefixed[T, U](p1: Parser[T], p2: Parser[U]) = p1.~!(p2) ^^ { case _ ~ x => x }
 65
 66  /**Once p1 is matched, disable backtracking. Does not consume p1 and yields the result of p2 */
 67  def guarded[T, U](p1: Parser[T], p2: Parser[U]) = guard(p1) ~! p2 ^^ { case _ ~ x => x }
 68
 69  def text(p1: Parser[String]): Parser[Text] = {
 70    positioned(p1 ^^ { Text(_) })
 71  }
 72
 73  def wrapped[T, U](prefix: Parser[T], postfix: Parser[U]): Parser[Text] = {
 74    prefixed(prefix, upto(postfix) <~ postfix)
 75  }
 76
 77  def upto[T](p: Parser[T]): Parser[Text] = {
 78    text(
 79      text("""\z""".r) ~ failure("end of file") ^^ { null } |
 80        guard(p) ^^ { _ => "" } |
 81        rep1(not(p) ~> ".|\r|\n".r) ^^ { _.mkString("") })
 82  }
 83
 84  def someUpto[T](p: Parser[T]): Parser[Text] = {
 85    text(
 86      text("""\z""".r) ~ failure("end of file") ^^ { null } |
 87        guard(p) ~ failure("expected any text before " + p) ^^ { null } |
 88        rep1(not(p) ~> ".|\r|\n".r) ^^ { _.mkString("") })
 89  }
 90
 91  lazy val octalDigit: Parser[Char] = accept("octalDigit", isOctalDigit)
 92  lazy val hexDigit: Parser[Char] = accept("hexDigit", isHexDigit)
 93
 94  override def accept[U](expected: String, f: PartialFunction[Elem, U]): Parser[U] =
 95    ('\\' ~> 'u' ~> uniEscapeSeq ^? f) | super.accept(expected, f)
 96
 97  private[this] lazy val printableChar: Parser[Char] = elem("printable", !isControl(_))
 98  private[this] lazy val printableCharNoDoubleQuote: Parser[Char] = elem("nodq", ch => !isControl(ch) && ch != '"')
 99
100  lazy val charEscapeSeq: Parser[Char] = '\\' ~> (
101    (accept("escape", simpleEscape))
102    | (octalEscapeSeq)
103    | ('u' ~> uniEscapeSeq))
104  lazy val uniEscapeSeq: Parser[Char] = (repN(4, hexDigit)) ^^ (x => parseInt(x.mkString, 16).toChar)
105
106  lazy val octalEscapeSeq: Parser[Char] = octalDigit ~ opt(octalDigit) ~ opt(octalDigit) ^^ {
107    case x ~ y ~ z => val digits = x :: List(y, z).flatMap(x => x); parseInt(digits.mkString, 8).toChar // 0377
108  }
109
110  lazy val characterLiteral: Parser[String] = squoted(charEscapeSeq | printableChar) ^^ { case x => "'" + x + "'" }
111
112  lazy val stringLiteral: Parser[String] = (tquoted(multiLineChars) ^^ { case x => "\"\"\"" + x + "\"\"\"" }) |
113    (dquoted(doubleQuotedChars) ^^ { case x => "\"" + x + "\"" })
114
115  lazy val doubleQuotedChars: Parser[String] = takeWhile(charEscapeSeq | printableCharNoDoubleQuote)
116  lazy val multiLineChars: Parser[String] = takeUntil(tripleQuote)
117
118}