aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala
diff options
context:
space:
mode:
authorJared Barocsi2021-06-18 09:05:17 -0700
committerGitHub2021-06-18 16:05:17 +0000
commiteb0841d27f5cd077c5f27f339ef9eb86cbe64599 (patch)
tree3c090f231ee26d0e929e095f6134ce22c25c5b72 /src/main/scala
parentecd6d7a6af9785d00ef1020b19cb5707ae1d6398 (diff)
Fix MultiInfo parser + serialization bug (#2265)
* Restore parsed MultiInfo structure in firrtl parser * Change erroneous expected output in InfoSpec test FileInfo compression sorts the outputted entries alphabetically, but this test did not reflect that fact * Fix typo in comment * Add unit tests for file locator parsing * Fix syntax issues and typos * More redundant braces removed Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Diffstat (limited to 'src/main/scala')
-rw-r--r--src/main/scala/firrtl/Visitor.scala49
1 files changed, 47 insertions, 2 deletions
diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala
index f1b3a5c2..ad2f5121 100644
--- a/src/main/scala/firrtl/Visitor.scala
+++ b/src/main/scala/firrtl/Visitor.scala
@@ -58,6 +58,51 @@ class Visitor(infoMode: InfoMode) extends AbstractParseTreeVisitor[FirrtlNode] w
private def string2Int(s: String): Int = string2BigInt(s).toInt
private def visitInfo(ctx: Option[InfoContext], parentCtx: ParserRuleContext): Info = {
+ // Convert a compressed FileInfo string into either into a singular FileInfo or a MultiInfo
+ // consisting of several FileInfos
+ def parseCompressedInfo(escaped: String): Info = {
+ var out: Seq[FileInfo] = Seq()
+
+ // Regular expression to match and capture the general File.format line:col pattern.
+ // Also matches the remaining part of the string which doesn't match the expression;
+ // which will be passed directly into the output as a FileInfo.
+ val splitCompressedInfo = """([^\s:]+)((?: \d+:(?:\d+|\{\d+(?:,\d+)+\}))+)|(?:[^\s].*)""".r
+
+ // Regular expression to capture the line number and column numbers in the compressed file info pattern.
+ val splitLineDescriptors = """(\d+):((?:\d+|\{\d+(?:,\d+)+\}))""".r
+
+ // Regular expression to match against individual column numbers in each line:col or line:{col1,col2}
+ // descriptor.
+ val splitColDescriptors = """\d+""".r
+
+ val matches = splitCompressedInfo.findAllIn(escaped)
+
+ // Grab each File.format line:col token from the input string
+ splitCompressedInfo.findAllIn(escaped).matchData.foreach { info =>
+ Option(info.group(1)) match {
+ // If there were no subgroups, the regex matched against a non-conforming source locator
+ // pattern, so do not process it
+ case None => out = out :+ ir.FileInfo.fromEscaped(info.toString)
+ case Some(file) =>
+ val lineDescriptors = info.group(2)
+ // Grab each line:col values from the separated (compressed) FileInfo.
+ splitLineDescriptors.findAllIn(lineDescriptors).matchData.foreach { lineDescriptor =>
+ val line = lineDescriptor.group(1)
+ val cols = lineDescriptor.group(2)
+ splitColDescriptors.findAllIn(cols).matchData.foreach {
+ // Use all the necessary info to generate normal uncompressed FileInfos
+ col => out = out :+ ir.FileInfo.fromEscaped(s"$file $line:$col")
+ }
+ }
+ }
+ }
+
+ out.size match {
+ case 0 => NoInfo
+ case 1 => out.head
+ case _ => new MultiInfo(out)
+ }
+ }
def genInfo(filename: String): String =
stripPath(filename) + " " + parentCtx.getStart.getLine + ":" +
parentCtx.getStart.getCharPositionInLine
@@ -68,11 +113,11 @@ class Visitor(infoMode: InfoMode) extends AbstractParseTreeVisitor[FirrtlNode] w
infoMode match {
case UseInfo =>
if (useInfo.length == 0) NoInfo
- else ir.FileInfo.fromEscaped(useInfo)
+ else parseCompressedInfo(useInfo)
case AppendInfo(filename) if (useInfo.length == 0) =>
ir.FileInfo.fromEscaped(genInfo(filename))
case AppendInfo(filename) =>
- val useFileInfo = ir.FileInfo.fromEscaped(useInfo)
+ val useFileInfo = parseCompressedInfo(useInfo)
val newFileInfo = ir.FileInfo.fromEscaped(genInfo(filename))
ir.MultiInfo(useFileInfo, newFileInfo)
case GenInfo(filename) =>