src/Pure/Thy/thy_structure.scala
changeset 57900 fd03765b06c0
child 57905 c0c5652e796e
equal deleted inserted replaced
57899:5867d1306712 57900:fd03765b06c0
       
     1 /*  Title:      Pure/Thy/thy_structure.scala
       
     2     Author:     Makarius
       
     3 
       
     4 Nested structure of theory source.
       
     5 */
       
     6 
       
     7 package isabelle
       
     8 
       
     9 
       
    10 import scala.collection.mutable
       
    11 import scala.annotation.tailrec
       
    12 
       
    13 
       
    14 object Thy_Structure
       
    15 {
       
    16   sealed abstract class Entry { def length: Int }
       
    17   case class Block(val name: String, val body: List[Entry]) extends Entry
       
    18   {
       
    19     val length: Int = (0 /: body)(_ + _.length)
       
    20   }
       
    21   case class Atom(val command: Command) extends Entry
       
    22   {
       
    23     def length: Int = command.length
       
    24   }
       
    25 
       
    26   def parse(syntax: Outer_Syntax, node_name: Document.Node.Name, text: CharSequence): Entry =
       
    27   {
       
    28     /* stack operations */
       
    29 
       
    30     def buffer(): mutable.ListBuffer[Entry] = new mutable.ListBuffer[Entry]
       
    31     var stack: List[(Int, String, mutable.ListBuffer[Entry])] =
       
    32       List((0, node_name.toString, buffer()))
       
    33 
       
    34     @tailrec def close(level: Int => Boolean)
       
    35     {
       
    36       stack match {
       
    37         case (lev, name, body) :: (_, _, body2) :: rest if level(lev) =>
       
    38           body2 += Block(name, body.toList)
       
    39           stack = stack.tail
       
    40           close(level)
       
    41         case _ =>
       
    42       }
       
    43     }
       
    44 
       
    45     def result(): Entry =
       
    46     {
       
    47       close(_ => true)
       
    48       val (_, name, body) = stack.head
       
    49       Block(name, body.toList)
       
    50     }
       
    51 
       
    52     def add(command: Command)
       
    53     {
       
    54       syntax.heading_level(command) match {
       
    55         case Some(i) =>
       
    56           close(_ > i)
       
    57           stack = (i + 1, command.source, buffer()) :: stack
       
    58         case None =>
       
    59       }
       
    60       stack.head._3 += Atom(command)
       
    61     }
       
    62 
       
    63 
       
    64     /* result structure */
       
    65 
       
    66     val spans = Thy_Syntax.parse_spans(syntax.scan(text))
       
    67     spans.foreach(span => add(Command(Document_ID.none, node_name, Nil, span)))
       
    68     result()
       
    69   }
       
    70 }
       
    71