Skip to content

Commit

Permalink
Merge pull request #11 from dantheking-crypto/feature/scopes
Browse files Browse the repository at this point in the history
Added support for scopes
  • Loading branch information
danielzsh authored Nov 2, 2020
2 parents 2756007 + aae648e commit eccc3cd
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 37 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/spark.yml → .github/workflows/compile.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Compile and Run Spark Program
name: Compile Spark

on:
pull_request:
Expand All @@ -15,17 +15,17 @@ jobs:
- uses: ilammy/[email protected]
- name: compile
run: |
cl main.cpp /Fe:spark-windows /std:c++latest
cl main.cpp /Fe:spark /std:c++latest
- name: run
run: |
spark-windows.exe test.spark
spark.exe test.spark
shell: cmd
- name: upload executable
uses: actions/upload-artifact@v2
with:
name: windows
path: |
spark-windows.exe
spark.exe
mac-and-ubuntu:
runs-on: ${{matrix.os}}
strategy:
Expand All @@ -36,15 +36,15 @@ jobs:
- uses: actions/checkout@v2
- name: compile
run: |
g++ -std=c++17 main.cpp -o spark-${{matrix.os}}
g++ -std=c++17 main.cpp -o spark
- name: run
run: |
./spark-${{matrix.os}} test.spark
./spark test.spark
shell: bash
- name: upload executable
uses: actions/upload-artifact@v2
with:
name: ${{matrix.os}}
path: |
spark-${{matrix.os}}
spark
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ Debug/*
.vs/*
*.sln
*.vcxproj.*
*.vcxproj
*.vcxproj
spark.exe
*.obj
63 changes: 53 additions & 10 deletions Interpreter/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,21 @@ class VarSymbol : public Symbol

private:

};
class ProcedureSymbol : public Symbol {
public:
std::vector<VarSymbol> params;
ProcedureSymbol(std::string name, std::vector<VarSymbol> p) : Symbol(name), params(p) {
}
ProcedureSymbol(std::string name) : Symbol(name) {
}
};
class ScopedSymbolTable {
private:
std::string scope_name;
int scope_level;
public:
int scope_level;
ScopedSymbolTable* enclosingScope = NULL;
std::map<std::string, Symbol*> symbols;
ScopedSymbolTable(std::string name, int level) {
define(new BuiltinTypeSymbol("int"));
Expand All @@ -57,7 +66,8 @@ class ScopedSymbolTable {
return symbols[name];
}
else {
return new Symbol();
if (enclosingScope != NULL) return enclosingScope->lookup(name);
else return new Symbol();
}
}
std::string print() {
Expand All @@ -76,20 +86,53 @@ class ScopedSymbolTable {
class SymbolTableBuilder {
public:
ScopedSymbolTable symtab;
SymbolTableBuilder(std::string name, int level) : symtab(name, level) {

ScopedSymbolTable& currentScope;
SymbolTableBuilder(std::string name, int level) : symtab("global", 1), currentScope(symtab) {
}
void visit(AstNode * node) {
if (node->print() == "Block") visit_Block(*static_cast<Block*>(node));
if (node->print() == "Program") visit_Program(*static_cast<Program*>(node));
else if (node->print() == "ProcedureDecl") visit_ProcedureDecl(*static_cast<ProcedureDecl*>(node));
else if (node->print() == "Block") visit_Block(*static_cast<Block*>(node));
else if (node->print() == "UnOp") visit_UnOp(*static_cast<UnOp*>(node));
else if (node->print() == "Var") visit_Var(*static_cast<Var*>(node));
else if (node->print() == "BinOp") return visit_BinOp(*static_cast<BinOp*>(node));
else if (node->print() == "Assign") visit_Assign(*static_cast<class Assign*>(node));
}
void visit_Program(Program program) {
// cout << "Enter scope: GLOBAL\n";
ScopedSymbolTable globalScope("global", 1);
currentScope = globalScope;
visit_Block(program.block);
// cout << currentScope.print();
// cout << "Leave scope: GLOBAL\n";
}
void visit_ProcedureDecl(ProcedureDecl proc) {
ProcedureSymbol* proc_symbol = new ProcedureSymbol(proc.name);
currentScope.define(proc_symbol);
// cout << "Enter scope: " << proc.name << endl;
ScopedSymbolTable proc_scope(proc.name, currentScope.scope_level + 1);
ScopedSymbolTable* enclosing = new ScopedSymbolTable(currentScope);
proc_scope.enclosingScope = enclosing;
currentScope = proc_scope;
for (VarDecl param : proc.params) {
BuiltinTypeSymbol* type = static_cast<BuiltinTypeSymbol*>(currentScope.lookup(param.type.type));
std::string param_name = param.var.value;
Symbol* var = new VarSymbol(param_name, type);
currentScope.define(var);
VarSymbol var_symbol(param_name, type);
proc_symbol->params.push_back(var_symbol);
}
visit_Block(proc.block);
// cout << currentScope.print();
currentScope = *proc_scope.enclosingScope;
}
void visit_Block(Block block) {
for (VarDecl decl : block.declarations) {
visit_VarDecl(decl);
}
for (ProcedureDecl* decl : block.procedures) {
visit(decl);
}
for (AstNode* node : block.children) {
visit(node);
}
Expand All @@ -103,7 +146,7 @@ class SymbolTableBuilder {
}
void visit_Assign(class Assign assign) {
std::string var_name = assign.var.value;
Symbol* var_symbol = symtab.lookup(var_name);
Symbol* var_symbol = currentScope.lookup(var_name);
if (var_symbol->name == "") {
std::string error = "Error: variable not defined: " + var_name;
throw error;
Expand All @@ -112,21 +155,21 @@ class SymbolTableBuilder {
}
void visit_Var(Var var) {
std::string var_name = var.value;
Symbol* var_symbol = symtab.lookup(var_name);
Symbol* var_symbol = currentScope.lookup(var_name);
if (var_symbol->name == "") {
std::string error = "Error: variable not defined: " + var_name;
throw error;
}
}
void visit_VarDecl(VarDecl varDecl) {
std::string type_name = varDecl.type.type;
BuiltinTypeSymbol* type_symbol = static_cast<BuiltinTypeSymbol*>(symtab.lookup(type_name));
BuiltinTypeSymbol* type_symbol = static_cast<BuiltinTypeSymbol*>(currentScope.lookup(type_name));
std::string var_name = varDecl.var.value;
if (symtab.lookup(var_name)->name != "") {
if (currentScope.lookup(var_name)->name != "") {
std::string error("Multiple definition of variable " + var_name);
throw error;
}
VarSymbol* var = new VarSymbol(var_name, type_symbol);
symtab.define(var);
currentScope.define(var);
}
};
15 changes: 11 additions & 4 deletions Interpreter/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace interpreter {
private:
Parser parser;
ScopedSymbolTable symTab;
ScopedSymbolTable& currentSymTab = symTab;
public:
std::map<std::string, std::variant<int, double, std::string>> GLOBAL_SCOPE;
Interpreter(std::string input) : parser(input), symTab("global", 1) {
Expand Down Expand Up @@ -248,14 +249,20 @@ namespace interpreter {
}
void visit_NoOp() {}
void interpret() {
Block block = parser.parseProgram();
Program p = parser.parseProgram();
SymbolTableBuilder symtabBuilder("global", 1);
//std::cout << "Building symtab...\n";
symtabBuilder.visit(&block);
try {
symtabBuilder.visit(&p);
}
catch (std::string error) {
cout << error << endl;
return;
}
//std::cout << "Finished building symtab...\n";
symTab = symtabBuilder.symtab;
symTab = symtabBuilder.currentScope;
//std::cout << "Interpreting...\n";
visit_Block(block);
visit_Block(p.block);
}
};
}
13 changes: 12 additions & 1 deletion Parser/astnodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,23 @@ class Block : public AstNode {
return s;
}
};
class Program : public AstNode {
public:
Block block;
Program(Block b) : block(b) {}
Program() {}
std::string print() {
return "Program";
}
};
class ProcedureDecl : public AstNode {
public:
Block block;
std::vector<VarDecl> params;
std::string name;
ProcedureDecl(std::string n, Block b) : block(b) {
ProcedureDecl(std::string n, Block b, std::vector<VarDecl> p) : block(b) {
name = n;
params = p;
}
std::string print() {
return "ProcedureDecl";
Expand Down
23 changes: 18 additions & 5 deletions Parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ class Parser {
if (currentToken.type == type) currentToken = lexer.nextToken();
else error(type, currentToken.type);
}
Block parseProgram() {
Program parseProgram() {
eat(MAIN);
eat(LeftParenthesis);
eat(RightParenthesis);
return parseBlock();

Program p(parseBlock());
return p;
}
Block parseBlock() {
eat(LeftBracket);
Expand Down Expand Up @@ -70,22 +70,36 @@ class Parser {
while (currentToken.type == INT || currentToken.type == REAL || currentToken.type == STRING)
{
std::vector<VarDecl> line = parseVarDeclarations();
eat(Semicolon);
decl.insert(decl.end(), line.begin(), line.end());
}
}

return decl;
}
std::vector<VarDecl> parseFormalParameters() {
std::vector<VarDecl> decl;
while (currentToken.type == INT || currentToken.type == REAL || currentToken.type == STRING)
{
std::vector<VarDecl> line = parseVarDeclarations();
decl.insert(decl.end(), line.begin(), line.end());
if (currentToken.type != Semicolon) break;
else eat(Semicolon);
}

return decl;
}
std::vector<ProcedureDecl*> parseFunctions() {
std::vector<ProcedureDecl*> declarations;
while (currentToken.type == FUNCTION) {
eat(FUNCTION);
std::string proc_name = currentToken.value;
eat(Identifier);
eat(LeftParenthesis);
std::vector<VarDecl> params = parseFormalParameters();
eat(RightParenthesis);
Block block = parseBlock();
ProcedureDecl* proc_decl = new ProcedureDecl(proc_name, block);
ProcedureDecl* proc_decl = new ProcedureDecl(proc_name, block, params);
declarations.push_back(proc_decl);
}
return declarations;
Expand All @@ -101,7 +115,6 @@ class Parser {
declarations.push_back(Var(currentToken));
eat(Identifier);
}
eat(Semicolon);
std::vector<VarDecl> var_decl(declarations.size());
for (unsigned int i = 0; i < var_decl.size(); i++) {
VarDecl varDecl(type, declarations[i]);
Expand Down
14 changes: 7 additions & 7 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ int interpret(string input) {
vector<Token> tokens = lexer.allTokens();

// tokens.size() is a long unsigned int, use to prevent -Wall or -Wextra warnings
cout << "Lexer tokens:" << endl;
/* cout << "Lexer tokens:" << endl;
for (long unsigned int i = 0; i < tokens.size(); i++) {
cout << tokens[i];
}
Parser parser(input);
Block block;
Program program;
try {
block = parser.parseProgram();
program = parser.parseProgram();
}
catch (string error) {
cout << error << "\n";
Expand All @@ -42,9 +42,9 @@ int interpret(string input) {
cout << "Parser blocks:" << endl;
for (int i = 0; i < block.size(); i++) {
cout << block[i]->print() << endl;
}
}*/
Interpreter interpreter(input);
cout << "Interpreting...\n";
// cout << "Interpreting...\n";
try {
interpreter.interpret();
}
Expand All @@ -53,7 +53,7 @@ int interpret(string input) {
return 1;
}

cout << "Variables: " << endl;
/*cout << "Variables: " << endl;
ScopedSymbolTable symtab = interpreter.getSymTab();
cout << symtab.print();
for (auto const& pair : interpreter.GLOBAL_SCOPE) {
Expand All @@ -69,7 +69,7 @@ int interpret(string input) {
cout << std::get<std::string>(pair.second);
}
cout << endl;
}
}*/
return 0;
}
int main (int argc, char** argv) {
Expand Down
8 changes: 6 additions & 2 deletions test.spark
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@
int: a, c, d;
real: b;
string: test, multi;
def foo () {
program:
def foo (int: bar) {
def proc (int: asdf) {
program: asdf = a;
}
program:
bar = a;
}
program: #this is a comment#
a = 1*1+4//-2;
Expand Down

0 comments on commit eccc3cd

Please sign in to comment.