Chat LIVE With Programming Experts! There Are 23 Online Right Now...

Welcome to Dream.In.Code
Become an Expert!

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




A Simple Script Interpreter (Continued)

 
Reply to this topicStart new topic

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

AdamSpeight2008
Group Icon



post 11 Jul, 2008 - 05:42 AM
Post #1


Continuation

vb

#Region "DRAW LINES"
Private Sub DrawLine(ByRef g As Graphics, ByRef penWIDTH As Single, ByRef pencolor As Color, ByRef X As Integer, ByRef Y As Integer, ByRef Ox As Integer, ByRef Oy As Integer)
' Draw an offset line on the current graphics surface.
Using usethispen As New Pen(pencolor, penWIDTH)
g.DrawLine(usethispen, X, Y, X + Ox, Y + Oy)
End Using
End Sub

Private Sub DrawLine2(ByRef g As Graphics, ByRef penWIDTH As Single, ByRef pencolor As Color, ByRef X As Integer, ByRef Y As Integer, ByRef Ox As Integer, ByRef Oy As Integer)
' Draw a line a line connection (X,Y) to (Ox,Oy)
Using usethispen As New Pen(pencolor, penWIDTH)
g.DrawLine(usethispen, X, Y, Ox, Oy)
End Using
End Sub
#End Region
#Region "THE COMMANDS"
#Region "COMMAND: PRINT"
Private Function Command_Print(ByRef state As ScriptState, ByRef cl() As String) As Boolean
' Command: PRINT <Text>

Dim FormatString As String = "PRINT"
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf
' How many fields does the command have?
Select Case cl.Length
Case 2
COutput.Text &= cl(1) & vbNewLine
Case Else
ErrorMessage("Unknown PRINT format" + vbNewLine)
Return False
End Select
Return True
End Function
#End Region
#Region "STORED PROCEDURE COMMAND"
#Region "MAKESHAPE"
Private Function Command_MakeShape(ByRef state As ScriptState, ByRef cl() As String) As Boolean
' Command: MAKESHAPE <Name>
' Rules;-
' 1. No nested MAKESHAPEs
' 2. Name must be unique
Dim FormatString As String = "MAKESHAPE"
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf
' How many fields does the command have?
Select Case cl.Length
Case 2
' It has 2 fields
' 0) MAKESHAPE
' 1) <Name>
'
' What is the current state of MakingShape
Select Case state.MakingShape
Case False
' Currently not making a shape.
' So is the name unique?
If state.ContainsShapeName(cl(1)) = True Then
' Breach of Rule 2
ErrorMessage(LineString & "Possible Cause;-" & vbNewLine & "1. The name is already being used.")
Return False
Else
' Yes it unique.
' Set the makingShape state to True
state.MakingShape = True
' Create a newShape
Dim newShape As New LogoShape
' Give it ites name.
newShape.ShapeName = cl(1)
' Add it the collection of other shapes.
state.myShapes.Add(newShape)
' Increment the shape Number
state.ShapeNumber += 1
End If
Case True
' Breach of rule 1
ErrorMessage(LineString & "Possible Causes;-" & vbNewLine & "1. Missing ENDSHAPE" & vbNewLine & "2. Nested MAKESHAPE are not allowed")
Return False

End Select
Case Else
Dim MessageText As String = LineString _
& "Error: Unknown Command" & vbNewLine _
& "Usage: MAKESHAPE <Name>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. No Nesting" & vbNewLine _
& "2. <Name> must be unique"
ErrorMessage(MessageText)
Return False
End Select
Return True
End Function
#End Region
#Region "COMMAND: ENDSHAPE"
Private Function Command_EndShape(ByRef state As ScriptState, ByRef cl() As String) As Boolean
' Command: ENDSHAPE
' Rules;-
' 1. Must have a matching MAKESHAPE
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf
Select Case cl.Length
Case 1
' Is the engine is making a shape?
Select Case state.MakingShape
Case True
' Yes, so set the MakingShape flag to true
state.MakingShape = False
Case False
' Unrecognised Command
ErrorMessage(LineString & "Missing MAKESHAPE")
Return False
End Select
Case Else
' Unrecognised Command
Dim MessageText As String = LineString _
& "Error: Unknown Command" & vbNewLine _
& "Usage: ENDSHAPE" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. Must have a matching MAKESHAPE"
ErrorMessage(MessageText)
Return False
End Select
Return True
End Function
#End Region
#Region "COMMAND: DRAWSHAPE"
Private Function Command_DrawShape(ByRef state As ScriptState, ByRef cl() As String, ByRef g As Graphics) As Boolean
' Command: DRAWSHAPE <Name>
' Rules;-
' 1. <Name> must have been made before it drawn.
' 2. <Name> can't the same as the MAKESHAPE it is it.
' 3. <Name> mustn't trigger a recursion.

Dim FormatString As String = "DRAWSHAPE"
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf
Select Case cl.Length
Case 2
' Is Rule 1 breached?
If state.ContainsShapeName(cl(1)) = False Then
' Rule 1 broken.
ErrorMessage(LineString & "This shape name isn't known to me.")
Return False
Else
' Is Rule 2 broken?
If mState.myShapes(mState.ShapeNumber).ShapeName = cl(1) And mState.MakingShape Then
' Yes
ErrorMessage(LineString & "I can't draw the shape whilst still making it.")
Return False
End If
' Is Rule 3 broken.
If state.ShapeStack.Contains(cl(1)) = True Then
ErrorMessage(LineString & "Recursive drawing of shapes is not allowed")
Return False
Else
' No Rules Broken, so push shape name being called onto the shaoe Stack
state.ShapeStack.Push(cl(1))
Dim snumber As Integer = state.IndexOfShapeName(cl(1))
' If the excution of the store shape, causes an error return false
If ExcuteScript(state.myShapes(snumber).ShapeData, g, COutput, True) = False Then Return False
' excuted ok the pop the shape name off the shape stack
If state.ShapeStack.Count > 0 Then state.ShapeStack.Pop()
End If
End If
Case Else
' Unrecognised Command
Dim MessageText As String = LineString _
& "Error: Unknown Command" & vbNewLine _
& "Usage: DRAWSHAPE <ShapeName>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. The Shape <ShapeName> must have been made before it can be drawn." & vbNewLine _
& "2. <Shape> can not be the same as the MAKESHAPE it is contained within." & vbNewLine _
& "3. Recursive calling of shapes is not allowed."
ErrorMessage(MessageText)
Return False
End Select
Return True
End Function
#End Region
#End Region
#Region "COMMAND: TURN"
Private Function Command_Turn(ByRef state As ScriptState, ByRef cl() As String) As Boolean
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf
Select Case cl.Length
Case 3
Select Case cl(1)
Case "FACE"
Dim turnangle As Single = 0
If IsNumeric(cl(2)) = True Then
If mState.MakingShape = False Then
turnangle = Val(cl(2))
mState.Angle = turnangle
mState.Angle = mState.Angle Mod 360
End If
Else
Select Case cl(2)
Case "NORTH" : mState.Angle = 0
Case "EAST" : mState.Angle = 90
Case "SOUTH" : mState.Angle = 180
Case "WEST" : mState.Angle = 270

Case Else
ErrorMessage("Sorry I don't know that direction.")
Return False
End Select

End If

Case "LEFT"
Dim turnangle As Single = 0
If IsNumeric(cl(2)) = False Then
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False
Else
If mState.MakingShape = False Then
turnangle = Val(cl(2))
mState.Angle += turnangle
mState.Angle = mState.Angle Mod 360
End If
End If
Case "RIGHT"
Dim turnangle As Single = 0
If IsNumeric(cl(2)) = False Then
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False
Else
If mState.MakingShape = False Then
turnangle = Val(cl(2))
mState.Angle -= turnangle
mState.Angle = mState.Angle Mod 360
End If
End If
Case Else
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False
End Select
Case Else
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False
End Select
Return True
End Function
#End Region
#Region "COMMAND: ROTATE"
Private Function Command_Rotate(ByRef state As ScriptState, ByRef CL() As String) As Boolean
Dim FormatString As String = "ROTATE"
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf
Select Case CL.Length
Case 2
If IsNumeric(CL(1)) = False Then
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False

Else
If mState.MakingShape = False Then

Dim TurnAngle As Double = Val(CL(1))
state.Angle = (state.Angle - TurnAngle) Mod 360
End If
End If
Case Else
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False



End Select
Return True
End Function
#End Region
#Region "COMMAND: PEN"
Private Function Command_Pen(ByRef state As ScriptState, ByRef commandline() As String) As Boolean
Dim FormatString As String = "PEN"
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf
' How many parameters does the command have, (this includes the command itself)?
Select Case commandline.Length
Case 2
Select Case commandline(1)
Case "UP" : state.PenDown = False
Case "DOWN" : state.PenDown = True
Case Else
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False
End Select
Case 3
Select Case commandline(1)
Case "COLOR"
Select Case commandline(2)
Case "RED" : state.Color = Color.Red
Case "BLACK" : state.Color = Color.Black
Case "BLUE" : state.Color = Color.Blue
Case "GREEN" : state.Color = Color.Green
Case Else
' Unrecognised Command
ErrorMessage(LineString & commandline(2) & " is not a recognised color.")
Return False
End Select
Case "WIDTH"
If IsNumeric(commandline(2)) Then
Dim SetWidth As Double = Val(commandline(2))
If SetWidth > 0 Then
state.Width = SetWidth
Else
ErrorMessage(LineString & "Pen Width must be greater the Zero.")
End If
Else
Select Case commandline(2)
Case "NORMAL" : state.Width = 1
Case "BIG" : state.Width = 3
Case "THIN" : state.Width = 0.5
Case Else
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False

End Select
End If
Case Else
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False
End Select
Case 5
Select Case commandline(1)
Case "COLOR"
If IsNumeric(commandline(2)) And IsNumeric(commandline(3)) And IsNumeric(commandline(4)) Then
Dim red As Integer = Val(commandline(2))
Dim green As Integer = Val(commandline(3))
Dim blue As Integer = Val(commandline(4))
If Not (red >= 0 And red <= 255) Then
' Unrecognised Command
ErrorMessage(LineString & "Red Values must be within the range 0 to 255 inclusive.")
Return False
End If
If Not (green >= 0 And green <= 255) Then
' Unrecognised Command
ErrorMessage(LineString & "Green Values must be within the range 0 to 255 inclusive.")
Return False
End If
If Not (blue >= 0 And blue <= 255) Then
' Unrecognised Command
ErrorMessage(LineString & "Blue Values must be within the range 0 to 255 inclusive.")
Return False
End If
state.Color = System.Drawing.Color.FromArgb(red, green, blue)
Else
' Unrecognised Command
ErrorMessage(LineString & "One of the color values is not a number.")
Return False
End If
Case Else
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False
End Select
Case Else
' Unrecognised Command
ErrorMessage(LineString & "Unrecognised Command")
Return False
End Select
Return True
End Function
#End Region
#Region "COMMAND: MOVE"
Private Function Command_Move(ByRef state As ScriptState, ByRef line() As String, ByRef g As Graphics) As Boolean
Dim FormatString As String = "Format: MOVE"
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf

Select Case line.Length
Case 4
If line(1) <> "TO" Then
ErrorMessage("UNKNOWN MOVE FORMAT")
Return False
End If
If IsNumeric(line(2)) = False Then
Dim MessageText As String = LineString _
& "Error: <X> isn't a number" & vbNewLine _
& "Usage: MOVE TO <X>,<Y>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. <X> must be a number." & vbNewLine _
& "2. <Y> must be a number."
ErrorMessage(MessageText)
Return False
End If
If IsNumeric(line(3)) = False Then
Dim MessageText As String = LineString _
& "Error: <Y> isn't a number" & vbNewLine _
& "Usage: MOVE TO <X>,<Y>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. <X> must be a number." & vbNewLine _
& "2. <Y> must be a number."
ErrorMessage(MessageText)
Return False
End If
If mState.MakingShape = False Then
If state.PenDown Then DrawLine2(g, state.Width, state.Color, state.X, state.Y, CInt(line(2)), CInt(line(3)))
'Todo: Bound Checks
state.X = CInt(line(2))
state.Y = CInt(line(3))
End If
Return True

Case 3
If IsNumeric(line(1)) = False Then
Dim MessageText As String = LineString _
& "Error: <X> isn't a number" & vbNewLine _
& "Usage: MOVE <X>,<Y>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. <X> must be a number." & vbNewLine _
& "2. <Y> must be a number."
ErrorMessage(MessageText)
Return False
End If
If IsNumeric(line(2)) = False Then
Dim MessageText As String = LineString _
& "Error: <Y> isn't a number" & vbNewLine _
& "Usage: MOVE <X>,<Y>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. <X> must be a number." & vbNewLine _
& "2. <Y> must be a number."
ErrorMessage(MessageText)
Return False
End If
If mState.MakingShape = False Then
If state.PenDown Then DrawLine(g, state.Width, state.Color, state.X, state.Y, CInt(line(1)), CInt(line(2)))
'Todo: Bound Checks
state.X += CInt(line(1))
state.Y += CInt(line(2))
End If
Return True
Case Else
Dim MessageText As String = LineString _
& "Error: Incorrect number of parameters" & vbNewLine _
& "Usage: MOVE <X>,<Y>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. <X> must be a number." & vbNewLine _
& "2. <Y> must be a number."
ErrorMessage(MessageText)
Return False
End Select
End Function
#End Region
#Region "COMMAND: FORWARD"
Private Function Command_Forward(ByRef state As ScriptState, ByRef line() As String, ByRef g As Graphics) As Boolean
' Command: FORWARD <Distance>
' Rules;-
' 1. <Distance> must be a number.
Dim LineString As String = "Line: " & state.LineNumber.ToString & vbCrLf
Select Case line.Length
Case 2
If IsNumeric(line(1)) = False Then
Dim MessageText As String = LineString _
& "Error: <Distance> isn't a number" & vbNewLine _
& "Usage: FORWARD <Distance>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. <Distance> must be a number."
ErrorMessage(MessageText)
Return False
Else
If mState.MakingShape = False Then
Dim distance As Double = Val(line(1))
Dim x2 As Double = 0
Dim y2 As Double = 0
x2 = state.X + (distance * Math.Cos(DegreeToRadian(state.Angle + 270)))
y2 = state.Y + (distance * Math.Sin(DegreeToRadian(state.Angle + 270)))
If state.PenDown Then DrawLine2(g, state.Width, state.Color, state.X, state.Y, x2, y2)
'Todo: Bound Checks
state.X = x2
state.Y = y2
Return True
End If
End If
Case Else
' Unrecognised Command
Dim MessageText As String = LineString _
& "Error: Unknown Command" & vbNewLine _
& "Usage: FORWARD <Distance>" & vbNewLine _
& "Rules;-" & vbNewLine _
& "1. <Distance> must be a number."
ErrorMessage(MessageText)
Return False
End Select
Return True
End Function
#End Region
#End Region
#Region "Misc. Useful Functions"
' Convert Radian To Degree
Private Shared Function RadianToDegree(ByVal radian As Double) As Double
Return (180 / Math.PI) * radian
End Function
' Convert Degree to Radian
Private Shared Function DegreeToRadian(ByVal degree As Double) As Double
Return (Math.PI / 180) * degree * 1
End Function
#End Region

End Class
#End Region



The Form
It contains only four controls
1. A RichTextBox called "RTB_Script"
2. A TextBox called "Txt_Output"
3. A PictureBox called "PBox_Outbox"
4. A Button called "But_Execute"

CODE

Public Class Form1
  Dim MyScriptEngine As New ScriptEngine
  Dim cmds As New List(Of String)

  Private Sub But_Execute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles But_Execute.Click
   If Me.RTB_Script.TextLength > 0 TheN
    Dim bmp As New Bitmap(PBox_Output.Width, PBox_Output.Height)
    Dim pg As Graphics = Graphics.FromImage(bmp)
    pg.Clear(Color.White)
    cmds.Clear()
    cmds.AddRange(RTB_Script.Lines)
    MyScriptEngine.ExcuteScript(cmds, pg, Me.Txt_Output)
    '   MyScriptEngine.ExcuteScript(RTB_Script.Lines.tolist, pg, Me.Txt_Output) 'VB2008
    PBox_Output.Image = bmp
    pg.Dispose()
   End If
  End Sub
End Class


This post has been edited by AdamSpeight2008: 11 Jul, 2008 - 03:51 PM


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


Register to Make This Ad Go Away!

Magic_Man
Group Icon



post 5 Apr, 2009 - 11:23 AM
Post #2
I downloaded your source and it took me a few minutes to figure out what I was doing but it was very fun to play with. This inspires me. I might try to create my own (even simpler than PenScript) language. Thanks for the tutorial. =D
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: 7/4/09 07:33AM

Live Help!

Be Social

Dream.In.Code RSS Feed Dream.In.Code LinkedIn Group Follow Us On Twitter Fan Us On Facebook

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month