' Executable filename: Parser.exe ' ' Author: Br. David Carlson ' ' Date: January 7, 2008 ' ' This freeware program provides an easy-to-use, table-driven LL(1) parser for educational use. ' The user supplies the program to be parsed as an input file and supplies files containing ' tables that specify the grammar rules, the finite state machine used to chop the program up ' into tokens, etc. The output file, if parsing is successful, contains an indented form of the ' parse tree for the given input program. The program can also be used to simply break the ' program up into a list of tokens, skipping the actual parsing. The .NET framework is needed ' in order to run this program. See the Parser.doc documentation file for further information. ' ' Revised June 2, 2008 so that nonterminals are indicated by uppercase letters, not by angle brackets ' around the nonterminals. This allows < to be used as a logical operator if desired. ' ' Revised June 24 and 25, 2013 to give better error reporting when parsing, tokenizing, etc. ' For parsing the program tries to display the line number of the file where the error was detected ' as well as the current lookahead symbol. Like most error reporting this is approximate. At times ' an error is only detected when the input program reaches a certain construct, but the actual error ' is in the grammar file. This revision also fixed a bug that sometimes caused a second or third run ' of the parser to give erroneous output in cases where the app was not shut down and restarted between ' runs. The app should now work correctly even if left open and re-run on the same, similar, or quite ' different input. Imports System Imports System.IO Imports System.Text Public Class Form1 Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code " Public Sub New() MyBase.New() 'This call is required by the Windows Form Designer. InitializeComponent() 'Add any initialization after the InitializeComponent() call End Sub 'Form overrides dispose to clean up the component list. Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean) If disposing Then If Not (components Is Nothing) Then components.Dispose() End If End If MyBase.Dispose(disposing) End Sub 'Required by the Windows Form Designer Private components As System.ComponentModel.IContainer 'NOTE: The following procedure is required by the Windows Form Designer 'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor. Friend WithEvents GroupBox1 As System.Windows.Forms.GroupBox Friend WithEvents RadioButtonParse As System.Windows.Forms.RadioButton Friend WithEvents RadioButtonFilter As System.Windows.Forms.RadioButton Friend WithEvents Label1 As System.Windows.Forms.Label Friend WithEvents ButtonRun As System.Windows.Forms.Button Friend WithEvents GroupBox2 As System.Windows.Forms.GroupBox Friend WithEvents Label7 As System.Windows.Forms.Label Friend WithEvents ButtonProgramFileOpen As System.Windows.Forms.Button Friend WithEvents ButtonProgramFileEdit As System.Windows.Forms.Button Friend WithEvents RadioButtonTokenize As System.Windows.Forms.RadioButton Friend WithEvents TextBoxProgramFile As System.Windows.Forms.TextBox Friend WithEvents OpenFileDialogProgram As System.Windows.Forms.OpenFileDialog Friend WithEvents LabelKeywordsFile As System.Windows.Forms.Label Friend WithEvents TextBoxKeywordsFile As System.Windows.Forms.TextBox Friend WithEvents ButtonKeywordsFileOpen As System.Windows.Forms.Button Friend WithEvents ButtonKeywordsFileEdit As System.Windows.Forms.Button Friend WithEvents LabelProgramFile As System.Windows.Forms.Label Friend WithEvents LabelFSMFile As System.Windows.Forms.Label Friend WithEvents LabelOutputFile As System.Windows.Forms.Label Friend WithEvents ButtonOutputFileEdit As System.Windows.Forms.Button Friend WithEvents ButtonOutputFileOpen As System.Windows.Forms.Button Friend WithEvents TextBoxOutputFile As System.Windows.Forms.TextBox Friend WithEvents ButtonFSMFileEdit As System.Windows.Forms.Button Friend WithEvents ButtonFSMFileOpen As System.Windows.Forms.Button Friend WithEvents TextBoxFSMFile As System.Windows.Forms.TextBox Friend WithEvents OpenFileDialogFSM As System.Windows.Forms.OpenFileDialog Friend WithEvents OpenFileDialogKeywords As System.Windows.Forms.OpenFileDialog Friend WithEvents OpenFileDialogTable As System.Windows.Forms.OpenFileDialog Friend WithEvents SaveFileDialogOutput As System.Windows.Forms.SaveFileDialog Friend WithEvents LabelMsg As System.Windows.Forms.Label Friend WithEvents LabelGrammarFile As System.Windows.Forms.Label Friend WithEvents ButtonGrammarFileEdit As System.Windows.Forms.Button Friend WithEvents ButtonGrammarFileOpen As System.Windows.Forms.Button Friend WithEvents TextBoxGrammarFile As System.Windows.Forms.TextBox Private Sub InitializeComponent() Me.GroupBox1 = New System.Windows.Forms.GroupBox Me.RadioButtonFilter = New System.Windows.Forms.RadioButton Me.RadioButtonParse = New System.Windows.Forms.RadioButton Me.RadioButtonTokenize = New System.Windows.Forms.RadioButton Me.Label1 = New System.Windows.Forms.Label Me.ButtonRun = New System.Windows.Forms.Button Me.LabelProgramFile = New System.Windows.Forms.Label Me.LabelFSMFile = New System.Windows.Forms.Label Me.LabelKeywordsFile = New System.Windows.Forms.Label Me.LabelGrammarFile = New System.Windows.Forms.Label Me.LabelOutputFile = New System.Windows.Forms.Label Me.GroupBox2 = New System.Windows.Forms.GroupBox Me.ButtonOutputFileEdit = New System.Windows.Forms.Button Me.ButtonOutputFileOpen = New System.Windows.Forms.Button Me.TextBoxOutputFile = New System.Windows.Forms.TextBox Me.ButtonGrammarFileEdit = New System.Windows.Forms.Button Me.ButtonGrammarFileOpen = New System.Windows.Forms.Button Me.TextBoxGrammarFile = New System.Windows.Forms.TextBox Me.ButtonKeywordsFileEdit = New System.Windows.Forms.Button Me.ButtonKeywordsFileOpen = New System.Windows.Forms.Button Me.TextBoxKeywordsFile = New System.Windows.Forms.TextBox Me.ButtonFSMFileEdit = New System.Windows.Forms.Button Me.ButtonFSMFileOpen = New System.Windows.Forms.Button Me.TextBoxFSMFile = New System.Windows.Forms.TextBox Me.ButtonProgramFileEdit = New System.Windows.Forms.Button Me.ButtonProgramFileOpen = New System.Windows.Forms.Button Me.TextBoxProgramFile = New System.Windows.Forms.TextBox Me.Label7 = New System.Windows.Forms.Label Me.OpenFileDialogProgram = New System.Windows.Forms.OpenFileDialog Me.OpenFileDialogFSM = New System.Windows.Forms.OpenFileDialog Me.OpenFileDialogKeywords = New System.Windows.Forms.OpenFileDialog Me.OpenFileDialogTable = New System.Windows.Forms.OpenFileDialog Me.SaveFileDialogOutput = New System.Windows.Forms.SaveFileDialog Me.LabelMsg = New System.Windows.Forms.Label Me.GroupBox1.SuspendLayout() Me.GroupBox2.SuspendLayout() Me.SuspendLayout() ' 'GroupBox1 ' Me.GroupBox1.Controls.Add(Me.RadioButtonFilter) Me.GroupBox1.Controls.Add(Me.RadioButtonParse) Me.GroupBox1.Controls.Add(Me.RadioButtonTokenize) Me.GroupBox1.ForeColor = System.Drawing.Color.RoyalBlue Me.GroupBox1.Location = New System.Drawing.Point(256, 8) Me.GroupBox1.Name = "GroupBox1" Me.GroupBox1.Size = New System.Drawing.Size(280, 72) Me.GroupBox1.TabIndex = 0 Me.GroupBox1.TabStop = False Me.GroupBox1.Text = "Mode of Operation" ' 'RadioButtonFilter ' Me.RadioButtonFilter.Location = New System.Drawing.Point(120, 32) Me.RadioButtonFilter.Name = "RadioButtonFilter" Me.RadioButtonFilter.Size = New System.Drawing.Size(48, 24) Me.RadioButtonFilter.TabIndex = 2 Me.RadioButtonFilter.Text = "Filter" ' 'RadioButtonParse ' Me.RadioButtonParse.Checked = True Me.RadioButtonParse.Location = New System.Drawing.Point(208, 32) Me.RadioButtonParse.Name = "RadioButtonParse" Me.RadioButtonParse.Size = New System.Drawing.Size(56, 24) Me.RadioButtonParse.TabIndex = 1 Me.RadioButtonParse.TabStop = True Me.RadioButtonParse.Text = "Parse" ' 'RadioButtonTokenize ' Me.RadioButtonTokenize.Location = New System.Drawing.Point(24, 32) Me.RadioButtonTokenize.Name = "RadioButtonTokenize" Me.RadioButtonTokenize.Size = New System.Drawing.Size(72, 24) Me.RadioButtonTokenize.TabIndex = 0 Me.RadioButtonTokenize.Text = "Tokenize" ' 'Label1 ' Me.Label1.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.Label1.ForeColor = System.Drawing.Color.RoyalBlue Me.Label1.Location = New System.Drawing.Point(16, 40) Me.Label1.Name = "Label1" Me.Label1.Size = New System.Drawing.Size(208, 48) Me.Label1.TabIndex = 1 Me.Label1.Text = "Select mode of operation, supply needed filenames, and click on Run. Then check t" & _ "he output file." ' 'ButtonRun ' Me.ButtonRun.Enabled = False Me.ButtonRun.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonRun.Location = New System.Drawing.Point(576, 40) Me.ButtonRun.Name = "ButtonRun" Me.ButtonRun.Size = New System.Drawing.Size(75, 23) Me.ButtonRun.TabIndex = 2 Me.ButtonRun.Text = "Run" ' 'LabelProgramFile ' Me.LabelProgramFile.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.LabelProgramFile.ForeColor = System.Drawing.Color.RoyalBlue Me.LabelProgramFile.Location = New System.Drawing.Point(16, 37) Me.LabelProgramFile.Name = "LabelProgramFile" Me.LabelProgramFile.Size = New System.Drawing.Size(80, 16) Me.LabelProgramFile.TabIndex = 3 Me.LabelProgramFile.Text = "Program file:" ' 'LabelFSMFile ' Me.LabelFSMFile.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.LabelFSMFile.ForeColor = System.Drawing.Color.RoyalBlue Me.LabelFSMFile.Location = New System.Drawing.Point(16, 79) Me.LabelFSMFile.Name = "LabelFSMFile" Me.LabelFSMFile.Size = New System.Drawing.Size(80, 16) Me.LabelFSMFile.TabIndex = 4 Me.LabelFSMFile.Text = "FSM file:" ' 'LabelKeywordsFile ' Me.LabelKeywordsFile.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.LabelKeywordsFile.ForeColor = System.Drawing.Color.RoyalBlue Me.LabelKeywordsFile.Location = New System.Drawing.Point(16, 115) Me.LabelKeywordsFile.Name = "LabelKeywordsFile" Me.LabelKeywordsFile.Size = New System.Drawing.Size(80, 16) Me.LabelKeywordsFile.TabIndex = 5 Me.LabelKeywordsFile.Text = "Keywords file:" ' 'LabelGrammarFile ' Me.LabelGrammarFile.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.LabelGrammarFile.ForeColor = System.Drawing.Color.RoyalBlue Me.LabelGrammarFile.Location = New System.Drawing.Point(16, 159) Me.LabelGrammarFile.Name = "LabelGrammarFile" Me.LabelGrammarFile.Size = New System.Drawing.Size(80, 16) Me.LabelGrammarFile.TabIndex = 6 Me.LabelGrammarFile.Text = "Grammar file:" ' 'LabelOutputFile ' Me.LabelOutputFile.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.LabelOutputFile.ForeColor = System.Drawing.Color.RoyalBlue Me.LabelOutputFile.Location = New System.Drawing.Point(16, 197) Me.LabelOutputFile.Name = "LabelOutputFile" Me.LabelOutputFile.Size = New System.Drawing.Size(80, 16) Me.LabelOutputFile.TabIndex = 7 Me.LabelOutputFile.Text = "Output file:" ' 'GroupBox2 ' Me.GroupBox2.Controls.Add(Me.ButtonOutputFileEdit) Me.GroupBox2.Controls.Add(Me.ButtonOutputFileOpen) Me.GroupBox2.Controls.Add(Me.TextBoxOutputFile) Me.GroupBox2.Controls.Add(Me.ButtonGrammarFileEdit) Me.GroupBox2.Controls.Add(Me.ButtonGrammarFileOpen) Me.GroupBox2.Controls.Add(Me.TextBoxGrammarFile) Me.GroupBox2.Controls.Add(Me.ButtonKeywordsFileEdit) Me.GroupBox2.Controls.Add(Me.ButtonKeywordsFileOpen) Me.GroupBox2.Controls.Add(Me.TextBoxKeywordsFile) Me.GroupBox2.Controls.Add(Me.ButtonFSMFileEdit) Me.GroupBox2.Controls.Add(Me.ButtonFSMFileOpen) Me.GroupBox2.Controls.Add(Me.TextBoxFSMFile) Me.GroupBox2.Controls.Add(Me.ButtonProgramFileEdit) Me.GroupBox2.Controls.Add(Me.ButtonProgramFileOpen) Me.GroupBox2.Controls.Add(Me.TextBoxProgramFile) Me.GroupBox2.Controls.Add(Me.LabelGrammarFile) Me.GroupBox2.Controls.Add(Me.LabelFSMFile) Me.GroupBox2.Controls.Add(Me.LabelKeywordsFile) Me.GroupBox2.Controls.Add(Me.LabelProgramFile) Me.GroupBox2.Controls.Add(Me.LabelOutputFile) Me.GroupBox2.ForeColor = System.Drawing.Color.RoyalBlue Me.GroupBox2.Location = New System.Drawing.Point(16, 88) Me.GroupBox2.Name = "GroupBox2" Me.GroupBox2.Size = New System.Drawing.Size(656, 232) Me.GroupBox2.TabIndex = 8 Me.GroupBox2.TabStop = False Me.GroupBox2.Text = "Files" ' 'ButtonOutputFileEdit ' Me.ButtonOutputFileEdit.Enabled = False Me.ButtonOutputFileEdit.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonOutputFileEdit.Location = New System.Drawing.Point(560, 194) Me.ButtonOutputFileEdit.Name = "ButtonOutputFileEdit" Me.ButtonOutputFileEdit.Size = New System.Drawing.Size(75, 23) Me.ButtonOutputFileEdit.TabIndex = 22 Me.ButtonOutputFileEdit.Text = "Edit" ' 'ButtonOutputFileOpen ' Me.ButtonOutputFileOpen.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonOutputFileOpen.Location = New System.Drawing.Point(464, 194) Me.ButtonOutputFileOpen.Name = "ButtonOutputFileOpen" Me.ButtonOutputFileOpen.Size = New System.Drawing.Size(75, 23) Me.ButtonOutputFileOpen.TabIndex = 21 Me.ButtonOutputFileOpen.Text = "Open" ' 'TextBoxOutputFile ' Me.TextBoxOutputFile.ForeColor = System.Drawing.SystemColors.ActiveCaption Me.TextBoxOutputFile.Location = New System.Drawing.Point(104, 195) Me.TextBoxOutputFile.Name = "TextBoxOutputFile" Me.TextBoxOutputFile.Size = New System.Drawing.Size(344, 20) Me.TextBoxOutputFile.TabIndex = 20 ' 'ButtonGrammarFileEdit ' Me.ButtonGrammarFileEdit.Enabled = False Me.ButtonGrammarFileEdit.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonGrammarFileEdit.Location = New System.Drawing.Point(560, 156) Me.ButtonGrammarFileEdit.Name = "ButtonGrammarFileEdit" Me.ButtonGrammarFileEdit.Size = New System.Drawing.Size(75, 23) Me.ButtonGrammarFileEdit.TabIndex = 19 Me.ButtonGrammarFileEdit.Text = "Edit" ' 'ButtonGrammarFileOpen ' Me.ButtonGrammarFileOpen.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonGrammarFileOpen.Location = New System.Drawing.Point(464, 156) Me.ButtonGrammarFileOpen.Name = "ButtonGrammarFileOpen" Me.ButtonGrammarFileOpen.Size = New System.Drawing.Size(75, 23) Me.ButtonGrammarFileOpen.TabIndex = 18 Me.ButtonGrammarFileOpen.Text = "Open" ' 'TextBoxGrammarFile ' Me.TextBoxGrammarFile.ForeColor = System.Drawing.SystemColors.ActiveCaption Me.TextBoxGrammarFile.Location = New System.Drawing.Point(104, 157) Me.TextBoxGrammarFile.Name = "TextBoxGrammarFile" Me.TextBoxGrammarFile.Size = New System.Drawing.Size(344, 20) Me.TextBoxGrammarFile.TabIndex = 17 ' 'ButtonKeywordsFileEdit ' Me.ButtonKeywordsFileEdit.Enabled = False Me.ButtonKeywordsFileEdit.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonKeywordsFileEdit.Location = New System.Drawing.Point(560, 112) Me.ButtonKeywordsFileEdit.Name = "ButtonKeywordsFileEdit" Me.ButtonKeywordsFileEdit.Size = New System.Drawing.Size(75, 23) Me.ButtonKeywordsFileEdit.TabIndex = 16 Me.ButtonKeywordsFileEdit.Text = "Edit" ' 'ButtonKeywordsFileOpen ' Me.ButtonKeywordsFileOpen.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonKeywordsFileOpen.Location = New System.Drawing.Point(464, 112) Me.ButtonKeywordsFileOpen.Name = "ButtonKeywordsFileOpen" Me.ButtonKeywordsFileOpen.Size = New System.Drawing.Size(75, 23) Me.ButtonKeywordsFileOpen.TabIndex = 15 Me.ButtonKeywordsFileOpen.Text = "Open" ' 'TextBoxKeywordsFile ' Me.TextBoxKeywordsFile.ForeColor = System.Drawing.SystemColors.ActiveCaption Me.TextBoxKeywordsFile.Location = New System.Drawing.Point(104, 113) Me.TextBoxKeywordsFile.Name = "TextBoxKeywordsFile" Me.TextBoxKeywordsFile.Size = New System.Drawing.Size(344, 20) Me.TextBoxKeywordsFile.TabIndex = 14 ' 'ButtonFSMFileEdit ' Me.ButtonFSMFileEdit.Enabled = False Me.ButtonFSMFileEdit.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonFSMFileEdit.Location = New System.Drawing.Point(560, 76) Me.ButtonFSMFileEdit.Name = "ButtonFSMFileEdit" Me.ButtonFSMFileEdit.Size = New System.Drawing.Size(75, 23) Me.ButtonFSMFileEdit.TabIndex = 13 Me.ButtonFSMFileEdit.Text = "Edit" ' 'ButtonFSMFileOpen ' Me.ButtonFSMFileOpen.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonFSMFileOpen.Location = New System.Drawing.Point(464, 76) Me.ButtonFSMFileOpen.Name = "ButtonFSMFileOpen" Me.ButtonFSMFileOpen.Size = New System.Drawing.Size(75, 23) Me.ButtonFSMFileOpen.TabIndex = 12 Me.ButtonFSMFileOpen.Text = "Open" ' 'TextBoxFSMFile ' Me.TextBoxFSMFile.ForeColor = System.Drawing.SystemColors.ActiveCaption Me.TextBoxFSMFile.Location = New System.Drawing.Point(104, 77) Me.TextBoxFSMFile.Name = "TextBoxFSMFile" Me.TextBoxFSMFile.Size = New System.Drawing.Size(344, 20) Me.TextBoxFSMFile.TabIndex = 11 ' 'ButtonProgramFileEdit ' Me.ButtonProgramFileEdit.Enabled = False Me.ButtonProgramFileEdit.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonProgramFileEdit.Location = New System.Drawing.Point(560, 34) Me.ButtonProgramFileEdit.Name = "ButtonProgramFileEdit" Me.ButtonProgramFileEdit.Size = New System.Drawing.Size(75, 23) Me.ButtonProgramFileEdit.TabIndex = 10 Me.ButtonProgramFileEdit.Text = "Edit" ' 'ButtonProgramFileOpen ' Me.ButtonProgramFileOpen.ForeColor = System.Drawing.Color.RoyalBlue Me.ButtonProgramFileOpen.Location = New System.Drawing.Point(464, 34) Me.ButtonProgramFileOpen.Name = "ButtonProgramFileOpen" Me.ButtonProgramFileOpen.Size = New System.Drawing.Size(75, 23) Me.ButtonProgramFileOpen.TabIndex = 9 Me.ButtonProgramFileOpen.Text = "Open" ' 'TextBoxProgramFile ' Me.TextBoxProgramFile.ForeColor = System.Drawing.SystemColors.ActiveCaption Me.TextBoxProgramFile.Location = New System.Drawing.Point(104, 35) Me.TextBoxProgramFile.Name = "TextBoxProgramFile" Me.TextBoxProgramFile.Size = New System.Drawing.Size(344, 20) Me.TextBoxProgramFile.TabIndex = 8 ' 'Label7 ' Me.Label7.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.Label7.ForeColor = System.Drawing.Color.RoyalBlue Me.Label7.Location = New System.Drawing.Point(16, 16) Me.Label7.Name = "Label7" Me.Label7.Size = New System.Drawing.Size(208, 16) Me.Label7.TabIndex = 9 Me.Label7.Text = "Parser freeware by Br. David Carlson" ' 'OpenFileDialogProgram ' Me.OpenFileDialogProgram.Filter = "Text files (*.txt)|*.txt" Me.OpenFileDialogProgram.ShowReadOnly = True Me.OpenFileDialogProgram.Title = "Open Program File" ' 'OpenFileDialogFSM ' Me.OpenFileDialogFSM.Title = "Open FSM File" ' 'OpenFileDialogKeywords ' Me.OpenFileDialogKeywords.Title = "Open Keywords File" ' 'OpenFileDialogTable ' Me.OpenFileDialogTable.Title = "Open Grammar File" ' 'SaveFileDialogOutput ' Me.SaveFileDialogOutput.Title = "Save Output File" ' 'LabelMsg ' Me.LabelMsg.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte)) Me.LabelMsg.ForeColor = System.Drawing.Color.Red Me.LabelMsg.Location = New System.Drawing.Point(16, 328) Me.LabelMsg.Name = "LabelMsg" Me.LabelMsg.Size = New System.Drawing.Size(635, 53) Me.LabelMsg.TabIndex = 10 ' 'Form1 ' Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13) Me.ClientSize = New System.Drawing.Size(680, 381) Me.Controls.Add(Me.LabelMsg) Me.Controls.Add(Me.Label7) Me.Controls.Add(Me.GroupBox2) Me.Controls.Add(Me.ButtonRun) Me.Controls.Add(Me.Label1) Me.Controls.Add(Me.GroupBox1) Me.Name = "Form1" Me.Text = "Parser 1.2" Me.GroupBox1.ResumeLayout(False) Me.GroupBox2.ResumeLayout(False) Me.GroupBox2.PerformLayout() Me.ResumeLayout(False) End Sub #End Region Private Const ArraySize As Integer = 600 Private Const MaxStates As Integer = 200 Private Const MaxCategories As Integer = 40 Private Const MaxLookAheads As Integer = 40 Private Const MaxNonTerminals As Integer = 200 Private Const MaxRules As Integer = 300 Private Const MaxRuleLength As Integer = 24 Private Const MaxKeywords As Integer = 200 Private Const MaxChar As Integer = 24 Private OutputFileStreamWriter As StreamWriter Private ProgramArray As String() Private FSMArray As String() Private GrammarArray As String() Private KeywordsArray As String() Private TokenAccepted As String() Private Categories As String() Private FSMTable As Integer(,) Private LookAheads As TokenClass() Private NonTerminals As String() Private RuleTable As Integer(,) Private Rules As RuleClass() Private NumStates As Integer Private NumCategories As Integer Private ChIndex As Integer Private FSMSize As Integer Private GrammarSize As Integer Private NumLines As Integer Private NumKeywords As Integer Private NumLookAheads As Integer Private NumNonTerminals As Integer Private NumRules As Integer Private Token As TokenClass Private CharIsSaved As Boolean Private SavedChar As Char ' Get the next char from ProgramArray into Ch, adjusting the rest of the parameters as needed. ' If there is a saved char, it is used instead of getting a new char from ProgramArray. ' Ch is the returned char, Status contains a string giving the status of the char Ch, ' Line is the current string from ProgramArray to look at to get the next char, ' LineNumber is the index of this string in ProgramArray, ChIndex is the index of where ' to get the next char in Line, and Len is the length of Line. Private Sub NextChar(ByRef Ch As Char, ByRef Status As String, ByRef Line As String, _ ByRef LineNumber As Integer, ByRef ChIndex As Integer, ByRef Len As Integer) Dim Classify As Boolean Ch = " " ' Use blank char as default value. Classify = False If CharIsSaved Then CharIsSaved = False Ch = SavedChar ChIndex = ChIndex + 1 Classify = True ElseIf (LineNumber = NumLines - 1) And (ChIndex = Len) Then Status = "eof" LineNumber = NumLines ElseIf (ChIndex = Len) Then ' We are at the end of a line other than the last line. Status = "whitespace" ' whitespace includes space char and eoln. LineNumber = LineNumber + 1 Line = ProgramArray(LineNumber) Len = Line.Length ChIndex = 0 Else Ch = Line.Chars(ChIndex) ChIndex = ChIndex + 1 Classify = True End If If Classify Then If Char.IsDigit(Ch) Then Status = "digit" ElseIf Char.IsLetter(Ch) Then Status = "alpha" ElseIf Ch = ":"c Then Status = "colon" ElseIf Ch = "="c Then Status = "equals" ElseIf Ch = ";" Then Status = "semicolon" ElseIf Ch = " "c Then Status = "whitespace" ElseIf Ch = "+"c Then Status = "plus" ElseIf Ch = "-"c Then Status = "minus" ElseIf Ch = "*"c Then Status = "asterisk" ElseIf Ch = "/"c Then Status = "slash" ElseIf Ch = "!"c Then Status = "exclamation" ElseIf Ch = "&"c Then Status = "ampersand" ElseIf Ch = "("c Then Status = "leftparen" ElseIf Ch = ")"c Then Status = "rightparen" ElseIf Ch = "'"c Then Status = "singlequote" ElseIf Ch = """"c Then Status = "doublequote" ElseIf Ch = ","c Then Status = "comma" ElseIf Ch = "."c Then Status = "period" ElseIf Ch = "<"c Then Status = "lessthan" ElseIf Ch = ">"c Then Status = "greaterthan" ElseIf Ch = "`"c Then Status = "tilde" ElseIf Ch = "`"c Then Status = "backquote" ElseIf Ch = "@"c Then Status = "at" ElseIf Ch = "#"c Then Status = "pound" ElseIf Ch = "$"c Then Status = "dollar" ElseIf Ch = "%"c Then Status = "percent" ElseIf Ch = "^"c Then Status = "caret" ElseIf Ch = "_"c Then Status = "underscore" ElseIf Ch = "|"c Then Status = "pipe" ElseIf Ch = "\"c Then Status = "backslash" ElseIf Ch = "["c Then Status = "leftbracket" ElseIf Ch = "]"c Then Status = "rightbracket" ElseIf Ch = "{"c Then Status = "leftbrace" ElseIf Ch = "}"c Then Status = "rightbrace" ElseIf Ch = "?"c Then Status = "question" Else Status = "other" End If End If End Sub ' Find the next state based on the present value of State and Status of current input. ' Uses FSMTable from the Form1 object. ' Return this new state in parameter State. Private Sub NextState(ByRef State As Integer, ByVal Status As String) Dim Found As Boolean Dim Column As Integer If (State < 1) Or (State > NumStates) Then State = -1 ' Indicates an error. Else Column = 0 Found = False While (Column < NumCategories) And (Not Found) If Status = Categories(Column) Then Found = True Else Column = Column + 1 End If End While If Found Then State = FSMTable(State - 1, Column) Else State = -1 ' Indicates an error. End If End If End Sub ' Checks to see if the current value of Token.Item is in KeywordsArray. If so, ' Token.Category is changed to the string keyword. Otherwise it is changed to the ' string identifier. Private Sub KeywordCheck() Dim k As Integer Dim Found As Boolean k = 0 Found = False While (k < NumKeywords) And (Not Found) If KeywordsArray(k) = Token.Item Then Found = True Else k = k + 1 End If End While If Found Then Token.Category = "keyword" Else Token.Category = "identifier" End If End Sub ' Retrieves the next token, placing it in the Token field of the Form1 object. ' The data for the token is taken from ProgramArray (and possibly SavedChar), ' starting at line LineNumber of ProgramArray and index ChIndex within this line. ' This routines advances ChIndex and LineNumber as needed so that they point to ' the location in ProgramArray right after the retrieved token. ' The information in the FSM file (stored in the FSMArray and associated variables) ' is used to determine what is a valid token and what category it fits. Private Sub NextToken(ByRef LineNumber As Integer, ByRef ChIndex As Integer) Dim CharCount, State, OldState, Len As Integer Dim Status, Line As String Dim Ch As Char If LineNumber < NumLines Then CharCount = 0 State = 1 Token.Item = "" Token.Category = "" Line = ProgramArray(LineNumber) Len = Line.Length Do OldState = State NextChar(Ch, Status, Line, LineNumber, ChIndex, Len) If (Status <> "whitespace") And (Status <> "eof") Then CharCount = CharCount + 1 If CharCount >= MaxChar Then Throw New IndexOutOfRangeException("Too many chars for token in program file line " & (LineNumber + 1).ToString) End If Token.Item = Token.Item & Ch End If NextState(State, Status) Loop Until (State = 0) Or (State = -1) If State = 0 Then ' A token was successfully found. If (Status <> "whitespace") And (Status <> "eof") Then ' We recorded 1 char too many. Token.Item = Token.Item.Substring(0, CharCount - 1) ' Remove the last char ... SavedChar = Ch ' ... and save it. ChIndex = ChIndex - 1 CharIsSaved = True End If Token.Category = TokenAccepted(OldState - 1) If (Not RadioButtonTokenize.Checked) And (Token.Category = "word") Then KeywordCheck() End If Else ' State = -1 Token.Category = "error" End If Else Token.Item = "" Token.Category = "EndMarker" End If End Sub ' Finds the next integer within string Str starting at index Position. ' Skips over initial whitespace, if need be, to find this integer. ' Returns this integer in parameter Item and returns the index after it in Position. ' Throws an exception if it cannot find a valid integer. ' Negative integers are not handled. Private Sub NextInt(ByVal Str As String, ByRef Position As Integer, ByRef Item As Integer) Dim k, Len, Sign As Integer Dim Ch As Char Len = Str.Length k = Position If Position < Len Then Ch = Str.Chars(k) Else Throw New ArithmeticException("Not a valid number") End If While (Ch <> "-"c) And (Not Char.IsDigit(Ch)) And (k < Len) k = k + 1 If k < Len Then Ch = Str.Chars(k) End If End While If k = Len Then Throw New ArithmeticException("Not a valid number") ElseIf (Ch = "-"c) Then If k = Len - 1 Then Throw New ArithmeticException("Not a valid number") Else k = k + 1 Ch = Str.Chars(k) If (Not Char.IsDigit(Ch)) Then Throw New ArithmeticException("Not a valid number") Else Sign = -1 End If End If Else ' We must have a digit for Ch Sign = 1 End If Item = 0 While Char.IsDigit(Ch) And (k < Len) Item = Item * 10 + Val(Ch) k = k + 1 If k < Len Then Ch = Str.Chars(k) End If End While Item = Sign * Item Position = k End Sub ' Returns in Item the substring found starting at Index in Str. Item will be the ' empty string if Str at Index is a blank or doesn't exist. The substring stops ' just before the first blank (or end of string Str). Index is normally advanced ' to the position of the char in Str just after the end of Item. Index always ' advances by at least 1, unless Str itself is the emtpy string. Private Sub NextString(ByVal Str As String, ByRef Index As Integer, ByRef Item As String) Dim [Continue] As Boolean Dim Len, Count As Integer Dim Ch As Char Item = "" Len = Str.Length() [Continue] = True Count = 0 While (Index < Len) And [Continue] Ch = Str.Chars(Index) If Ch = " "c Then [Continue] = False ElseIf Count >= MaxChar - 1 Then Throw New IndexOutOfRangeException("Too many chars for the string") Else Item = Item & Ch Count = Count + 1 End If Index = Index + 1 End While End Sub ' Advances Index to skip over blank characters at position Index and following in string Str. ' Index is advanced to the position of the first non-blank at or following the starting ' location given by Index. If there is no non-blank in this section, Index is ' set to 1 more than the last valid index for the string Str. Private Sub SkipBlanks(ByVal Str As String, ByRef Index As Integer) Dim Ch As Char Dim [Continue] As Boolean Dim Len As Integer Len = Str.Length() [Continue] = True While (Index < Len) And [Continue] Ch = Str.Chars(Index) If Ch = " "c Then Index = Index + 1 Else [Continue] = False End If End While End Sub ' Reads the lines of the FSM file into the field FSMArray. Also places the count of the ' number of these lines into the field FSMSize. Private Sub ReadFSMFile() Dim k As Integer Dim Line As String Dim FSMFileStreamReader As StreamReader Try k = 0 FSMFileStreamReader = New StreamReader(TextBoxFSMFile.Text) FSMArray = New String(ArraySize - 1) {} Do Line = FSMFileStreamReader.ReadLine() FSMArray(k) = Line k = k + 1 Loop Until (Line Is Nothing) Or (k = ArraySize) FSMSize = k Catch Except As Exception Throw New Exception("Error in FSM file line " & (k + 1).ToString & ": " & Except.Message) Finally FSMFileStreamReader.Close() End Try End Sub ' Reads the lines of the grammar file into the field GrammarArray. Also places the count of the ' number of these lines into the field GrammarSize. Private Sub ReadGrammarFile() Dim k As Integer Dim Line As String Dim GrammarFileStreamReader As StreamReader Try k = 0 GrammarFileStreamReader = New StreamReader(TextBoxGrammarFile.Text) GrammarArray = New String(ArraySize - 1) {} Do Line = GrammarFileStreamReader.ReadLine() GrammarArray(k) = Line k = k + 1 Loop Until (Line Is Nothing) Or (k = ArraySize) GrammarSize = k Catch Except As Exception Throw New Exception("Error in grammar file line " & (k + 1).ToString & ": " & Except.Message) Finally GrammarFileStreamReader.Close() End Try End Sub ' Extracts the data from the field GrammarArray, placing it into the fields NumLookAheads, ' NumNonTerminals, NumRules, LookAheads, NonTerminals, Rules, and RuleTable. ' Revised June 2, 2008 so that nonterminals are indicated by uppercase letters, not by angle brackets ' around the nonterminals. This allows < to be used as a logical operator if desired. Private Sub ExtractGrammarData() Dim Start, Num, Row, Col, RuleLength As Integer Dim Line, Item, Category, NonTerminal, TempString, BodyPart As String Try Start = 0 Num = 0 NextInt(GrammarArray(0), Start, NumLookAheads) If (NumLookAheads < 1) Or (NumLookAheads > MaxLookAheads) Then Throw New IndexOutOfRangeException("In grammar file invalid num lookaheads " & NumLookAheads.ToString) End If LookAheads = New TokenClass(NumLookAheads - 1) {} For Row = 1 To NumLookAheads Num = Num + 1 Line = GrammarArray(Num) Start = 0 NextString(Line, Start, Item) SkipBlanks(Line, Start) NextString(Line, Start, Category) LookAheads(Row - 1) = New TokenClass(Item, Category) Next Num = Num + 1 While (Num < GrammarSize) And (GrammarArray(Num) = "") Num = Num + 1 End While If Num >= GrammarSize Then Throw New IndexOutOfRangeException("Can't find int for num nonterminals in grammar file") End If Start = 0 NextInt(GrammarArray(Num), Start, NumNonTerminals) If (NumNonTerminals < 1) Or (NumNonTerminals > MaxNonTerminals) Then Throw New IndexOutOfRangeException("In grammar file invalid num nonterminals " & NumNonTerminals.ToString) End If NonTerminals = New String(NumNonTerminals - 1) {} RuleTable = New Integer(NumNonTerminals - 1, NumLookAheads - 1) {} For Row = 0 To NumNonTerminals - 1 Num = Num + 1 Line = GrammarArray(Num) Start = 0 NextString(Line, Start, NonTerminal) NonTerminals(Row) = NonTerminal For Col = 0 To NumLookAheads - 1 NextInt(Line, Start, RuleTable(Row, Col)) Next Next Num = Num + 1 While (Num < GrammarSize) And (GrammarArray(Num) = "") Num = Num + 1 End While If Num >= GrammarSize Then Throw New IndexOutOfRangeException("Can't find integer for num grammar rules") End If Start = 0 NextInt(GrammarArray(Num), Start, NumRules) If (NumRules < 1) Or (NumRules > MaxRules) Then Throw New IndexOutOfRangeException("Invalid num grammar rules " & NumRules.ToString) End If Rules = New RuleClass(NumRules - 1) {} For Row = 0 To NumRules - 1 Num = Num + 1 Line = GrammarArray(Num) If Line Is Nothing Then Throw New IndexOutOfRangeException("Line " & (Num + 1).ToString & " from grammar file is empty") End If Start = 0 NextString(Line, Start, TempString) ' Ignore the rule number SkipBlanks(Line, Start) NextString(Line, Start, TempString) ' Ignore the head of the rule SkipBlanks(Line, Start) NextString(Line, Start, TempString) ' Ignore the -> NextInt(Line, Start, RuleLength) If (RuleLength < 0) Or (RuleLength > MaxRuleLength) Then Throw New IndexOutOfRangeException("Invalid number " & RuleLength.ToString & " in RHS of grammar rule " & (Num + 1).ToString) End If Rules(Row) = New RuleClass(RuleLength) Rules(Row).RuleBodyArray = New TokenClass(RuleLength - 1) {} For Col = 0 To RuleLength - 1 SkipBlanks(Line, Start) NextString(Line, Start, BodyPart) If Char.IsUpper(BodyPart, 0) Then ' Modified June 2, 2008 Category = "nonterminal" Else Category = "terminal" End If Rules(Row).RuleBodyArray(Col) = New TokenClass(BodyPart, Category) Next Next Catch Except As Exception Throw New Exception("Error in grammar file line " & (Num + 1).ToString & ": " & Except.Message) End Try End Sub ' Extracts the data from the field FSMArray, placing it into the fields NumStates, ' TokenAccepted, NumCategories, Categories, and FSMTable. Private Sub ExtractFSMData() Dim Start, Num, Row, Col, Index, Item As Integer Dim Line As String Try Start = 0 Num = 0 NextInt(FSMArray(0), Start, NumStates) If (NumStates < 1) Or (NumStates > MaxStates) Then Throw New IndexOutOfRangeException("In FSM file invalid num states " & NumStates.ToString) End If TokenAccepted = New String(NumStates - 1) {} For Row = 1 To NumStates Num = Num + 1 If FSMArray(Num).Length > MaxChar Then Throw New IndexOutOfRangeException("Too many chars for a token in FSM file") End If TokenAccepted(Row - 1) = FSMArray(Num) Next Num = Num + 1 While (Num < FSMSize) And (FSMArray(Num) = "") Num = Num + 1 End While If Num >= FSMSize Then Throw New IndexOutOfRangeException("Can't find integer for num categories in FSM file") End If Start = 0 NextInt(FSMArray(Num), Start, NumCategories) If (NumCategories < 1) Or (NumCategories > MaxCategories) Then Throw New IndexOutOfRangeException("In FSM file invalid num categories " & NumCategories.ToString) End If Categories = New String(NumCategories - 1) {} For Col = 1 To NumCategories Num = Num + 1 If FSMArray(Num).Length > MaxChar Then Throw New IndexOutOfRangeException("Too many chars for a category in FSM file") End If Categories(Col - 1) = FSMArray(Num) Next Num = Num + 1 While (Num < FSMSize) And (FSMArray(Num) = "") Num = Num + 1 End While Num = Num + 1 ' Skip the comment line. If Num >= FSMSize Then Throw New IndexOutOfRangeException("Can't find first integer for FSM transition table") End If FSMTable = New Integer(NumStates - 1, NumCategories - 1) {} For Row = 0 To NumStates - 1 Line = FSMArray(Num) Num = Num + 1 Index = 0 NextInt(Line, Index, Item) FSMTable(Row, 0) = Item For Col = 1 To NumCategories - 1 NextInt(Line, Index, Item) FSMTable(Row, Col) = Item Next Next Catch Except As Exception Throw New Exception("Error in FSM file line " & (Num + 1).ToString & ": " & Except.Message) End Try End Sub ' Reads the program file lines into the field ProgramArray. Also places the count of the ' number of such lines into the field NumLines. Private Sub ReadProgramFile() Dim k As Integer Dim Line As String Dim ProgramFileStreamReader As StreamReader Try k = 0 ProgramFileStreamReader = New StreamReader(TextBoxProgramFile.Text) ProgramArray = New String(ArraySize - 1) {} Do Line = ProgramFileStreamReader.ReadLine() ProgramArray(k) = Line k = k + 1 Loop Until (Line Is Nothing) Or (k = ArraySize) If Line Is Nothing Then NumLines = k - 1 Else NumLines = k End If Catch Except As Exception Throw New Exception("Error in program file line " & (k + 1).ToString & ": " & Except.Message) Finally ProgramFileStreamReader.Close() End Try End Sub ' Reads the keywords file lines into the field KeywordsArray. Also places the count of the ' number of such keywords into the field NumKeywords. Private Sub ReadKeywordsFile() Dim k, Start As Integer Dim Line As String Dim KeywordsFileStreamReader As StreamReader Try k = 0 Start = 0 KeywordsFileStreamReader = New StreamReader(TextBoxKeywordsFile.Text) KeywordsArray = New String(MaxKeywords - 1) {} Line = KeywordsFileStreamReader.ReadLine() ' First line has count of number of keywords. NextInt(Line, Start, NumKeywords) If (NumKeywords < 0) Or (NumKeywords > MaxKeywords) Then Throw New IndexOutOfRangeException("In keywords file invalid num keywords " & NumKeywords.ToString) End If For k = 1 To NumKeywords Line = KeywordsFileStreamReader.ReadLine() If (Line Is Nothing) Then Throw New Exception("Couldn't read keyword " & k.ToString & " in keywords file") Else KeywordsArray(k - 1) = Line End If Next Catch Except As Exception Throw New Exception("Error in keywords file line " & k.ToString & ": " & Except.Message) Finally KeywordsFileStreamReader.Close() End Try End Sub ' Finds LookAheadSymbol in the LookAheads field, and finds StackNonTerminal in the ' NonTerminals field. Returns the rule number of the grammar rule from RuleTable ' that corresponds to LookAheadSymbol and StackNonTerminal. If either of the two ' lookups fails, 0 (an invalid rule number) is returned as the value of RuleNumber. Private Sub FindRule(ByRef LookAheadSymbol As TokenClass, ByRef StackNonTerminal As String, _ ByRef RuleNumber As Integer) Dim Row, Col As Integer Dim Found As Boolean Try ' Find LookAheadSymbol in LookAheads array. Col = 0 Found = False While (Col < NumLookAheads) And (Not Found) If LookAheads(Col).Category = LookAheadSymbol.Category Then If (LookAheads(Col).Category = "special") Or _ (LookAheads(Col).Category = "keyword") Then ' Need items to match too. If LookAheads(Col).Item = LookAheadSymbol.Item Then Found = True Else Col = Col + 1 End If Else Found = True End If Else Col = Col + 1 End If End While If Not Found Then RuleNumber = 0 Return End If ' Find StackNonTerminal in NonTerminals array. Row = 0 Found = False While (Row < NumNonTerminals) And (Not Found) If NonTerminals(Row) = StackNonTerminal Then Found = True Else Row = Row + 1 End If End While If Not Found Then RuleNumber = 0 Return End If ' Get the rule number. RuleNumber = RuleTable(Row, Col) Catch Except As Exception ' Modified June 24, 2013 Throw New Exception("No grammar rule found to use. Lookahead " & AdjustString(LookAheadSymbol.Item) & "/" & LookAheadSymbol.Category) End Try End Sub ' Print the contents of the StackInfo item with appropriate indenting. Private Sub Print(ByRef StackInfo As StackInfoClass) Dim k As Integer For k = 1 To StackInfo.NumTabs OutputFileStreamWriter.Write(" ") Next OutputFileStreamWriter.Write(StackInfo.Token.Item) End Sub ' Convert any possible empty string so it can be seen, but leave other strings alone. ' Added June 24, 2013 Private Function AdjustString(ByVal Str As String) As String If (Str.Length = 0) Then Return "" Else Return Str End If End Function ' Process the data and write the results to the output file. ' If tokenize or filter was the operation selected, tokens are grabbed from the program ' data in ProgramArray and written in readable form to the output file. ' If parse was the operation selected, the program data from ProgramArray is parsed (if ' possible) using the rules found in RuleTable and an indented form of the parse tree ' is written to the output file. Modified June 24, 2013 to include more detailed ' error reporting. Private Sub WriteOutputFile() Dim Num As Integer Num = 0 If RadioButtonParse.Checked Then ' Parsing is the operation that was selected. Try Dim S As Stack Dim StartToken As TokenClass Dim StackInfo, NewStackInfo As StackInfoClass Dim RuleNumber, k As Integer CharIsSaved = False ' This line and the next added June 24, 2013. SavedChar = " " S = New Stack(24) StartToken = New TokenClass("PROGRAM", "nonterminal") ' Modified June 2, 2008 StackInfo = New StackInfoClass(StartToken, 0) S.Push(StackInfo) OutputFileStreamWriter = New StreamWriter(TextBoxOutputFile.Text) ChIndex = 0 Token = New TokenClass("", "") ' We will overwrite Token with new info each time we get a new token. NextToken(Num, ChIndex) While (S.Count > 0) StackInfo = S.Pop() Print(StackInfo) If StackInfo.Token.Category = "terminal" Then OutputFileStreamWriter.Write(" ") If Token.Category = "EndMarker" Then ' Cannot match. OutputFileStreamWriter.WriteLine() OutputFileStreamWriter.WriteLine("Parsing failed. End of program file reached. Item popped was " & AdjustString(StackInfo.Token.Item)) Throw New Exception("Parsing failed") ElseIf (Token.Category = "identifier") Or (Token.Category = "number") Then OutputFileStreamWriter.Write(Token.Item) If Token.Category = StackInfo.Token.Item Then NextToken(Num, ChIndex) Else OutputFileStreamWriter.WriteLine() OutputFileStreamWriter.WriteLine("Parsing failed. Program file line " & (Num + 1).ToString & " Item popped was " & AdjustString(StackInfo.Token.Item) & " and does not match lookahead " & AdjustString(Token.Category)) Throw New Exception("Parsing failed") End If ElseIf Token.Item = StackInfo.Token.Item Then NextToken(Num, ChIndex) Else OutputFileStreamWriter.WriteLine() OutputFileStreamWriter.WriteLine("Parsing failed. Program file line " & (Num + 1).ToString & " Item popped was " & AdjustString(StackInfo.Token.Item) & " and does not match lookahead " & AdjustString(Token.Item)) Throw New Exception("Parsing failed") End If OutputFileStreamWriter.WriteLine() Else ' StackInfo.Token.Category is "nonterminal" OutputFileStreamWriter.WriteLine() FindRule(Token, StackInfo.Token.Item, RuleNumber) If RuleNumber = 0 Then OutputFileStreamWriter.WriteLine() OutputFileStreamWriter.WriteLine("Parsing failed, no matching rule. Program file line " & (Num + 1).ToString & " Item popped was " & AdjustString(StackInfo.Token.Item) & " and lookahead was " & AdjustString(Token.Item)) Throw New Exception("Parsing failed") Else ' Push the parts of the rule body in backwards order. For k = Rules(RuleNumber - 1).RuleBodyLength - 1 To 0 Step -1 NewStackInfo = New StackInfoClass(Rules(RuleNumber - 1).RuleBodyArray(k), _ StackInfo.NumTabs + 1) S.Push(NewStackInfo) Next End If End If End While If Token.Category = "EndMarker" Then OutputFileStreamWriter.WriteLine() OutputFileStreamWriter.WriteLine("Parsing succeeded") Else OutputFileStreamWriter.WriteLine() OutputFileStreamWriter.WriteLine("Parsing failed. The stack is empty but we have not reached the end of the program file, now at line " & (Num + 1).ToString) Throw New Exception("Parsing failed") End If Catch Except As Exception Throw New Exception("Error in program file line " & (Num + 1).ToString & ": " & Except.Message) Finally OutputFileStreamWriter.Close() End Try Else ' Tokenize or filter was the selected operation. Try OutputFileStreamWriter = New StreamWriter(TextBoxOutputFile.Text) Token = New TokenClass("", "") ChIndex = 0 Do NextToken(Num, ChIndex) OutputFileStreamWriter.WriteLine(Token.ToString) Loop Until (Token.Category = "EndMarker") Or (Num >= NumLines) Catch Except As Exception Throw New Exception("Error in program file line " & (Num + 1).ToString & ": " & Except.Message) Finally OutputFileStreamWriter.Close() End Try End If End Sub ' Adjust which items on the form are enabled and which are grayed out. Private Sub AdjustForm() LabelMsg.Text = "" If RadioButtonFilter.Checked Then LabelKeywordsFile.Enabled = True TextBoxKeywordsFile.Enabled = True ButtonKeywordsFileOpen.Enabled = True LabelGrammarFile.Enabled = False TextBoxGrammarFile.Enabled = False ButtonGrammarFileOpen.Enabled = False If (TextBoxKeywordsFile.Text = "") Or (TextBoxProgramFile.Text = "") _ Or (TextBoxFSMFile.Text = "") Or (TextBoxOutputFile.Text = "") Then ButtonRun.Enabled = False Else ButtonRun.Enabled = True End If ElseIf RadioButtonTokenize.Checked Then LabelKeywordsFile.Enabled = False TextBoxKeywordsFile.Enabled = False ButtonKeywordsFileOpen.Enabled = False LabelGrammarFile.Enabled = False TextBoxGrammarFile.Enabled = False ButtonGrammarFileOpen.Enabled = False If (TextBoxProgramFile.Text = "") Or (TextBoxFSMFile.Text = "") _ Or (TextBoxOutputFile.Text = "") Then ButtonRun.Enabled = False Else ButtonRun.Enabled = True End If Else ' Radio button for parse is checked. LabelKeywordsFile.Enabled = True TextBoxKeywordsFile.Enabled = True ButtonKeywordsFileOpen.Enabled = True LabelGrammarFile.Enabled = True TextBoxGrammarFile.Enabled = True ButtonGrammarFileOpen.Enabled = True If (TextBoxGrammarFile.Text = "") Or (TextBoxKeywordsFile.Text = "") _ Or (TextBoxProgramFile.Text = "") Or (TextBoxFSMFile.Text = "") _ Or (TextBoxOutputFile.Text = "") Then ButtonRun.Enabled = False Else ButtonRun.Enabled = True End If End If If TextBoxProgramFile.Text = "" Then ButtonProgramFileEdit.Enabled = False Else ButtonProgramFileEdit.Enabled = True End If If TextBoxFSMFile.Text = "" Then ButtonFSMFileEdit.Enabled = False Else ButtonFSMFileEdit.Enabled = True End If If TextBoxOutputFile.Text = "" Then ButtonOutputFileEdit.Enabled = False Else ButtonOutputFileEdit.Enabled = True End If If (TextBoxKeywordsFile.Text = "") Or (RadioButtonTokenize.Checked) Then ButtonKeywordsFileEdit.Enabled = False Else ButtonKeywordsFileEdit.Enabled = True End If If (TextBoxGrammarFile.Text = "") Or (RadioButtonTokenize.Checked) Or (RadioButtonFilter.Checked) Then ButtonGrammarFileEdit.Enabled = False Else ButtonGrammarFileEdit.Enabled = True End If End Sub Private Sub ButtonProgramFileEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonProgramFileEdit.Click LabelMsg.Text = "" System.Diagnostics.Process.Start("Notepad.exe", TextBoxProgramFile.Text) End Sub Private Sub ButtonProgramFileOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonProgramFileOpen.Click LabelMsg.Text = "" If (OpenFileDialogProgram.ShowDialog() = DialogResult.OK) Then TextBoxProgramFile.Text = OpenFileDialogProgram.FileName End If End Sub Private Sub RadioButtonParse_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButtonParse.CheckedChanged AdjustForm() End Sub Private Sub RadioButtonFilter_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButtonFilter.CheckedChanged AdjustForm() End Sub Private Sub RadioButtonTokenize_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButtonTokenize.CheckedChanged AdjustForm() End Sub Private Sub ButtonFSMFileOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonFSMFileOpen.Click LabelMsg.Text = "" If (OpenFileDialogFSM.ShowDialog() = DialogResult.OK) Then TextBoxFSMFile.Text = OpenFileDialogFSM.FileName End If End Sub Private Sub ButtonFSMFileEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonFSMFileEdit.Click LabelMsg.Text = "" System.Diagnostics.Process.Start("Notepad.exe", TextBoxFSMFile.Text) End Sub Private Sub ButtonKeywordsFileOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonKeywordsFileOpen.Click LabelMsg.Text = "" If (OpenFileDialogKeywords.ShowDialog() = DialogResult.OK) Then TextBoxKeywordsFile.Text = OpenFileDialogKeywords.FileName End If End Sub Private Sub ButtonKeywordsFileEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonKeywordsFileEdit.Click LabelMsg.Text = "" System.Diagnostics.Process.Start("Notepad.exe", TextBoxKeywordsFile.Text) End Sub Private Sub ButtonTableFileOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonGrammarFileOpen.Click LabelMsg.Text = "" If (OpenFileDialogTable.ShowDialog() = DialogResult.OK) Then TextBoxGrammarFile.Text = OpenFileDialogTable.FileName End If End Sub Private Sub ButtonTableFileEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonGrammarFileEdit.Click LabelMsg.Text = "" System.Diagnostics.Process.Start("Notepad.exe", TextBoxGrammarFile.Text) End Sub Private Sub ButtonOutputFileOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonOutputFileOpen.Click LabelMsg.Text = "" If (SaveFileDialogOutput.ShowDialog() = DialogResult.OK) Then TextBoxOutputFile.Text = SaveFileDialogOutput.FileName End If End Sub Private Sub ButtonOutputFileEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonOutputFileEdit.Click LabelMsg.Text = "" System.Diagnostics.Process.Start("Notepad.exe", TextBoxOutputFile.Text) End Sub Private Sub TextBoxProgramFile_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBoxProgramFile.TextChanged LabelMsg.Text = "" AdjustForm() End Sub Private Sub TextBoxFSMFile_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBoxFSMFile.TextChanged LabelMsg.Text = "" AdjustForm() End Sub Private Sub TextBoxKeywordsFile_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBoxKeywordsFile.TextChanged LabelMsg.Text = "" AdjustForm() End Sub Private Sub TextBoxTableFile_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBoxGrammarFile.TextChanged LabelMsg.Text = "" AdjustForm() End Sub Private Sub TextBoxOutputFile_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBoxOutputFile.TextChanged LabelMsg.Text = "" AdjustForm() End Sub ' The main action starts when the user clicks on the Run button. This click handler ' for the Run button farms out the work to the appropriate routines. Private Sub ButtonRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRun.Click LabelMsg.Text = "" Try ReadFSMFile() ExtractFSMData() ReadProgramFile() If Not RadioButtonTokenize.Checked Then ReadKeywordsFile() End If If RadioButtonParse.Checked Then ReadGrammarFile() ExtractGrammarData() End If WriteOutputFile() Catch Except As Exception LabelMsg.Text = Except.Message End Try End Sub End Class