📄 scanners.scala
字号:
putChar(in.ch) in.next } else { setName token = ScannerConfiguration.name2token(name) return } } } } private def getOperatorRest { while (true) { in.ch match { case '~' | '!' | '@' | '#' | '%' | '^' | '*' | '+' | '-' | '<' | '>' | '?' | ':' | '=' | '&' | '|' | '\\' => putChar(in.ch) in.next case '/' => in.next if (skipComment) { setName token = ScannerConfiguration.name2token(name) return } else putChar('/') case _ => if (isSpecial(in.ch)) { putChar(in.ch) in.next } else { setName token = ScannerConfiguration.name2token(name) return } } } } private def getIdentOrOperatorRest { if (isIdentPart(in.ch)) getIdentRest else in.ch match { case '~' | '!' | '@' | '#' | '%' | '^' | '*' | '+' | '-' | '<' | '>' | '?' | ':' | '=' | '&' | '|' | '\\' | '/' => getOperatorRest case _ => if (isSpecial(in.ch)) getOperatorRest else { setName token = ScannerConfiguration.name2token(name) } } } private def getStringLit(delimiter: Char, litType: Int) { //assert((litType==STRINGLIT) || (litType==IDENTIFIER)) while (in.ch != delimiter && (in.isUnicode || in.ch != CR && in.ch != LF && in.ch != SU)) { getlitch() } if (in.ch == delimiter) { token = litType setName in.next } else { val typeDesc = if(litType == STRINGLIT) "string literal" else "quoted identifier" syntaxError("unclosed " + typeDesc) } } private def getMultiLineStringLit { if (in.ch == '\"') { in.next if (in.ch == '\"') { in.next if (in.ch == '\"') { in.next token = STRINGLIT setName } else { putChar('\"') putChar('\"') getMultiLineStringLit } } else { putChar('\"') getMultiLineStringLit } } else if (in.ch == SU) { incompleteInputError("unclosed multi-line string literal") } else { putChar(in.ch) in.next getMultiLineStringLit } }// Literals ----------------------------------------------------------------- /** read next character in character or string literal: */ protected def getlitch() = if (in.ch == '\\') { in.next if ('0' <= in.ch && in.ch <= '7') { val leadch: Char = in.ch var oct: Int = in.digit2int(in.ch, 8) in.next if ('0' <= in.ch && in.ch <= '7') { oct = oct * 8 + in.digit2int(in.ch, 8) in.next if (leadch <= '3' && '0' <= in.ch && in.ch <= '7') { oct = oct * 8 + in.digit2int(in.ch, 8) in.next } } putChar(oct.asInstanceOf[Char]) } else { in.ch match { case 'b' => putChar('\b') case 't' => putChar('\t') case 'n' => putChar('\n') case 'f' => putChar('\f') case 'r' => putChar('\r') case '\"' => putChar('\"') case '\'' => putChar('\'') case '\\' => putChar('\\') case _ => syntaxError(in.cpos - 1, "invalid escape character") putChar(in.ch) } in.next } } else { putChar(in.ch) in.next } /** read fractional part and exponent of floating point number * if one is present. */ protected def getFraction { token = DOUBLELIT while ('0' <= in.ch && in.ch <= '9') { putChar(in.ch) in.next } if (in.ch == 'e' || in.ch == 'E') { val lookahead = in.copy lookahead.next if (lookahead.ch == '+' || lookahead.ch == '-') { lookahead.next } if ('0' <= lookahead.ch && lookahead.ch <= '9') { putChar(in.ch) in.next if (in.ch == '+' || in.ch == '-') { putChar(in.ch) in.next } while ('0' <= in.ch && in.ch <= '9') { putChar(in.ch) in.next } } token = DOUBLELIT } if (in.ch == 'd' || in.ch == 'D') { putChar(in.ch) in.next token = DOUBLELIT } else if (in.ch == 'f' || in.ch == 'F') { putChar(in.ch) in.next token = FLOATLIT } setName } /** convert name to long value */ def intVal(negated: Boolean): Long = { if (token == CHARLIT && !negated) { if (name.length > 0) name(0) else 0 } else { var value: Long = 0 val divider = if (base == 10) 1 else 2 val limit: Long = if (token == LONGLIT) Math.MAX_LONG else Math.MAX_INT var i = 0 val len = name.length while (i < len) { val d = in.digit2int(name(i), base) if (d < 0) { syntaxError("malformed integer number") return 0 } if (value < 0 || limit / (base / divider) < value || limit - (d / divider) < value * (base / divider) && !(negated && limit == value * base - 1 + d)) { syntaxError("integer number too large") return 0 } value = value * base + d i += 1 } if (negated) -value else value } } /** convert name, base to double value */ def floatVal(negated: Boolean): Double = { val limit: Double = if (token == DOUBLELIT) Math.MAX_DOUBLE else Math.MAX_FLOAT try { val value: Double = java.lang.Double.valueOf(name.toString()).doubleValue() if (value > limit) syntaxError("floating point number too large") if (negated) -value else value } catch { case _: NumberFormatException => syntaxError("malformed floating point number") 0.0 } } /** read a number into name and set base */ protected def getNumber { while (in.digit2int(in.ch, if (base < 10) 10 else base) >= 0) { putChar(in.ch) in.next } token = INTLIT if (base <= 10 && in.ch == '.') { val lookahead = in.copy lookahead.next lookahead.ch match { case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'd' | 'D' | 'e' | 'E' | 'f' | 'F' => putChar(in.ch) in.next return getFraction case _ => if (!isIdentStart(lookahead.ch)) { putChar(in.ch) in.next return getFraction } } } if (base <= 10 && (in.ch == 'e' || in.ch == 'E' || in.ch == 'f' || in.ch == 'F' || in.ch == 'd' || in.ch == 'D')) { return getFraction } setName if (in.ch == 'l' || in.ch == 'L') { in.next token = LONGLIT } }// XML lexing---------------------------------------------------------------- def xSync = { token = NEWLINE // avoid getting NEWLINE from nextToken if last was RBRACE //in.next nextToken }// Errors ----------------------------------------------------------------- /** generate an error at the given position */ def syntaxError(pos: Int, msg: String) { error(pos, msg) token = ERROR errpos = pos } /** generate an error at the current token position */ def syntaxError(msg: String) { syntaxError(pos, msg) } /** signal an error where the input ended in the middle of a token */ def incompleteInputError(msg: String) { incompleteInputError(pos, msg) token = EOF errpos = pos } override def toString() = token match { case IDENTIFIER | BACKQUOTED_IDENT => "id(" + name + ")" case CHARLIT => "char(" + intVal + ")" case INTLIT => "int(" + intVal + ")" case LONGLIT => "long(" + intVal + ")" case FLOATLIT => "float(" + floatVal + ")" case DOUBLELIT => "double(" + floatVal + ")" case STRINGLIT => "string(" + name + ")" case SEMI => ";" case NEWLINE => ";" case NEWLINES => ";;" case COMMA => "," case _ => ScannerConfiguration.token2string(token) } /** INIT: read lookahead character and token. */ def init { in.next nextToken } } /** ... */ class UnitScanner(unit: CompilationUnit) extends Scanner { val in = new CharArrayReader(unit.source.asInstanceOf[BatchSourceFile].content, !settings.nouescape.value, syntaxError) def warning(pos: Int, msg: String) = unit.warning(pos, msg) def error (pos: Int, msg: String) = unit. error(pos, msg) def incompleteInputError(pos: Int, msg: String) = unit.incompleteInputError(pos, msg) def deprecationWarning(pos: Int, msg: String) = unit.deprecationWarning(pos, msg) implicit def p2g(pos: Position): Int = pos.offset.getOrElse(-1) implicit def g2p(pos: Int): Position = new OffsetPosition(unit.source, pos) }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -