aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Parser.scala
diff options
context:
space:
mode:
authorJack Koenig2022-09-13 11:49:08 -0400
committerGitHub2022-09-13 11:49:08 -0400
commit6cf4a175bfae5ff6eb3cd8fcdd1e5f69cda5d92d (patch)
treee962a6898d71aea97581ae68d7c437f0de69f001 /src/main/scala/firrtl/Parser.scala
parent50a1230de1d68014cd88e4fcca2bdf3a5c94d6d3 (diff)
Make the Parser handle errors more gracefully (#2549)
Ever since introducing the Listener, the firrtl Parser now can hit errors in the code converting from concrete syntax to abstract syntax that may be due to syntax errors. These errors are essentially broken assumptions about the structure of the parsed code because there is an error. These errors are reported before the standard ANTLR syntax errors are aggregated and reported, and thus could result in less than elegant error messages (eg. NullPointerException). Now, the Parser will mask off such errors in the event of standard syntax errors caught by the ANTLR-generated parser. This commit also cleans up some ParserSpec tests slightly to make the ScalaTest style more canonical.
Diffstat (limited to 'src/main/scala/firrtl/Parser.scala')
-rw-r--r--src/main/scala/firrtl/Parser.scala19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/main/scala/firrtl/Parser.scala b/src/main/scala/firrtl/Parser.scala
index b2d97e86..a4c366ec 100644
--- a/src/main/scala/firrtl/Parser.scala
+++ b/src/main/scala/firrtl/Parser.scala
@@ -10,6 +10,8 @@ import firrtl.parser.Listener
import firrtl.Utils.time
import firrtl.antlr.{FIRRTLParser, _}
+import scala.util.control.NonFatal
+
class ParserException(message: String) extends FirrtlUserException(message)
case class ParameterNotSpecifiedException(message: String) extends ParserException(message)
@@ -42,12 +44,25 @@ object Parser extends LazyLogging {
parser.getInterpreter.setPredictionMode(PredictionMode.SLL)
parser.addParseListener(listener)
- // Concrete Syntax Tree
- parser.circuit
+ // Syntax errors may violate assumptions in the Listener and Visitor.
+ // We need to handle these errors gracefully.
+ val throwable =
+ try {
+ parser.circuit
+ None
+ } catch {
+ case e: ParserException => throw e
+ case NonFatal(e) => Some(e)
+ }
val numSyntaxErrors = parser.getNumberOfSyntaxErrors
if (numSyntaxErrors > 0) throw new SyntaxErrorsException(s"$numSyntaxErrors syntax error(s) detected")
+ // Note that this should never happen because any throwables caught should be due to syntax
+ // errors that are reported above. This is just to ensure that we don't accidentally mask any
+ // bugs in the Parser, Listener, or Visitor.
+ if (throwable.nonEmpty) Utils.throwInternalError(exception = throwable)
+
listener.getCircuit
}