Question
Can anyone convert this Scala code to Python? import scala.collection.mutable.ListBuffer import scala.collection.mutable.Map import scala.io.Source import java.io._ /* The singleton object StateMachineParser provides a method to
Can anyone convert this Scala code to Python?
import scala.collection.mutable.ListBuffer import scala.collection.mutable.Map import scala.io.Source import java.io._
/* The singleton object StateMachineParser provides a method to load the DSL input file and parse it to configure a state machine. */
object StateMachineParser {
def loadFile(fileName: String): StateMachine = { var dsl: Source = null try { dsl = Source.fromFile(fileName) } catch { case e: FileNotFoundException => throw new RuntimeException(e.getMessage) } val loader = new StateMachineParser(dsl) loader.trace("Loaded file '" + fileName + "'.") loader.run val stateMachine = loader.getMachine loader.trace( "Completed definition of state machine with start state '" + stateMachine.getStart.name + "'.") stateMachine } }
/* Class StateMachineParser implements a driver for the Delimiter- Directed Translation parser where the delimiter is the end of the line. Each line is read and then parsed by an appropriate line parser. The line parsers are implemented using the State design pattern. */
class StateMachineParser(input: Source) extends IncrementalStateMachineBuilder {
// Line parser "state" variable private var lineParser: LineParser = null
/* Method "run" repeatedly reads line from DSL file and parses it with the line parser for the current "state" of parser. */ def run { setLineParser(new TopLevelLineParser(this)) try { for (line <- input.getLines) lineParser.parse(line) } catch { case e: IOException => throw new RuntimeException(e) } finishMachine }
// Set the "state" object used by parser for continuing processing. def setLineParser(linePar: LineParser) { lineParser = linePar } }
/* The LineParser hierarchy implements the line parsers plugged into the StateMachineParser object according to the State design pattern. This hierarchy is implemented according to the Template Method design pattern. The abstract method doParse is the hook method where the different parsing actions are implemented for each block of DSL code. Each subclass will implement a parser for a specific block of DSL code.
This Scala version caches the parsed words, which differs from the approach that Fowler took in the Java version. */
abstract class LineParser(context: StateMachineParser) {
// Current line protected var line: String = null
// Current line after spliting into words protected var words: Array[String] = null
// Template method. final def parse(s: String) { line = removeComment(s).trim() if (!isBlankLine) { words = lexWords try { doParse } catch { case e: RecognitionException => println(e.getMessage + " ..Unrecognized line skipped.") } } }
// Hook method for parsing action def doParse: Unit
// Break the line up into items surrounded by white spaces protected def lexWords: Array[String] = line.split("\\s+")
// Does the line contain only one word? protected def hasOnlyWord(word: String): Boolean = { if (words(0) == word) { if (words.length != 1) failToRecognizeLine true } else false }
// Does the line begin with the given argument keyword? protected def hasKeyword(keyword: String): Boolean = (keyword == words(0))
// Error condition when line unrecognizable protected def failToRecognizeLine { throw new RecognitionException(line) }
// Change parser state to look for autonomous statements protected def returnToTopLevel { context.setLineParser(new TopLevelLineParser(context)) }
// Is the line only white space? private def isBlankLine: Boolean = line.matches("^\\s*$")
// Remove comments from line private def removeComment(line: String): String = line.replaceFirst("#.*", "") }
/* Class TopLevelLineParser implements a top-level line parser that switches the parser state to other line parsers based on the keyword at the beginning of the line. */
class TopLevelLineParser(context: StateMachineParser) extends LineParser(context) {
// Implementation of the hook method def doParse { if (hasOnlyWord("events")) { context.trace("Parsing 'events' block.") context.setLineParser(new EventLineParser(context)) } else if (hasOnlyWord("resetEvents")) { context.trace("Parsing 'resetEvents' block.") context.setLineParser(new ResetEventLineParser(context)) } else if (hasOnlyWord("commands")) { context.trace("Parsing 'commands' block.") context.setLineParser(new CommandLineParser(context)) } else if (hasKeyword("state")) processState else failToRecognizeLine }
// Process the state block, which has the state name on the line. private def processState { context.trace("Parsing 'state' named '" + words(1) + "'.") val curState = context.obtainState(words(1)) // bypass addState context.primeMachine(curState) // in 'context' context.setLineParser(new StateLineParser(context,curState)) } }
/* Class EventLineParser implements a line parser for "event" blocks in the DSL code. */
class EventLineParser(context: StateMachineParser) extends LineParser(context) {
// Implementation of the hook method def doParse { if (hasOnlyWord("end")) returnToTopLevel else if (words.length == 2) { context.trace("..Define event '" + words(0) + "'.") context.addEvent(words(0), words(1)) } else failToRecognizeLine } }
/* Class ResetEventLineParser implements the line parser for "resetEvent" blocks in the DSL code. */
class ResetEventLineParser(context: StateMachineParser) extends LineParser(context) {
// Implementation of the hook method def doParse { if (hasOnlyWord("end")) returnToTopLevel else if (words.length == 1) { context.trace("..Define resetEvent '" + words(0) + "'.") context.addResetEvent(words(0)) } else failToRecognizeLine } }
/* Class CommandLineParser implements a line parser for "command" blocks in the DSL code. */
class CommandLineParser(context: StateMachineParser) extends LineParser(context) {
// Implementation of the hook method def doParse { if (hasOnlyWord("end")) returnToTopLevel else if (words.length == 2) { context.trace("..Define event '" + words(0) + "'.") context.addCommand(words(0), words(1)) } else failToRecognizeLine } }
/* Class StateLineParser implements a line parser for the "state" definition blocks in the DSL code. This block is more complex than the others because it includes transition and action statements. */
class StateLineParser(context: StateMachineParser, curState: State) extends LineParser(context) {
// Implementation of the hook method def doParse { if (hasOnlyWord("end")) context.setLineParser(new TopLevelLineParser(context)) else if (isTransition) processTransition else if (hasKeyword("actions")) processActions else throw new RecognitionException(line) }
// Does the line contain a "=>" symbol? private def isTransition = line.matches(".*=>.*")
// Reparse the line and process the "transition" statement. private def processTransition { val tokens = for (s <- line.split("=>")) yield s.trim context.trace("..Add transition on '" + tokens(0) + "' to '" + words(1) + "'") val trigger = context.getEvent(tokens(0)) // trigger event val target = context.obtainState(tokens(1)) // target state trigger match { // bypass addTransition in 'context' case Some(e) => curState.addTransition(e,target) case None => context.syntaxError("Undefined event '" + tokens(0) + "' in transition.") } }
// Handle the "actions" statement private def processActions { for (name <- words.drop(1)) { context.trace("..Add action '" + name + "'.") context.getCommand(name) match {// bypass addAction in 'context' case Some(ac) => curState.addAction(ac) case None => println("[Error] Attempt to add undefined action '" + name + "' to state '" + curState.name + "'." + " ..Unrecognized name skipped." ) } } }
}
/* Some limited testing. */
object DelimiterDSLTest {
def main(args: Array[String]) { println( " Delimiter-Directed Translation External DSL test beginning. " )
// Load and parse the DSL to configure the State Machine val machine = StateMachineParser.loadFile("CustomExternalStateMachineDSL.dsl") println println(machine)
// Build the controller val commandsChannel = new CommandChannel val control = new Controller(machine,commandsChannel) println(control.toString)
// Execute the model control.handle('D1CL) control.handle('L1ON) control.handle('D2OP) control.handle('PNCL)
println(" Commands output: " + commandsChannel.getOutput)
println( " Delimiter-Directed Translation External DSL test ending. ") } }
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started