Bugala wrote: ↑Thu Sep 26, 2019 9:40 am
@jalih, yes I would like to take a look at that. Maybe I can use parts of it for my own parser.
Below is a small example on how to use scanner and parser helper module. Notice that when you define keywords and keysyms, "" and #idsym must be at the last index.
@INCLUDE "./parser/parser.hws"
; Define some keysym constants
Const #printstr = 100
Const #addsym = 101
Const #endsym = 102
; New Parser object that we will be extending
Script = Parser:new()
Function Script:printstr_stmt()
self:getsym()
self:expect(#lparen)
self:expect(#litstrsym)
DebugPrint(self:litstr())
self:expect(#rparen)
EndFunction
Function Script:add_stmt()
self:getsym()
self:expect(#lparen)
self:expect(#numbersym)
Local a = self:val()
self:expect(#comma)
self:expect(#numbersym)
Local b = self:val()
self:expect(#rparen)
DebugPrint(a+b)
EndFunction
Function Script:stmt()
Switch(self:sym())
Case #idsym:
Error("line: " ..self:line() .." column: " ..self:col() ..", unknown command.")
Case #printstr:
self:printstr_stmt()
Case #addsym:
self:add_stmt()
EndSwitch
EndFunction
Function Script:cmpndstmt()
Repeat
self:stmt()
If self:accept(#endsym) Then Break
If self:accept(#eofsym) Then Error("line: " ..self:line() .." column: " ..self:col() ..", missing end statement.")
Forever
EndFunction
Function Script:run(fn)
; Define some keywords
Local keywords = {}
keywords[0] = "printstr"
keywords[1] = "add"
keywords[2] = "end"
keywords[3] = "" ; This must be the last item
; Define some keywords
Local keysyms = {}
keysyms[0] = #printstr
keysyms[1] = #addsym
keysyms[2] = #endsym
keysyms[3] = #idsym ; This must be the last item
self:begin(fn, keywords, keysyms) ; Start parsing
self:cmpndstmt()
self:end() ; End parsing
EndFunction
Script:run("test.txt")
Almost forgot to comment back. Yes I took a look at your code and it was useful look. I decided to take for my current script system a different approach, mainly because in your script system there was need to having defined each command as keywords for it to recognise them, and this was problematic for the GOTO idea I was having, since I want to be able to define places in way of "MAIN:" where I can jumpto, and that would mean that I would need to define each place in those keywords before I can use them, which isnt suitable.
Anyway, I am basically going to be making two different parsers for two different kind of scripts, and I dont think the approach I am taking for the first one will solve the problems I am having with the second one, and when I get to there, at least currently I am very much thinking of using your parser as the basis for the second one.
For the second one probably needs to use something like IF-ELSE, or SWITCH, or even calculations. I very much liked that in your parser you were even able to make calculations with it, and + etc. were separately recognised.
Bugala wrote: ↑Sat Sep 28, 2019 9:01 am
Yes I took a look at your code and it was useful look. I decided to take for my current script system a different approach, mainly because in your script system there was need to having defined each command as keywords for it to recognise them, and this was problematic for the GOTO idea I was having, since I want to be able to define places in way of "MAIN:" where I can jumpto, and that would mean that I would need to define each place in those keywords before I can use them, which isnt suitable.
Keywords need to be defined, but naturally parser and it's scanner can handle labels and variable definitions too. That is what #idsym keysym is really for and scanner returns it, if it encounters unknown undefined keyword. You can use Parser objects id() method to get that scanned word.
If you want to support variables and labels with your script then more work is needed, you need to implement symbol table.