Welcome to Dream.In.Code
Getting Help is Easy!

Join 132,195 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 1,151 people online right now. Registration is fast and FREE... Join Now!




A Simple Script Interpreter

 
Reply to this topicStart new topic

> A Simple Script Interpreter, Example of how to write one.

AdamSpeight2008
Group Icon



post 8 Jul, 2008 - 09:18 PM
Post #1


This is my first attempt of writing simple script interpreter.

Part 1: The State & Engine core
Part 2: Command Routines & Forms
CODE

' A Generic Scripting engine.
' By AdamSpeight2008
' Inspiration: Logo by Daniel G. Bobrow, Wally Feurzeig and Seymour Papert.
#Region "THE SCRIPT ENGINE"
Public Class ScriptEngine
    Private Const ScriptName = "PenScript v1.00"
    Private Tokens_Comment() As String = {"'"}
    Private Tokens_Delimiter() As String = {",", " "}
    Protected Friend mState As New ScriptState
#Region "PenScript Commands"
    ' PEN UP
    ' PEN DOWN
    ' PEN COLOR RED
    ' PEN COLOR GREEN
    ' PEN COLOR BLUE
    ' PEN COLOR BLACK
    ' PEN COLOR <RED>,<GREEN>,<BLUE>
    ' PEN WIDTH NORMAL
    ' PEN WIDTH BIG
    ' PEN WIDTH THIN
    ' PEN WIDTH <WIDTH>
    ' MOVE <X>,<Y>
    ' FORWARD <DISTANCE>
    ' TURN LEFT <DEGREES>
    ' TURN RIGHT <DEGREES>
    ' ROTATE <DEGREES>
    ' MAKESHAPE <SHAPE NAME>
    ' ENDSHAPE
    ' DRAWSHAPE <SHAPE NAME>
#End Region

#Region "States used by script engine"
    ' #### Start of Properties used by the script. ####
    Partial Class ScriptState
        Public myShapes As New List(Of LogoShape)
        Public ShapeStack As New Stack(Of String)
        Private mCurrentInstruction As String
        Private mMakingShape As Boolean
        Private mWidth As Single = 1
        Private mAngle As Double = 180
        Private mPenDown As Boolean
        Private mShapeNumber As Integer
        Private mX As Double = 0
        Private mY As Double = 0
        Private mLineNumber As Integer
        Private mColor As Color = Drawing.Color.Black


        Public Property CurrentInstruction() As String
            Get
                Return mCurrentInstruction
            End Get
            Set(ByVal value As String)
                mCurrentInstruction = value
            End Set
        End Property

        Public Property MakingShape() As Boolean
            Get
                Return mMakingShape
            End Get
            Set(ByVal value As Boolean)
                mMakingShape = value
            End Set
        End Property

        Public Property Width() As Single
            Get
                Return mWidth
            End Get
            Set(ByVal value As Single)
                mWidth = value
            End Set
        End Property

        Public Property Angle() As Double
            Get
                Return mAngle
            End Get
            Set(ByVal value As Double)
                mAngle = value
            End Set
        End Property

        Public Property PenDown() As Boolean
            Get
                Return mPenDown
            End Get
            Set(ByVal value As Boolean)
                mPenDown = value
            End Set
        End Property
        Public Property X() As Double
            Get
                Return mX
            End Get
            Set(ByVal value As Double)
                mX = value
            End Set
        End Property

        Public Property Y() As Double
            Get
                Return mY
            End Get
            Set(ByVal value As Double)
                mY = value
            End Set
        End Property

        Public Property ShapeNumber() As Integer
            Get
                Return mShapeNumber
            End Get
            Set(ByVal value As Integer)
                mShapeNumber = value
            End Set
        End Property

        Public Property LineNumber() As Integer
            Get
                Return mLineNumber
            End Get
            Set(ByVal value As Integer)
                mLineNumber = value
            End Set
        End Property

        Public Property Color() As Color
            Get
                Return mColor
            End Get
            Set(ByVal value As Color)
                mColor = value
            End Set
        End Property
        '### End of properties ###

        '### Start of Functions ###
        Public Function ContainsShapeName(ByRef ThisShapeName As String) As Boolean
            If myShapes.Count = 0 Then Return False
            For i As Integer = 0 To myShapes.Count - 1
                If myShapes(i).ShapeName = ThisShapeName Then Return True
            Next
            Return False
        End Function

        Public Function IndexOfShapeName(ByRef ThisShapeName As String) As Integer
            For i As Integer = 0 To myShapes.Count - 1
                If myShapes(i).ShapeName = ThisShapeName Then Return i
            Next
        End Function
        '### End of functions ###
    End Class
#End Region

#Region "Logo Shape class"
    ' The logo shape class
    Public Class LogoShape
        Private mShapeData As New List(Of String)
        Private mShapeName As String
        Public Property ShapeName() As String
            Get
                Return mShapeName
            End Get
            Set(ByVal value As String)
                mShapeName = value
            End Set
        End Property
        Public ReadOnly Property ShapeData() As List(Of String)
            Get
                Return mShapeData
            End Get
        End Property
        Public Sub AddShapeData(ByRef shapeText As String)
            mShapeData.Add(shapeText)
        End Sub
    End Class
#End Region

    Private Function RecombineInstructionFields(ByRef a() As String) As String
        Dim c As String = ""
        For Each p As String In a
            c &= p & " "
        Next
        Return c
    End Function

#Region "Enumerations"
    Public Enum ExitStates As Integer
        OK = True
        HasError = False
    End Enum
#End Region


    Private COutput As Control

#Region "ENGINE CORE"
#Region "CORE: EXECUTING THE SCRIPT"
    Public Function ExcuteScript(ByRef Commands As List(Of String), ByRef g As Graphics, ByRef OutputCtrl As Control, Optional ByRef SelfCalling As Boolean = False)
        ' Check that is something to execute.
        If Commands.Count = 0 Then Return False
        'Is the output control a textbox?
        If (TypeOf OutputCtrl Is TextBox) = False Then
            ' nope
            Return False
        End If
        ' If the ExecuteScript function is not being selfcalled
        If Not SelfCalling Then
            ' Set a local reference to the "console" control
            COutput = OutputCtrl
            ' clear the consol
            COutput.Text = ""
            COutput.Text &= ScriptName & vbNewLine
            ' also initialise the script states.
            InitialiseScriptEngineStates()
        End If
        Dim CommandStream As New IO.MemoryStream()
        Dim buffer() As Byte
        ' Trim Spaces & Remove the end of line character from each command
        For Each ThisString As String In Commands
            buffer = System.Text.Encoding.UTF8.GetBytes(ThisString.Trim(" "))
            CommandStream.Write(buffer, 0, buffer.Length)
            CommandStream.WriteByte(13)
        Next
        ' Set the CommandStream position back to the start.
        CommandStream.Position = 0
        ' Create the script parser for the command stream.
        Dim ScriptParser As New Microsoft.VisualBasic.FileIO.TextFieldParser(CommandStream)
        Dim CommandFields() As String = {}
        ' Initialise the Execution state to OK
        Dim ExecutionState As ExitStates = ExitStates.OK
        ' Tell the Script Parser what are the tokens for comments.
        ScriptParser.CommentTokens = Tokens_Comment
        ' Tell the Script Parser what the tokens are for delimiting he command.
        ScriptParser.Delimiters = Tokens_Delimiter
        ' Tell the Script Parsers that delimiters in strings are allowed.
        ScriptParser.HasFieldsEnclosedInQuotes = True
        ' While the script parser has something to parse.
        While Not ScriptParser.EndOfData
            ' Set the State(LineNumber) to the current line Number of the parser commands.
            mState.LineNumber = ScriptParser.LineNumber
            ' TRY & Read the next command, parse it into fields.
            Try
                CommandFields = ScriptParser.ReadFields
            Catch ex As Exception
                ErrorMessage("Error Message: " & ex.Message & vbNewLine)
                ' Execution Failed, so indicate error
                ExecutionState = ExitStates.HasError
                ' Close the Command Stream
                CommandStream.Close()
                CommandStream = Nothing
                ' Exit execution
                Exit While
            End Try
            ' Record the Current Instruction in the State(CurrentInstruction)
            mState.CurrentInstruction = RecombineInstructionFields(CommandFields)
            ' Try and execute the CommandFields
            ' The processing and execution is passed to ExecuteCommand() function
            ' - This is to keep the code simple
            ' - Makes implementing new easier.
            If ExcuteCommand(CommandFields, g, COutput) = False Then
                ' Execution Failed, so indicate error
                ExecutionState = ExitStates.HasError
                ' Exit execution
                Exit While
            End If
        End While
        ' Close the Command Stream
        CommandStream.Close()
        CommandStream = Nothing
        ' Check the state of execution
        Select Case True
            Case mState.MakingShape = False And ExecutionState = ExitStates.OK
                If Not SelfCalling Then ErrorMessage("Executed Successfully.")
                Return True
            Case mState.MakingShape = False And ExecutionState = ExitStates.HasError
                If Not SelfCalling Then ErrorMessage("Unsuccessful Execution")
                Return True
            Case mState.MakingShape = True And ExecutionState = ExitStates.OK
                If Not SelfCalling Then ErrorMessage("Missing ENDSHAPE")
                Return False
            Case mState.MakingShape = True And ExecutionState = ExitStates.HasError
                If Not SelfCalling Then ErrorMessage("Error in Execution (whilst Making Shape)")
                Return True
            Case Else
                Return False
        End Select
    End Function
#End Region

#Region "CORE: EXECUTING THE COMMAND"
    Private Function ExcuteCommand(ByRef command() As String, ByRef g As Graphics, ByRef OutputC As Control) As Boolean
        ' Define the exitState to be true (Assumes the command will execute successfully, until an error occurs.)
        Dim ExitState As Boolean = True
        ' Shall I record this instruction. (Used for stord procedures)
        Dim RecordInstruction As Boolean = True
        ' Which command is it?
        Select Case command(0)
            ' -- Start of Known Instructions --
            Case "PRINT" : ExitState = Command_Print(mState, command)
            Case "PEN" : ExitState = Command_Pen(mState, command)
            Case "MOVE" : ExitState = Command_Move(mState, command, g)
            Case "ROTATE" : ExitState = Command_Rotate(mState, command)
            Case "TURN" : ExitState = Command_Turn(mState, command)
            Case "FORWARD" : ExitState = Command_Forward(mState, command, g)
            Case "MAKESHAPE" : RecordInstruction = False : ExitState = Command_MakeShape(mState, command)
            Case "ENDSHAPE" : RecordInstruction = False : ExitState = Command_EndShape(mState, command)
            Case "DRAWSHAPE" : ExitState = Command_DrawShape(mState, command, g)
                ' -- End of known instructions --
            Case Else
                ' Unknown instruction
                ErrorMessage("Line: " & mState.LineNumber.ToString & vbCrLf & "Unknown Command." & vbCrLf & command(0))
                ExitState = False
        End Select
        ' Should I record this instruction
        If mState.MakingShape And RecordInstruction Then mState.myShapes(mState.ShapeNumber).AddShapeData(mState.CurrentInstruction)
        Return ExitState
    End Function
#End Region

#End Region


    Private Sub ErrorMessage(ByRef Message As String)
        ' Append the error message onto end of text.
        COutput.Text &= Message & vbNewLine
    End Sub

    Private Sub InitialiseScriptEngineStates()
        ' Initialise the states with there default values
        With mState
            .Angle = 0
            .X = 0
            .Y = 0
            .PenDown = False
            .MakingShape = False
            .LineNumber = 0
            .ShapeNumber = -1
            .ShapeStack.Clear()
            .myShapes.Clear()
            .Color = Color.Black
        End With
    End Sub

Continue in part2

This post has been edited by AdamSpeight2008: 11 Jul, 2008 - 05:38 AM


Attached File(s)
Attached File  PenScript.zip ( 173.65k ) Number of downloads: 63
Go to the top of the page
+Quote Post


Register to Make This Ad Go Away!

jagatworld
Group Icon



post 10 Jul, 2008 - 11:56 PM
Post #2
Hello AdamSpeight2008,

Upto some extent, it is ok, but at the last moment, i got a problem.


CODE


MyScriptEngine.ExcuteScript(RTB_Script.Lines.ToList, pg, Me.Txt_Output)  

error in :  RTB_Script.Lines.ToList



is giving error.

Please let me know what is the problem........ the error is
QUOTE

Error 1 Value of type 'String' cannot be converted to 'System.Collections.Generic.List(Of String)'. E:\Srikanth\SampleApps\ScriptInterpreter\ScriptInterpreter\Form1.vb 12 41 ScriptInterpreter


Thanks.
Go to the top of the page
+Quote Post

AdamSpeight2008
Group Icon



post 11 Jul, 2008 - 01:28 AM
Post #3
Original was written in Visual Basic 2008, and if run on a lower version would through this error. stupid.gif
Modified to compatible in most version of vb.net.
Go to the top of the page
+Quote Post

AdamSpeight2008
Group Icon



post 13 Jul, 2008 - 07:18 AM
Post #4
Now split across two tutorials
Part 1: States & Core
Part 2: Commands & Form
Go to the top of the page
+Quote Post


Fast ReplyReply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 

Lo-Fi Version Time is now: 11/21/08 05:02PM

Live Help!

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

Bye Bye Ads

Free DIC T-Shirt

T-Shirt Example

Related Sites

Monthly Drawing

Thumb Drive

Partners

Top Contributors

Top 10 Kudos This Month