diff --git a/Project.toml b/Project.toml index c314b2c..f8ed7f7 100644 --- a/Project.toml +++ b/Project.toml @@ -2,3 +2,6 @@ name = "TComp" uuid = "b858fc1c-1812-4b3c-a2e6-a1a64b2d44f1" authors = ["Tan Kian-ting "] version = "0.1.0" + +[deps] +Match = "7eb4fadd-790c-5f42-8a69-bfa0b872bfbf" \ No newline at end of file diff --git a/src/TComp.jl b/src/TComp.jl index 6845b58..a719774 100644 --- a/src/TComp.jl +++ b/src/TComp.jl @@ -1,7 +1,75 @@ module TComp include("./parser.jl") using .Parser +using Match + + +inp = ARGS +f = open(ARGS[1], "r") +prog = read(f, String) + +print(prog) +parsed = Parser.totalParse(prog) +print(parsed) +tmp_var_no = 0 + + + +# Pass 1 duplicated varname unified +function unifyVar(parsed, env) + @match parsed begin + # letrec is not considered + #[("%let", "id"), [ty, var], val, [("%lambda", "id"), args, body]] => nothing + + [("%let", "id"), [ty, var], val, body] => + begin + envNew = env + push!(envNew, var[1]) # push x of var = ("x", "id") in newEnv + res = [("%let", "id"), + [ty, unifyVar(var, envNew)], + unifyVar(val, env), + unifyVar(body, envNew)] + return res + end + (var, "id") => + begin + reversedEnv = reverse(env) + index = length(env) - findfirst(e -> e == var, reversedEnv) + 1 + return (index, "id") + end + [(plus, "plus"), lhs, rhs] => + begin + lhs_new = unifyVar(lhs, env) + rhs_new = unifyVar(rhs, env) + return [(plus, "plus"), lhs_new, rhs_new] + + end + [(minus, "minus"), lhs, rhs] => + begin + lhs_new = unifyVar(lhs, env) + rhs_new = unifyVar(rhs, env) + return [(minus, "minus"), lhs_new, rhs_new] + + end + [("%call", "id"), callee, args...] => + begin + unifiedCallee = unifyVar(callee, env) + unifiedArgs = map(x ->unifyVar(x, env), args[1]) + + return vcat([("%call", "id"), unifiedCallee], [unifiedArgs]) + end + (c, "int") => return parsed + _ => "Error" + end +end + +emptyEnv = [] +res = unifyVar(parsed, emptyEnv) +print(res) + + +close(f) + -greet() = print("Hello World!") end # module diff --git a/src/parser.jl b/src/parser.jl index 2c2f19d..488ae7e 100644 --- a/src/parser.jl +++ b/src/parser.jl @@ -90,10 +90,11 @@ patternList = [("int", "\\d+"), ("lParen", "[\\(]"), ("rParen", "[\\)]"), ("plus", "[+]"), + ("funType", "[-][\\>]"), ("minus", "[\\-]"), ("mul", "[\\*]"), ("div", "[\\/]"), - ("sp", "\\s+"), + ("sp", "[\\n\\r ]+"), ("comma", "[,]"), ("semicolon", "[;]"), ("lambda", "[=][\\>]"), @@ -112,21 +113,15 @@ matchEachItem = Regex(tmp) matchAll = "^(" * tmp * ")+\$" matchEntirely = Regex(matchAll) -print(matchEntirely) +#println(matchEntirely) +""" +((int -> int) -> int) + add = (x , y) => x + y; -inp = """ -((a, b, c)=>(d=>e)) add = add; -int a = 8; -12 + foo(13*a,14,15) """ - -print("~~~\n") -isEntirelyMatched = match(matchEntirely, inp) - -if isEntirelyMatched == false - print("illegal tokens contained.") - -end + int a = 8; +12 + foo(13*a,14,15) +""" function prettyString(ele) @@ -146,66 +141,112 @@ function prettyString(ele) else #number return string(ele) end - end -mI = eachmatch(matchEachItem, inp) +function prettyStringLisp(ele) + if isa(ele, String) + return ele + elseif isa(ele, Tuple) + res = prettyStringLisp(ele[1]) + return res + elseif isa(ele, Array) + mappedEle = map(prettyStringLisp, ele) + mappedString = "(" * join(mappedEle, " ") * ")" + return mappedString + elseif isa(ele, ParserResult) + res = prettyStringLisp(ele.matched) + return res + else #number + return string(ele) + end +end + + + function processKeys(x) keys_ = keys(x) return filter((i) -> x[i] != nothing, keys_)[1] end -matchedList = map((x)->x.match, collect(mI)) - -groupNameList = map(processKeys, collect(mI)) - -zippedTokenList = collect(zip(matchedList, groupNameList)) - -print(zippedTokenList) - -withoutSpaces = filter((x)-> x[2] != "sp", zippedTokenList) -initWrapped = ParserResult([], withoutSpaces) -test1 = initWrapped >> strng("123") >> (strng("+")|strng("-")) -test2 = initWrapped >> seq([strng("123"), strng("+")]) -println(prettyString(test1)) -println(prettyString(test2)) +#test1 = initWrapped >> strng("123") >> (strng("+")|strng("-")) +#test2 = initWrapped >> seq([strng("123"), strng("+")]) + +#println(prettyString(test1)) +#println(prettyString(test2)) """ atom = int | id -unit = "(" unit ")" | atom +func = "(" fn_args ")" "=>" body +unit = func | "(" exp ")" | atom args = unit ("," unit)* factor = unit "(" args ")" term = (factor (*|/) factor) | factor exp = (term (+|-) term) | term -tyOfArgs = ty ("," ty)* -tyOfFn = "(" ty => ty ")" -ty = id | tyOfFn | "(" tyOfArgs ")" - letexp = ty id "=" exp ";" body body = exp | letexp """ atom = typ("int") | typ("id") -function longUnitAux(input) - rawFunc = seq([typ("lParen"), unit, typ("rParen")]) + +function fnArgItemAux(input) + rawFunc = seq([typ("comma"), typ("id")]) rawRes = rawFunc.fun(input) if rawRes != nothing matched = rawRes.matched[2] res = ParserResult(matched, rawRes.remained) return res else - return rawRes + return nothing + end +end +fnArgItem = Psr(fnArgItemAux) + +function fnArgsAux(input) + rawFunc = seq([typ("id"), many0(fnArgItem)]) + res = rawFunc.fun(input) + if res != nothing + matched = vcat([res.matched[1]], res.matched[2]) + res = ParserResult(matched, res.remained) + return res + else + return nothing + end +end +fnArgs = Psr(fnArgsAux) + +function funcAux(input) + rawFunc = seq([typ("lParen"), fnArgs, typ("rParen"), typ("lambda"), body]) + rawRes = rawFunc.fun(input) + if rawRes != nothing + matched = [("%lambda", "id"), rawRes.matched[2], rawRes.matched[5]] + res = ParserResult(matched, rawRes.remained) + return res + else + return nothing + end +end + +function longUnitAux(input) + rawFunc = seq([typ("lParen"), exp, typ("rParen")]) + rawRes = rawFunc.fun(input) + if rawRes != nothing + matched = rawRes.matched[2] + res = ParserResult(matched, rawRes.remained) + return res + else + return nothing end end function unitAux(input) + fun = Psr(funcAux) longUnit = Psr(longUnitAux) - rawFunc = longUnit | atom + rawFunc = fun | longUnit | atom res = rawFunc.fun(input) return res end @@ -220,7 +261,7 @@ function argItemAux(input) res = ParserResult(matched, rawRes.remained) return res else - return rawRes + return nothing end end argItem = Psr(argItemAux) @@ -245,7 +286,7 @@ function longFactorAux(input) res = ParserResult(matched, rawRes.remained) return res else - return rawRes + return nothing end end @@ -266,7 +307,7 @@ function longTermAux(input) res = ParserResult(matched, rawRes.remained) return res else - return rawRes + return nothing end end @@ -288,7 +329,7 @@ function longExpAux(input) res = ParserResult(matched, rawRes.remained) return res else - return rawRes + return nothing end end @@ -302,48 +343,62 @@ exp = Psr(expAux) """tyOfArgs = "(" ty ("," ty)* ")" -tyOfFn = "(" ty => ty ")" -ty = id | tyOfFn | tyOfArgs """ +tyHead = tyOfArgs | tyOfFn | id +tyOfFn = "(" tyHead -> ty ")" +ty = id | tyOfFn """ function tyArgItemAux(input) - rawFunc = seq([typ("comma"), typ("id")]) + rawFunc = seq([typ("comma"), ty]) rawRes = rawFunc.fun(input) if rawRes != nothing matched = rawRes.matched[2] res = ParserResult(matched, rawRes.remained) return res else - return rawRes + return nothing end end + function tyOfArgsAux(input) tyArgItem = Psr(tyArgItemAux) - rawFunc = seq([typ("lParen"), typ("id"), many0(tyArgItem), typ("rParen")]) + rawFunc = seq([typ("lParen"), ty, many0(tyArgItem), typ("rParen")]) res = rawFunc.fun(input) if res != nothing matched = vcat([("%argType")], vcat([res.matched[2]], res.matched[3])) res = ParserResult(matched, res.remained) + return res + else + return nothing end +end + +function tyHeadAux(input) + tyOfArgs = Psr(tyOfArgsAux) + tyOfFn = Psr(tyOfFnAux) + rawFunc = tyOfArgs | tyOfFn | typ("id") + res = rawFunc.fun(input) return res end function tyOfFnAux(input) - rawFunc = seq([typ("lParen"), ty, typ("lambda"), ty, typ("rParen")]) + tyHead = Psr(tyHeadAux) + rawFunc = seq([typ("lParen"), tyHead, typ("funType"), ty, typ("rParen")]) rawRes = rawFunc.fun(input) if rawRes != nothing matched = [("%funType", "id"), rawRes.matched[2], rawRes.matched[4]] res = ParserResult(matched, rawRes.remained) return res else - return rawRes + return nothing end end + + function tyAux(input) - tyOfFn = Psr(tyOfArgsAux) - tyOfArgs = Psr(tyOfFnAux) - rawFunc = tyOfFn | tyOfArgs | typ("id") + tyOfFn= Psr(tyOfFnAux) + rawFunc = tyOfFn | typ("id") res = rawFunc.fun(input) return res end @@ -363,7 +418,7 @@ function letExpAux(input) res = ParserResult(matched, rawRes.remained) return res else - return rawRes + return nothing end end @@ -371,8 +426,24 @@ letExp = Psr(letExpAux) body = letExp | exp -test3 = initWrapped >> body -println(prettyString(test3)) +function totalParse(prog) + isEntirelyMatched = match(matchEntirely, prog) + if isEntirelyMatched == false + throw("illegal tokens contained.") + end + + mI = eachmatch(matchEachItem, prog) + matchedList = map((x)->x.match, collect(mI)) + groupNameList = map(processKeys, collect(mI)) + zippedTokenList = collect(zip(matchedList, groupNameList)) + print(zippedTokenList) + + withoutSpaces = filter((x)-> x[2] != "sp", zippedTokenList) + initWrapped = ParserResult([], withoutSpaces) + res = initWrapped >> body + println(prettyStringLisp(res)) + return res.matched +end end diff --git a/test/prog.tc b/test/prog.tc new file mode 100644 index 0000000..fd55679 --- /dev/null +++ b/test/prog.tc @@ -0,0 +1,3 @@ +(int -> int) +addmulti2 = (x , y) => (x + y) * 2; +addmulti2(40,10) \ No newline at end of file diff --git a/test/prog1.tc b/test/prog1.tc new file mode 100644 index 0000000..02c43fd --- /dev/null +++ b/test/prog1.tc @@ -0,0 +1,5 @@ +int a = 12; +int b = 12; +int a = 15; +int d = 20; +a + d((0 - a), b) \ No newline at end of file