merged
authorwenzelm
Sat, 04 Jul 2009 12:40:57 +0200
changeset 31940 5fe21cac6bf7
parent 31939 e1ac7ab73bb1 (current diff)
parent 31929 ecfc667cac53 (diff)
child 31941 d3a94ae9936f
child 31965 f6d9798b13f1
merged
--- a/src/Pure/General/symbol.scala	Sat Jul 04 07:58:34 2009 +0200
+++ b/src/Pure/General/symbol.scala	Sat Jul 04 12:40:57 2009 +0200
@@ -7,7 +7,7 @@
 package isabelle
 
 import scala.io.Source
-import scala.collection.jcl
+import scala.collection.{jcl, mutable}
 import scala.util.matching.Regex
 
 
@@ -34,14 +34,59 @@
   def is_open(s: String): Boolean =
   {
     val len = s.length
-    len == 1 && Character.isHighSurrogate(s(0)) ||
+    len == 1 && Character.isLowSurrogate(s(0)) ||
     s == "\\" ||
     s == "\\<" ||
     len > 2 && s(len - 1) != '>'
   }
 
 
-  /** Recoding **/
+  /** Decoding offsets **/
+
+  class Index(text: String)
+  {
+    case class Entry(chr: Int, sym: Int)
+    val index: Array[Entry] =
+    {
+      val length = text.length
+      val matcher = regex.pattern.matcher(text)
+      val buf = new mutable.ArrayBuffer[Entry]
+      var chr = 0
+      var sym = 0
+      while (chr < length) {
+        val c = text(chr)
+        val len =
+          if (c == '\\' || Character.isHighSurrogate(c)) {
+            matcher.region(chr, length).lookingAt
+            matcher.group.length
+          } else 1
+        chr += len
+        sym += 1
+        if (len > 1) buf += Entry(chr, sym)
+      }
+      buf.toArray
+    }
+    def decode(sym: Int): Int =
+    {
+      val end = index.length
+      def bisect(a: Int, b: Int): Int =
+      {
+        if (a < b) {
+          val c = (a + b) / 2
+          if (sym < index(c).sym) bisect(a, c)
+          else if (c + 1 == end || sym < index(c + 1).sym) c
+          else bisect(c + 1, b)
+        }
+        else -1
+      }
+      val i = bisect(0, end)
+      if (i < 0) sym
+      else index(i).chr + sym - index(i).sym
+    }
+  }
+
+
+  /** Recoding text **/
 
   private class Recoder(list: List[(String, String)])
   {
@@ -71,8 +116,7 @@
       while (i < len) {
         val c = text(i)
         if (min <= c && c <= max) {
-          matcher.region(i, len)
-          matcher.lookingAt
+          matcher.region(i, len).lookingAt
           val x = matcher.group
           result.append(table.get(x) getOrElse x)
           i = matcher.end