privatedef quoted_body(quote: Symbol.Symbol): Parser[String] = {
rep(many1(sym => sym != quote && sym != "\\") | "\\" + quote | "\\\\" |
("""\\\d\d\d""".r ^? { case x if x.substring(1, 4).toInt <= 255 => x })) ^^ (_.mkString)
}
def quoted(quote: Symbol.Symbol): Parser[String] = {
quote ~ quoted_body(quote) ~ quote ^^ { case x ~ y ~ z => x + y + z }
}.named("quoted")
def quoted_content(quote: Symbol.Symbol, source: String): String = {
require(parseAll(quoted(quote), source).successful, "no quoted text") val body = source.substring(1, source.length - 1) if (body.exists(_ == '\\')) { val content =
rep(many1(sym => sym != quote && sym != "\\") | "\\" ~> (quote | "\\" | """\d\d\d""".r ^^ { case x => x.toInt.toChar.toString }))
parseAll(content ^^ (_.mkString), body).get
} else body
}
def quoted_line(quote: Symbol.Symbol, ctxt: Line_Context): Parser[(String, Line_Context)] = {
ctxt match { case Finished =>
quote ~ quoted_body(quote) ~ opt_term(quote) ^^
{ case x ~ y ~ Some(z) => (x + y + z, Finished) case x ~ y ~ None => (x + y, Quoted(quote)) } case Quoted(q) if q == quote =>
quoted_body(quote) ~ opt_term(quote) ^^
{ case x ~ Some(y) => (x + y, Finished) case x ~ None => (x, ctxt) } case _ => failure("")
}
}.named("quoted_line")
def recover_quoted(quote: Symbol.Symbol): Parser[String] =
quote ~ quoted_body(quote) ^^ { case x ~ y => x + y }
def apply(in: Input) = { val start = in.offset val end = in.source.length val matcher = new Symbol.Matcher(in.source)
var i = start var d = depth var finished = false while (!finished && i < end) { val sym = matcher.match_symbol(i) val n = sym.length if (Symbol.is_open(sym)) { i += n; d += 1 } elseif (Symbol.is_close(sym) && d > 0) { i += n; d -= 1; if (d == 0) finished = true } elseif (d > 0) i += n else finished = true
} if (i == start) Failure("bad input", in) else Success((in.source.subSequence(start, i).toString, d), in.drop(i - start))
}
}.named("cartouche_depth")
def cartouche: Parser[String] =
cartouche_depth(0) ^? { case (x, d) if d == 0 => x }
def contains(elem: String): Boolean =
lookup(elem) match { case Some((tip, _)) => tip case _ => false
}
/* build lexicon */
def + (elem: String): Lexicon = if (contains(elem)) this else { val len = elem.length def extend(tree: Lexicon.Tree, i: Int): Lexicon.Tree = if (i < len) { val c = elem.charAt(i) val end = (i + 1 == len)
tree.branches.get(c) match { case Some((s, tr)) =>
Lexicon.Tree(tree.branches +
(c -> (if (end) elem else s, extend(tr, i + 1)))) case None =>
Lexicon.Tree(tree.branches +
(c -> (if (end) elem else"", extend(Lexicon.empty_tree, i + 1))))
}
} else tree new Lexicon(extend(rep, 0))
}
def ++ (other: Lexicon): Lexicon = if (this eq other) this elseif (is_empty) other elsethis ++ other.raw_iterator
def -- (remove: Iterable[String]): Lexicon = if (remove.exists(contains))
Lexicon.empty ++ iterator.filterNot(a => remove.exists(b => a == b)) elsethis
/* scan */
def scan(in: Reader[Char]): String = { val source = in.source val offset = in.offset val len = source.length - offset
@tailrec def scan_tree(tree: Lexicon.Tree, result: String, i: Int): String = { if (i < len) {
tree.branches.get(source.charAt(offset + i)) match { case Some((s, tr)) => scan_tree(tr, if (s.isEmpty) result else s, i + 1) case None => result
}
} else result
}
scan_tree(rep, "", 0)
}
}
/** read stream without decoding: efficient length operation **/
privateclass Restricted_Seq(seq: IndexedSeq[Char], start: Int, end: Int) extends CharSequence { def charAt(i: Int): Char = if (0 <= i && i < length) seq(start + i) elsethrownew IndexOutOfBoundsException
def length: Int = end - start // avoid expensive seq.length
def subSequence(i: Int, j: Int): CharSequence = if (0 <= i && i <= j && j <= length) new Restricted_Seq(seq, start + i, start + j) elsethrownew IndexOutOfBoundsException
overridedef toString: String =
Library.string_builder(hint = length) { buf => for (offset <- start until end) buf.append(seq(offset))
}
}
abstractclass Byte_Reader extends Reader[Char] with AutoCloseable
privatedef make_byte_reader(stream: InputStream, stream_length: Int): Byte_Reader = { val buffered_stream = new BufferedInputStream(stream) val seq = new PagedSeq({ (buf: Array[Char], offset: Int, length: Int) => var i = 0 var c = 0 var eof = false while (!eof && i < length) {
c = buffered_stream.read if (c == -1) eof = true else { buf(offset + i) = c.toChar; i += 1 }
} if (i > 0) i else -1
}) val restricted_seq = new Restricted_Seq(seq, 0, stream_length)
class Paged_Reader(overrideval offset: Int) extends Byte_Reader { overridelazyval source: CharSequence = restricted_seq def first: Char = if (seq.isDefinedAt(offset)) seq(offset) else'\u001a' def rest: Paged_Reader = if (seq.isDefinedAt(offset)) new Paged_Reader(offset + 1) elsethis def pos: InputPosition = new OffsetPosition(source, offset) def atEnd: Boolean = !seq.isDefinedAt(offset) overridedef drop(n: Int): Paged_Reader = new Paged_Reader(offset + n) def close(): Unit = buffered_stream.close()
} new Paged_Reader(0)
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.