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 + -
显示快捷键?