diff options
| author | Jack | 2022-07-30 22:41:15 +0000 |
|---|---|---|
| committer | Jack | 2022-07-30 22:41:15 +0000 |
| commit | 4cd44fa4dab370fcc5c20bcacc1fa0ee02327252 (patch) | |
| tree | 05730be260feca0d2a870c4bb88325d36631a8fc /core/src/main/scala/chisel3/Printable.scala | |
| parent | fe9635ef21bad233945617a24ab16cfa4055f2d1 (diff) | |
| parent | bced77045c8fc5db37e40b159c49220929e15d46 (diff) | |
Merge branch '3.5.x' into 3.5-release
Diffstat (limited to 'core/src/main/scala/chisel3/Printable.scala')
| -rw-r--r-- | core/src/main/scala/chisel3/Printable.scala | 77 |
1 files changed, 48 insertions, 29 deletions
diff --git a/core/src/main/scala/chisel3/Printable.scala b/core/src/main/scala/chisel3/Printable.scala index a616f2b0..78655517 100644 --- a/core/src/main/scala/chisel3/Printable.scala +++ b/core/src/main/scala/chisel3/Printable.scala @@ -63,57 +63,76 @@ object Printable { */ def pack(fmt: String, data: Data*): Printable = { val args = data.toIterator - // Error handling def carrotAt(index: Int) = (" " * index) + "^" def errorMsg(index: Int) = s"""| fmt = "$fmt" | ${carrotAt(index)} | data = ${data.mkString(", ")}""".stripMargin - def getArg(i: Int): Data = { + + def checkArg(i: Int): Unit = { if (!args.hasNext) { val msg = "has no matching argument!\n" + errorMsg(i) // Exception wraps msg in s"Format Specifier '$msg'" throw new MissingFormatArgumentException(msg) } - args.next() + val _ = args.next() } + var iter = 0 + var curr_start = 0 + val buf = mutable.ListBuffer.empty[String] + while (iter < fmt.size) { + // Encountered % which is either + // 1. Describing a format specifier. + // 2. Literal Percent + // 3. Dangling percent - most likely due to a typo - intended literal percent or forgot the specifier. + // Try to give meaningful error reports + if (fmt(iter) == '%') { + if (iter != fmt.size - 1 && (fmt(iter + 1) != '%' && !fmt(iter + 1).isWhitespace)) { + checkArg(iter) + buf += fmt.substring(curr_start, iter) + curr_start = iter + iter += 1 + } - val pables = mutable.ListBuffer.empty[Printable] - var str = "" - var percent = false - for ((c, i) <- fmt.zipWithIndex) { - if (percent) { - val arg = c match { - case FirrtlFormat(x) => FirrtlFormat(x.toString, getArg(i)) - case 'n' => Name(getArg(i)) - case 'N' => FullName(getArg(i)) - case '%' => Percent - case x => - val msg = s"Illegal format specifier '$x'!\n" + errorMsg(i) - throw new UnknownFormatConversionException(msg) + // Last character is %. + else if (iter == fmt.size - 1) { + val msg = s"Trailing %\n" + errorMsg(fmt.size - 1) + throw new UnknownFormatConversionException(msg) + } + + // A lone % + else if (fmt(iter + 1).isWhitespace) { + val msg = s"Unescaped % - add % if literal or add proper specifier if not\n" + errorMsg(iter + 1) + throw new UnknownFormatConversionException(msg) + } + + // A literal percent - hence increment by 2. + else { + iter += 2 } - pables += PString(str.dropRight(1)) // remove format % - pables += arg - str = "" - percent = false - } else { - str += c - percent = c == '%' } - } - if (percent) { - val msg = s"Trailing %\n" + errorMsg(fmt.size - 1) - throw new UnknownFormatConversionException(msg) + + // Normal progression + else { + iter += 1 + } } require( !args.hasNext, s"Too many arguments! More format specifier(s) expected!\n" + errorMsg(fmt.size) ) + buf += fmt.substring(curr_start, iter) + + // The string received as an input to pack is already + // treated i.e. escape sequences are processed. + // Since StringContext API assumes the parts are un-treated + // treatEscapes is called within the implemented custom interpolators. + // The literal \ needs to be escaped before sending to the custom cf interpolator. - pables += PString(str) - Printables(pables) + val bufEscapeBackSlash = buf.map(_.replace("\\", "\\\\")) + StringContext(bufEscapeBackSlash.toSeq: _*).cf(data: _*) } } |
