markupparsers.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 719 行 · 第 1/2 页

SCALA
719
字号
        else {          tmppos = pos          ch match {            case '<' => // end tag, cdata, comment, pi or child node              nextch              exit = content_LT(ts)            case '{' => // either the character '{' or an embedded scala block              content_BRACE(tmppos, ts)            case '&' => // EntityRef or CharRef               content_AMP(ts)            case SU =>              exit = true            case _ =>  // text content              appendText(tmppos, ts, xText)              // here xEmbeddedBlock might be true          }        }      }      ts    }    /** '<' element ::= xmlTag1 '>'  { xmlExpr | '{' simpleExpr '}' } ETag     *                | xmlTag1 '/' '>'     */    /*[Duplicate]*/ def element: Tree = {      val pos1 = pos      val (qname, attrMap) = xTag      if (ch == '/') { // empty element        xToken('/')        xToken('>')        handle.element(pos1, qname, attrMap, new mutable.ListBuffer[Tree])      }      else { // handle content        xToken('>')        if (qname == "xml:unparsed")          return xUnparsed        debugLastStartElement.push((pos1, qname))        val ts = content        xEndTag(qname)        debugLastStartElement.pop        qname match {          case "xml:group" => handle.group(pos1, ts)          case _ => handle.element(pos1, qname, attrMap, ts)        }      }    }    /** actually, Name ::= (Letter | '_' | ':') (NameChar)*  but starting with ':' cannot happen     *  Name ::= (Letter | '_') (NameChar)*     *     *  see  [5] of XML 1.0 specification     *     *  pre-condition:  ch != ':' // assured by definition of XMLSTART token     *  post-condition: name does neither start, nor end in ':'     */    /*[Duplicate]*/   def xName: String = {      if (ch == SU) {        throw TruncatedXML        reportSyntaxError("name expected, but char '"+ch+"' cannot start a name")        return ""      }      val buf = new StringBuilder      do {        buf append nextch              } while (xml.Parsing.isNameChar(ch))      if (':' == buf.last) {        reportSyntaxError( "name cannot end in ':'" )        buf.setLength(buf.length - 1)      }      val n = buf.toString().intern()      //cbuf.length = 0      n    }    /** scan [S] '=' [S]*/    /*[Duplicate]*/   def xEQ = { xSpaceOpt; xToken('='); xSpaceOpt }    /** skip optional space S? */    /*[Duplicate]*/   def xSpaceOpt = { while (xml.Parsing.isSpace(ch)) { nextch }}    /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */    /*[Duplicate]*/ def xSpace =      if (xml.Parsing.isSpace(ch)) { nextch; xSpaceOpt }      else if (ch == SU)        throw TruncatedXML      else reportSyntaxError("whitespace expected")    /** '<?' ProcInstr ::= Name [S ({Char} - ({Char}'>?' {Char})]'?>'     *     * see [15]     */    /*[Duplicate]*/ def xProcInstr: Tree = {      val sb: StringBuilder = new StringBuilder()      val n = xName      if (xml.Parsing.isSpace(ch)) {        xSpace        while (true) {          if (ch == '?' && { sb.append(ch); nextch; ch == '>' }) {            sb.length = sb.length - 1            nextch            return handle.procInstr(tmppos, n, sb.toString)          } else             sb.append(ch);          nextch        }      }      xToken('?')      xToken('>')       handle.procInstr(tmppos, n, sb.toString)    }    /** parse character data.     *  precondition: xEmbeddedBlock == false (we are not in a scala block)     */    /*[Duplicate]*/ def xText: String = {      if (xEmbeddedBlock) Predef.error("internal error: encountered embedded block"); // assert      //Console.println("xText ch now "+ch)      //if( xCheckEmbeddedBlock ) {      //  return ""      //} else {        var exit = false        val buf = new StringBuilder        while (!exit && (ch!=SU)) {          buf append ch          val expectRBRACE = ch == '}'          // TODO check for "}}"          nextch          if (expectRBRACE) {            if (ch == '}')              nextch            else {              reportSyntaxError("in XML content, please use '}}' to express '}'")              throw ConfusedAboutBracesException            }          }          exit = xCheckEmbeddedBlock ||(ch == '<') || (ch == '&')        }        val str = buf.toString()        //cbuf.length = 0        str      //}    }    //val cbuf = new StringBuilder()    /** append Unicode character to name buffer*/    //private def putChar(c: char) = cbuf.append(c)    /** xLiteral = element { element }     *  @return Scala representation of this xml literal     *  precondition: s.xStartsXML == true     */    def xLiteral: Tree = try {      input = parser.in.flush      handle.isPattern = false            //val pos = s.currentPos      var tree:Tree = null      val ts = new mutable.ArrayBuffer[Tree]()      tmppos = (pos)    // Iuli: added this line, as it seems content_LT uses tmppos when creating trees      assert(nextch == '<')      content_LT(ts)      //Console.println("xLiteral:ts = "+ts.toList)      //lastend = s.in.bp      //lastch  = s.in.ch      //if (settings.debug.value) {      //  Console.println("DEBUG 1: I am getting char '"+ch+"' at lastend "+lastend+" pos = "+pos); // DEBUG       //}      val save = input.offset      xSpaceOpt      // parse more XML ?      if (ch == '<') {        while (ch == '<') {           nextch          ts.append(element)          xSpaceOpt        }        tree = handle.makeXMLseq((pos), ts)        parser.in.resume(Tokens.XMLSTART)      } else {        parser.in.seek(save, Tokens.XMLSTART)        assert(ts.length == 1)        tree = ts(0)      }      tree    } catch {      case c @ TruncatedXML =>        parser.incompleteInputError(c.getMessage)        parser.in.resume(Tokens.XMLSTART)        EmptyTree      case c @ (MissingEndTagException | ConfusedAboutBracesException) =>        parser.syntaxError((debugLastStartElement.top._1):Int,                           c.getMessage + debugLastStartElement.top._2+">")        parser.in.resume(Tokens.XMLSTART)        EmptyTree      case _:ArrayIndexOutOfBoundsException =>         parser.syntaxError((debugLastStartElement.top._1),                      "missing end tag in XML literal for <"                      +debugLastStartElement.top._2+">");        parser.in.resume(Tokens.XMLSTART)        EmptyTree    }    /** @see xmlPattern. resynchronizes after successful parse      *  @return this xml pattern     *  precondition: s.xStartsXML == true     */    def xLiteralPattern: Tree = try {      input = parser.in.flush      val oldMode = handle.isPattern;      handle.isPattern = true      assert(nextch == '<')      var tree = xPattern; xSpaceOpt;      handle.isPattern = oldMode;      parser.in.resume(Tokens.XMLSTART)      tree    } catch {      case c @ TruncatedXML =>        parser.syntaxError(pos - 1, c.getMessage)        //s.nextToken        parser.in.resume(Tokens.XMLSTART)        EmptyTree      case c @ (MissingEndTagException | ConfusedAboutBracesException) =>        parser.syntaxError((debugLastStartElement.top._1),                      c.getMessage + debugLastStartElement.top._2+">")        EmptyTree      case _:ArrayIndexOutOfBoundsException =>        parser.syntaxError((debugLastStartElement.top._1),                      "missing end tag in XML literal for <"                      +debugLastStartElement.top._2+">")        EmptyTree    }    def xEmbeddedExpr: Tree = {      xEmbeddedBlock = false      parser.in.resume(LBRACE)      parser.in.sepRegions = RBRACE :: parser.in.sepRegions      val b = parser.block() //p.expr(true,false);      parser.in.sepRegions = parser.in.sepRegions.tail      if (parser.in.token != RBRACE) {        input = parser.in.flush        reportSyntaxError(" expected end of Scala block")      } else {        input = parser.in.flush        assert(nextch == '}')      }      b    }    /** xScalaPatterns  ::= patterns     */    def xScalaPatterns: List[Tree] = {      xEmbeddedBlock = false      parser.in.resume(LBRACE)      val b = parser.patterns(true)      if (parser.in.token != RBRACE) {        input = parser.in.flush        reportSyntaxError(" expected end of Scala pattern")      } else {        input = parser.in.flush        assert(nextch == '}')      }      b    }    //var ch: Char = _;    //def lookahead = { s.xLookahead }    var scannerState: List[List[Int]] = Nil/*    private def pushScannerState {      scannerState = s.sepRegions :: scannerState      s.sepRegions = Nil    }    private def popScannerState {       s.sepRegions = scannerState.head      scannerState = scannerState.tail    }    *//*    private def init {      ch = s.in.ch      pos = s.in.cpos    }    */    def reportSyntaxError(str: String) = {      parser.syntaxError(pos - 1, "in XML literal: " + str)      nextch    }/*    private def sync {      xEmbeddedBlock = false      s.xSync    }*/    /** '<' xPattern  ::= Name [S] { xmlPattern | '{' pattern3 '}' } ETag     *                  | Name [S] '/' '>'     */    def xPattern: Tree = {      val pos1 = pos      val qname = xName      debugLastStartElement.push((pos1, qname))      xSpaceOpt      if (ch == '/') { // empty tag        nextch        xToken('>')        return handle.makeXMLpat(pos1, qname, new mutable.ArrayBuffer[Tree]())      }      // else: tag with content      xToken('>')      var ts = new mutable.ArrayBuffer[Tree]      var exit = false      while (! exit) {        val pos2 = pos        if (xEmbeddedBlock) {          ts ++= xScalaPatterns        } else          ch match {            case '<' => // tag              nextch              if (ch != '/') { //child                ts.append(xPattern)              } else {                exit = true              }            case '{' => // embedded Scala patterns              while (ch == '{') {                nextch                ts ++= xScalaPatterns              }              // postcond: xEmbeddedBlock = false;              if (xEmbeddedBlock) Predef.error("problem with embedded block"); // assert            case SU =>              throw TruncatedXML            case _ => // teMaxt               appendText(pos2, ts, xText)              // here  xEmbeddedBlock might be true;              //if( xEmbeddedBlock ) throw new ApplicationError("after:"+text); // assert          }      }      xEndTag(qname)      debugLastStartElement.pop      handle.makeXMLpat(pos1, qname, ts)    }  } /* class MarkupParser */}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?