My practicle adaptation of previous code.
func_tokenizer.bb :
TEST:
func_tokenizer.bb :
; Author: Steve Hill ; Date: 2003-08-27 13:41:23 ; Title: Blitz Lexical Analyser ; Description: Blitz functions to split a Blitz source file into tokens ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; OpenState(file$,mode) - creates a new TState ; GetToken(state) - read the next token ; CloseState() - destroys and closes the current state ; ; The current token is available in state\tok$ ; ; Versions ; 0.1 Initial version 27 Aug 2003 ; 0.2 Added >< => =< 29 Aug 2003 ; 0.3 Added "mode" select 16 Apr 2007 by _33 ; REPLACED "tok" by "token" (this is not Tokamak) 16 Apr 2007 by _33 ; 0.4 Removed PRINTs and ENDs which made this unusable 16 Apr 2007 by _33 ; Added some error management "ok flag" 16 Apr 2007 by _33 ; ; FUTURE RELEASE: -Add function to return FLOAT, INT, and STRING ; -More cleanup, optimize, expand on concept ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Const SPACE = 32 Const TAB = 9 Const CR = 13 Const LF = 10 Global WHITE_SPACE$ = Chr$(SPACE) + Chr$(TAB) + Chr$(CR) Const ALPHA$ = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" Const DIGITS$ = "0123456789" Const HEXDIGITS$ = "0123456789abcdefABCDEF" Const BINDIGITS$ = "01" Const DELIM$ = "^*+-~<>/\#%.$()[],=\:?!" Global QUOTE$ = Chr$(34) Global ALPHANUM$ = ALPHA$ + DIGITS$ ; TState ; ; Keeps track of the current file, look-ahead character and token. ; Can be used as a stack for include files. ; Type TState Field file Field mode Field ch$ Field token$ Field tokenType Field lineNum ; Field charNum Field content$ ;v0.3 Field content_len% ;v0.3 Field ch_pos ;v0.3 End Type Const TOKEN_WORD = 0 Const TOKEN_OPERATOR = 1 Const TOKEN_COMMENT = 2 Const TOKEN_DEC_NUMBER = 3 Const TOKEN_HEX_NUMBER = 4 Const TOKEN_BIN_NUMBER = 5 Const TOKEN_STRING = 6 Const TOKEN_EOL = 7 Const TOKEN_EOF = 8 Const TOKEN_UNKNOWN = 9 ; TDescriptor ; ; Describes a function: name, return type and parameter type list. ; Assigned unique id for each functions ... its "pointer" ; Type TDescriptor Field name$ Field typ$ Field params$ Field id End Type ; OpenState ; ; Open the file initialise the fields ; 1 = file, 2 = inline tokenize Function OpenState(fi$,mode) state.TState = New TState state\mode = mode state\ch_pos = 0 If state\mode = 1 Then state\file = ReadFile(fi$) If state\file = 0 Then Return 0 EndIf ElseIf state\mode = 2 state\content$ = fi$ EndIf state\lineNum = 1 state\ch$ = "" state\token$ = "" Return GetToken(state) End Function ; CloseState ; ; Close current file, pop state ; Function CloseState() For state.TState = Each TState If state\mode = 1 Then CloseFile(state\file) Next Delete Each TState End Function ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; LEXICAL FUNCTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GetChar ; ; Read a character from the current file into the state ; Function GetChar(state.TState) If state\ch$ = Chr$(LF) Then state\lineNum = state\LineNum + 1 : state\ch_pos = 0 If state\mode = 1 Then If Eof(state\file) Then state\ch$ = "" : Return state\ch$ = Chr$(ReadByte(state\file)) Else state\ch_pos = state\ch_pos + 1 state\ch$ = Mid$(state\content$,state\ch_pos,1) EndIf ;morel End Function ; SkipSpace ; ; Skip white space ; Function SkipSpace(state.TState) While Instr(WHITE_SPACE$, state\ch$) <> 0 GetChar(state) If state\ch$ = "" Return Wend End Function ; GetFollowing ; ; Generic token reader, reads while characters are ; those in pat. Places token in state. ; Function GetFollowing(state.TState, pat$) token$ = state\ch$ GetChar(state) While Instr(pat$, state\ch$) <> 0 If state\ch$ = "" Exit token$ = token$ + state\ch$ GetChar(state) Wend state\token$ = token$ End Function ; GetDecNumber ; ; eg. 1 or 1.2 Function GetDecNumber$(state.TState) GetFollowing(state, DIGITS$ + ".") state\tokenType = TOKEN_DEC_NUMBER End Function ; GetBinNumber ; ; eg. %1100 Function GetBinNumber$(state.TState) GetFollowing(state, BINDIGITS$) state\tokenType = TOKEN_BIN_NUMBER End Function ; GetHexNumber ; ; eg. $abC1 Function GetHexNumber$(state.TState) GetFollowing(state, HEXDIGITS$) If state\token$ = "$" state\tokenType = TOKEN_OPERATOR Else state\tokenType = TOKEN_HEX_NUMBER EndIf End Function ; GetEOL ; ; Get end of line Function GetEOL(state.TState) state\token$ = state\ch$ GetChar(state) state\tokenType = TOKEN_EOL End Function ; GetWord ; ; eg. myVar_2 or WaitKey Function GetWord(state.TState) GetFollowing(state, ALPHANUM$ + "_") If state\token$ = "Or" Or state\token$ = "And" Or state\token$ = "Xor" Then state\tokenType = TOKEN_OPERATOR Else state\tokenType = TOKEN_WORD EndIf End Function Function GetOperator(state.TState) t$ = state\ch$ GetChar(state) r$ = t$ Select t$ Case ">" t$ = state\ch$ Select t$ Case "=" r$ = ">=" GetChar(state) Case "<" r$ = "><" GetChar(state) Default r$ = ">" End Select Case "<" t$ = state\ch$ Select t$ Case "=" r$ = "<=" GetChar(state) Case ">" r$ = "<>" GetChar(state) Default r$ = "<" End Select Case "=" t$ = state\ch$ Select t$ Case ">" r$ = "=>" GetChar(state) Case "<" r$ = "=<" GetChar(state) Default r$ = "=" End Select End Select state\token$ = r$ state\tokenType = TOKEN_OPERATOR End Function Function GetComment(state.TState) token$ = state\ch$ GetChar(state) While state\ch$ <> Chr$(LF) If state\ch$ = "" Exit If state\ch$ <> Chr$(CR) token$ = token$ + state\ch$ EndIf GetChar(state) Wend state\token$ = token$ state\tokenType = TOKEN_COMMENT End Function Function GetString(state.TState) state\token$ = "" GetChar(state) While state\ch$ <> QUOTE$ And state\ch$ <> "" state\token$ = state\token$ + state\ch$ GetChar(state) Wend If state\ch$ <> "" GetChar(state) EndIf state\tokenType = TOKEN_STRING End Function Function GetUnrecognized(state.TState) state\token$ = state\ch$ state\tokenType = TOKEN_UNKNOWN GetChar(state) End Function ; GetToken ; ; Use first character to determine type of token and then ; read appropriate token using the corresponding Get function Function GetToken%(state.TState) SkipSpace(state) ch$ = state\ch$ If ch$ = "" Then state\token$ = "" state\tokenType = TOKEN_EOF Return 1 EndIf If Instr(DIGITS$, ch$) <> 0 Then GetDecNumber$(state) ElseIf Instr(ALPHA$, ch$) <> 0 Then GetWord(state) ElseIf ch$ = ";" Then GetComment(state) ElseIf ch$ = QUOTE$ Then GetString(state) ElseIf ch$ = "%" Then GetBinNumber(state) ElseIf ch$ = "$" Then GetHexNumber(state) ElseIf Instr(DELIM$, ch$) <> 0 Then GetOperator(state) ElseIf ch$ = Chr$(LF) GetEOL(state) Else GetUnrecognized(state) EndIf Return 1 End Function
TEST:
Graphics 1024,768,32,2 Include "func_tokenizer.bb" mode = Input$("type 1 to read from file, 2 to enter your own test: ") inFile$ = Input$("Input file: ") While inFile$ <>"" Print "" Print "Parsing " + inFile$ ok = OpenState(inFile$, mode) state.TState = Last TState While ok Color 0,255,0 Select state\tokenType Case TOKEN_WORD Write "W" : Color 0,255,255 : Write state\token$ Case TOKEN_OPERATOR Write "O" : Color 0,255,255 : Write state\token$ Case TOKEN_COMMENT Write "C" : Color 0,255,255 : Write state\token$ Case TOKEN_DEC_NUMBER Write "D" : Color 0,255,255 : Write state\token$ Case TOKEN_HEX_NUMBER Write "H" : Color 0,255,255 : Write state\token$ Case TOKEN_BIN_NUMBER Write "B" : Color 0,255,255 : Write state\token$ Case TOKEN_STRING Write "S" : Color 255,255,255 : Write state\token$ Case TOKEN_EOL Color 255,255,0 : Write "EOL" : Print "" Case TOKEN_EOF Color 255,0,255 : Write "EOF" : Print "" : ok = 0 Case TOKEN_UNKNOWN Color 255,0,0 : Write "U" End Select If ok Then ok = GetToken(state) If KeyHit(1) Then ok = 0 Wend CloseState() Color 255,255,255 inFile$ = Input$("Input file: ") Wend End