Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
hand coded recursive descent parser
|
||||
expr : term ( ( PLUS | MINUS ) term )* ;
|
||||
term : factor ( ( MULT | DIV ) factor )* ;
|
||||
factor : NUMBER | '(' expr ')';
|
||||
*/
|
||||
|
||||
calcLexer := makeCalcLexer()
|
||||
string := "((3+4)*(7*9)+3)+4"
|
||||
tokens := tokenize(string, calcLexer)
|
||||
msgbox % printTokens(tokens)
|
||||
ast := expr()
|
||||
msgbox % printTree(ast)
|
||||
msgbox % expression := evalTree(ast)
|
||||
filedelete expression.ahk
|
||||
fileappend, % "msgbox % " expression, expression.ahk
|
||||
run, expression.ahk
|
||||
return
|
||||
|
||||
|
||||
expr()
|
||||
{
|
||||
global tokens
|
||||
ast := object(1, "expr")
|
||||
if node := term()
|
||||
ast._Insert(node)
|
||||
loop
|
||||
{
|
||||
if peek("PLUS") or peek("MINUS")
|
||||
{
|
||||
op := getsym()
|
||||
newop := object(1, op.type, 2, op.value)
|
||||
node := term()
|
||||
ast._Insert(newop)
|
||||
ast._Insert(node)
|
||||
}
|
||||
Else
|
||||
Break
|
||||
}
|
||||
return ast
|
||||
}
|
||||
|
||||
term()
|
||||
{
|
||||
global tokens
|
||||
tree := object(1, "term")
|
||||
if node := factor()
|
||||
tree._Insert(node)
|
||||
loop
|
||||
{
|
||||
if peek("MULT") or peek("DIV")
|
||||
{
|
||||
op := getsym()
|
||||
newop := object(1, op.type, 2, op.value)
|
||||
node := factor()
|
||||
tree._Insert(newop)
|
||||
tree._Insert(node)
|
||||
}
|
||||
else
|
||||
Break
|
||||
}
|
||||
return tree
|
||||
}
|
||||
|
||||
factor()
|
||||
{
|
||||
global tokens
|
||||
if peek("NUMBER")
|
||||
{
|
||||
token := getsym()
|
||||
tree := object(1, token.type, 2, token.value)
|
||||
return tree
|
||||
}
|
||||
else if peek("OPEN")
|
||||
{
|
||||
getsym()
|
||||
tree := expr()
|
||||
if peek("CLOSE")
|
||||
{
|
||||
getsym()
|
||||
return tree
|
||||
}
|
||||
else
|
||||
error("miss closing parentheses ")
|
||||
}
|
||||
else
|
||||
error("no factor found")
|
||||
}
|
||||
|
||||
peek(type, n=1)
|
||||
{
|
||||
global tokens
|
||||
if (tokens[n, "type"] == type)
|
||||
return 1
|
||||
}
|
||||
|
||||
getsym(n=1)
|
||||
{
|
||||
global tokens
|
||||
return token := tokens._Remove(n)
|
||||
}
|
||||
|
||||
error(msg)
|
||||
{
|
||||
global tokens
|
||||
msgbox % msg " at:`n" printToken(tokens[1])
|
||||
}
|
||||
|
||||
|
||||
printTree(ast)
|
||||
{
|
||||
if !ast
|
||||
return
|
||||
|
||||
n := 0
|
||||
loop
|
||||
{
|
||||
n += 1
|
||||
if !node := ast[n]
|
||||
break
|
||||
if !isobject(node)
|
||||
treeString .= node
|
||||
else
|
||||
treeString .= printTree(node)
|
||||
}
|
||||
return ("(" treeString ")" )
|
||||
}
|
||||
|
||||
evalTree(ast)
|
||||
{
|
||||
if !ast
|
||||
return
|
||||
|
||||
n := 1
|
||||
loop
|
||||
{
|
||||
n += 1
|
||||
if !node := ast[n]
|
||||
break
|
||||
if !isobject(node)
|
||||
treeString .= node
|
||||
else
|
||||
treeString .= evalTree(node)
|
||||
}
|
||||
if (n == 3)
|
||||
return treeString
|
||||
return ("(" treeString ")" )
|
||||
}
|
||||
|
||||
#include calclex.ahk
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
tokenize(string, lexer)
|
||||
{
|
||||
stringo := string ; store original string
|
||||
locationInString := 1
|
||||
size := strlen(string)
|
||||
tokens := object()
|
||||
|
||||
start:
|
||||
Enum := Lexer._NewEnum()
|
||||
While Enum[type, value] ; loop through regular expression lexing rules
|
||||
{
|
||||
if (1 == regexmatch(string, value, tokenValue))
|
||||
{
|
||||
token := object()
|
||||
token.pos := locationInString
|
||||
token.value := tokenValue
|
||||
token.length := strlen(tokenValue)
|
||||
token.type := type
|
||||
tokens._Insert(token)
|
||||
locationInString += token.length
|
||||
string := substr(string, token.length + 1)
|
||||
goto start
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (locationInString < size)
|
||||
msgbox % "unrecognized token at " substr(stringo, locationInstring)
|
||||
return tokens
|
||||
}
|
||||
|
||||
makeCalcLexer()
|
||||
{
|
||||
calcLexer := object()
|
||||
PLUS := "\+"
|
||||
MINUS := "-"
|
||||
MULT := "\*"
|
||||
DIV := "/"
|
||||
OPEN := "\("
|
||||
CLOSE := "\)"
|
||||
NUMBER := "\d+"
|
||||
WS := "[ \t\n]+"
|
||||
END := "\."
|
||||
RULES := "PLUS,MINUS,MULT,DIV,OPEN,CLOSE,NUMBER,WS,END"
|
||||
loop, parse, rules, `,
|
||||
{
|
||||
type := A_LoopField
|
||||
value := %A_LoopField%
|
||||
calcLexer._Insert(type, value)
|
||||
}
|
||||
return calcLexer
|
||||
}
|
||||
|
||||
printTokens(tokens)
|
||||
{
|
||||
loop % tokens._MaxIndex()
|
||||
{
|
||||
tokenString .= printToken(tokens[A_Index]) "`n`n"
|
||||
}
|
||||
return tokenString
|
||||
}
|
||||
|
||||
|
||||
printToken(token)
|
||||
{
|
||||
string := "pos= " token.pos "`nvalue= " token.value "`ntype= " token.type
|
||||
return string
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue