Skip to content

Instantly share code, notes, and snippets.

@GWRon
Created September 19, 2021 12:27
Show Gist options
  • Save GWRon/681d58b710c6fecaebfb2a6e97ad5d8d to your computer and use it in GitHub Desktop.
Save GWRon/681d58b710c6fecaebfb2a6e97ad5d8d to your computer and use it in GitHub Desktop.
SuperStrict
Framework Brl.StandardIO
Import Pub.FreeProcess
Import MaxGUI.Drivers
Import Brl.EventQueue
Import Brl.Bank
Import "lexer/Lexer.bmx"
Import "parser/Parser.bmx"
New TApp.Run()
Type TApp
Field guiWindow:TGadget
Field guiTreeview:TGadget
Field guiTreeviewRoot:TGadget
Field guiTextarea:TGadget
Field codeLineStartIndices:int[]
Field codeLineEndIndices:int[]
Field codeContent:String
Method InitGUI()
guiWindow:TGadget = CreateWindow("TreeVisualizer", 100, 100, 800, 400, Null) ', WINDOW_TITLEBAR | WINDOW_STATUS)
guiTextarea = CreateTextArea(0, 0, ClientWidth(guiWindow) / 2 - 5,ClientHeight(guiWindow), guiWindow, TEXTAREA_READONLY)
'pin to corners
SetGadgetLayout(guiTextArea, EDGE_ALIGNED, EDGE_RELATIVE, EDGE_ALIGNED, EDGE_ALIGNED)
guiTreeview:TGadget = CreateTreeView(ClientWidth(guiWindow) / 2 + 5, 0, ClientWidth(guiWindow) / 2 - 5, ClientHeight(guiWindow), guiWindow)
'pin to corners
SetGadgetLayout(guiTreeview, EDGE_RELATIVE, EDGE_ALIGNED, EDGE_ALIGNED, EDGE_ALIGNED)
guiTreeviewRoot = TreeViewRoot(guiTreeview)
End Method
Method ProcessFile:String(uri:String)
Local fileURI:String = CurrentDir() + "/" + uri
codeContent = LoadFileContent(fileURI)
'cache line start/ending (so also length) information
Local lines:String[] = codeContent.Split("~n")
codeLineStartIndices = new Int[lines.length]
codeLineEndIndices = new Int[lines.length]
Local lastIndex:int = 0
for local i:int = 0 until lines.length
codeLineStartIndices[i] = lastIndex
codeLineEndIndices[i] = lastIndex + lines[i].length + 1 'add back newline
lastIndex = codeLineEndIndices[i]
'print "line "+i+" = " + codeLineStartIndices[i] +" - " + codeLineEndIndices[i] + " = ~q" + codeContent[codeLineStartIndices[i] .. codeLineEndIndices[i]] +"~q"
Next
SetTextAreaText( guiTextArea, codeContent, 0, TEXTAREA_ALL, TEXTAREA_CHARS)
Local parser:IParser = New TParser(New TLexer(fileURI))
Local x:ISyntax = parser.ParseCompilationUnit()
'handle errors
'rem
For Local error:TParseError = EachIn parser.Errors()
Print "PARSE ERROR: " + error.ToString()
Notify "PARSE ERROR: " + error.ToString()
Next
'endrem
AppendNode(x, True, guiTreeviewRoot)
Function AppendNode(o:Object, showMinorFields:Int, parentNode:TGadget, prependText:String = "")
Local t:TTypeId = TTypeId.ForObject(o)
If Not o
Return
ElseIf ISyntax(o)
Local syntax:ISyntax = ISyntax(o)
Local codeRange:SCodeRange = ISyntax(o).CodeRange()
Local lineInfo:String = " ["+codeRange.startLocation.line+":"+codeRange.startLocation.column+"]"
Local label:String = t.Name()
if prependText then label = prependText + ": " + label + lineInfo
Local node:TGadget = AddTreeViewNode(label, parentNode, -1, o)
For Local f:TField = EachIn GetAllFields(t)
If Not showMinorFields And f.MetaData("minor") Then Continue
Local fValue:Object = f.Get(syntax)
AppendNode(fValue, showMinorFields, node, f.Name())
Next
ElseIf t.ExtendsType(ArrayTypeId)
If t.Name() = "Null[]" Then Return
'1) fieldname:typename[] ?
'Local label:String = t.Name()
'if prependText then label = prependText + ": " + label
'2) fieldname
Local label:String = prependText
Local node:TGadget = AddTreeViewNode(label, parentNode, -1, o)
For Local i:Int = 0 Until t.ArrayLength(o)
AppendNode(t.GetArrayElement(o, i), showMinorFields, node)
Next
ElseIf TSyntaxToken(o)
Local codeRange:SCodeRange = TSyntaxToken(o).lexerToken.CodeRange()
Local lineInfo:String = " ["+codeRange.startLocation.line+":"+codeRange.startLocation.column+"]"
AddTreeViewNode(o.ToString() + lineInfo, parentNode, -1, o)
Else
AddTreeViewNode(o.ToString(), parentNode, -1, o)
End If
End Function
End Method
Function LoadFileContent:String(url:Object)
'source: http://sodaware.sdf.org/blog/blitzmax-file-loading/
'ensure finishing with 0 byte
Local bank:TBank = LoadBank(url)
bank.Resize(bank.size() + 1)
PokeByte(bank, bank.size() - 1, 0)
Local buffer:Byte Ptr = LockBank(bank)
Local content:String = String.FromCString(buffer)
UnlockBank(bank)
Return content
End Function
Method OnClickTreeView()
If Not guiTreeview.SelectedNode() Then Return
local syntaxOrToken:ISyntaxOrSyntaxToken = ISyntaxOrSyntaxToken(guiTreeview.SelectedNode().extra)
if not syntaxOrToken Then Return
Local codeRange:SCodeRange = syntaxOrToken.CodeRange()
if not codeRange.IsValid() Then Return
Local startIndex:Int = codeLineStartIndices[codeRange.startLocation.line - 1] + (codeRange.startLocation.column - 1)
Local endIndex:Int = codeLineStartIndices[codeRange.endLocation.line - 1] + (codeRange.endLocation.column - 1)
print "code " + startIndex + " - " + endIndex + " ["+codeRange.startLocation.line+":"+codeRange.startLocation.column+"] - ["+codeRange.endLocation.line+":"+codeRange.endLocation.column+"]" + " = ~q" + codeContent[startIndex .. endIndex] +"~q"
'select
guiTextArea.SetSelection(startIndex, endIndex - startIndex, TEXTAREA_CHARS)
End Method
Method Run()
InitGUI()
ProcessFile("samples/test.bmx")
Repeat
Select WaitEvent()
Case EVENT_APPTERMINATE, EVENT_WINDOWCLOSE
End
Case EVENT_GADGETSELECT
'select something on tree view
if EventSource() = guiTreeview
OnClickTreeView()
endif
Case EVENT_GADGETACTION
'double click on tree view
'if EventSource() = guiTreeview
' OnClickTreeView()
'endif
EndSelect
Forever
End Method
End Type
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment