Skip to content

Commit

Permalink
Semantic Analysis is basically finished, and more:
Browse files Browse the repository at this point in the history
Need to implement proper error handling for semantic parse.
Fixed a few things in the Language Specification.
Added a WARN flag to basic_io::Flag
  • Loading branch information
therealgymmy committed Mar 9, 2012
1 parent 9c0459b commit 9e50045
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 18 deletions.
6 changes: 3 additions & 3 deletions doc/Language Specification
Expand Up @@ -121,12 +121,12 @@ Production Rules:
statements -> statements statement
statements -> Nothing
statement -> lvalue BECOMES expr SEMI
statement -> IF LPAREN tests AND test RPAREN
statement -> IF LPAREN tests RPAREN
LBRACE statements RBRACE
statement -> IF LPAREN tests AND test RPAREN
statement -> IF LPAREN tests RPAREN
LBRACE statements RBRACE
ELSE LBRACE statements RBRACE
statement -> WHILE LPAREN tests AND test RPAREN
statement -> WHILE LPAREN tests RPAREN
LBRACE statements RBRACE
tests -> tests AND test
tests -> test
Expand Down
5 changes: 3 additions & 2 deletions src/basic_io.cc
Expand Up @@ -6,12 +6,13 @@

namespace basic_io {

void out(std::string const& msg, Flags flag) {
void out(std::string const& msg, Flag flag) {
switch (flag) {
default:
throw "error";
break;
case ERROR:
case ERROR: // fall-through
case WARN:
std::cerr << msg;
break;
case INFO:
Expand Down
5 changes: 3 additions & 2 deletions src/basic_io.h
Expand Up @@ -17,14 +17,15 @@

namespace basic_io {

enum Flags {
enum Flag {
ERROR,
WARN,
INFO,
};

// Outputs msg to stdout/stderr depending on error flag.
// When not specified, flag defaults to INFO.
void out(std::string const& msg, Flags flag = INFO);
void out(std::string const& msg, Flag flag = INFO);

}

Expand Down
6 changes: 3 additions & 3 deletions src/parse_common.h
Expand Up @@ -62,12 +62,12 @@ enum ProductionRule {
Stmnts_Exp_Stmnts_Stmnt,// statements -> statements statement
Stmnts_Exp_Nothing, // statements -> Nothing
Stmnt_Exp_Assign, // statement -> lvalue BECOMES expr SEMI
Stmnt_Exp_If, // statement -> IF LPAREN tests AND test RPAREN
Stmnt_Exp_If, // statement -> IF LPAREN tests RPAREN
// LBRACE statements RBRACE
Stmnt_Exp_If_Else, // statement -> IF LPAREN tests AND test RPAREN
Stmnt_Exp_If_Else, // statement -> IF LPAREN tests RPAREN
// LBRACE statements RBRACE
// ELSE LBRACE statements RBRACE
Stmnt_Exp_While, // statement -> WHILE LPAREN tests AND test RPAREN
Stmnt_Exp_While, // statement -> WHILE LPAREN tests RPAREN
// LBRACE statements RBRACE

Tests_Exp_Tests_Test, // tests -> tests AND test
Expand Down
4 changes: 2 additions & 2 deletions src/run_main.cc
Expand Up @@ -63,11 +63,11 @@ void run_main::run()
}
catch (error::ErrorObjectInterface *e) {
error::ErrorObjectPtr err(e);
basic_io::out(err->toString() + "\n");
basic_io::out(err->toString() + "\n", basic_io::ERROR);
std::exit(err->retCode());
}
catch (...) {
basic_io::out("Encountered unknown error.\n");
basic_io::out("Encountered unknown error.\n", basic_io::ERROR);
std::exit(1);
}
///
Expand Down
146 changes: 141 additions & 5 deletions src/semantic_parse.cc
Expand Up @@ -20,6 +20,9 @@ ParseTree::ParseTree(Tree *tree) : ParseTreeInterface(tree)

// Build symbol table.
buildSymbolTables(vecTree_, symTables_, fcnTable_);

// Type Check
typeCheck(vecTree_);
}

std::string ParseTree::symTablesToString()
Expand Down Expand Up @@ -157,6 +160,85 @@ Type ParseTree::getType(VectorTree &vecTree)
return type;
}

Type ParseTree::checkExprType(VectorTree &vecTree, std::string const& fcnName)
{
Type type;
Type typeExpr, typeTerm;
switch (vecTree.rule) {
default:
throw "Not a valid structure to query for type.\n";

case Expr_Exp_Term:
type = checkTermType(vecTree.leaves[0], fcnName);
break;
case Expr_Exp_Plus:
typeExpr = checkExprType(vecTree.leaves[0], fcnName);
typeTerm = checkTermType(vecTree.leaves[2], fcnName);
if (typeExpr == INT && typeTerm == INT) {
type = INT;
}
else if ((typeExpr == INT_STAR && typeTerm == INT) ||
(typeExpr == INT && typeTerm == INT_STAR)) {
type = INT_STAR;
}
else if ((typeExpr == CHAR_STAR && typeTerm == INT) ||
(typeExpr == INT && typeTerm == CHAR_STAR)) {
type = CHAR_STAR;
}
else {
throw "Invalid operation. Expr_Exp_Plus "
"not allowed for this combination of types.\n";
}
break;
case Expr_Exp_Minus:
typeExpr = checkExprType(vecTree.leaves[0], fcnName);
typeTerm = checkTermType(vecTree.leaves[2], fcnName);
if ((typeExpr == INT && typeTerm == INT) ||
(typeExpr == INT_STAR && typeTerm == INT_STAR) ||
(typeExpr == CHAR_STAR && typeTerm == CHAR_STAR)) {
type = INT;
}
else if (typeExpr == INT_STAR && typeTerm == INT) {
type = INT_STAR;
}
else if (typeExpr == CHAR_STAR && typeTerm == CHAR) {
type = CHAR_STAR;
}
else {
throw "Invalid operation. Expr_Exp_Minus "
"not allowed for this combination of types.\n";
}
break;
}
return type;
}

Type ParseTree::checkTermType(VectorTree &vecTree, std::string const& fcnName)
{
Type type;
switch (vecTree.rule) {
default:
throw "Not a valid structure to query for type.\n";

case Term_Exp_Ftor:
type = checkFtorType(vecTree.leaves[0], fcnName);
break;
case Term_Exp_Star: // fall-through
case Term_Exp_Slash: // fall-through
case Term_Exp_Pct:
if (checkTermType(vecTree.leaves[0], fcnName) == INT &&
checkTermType(vecTree.leaves[2], fcnName) == INT) {
type = INT;
}
else {
throw "Invalid operation. Multiplication/Division/Mod "
"only allowed for integers.\n";
}
break;
}
return type;
}

Type ParseTree::checkFtorType(VectorTree &vecTree, std::string const& fcnName)
{
Type type;
Expand Down Expand Up @@ -230,9 +312,10 @@ Type ParseTree::checkLvalType(VectorTree &vecTree, std::string const& fcnName)
type = checkLvalType(vecTree.leaves[1], fcnName);
break;
}
return type;
}

void ParseTree::typeCheck(VectorTree &ret)
void ParseTree::typeCheck(VectorTree &ret, std::string const& fcnName)
{
switch (ret.rule) {
default: // Do nothing.
Expand All @@ -247,11 +330,64 @@ void ParseTree::typeCheck(VectorTree &ret)
break;
case ProcW_Exp: // fall-through
case Proc_Exp:
typeCheck(ret.leaves[8]);
typeCheck(ret.leaves[9]);
typeCheck(ret.leaves[8], ret.leaves[1].token.lexeme);
typeCheck(ret.leaves[9], ret.leaves[1].token.lexeme);

Type retType;
// to be implemented
if (checkExprType(ret.leaves[11], ret.leaves[1].token.lexeme) !=
(ret.rule == ProcW_Exp ? INT : getType(ret.leaves[0]))) {
throw "Return type does not match function signature.\n";
}
break;
case Dcls_Exp_Assign:
typeCheck(ret.leaves[0], fcnName);
if (getType(ret.leaves[1].leaves[0]) !=
checkExprType(ret.leaves[3], fcnName)) {
std::cout << "eee" << std::endl;
throw "Cannot assign, lhs and rhs types are not the same\n";
}
break;
case Stmnts_Exp_Stmnts_Stmnt:
typeCheck(ret.leaves[0], fcnName);
typeCheck(ret.leaves[1], fcnName);
break;
case Stmnt_Exp_Assign:
if (checkLvalType(ret.leaves[0], fcnName) !=
checkExprType(ret.leaves[2], fcnName)) {
throw "Cannot assign, lhs and rhs types are not the same\n";
}
break;
case Stmnt_Exp_If:
typeCheck(ret.leaves[2], fcnName);
typeCheck(ret.leaves[5], fcnName);
break;
case Stmnt_Exp_If_Else:
typeCheck(ret.leaves[2], fcnName);
typeCheck(ret.leaves[5], fcnName);
typeCheck(ret.leaves[9], fcnName);
break;
case Stmnt_Exp_While:
typeCheck(ret.leaves[2], fcnName);
typeCheck(ret.leaves[5], fcnName);
break;
case Tests_Exp_Tests_Test:
typeCheck(ret.leaves[0], fcnName);
typeCheck(ret.leaves[2], fcnName);
break;
case Tests_Exp_Test:
typeCheck(ret.leaves[0], fcnName);
break;
case Test_Exp_Eq: // fall-through
case Test_Exp_Ne: // fall-through
case Test_Exp_Lt: // fall-through
case Test_Exp_Le: // fall-through
case Test_Exp_Ge: // fall-through
case Test_Exp_Gt:
if (!((checkExprType(ret.leaves[0], fcnName) == INT &&
checkExprType(ret.leaves[2], fcnName) == INT) ||
(checkExprType(ret.leaves[0], fcnName) == CHAR &&
checkExprType(ret.leaves[2], fcnName) == CHAR))) {
throw "comparison only allowed between INT or between CHAR\n";
}
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/semantic_parse.h
Expand Up @@ -61,7 +61,7 @@ class ParseTree: public ParseTreeInterface {
// Intended for Type_Exp only
static Type getType(VectorTree &vecTree);
// Typecheck the parse tree to make sure it is semantically correct.
void typeCheck(VectorTree &ret);
void typeCheck(VectorTree &ret, std::string const& fcnName = "");
// Check Type information about the tree.
// Intended for deducing type information related to
// symTables_ and fcnTable_.
Expand Down

0 comments on commit 9e50045

Please sign in to comment.