LARA

package tool
 
trait Reporter {
  // Informs scalac that this will be mixed-in with the class Compiler, so
  // we'll have access to the source file information (scala.io.Source has nice
  // methods for displaying error messages).
  this: Compiler =>
 
  private var foundErrors = false
 
  /** Simple warnings */
  def warn(msg: String): Unit = outputErrorMsg("Warning", msg)
  def warn(msg: String, i: Int): Unit = report(i, "Warning: " + msg)
  def warn(msg: String, pos: Positional): Unit = warn(msg, pos.pos)
 
  /** Non-fatal errors. The compiler should call terminateIfErrors
   * before the errors can have an impact (for instance at the end
   * of the phase). */
  def error(msg: String): Unit = { foundErrors = true; outputErrorMsg("Error", msg) }
  def error(msg: String, i: Int): Unit = { foundErrors = true; report(i, "Error: " + msg) }
  def error(msg: String, pos: Positional): Unit = error(msg, pos.pos)
 
  /** Errors from which the compiler cannot recover or continue. */
  def fatalError(msg: String): Nothing = { outputErrorMsg("Fatal error", msg); terminate }
  def fatalError(msg: String, i: Int): Nothing = {
    report(i, "Fatal error: " + msg)
    terminate
  }
  def fatalError(msg: String, pos: Positional): Nothing = fatalError(msg, pos.pos)
 
  /** Stops the compiler if they were non-fatal errors. */
  def terminateIfErrors = {
    if(foundErrors) {
      Console.err.println("There were errors.")
      terminate
    }
  }
 
  private def outputErrorMsg(prefix: String, msg: String) = {
    Console.err.println(prefix + ": " + msg)
  }
 
  private def terminate: Nothing = {
    exit(-1)
  }
 
  // circumvents what I think is a bug in scala.io.Source
  private def report(pos: Int, msg: String): Unit = {
    val buf = new StringBuilder
    val line = scala.io.Position.line(pos)
    val col = scala.io.Position.column(pos)
    buf.append(line + ":" + col + ": " + msg)
    buf.append("\n")
    buf.append(source.getLine(line))
    buf.append("\n")
    var i = 1
    while(i < col) {
      buf.append(' ')
      i += 1
    }
    buf.append('^')
    Console.err.println(buf.toString)
  }
}