diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/compile.yml similarity index 76% rename from .github/workflows/c-cpp.yml rename to .github/workflows/compile.yml index 1dc2fe6..ccdda99 100644 --- a/.github/workflows/c-cpp.yml +++ b/.github/workflows/compile.yml @@ -1,4 +1,4 @@ -name: C/C++ CI +name: Compile Spark on: pull_request: @@ -15,17 +15,17 @@ jobs: - uses: ilammy/msvc-dev-cmd@v1.4.1 - 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: @@ -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 diff --git a/.gitignore b/.gitignore index 3a8c69e..83b4018 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,6 @@ Debug/* .vs/* *.sln *.vcxproj.* -*.vcxproj \ No newline at end of file +*.vcxproj +spark.exe +*.obj \ No newline at end of file diff --git a/Interpreter/Stack.h b/Interpreter/Stack.h new file mode 100644 index 0000000..267a4d9 --- /dev/null +++ b/Interpreter/Stack.h @@ -0,0 +1,39 @@ +#pragma once +#include +#include +#include +#include +enum class ARType { + PROGRAM, + FUNCTION +}; +using value = std::variant; +class ActivationRecord { +public: + std::string name; + ARType type; + int nesting_level; + std::map members; + ActivationRecord(ARType type, int nesting_level, std::string name = "") { + this->name = name; + this->type = type; + this->nesting_level = nesting_level; + this->members = members; + } + value& operator [] (std::string index) { + return members[index]; + } +}; +class CallStack { +public: + std::vector records; + void push(ActivationRecord& ar) { + records.push_back(ar); + } + void pop() { + records.pop_back(); + } + ActivationRecord& peek() { + return records.back(); + } +}; \ No newline at end of file diff --git a/Interpreter/SymbolTable.h b/Interpreter/SymbolTable.h new file mode 100644 index 0000000..7ba8739 --- /dev/null +++ b/Interpreter/SymbolTable.h @@ -0,0 +1,153 @@ +#pragma once +#include +#include +#include +#include "../Parser/astnodes.h" +#include "./Symbols.h" +class ScopedSymbolTable { +private: + std::string scope_name; +public: + int scope_level; + ScopedSymbolTable* enclosingScope = NULL; + std::map symbols; + ScopedSymbolTable(std::string name, int level) { + define(new BuiltinTypeSymbol("int")); + define(new BuiltinTypeSymbol("real")); + define(new BuiltinTypeSymbol("string")); + scope_name = name; + scope_level = level; + } + void define(Symbol* symbol) { + // std::// cout << "Define: " << symbol->print() << std::endl; + symbols[symbol->name] = symbol; + } + Symbol* lookup(std::string name) { + // std::// cout << "Lookup: " << name << "\n"; + if (symbols.count(name)) { + return symbols[name]; + } + else { + if (enclosingScope != NULL) return enclosingScope->lookup(name); + else return new Symbol(); + } + } + std::string print() { + std::string rep(""); + rep += "SCOPE (SCOPED SYMBOL TABLE)\n==================\n"; + rep += "Scope name: " + scope_name + "\n"; + rep += "Scope level: " + std::to_string(scope_level) + "\n"; + rep += "Contents:\n...................\n"; + for (auto pair : symbols) { + rep += pair.first + ": " + pair.second->print() + "\n"; + } + rep += "====================\n"; + return rep; + } +}; +class SymbolTableBuilder { +public: + ScopedSymbolTable symtab; + ScopedSymbolTable& currentScope; + std::map types; + SymbolTableBuilder(std::string name, int level) : symtab("global", 1), currentScope(symtab) { + } + void visit(AstNode* node) { + if (node->print() == "Program") visit_Program(*static_cast(node)); + else if (node->print() == "FunctionDecl") visit_ProcedureDecl(*static_cast(node)); + else if (node->print() == "FunctionCall") visit_FunctionCall(*static_cast(node)); + else if (node->print() == "Block") visit_Block(*static_cast(node)); + else if (node->print() == "UnOp") visit_UnOp(*static_cast(node)); + else if (node->print() == "Var") visit_Var(*static_cast(node)); + else if (node->print() == "BinOp") return visit_BinOp(*static_cast(node)); + else if (node->print() == "Assign") visit_Assign(*static_cast(node)); + } + void visit_FunctionCall(FunctionCall& functionCall) { + if (functionCall.params.size() != static_cast(symtab.lookup(functionCall.proc_name))->params.size()) { + std::string error("Function call parameters do not match function parameters."); + throw error; + } + for (AstNode* param : functionCall.params) { + visit(param); + } + ProcedureSymbol procSymbol = *static_cast(symtab.lookup(functionCall.proc_name)); + functionCall.procSymbol = procSymbol; + } + 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(FunctionDecl 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(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); + types[param_name] = param.type.type; + } + visit_Block(proc.block); + // // cout << currentScope.print(); + currentScope = *proc_scope.enclosingScope; + proc_symbol->blockAst = *new Block(proc.block); + } + void visit_Block(Block block) { + for (VarDecl decl : block.declarations) { + visit_VarDecl(decl); + } + for (FunctionDecl* decl : block.procedures) { + visit(decl); + } + for (AstNode* node : block.children) { + visit(node); + } + } + void visit_UnOp(UnOp unOp) { + visit(unOp.expr); + } + void visit_BinOp(BinOp binOp) { + visit(binOp.left); + visit(binOp.right); + } + void visit_Assign(class Assign assign) { + std::string var_name = assign.var.value; + Symbol* var_symbol = currentScope.lookup(var_name); + if (var_symbol->name == "") { + std::string error = "Error: variable not defined: " + var_name; + throw error; + } + visit(assign.right); + } + void visit_Var(Var var) { + std::string var_name = var.value; + 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(currentScope.lookup(type_name)); + std::string var_name = varDecl.var.value; + 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); + currentScope.define(var); + types[var_name] = type_name; + } +}; \ No newline at end of file diff --git a/Interpreter/Symbols.h b/Interpreter/Symbols.h index 2f7e9b1..d3d1bd7 100644 --- a/Interpreter/Symbols.h +++ b/Interpreter/Symbols.h @@ -1,8 +1,5 @@ #pragma once #include -#include -#include -#include "../Parser/astnodes.h" class Symbol { private: @@ -34,99 +31,3 @@ class VarSymbol : public Symbol private: }; -class ScopedSymbolTable { -private: - std::string scope_name; - int scope_level; -public: - std::map symbols; - ScopedSymbolTable(std::string name, int level) { - define(new BuiltinTypeSymbol("int")); - define(new BuiltinTypeSymbol("real")); - define(new BuiltinTypeSymbol("string")); - scope_name = name; - scope_level = level; - } - void define(Symbol* symbol) { - // std::cout << "Define: " << symbol->print() << std::endl; - symbols[symbol->name] = symbol; - } - Symbol* lookup(std::string name) { - // std::cout << "Lookup: " << name << "\n"; - if (symbols.count(name)) { - return symbols[name]; - } - else { - return new Symbol(); - } - } - std::string print() { - std::string rep(""); - rep += "SCOPE (SCOPED SYMBOL TABLE)\n==================\n"; - rep += "Scope name: " + scope_name + "\n"; - rep += "Scope level: " + std::to_string(scope_level) + "\n"; - rep += "Contents:\n...................\n"; - for (auto pair : symbols) { - rep += pair.first + ": " + pair.second->print() + "\n"; - } - rep += "====================\n"; - return rep; - } -}; -class SymbolTableBuilder { -public: - ScopedSymbolTable symtab; - SymbolTableBuilder(std::string name, int level) : symtab(name, level) { - - } - void visit(AstNode * node) { - if (node->print() == "Block") visit_Block(*static_cast(node)); - else if (node->print() == "UnOp") visit_UnOp(*static_cast(node)); - else if (node->print() == "Var") visit_Var(*static_cast(node)); - else if (node->print() == "BinOp") return visit_BinOp(*static_cast(node)); - else if (node->print() == "Assign") visit_Assign(*static_cast(node)); - } - void visit_Block(Block block) { - for (VarDecl decl : block.declarations) { - visit_VarDecl(decl); - } - for (AstNode* node : block.children) { - visit(node); - } - } - void visit_UnOp(UnOp unOp) { - visit(unOp.expr); - } - void visit_BinOp(BinOp binOp) { - visit(binOp.left); - visit(binOp.right); - } - void visit_Assign(class Assign assign) { - std::string var_name = assign.var.value; - Symbol* var_symbol = symtab.lookup(var_name); - if (var_symbol->name == "") { - std::string error = "Error: variable not defined: " + var_name; - throw error; - } - visit(assign.right); - } - void visit_Var(Var var) { - std::string var_name = var.value; - Symbol* var_symbol = symtab.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(symtab.lookup(type_name)); - std::string var_name = varDecl.var.value; - if (symtab.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); - } -}; \ No newline at end of file diff --git a/Interpreter/interpreter.h b/Interpreter/interpreter.h index 38705e9..5018b12 100644 --- a/Interpreter/interpreter.h +++ b/Interpreter/interpreter.h @@ -7,14 +7,18 @@ #include #include #include +#include "./Stack.h" +#include "./SymbolTable.h" namespace interpreter { class Interpreter { private: Parser parser; ScopedSymbolTable symTab; + ScopedSymbolTable& currentSymTab = symTab; + std::map types; public: - std::map> GLOBAL_SCOPE; + CallStack stack; Interpreter(std::string input) : parser(input), symTab("global", 1) { } @@ -26,8 +30,11 @@ namespace interpreter { else return "real"; } else if (node->print() == "Var") { - Var* var = static_cast(node); - return symTab.lookup(var->value)->type->name; + // cout << "Getting type of Var..." << endl; + Var* var = dynamic_cast(node); + // cout << var->value << endl; + // cout << types[var->value]; + return types[var->value]; } else if (node->print() == "Num") { Num* num = static_cast(node); @@ -46,12 +53,15 @@ namespace interpreter { else if (node->print() == "Assign") visit_Assign(*static_cast(node)); else if (node->print() == "NoOp") visit_NoOp(); else if (node->print() == "Print") visit_Print(*static_cast(node)); + else if (node->print() == "FunctionDecl") visit_FunctionDecl(*static_cast(node)); + else if (node->print() == "FunctionCall") visit_FunctionCall(*static_cast(node)); else { std::string error = "Error: void operation not recognized"; throw error; } } else if constexpr (std::is_same_v || std::is_same_v) { + // cout << "Visiting number: " << node->print() << endl; if (node->print() == "BinOp") { BinOp binOp = *static_cast(node); return visit_BinOp(binOp); @@ -78,7 +88,33 @@ namespace interpreter { throw error; } } + void visit_FunctionDecl(FunctionDecl functionDecl) { + + } + void visit_FunctionCall(FunctionCall functionCall) { + std::string proc_name = functionCall.proc_name; + // cout << proc_name << endl; + ActivationRecord ar(ARType::FUNCTION, 2, proc_name); + ProcedureSymbol proc_symbol = functionCall.procSymbol; + // // cout << proc_symbol.print() << endl; + std::vector formal_params = proc_symbol.params; + std::vector actual_params = functionCall.params; + for (int i = 0; i < formal_params.size(); i++) { + if (formal_params[i].type->name == "int") ar[formal_params[i].name] = visit(actual_params[i]); + else if (formal_params[i].type->name == "real") ar[formal_params[i].name] = visit(actual_params[i]); + else if (formal_params[i].type->name == "string") ar[formal_params[i].name] = visit(actual_params[i]); + } + stack.push(ar); + ar = stack.peek(); + // cout << std::get(ar["bar"]) << endl; + // cout << "AR Done!" << endl; + // cout << std::get(ar["bar"]) << endl; + visit_Block(proc_symbol.blockAst); + // cout << "Block done!" << endl; + stack.pop(); + } void visit_Print(Print p) { + // cout << p.str.raw << endl; cout << visit_String(p.str); cout << endl; } @@ -86,10 +122,14 @@ namespace interpreter { int expr_index = 0; std::string result = ""; for (int i = 0; i < str.raw.size(); i++) { + // cout << str.raw[i]; if (str.raw[i] == '{') { AstNode* node = str.expr[expr_index]; + // cout << boolalpha << (node == nullptr) << endl << node->print() << endl; expr_index++; + // cout << getType(node) << endl; if (getType(node) == "int") { + // cout << visit(node) << endl; result += std::to_string(visit(node)); } else if (getType(node) == "real") { @@ -102,6 +142,7 @@ namespace interpreter { } else result += str.raw[i]; } + // cout << result << endl; return result; } template @@ -183,23 +224,30 @@ namespace interpreter { } } void visit_Block(Block block) { + ActivationRecord ar = stack.peek(); + // cout << std::get(ar["bar"]) << endl; + // cout << "Visiting block..." << endl; for (AstNode* child : block.children) { + // cout << "Visiting child..." << endl; + // cout << child->print() << endl; visit(child); } } void visit_Assign(class Assign assign) { std::string var_name = assign.var.value; - std::string type = symTab.lookup(var_name)->type->name; + std::string type = types[var_name]; + ActivationRecord& ar = stack.peek(); if (type == "int") { - GLOBAL_SCOPE[var_name] = visit(assign.right); + ar[var_name] = visit(assign.right); return; } else if (type == "real") { - GLOBAL_SCOPE[var_name] = visit(assign.right); + ar[var_name] = visit(assign.right); return; } else if (type == "string") { - GLOBAL_SCOPE[var_name] = visit_String(*static_cast(assign.right)); + ar[var_name] = visit_String(*static_cast(assign.right)); + return; } else { std::string error("Var type not supported"); @@ -208,20 +256,22 @@ namespace interpreter { } template T visit_Var(Var var) { - if (GLOBAL_SCOPE.find(var.value) != GLOBAL_SCOPE.end()) { + ActivationRecord& ar = stack.peek(); + // if (ar.name == "foo") cout << std::get(ar["bar"]) << endl; + if (ar.members.find(var.value) != ar.members.end()) { if constexpr (std::is_same_v) { - std::string type = symTab.lookup(var.value)->type->name; - if (type == "int") return (T)std::get(GLOBAL_SCOPE[var.value]); + std::string type = types[var.value]; + if (type == "int") return (T)std::get(ar[var.value]); else { std::string error("Wanted integer, got " + type); throw error; } } else if constexpr (std::is_same_v) { - std::string type = symTab.lookup(var.value)->type->name; - if (type == "real") return (T)std::get(GLOBAL_SCOPE[var.value]); + std::string type = types[var.value]; + if (type == "real") return (T)std::get(ar[var.value]); else if (type == "int") { - return (T)std::get(GLOBAL_SCOPE[var.value]); + return (T)std::get(ar[var.value]); } else { std::string error("Wanted real, got " + type); @@ -229,8 +279,8 @@ namespace interpreter { } } else if constexpr (std::is_same_v) { - std::string type = symTab.lookup(var.value)->type->name; - if (type == "string") return std::get(GLOBAL_SCOPE[var.value]); + std::string type = types[var.value]; + if (type == "string") return std::get(ar[var.value]); else { std::string error("Wanted string, got " + type); throw error; @@ -248,14 +298,31 @@ namespace interpreter { } void visit_NoOp() {} void interpret() { - Block block = parser.parseProgram(); + Program p; + try { + p = parser.parseProgram(); + } + catch (std::string error) { + cout << error << endl; + return; + } SymbolTableBuilder symtabBuilder("global", 1); - //std::cout << "Building symtab...\n"; - symtabBuilder.visit(&block); - //std::cout << "Finished building symtab...\n"; - symTab = symtabBuilder.symtab; - //std::cout << "Interpreting...\n"; - visit_Block(block); + //std::// cout << "Building symtab...\n"; + try { + symtabBuilder.visit(&p); + } + catch (std::string error) { + cout << error << endl; + return; + } + //std::// cout << "Finished building symtab...\n"; + types = symtabBuilder.types; + //std::// cout << "Interpreting...\n"; + ARType t = ARType::PROGRAM; + ActivationRecord ar(t, 1); + stack.push(ar); + visit_Block(p.block); + stack.pop(); } }; } \ No newline at end of file diff --git a/Lexer/Lexer.h b/Lexer/Lexer.h index 7fc8b3e..9f00042 100644 --- a/Lexer/Lexer.h +++ b/Lexer/Lexer.h @@ -36,6 +36,9 @@ class Lexer { int getCol () { return column; } + char getChar() { + return input[position]; + } vector allTokens () { vector tokens; Token currentToken; diff --git a/Parser/astnodes.h b/Parser/astnodes.h index 262ef19..6387911 100644 --- a/Parser/astnodes.h +++ b/Parser/astnodes.h @@ -2,6 +2,7 @@ #include #include #include "../Lexer/tokens.h" +#include "../Interpreter/Symbols.h" class AstNode { private: std::string type; @@ -146,12 +147,13 @@ class VarDecl : public AstNode { return s; } }; -class ProcedureDecl; +class FunctionDecl; + class Block : public AstNode { public: std::vector children; std::vector declarations; - std::vector procedures; + std::vector procedures; Block () {} Block(std::vector d) : declarations(d) {} void append(AstNode* node) { @@ -168,16 +170,52 @@ class Block : public AstNode { return s; } }; -class ProcedureDecl : public AstNode { +class ProcedureSymbol : public Symbol { +public: + std::vector params; + ProcedureSymbol(std::string name, std::vector p) : Symbol(name), params(p) { + } + ProcedureSymbol(std::string name) : Symbol(name) { + } + ProcedureSymbol() {} + Block blockAst; +}; +class Program : public AstNode { +public: + Block block; + Program(Block b) : block(b) {} + Program() {} + std::string print() { + return "Program"; + } +}; +class FunctionDecl : public AstNode { public: Block block; + std::vector params; std::string name; - ProcedureDecl(std::string n, Block b) : block(b) { + FunctionDecl(std::string n, Block b, std::vector p) : block(b) { name = n; + params = p; + } + std::string print() { + return "FunctionDecl"; + } +}; +class FunctionCall : public AstNode { +public: + std::string proc_name; + std::vector params; + Token token; + FunctionCall(std::string proc_name, std::vector params, Token token) { + this->proc_name = proc_name; + this->params = params; + this->token = token; } std::string print() { - return "ProcedureDecl"; + return "FunctionCall"; } + ProcedureSymbol procSymbol; }; diff --git a/Parser/parser.h b/Parser/parser.h index 5b10e54..deb3ebe 100644 --- a/Parser/parser.h +++ b/Parser/parser.h @@ -10,19 +10,19 @@ class Parser { currentToken = lexer.nextToken(); } void error (TokenType expected, TokenType received) { - std::string error = "Invalid syntax: Expected " + std::to_string(expected) + ", got " + std::to_string(received); + std::string error = "Invalid syntax: Expected " + std::to_string(expected) + ", got " + std::to_string(received) + " " + currentToken.value; throw error; } void eat (TokenType type) { 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); @@ -70,26 +70,57 @@ class Parser { while (currentToken.type == INT || currentToken.type == REAL || currentToken.type == STRING) { std::vector line = parseVarDeclarations(); + eat(Semicolon); decl.insert(decl.end(), line.begin(), line.end()); } } return decl; } - std::vector parseFunctions() { - std::vector declarations; + std::vector parseFormalParameters() { + std::vector decl; + while (currentToken.type == INT || currentToken.type == REAL || currentToken.type == STRING) + { + std::vector line = parseVarDeclarations(); + decl.insert(decl.end(), line.begin(), line.end()); + if (currentToken.type != Semicolon) break; + else eat(Semicolon); + } + + return decl; + } + std::vector parseFunctions() { + std::vector declarations; while (currentToken.type == FUNCTION) { eat(FUNCTION); std::string proc_name = currentToken.value; eat(Identifier); eat(LeftParenthesis); + std::vector params = parseFormalParameters(); eat(RightParenthesis); Block block = parseBlock(); - ProcedureDecl* proc_decl = new ProcedureDecl(proc_name, block); + FunctionDecl* proc_decl = new FunctionDecl(proc_name, block, params); declarations.push_back(proc_decl); } return declarations; } + FunctionCall parseFunctionCall() { + Token token = currentToken; + std::string proc_name = token.value; + eat(Identifier); + eat(LeftParenthesis); + vector params; + if (currentToken.type != RightParenthesis) { + params.push_back(parseExpression()); + } + while (currentToken.type == Comma) { + eat(Comma); + params.push_back(parseExpression()); + } + eat(RightParenthesis); + FunctionCall procCall(proc_name, params, token); + return procCall; + } std::vector parseVarDeclarations() { Type type = parseType(); eat(Colon); @@ -101,7 +132,6 @@ class Parser { declarations.push_back(Var(currentToken)); eat(Identifier); } - eat(Semicolon); std::vector var_decl(declarations.size()); for (unsigned int i = 0; i < var_decl.size(); i++) { VarDecl varDecl(type, declarations[i]); @@ -128,7 +158,8 @@ class Parser { return node; } if (currentToken.type == Identifier) { - node = new class Assign(parseAssignment()); + if (lexer.getChar() == '(') node = new FunctionCall(parseFunctionCall()); + else node = new class Assign(parseAssignment()); return node; } else { diff --git a/main.cpp b/main.cpp index 508d7d3..8a2aa89 100644 --- a/main.cpp +++ b/main.cpp @@ -26,50 +26,50 @@ int interpret(string input) { vector 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]; + // cout << tokens[i]; } Parser parser(input); - Block block; + Program program; try { - block = parser.parseProgram(); + program = parser.parseProgram(); } catch (string error) { - cout << error << "\n"; + // cout << error << "\n"; return 1; } - cout << "Parser blocks:" << endl; + // cout << "Parser blocks:" << endl; for (int i = 0; i < block.size(); i++) { - cout << block[i]->print() << endl; - } + // cout << block[i]->print() << endl; + }*/ Interpreter interpreter(input); - cout << "Interpreting...\n"; + // // cout << "Interpreting...\n"; try { interpreter.interpret(); } catch (std::string error) { - cout << error << "\n"; + // cout << error << "\n"; return 1; } - cout << "Variables: " << endl; + /*// cout << "Variables: " << endl; ScopedSymbolTable symtab = interpreter.getSymTab(); - cout << symtab.print(); + // cout << symtab.print(); for (auto const& pair : interpreter.GLOBAL_SCOPE) { - cout << pair.first << " "; + // cout << pair.first << " "; std::string type = symtab.lookup(pair.first)->type->name; if (type == "int") { - cout << std::get(pair.second); + // cout << std::get(pair.second); } else if (type == "real") { - cout << std::get(pair.second); + // cout << std::get(pair.second); } else if (type == "string") { - cout << std::get(pair.second); + // cout << std::get(pair.second); } - cout << endl; - } + // cout << endl; + }*/ return 0; } int main (int argc, char** argv) { diff --git a/test.spark b/test.spark index 2c2eb20..b07f59b 100644 --- a/test.spark +++ b/test.spark @@ -3,11 +3,16 @@ int: a, c, d; real: b; string: test, multi; - def foo () { - program: + def foo (int: bar) { + def sub (int: asdf) { + program: + print('{asdf}'); } + program: + sub(bar); } program: #this is a comment# a = 1*1+4//-2; + foo(a); b = -13+4.5; test = 'The value of a is {a}, and the value of b is {b}'; multi = 'a*b={a*b}';