aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Translator.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/firrtl/Translator.scala')
-rw-r--r--src/main/scala/firrtl/Translator.scala115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/Translator.scala b/src/main/scala/firrtl/Translator.scala
new file mode 100644
index 00000000..eba78b39
--- /dev/null
+++ b/src/main/scala/firrtl/Translator.scala
@@ -0,0 +1,115 @@
+
+/* TODO
+ * - Add support for comments (that being said, current Scopers regex should ignore commented lines)
+ * - Add better error messages for illformed FIRRTL
+ * - Add support for files that do not have a circuit (like a module by itself in a file)
+ * - Improve performance? Replace regex?
+ * - Add proper commnad-line arguments?
+ * - Wrap in Reader subclass. This would have less memory footprint than creating a large string
+ */
+
+package firrtl
+
+import scala.io.Source
+import scala.collection.mutable.Stack
+import scala.collection.mutable.StringBuilder
+import java.io._
+
+
+object Translator
+{
+
+ def addBrackets(inputIt: Iterator[String]): StringBuilder = {
+ def countSpaces(s: String): Int = s.prefixLength(_ == ' ')
+
+ val Scopers = """\s*(circuit|module|when|else)(.*)""".r
+
+ // Function start
+ val it = inputIt.zipWithIndex
+ var ret = new StringBuilder()
+
+ if( !it.hasNext ) throw new Exception("Empty file!")
+
+ // Find circuit before starting scope checks
+ var line = it.next
+ while ( it.hasNext && !line._1.contains("circuit") ) {
+ ret ++= line._1 + "\n"
+ line = it.next
+ }
+ ret ++= line._1 + " { \n"
+ if( !it.hasNext ) throw new Exception("No circuit in file!")
+
+
+ val scope = Stack[Int]()
+ scope.push(countSpaces(line._1))
+ var newScope = true // indicates if increasing scope spacing is legal on next line
+
+ while( it.hasNext ) {
+ it.next match { case (text, lineNum) =>
+ val spaces = countSpaces(text)
+
+ val l = if (text.length > spaces ) { // Check that line has text in it
+ if (newScope) {
+ scope.push(countSpaces(text))
+ } else {
+
+ // Check if change in current scope
+ if( spaces < scope.top ) {
+ while( spaces < scope.top ) {
+ // Close scopes (adding brackets as we go)
+ scope.pop()
+ ret.deleteCharAt(ret.lastIndexOf("\n")) // Put on previous line
+ ret ++= " }\n"
+ }
+ if( spaces != scope.top )
+ throw new Exception("Spacing does not match scope on line : " + lineNum + " : " + scope.top)
+ }
+ else if( spaces > scope.top )
+ throw new Exception("Invalid increase in scope on line " + lineNum)
+ }
+ // Now match on legal scope increasers
+ text match {
+ case Scopers(keyword, _* ) => {
+ newScope = true
+ text + " { "
+ }
+ case _ => {
+ newScope = false
+ text
+ }
+ }
+ } // if( text.length > spaces )
+ else {
+ text // empty lines
+ }
+
+ ret ++= l + "\n"
+ } // it.next match
+ } // while( it.hasNext )
+
+ // Print any closing braces
+ while( scope.top > 0 ) {
+ scope.pop()
+ ret.deleteCharAt(ret.lastIndexOf("\n")) // Put on previous line
+ ret ++= " }\n"
+ }
+
+ ret
+ }
+
+ def main(args: Array[String]) {
+
+ try {
+ val translation = addBrackets(Source.fromFile(args(0)).getLines)
+
+ val writer = new PrintWriter(new File(args(1)))
+ writer.write(translation.result)
+ writer.close()
+ } catch {
+ case e: Exception => {
+ throw new Exception("USAGE: Translator <input file> <output file>\n" + e)
+ }
+ }
+ }
+
+}