Here is some progress I think. it needs to be cleaned up and i left the multiple expressions as a stub, but it is producing the basic nested tree structure
i have a feeling that from here, rather than trying to emulate a tuple, it may be easier to parse everything into json which could possibly be converted to an agk typed array, and will definitely be easier to work with for further text processing evauluations
// Project: Parser
// Created: 2015-09-14
// set window properties
SetWindowTitle( "Parser" )
SetWindowSize( 1024, 768, 0 )
// set display properties
SetVirtualResolution( 1024, 768 )
SetOrientationAllowed( 1, 1, 1, 1 )
type ParserData
Tokens as TokenData[]
StopAt$
Index
endtype
type TokenData
Typ$
Value$
endtype
type PrevData
firstTyp$
parsed$
endtype
global CharIndex
global TokenIndex
input$ = "foo = 3 + 4;"
Token as TokenData[]
Token=Lexer(input$)
for i = 0 to Token.length
message(Token[i].Typ$+", "+Token[i].Value$)
next i
message("Parsed: " + Parse(Token))
end
function Parse(Tokens ref as TokenData[])
parser as ParserData
parser.Tokens = Tokens
parser.StopAt$ = ";"
parsedData as PrevData
for i = 0 to Tokens.length
prevNone as PrevData
parsedData = NextExpression(parser, prevNone)
if parsedData.parsed$ > ""
exitfunction parsedData.parsed$
endif
next i
endfunction parsedData.parsed$
function NextExpression(parser ref as ParserData, prev as PrevData)
nxt as PrevData
prevNone as PrevData
nextToken as TokenData
nextToken = parser.Tokens[parser.Index]
if nextToken.Typ$ = parser.StopAt$
exitfunction prev
endif
inc parser.Index
if (nextToken.Typ$ = "number" or nextToken.Typ$ = "string" or nextToken.Typ$ = "symbol") and prev.firstTyp$ = ""
prev.firstTyp$ = nextToken.Typ$
prev.parsed$ = "(" + nextToken.Typ$ + "," + nextToken.Value$ + ")"
exitfunction NextExpression(parser, prev)
elseif nextToken.Typ$ = "operation"
nxt = NextExpression(parser, prevNone)
prev.parsed$ = "(operation," + nextToken.Value$ + "," + prev.parsed$ + "," + nxt.parsed$ + ")"
exitfunction NextExpression(parser, prev)
elseif nextToken.Typ$ = "("
elseif nextToken.Typ$ = "{"
elseif nextToken.Typ$ = "="
if prev.firstTyp$ <> "symbol"
Message("You can only assign to a symbol.")
endif
nxt = NextExpression(parser, prevNone)
prev.parsed$ = "(assignment," + prev.parsed$ + "," + nxt.parsed$ + ")"
exitfunction NextExpression(parser, prev)
else
Message("unexpected token " + nextToken.Typ$ + "," + nextToken.Value$)
endif
endfunction prev
function MultyExpression(Parser ref as ParserData, sep$, end$)
/*
Result as TokenData
if(Parser.Tokens[Parser.Index].Typ$=";") then message("Reached the end!")
typ$=Parser.Tokens[Parser.Index+1].Typ$
if (Typ$=end$)
Parser.Index=Parser.Index+1
else
ArgParser as ParserData
ArgParser.Tokens=Parser.Tokens //<- ???
endif
*/
endfunction
function Lexer(Chars$)
result as TokenData[]
yield as TokenData
while (mid(Chars$,CharIndex+1,1)<>"" and CharIndex<len(Chars$))
CharIndex=CharIndex+1
c$=mid(Chars$,CharIndex,1)
if FindString(" "+chr(10),c$)>0
continue
elseif FindString("+-*/",c$)>0
yield.Typ$="operation"
yield.Value$=c$
elseif FindString("(){},;=:",c$)>0
yield.Typ$=c$
yield.Value$=c$
elseif FindString("'"+chr(34),c$)>0
yield.Typ$="string"
yield.Value$=ScanString(c$,Chars$)
elseif FindString(".0123456789",c$)>0
yield.Typ$="number"
yield.Value$=Scan(c$,Chars$,".0123456789")
elseif FindString("ABCDEFGHIJKLMNOPQRST",Upper(c$))>0
yield.Typ$="symbol"
yield.Value$=Scan(c$,Chars$,"abcdefghijklmnopqrstABCDEFGHIJKLMNOPQRST0123456789")
else
message("Error: 1")
endif
result.insert(yield)
endwhile
endfunction result
function Scan(First$,Chars$,Allowed$)
result$ = First$
p$=mid(Chars$,CharIndex+1,1)
while (p$<>"" and FindString(Allowed$,p$)>0)
CharIndex=CharIndex+1
c$=mid(Chars$,CharIndex,1)
result$=result$+c$
p$=mid(Chars$,CharIndex+1,1)
endwhile
endfunction result$
function ScanString(Delim$,Chars$)
result$ = ""
while (mid(Chars$,CharIndex+1,1)<>Delim$)
CharIndex=CharIndex+1
c$=mid(Chars$,CharIndex,1)
if c$=""
message("Error: 2")
exitfunction ""
endif
result$=result$+c$
endwhile
CharIndex=CharIndex+1
endfunction result$
//~ type KeyData
//~ Typ
//~ Position
//~ Length
//~ endtype
//~
//~
//~
//~ KeyList as KeyData[]
//~
//~
//~ String$=ReadFile("Code.txt")
//~
//~ message(ParserNext(String$))
//~
//~ do
//~
//~
//~ Print( ScreenFPS() )
//~ Sync()
//~ loop
//~
//~ function ReadFile(File$)
//~ FileID=opentoread(File$)
//~ String$=ReadString(FileID)
//~ closefile(FileID)
//~ endfunction String$
//~
//~ function ParserInit()
//~ global ParsePosition
//~ global ParseLine
//~ global ParseCol
//~
//~ ParsePosition=0
//~ ParseLine=1
//~ ParseCol=0
//~ endfunction
//~
//~
//~ function ParserIsKeyword(String$,Key$)
//~ if FindString(String$,Key$,1,1)>=0 then exitfunction 1
//~ endfunction 0
//~
//~ function ParserIsDigit(Char$)
//~ if FindString("0123456789",Char$,1,1)>=0 then exitfunction 1
//~ endfunction 0
//~
//~ function ParserIsIdStart(Char$)
//~ if FindString("abcdefghijklmnopqrstuvwxyz",Char$,0,1)>=0 then exitfunction 1
//~ endfunction 0
//~
//~ function ParserIsId(Char$)
//~ if ParserIsIdStart(Char$) or FindString("?!-<>=0123456789",Char$,1,1)>=0 then exitfunction 1
//~ endfunction 0
//~
//~ function ParserIsOpChar(Char$)
//~ if FindString("+-*/%=&|<>!",Char$,1,1)>=0 then exitfunction 1
//~ endfunction 0
//~
//~ function ParserIsPunc(Char$)
//~ if FindString(",;(){}[]",Char$,1,1)>=0 then exitfunction 1
//~ endfunction 0
//~
//~ function ParserIsWhitespace(Char$)
//~ if Char$=" " then exitfunction 1
//~ endfunction 0
//~
//~ function ParserReadWhile(String$)
//~ local TempString$
//~ TempString$=""
//~ while not ParseEOF(String$) and ParserPeek(String$)<>""
//~ TempString$=TempString$+ParseNext(String$)
//~ endwhile
//~ endfunction TempString$
//~
//~
//~ function ParseReadNumber(String$)
//~ -----------------------------------------------http://lisperator.net/pltut/parser/token-stream
//~ has_dot = 0
//~ while(digit)
//~ if (ch == ".")
//~ if (has_dot) then exitfunction 0
//~ has_dot = true;
//~ exitfunction 1
//~ endif
//~ digit = ParserIsDigit(ch)
//~ endwhile
//~
//~
//~ return { type: "num", value: parseFloat(number) };
//~ endfunction
//~
//~
//~ function ParserNext(String$)
//~ ParsePosition=ParsePosition+1
//~ local Char$
//~ Char$=Mid(String$,ParsePosition,1)
//~ if Char$=""
//~ ParseLine=ParseLine+1
//~ ParseCol=0
//~ else
//~ ParseCol=ParseCol+1
//~ endif
//~ endfunction Char$
//~
//~ function ParserPeek(String$)
//~ local Char$
//~ Char$=Mid(String$,ParsePosition,1)
//~ endfunction Char$
//~
//~ function ParserEOF(String$)
//~ if ParserPeek(String$)="" then exitfunction 1
//~ endfunction 0
//~
//~ function ParserCroak(Message$)
//~ message(Message$+" ("+str(ParseLine)+":"+str(ParseCol)+")")
//~ endfunction 0
//~
//~ function ParserReadNext()
//~ read_while(is_whitespace);
//~ if (input.eof()) return 0;
//~ var ch = input.peek();
//~ if (ch == "#") {
//~ skip_comment();
//~ return read_next();
//~ }
//~ if (ch == '"') return read_string();
//~ if (is_digit(ch)) return read_number();
//~ if (is_id_start(ch)) return read_ident();
//~ if (is_punc(ch)) return {
//~ type : "punc",
//~ value : input.next()
//~ };
//~ if (is_op_char(ch)) return {
//~ type : "op",
//~ value : read_while(is_op_char)
//~ };
//~ input.croak("Can't handle character: " + ch);
//~ endfunction 0
http://games.joshkirklin.com/sulium
A single player RPG featuring a branching, player driven storyline of meaningful choices and multiple endings alongside challenging active combat and intelligent AI.