Efficient scanning of literals.
authorwenzelm
Tue, 16 Jun 2009 15:25:32 +0200
changeset 3164831b1f296515b
parent 31647 76d8c30a92c5
child 31649 a11ea667d676
Efficient scanning of literals.
src/Pure/General/scan.scala
src/Pure/IsaMakefile
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/Pure/General/scan.scala	Tue Jun 16 15:25:32 2009 +0200
     1.3 @@ -0,0 +1,82 @@
     1.4 +/*  Title:      Pure/General/scan.scala
     1.5 +    Author:     Makarius
     1.6 +
     1.7 +Efficient scanning of literals.
     1.8 +*/
     1.9 +
    1.10 +package isabelle
    1.11 +
    1.12 +import scala.util.parsing.combinator.RegexParsers
    1.13 +
    1.14 +
    1.15 +object Scan
    1.16 +{
    1.17 +
    1.18 +  /* class Lexicon -- position tree */
    1.19 +
    1.20 +  case class Lexicon(val tab: Map[Char, (Boolean, Lexicon)])
    1.21 +
    1.22 +  val empty_lexicon = Lexicon(Map())
    1.23 +
    1.24 +  def is_literal(lx: Lexicon, str: CharSequence): Boolean =
    1.25 +  {
    1.26 +    val len = str.length
    1.27 +    def is_lit(lexicon: Lexicon, i: Int): Boolean =
    1.28 +      i < len && {
    1.29 +        lexicon.tab.get(str.charAt(i)) match {
    1.30 +          case Some((tip, lex)) => tip && i + 1 == len || is_lit(lex, i + 1)
    1.31 +          case None => false
    1.32 +        }
    1.33 +      }
    1.34 +    is_lit(lx, 0)
    1.35 +  }
    1.36 +
    1.37 +  def extend_lexicon(lx: Lexicon, str: CharSequence): Lexicon =
    1.38 +  {
    1.39 +    val len = str.length
    1.40 +    def ext(lexicon: Lexicon, i: Int): Lexicon =
    1.41 +      if (i == len) lexicon
    1.42 +      else {
    1.43 +        val c = str.charAt(i)
    1.44 +        val is_last = (i + 1 == len)
    1.45 +        lexicon.tab.get(c) match {
    1.46 +          case Some((tip, lex)) => Lexicon(lexicon.tab + (c -> (tip || is_last, ext(lex, i + 1))))
    1.47 +          case None => Lexicon(lexicon.tab + (c -> (is_last, ext(empty_lexicon, i + 1))))
    1.48 +        }
    1.49 +      }
    1.50 +    if (is_literal(lx, str)) lx else ext(lx, 0)
    1.51 +  }
    1.52 +
    1.53 +}
    1.54 +
    1.55 +
    1.56 +class Scan extends RegexParsers
    1.57 +{
    1.58 +  override val whiteSpace = "".r
    1.59 +
    1.60 +  def keyword(lx: Scan.Lexicon): Parser[String] = new Parser[String] {
    1.61 +    def apply(in: Input) =
    1.62 +    {
    1.63 +      val source = in.source
    1.64 +      val offset = in.offset
    1.65 +      val len = source.length - offset
    1.66 +
    1.67 +      def scan(lexicon: Scan.Lexicon, i: Int, res: Int): Int =
    1.68 +      {
    1.69 +        if (i < len) {
    1.70 +          lexicon.tab.get(source.charAt(offset + i)) match {
    1.71 +            case Some((tip, lex)) => scan(lex, i + 1, if (tip) i + 1 else res)
    1.72 +            case None => res
    1.73 +          }
    1.74 +        } else res
    1.75 +      }
    1.76 +      scan(lx, 0, 0) match {
    1.77 +        case res if res > 0 =>
    1.78 +          Success(source.subSequence(offset, res).toString, in.drop(res))
    1.79 +        case _ => Failure("keyword expected", in)
    1.80 +      }
    1.81 +    }
    1.82 +  }.named("keyword")
    1.83 +
    1.84 +}
    1.85 +
     2.1 --- a/src/Pure/IsaMakefile	Mon Jun 15 21:33:27 2009 +0200
     2.2 +++ b/src/Pure/IsaMakefile	Tue Jun 16 15:25:32 2009 +0200
     2.3 @@ -115,9 +115,9 @@
     2.4  ## Scala material
     2.5  
     2.6  SCALA_FILES = General/event_bus.scala General/markup.scala		\
     2.7 -  General/position.scala General/swing.scala General/symbol.scala	\
     2.8 -  General/xml.scala General/yxml.scala Isar/isar.scala			\
     2.9 -  Isar/isar_document.scala Isar/outer_keyword.scala			\
    2.10 +  General/position.scala General/scan.scala General/swing.scala		\
    2.11 +  General/symbol.scala General/xml.scala General/yxml.scala		\
    2.12 +  Isar/isar.scala Isar/isar_document.scala Isar/outer_keyword.scala	\
    2.13    System/cygwin.scala System/isabelle_process.scala			\
    2.14    System/isabelle_system.scala Thy/thy_header.scala			\
    2.15    Tools/isabelle_syntax.scala