add parser rules and add basic typechecker (not tested)
This commit is contained in:
parent
1747789314
commit
1d851522ba
3 changed files with 212 additions and 10 deletions
77
src/TComp.jl
77
src/TComp.jl
|
@ -21,6 +21,83 @@ println("PARSED\n", Parser.prettyStringLisp(parsed))
|
||||||
tmp_var_no = 0
|
tmp_var_no = 0
|
||||||
|
|
||||||
|
|
||||||
|
typeEnv = [
|
||||||
|
("+", ("Fn", ["int", "int"], "int")),
|
||||||
|
("-", ("Fn", ["int", "int"], "int")),
|
||||||
|
("*", ("Fn", ["int", "int"], "int")),
|
||||||
|
("/", ("Fn", ["int", "int"], "int")),
|
||||||
|
]
|
||||||
|
function typeCheck(ast, typeEnv)
|
||||||
|
pl = Parser.prettyStringLisp
|
||||||
|
result = @match ast begin
|
||||||
|
(_, "bool") => "bool"
|
||||||
|
(_, "int") => "int"
|
||||||
|
[("%prime", _), (op, _), (lhs, rhs)] => begin
|
||||||
|
t_lhs = typeCheck(lhs, env)
|
||||||
|
t_rhs = typeCheck(rhs, env)
|
||||||
|
actualInputType = [t_lhs, t_rhs]
|
||||||
|
funcType = findfirst(x->x[1] == op, typeEnv)[2]
|
||||||
|
expectedInputType = funcType[2]
|
||||||
|
zipped = zip(expectedInputType, actualInputType)
|
||||||
|
mapped = map(a -> a[1] && a[2] , zipped)
|
||||||
|
reduced = reduce((x,y)->x || y, mapped)
|
||||||
|
if reduced == true
|
||||||
|
return funcType[3]
|
||||||
|
else
|
||||||
|
throw("Type Error: Operands of"
|
||||||
|
* op * " expected to be"
|
||||||
|
* string(expectedInputType)
|
||||||
|
* ", found"
|
||||||
|
* string(actualInputType))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
(var, "%id") => begin
|
||||||
|
t_var_id = findfirst(x->x[1] == var, typeEnv)
|
||||||
|
if t_var_id == nothing
|
||||||
|
throw(var * "not found in typeEnv")
|
||||||
|
else
|
||||||
|
return typeEnv[t_var_id]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
[("%let", _),[(tVar, _), (var_)], exp, body] =>
|
||||||
|
begin
|
||||||
|
typeOfExp = typeCheck(exp, typeEnv)
|
||||||
|
if tVar != typeOfExp
|
||||||
|
throw("Type Error: type of " * var
|
||||||
|
* "should be" * tVar
|
||||||
|
* ", found " * typeOfExp)
|
||||||
|
else
|
||||||
|
newTypeEnv = typeEnv
|
||||||
|
pushfirst!((var, tVar), newTypeEnv)
|
||||||
|
return typeCheck(body, newTypeEnv)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
[("!", "not"), operand] =>
|
||||||
|
begin
|
||||||
|
tOperand = typeCheck(operand, typeEnv)
|
||||||
|
if tOperand != "bool"
|
||||||
|
throw("Type Error: type of operands for !"
|
||||||
|
* "should be" * tVar
|
||||||
|
* ", found " * typeOfExp)
|
||||||
|
else
|
||||||
|
return "bool"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
[(cmp, _), lhs, rhs] where (cmp[2]) in ["==", "!=", "<", "<=", ">", ">=", "&", "|"] =>
|
||||||
|
begin
|
||||||
|
tLhs = typeCheck(lhs, typeEnv)
|
||||||
|
tRhs = typeCheck(rhs, typeEnv)
|
||||||
|
if !(tLhs == "bool" & tRhs == "bool")
|
||||||
|
throw("Type Error: operands of"
|
||||||
|
* cmp * "should be (bool, bool), not"
|
||||||
|
* string([tLhs, tRhs]))
|
||||||
|
else
|
||||||
|
return "bool"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
# Pass 1: Duplicated varname uniquified
|
# Pass 1: Duplicated varname uniquified
|
||||||
function uniquifyVar(parsed, env)
|
function uniquifyVar(parsed, env)
|
||||||
|
|
137
src/parser.jl
137
src/parser.jl
|
@ -87,11 +87,25 @@ end
|
||||||
|
|
||||||
|
|
||||||
patternList = [
|
patternList = [
|
||||||
|
("if", "if"),
|
||||||
|
("then", "then"),
|
||||||
|
("else", "else"),
|
||||||
|
("True", "bool"),
|
||||||
|
("False", "bool"),
|
||||||
("cmt", "[#][^\\r\\n]+"),
|
("cmt", "[#][^\\r\\n]+"),
|
||||||
("int", "\\d+"),
|
("int", "\\d+"),
|
||||||
("id", "[_a-zA-Z][_0-9a-zA-Z]*"),
|
("id", "[_a-zA-Z][_0-9a-zA-Z]*"),
|
||||||
("lParen", "[\\(]"),
|
("lParen", "[\\(]"),
|
||||||
("rParen", "[\\)]"),
|
("rParen", "[\\)]"),
|
||||||
|
("eq", "[=][=]"),
|
||||||
|
("ne", "[!][=]"),
|
||||||
|
("lt", "[<]"),
|
||||||
|
("le", "[<][=]"),
|
||||||
|
("gt", "[>]"),
|
||||||
|
("ge", "[>][=]"),
|
||||||
|
("and", "[&]"),
|
||||||
|
("or", "[\\|]"),
|
||||||
|
("not", "[!]"),
|
||||||
("plus", "[+]"),
|
("plus", "[+]"),
|
||||||
("funType", "[-][\\>]"),
|
("funType", "[-][\\>]"),
|
||||||
("minus", "[\\-]"),
|
("minus", "[\\-]"),
|
||||||
|
@ -182,18 +196,21 @@ end
|
||||||
#println(prettyString(test2))
|
#println(prettyString(test2))
|
||||||
|
|
||||||
"""
|
"""
|
||||||
atom = int | id
|
atom = int | id | bool
|
||||||
func = "(" fn_args ")" "=>" body
|
func = "(" fn_args ")" "=>" body
|
||||||
unit = func | "(" exp ")" | atom
|
unit = func | "(" exp ")" | atom
|
||||||
args = unit ("," unit)*
|
args = unit ("," unit)*
|
||||||
factor = unit "(" args ")"
|
factor = unit "(" args ")"
|
||||||
term = (factor (*|/) term) | factor
|
unary = (-|!) factor | factor
|
||||||
exp = (term [(+|-) exp]) | term
|
term = (unary (*|/) term) | unary
|
||||||
|
eqcheckee = (term [(+|-) exp]) | term
|
||||||
|
logical = eqcheckee ("=="|"<"|"<="|">"|">=") eqcheckee | eqcheckee
|
||||||
|
subexp = logical ("&&"|"||") logical | logical
|
||||||
|
exp = if subexp then subexp else subexp | subexp
|
||||||
letexp = ty id "=" exp ";" body
|
letexp = ty id "=" exp ";" body
|
||||||
body = exp | letexp
|
body = exp | letexp
|
||||||
"""
|
"""
|
||||||
atom = typ("int") | typ("id")
|
atom = typ("int") | typ("id") | typ("bool")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -304,8 +321,35 @@ end
|
||||||
|
|
||||||
factor = Psr(factorAux)
|
factor = Psr(factorAux)
|
||||||
|
|
||||||
|
function longUnaryAux(input)
|
||||||
|
rawFunc = seq([(typ("minus") | typ("not")), factor])
|
||||||
|
rawRes = rawFunc.fun(input)
|
||||||
|
if rawRes != nothing
|
||||||
|
rator = rawRes.matched[1]
|
||||||
|
rand = rawRes.matched[2]
|
||||||
|
if rator[2] == "minus" # -a -> 0 - a
|
||||||
|
matched = [("%prime", "id"), rator, [("0", "int"), rand]]
|
||||||
|
else
|
||||||
|
matched = [rator, rand]
|
||||||
|
end
|
||||||
|
res = ParserResult(matched, rawRes.remained)
|
||||||
|
return res
|
||||||
|
else
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function unaryAux(input)
|
||||||
|
longUnary = Psr(longUnaryAux)
|
||||||
|
rawFunc = longUnary | factor
|
||||||
|
res = rawFunc.fun(input)
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
|
||||||
|
unary = Psr(unaryAux)
|
||||||
|
|
||||||
function longTermAux(input)
|
function longTermAux(input)
|
||||||
rawFunc = seq([factor, (typ("mul") | typ("div")), term])
|
rawFunc = seq([unary, (typ("mul") | typ("div")), term])
|
||||||
rawRes = rawFunc.fun(input)
|
rawRes = rawFunc.fun(input)
|
||||||
if rawRes != nothing
|
if rawRes != nothing
|
||||||
#correct the tree a /(b / c) -> (a / b) / c
|
#correct the tree a /(b / c) -> (a / b) / c
|
||||||
|
@ -334,7 +378,7 @@ end
|
||||||
|
|
||||||
function termAux(input)
|
function termAux(input)
|
||||||
longTerm = Psr(longTermAux)
|
longTerm = Psr(longTermAux)
|
||||||
rawFunc = longTerm | factor
|
rawFunc = longTerm | unary
|
||||||
res = rawFunc.fun(input)
|
res = rawFunc.fun(input)
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
|
@ -342,8 +386,8 @@ end
|
||||||
term = Psr(termAux)
|
term = Psr(termAux)
|
||||||
|
|
||||||
|
|
||||||
function longExpAux(input)
|
function longEqCheckeeAux(input)
|
||||||
rawFunc = seq([term, (typ("plus") | typ("minus")), exp])
|
rawFunc = seq([term, (typ("plus") | typ("minus")), eqCheckee])
|
||||||
rawRes = rawFunc.fun(input)
|
rawRes = rawFunc.fun(input)
|
||||||
if rawRes != nothing
|
if rawRes != nothing
|
||||||
#correct the tree a -(b - c) -> (a - b) - c
|
#correct the tree a -(b - c) -> (a - b) - c
|
||||||
|
@ -370,15 +414,88 @@ function longExpAux(input)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function eqCheckeeAux(input)
|
||||||
|
longEqCheckee = Psr(longEqCheckeeAux)
|
||||||
|
rawFunc = longEqCheckee | term
|
||||||
|
res = rawFunc.fun(input)
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
eqCheckee = Psr(eqCheckeeAux)
|
||||||
|
|
||||||
|
|
||||||
|
function longlogicalAux(input)
|
||||||
|
rawFunc = seq([eqCheckee, (typ("eq") | typ("ne")|typ("lt") | typ("gt")|typ("le") | typ("ge")), eqCheckee])
|
||||||
|
rawRes = rawFunc.fun(input)
|
||||||
|
if rawRes != nothing
|
||||||
|
rator = rawRes.matched[2]
|
||||||
|
l = rawRes.matched[1]
|
||||||
|
r = rawRes.matched[3]
|
||||||
|
matched = [rator, l, r]
|
||||||
|
res = ParserResult(matched, rawRes.remained)
|
||||||
|
return res
|
||||||
|
else
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function logicalAux(input)
|
||||||
|
longLogical = Psr(longlogicalAux)
|
||||||
|
rawFunc = longLogical | eqCheckee
|
||||||
|
res = rawFunc.fun(input)
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
logical = Psr(logicalAux)
|
||||||
|
|
||||||
|
function longSubExpAux(input)
|
||||||
|
rawFunc = seq([logical, (typ("and") | typ("or")), logical])
|
||||||
|
rawRes = rawFunc.fun(input)
|
||||||
|
if rawRes != nothing
|
||||||
|
rator = rawRes.matched[2]
|
||||||
|
l = rawRes.matched[1]
|
||||||
|
r = rawRes.matched[3]
|
||||||
|
matched = [rator, l, r]
|
||||||
|
res = ParserResult(matched, rawRes.remained)
|
||||||
|
return res
|
||||||
|
else
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function subExpAux(input)
|
||||||
|
longSubExp = Psr(longSubExpAux)
|
||||||
|
rawFunc = longSubExp | logical
|
||||||
|
res = rawFunc.fun(input)
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
subExp = Psr(subExpAux)
|
||||||
|
|
||||||
|
function longExpAux(input)
|
||||||
|
rawFunc = seq([typ("if"), subExp,
|
||||||
|
typ("then"), subExp,
|
||||||
|
typ("else"), subExp])
|
||||||
|
rawRes = rawFunc.fun(input)
|
||||||
|
if rawRes != nothing
|
||||||
|
cond = rawRes.matched[2]
|
||||||
|
branch1 = rawRes.matched[4]
|
||||||
|
branch2 = rawRes.matched[6]
|
||||||
|
matched = [("%if", "id"), cond, branch1, branch2]
|
||||||
|
res = ParserResult(matched, rawRes.remained)
|
||||||
|
return res
|
||||||
|
else
|
||||||
|
return nothing
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function expAux(input)
|
function expAux(input)
|
||||||
longExp = Psr(longExpAux)
|
longExp = Psr(longExpAux)
|
||||||
rawFunc = longExp | term
|
rawFunc = longExp | subExp
|
||||||
res = rawFunc.fun(input)
|
res = rawFunc.fun(input)
|
||||||
return res
|
return res
|
||||||
end
|
end
|
||||||
exp = Psr(expAux)
|
exp = Psr(expAux)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""tyOfArgs = "(" ty ("," ty)* ")"
|
"""tyOfArgs = "(" ty ("," ty)* ")"
|
||||||
tyHead = tyOfArgs | tyOfFn | id
|
tyHead = tyOfArgs | tyOfFn | id
|
||||||
tyOfFn = "(" tyHead -> ty ")"
|
tyOfFn = "(" tyHead -> ty ")"
|
||||||
|
|
8
test/prog3.tc
Normal file
8
test/prog3.tc
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
int a = -10;
|
||||||
|
int a = False;
|
||||||
|
int b = (12 + (-3));
|
||||||
|
int c = (14 + b);
|
||||||
|
int d = 20;
|
||||||
|
if ((True & a) | False)
|
||||||
|
then 12
|
||||||
|
else (if !True then 0 else (d - 3))
|
Loading…
Reference in a new issue