From 20547f2b600d9ef21efec66d24607b349827741c Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Wed, 8 Nov 2023 06:03:04 -0800 Subject: [PATCH 1/6] update --- src/calc.cpp | 35 +- src/dumped/lex.cpp | 43 ++ src/dumped/parse.cpp | 63 ++ src/format.cpp | 118 ++++ src/lex.cpp | 22 +- src/lib/ASTNode.h | 86 +++ src/lib/DataType.h | 11 + src/lib/Function.h | 13 + src/lib/Lexer.cpp | 146 ++--- src/lib/Lexer.h | 60 +- src/lib/ParserB.cpp | 1355 +++++++++++++++++++++++++++++++----------- src/lib/ParserB.h | 53 +- src/lib/Scope.h | 59 ++ src/main | Bin 0 -> 420440 bytes src/scrypt.cpp | 97 +++ src/test.cpp | 69 +++ 16 files changed, 1728 insertions(+), 502 deletions(-) create mode 100644 src/dumped/lex.cpp create mode 100644 src/dumped/parse.cpp create mode 100644 src/lib/ASTNode.h create mode 100644 src/lib/DataType.h create mode 100644 src/lib/Function.h create mode 100644 src/lib/Scope.h create mode 100644 src/main create mode 100644 src/test.cpp diff --git a/src/calc.cpp b/src/calc.cpp index c05e55a..6c7cd6a 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -24,8 +24,9 @@ int main() { //std::string input = "(((a / 4) + (c / 3))"; //std::string input = "88=mgh\n=\n=x\n=4321\nx=\nx = y =\n88 = mph"; //std::string input = "x = y = 0 + 1 + 2 * 3 - 4 / (5 + 6)\nb=13\n(7 - (b = (b + 5)))\n1 % 114514\n\n1=a\n1+1\n"; - std::string input = "(x = 10)\n(y = 57)\n(z = 16)\n((((x = 3) + (y = 5)) + w) + (z = 145))\n((x + y) + z)"; - //std::string input = "()+)"; + // std::string input = "1==false"; + // std::string input = "(1 == 2)"; + std::string input = "x = 42\nx % 2 != 0"; #endif @@ -60,40 +61,38 @@ int main() { continue; } - ParserB::setupExpressionInfix(TokenVector); - // ParserB - Node root; - std::pair, std::string> errorResult = ParserB::MakeTreeInfix(TokenVector, 0, TokenVector.size() - 2, root); + ParserB::setupExpression(TokenVector); + std::unique_ptr root; + std::pair, std::string> errorResult = ParserB::MakeExpressionTree(TokenVector, 0, TokenVector.size() - 2, root); if (errorResult.first.first != -1) { std::cout << "Unexpected token at line " << errorResult.first.first << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; continue; } - ParserB::print(root); + ParserB::print(root.get()); std::cout << std::endl; // Calculate - double result; - std::map originalVariableMap(ParserB::variableMap); - std::map originalVariableInitializedMap(ParserB::variableInitializedMap); - std::string errorMessage = ParserB::calculate(root, result); + Result result; + std::map originalVariableTypeMap(ParserB::variableTypeMap); + std::map originalVariableDoubleMap(ParserB::variableDoubleMap); + std::map originalVariableBoolMap(ParserB::variableBoolMap); - if (errorMessage == "114514") - { - std::cout << input << std::endl; - } + std::string errorMessage = ParserB::calculate(root.get(), result); if (errorMessage.length() != 0) { std::cout << errorMessage << std::endl; - ParserB::variableMap.swap(originalVariableMap); - ParserB::variableInitializedMap.swap(originalVariableInitializedMap); + ParserB::variableTypeMap.swap(originalVariableTypeMap); + ParserB::variableDoubleMap.swap(originalVariableDoubleMap); + ParserB::variableBoolMap.swap(originalVariableBoolMap); continue; } - std::cout << result << std::endl; + ParserB::printValue(result); + std::cout << std::endl; } return 0; } \ No newline at end of file diff --git a/src/dumped/lex.cpp b/src/dumped/lex.cpp new file mode 100644 index 0000000..83afbfb --- /dev/null +++ b/src/dumped/lex.cpp @@ -0,0 +1,43 @@ +#include "lib/Lexer.h" + +int main() { + +#if DEBUG == 0 + std::string input = ""; + std::string line; + + while(!std::cin.eof()) { + char c; + std::cin.get(c); + line = std::string(1, c); + input += line; + } + input = input.substr(0, input.size()-1); +#endif +#if DEBUG == 1 + + //std::string input = "(* (+ 1 2) 3 (/ 4 5 (- 6 7)))\n(* (+ 1 2) 3 (/ 4 5 (- 6 7)))\n(* (+ 1 2) 3 (/ 4 5 (- 6 7)))"; + //std::string input = "(= a b 3)"; + //std::string input = "(- (= b (+ b 5)) 7)"; + //std::string input = "(* a b)"; + //std::string input = "(= foo_ b 3)\n( + b 0 )\n(- (= b (+ b 5)) 7)\n(* foo b)\n"; + std::string input = R"((x = 42) +(steps = 0) +while (x > 1) { + (steps = (steps + 1)) + if ((x % 2) == 0) { + (x = (x / 2)) + } + else { + (x = ((3 * x) + 1)) + } +} +print steps)"; + //std::string input = "(=(n) 9)"; +#endif + std::vector TokenVector; + std::pair errorPair = Token::GenTokenVector(input, TokenVector); + + Token::printLexer(TokenVector); + return 0; +} diff --git a/src/dumped/parse.cpp b/src/dumped/parse.cpp new file mode 100644 index 0000000..891819e --- /dev/null +++ b/src/dumped/parse.cpp @@ -0,0 +1,63 @@ +#include "lib/Parser.h" + +int main() { +#if DEBUG == 0 + std::string input = ""; + std::string line; + + while(!std::cin.eof()) { + char c; + std::cin.get(c); + line = std::string(1, c); + input += line; + } + input = input.substr(0, input.size()-1); + // std::cout << "LOLOLOLOLOLOLOLOLO" << std::endl; + // std::cout << input << std::endl; + // std::cout << "LOLOLOLOLOLOLOLOLO" << std::endl; +#endif +#if DEBUG == 1 + + //std::string input = "(* (+ 1 2) 3 (/ 4 5 (- 6 7)))\n(* (+ 1 2) 3 (/ 4 5 (- 6 7)))\n(* (+ 1 2) 3 (/ 4 5 (- 6 7)))"; + //std::string input = "(= a b 3)"; + //std::string input = "(- (= b (+ b 5)) 7)"; + //std::string input = "(* a b)"; + //std::string input = "9\n(= foo b 3)\n( + b 0 )\n(- (= b (+ b 5)) 7)\n(* foo b)\n"; + std::string input = "(=9 a)"; + // std::string input = "\t \n ( - 3 -)"; + //std::string input = "( = ( + x ) 89 )"; + //std::string input = "( = a ( + 2 2 ) 4 )"; + //std::string input = "12\n"; + //std::string input = " \n (- 1 10)\n"; + // std::string input = "(=(n) 9)"; +#endif + + if (input.size() == 0) { std::cout << "Unexpected token at line 1 column 1: END" << std::endl; return 2; } + + std::vector TokenVector; + std::pair errorPair = Token::GenTokenVector(input, TokenVector); + + int errorLine = errorPair.first; + int errorIndex = errorPair.second; + + if (errorLine != -1) + { + std::cout << "Syntax error on line " << errorLine << " column " << errorIndex << "." << std::endl; + exit(1); + } + + Parser::setupExpression(TokenVector); + //std::cout << Parser::expressionLines.size() << std::endl; + for (std::vector expressionLine : Parser::expressionLines) + { + // Token::printLexer(expressionLine); + // std::cout << "==================" << std::endl; + + Node root = Parser::MakeTree(expressionLine, 0, expressionLine.size() - 2); + Parser::print(root); + std::cout << std::endl; + std::cout << Parser::calculate(root) << std::endl; + } + + return 0; +} diff --git a/src/format.cpp b/src/format.cpp index e69de29..b0c2aef 100644 --- a/src/format.cpp +++ b/src/format.cpp @@ -0,0 +1,118 @@ +#include "lib/ParserB.h" + +int main() { +#if DEBUG == 0 + std::string input = ""; + std::string line; + + while(!std::cin.eof()) { + char c; + std::cin.get(c); + line = std::string(1, c); + input += line; + } + input = input.substr(0, input.size()-1); +#endif +#if DEBUG == 1 +// std::string input = R"(x = 42 +// steps = 0 + +// while x > 1 { +// steps = steps + 1 +// if x % 2 == 0 { +// x = x / 2 +// } +// else { +// x = 3 * x + 1 +// } +// } + +// print steps)"; + +// std::string input = R"( +// val = 105 +// fizz = val % 3 == 0 +// buzz = false +// if val % 5 == 0 { +// buzz = true +// } + +// if fizz & buzz { +// if buzz { +// print 333555 +// } +// else { +// print 333 +// } +// } +// else if buzz { +// print 555 +// } +// else { +// print val +// })"; + +// std::string input = R"( +// a = 0 +// if (a == 0) { +// print 0 +// } else if (a == 1) { +// print 11 +// } else { +// print 222 +// } +// print a +// )"; + + std::string input = R"( +z = 42 + +def foo(x, y) { + def square(value) { + return value * value + } + + print square(x + y + z) +} + +z = 108 +f = foo +print 1 + )"; + +// std::string input = R"( +// x=1 +// y=2 + +// def add(a, b) { +// return a+b +// } +// )"; + +#endif + + std::vector TokenVector; + std::pair errorPair = Token::GenTokenVector(input, TokenVector); + + if (errorPair.first != -1) + { + std::cout << "Syntax error on line " << errorPair.first << " column " << errorPair.second << "." << std::endl; + exit(1); + } + // Token::printLexer(TokenVector); + + std::vector> flows; + std::pair, std::string> errorResult = ParserB::HandleTokenVector(TokenVector, 0, TokenVector.size()-2, flows); + if (errorResult.first.first != -1) + { + std::cout << "Unexpected token at line " << errorResult.first.first << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; + exit(2); + } + + for (int i=0; i < (int)flows.size(); i++) + { + ParserB::print(flows[i].get()); + std::cout << std::endl; + } + return 0; +} \ No newline at end of file diff --git a/src/lex.cpp b/src/lex.cpp index ad9bba2..81c84a3 100644 --- a/src/lex.cpp +++ b/src/lex.cpp @@ -1,7 +1,5 @@ #include "lib/Lexer.h" - int main() { - #if DEBUG == 0 std::string input = ""; std::string line; @@ -18,13 +16,25 @@ int main() { // std::cout << "LOLOLOLOLOLOLOLOLO" << std::endl; #endif #if DEBUG == 1 - + //std::string input = "(* (+ 1 2) 3 (/ 4 5 (- 6 7)))\n(* (+ 1 2) 3 (/ 4 5 (- 6 7)))\n(* (+ 1 2) 3 (/ 4 5 (- 6 7)))"; //std::string input = "(= a b 3)"; //std::string input = "(- (= b (+ b 5)) 7)"; //std::string input = "(* a b)"; //std::string input = "(= foo_ b 3)\n( + b 0 )\n(- (= b (+ b 5)) 7)\n(* foo b)\n"; - std::string input = " !===!==>=<-=>=<<>>==^^!=|&<>"; + //std::string input = "a\n"; + std::string input = R"((x = 42) +(steps = 0) +while (x > 1) { + (steps = (steps + 1)) + if ((x % 2) == 0) { + (x = (x / 2)) + } + else { + (x = ((3 * x) + 1)) + } +} +print steps)"; //std::string input = "(=(n) 9)"; #endif @@ -33,13 +43,11 @@ int main() { int errorLine = errorPair.first; int errorIndex = errorPair.second; - if (errorLine != -1) { std::cout << "Syntax error on line " << errorLine << " column " << errorIndex << "." << std::endl; exit(1); } - Token::printLexer(TokenVector); return 0; -} +} \ No newline at end of file diff --git a/src/lib/ASTNode.h b/src/lib/ASTNode.h new file mode 100644 index 0000000..b2fdf89 --- /dev/null +++ b/src/lib/ASTNode.h @@ -0,0 +1,86 @@ +#pragma once + + +#include + +#include "Lexer.h" + +class Node +{ +public: + Node() : value(Token(TokenType::NONE, "", -1, -1, -1)) {} + Node(Token token) : value(token) {} + virtual ~Node() = default; + + Token value; +}; + +// An operation expression node should always have 2 children +// A function call expression: Node1: function. Node2, 3...: parameters. +// A function call expression must have a variable token and children.size() != 0 +class ExpressionNode : public Node +{ +public: + ExpressionNode() : Node(), children() {} + ExpressionNode(Token token) : Node(token), children() {} + virtual ~ExpressionNode() = default; + + std::vector> children; +}; + + +class WhileNode : public Node +{ +public: + WhileNode() : Node(), condition(std::make_unique()), flows() {} + WhileNode(Token token) : Node(token), condition(std::make_unique()), flows() {} + virtual ~WhileNode() = default; + + std::unique_ptr condition; + std::vector> flows; // expressions and statements inside {...} +}; + + +class IfNode : public Node +{ +public: + IfNode() : Node(), conditions(), flowGroups() {} + IfNode(Token token) : Node(token), conditions(), flowGroups() {} + virtual ~IfNode() = default; + + std::vector> conditions; + std::vector>> flowGroups; // groups of expressions and statements inside each {...} +}; + + +class PrintNode : public Node +{ +public: + PrintNode() : Node(), content(std::make_unique()) {} + PrintNode(Token token) : Node(token), content(std::make_unique()) {} + virtual ~PrintNode() = default; + + std::unique_ptr content; +}; + +class ReturnNode : public Node +{ +public: + ReturnNode() : Node(), content(std::make_unique()) {} + ReturnNode(Token token) : Node(token), content(std::make_unique()) {} + virtual ~ReturnNode() = default; + + std::unique_ptr content; +}; + +class FunctionDefineNode : public Node +{ +public: + FunctionDefineNode() : Node(), functionName(), parameterNames(), flows() {} + FunctionDefineNode(Token token) : Node(token), functionName(), parameterNames(), flows() {} + virtual ~FunctionDefineNode() = default; + + std::string functionName; + std::vector parameterNames; + std::vector> flows; +}; \ No newline at end of file diff --git a/src/lib/DataType.h b/src/lib/DataType.h new file mode 100644 index 0000000..3877bf9 --- /dev/null +++ b/src/lib/DataType.h @@ -0,0 +1,11 @@ +#pragma once + +enum class DataType +{ + NONE, + NUL, + UNINITIALIZED, + BOOL, + DOUBLE, + FUNCTION, +}; \ No newline at end of file diff --git a/src/lib/Function.h b/src/lib/Function.h new file mode 100644 index 0000000..c763381 --- /dev/null +++ b/src/lib/Function.h @@ -0,0 +1,13 @@ +#pragma once +#include "ASTNode.h" +#include "Scope.h" + +class Function +{ +public: + Function() = default; + std::vector m_ParameterNames; + std::vector> m_FunctionFlows; + + Scope m_CaptureScope; +}; \ No newline at end of file diff --git a/src/lib/Lexer.cpp b/src/lib/Lexer.cpp index 90b87dd..d96670c 100644 --- a/src/lib/Lexer.cpp +++ b/src/lib/Lexer.cpp @@ -1,5 +1,4 @@ #include "Lexer.h" -#include "Utils.h" Token::Token(TokenType itype, std::string icontent, int iline, int iindex, double ivalue) : type(itype), content(icontent), line(iline), index(iindex), value(ivalue) @@ -26,65 +25,6 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< for (int i = 0; i < len; i++) { - // std::cout << (int)input.at(i) << std::endl; - - // record while - if ((input.at(i) == 'w')){ - if (!recordingNumber && !recordingVariable && i + 4 < len){ - if (input.substr(i,5) == "while"){ - if (i + 5 < len && input.substr(i,6) == "while "){ - res.emplace_back(TokenType::WHILE, "while", line, index, -1); - i = i + 5; - index = index + 6; - continue; - } - else if (i + 5 == len){ - res.emplace_back(TokenType::WHILE, "while", line, index, -1); - index = index + 5; - break; - } - } - } - } - - // record if - if ((input.at(i) == 'i')){ - if (!recordingNumber && !recordingVariable && i + 1 < len){ - if (input.substr(i,2) == "if"){ - if (i + 2 < len && input.substr(i,3) == "if "){ - res.emplace_back(TokenType::IF, "if", line, index, -1); - i = i + 2; - index = index + 3; - continue; - } - else if (i + 2 == len){ - res.emplace_back(TokenType::IF, "if", line, index, -1); - index = index + 2; - break; - } - } - } - } - - // record else - if ((input.at(i) == 'e')){ - if (!recordingNumber && !recordingVariable && i + 3 < len){ - if (input.substr(i,4) == "else"){ - if (i + 4 < len && input.substr(i,5) == "else "){ - res.emplace_back(TokenType::ELSE, "else", line, index, -1); - i = i + 4; - index = index + 5; - continue; - } - else if (i + 4 == len){ - res.emplace_back(TokenType::ELSE, "else", line, index, -1); - index = index + 4; - break; - } - } - } - } - // variable if ((input.at(i) >= 'a' && input.at(i) <= 'z') || (input.at(i) >= 'A' && input.at(i) <= 'Z') || input.at(i) == '_') { @@ -139,7 +79,6 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< // nothing before a point if (!recordingNumber) { - // if there's error, the last token would be ERROR instead of END #if DEBUG std::cout << "2" << std::endl; #endif @@ -148,7 +87,6 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< // already have a point if (afterPoint) { - // if there's error, the last token would be ERROR instead of END #if DEBUG std::cout << "3" << std::endl; #endif @@ -166,18 +104,16 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< // ERROR if point not followed by a number if (recordingNumber && currentStringValue.back() == '.') { - // if there's error, the last token would be ERROR instead of END #if DEBUG std::cout << "4" << std::endl; #endif return { line, index }; } - // number ends // the last digit is recorded if (recordingNumber) { - res.emplace_back(TokenType::number, currentStringValue, line, index - numberLength, currentValue); + res.emplace_back(TokenType::NUMBER, currentStringValue, line, index - numberLength, currentValue); recordingNumber = false; afterPoint = false; currentValue = 0; @@ -188,7 +124,16 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< // variable ends // the last character of variable is recorded if (recordingVariable) { - res.emplace_back(TokenType::variable, variableName, line, index - variableLength, -1); + if (variableName == "while") { res.emplace_back(TokenType::WHILE, variableName, line, index - variableLength, -1); } + else if (variableName == "if") { res.emplace_back(TokenType::IF, variableName, line, index - variableLength, -1); } + else if (variableName == "else") { res.emplace_back(TokenType::ELSE, variableName, line, index - variableLength, -1); } + else if (variableName == "true") { res.emplace_back(TokenType::TRUE, variableName, line, index - variableLength, 1); } + else if (variableName == "false") { res.emplace_back(TokenType::FALSE, variableName, line, index - variableLength, 0); } + else if (variableName == "print") { res.emplace_back(TokenType::PRINT, variableName, line, index - variableLength, -1); } + else if (variableName == "def") { res.emplace_back(TokenType::DEF, variableName, line, index - variableLength, -1); } + else if (variableName == "null") { res.emplace_back(TokenType::NUL, variableName, line, index - variableLength, -1); } + else if (variableName == "return") { res.emplace_back(TokenType::RETURN, variableName, line, index - variableLength, -1); } + else { res.emplace_back(TokenType::VARIABLE, variableName, line, index - variableLength, -1); } recordingVariable = false; variableName = ""; variableLength = 0; @@ -208,37 +153,37 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< else if (input.at(i) == '=') { if ( i + 1 < len && input.at(i+1) == '='){ - res.emplace_back(TokenType::equality,"==", line, index, -1); + res.emplace_back(TokenType::EQUALITY,"==", line, index, -1); i++; index++; } else{ - res.emplace_back(TokenType::equals, "=", line, index, -1); + res.emplace_back(TokenType::ASSIGNMENT, "=", line, index, -1); } } else if (input.at(i) == '>'){ if ( i + 1 < len && input.at(i+1) == '='){ - res.emplace_back(TokenType::bigger_equal,">=", line, index, -1); + res.emplace_back(TokenType::BIGGER_EQUAL,">=", line, index, -1); i++; index++; } else{ - res.emplace_back(TokenType::bigger, ">", line, index, -1); + res.emplace_back(TokenType::BIGGER, ">", line, index, -1); } } else if (input.at(i) == '<'){ if ( i + 1 < len && input.at(i+1) == '='){ - res.emplace_back(TokenType::smaller_equal,"<=", line, index, -1); + res.emplace_back(TokenType::SMALLER_EQUAL,"<=", line, index, -1); i++; index++; } else{ - res.emplace_back(TokenType::smaller, "<", line, index, -1); + res.emplace_back(TokenType::SMALLER, "<", line, index, -1); } } else if (input.at(i) == '!'){ if ( i + 1 < len && input.at(i+1) == '='){ - res.emplace_back(TokenType::inequality,"!=", line, index, -1); + res.emplace_back(TokenType::INEQUALITY,"!=", line, index, -1); i++; index++; } @@ -252,52 +197,59 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< } else if (input.at(i) == '|') { - res.emplace_back(TokenType::inclusive_or, "|", line, index, -1); + res.emplace_back(TokenType::INCLUSIVE_OR, "|", line, index, -1); } else if (input.at(i) == '^') { - res.emplace_back(TokenType::exclusive_or, "^", line, index, -1); + res.emplace_back(TokenType::EXCLUSIVE_OR, "^", line, index, -1); } else if (input.at(i) == '+') { - res.emplace_back(TokenType::plus, "+", line, index, -1); + res.emplace_back(TokenType::PLUS, "+", line, index, -1); } else if (input.at(i) == '-') { - res.emplace_back(TokenType::minus, "-", line, index, -1); + res.emplace_back(TokenType::MINUS, "-", line, index, -1); } else if (input.at(i) == '*') { - res.emplace_back(TokenType::multiply, "*", line, index, -1); + res.emplace_back(TokenType::MULTIPLY, "*", line, index, -1); } else if (input.at(i) == '/') { - res.emplace_back(TokenType::divide, "/", line, index, -1); + res.emplace_back(TokenType::DIVIDE, "/", line, index, -1); } else if (input.at(i) == '%') { - res.emplace_back(TokenType::mod, "%", line, index, -1); + res.emplace_back(TokenType::MOD, "%", line, index, -1); } else if (input.at(i) == '(') { - res.emplace_back(TokenType::leftParenthesis, "(", line, index, -1); + res.emplace_back(TokenType::LEFT_PARENTHESIS, "(", line, index, -1); } else if (input.at(i) == ')') { - res.emplace_back(TokenType::rightParenthesis, ")", line, index, -1); + res.emplace_back(TokenType::RIGHT_PARENTHESIS, ")", line, index, -1); } else if (input.at(i) == '{') { - res.emplace_back(TokenType::leftBracket, "{", line, index, -1); + res.emplace_back(TokenType::LEFT_BRACE, "{", line, index, -1); } else if (input.at(i) == '}') { - res.emplace_back(TokenType::rightBracket, "}", line, index, -1); + res.emplace_back(TokenType::RIGHT_BRACE, "}", line, index, -1); + } + else if (input.at(i) == ',') + { + res.emplace_back(TokenType::COMMA, ",", line, index, -1); + } + else if (input.at(i) == ';') + { + res.emplace_back(TokenType::SEMICOLON, ";", line, index, -1); } // Error else { - // if there's error, the last token would be ERROR instead of END #if DEBUG std::cout << "5" << std::endl; #endif @@ -310,7 +262,6 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< // final checks if (recordingNumber && currentStringValue.back() == '.') { - // if there's error, the last token would be ERROR instead of END #if DEBUG std::cout << "6" << std::endl; #endif @@ -319,25 +270,26 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< // the last digit is recorded if (recordingNumber) { - res.emplace_back(TokenType::number, currentStringValue, line, index - numberLength, currentValue); - recordingNumber = false; - afterPoint = false; - currentValue = 0; - currentStringValue = ""; - numberLength = 0; + res.emplace_back(TokenType::NUMBER, currentStringValue, line, index - numberLength, currentValue); } // variable ends // the last character of variable is recorded if (recordingVariable) { - res.emplace_back(TokenType::variable, variableName, line, index - variableLength, -1); - recordingVariable = false; - variableName = ""; - variableLength = 0; + if (variableName == "while") { res.emplace_back(TokenType::WHILE, variableName, line, index - variableLength, -1); } + else if (variableName == "if") { res.emplace_back(TokenType::IF, variableName, line, index - variableLength, -1); } + else if (variableName == "else") { res.emplace_back(TokenType::ELSE, variableName, line, index - variableLength, -1); } + else if (variableName == "true") { res.emplace_back(TokenType::TRUE, variableName, line, index - variableLength, 1); } + else if (variableName == "false") { res.emplace_back(TokenType::FALSE, variableName, line, index - variableLength, 0); } + else if (variableName == "print") { res.emplace_back(TokenType::PRINT, variableName, line, index - variableLength, -1); } + else if (variableName == "def") { res.emplace_back(TokenType::DEF, variableName, line, index - variableLength, -1); } + else if (variableName == "null") { res.emplace_back(TokenType::NUL, variableName, line, index - variableLength, -1); } + else if (variableName == "return") { res.emplace_back(TokenType::RETURN, variableName, line, index - variableLength, -1); } + else { res.emplace_back(TokenType::VARIABLE, variableName, line, index - variableLength, -1); } } - res.emplace_back(TokenType::end, "END", line, index, -1); + res.emplace_back(TokenType::END, "END", line, index, -1); return { -1, -1 }; } diff --git a/src/lib/Lexer.h b/src/lib/Lexer.h index 42541fd..ced420d 100644 --- a/src/lib/Lexer.h +++ b/src/lib/Lexer.h @@ -7,49 +7,59 @@ enum class TokenType { - none, // - variable, // a b c - number, // 1 2 3 + NONE, // + NUL, // function return type + RETURN, + VARIABLE, // a b c + NUMBER, // 1 2 3 - leftParenthesis, // ( - rightParenthesis, // ) + LEFT_PARENTHESIS, // ( + RIGHT_PARENTHESIS, // ) + LEFT_BRACKET, // ( + RIGHT_BRACKET, // ) - multiply, // * - divide, // / - mod, // % + MULTIPLY, // * + DIVIDE, // / + MOD, // % - plus, // + - minus, // - + PLUS, // + + MINUS, // - - smaller, // < - bigger, // > - smaller_equal, // <= - bigger_equal, // >= + SMALLER, // < + BIGGER, // > + SMALLER_EQUAL, // <= + BIGGER_EQUAL, // >= - equality, // == - inequality, // != + EQUALITY, // == + INEQUALITY, // != AND, // & - exclusive_or, // ^ + EXCLUSIVE_OR, // ^ - inclusive_or, // | + INCLUSIVE_OR, // | - equals, // = + ASSIGNMENT, // = - end, // END - error, // ERROR + END, // END + ERROR, // ERROR + COMMA, // , + SEMICOLON, // ; - leftBracket, // { - rightBracket, // } + + + + LEFT_BRACE, // { + RIGHT_BRACE, // } TRUE, FALSE, WHILE, - ELSE, IF, - PRINT + ELSE, + PRINT, + DEF, }; class Token { diff --git a/src/lib/ParserB.cpp b/src/lib/ParserB.cpp index 4a645f6..fe0f49d 100644 --- a/src/lib/ParserB.cpp +++ b/src/lib/ParserB.cpp @@ -1,36 +1,318 @@ #include "ParserB.h" // Initialize static member variables -std::stack jumptoStack = stack(); -int currentLine = 1; -bool skipLine = 1; -std::vector> ParserB::expressionLines = std::vector>(); -std::map ParserB::variableMap = std::map(); -std::map ParserB::variableInitializedMap = std::map(); -std::map ParserB::hierarchyMap = { - {TokenType::number , 0}, // 1 2 3 - {TokenType::variable , 0}, // a b c - {TokenType::leftParenthesis , 1}, // () - {TokenType::multiply , 2}, // * - {TokenType::divide , 2}, // / - {TokenType::mod , 2}, // % - {TokenType::plus , 3}, // + - {TokenType::minus , 3} // - - {TokenType::smaller , 4}, // < - {TokenType::bigger , 4}, // > - {TokenType::smaller_equal , 4}, // <= - {TokenType::bigger_equal , 4}, // >= - {TokenType::equality , 5}, // == - {TokenType::inequality , 5}, // != - {TokenType::and , 6}, // & - {TokenType::exclusive_or , 7} // ^ - {TokenType::inclusive_or , 8}, // | - {TokenType::equals , 9} // = +// std::stack ParserB::ScopeStack = {}; +// ParserB::ScopeStack.push(Scope()); + +std::stack ParserB::ScopeStack = std::stack(); +std::map ParserB::hierarchyMap = { + {TokenType::NUL , 0}, // null + {TokenType::NUMBER , 0}, // 1 2 3 + {TokenType::TRUE , 0}, // true + {TokenType::FALSE , 0}, // false + {TokenType::VARIABLE , 0}, // a b c + {TokenType::LEFT_PARENTHESIS ,1}, // () + {TokenType::MULTIPLY , 2}, // * + {TokenType::DIVIDE , 2}, // / + {TokenType::MOD , 2}, // % + {TokenType::PLUS , 3}, // + + {TokenType::MINUS , 3}, // - + {TokenType::SMALLER , 4}, // < + {TokenType::BIGGER , 4}, // > + {TokenType::SMALLER_EQUAL , 4}, // <= + {TokenType::BIGGER_EQUAL , 4}, // >= + {TokenType::EQUALITY , 5}, // == + {TokenType::INEQUALITY , 5}, // != + {TokenType::AND , 6}, // & + {TokenType::EXCLUSIVE_OR , 7}, // ^ + {TokenType::INCLUSIVE_OR , 8}, // | + {TokenType::ASSIGNMENT , 9} // = }; -std::pair, std::string> ParserB::MakeTreeInfix(std::vector expression, int leftBound, int rightBound, Node& node) +// takes in a node* vector and add elements into it given the tokenVector +std::pair, std::string> ParserB::HandleTokenVector(std::vector tokenVector, int leftBound, int rightBound, std::vector>& nodes) { + int start = leftBound; + while (start < rightBound) + { + // std::cout << start << std::endl; + if (tokenVector[start].type == TokenType::DEF) + { + std::unique_ptr node = std::make_unique(tokenVector[start]); + + int defIndex = start; + // Name + int functionNameIndex = defIndex + 1; + if (tokenVector[functionNameIndex].type != TokenType::VARIABLE) { std::cout << "there is something wrong. def not followed by variable" << std::endl; } + + // (...) + int leftParenthesisIndex = functionNameIndex + 1; + if (tokenVector[leftParenthesisIndex].type != TokenType::LEFT_PARENTHESIS) { std::cout << "there is something wrong. functionname not followed by (" << std::endl; } + int rightParenthesisIndex = findRightParenthesisNoError(tokenVector, leftParenthesisIndex + 1, rightBound); + if (rightParenthesisIndex > rightBound) + { + return { { tokenVector[rightParenthesisIndex].line, tokenVector[rightParenthesisIndex].index }, tokenVector[rightParenthesisIndex].content }; + } + + // {...} + int leftBraceIndex = rightParenthesisIndex + 1; + if (tokenVector[leftBraceIndex].type != TokenType::LEFT_BRACE) { std::cout << "there is something wrong. in function def ) not followed by {" << std::endl; } + int rightBraceIndex = findRightBraceNoError(tokenVector, leftBraceIndex + 1, rightBound); + if (rightBraceIndex > rightBound) + { + return { { tokenVector[rightBraceIndex].line, tokenVector[rightBraceIndex].index }, tokenVector[rightBraceIndex].content }; + } + + + // Node Setup + // Function name + node->functionName = tokenVector[functionNameIndex].content; + + // Function Parameters + int parameterIndex = leftParenthesisIndex + 1; + while (parameterIndex < rightParenthesisIndex) + { + // std::cout << "111" << std::endl; + if (tokenVector[parameterIndex].type == TokenType::COMMA) + { + parameterIndex += 1; + continue; + } + if (tokenVector[parameterIndex].type != TokenType::VARIABLE) + { + return { { tokenVector[parameterIndex].line, tokenVector[parameterIndex].index }, tokenVector[parameterIndex].content }; + } + node->parameterNames.push_back(tokenVector[parameterIndex].content); + parameterIndex += 1; + } + + // Function Flows + std::pair, std::string> errorResultFlows = HandleTokenVector(tokenVector, leftBraceIndex + 1, rightBraceIndex - 1, node->flows); + if (errorResultFlows.first.first != -1) + { + return errorResultFlows; + } + + nodes.push_back(std::move(node)); + start = rightBraceIndex + 1; + } + + else if (tokenVector[start].type == TokenType::WHILE) + { + std::unique_ptr node = std::make_unique(tokenVector[start]); + + // find where { is + int leftBraceIndex = start + 1; + while (leftBraceIndex < rightBound) + { + if (tokenVector[leftBraceIndex].type == TokenType::LEFT_BRACE) { break; } + leftBraceIndex += 1; + } + // { not found + if (leftBraceIndex == rightBound) + { + return { { tokenVector[leftBraceIndex].line, tokenVector[leftBraceIndex].index }, tokenVector[leftBraceIndex].content }; + } + // find } + int rightBraceIndex = findRightBraceNoError(tokenVector, leftBraceIndex + 1, rightBound); + if (rightBraceIndex > rightBound) + { + return { { tokenVector[rightBraceIndex].line, tokenVector[rightBraceIndex].index }, tokenVector[rightBraceIndex].content }; + } + + // condition + std::pair, std::string> errorResultCondition = MakeExpressionTree(tokenVector, start + 1, leftBraceIndex - 1, node->condition); + if (errorResultCondition.first.first != -1) + { + return errorResultCondition; + } + + // statements and expressions inside {...} + std::pair, std::string> errorResultFlows = HandleTokenVector(tokenVector, leftBraceIndex + 1, rightBraceIndex - 1, node->flows); + if (errorResultFlows.first.first != -1) + { + return errorResultFlows; + } + + nodes.push_back(std::move(node)); + start = rightBraceIndex + 1; + } + else if (tokenVector[start].type == TokenType::IF) + { + std::unique_ptr node = std::make_unique(tokenVector[start]); + + // if + // find { + int leftBraceIndex = start + 1; + while (leftBraceIndex < rightBound) + { + if (tokenVector[leftBraceIndex].type == TokenType::LEFT_BRACE) { break; } + leftBraceIndex += 1; + } + // ERROR: { not found + if (leftBraceIndex == rightBound) + { return { { tokenVector[leftBraceIndex].line, tokenVector[leftBraceIndex].index }, tokenVector[leftBraceIndex].content }; } + // find } + int rightBraceIndex = findRightBraceNoError(tokenVector, leftBraceIndex + 1, rightBound); + // ERROR: } not found + if (rightBraceIndex > rightBound) + { return { { tokenVector[rightBraceIndex].line, tokenVector[rightBraceIndex].index }, tokenVector[rightBraceIndex].content }; } + + // condition + std::unique_ptr condition1 = std::make_unique(); + std::pair, std::string> errorResultCondition1 = MakeExpressionTree(tokenVector, start + 1, leftBraceIndex - 1, condition1); + if (errorResultCondition1.first.first != -1) { return errorResultCondition1; } + + // statements and expressions inside {...} + std::vector> flows1; + std::pair, std::string> errorResultFlows1 = HandleTokenVector(tokenVector, leftBraceIndex + 1, rightBraceIndex - 1, flows1); + if (errorResultFlows1.first.first != -1) { return errorResultFlows1; } + node->conditions.push_back(std::move(condition1)); + node->flowGroups.push_back(std::move(flows1)); + start = rightBraceIndex + 1; + + + // Else + if (tokenVector[start].type == TokenType::ELSE) + { + // Case 1 else {...} + if (tokenVector[start+1].type == TokenType::LEFT_BRACE) + { + // find where { is + leftBraceIndex = start + 1; + // find } + rightBraceIndex = findRightBraceNoError(tokenVector, leftBraceIndex + 1, rightBound); + // ERROR: } not found + if (rightBraceIndex > rightBound) + { return { { tokenVector[rightBraceIndex].line, tokenVector[rightBraceIndex].index }, tokenVector[rightBraceIndex].content }; } + + // statements and expressions inside {...} + std::vector> flows; + std::pair, std::string> errorResultFlows = HandleTokenVector(tokenVector, leftBraceIndex + 1, rightBraceIndex - 1, flows); + if (errorResultFlows.first.first != -1) { return errorResultFlows; } + node->flowGroups.push_back(std::move(flows)); + start = rightBraceIndex + 1; + } + // Case 2 else if {...} + else if (tokenVector[start+1].type == TokenType::IF) + { + int newstart = start + 1; // if + // Find the end of the whole if statement + // skip all else_if + while (tokenVector[start].type == TokenType::ELSE && tokenVector[start + 1].type == TokenType::IF) + { + // find where { is + int leftBraceIndex = start + 2; + while (leftBraceIndex < rightBound) + { + if (tokenVector[leftBraceIndex].type == TokenType::LEFT_BRACE) { break; } + leftBraceIndex += 1; + } + // { not found + if (leftBraceIndex == rightBound) + { + // std::cout << "{ not found" << std::endl; + return { { tokenVector[leftBraceIndex].line, tokenVector[leftBraceIndex].index }, tokenVector[leftBraceIndex].content }; + } + // find } + int rightBraceIndex = findRightBraceNoError(tokenVector, leftBraceIndex + 1, rightBound); + if (rightBraceIndex > rightBound) + { + // std::cout << "} not found" << std::endl; + return { { tokenVector[rightBraceIndex].line, tokenVector[rightBraceIndex].index }, tokenVector[rightBraceIndex].content }; + } + + start = rightBraceIndex + 1; + } + // skip else (if there is one) + if (tokenVector[start].type == TokenType::ELSE) + { + // find where { is + // the last else must be "else", not else if + if (tokenVector[start+1].type != TokenType::LEFT_BRACE) + { + return { { tokenVector[start+1].line, tokenVector[start+1].index }, tokenVector[start+1].content }; + } + leftBraceIndex = start + 1; + // find } + rightBraceIndex = findRightBraceNoError(tokenVector, leftBraceIndex + 1, rightBound); + // ERROR: } not found + if (rightBraceIndex > rightBound) + { return { { tokenVector[rightBraceIndex].line, tokenVector[rightBraceIndex].index }, tokenVector[rightBraceIndex].content }; } + + start = rightBraceIndex + 1; + } + + + + // statements and expressions after else + std::vector> flows; + std::pair, std::string> errorResultFlows = HandleTokenVector(tokenVector, newstart, start - 1, flows); + if (errorResultFlows.first.first != -1) { return errorResultFlows; } + node->flowGroups.push_back(std::move(flows)); + } + else + { + return { { tokenVector[start+1].line, tokenVector[start+1].index }, tokenVector[start+1].content }; + } + } + nodes.push_back(std::move(node)); + } + else if (tokenVector[start].type == TokenType::PRINT) + { + std::unique_ptr node = std::make_unique(tokenVector[start]); + int printIndex = start; + start += 1; + while (tokenVector[start].line == tokenVector[printIndex].line && start <= rightBound) + { + start += 1; + } + auto errorResult = MakeExpressionTree(tokenVector, printIndex + 1, start - 1, node->content); + if (errorResult.first.first != -1) + { + return errorResult; + } + nodes.push_back(std::move(node)); + } + else if (tokenVector[start].type == TokenType::RETURN) + { + std::unique_ptr node = std::make_unique(tokenVector[start]); + int printIndex = start; + start += 1; + while (tokenVector[start].line == tokenVector[printIndex].line && start <= rightBound) + { + start += 1; + } + auto errorResult = MakeExpressionTree(tokenVector, printIndex + 1, start - 1, node->content); + if (errorResult.first.first != -1) + { + return errorResult; + } + nodes.push_back(std::move(node)); + } + else + { + std::unique_ptr node = std::make_unique(tokenVector[start]); + int beginIndex = start; + start += 1; + while (tokenVector[start].line == tokenVector[beginIndex].line && start <= rightBound) + { + start += 1; + } + auto errorResult = MakeExpressionTree(tokenVector, beginIndex, start - 1, node); + if (errorResult.first.first != -1) + { + return errorResult; + } + nodes.push_back(std::move(node)); + } + } + return { { -1, -1 }, "" }; +} + +std::pair, std::string> ParserB::MakeExpressionTree(std::vector expression, int leftBound, int rightBound, std::unique_ptr& node) +{ if (leftBound > rightBound) { #if DEBUG std::cout << "1 no expression " << std::endl; @@ -41,19 +323,7 @@ std::pair, std::string> ParserB::MakeTreeInfix(std::vector rightBound) - { - return { { expression[rightIndex].line, expression[rightIndex].index }, expression[rightIndex].content }; - } - i = rightIndex + 1; - } - - + int i = leftBound ; while (i <= rightBound) { // current token does not belongs to hierarchyMap @@ -62,15 +332,7 @@ std::pair, std::string> ParserB::MakeTreeInfix(std::vector, std::string> ParserB::MakeTreeInfix(std::vector i ? topIndex : i; - } + { topIndex = topIndex > i ? topIndex : i; } + } + // lower hierarchy + else + { // do nothing } + // Find the next element // ignore content inside (...) - if (expression[i].type == TokenType::leftParenthesis) + if (expression[i].type == TokenType::LEFT_PARENTHESIS) { int rightIndex = findRightParenthesisNoError(expression, i+1, rightBound); if (rightIndex > rightBound) @@ -103,28 +366,118 @@ std::pair, std::string> ParserB::MakeTreeInfix(std::vector rightBound) + { + return { { expression[rightIndex].line, expression[rightIndex].index }, expression[rightIndex].content }; + } + i = rightIndex + 1; + } else { i += 1; } } + // case 0 null + if (expression[topIndex].type == TokenType::NUL) + { + node = std::make_unique(expression[topIndex]); + return { { -1, -1 }, "" }; + } // case 1 number - if (expression[topIndex].type == TokenType::number) + else if (expression[topIndex].type == TokenType::NUMBER) { - node = Node(expression[topIndex]); + node = std::make_unique(expression[topIndex]); return { { -1, -1 }, "" }; } // case 2 variable - else if (expression[topIndex].type == TokenType::variable) + else if (expression[topIndex].type == TokenType::VARIABLE) { - node = Node(expression[topIndex]); + // function call + // recognize a function call if variable followed by (...) e.g. add(1, 2) + // Seperate a function call into function and parameters. e.g. "getFunc()(1,2)(3)" should be seperated as "getFunc()(1,2)" and "(3)", + if (topIndex+1 <= rightBound && expression[topIndex+1].type == TokenType::LEFT_PARENTHESIS) + { + node = std::make_unique(expression[topIndex]); + + // getFunc()(1,2)() + // get The last pair of parenthesis (...) + int leftParenthesisIndex = topIndex + 1; + int rightParenthesisIndex; + while (true) { + rightParenthesisIndex = findRightParenthesisNoError(expression, leftParenthesisIndex + 1, rightBound); + if (rightParenthesisIndex > rightBound) + { + return { { expression[rightParenthesisIndex].line, expression[rightParenthesisIndex].index }, expression[rightParenthesisIndex].content }; + } + if (rightParenthesisIndex + 1 <= rightBound && expression[rightParenthesisIndex + 1].type == TokenType::LEFT_PARENTHESIS) + { + leftParenthesisIndex = rightParenthesisIndex + 1; + } + else { + break; + } + } + + + // Function + std::unique_ptr functionNode = std::make_unique(); + MakeExpressionTree(expression, topIndex, leftParenthesisIndex - 1, functionNode); + node->children.push_back(std::move(functionNode)); + + // Parameters + // add parameter values into children + // parameter values are seperated by comma. Remember to skip parenthesis. + int left = leftParenthesisIndex + 1; + while (left <= rightParenthesisIndex-1) + { + std::unique_ptr parameterNode = std::make_unique(); + int right = left; + while (right <= rightParenthesisIndex-1 && expression[right].type != TokenType::COMMA) + { + // Skip parenthesis e.g. add(add(1, 2), 3) + if (expression[right].type == TokenType::LEFT_PARENTHESIS) + { + int right = findRightParenthesisNoError(expression, right+1, rightParenthesisIndex-1); + if (right > rightParenthesisIndex-1) + { + return { { expression[right].line, expression[right].index }, expression[right].content }; + } + } + right += 1; + } + MakeExpressionTree(expression, left, right-1, parameterNode); + node->children.push_back(std::move(parameterNode)); + left = right + 1; + } + } + // variable + else + { + node = std::make_unique(expression[topIndex]); + } return { { -1, -1 }, "" }; } - // case 3 = - else if (expression[topIndex].type == TokenType::equals) + // case 3 true + else if (expression[topIndex].type == TokenType::TRUE) { - Node res = Node(expression[topIndex]); + node = std::make_unique(expression[topIndex]); + return { { -1, -1 }, "" }; + } + // case 4 false + else if (expression[topIndex].type == TokenType::FALSE) + { + node = std::make_unique(expression[topIndex]); + return { { -1, -1 }, "" }; + } + // case 5 = + else if (expression[topIndex].type == TokenType::ASSIGNMENT) + { + node = std::make_unique(expression[topIndex]); // check assignment ERROR // Error 1. Nothing before = e.g =8 @@ -134,335 +487,631 @@ std::pair, std::string> ParserB::MakeTreeInfix(std::vector, std::string> errorResult1 = MakeTreeInfix(expression, leftBound, topIndex-1, node1); + // on the left + std::unique_ptr node1; + std::pair, std::string> errorResult1 = MakeExpressionTree(expression, leftBound, topIndex-1, node1); if (errorResult1.first.first != -1) { return errorResult1; } - res.children.push_back(node1); + node->children.push_back(std::move(node1)); - Node node2; - std::pair, std::string> errorResult2 = MakeTreeInfix(expression, topIndex+1, rightBound, node2); + // on the right + std::unique_ptr node2; + std::pair, std::string> errorResult2 = MakeExpressionTree(expression, topIndex+1, rightBound, node2); if (errorResult2.first.first != -1) { return errorResult2; } - res.children.push_back(node2); + node->children.push_back(std::move(node2)); - node = res; return { { -1, -1 }, "" }; } - // case 4 + - * / - else if (expression[topIndex].type == TokenType::plus || expression[topIndex].type == TokenType::minus || - expression[topIndex].type == TokenType::multiply || expression[topIndex].type == TokenType::divide) + // case 6 + - * / + else if (expression[topIndex].type == TokenType::PLUS || expression[topIndex].type == TokenType::MINUS || + expression[topIndex].type == TokenType::MULTIPLY || expression[topIndex].type == TokenType::DIVIDE || + expression[topIndex].type == TokenType::MOD || + expression[topIndex].type == TokenType::SMALLER || expression[topIndex].type == TokenType::BIGGER|| + expression[topIndex].type == TokenType::SMALLER_EQUAL || expression[topIndex].type == TokenType::BIGGER_EQUAL || + expression[topIndex].type == TokenType::INEQUALITY || expression[topIndex].type == TokenType::EQUALITY || + expression[topIndex].type == TokenType::AND || expression[topIndex].type == TokenType::EXCLUSIVE_OR || expression[topIndex].type == TokenType::INCLUSIVE_OR) { - Node res = Node(expression[topIndex]); + node = std::make_unique(expression[topIndex]); - Node node1; - std::pair, std::string> errorResult1 = MakeTreeInfix(expression, leftBound, topIndex-1, node1); + // on the left + std::unique_ptr node1; + std::pair, std::string> errorResult1 = MakeExpressionTree(expression, leftBound, topIndex-1, node1); if (errorResult1.first.first != -1) { return errorResult1; } - res.children.push_back(node1); + node->children.push_back(std::move(node1)); - Node node2; - std::pair, std::string> errorResult2 = MakeTreeInfix(expression, topIndex+1, rightBound, node2); + // on the right + std::unique_ptr node2; + std::pair, std::string> errorResult2 = MakeExpressionTree(expression, topIndex+1, rightBound, node2); if (errorResult2.first.first != -1) { return errorResult2; } - res.children.push_back(node2); + node->children.push_back(std::move(node2)); - node = res; return { { -1, -1 }, "" }; } - // case 5 (...) - else if (expression[topIndex].type == TokenType::leftParenthesis) - {skipLine + // case 7 (...) + else if (expression[topIndex].type == TokenType::LEFT_PARENTHESIS) + { int rightIndex = findRightParenthesisNoError(expression, topIndex+1, rightBound); if (rightIndex > rightBound) { return { { expression[rightIndex].line, expression[rightIndex].index }, expression[rightIndex].content }; } - return MakeTreeInfix(expression, topIndex+1, rightIndex-1, node); + // get rid of the parenthesis pair + return MakeExpressionTree(expression, topIndex+1, rightIndex-1, node); } - // case 6 ERROR - else - { + // case 8 ERROR #if DEBUG std::cout << "3 " << std::endl; #endif - return { { expression[topIndex].line, expression[topIndex].index }, expression[topIndex].content }; - } + return { { expression[topIndex].line, expression[topIndex].index }, expression[topIndex].content }; } - -static void parseLines(std::vector expressionLines); +std::string ParserB::calculate(Node* root, Result& result) { - // line count start from 1 - while (currentline < expressions.size() + 1) - { - expression = expressions[i-1]; + auto& variableTypeMap = ScopeStack.top().variableTypeMap; - // Lexer - std::vector TokenVector; - std::pair errorPair = Token::GenTokenVector(expression, TokenVector); - if (errorPair.first != -1) + // Def + if (root->value.type == TokenType::DEF) + { + // std::cout << "DEFFFFFFFFF" << std::endl; + FunctionDefineNode* functionDefineNode = dynamic_cast(root); + Result result; + result.type = DataType::FUNCTION; + result.function = std::make_shared(); + result.function->m_ParameterNames = functionDefineNode->parameterNames; + result.function->m_FunctionFlows = std::move(functionDefineNode->flows); + result.function->m_CaptureScope = Scope(ScopeStack.top()); + setVariable(functionDefineNode->functionName, result); + return ""; + } + // While + if (root->value.type == TokenType::WHILE) + { + WhileNode* whileNode = dynamic_cast(root); + while (true) { - std::cout << "Syntax error on line " << lineCount << " column " << errorPair.second << "." << std::endl; - exit(1); + // check condition + Result conditionResult; + std::string errorMessageCondition = calculate(whileNode->condition.get(), conditionResult); + // ERROR: Condition is not a bool + if (conditionResult.type != DataType::BOOL) { return "Runtime error: condition is not a bool."; } + if (errorMessageCondition != "") { return errorMessageCondition; } + if (conditionResult.boolValue == 0) { break; } + // execute flows + for (int i=0; i < (int)whileNode->flows.size(); i++) + { + Result flowResult; + std::string errorMessageFlow = calculate(whileNode->flows[i].get(), flowResult); + if (errorMessageFlow != "") { return errorMessageFlow; } + } } + return ""; + } + // If + else if (root->value.type == TokenType::IF) + { + IfNode* ifNode = dynamic_cast(root); + for (int conditionIndex = 0; conditionIndex < (int)ifNode->conditions.size(); conditionIndex++) + { + // check conditions + Result conditionResult; + std::string errorMessageCondition = calculate(ifNode->conditions[conditionIndex].get(), conditionResult); + // ERROR: Condition is not a bool + if (conditionResult.type != DataType::BOOL) { return "Runtime error: condition is not a bool."; } + if (errorMessageCondition != "") { return errorMessageCondition; } + if (conditionResult.boolValue == 1) + { + // execute flows + for (int i=0; i < (int)ifNode->flowGroups[conditionIndex].size(); i++) + { + Result flowResult; + std::string errorMessageFlow = calculate(ifNode->flowGroups[conditionIndex][i].get(), flowResult); + if (errorMessageFlow != "") { return errorMessageFlow; } + } + return ""; + } + } - // ParserB - ParserB::setupExpressionInfix(TokenVector); // register variables - - if (TokenVector[0].type == TokenType::while) + // check else + if (ifNode->conditions.size() != ifNode->flowGroups.size()) { - // Parse - Node root; - std::pair, std::string> errorResult = ParserB::MakeTreeInfix(TokenVector, 1, TokenVector.size() - 3, root); - if (errorResult.first.first != -1) + for (int i=0; i < (int)ifNode->flowGroups[ifNode->flowGroups.size()-1].size(); i++) { - std::cout << "Unexpected token at line " << currentLine << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; - exit(2); + Result flowResult; + std::string errorMessageFlow = calculate(ifNode->flowGroups[ifNode->flowGroups.size()-1][i].get(), flowResult); + if (errorMessageFlow != "") { return errorMessageFlow; } } + return ""; + } + return ""; + } + // Print + else if (root->value.type == TokenType::PRINT) + { + PrintNode* printNode = dynamic_cast(root); + Result flowResult; + std::string errorMessageFlow = calculate(printNode->content.get(), flowResult); + if (errorMessageFlow != "") { return errorMessageFlow; } + ParserB::printValue(flowResult); + std::cout << std::endl; + } + // Return + else if (root->value.type == TokenType::RETURN) + { + ReturnNode* returnNode = dynamic_cast(root); + std::string errorMessageFlow = calculate(returnNode->content.get(), result); + if (errorMessageFlow != "") { return errorMessageFlow; } + } - // Calculate - double result; - std::string errorMessage = ParserB::calculate(root, result); + // Expression + else + { + ExpressionNode* expressionNode = dynamic_cast(root); - if (errorMessage.length() != 0) - { - std::cout << errorMessage << std::endl; - exit(3); + // null + if (expressionNode->value.type == TokenType::NUL) + { + result.type = DataType::NUL; - continue; - } + return ""; + } - if (result != 0) - { - jumptoStack.push(currentLine); - } - else { + // number + else if (expressionNode->value.type == TokenType::NUMBER) + { + result.type = DataType::DOUBLE; + result.doubleValue = expressionNode->value.value; - } - } - else if (TokenVector[0].type == TokenType::if) + return ""; + } + + // true + else if (expressionNode->value.type == TokenType::TRUE) { - // Parse - Node root; - std::pair, std::string> errorResult = ParserB::MakeTreeInfix(TokenVector, 1, TokenVector.size() - 3, root); - if (errorResult.first.first != -1) - { - std::cout << "Unexpected token at line " << currentLine << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; - exit(2); - } + result.type = DataType::BOOL; + result.boolValue = expressionNode->value.value; - // Calculate - double result; - std::string errorMessage = ParserB::calculate(root, result); + return ""; + } - if (errorMessage.length() != 0) - { - std::cout << errorMessage << std::endl; - exit(3); + // false + else if (expressionNode->value.type == TokenType::FALSE) + { + result.type = DataType::BOOL; + result.boolValue = expressionNode->value.value; - continue; - } + return ""; } - else if (TokenVector[0].type == TokenType::print) + + // variable + else if (expressionNode->value.type == TokenType::VARIABLE) { - // Parse - Node root; - std::pair, std::string> errorResult = ParserB::MakeTreeInfix(TokenVector, 1, TokenVector.size() - 2, root); - if (errorResult.first.first != -1) + if (variableTypeMap.at(expressionNode->value.content) == DataType::UNINITIALIZED) { - std::cout << "Unexpected token at line " << currentLine << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; - exit(2); + return "Runtime error: unknown identifier " + expressionNode->value.content; } + // Function Call + if (expressionNode->children.size() != 0) + { + // variable is not a function + if (variableTypeMap.at(expressionNode->value.content) != DataType::FUNCTION) + { + return "Runtime error: not a function."; + } - // Calculate - double result; - std::string errorMessage = ParserB::calculate(root, result); - if (errorMessage.length() != 0) - { - std::cout << errorMessage << std::endl; - exit(3); + Result functionResult; + getVariable(expressionNode->value.content, functionResult); + std::shared_ptr function = functionResult.function; + + // Parameters don't match + if (function->m_ParameterNames.size() != expressionNode->children.size()-1) + { + return "Runtime error: incorrect argument count."; + } - continue; + // execute the function + // 1. create a new scope + Scope localScope(ScopeStack.top()); + // Overwrite the localscope with the captured scope + localScope.OverwriteBy(function->m_CaptureScope); + + ScopeStack.push(localScope); + // 2. set parameter values + for (int i = 1; i < (int)expressionNode->children.size(); i++) + { + Result parameterResult; + calculate(expressionNode->children[i].get(), parameterResult); + setVariable(function->m_ParameterNames[i-1], parameterResult); + } + for (int i=0; i < (int)function->m_FunctionFlows.size(); i++) + { + calculate(function->m_FunctionFlows[i].get(), result); + if (function->m_FunctionFlows[i]->value.type == TokenType::RETURN) + { + ScopeStack.pop(); + return ""; + } + } + result.type = DataType::NUL; + ScopeStack.pop(); } - - std::cout << result << std::endl; - currentLine += 1; - } - else if (TokenVector[0].type == TokenType::rightBracket) - { - // redundant } - if (jumptoStack.empty()) + else { - std::cout << "Unexpected token at line " << currentLine << " column " << TokenVector[0].index << ": " << TokenVector[0].content << std::endl; - exit(2); + getVariable(expressionNode->value.content, result); } - - currentLine = jumptoStack.top(); - jumptoStack.pop(); - currentLine += 1; + return ""; } - else + + // = + else if (expressionNode->value.type == TokenType::ASSIGNMENT) { - // ParserB - Node root; - std::pair, std::string> errorResult = ParserB::MakeTreeInfix(TokenVector, 0, TokenVector.size() - 2, root); + // the last child must be a number or an initialized variable + std::string errorMessage = calculate(expressionNode->children[1].get(), result); + if (errorMessage != "") { return errorMessage; } - if (errorResult.first.first != -1) - { - std::cout << "Unexpected token at line " << errorResult.first.first << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; - continue; - } - ParserB::print(root); - std::cout << std::endl; + // the first child must be a variable + if (expressionNode->children[0].get()->value.type != TokenType::VARIABLE) + { return "Runtime error: invalid assignee."; } - // Calculate - double result; - std::string errorMessage = ParserB::calculate(root, result); + setVariable(expressionNode->children[0]->value.content, result); - if (errorMessage.length() != 0) - { - std::cout << errorMessage << std::endl; - exit(3); + return ""; + } - continue; + // + - * / % == != > < >= <= & | ^ + else { + // variable for operation is uninitialaized + Result result1; + Result result2; + std::string errorMessage1 = calculate(expressionNode->children[0].get(), result1); + if (errorMessage1 != "") { return errorMessage1; } + std::string errorMessage2 = calculate(expressionNode->children[1].get(), result2); + if (errorMessage2 != "") { return errorMessage2; } + + + // handle type errors and set resultType + // arithematic operations + // + - * / % + if (expressionNode->value.type == TokenType::PLUS || expressionNode->value.type == TokenType::MINUS || expressionNode->value.type == TokenType::MULTIPLY || + expressionNode->value.type == TokenType::DIVIDE || expressionNode->value.type == TokenType::MOD) + { + // arithmetic operator only works on double and return double + if (result1.type == DataType::BOOL || result2.type == DataType::BOOL) + { + return "Runtime error: invalid operand type."; + } + result.type = DataType::DOUBLE; + // + - * / + if (expressionNode->value.type == TokenType::PLUS) { + result.doubleValue = result1.doubleValue + result2.doubleValue; + } + else if (expressionNode->value.type == TokenType::MINUS) { + result.doubleValue = result1.doubleValue - result2.doubleValue; + } + else if (expressionNode->value.type == TokenType::MULTIPLY) { + result.doubleValue = result1.doubleValue * result2.doubleValue; + } + else if (expressionNode->value.type == TokenType::DIVIDE) + { + if (result2.doubleValue == 0) { + return "Runtime error: division by zero."; + } + result.doubleValue = result1.doubleValue / result2.doubleValue; + } + // % + else if (expressionNode->value.type == TokenType::MOD) { + result.doubleValue = std::fmod(result1.doubleValue, result2.doubleValue); + } + } + // ordered comparison + // < <= > >= + else if (expressionNode->value.type == TokenType::SMALLER || expressionNode->value.type == TokenType::SMALLER_EQUAL || + expressionNode->value.type == TokenType::BIGGER || expressionNode->value.type == TokenType::BIGGER_EQUAL) + { + // Comparsion operator only compare double and return bool + if (result1.type == DataType::BOOL || result2.type == DataType::BOOL) + { + return "Runtime error: invalid operand type."; + } + result.type = DataType::BOOL; + // > + if (expressionNode->value.type == TokenType::BIGGER) { + result.boolValue = result1.doubleValue > result2.doubleValue; + } + // < + else if (expressionNode->value.type == TokenType::SMALLER) { + result.boolValue = result1.doubleValue < result2.doubleValue; + } + // >= + else if (expressionNode->value.type == TokenType::BIGGER_EQUAL) { + result.boolValue = result1.doubleValue >= result2.doubleValue; + } + // <= + else if (expressionNode->value.type == TokenType::SMALLER_EQUAL) { + result.boolValue = result1.doubleValue <= result2.doubleValue; + } + } + // logic operations + // & | ^ + else if (expressionNode->value.type == TokenType::AND || expressionNode->value.type == TokenType::INCLUSIVE_OR || + expressionNode->value.type == TokenType::EXCLUSIVE_OR) + { + if (result1.type != DataType::BOOL || result2.type != DataType::BOOL) + { + return "Runtime error: invalid operand type."; + } + result.type = DataType::BOOL; + // & + if (expressionNode->value.type == TokenType::AND) { + result.boolValue = result1.boolValue && result2.boolValue; + } + // | + else if (expressionNode->value.type == TokenType::INCLUSIVE_OR) { + result.boolValue = result1.boolValue || result2.boolValue; + } + // ^ + else if (expressionNode->value.type == TokenType::EXCLUSIVE_OR) { + result.boolValue = result1.boolValue != result2.boolValue; + } + } + // Equality and Inequality + // == != + else if (expressionNode->value.type == TokenType::EQUALITY || expressionNode->value.type == TokenType::INEQUALITY) + { + result.type = DataType::BOOL; + // == + if (expressionNode->value.type == TokenType::EQUALITY) { + if (result1.type == DataType::NUL && result2.type == DataType::NUL) + { + result.boolValue = true; + } + else if (result1.type != result2.type) + { + result.boolValue = false; + } + else + { + if (result1.type == DataType::DOUBLE) + { result.boolValue = result1.doubleValue == result2.doubleValue; } + else if (result1.type == DataType::BOOL) + { result.boolValue = result1.boolValue == result2.boolValue; } + else + { std::cout << "Something's wrong == comparison"; } + } + } + // != + else if (expressionNode->value.type == TokenType::INEQUALITY) { + if (result1.type == DataType::NUL && result2.type == DataType::NUL) + { + result.boolValue = false; + } + else if (result1.type != result2.type) + { + result.boolValue = true; + } + else + { + if (result1.type == DataType::DOUBLE) + { result.boolValue = result1.doubleValue != result2.doubleValue; } + else if (result1.type == DataType::BOOL) + { result.boolValue = result1.boolValue != result2.boolValue; } + else + { std::cout << "Something's wrong == comparison"; } + } + } } - currentLine += 1; + return ""; } } - + return ""; } -std::string ParserB::calculate(Node root, double& result) +void ParserB::print(Node* root, int indent) { - // number - if (root.value.type == TokenType::number) - { - result = root.value.value; - return ""; - } + for (int i=0; ivalue.type == TokenType::DEF) { - if (variableInitializedMap.find(root.value.content) == variableInitializedMap.end()) + FunctionDefineNode* functionDefineRoot = dynamic_cast(root); + + std::cout << "def "; + std::cout << functionDefineRoot->functionName; + std::cout << "("; + for (int i = 0; i < (int)functionDefineRoot->parameterNames.size(); i++) { - return "Runtime error: unknown identifier " + root.value.content; + std::cout << functionDefineRoot->parameterNames[i]; + if (i != (int)functionDefineRoot->parameterNames.size()-1) + { + std::cout << ", "; + } + } + std::cout << ") "; + std::cout << "{" << std::endl; + for (int i=0; i < (int)functionDefineRoot->flows.size(); i++) + { + print(functionDefineRoot->flows[i].get(), indent + 1); + std::cout << std::endl; } - result = variableMap.at(root.value.content); - return ""; - } - // = - else if (root.value.type == TokenType::equals) + for (int i=0; i < indent; i++) { std::cout << " "; } + std::cout << "}"; + } + // While + else if (root->value.type == TokenType::WHILE) { - // the last child must be a number or an initialized variable - Node last = root.children[root.children.size()-1]; - if (last.value.type == TokenType::variable && variableInitializedMap.find(last.value.content) == variableInitializedMap.end()) + WhileNode* whileRoot = dynamic_cast(root); + + std::cout << "while "; + print(whileRoot->condition.get(), 0); + std::cout << " {" << std::endl; + for (int i=0;i < (int)whileRoot->flows.size(); i++) { - return "Runtime error: unknown identifier " + last.value.content; + print(whileRoot->flows[i].get(), indent + 1); + std::cout << std::endl; } + for (int i=0; ivalue.type == TokenType::IF) + { + IfNode* ifRoot = dynamic_cast(root); - std::string errorMessage = calculate(last, result); - if (errorMessage != "") { return errorMessage; } - - // set values - for (int i = 0; i < (int)root.children.size()-1; i++) + // if + std::cout << "if "; + print(ifRoot->conditions[0].get(), 0); + std::cout << " {" << std::endl; + for (int i=0 ; i < (int)ifRoot->flowGroups[0].size(); i++) { - variableMap.at(root.children[i].value.content) = result; - variableInitializedMap.at(root.children[i].value.content) = true; + print(ifRoot->flowGroups[0][i].get(), indent + 1); + std::cout << std::endl; } + for (int i=0; iconditions.size(); conditionIndex++) + { + std::cout << std::endl; + for (int i=0; iconditions[conditionIndex].get(), 0); + std::cout << " {" << std::endl; + for (int i=0; i < (int)ifRoot->flowGroups[conditionIndex].size(); i++) + { + print(ifRoot->flowGroups[conditionIndex][i].get(), indent + 1); + std::cout << std::endl; + } + for (int a=0; aconditions.size() != ifRoot->flowGroups.size()) { - return "Runtime error: unknown identifier " + root.children[0].value.content; + std::cout << std::endl; + for (int i=0; iflowGroups[ifRoot->flowGroups.size()-1].size(); i++) + { + print(ifRoot->flowGroups[ifRoot->flowGroups.size()-1][i].get(), indent + 1); + std::cout << std::endl; + } + for (int i=0; ivalue.type == TokenType::PRINT) + { + PrintNode* printRoot = dynamic_cast(root); - std::string errorMessage = calculate(root.children[0], result); - if (errorMessage != "") { return errorMessage; } + std::cout << "print "; + print(printRoot->content.get()); + } + // Return + else if (root->value.type == TokenType::RETURN) + { + ReturnNode* returnRoot = dynamic_cast(root); + std::cout << "return "; + print(returnRoot->content.get()); + } - for (int i = 1; i < (int)root.children.size(); i++) + // ExpressionNode + else + { + ExpressionNode* expressionNode = dynamic_cast(root); + + if (expressionNode->value.type == TokenType::NUL) { - // variable for operation is uninitialaized - if (root.children[i].value.type == TokenType::variable && variableInitializedMap.at(root.children[i].value.content) == false) + std::cout << "null"; + } + else if (expressionNode->value.type == TokenType::NUMBER) + { + int v = floor(expressionNode->value.value); + // 1000.000 -> 1000 + if ((double)v == expressionNode->value.value) + { std::cout << v; } + else + { std::cout << expressionNode->value.content; } + } + else if (expressionNode->value.type == TokenType::VARIABLE) + { + // Function Call + if (expressionNode->children.size() != 0) { - return "Runtime error: unknown identifier " + root.children[i].value.content; - } - else if (root.value.type == TokenType::plus) { - double r; - std::string errorMessage = calculate(root.children[i], r); - if (errorMessage != "") { return errorMessage; } - result += r; - } - else if (root.value.type == TokenType::minus) { - double r; - std::string errorMessage = calculate(root.children[i], r); - if (errorMessage != "") { return errorMessage; } - result -= r; + print(expressionNode->children[0].get()); + std::cout << "("; + for (int i = 1; i < (int)expressionNode->children.size(); i++) + { + print(expressionNode->children[i].get()); + if (i != (int)expressionNode->children.size() - 1) + { + std::cout << ", "; + } + } + std::cout << ")"; } - else if (root.value.type == TokenType::multiply) { - double r; - std::string errorMessage = calculate(root.children[i], r); - if (errorMessage != "") { return errorMessage; } - result *= r; + // Normal Variable + else + { + std::cout << expressionNode->value.content; } - else if (root.value.type == TokenType::divide) + } + else if (expressionNode->value.type == TokenType::TRUE) + { + std::cout << expressionNode->value.content; + } + else if (expressionNode->value.type == TokenType::FALSE) + { + std::cout << expressionNode->value.content; + } + else { + std::cout << "("; + for (int i = 0; i < (int)expressionNode->children.size(); i++) { - double r; - std::string errorMessage = calculate(root.children[i], r); - if (errorMessage != "") { return errorMessage; } - if (r == 0) { - return "Runtime error: division by zero."; + print(expressionNode->children[i].get()); + if (i != (int)expressionNode->children.size() - 1) + { + std::cout << " " << expressionNode->value.content << " "; } - result /= r; } + std::cout << ")"; } - return ""; } } - -void ParserB::print(Node root) +void ParserB::printValue(Result& value) { - if (root.value.type == TokenType::number) + if (value.type == DataType::NUL) { - int v = floor(root.value.value); - // 1000.000 -> 1000 - if ((double)v == root.value.value) - { - std::cout << v; - } - else - { - std::cout << root.value.content; - } + std::cout << "null"; } - else if (root.value.type == TokenType::variable) + + else if (value.type == DataType::BOOL) { - std::cout << root.value.content; + if (value.boolValue == 0) { std::cout << "false"; } + else { std::cout << "true"; } } - else { - std::cout << "("; - for (int i = 0; i < (int)root.children.size(); i++) - { - print(root.children[i]); - if (i != (int)root.children.size() - 1) - { - std::cout << " " << root.value.content << " "; - } - } - std::cout << ")"; + + else if (value.type == DataType::DOUBLE) + { + std::cout << value.doubleValue; + } + + else + { + std::cout << (value.type == DataType::FUNCTION) << std::endl; + std::cout << (value.type == DataType::NUL) << std::endl; + std::cout << "There is something wrong PrintValue" << std::endl; } } @@ -472,8 +1121,9 @@ int ParserB::findRightParenthesisNoError(std::vector expression, int left int balance = 1; int p = leftBound; while (p <= rightBound) { - if (expression[p].type == TokenType::leftParenthesis) { balance += 1; } - if (expression[p].type == TokenType::rightParenthesis) { balance -= 1; } + if (expression[p].type == TokenType::LEFT_PARENTHESIS) { balance += 1; } + else if (expression[p].type == TokenType::RIGHT_PARENTHESIS) { balance -= 1; } + if (balance == 0) { break; } p += 1; } @@ -486,68 +1136,101 @@ int ParserB::findRightBracketNoError(std::vector expression, int leftBoun int balance = 1; int p = leftBound; while (p <= rightBound) { - if (expression[p].type == TokenType::leftParenthesis) { balance += 1; } - if (expression[p].type == TokenType::rightParenthesis) { balance -= 1; } + if (expression[p].type == TokenType::LEFT_BRACKET) { balance += 1; } + else if (expression[p].type == TokenType::RIGHT_BRACKET) { balance -= 1; } + if (balance == 0) { break; } p += 1; } return p; } - -// return vectors of lines in infix notation -// register variables in map -void ParserB::setupExpressionInfix(std::vector expression) +// exclude left brace +int ParserB::findRightBraceNoError(std::vector expression, int leftBound, int rightBound) { - if (expression.size() == 1) - { -#if DEBUG - std::cout << "-1 empty expression" << std::endl; -#endif + int balance = 1; + int p = leftBound; + while (p <= rightBound) { + if (expression[p].type == TokenType::LEFT_BRACE) { balance += 1; } + else if (expression[p].type == TokenType::RIGHT_BRACE) { balance -= 1; } - std::cout << "Unexpected token at line " << 1 << " column " << 1 << ": " << "END" << std::endl; - exit(2); + if (balance == 0) { break; } + p += 1; } + return p; +} + +// void ParserB::setupExpression(std::vector& expression, int leftBound, int rightBound, ) +void ParserB::setupExpression(std::vector& expression) +{ + auto& variableTypeMap = ScopeStack.top().variableTypeMap; + for (int i = 0; i < (int)expression.size()-1; i++) { Token token = expression[i]; // handle new variable - if (token.type == TokenType::variable) + if (token.type == TokenType::VARIABLE) { - if (variableMap.find(token.content) == variableMap.end()) - { - variableMap.insert({ token.content, -1 }); - variableInitializedMap.insert({ token.content, false }); - } + variableTypeMap[token.content] = DataType::UNINITIALIZED; } } } +void ParserB::getVariable(std::string& variableName, Result& result) { + auto& variableTypeMap = ScopeStack.top().variableTypeMap; + auto& variableDoubleMap = ScopeStack.top().variableDoubleMap; + auto& variableBoolMap = ScopeStack.top().variableBoolMap; + auto& variableFunctionMap = ScopeStack.top().variableFunctionMap; + result.type = variableTypeMap[variableName]; + if (result.type == DataType::NUL) + { + + } + else if (result.type == DataType::DOUBLE) + { + result.doubleValue = variableDoubleMap[variableName]; + } + else if (result.type == DataType::BOOL) + { + result.boolValue = variableBoolMap[variableName]; + } + else if (result.type == DataType::FUNCTION) + { + result.function = variableFunctionMap[variableName]; + } + else + { + std::cout << (result.type == DataType::NUL) << std::endl; + std::cout << "There is a problem getVariable" << std::endl; + } +} + +void ParserB::setVariable(std::string& variableName, Result& result) { + auto& variableTypeMap = ScopeStack.top().variableTypeMap; + auto& variableDoubleMap = ScopeStack.top().variableDoubleMap; + auto& variableBoolMap = ScopeStack.top().variableBoolMap; + auto& variableFunctionMap = ScopeStack.top().variableFunctionMap; + variableTypeMap[variableName] = result.type; + if (result.type == DataType::NUL) + { -// std::string ParserB::Checkerror(Node root, bool &result){ // only check whether all variable have value or will it be assigned value in the expression -// for (size_t i =0; i #include #include +#include +#include +#include "DataType.h" #include "Lexer.h" -#include "Utils.h" +#include "Scope.h" +#include "Function.h" +#include "ASTNode.h" -class Node -{ -public: - Node() : value(Token(TokenType::none, "", -1, -1, -1)) {} - Node(Token token) : value(token) {} - std::vector children; - Token value; +class Result { +public: + ~Result() { + if (type == DataType::FUNCTION && function != nullptr) { + // delete function; + // function = nullptr; + } + } + + DataType type; + + std::shared_ptr function; + union { + double doubleValue; + bool boolValue; + }; }; class ParserB { public: - static std::pair, std::string> MakeTreeInfix(std::vector expression, int leftBound, int rightBound, Node& node); - static std::string calculate(Node root, double& result); - static void print(Node root); - static void setupExpression(std::vector expression); - static void setupExpressionInfix(std::vector expression); - static std::vector> expressionLines; - static std::map variableMap; - static std::map variableInitializedMap; + static std::pair, std::string> HandleTokenVector(std::vector tokenVector, int leftBound, int rightBound, std::vector>& nodes); + static std::pair, std::string> MakeExpressionTree(std::vector expression, int leftBound, int rightBound, std::unique_ptr& node); + static std::string calculate(Node* root, Result& result); + static void print(Node* root, int indent = 0); + static void printValue(Result& result); + static void setupExpression(std::vector& expression); + static void getVariable(std::string& variableName, Result& result); + static void setVariable(std::string& variableName, Result& result); + static int findRightParenthesisNoError(std::vector expression, int leftBound, int rightBound); + static int findRightBracketNoError(std::vector expression, int leftBound, int rightBound); + static int findRightBraceNoError(std::vector expression, int leftBound, int rightBound); + static std::stack ScopeStack; static std::map hierarchyMap; private: - static int findLeftParenthesis(std::vector expression, int leftBound, int rightBound); - static int findRightParenthesis(std::vector expression, int leftBound, int rightBound); - static int findRightParenthesisNoError(std::vector expression, int leftBound, int rightBound); }; diff --git a/src/lib/Scope.h b/src/lib/Scope.h new file mode 100644 index 0000000..ddff23a --- /dev/null +++ b/src/lib/Scope.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include "DataType.h" + +class Function; + +class Scope +{ +public: + Scope() + : variableTypeMap(), variableDoubleMap(), variableBoolMap() + , variableFunctionMap() + {} + + // Copy constructor + Scope(const Scope& other) + : variableTypeMap(other.variableTypeMap), variableDoubleMap(other.variableDoubleMap), + variableBoolMap(other.variableBoolMap), variableFunctionMap(other.variableFunctionMap) + {} + + void OverwriteBy(Scope& other) + { + for (std::pair kv : other.variableTypeMap) + { + std::string variableName = kv.first; + + variableTypeMap[variableName] = other.variableTypeMap[variableName]; + + if (other.variableTypeMap[variableName] == DataType::NUL) + { + + } + else if (other.variableTypeMap[variableName] == DataType::DOUBLE) + { + variableDoubleMap[variableName] = other.variableDoubleMap[variableName]; + } + else if (other.variableTypeMap[variableName] == DataType::BOOL) + { + variableBoolMap[variableName] = other.variableBoolMap[variableName]; + } + else if (other.variableTypeMap[variableName] == DataType::FUNCTION) + { + variableFunctionMap[variableName] = other.variableFunctionMap[variableName]; + } + else + { + // std::cout << variableName << std::endl; + // std::cout << "There is a problem overwrite scope" << std::endl; + } + } + } + + std::map variableTypeMap; + std::map variableDoubleMap; + std::map variableBoolMap; + std::map> variableFunctionMap; +}; \ No newline at end of file diff --git a/src/main b/src/main new file mode 100644 index 0000000000000000000000000000000000000000..33e07b5dc5e1d5fe01e88a9a3a7f664a7b33ccba GIT binary patch literal 420440 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
N?}# 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 z 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⩔=evZ? z?cifmFwb`Y_uq$VxLevUJ6Y)Hd`<@5v9ZiU26WB>elqs$I^d50zZ!B=`!nxn(fp@K zIM3%rIA6LSt^n@utM}g{?R|em8n~a&b~NyPo10A!^}JsW+^@^`H1NldmU+(M`r8x0AACmeT|wu44+*BTo_xb0!z|X+F+NJ3K-+}jhUdE;8rRgD|zn6Ee3&3x=Li(8kokxND@9TZ; zmqN#{Z#nm2!TmZ#Cjj^J)~*8n`sMOn)r55xaGw7ai)Wgi?~MMR zL^z+{N7{sr^7*@g`}d5V1m5#YX|MZm??;5r4#zbc%JV`08Q@RO5?td}!@rjHtrrU& z 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 1 { +// steps = steps + 1 +// if x % 2 == 0 { +// x = x / 2 +// } +// else { +// x = 3 * x + 1 +// } +// } + +// print steps)"; + + + + std::string input = R"( +z = 42 + +def foo(x, y) { + def square(value) { + return value * value + } + + print square(x + y + z) +} + +z = 108 +f = foo + +result = f(1, 2) +if result != null { + print result +} + )"; + + + + +#endif + + // Lexer + std::vector TokenVector; + std::pair errorPair = Token::GenTokenVector(input, TokenVector); + if (errorPair.first != -1) + { + std::cout << "Syntax error on line " << errorPair.first << " column " << errorPair.second << "." << std::endl; + exit(1); + } + // Token::printLexer(TokenVector); + + // Parser + // Add the global Scope + ParserB::ScopeStack.push(Scope()); + ParserB::setupExpression(TokenVector); + std::vector> flows; + std::pair, std::string> errorResult = ParserB::HandleTokenVector(TokenVector, 0, TokenVector.size()-2, flows); + if (errorResult.first.first != -1) + { + std::cout << "Unexpected token at line " << errorResult.first.first << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; + exit(2); + } + + // Calculate + // std::cout << "start calculating" << std::endl; + for (int i=0; i < (int)flows.size(); i++) + { + Result result; + std::string errorMessage = ParserB::calculate(flows[i].get(), result); + + if (errorMessage.length() != 0) + { + std::cout << errorMessage << std::endl; + exit(3); + } + } + return 0; +} diff --git a/src/test.cpp b/src/test.cpp new file mode 100644 index 0000000..683b13a --- /dev/null +++ b/src/test.cpp @@ -0,0 +1,69 @@ +#include "lib/Lexer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +class Node +{ +public: + Node() : value(Token(TokenType::NONE, "", -1, -1, -1)) {} + Node(Token token) : value(token) {} + virtual ~Node() = default; + + Token value; +}; + +class Function +{ +public: + Function() = default; +}; + +class Scope +{ +public: + Scope() + : variableFunctionMap() + {} + + std::map> variableFunctionMap; +}; + +class Result +{ +public: + ~Result() { + } + + Function* function; +}; + + +int main() { + + std::stack ScopeStack = std::stack(); + ScopeStack.push(Scope()); + auto& variableFunctionMap = ScopeStack.top().variableFunctionMap; + + // // std::map> variableFunctionMap = std::map>(); + + // Result result = Result(); + // result.function = new Function(); + + // // variableFunctionMap["add"] = std::make_shared(); + // // variableFunctionMap["add"].reset(result.function); + // std::shared_ptr p = std::make_shared(); + // p.reset(result.function); + + Result result = Result(); + result.function = new Function(); + variableFunctionMap["add"] = std::make_shared(); + variableFunctionMap["add"].reset(result.function); + + return 0; +} \ No newline at end of file From 9ef412ff63cbf14d52056e4caaa71601035a721f Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Mon, 20 Nov 2023 14:01:09 -0800 Subject: [PATCH 2/6] update --- src/lib/Utils.cpp | 18 ------------------ src/lib/Utils.h | 15 --------------- 2 files changed, 33 deletions(-) delete mode 100644 src/lib/Utils.cpp delete mode 100644 src/lib/Utils.h diff --git a/src/lib/Utils.cpp b/src/lib/Utils.cpp deleted file mode 100644 index 89df160..0000000 --- a/src/lib/Utils.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "Utils.h" - - -void hint(std::vector expression, std::vector> expressionLines, int checkIndex, - int line, int index, std::string content) -{ - if (expression[checkIndex].line == line && expression[checkIndex].index == index && expression[checkIndex].content == content) - { - for (std::vector v : expressionLines) - { - for (Token token : v) - { - std::cout << token.content << " "; - } - std::cout << std::endl; - } - } -} diff --git a/src/lib/Utils.h b/src/lib/Utils.h deleted file mode 100644 index 12f0180..0000000 --- a/src/lib/Utils.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "Lexer.h" - -#define DEBUG 1 -#define HINT 0 - -void hint(std::vector expression, std::vector> expressionLines, int checkIndex, - int line=1, int index=7, std::string content="89"); - -// git add * -// git commit -m "Checkpoint2 partA finished" -// git push origin Michael - -// g++ -Wall -Wextra -Werror -std=c++17 parse.cpp -o main lib/Parser.cpp lib/Lexer.cpp \ No newline at end of file From bae35d1896a8341e0f43df68f5dba885e3d3dd59 Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Tue, 21 Nov 2023 17:20:51 -0800 Subject: [PATCH 3/6] pop() update --- src/a.out | Bin 100898 -> 0 bytes src/calc.cpp | 51 +- src/format.cpp | 109 ++-- src/lex.cpp | 26 +- src/lib/ASTNode.h | 48 +- src/lib/DataType.h | 2 + src/lib/Function.h | 12 +- src/lib/Lexer.cpp | 18 +- src/lib/Lexer.h | 6 +- src/lib/Parser.cpp | 526 ------------------ src/lib/Parser.h | 39 -- src/lib/ParserB.cpp | 1263 +++++++++++++++++++++++++++++++++++++++---- src/lib/ParserB.h | 337 +++++++++++- src/lib/Scope.h | 68 ++- src/lib/main | Bin 0 -> 161520 bytes src/main | Bin 420440 -> 0 bytes src/parse.cpp | 63 --- src/scrypt.cpp | 52 +- src/test.cpp | 87 +-- 19 files changed, 1791 insertions(+), 916 deletions(-) delete mode 100644 src/a.out delete mode 100644 src/lib/Parser.cpp delete mode 100644 src/lib/Parser.h create mode 100644 src/lib/main delete mode 100644 src/main delete mode 100644 src/parse.cpp diff --git a/src/a.out b/src/a.out deleted file mode 100644 index 23904fba7be0a261686e5eb200bad35fc56224f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100898 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

UbpYr)14-wf=unFgF3tbgq& zXdAva`EiU>wO`1I+XS1r1aZM{+W*A-bUgSV<{Ei$%s(0MpUBscxj&*l#~?57VE%6_ zY&FwobHTl*KYqUjzl{aI4aPjS-=+}bgWmVsaBiVJ9jGJgw4QjUn*X9WUU%yh(v1ESj1yWpjyn%yDCz{3JDz?#(1UY{ zC650N^8Y0C#5d6vy5B?^`b0QCKp#o9E-xnUW}nOasjHYyr-crghJ2Q^qR$O-Oy3WF zaa-3BFUJNx9c5Ez5hv=RNd{~ssm2G9r`EGtKdIJBh%4}jr>Fy) z$KeL6ijPccz`UysdMr!mk2P8i<*N!RaM_|Ieh4*G0c#$ud>@ZX#DgMLgw z+Dlo#?zZb*cb`vv?~KK$qjWuiGuDU2k2Ts!>!iC2__e1qNpqHy5zXJNH=S`9abllG z+ZGIA3ZKW8*yHK2G)@Aon_%Y z__z=-#}XF8o6$y70kf=4@UuJ#-`Qcv{1L3(c?aM5-}gMzP;{@al!m`2Mj z^4)^G*giVX(W)^YVWbn`bimeB)p$9}z`LK3=BzWqZbZIXwozZM`(rrMuus!@!uHKZ zd>sd2QzT9~?rnF+Al zExO{Ot<1F&Y+ugHwKq<2`mHQaJgyUH3#vxj-g{B6|1j|;P1wh1yBD}@?5Fm_FCFct znJ;Lm{q1^uk7rFE^!r|%O`W6l4QNc=aslp+T&<_$p3T4E;Gd&* zlu!NR`eP?8@^{i<+3F)Y-@R^Ht3ds0S5mhCclN1gpngsrMx#APpV0n@?N_Jgw_byI zN7<*Le&mUxpbzbi%kW;O0gdj(Jhw?hXI+e=3)rTeDHu8$LA=1zX$Tr-7e$=tGI^Twd4FWlG{P%~^k5aaY=h0wz z>lWgQHarPkeF!>66|2SzKvU{%_;B8%FQ-ZT%q*MZV9s@rk14P8wU5J{yrFTY9tZB3 zh(}%L%w;k@_41bBZ700_6ZxB`x!R6FT@IoiuJjFVnI>IGx7(4nL%Bx0JG}9X_ILQtTbES$(uosg zTa8wYG5?|A7cQ`6(5a6@J4dEWnmK&NzTe@g0C-fV;kqC6)k~$_xkh6I!XWQ@?w0Xs z-z)UJ^YNZIqm9zc_ZIAa`gIvbS+m>Ez}29kLfjdY546R<4dPv|9o;@!O{H&f`_<#H z1_rV?OK~4VV*a7!I51Kwk5Z`YUWYVV-cW+W%G1t{L_&-?fZ|UoXj~ zeN)3NT6Q^Kxs7qOo>BXs`iR(z9V zHSa^VZ#lv7#3A@bHY3fqBn{u~lIORPKm4$dj23_+9-rMC;dYMrkor_nT~Jh*G3p^ zxbFd`?sU>SzM)s}K9MiTiA&qe>kE1g>0EkJXyc~?O!|HseT%SqAwh%(+wa z0g!#S?;bqrwSgR+Mc!lIH3{w7p5A2s3&BS&nK9ZjjJ59rJdg&>tzFtne5}IppOR+act2%26&CJ@#9>8ZsTOy zqI<4r9#ntDLD=qxV7t@qr;L6I`D@*ZI_WqA5C?WW`&_Q8AfFZs4w`=8P1?R&(C?XL zYun41`%Tp}z7A`1?Xj|-{OEBb+Jt>a<>{U_0e)sXQr560N84A_73@2&&^#5BH*H^| zPNom%cgWXIC$0f6x!Sh@^gvymG4^4!scTFN9QAk>F zh}#0aLfykL@j=*N)P_6LCfqPoza32E-fBRl@ic5a_XZcM-(HX@*>BGks=gj|=Ka3BXniFw z$G*^VOMeS_(#+G;F~Rt`4D4r&o5N_4bs*&VO4tjUFY!#=Xakc+Xg5(->04u43T?p&5A<-xYtCGx)+uO5j@@W`{0Vw`0LucO>N-w^?e-bfI1=s5 zHh<>?#*v8k1NcgbuWbimj0ao4$>B@HW4lt9G7ZOpmSx`qNw!aH6v~M4qv2Zkyc5->DC3hXtCPBvcx&21jvq^L(_k;e{Oh*O zZ?Cmvzx8AgzVgkgu>^UNzT*YICqZZW`z|6aP)E{N%K_rj=U=P&@EY{<_8gz-<6?fd zBb;e?HKShFf;OM}i~ss7$4+zFU={d+^e2yYW?UI--^BIhTD>NWbBGVy%Us92G-R)Z z)BQ8~0dX@x2S>g+S5OB0owU^DP0%IG(|#U#;vGl!K^yGj+NJ9a`h5@S^jg&d)%fIQ zwSO~YdJJf)!|{$jH9qe~JkD1|=cFW`?NTo2fN{%h@Hxb2&N-U*u>U3vbWKk%R&i*n z?F7(sCGvCiQ$G5`S%9Z-0R4yqX#)=WjfN$#n;|4P5OaXO&h@Jn?C5D zxNrJA%RoC9fJT({HGsj#+Sco+Zwh0d4*Mjoukh=WxSqmAuf2(Nv@<8|^hw8v7ie&< z;N|p5f8~3hK8br}P5tQYlg1*Pa>$E)(vzUc58vzEd0O=6y8Wo1QsmjMEuky4f6TQG zO4`{8i}IMKy(z1UFh1Ld`j~T7>(Phlc0}3ET-9>CGij%wgU$9aY39%=g*w8+*N%?b zjr>ggL0NF{rA*G0w&GZ&Oa5!vink%HOJ+RvcKDn=u;>14>s!h?%YPOy>rR++v0pV| z;JDRmBT0T8DSkFWRm^9t!U)__sfS_>RAV{Nv(D zPg}Q#JHz~NZ%?Nc`N=^$dZDYf+qJswpud0{?TIjGKwhRU439Q!H~pO0cDo+wytdm_ zz+KA)`u>m0^T!d-&vu(Cg8*y(;FF5UG+Gz7g7fow_8_i6k*A0nY8HRM!X-u2Yw+n) zFTvO8%XItu`P?L)rXPG=ach$Hy4y{+8F1eRn`V!(H)4Qpzu4Xgt|K75w65{CYeRf{ zyoLM}%6IjbKJk8wc-$M2e2yC25=`Ez&dqv9x(HQ;O8wUKlN zt{*mjU$M^or&Yz$Rl=tdroO`ttHu^@9izci)<9dxE3--Fi zeZh%~Grn%sbFcP1^g)DgEU@-B7pT@>0^eqob+EuLFOa0p*o?e>0UNpbTAMc5OANo= zxhI(Bb;d{f7NiMV^}AYd=G0^F!+yL9ycmKWlk-HYAROIeq5Oo_R5q}he|v=vDAjSa(2G!+cnNgTd|_oVqS)YTP+G}|QXOoTZ!8DP+4 zl|vJpQ#TYe$q&kz5kj*&oN%1$mdbF)zb)bAPB_j%3p3pDy-Iko6OMEC6vETfWbPj{ zMSQ&`XLYh&rV7`;_BX_b-rP!>9=udx-

h>+D>%`Ao!Vo?z4G-~_f^VE^rQIcYot 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 WSKhud_e<~Y+&t& root; - std::pair, std::string> errorResult = ParserB::MakeExpressionTree(TokenVector, 0, TokenVector.size() - 2, root); - + // std::unique_ptr root; + // std::pair, std::string> errorResult = ParserB::MakeExpressionTree(TokenVector, 0, TokenVector.size() - 2, root); + + std::vector> flows; + // std::cout << TokenVector.at(TokenVector.size()-2).content << std::endl; + TokenVector.pop_back(); + TokenVector.push_back(Token(TokenType::SEMICOLON, ";", 0, 0 )); + TokenVector.push_back(Token(TokenType::END, "", 0, 0 )); + + std::pair, std::string> errorResult = ParserB::HandleTokenVector(TokenVector, 0, TokenVector.size()-2, flows); + + if (errorResult.first.first != -1) { std::cout << "Unexpected token at line " << errorResult.first.first << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; continue; } - ParserB::print(root.get()); + ParserB::print_no_semicolon(flows[0].get()); + // ParserB::print(flows[0].get(), 0, false); std::cout << std::endl; // Calculate Result result; - std::map originalVariableTypeMap(ParserB::variableTypeMap); - std::map originalVariableDoubleMap(ParserB::variableDoubleMap); - std::map originalVariableBoolMap(ParserB::variableBoolMap); - - std::string errorMessage = ParserB::calculate(root.get(), result); + Scope* originalScope = new Scope(*(ParserB::ScopeStack.top())); + std::string errorMessage = ParserB::calculate(flows[0].get(), result); if (errorMessage.length() != 0) { + // Error std::cout << errorMessage << std::endl; - ParserB::variableTypeMap.swap(originalVariableTypeMap); - ParserB::variableDoubleMap.swap(originalVariableDoubleMap); - ParserB::variableBoolMap.swap(originalVariableBoolMap); - continue; + delete ParserB::ScopeStack.top(); + ParserB::ScopeStack.pop(); + ParserB::ScopeStack.push(originalScope); + } + else + { + // No Error + ParserB::printValue(result); + std::cout << std::endl; + delete originalScope; } - ParserB::printValue(result); - std::cout << std::endl; } + + ParserB::clean(); + delete ParserB::ScopeStack.top(); return 0; } \ No newline at end of file diff --git a/src/format.cpp b/src/format.cpp index b0c2aef..d796c35 100644 --- a/src/format.cpp +++ b/src/format.cpp @@ -14,83 +14,35 @@ int main() { input = input.substr(0, input.size()-1); #endif #if DEBUG == 1 -// std::string input = R"(x = 42 -// steps = 0 - -// while x > 1 { -// steps = steps + 1 -// if x % 2 == 0 { -// x = x / 2 -// } -// else { -// x = 3 * x + 1 -// } -// } - -// print steps)"; - -// std::string input = R"( -// val = 105 -// fizz = val % 3 == 0 -// buzz = false -// if val % 5 == 0 { -// buzz = true -// } - -// if fizz & buzz { -// if buzz { -// print 333555 -// } -// else { -// print 333 -// } -// } -// else if buzz { -// print 555 -// } -// else { -// print val -// })"; - -// std::string input = R"( -// a = 0 -// if (a == 0) { -// print 0 -// } else if (a == 1) { -// print 11 -// } else { -// print 222 -// } -// print a -// )"; - std::string input = R"( -z = 42 - +(z = 42); def foo(x, y) { - def square(value) { - return value * value - } - - print square(x + y + z) + def square(value) { + return (value * value); + } + print square(((x + y) + z)); +} +(z = 108); +(f = foo); +(result = f(1, 2)); +if (result != null) { + print result; } -z = 108 -f = foo -print 1 +def p() { + print a; + return; +} +p(); +def p() { + return null; +} )"; -// std::string input = R"( -// x=1 -// y=2 - -// def add(a, b) { -// return a+b -// } -// )"; - #endif - + // std::cout << "===================" << std::endl; + // std::cout << input << std::endl; + // std::cout << "===================" << std::endl; std::vector TokenVector; std::pair errorPair = Token::GenTokenVector(input, TokenVector); @@ -100,7 +52,6 @@ print 1 exit(1); } // Token::printLexer(TokenVector); - std::vector> flows; std::pair, std::string> errorResult = ParserB::HandleTokenVector(TokenVector, 0, TokenVector.size()-2, flows); if (errorResult.first.first != -1) @@ -108,11 +59,23 @@ print 1 std::cout << "Unexpected token at line " << errorResult.first.first << " column " << errorResult.first.second << ": " << errorResult.second << std::endl; exit(2); } - + for (int i=0; i < (int)flows.size(); i++) { ParserB::print(flows[i].get()); + // if (flows[i].get()->value.type == TokenType::ARRAY) { + // ArrayNode* Array = dynamic_cast(flows[i].get()); + // if (Array->ArrayContent[2]->value.type == TokenType::NUMBER) { + // std::cout << "yes" << std::endl; + // } + // std::cout << Array->ArrayContent[2]->value << std::endl; + // } + // if (flows[i].get()->value.type == TokenType::VARIABLE) { + // std::cout << flows[i].get()->value.content << std::endl; + // } + + std::cout << std::endl; } - return 0; + return 0; } \ No newline at end of file diff --git a/src/lex.cpp b/src/lex.cpp index 81c84a3..5cff0b0 100644 --- a/src/lex.cpp +++ b/src/lex.cpp @@ -1,3 +1,4 @@ + #include "lib/Lexer.h" int main() { #if DEBUG == 0 @@ -23,19 +24,20 @@ int main() { //std::string input = "(* a b)"; //std::string input = "(= foo_ b 3)\n( + b 0 )\n(- (= b (+ b 5)) 7)\n(* foo b)\n"; //std::string input = "a\n"; - std::string input = R"((x = 42) -(steps = 0) -while (x > 1) { - (steps = (steps + 1)) - if ((x % 2) == 0) { - (x = (x / 2)) - } - else { - (x = ((3 * x) + 1)) - } -} -print steps)"; +// std::string input = R"((x = 42) +// (steps = 0) +// while (x > 1) { +// (steps = (steps + 1)) +// if ((x % 2) == 0) { +// (x = (x / 2)) +// } +// else { +// (x = ((3 * x) + 1)) +// } +// } +// print steps)"; //std::string input = "(=(n) 9)"; + std::string input = "[9]"; #endif std::vector TokenVector; diff --git a/src/lib/ASTNode.h b/src/lib/ASTNode.h index b2fdf89..ffed6c5 100644 --- a/src/lib/ASTNode.h +++ b/src/lib/ASTNode.h @@ -8,24 +8,58 @@ class Node { public: - Node() : value(Token(TokenType::NONE, "", -1, -1, -1)) {} - Node(Token token) : value(token) {} + Node() : value(Token(TokenType::NONE, "", -1, -1, -1)) , ArrayContent(){} + Node(Token token) : value(token), ArrayContent() {} + // Node(Node * copy) : value(copy->value), lookUp(copy->lookUp), lookUpStr(copy->lookUpStr), + // lookUpIndex(copy->lookUpIndex) { + // for (ele : copy->ArrayContent) { + // this->ArrayContent.push_back(ele); + // } + // } virtual ~Node() = default; + Token value; + bool lookUp = false; + std::string lookUpStr = ""; + double lookUpIndex = -1; + std::vector> ArrayContent; + int EqualityIndex = -1; + bool subArray = false; }; // An operation expression node should always have 2 children // A function call expression: Node1: function. Node2, 3...: parameters. // A function call expression must have a variable token and children.size() != 0 + class ExpressionNode : public Node { public: ExpressionNode() : Node(), children() {} ExpressionNode(Token token) : Node(token), children() {} virtual ~ExpressionNode() = default; - + + bool ArrayLookUp = false; + bool LookUpForm = true; + double index = -1; + // bool WrongArgu = false; + // std::string lookUpStr = "" std::vector> children; + std::vector> children2; +}; + +class ArrayNode : public Node +{ + public: + ArrayNode() : Node(), LookUpNode(){}; + ArrayNode(Token token) : Node(token), LookUpNode() {}; + virtual ~ArrayNode() = default; + std::vector> LookUpNode; + + // bool lookUp = false; + // std::string lookUpStr = ""; + // int lookUpIndex = -1; + // std::vector> ArrayContent; // stored all elements in array }; @@ -56,11 +90,12 @@ class IfNode : public Node class PrintNode : public Node { public: - PrintNode() : Node(), content(std::make_unique()) {} - PrintNode(Token token) : Node(token), content(std::make_unique()) {} + PrintNode() : Node(), content(std::make_unique()), content2(nullptr) {} + PrintNode(Token token) : Node(token), content(std::make_unique()), content2(nullptr) {} virtual ~PrintNode() = default; std::unique_ptr content; + std::unique_ptr content2; }; class ReturnNode : public Node @@ -83,4 +118,5 @@ class FunctionDefineNode : public Node std::string functionName; std::vector parameterNames; std::vector> flows; -}; \ No newline at end of file +}; + diff --git a/src/lib/DataType.h b/src/lib/DataType.h index 3877bf9..fb7c7e8 100644 --- a/src/lib/DataType.h +++ b/src/lib/DataType.h @@ -8,4 +8,6 @@ enum class DataType BOOL, DOUBLE, FUNCTION, + ARRAY, + SUBARRAY }; \ No newline at end of file diff --git a/src/lib/Function.h b/src/lib/Function.h index c763381..fce5e60 100644 --- a/src/lib/Function.h +++ b/src/lib/Function.h @@ -6,8 +6,18 @@ class Function { public: Function() = default; + + void setScope(Scope& scope) { + m_CaptureScope = new Scope(scope); + + for (std::string parameterName : m_ParameterNames) + { + m_CaptureScope->variableTypeMap.erase(parameterName); + } + } + std::vector m_ParameterNames; std::vector> m_FunctionFlows; - Scope m_CaptureScope; + Scope* m_CaptureScope; }; \ No newline at end of file diff --git a/src/lib/Lexer.cpp b/src/lib/Lexer.cpp index d96670c..0721dee 100644 --- a/src/lib/Lexer.cpp +++ b/src/lib/Lexer.cpp @@ -154,7 +154,7 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< { if ( i + 1 < len && input.at(i+1) == '='){ res.emplace_back(TokenType::EQUALITY,"==", line, index, -1); - i++; + i++; index++; } else{ @@ -231,6 +231,14 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< { res.emplace_back(TokenType::RIGHT_PARENTHESIS, ")", line, index, -1); } + else if (input.at(i) == '[') + { + res.emplace_back(TokenType::LEFT_BRACKET, "[", line, index, -1); + } + else if (input.at(i) == ']') + { + res.emplace_back(TokenType::RIGHT_BRACKET, "]", line, index, -1); + } else if (input.at(i) == '{') { res.emplace_back(TokenType::LEFT_BRACE, "{", line, index, -1); @@ -239,6 +247,14 @@ std::pair Token::GenTokenVector(const std::string& input, std::vector< { res.emplace_back(TokenType::RIGHT_BRACE, "}", line, index, -1); } + else if (input.at(i) == '[') + { + res.emplace_back(TokenType::LEFT_BRACKET, "[", line, index, -1); + } + else if (input.at(i) == ']') + { + res.emplace_back(TokenType::RIGHT_BRACKET, "]", line, index, -1); + } else if (input.at(i) == ',') { res.emplace_back(TokenType::COMMA, ",", line, index, -1); diff --git a/src/lib/Lexer.h b/src/lib/Lexer.h index ced420d..7cc3647 100644 --- a/src/lib/Lexer.h +++ b/src/lib/Lexer.h @@ -15,8 +15,8 @@ enum class TokenType { LEFT_PARENTHESIS, // ( RIGHT_PARENTHESIS, // ) - LEFT_BRACKET, // ( - RIGHT_BRACKET, // ) + LEFT_BRACKET, // [ + RIGHT_BRACKET, // ] MULTIPLY, // * DIVIDE, // / @@ -60,6 +60,8 @@ enum class TokenType { ELSE, PRINT, DEF, + + ARRAY }; class Token { diff --git a/src/lib/Parser.cpp b/src/lib/Parser.cpp deleted file mode 100644 index 1e9dd42..0000000 --- a/src/lib/Parser.cpp +++ /dev/null @@ -1,526 +0,0 @@ -#include "Parser.h" - -std::vector> Parser::expressionLines = std::vector>(); -std::map Parser::variableMap = std::map(); -std::map Parser::variableInitializedMap = std::map(); - -Node Parser::MakeTree(std::vector expression, int leftBound, int rightBound) -{ - // """ - // case 1. ( - // ERRORS: - // 1. ( not followed by operation symbol - // 2. ) is not the last token - // """ - if (expression[leftBound].type == TokenType::leftParenthesis) - { - // ( not followed by operation symbol - if (expression[leftBound + 1].type != TokenType::plus && expression[leftBound + 1].type != TokenType::minus && expression[leftBound + 1].type != TokenType::multiply && expression[leftBound + 1].type != TokenType::divide && expression[leftBound + 1].type != TokenType::equals) - { -#if DEBUG - std::cout << "1 ( not followed by operation symbol. e.g. (3 4) " << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, leftBound + 1); -#endif - std::cout << "Unexpected token at line " << expression[leftBound + 1].line << " column " << expression[leftBound + 1].index << ": " << expression[leftBound + 1].content << std::endl; - exit(2); - } - - int rightIndex = findRightParenthesis(expression, leftBound + 1, rightBound); - - // ) is not the last token - if (rightIndex != rightBound) { -#if DEBUG - std::cout << "2 ) is not the last token. e.g. (+1 2 e.g. (+ 1 2) 114514 " << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, rightIndex+1); -#endif - std::cout << "Unexpected token at line " << expression.at(rightIndex+1).line << " column " << expression.at(rightIndex+1).index << ": " << expression.at(rightIndex+1).content << std::endl; - exit(2); - } - - return MakeTree(expression, leftBound + 1, rightIndex - 1); - } - - - // """ - // case 2. number - // ERRORS: - // 3. there can be only one number - // """ - // number - else if (expression[leftBound].type == TokenType::number) - { - // there can be only one number - if (leftBound != rightBound) - { -#if DEBUG - std::cout << "3 there can be only one number e.g. 0 1 2" << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, leftBound+1); -#endif - std::cout << "Unexpected token at line " << expression[leftBound + 1].line << " column " << expression[leftBound + 1].index << ": " << expression[leftBound + 1].content << std::endl; - exit(2); - } - return Node(expression[leftBound]); - } - - - // """ - // case 3. variable - // ERRORS: - // 4. there can be only one variable - // """ - // variable - else if (expression[leftBound].type == TokenType::variable) - { - // there can be only one variable - // e.g. a 1 2 - if (leftBound != rightBound) - { -#if DEBUG - std::cout << "4 there can be only one variable e.g. a 1 2" << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, leftBound+1); -#endif - std::cout << "Unexpected token at line " << expression[leftBound + 1].line << " column " << expression[leftBound + 1].index << ": " << expression[leftBound + 1].content << std::endl; - exit(2); - } - return Node(expression[leftBound]); - } - - - // """ - // case 4. operations - // ERRORS: - // 4.5 token before operation must be ( - // 5 nothing follows the operation - // 5.5 the first element after = can not be number or (...) - // 6 when =, a variable can only be assigned to one number - // 6.5 when =, a variable can only be assigned to one (...) - - // """ - // operations = + - * / - else if (expression[leftBound].type == TokenType::plus || expression[leftBound].type == TokenType::minus || expression[leftBound].type == TokenType::multiply || expression[leftBound].type == TokenType::divide || expression[leftBound].type == TokenType::equals) - { - // token before operation must be ( - if (leftBound == 0 || expression[leftBound-1].type != TokenType::leftParenthesis) - { -#if DEBUG - std::cout << "4.5 token before operation must be ( e.g. '+ 1 2 3' " << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, leftBound); -#endif - std::cout << "Unexpected token at line " << expression[leftBound].line << " column " << expression[leftBound].index << ": " << expression[leftBound].content << std::endl; - exit(2); - } - - // nothing follows the operation - if (leftBound == rightBound) - { -#if DEBUG - std::cout << "5 nothing follows the operation e.g. '+'" << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, leftBound+1); -#endif - std::cout << "Unexpected token at line " << expression[leftBound + 1].line << " column " << expression[leftBound + 1].index << ": " << expression[leftBound + 1].content << std::endl; - exit(2); - } - - // iterate through all the elements and add them as children - Node res = Node(expression[leftBound]); - int p = leftBound + 1; - - // the first element after = can not be number or (...) - if (expression[leftBound].type == TokenType::equals && (expression[p].type == TokenType::number || expression[p].type == TokenType::leftParenthesis)) - { -#if DEBUG - std::cout << "5.5 the first element after = can not be number or (...) e.g. '= (a+2) 3'" << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, p); -#endif - std::cout << "Unexpected token at line " << expression[p].line << " column " << expression[p].index << ": " << expression[p].content << std::endl; - exit(2); - } - - - while (p <= rightBound) - { - // number - if (expression[p].type == TokenType::number) - { - // when =, the elements other than the last element shouldn't be a number - // = 3 a 4 b 3 = a = 4 = b - if (p != rightBound && expression[leftBound].type == TokenType::equals) - { -#if DEBUG - std::cout << "6 when =, a variable can only be assigned to one number. e.g. '= a 4 5 6 (error on 5)' " << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, p+1); -#endif - std::cout << "Unexpected token at line " << expression[p+1].line << " column " << expression[p+1].index << ": " << expression[p+1].content << std::endl; - exit(2); - } - - res.children.push_back(MakeTree(expression, p, p)); - p += 1; - } - // variable - else if (expression[p].type == TokenType::variable) - { - res.children.push_back(MakeTree(expression, p, p)); - p += 1; - } - // ( - else if (expression[p].type == TokenType::leftParenthesis) - { - int rightIndex = findRightParenthesis(expression, p + 1, rightBound); - - // when =, the elements other than the last element shouldn't be a (...) - // = 3 (a+b) 4 b 3 = (a+b) = 4 = b - if (rightIndex != rightBound && expression[leftBound].type == TokenType::equals) - { -#if DEBUG - std::cout << "6.5 when =, a variable can only be assigned to one (...) e.g. '= x (a+b) 4' " << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, rightIndex+1); -#endif - std::cout << "Unexpected token at line " << expression[rightIndex+1].line << " column " << expression[rightIndex+1].index << ": " << expression[rightIndex+1].content << std::endl; - exit(2); - } - - res.children.push_back(MakeTree(expression, p, rightIndex)); - p = rightIndex + 1; - } - - - // """ - // case 5. ErrorToken - // """ - // ErrorToken - else - { -#if DEBUG - std::cout << "7" << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, p); -#endif - std::cout << "Unexpected token at line " << expression[p].line << " column " << expression[p].index << ": " << expression[p].content << std::endl; - exit(2); - } - } - - - // """ - // Last ERROR Check - // """ - // if =, there must be at least two children - // (= foo) - if (expression[leftBound].type == TokenType::equals && res.children.size() < 2) - { -#if DEBUG - std::cout << "7.5 if =, there must be at least two children, e.g. (= foo)" << std::endl; -#endif -#if HINT - hint(expression, Parser::expressionLines, rightBound+1); -#endif - std::cout << "Unexpected token at line " << expression[rightBound+1].line << " column " << expression[rightBound+1].index << ": " << expression[rightBound+1].content << std::endl; - exit(2); - } - return res; - } - - - std::cout << "Something wrong..." << std::endl; - exit(2); - return Node(); -} - - -double Parser::calculate(Node root) -{ - // number - if (root.value.type == TokenType::number) - { - return root.value.value; - } - - // variable - else if (root.value.type == TokenType::variable) - { - if (variableInitializedMap.at(root.value.content) == false) - { - std::cout << "Runtime error: unknown identifier " << root.value.content << std::endl; - exit(3); - } - return variableMap.at(root.value.content); - } - - // = - else if (root.value.type == TokenType::equals) - { - // the last child must be a number or an initialized variable - Node last = root.children[root.children.size()-1]; - if (last.value.type == TokenType::variable && variableInitializedMap.at(last.value.content) == false) - { - std::cout << "Runtime error: unknown identifier " << last.value.content << std::endl; - exit(3); - } - double res = calculate(last); - - // set values - for (int i = 0; i < (int)root.children.size()-1; i++) - { - variableMap.at(root.children[i].value.content) = res; - variableInitializedMap.at(root.children[i].value.content) = true; - } - - return res; - } - - // + - * / - else { - // variable for operation is uninitialaized - if (root.children[0].value.type == TokenType::variable && variableInitializedMap.at(root.children[0].value.content) == false) - { - std::cout << "Runtime error: unknown identifier " << root.children[0].value.content << std::endl; - exit(3); - } - double res = calculate(root.children[0]); - for (int i = 1; i < (int)root.children.size(); i++) - { - // variable for operation is uninitialaized - if (root.children[i].value.type == TokenType::variable && variableInitializedMap.at(root.children[i].value.content) == false) - { - std::cout << "Runtime error: unknown identifier " << root.children[i].value.content << std::endl; - exit(3); - } - if (root.value.type == TokenType::plus) { res += calculate(root.children[i]); } - if (root.value.type == TokenType::minus) { res -= calculate(root.children[i]); } - if (root.value.type == TokenType::multiply) { res *= calculate(root.children[i]); } - if (root.value.type == TokenType::divide) - { - if (calculate(root.children[i]) == 0) { - std::cout << "Runtime error: division by zero." << std::endl; - exit(3); - } - res /= calculate(root.children[i]); - } - } - return res; - } -} - - -void Parser::print(Node root) -{ - if (root.value.type == TokenType::number) - { - int v = floor(root.value.value); - // 1000.000 -> 1000 - if ((double)v == root.value.value) - { - std::cout << v; - } - else - { - std::cout << root.value.content; - } - } - else if (root.value.type == TokenType::variable) - { - std::cout << root.value.content; - } - else { - std::cout << "("; - for (int i = 0; i < (int)root.children.size(); i++) - { - print(root.children[i]); - if (i != (int)root.children.size() - 1) - { - std::cout << " " << root.value.content << " "; - } - } - std::cout << ")"; - } -} - - -// exclude rightParenthesis -int Parser::findLeftParenthesis(std::vector expression, int leftBound, int rightBound) -{ - int balance = 1; - int p = rightBound; - while (p >= leftBound) { - if (expression[p].type == TokenType::leftParenthesis) { balance -= 1; } - if (expression[p].type == TokenType::rightParenthesis) { balance += 1; } - if (balance == 0) { break; } - p -= 1; - } - return p; -} - - -int Parser::findRightParenthesis(std::vector expression, int leftBound, int rightBound) -{ - int balance = 1; - int p = leftBound; - while (p <= rightBound) { - if (expression[p].type == TokenType::leftParenthesis) { balance += 1; } - if (expression[p].type == TokenType::rightParenthesis) { balance -= 1; } - if (balance == 0) { break; } - p += 1; - } - if (p > rightBound) - { -#if DEBUG - std::cout << "right parenthesis not found" << std::endl; -#endif - if (expression[p].line == 1 && expression[p].index == 6 && expression[p].content == "(") - { - for (std::vector v : expressionLines) - { - for (Token token : v) - { - std::cout << token.content << " "; - } - std::cout << std::endl; - } - } - std::cout << "Unexpected token at line " << expression[p].line << " column " << expression[p].index << ": " << expression[p].content << std::endl; - exit(2); - } - return p; -} - - -int Parser::findRightParenthesisNoError(std::vector expression, int leftBound, int rightBound) -{ - int balance = 1; - int p = leftBound; - while (p <= rightBound) { - if (expression[p].type == TokenType::leftParenthesis) { balance += 1; } - if (expression[p].type == TokenType::rightParenthesis) { balance -= 1; } - if (balance == 0) { break; } - p += 1; - } - return p; -} - - -// return vectors of lines -// register variables in map -void Parser::setupExpression(std::vector expression) -{ - if (expression.size() == 1) - { -#if DEBUG - std::cout << "-1 empty expression" << std::endl; -#endif - - std::cout << "Unexpected token at line " << 1 << " column " << 1 << ": " << "END" << std::endl; - exit(2); - } - std::vector> res; - std::vector current; - current.push_back(expression[0]); - int currentLine = expression[0].line; - // handle the first token variable - if (expression[0].type == TokenType::variable) - { - if (variableMap.find(expression[0].content) == variableMap.end()) - { - variableMap.insert({ expression[0].content, -1 }); - variableInitializedMap.insert({ expression[0].content, false }); - } - } - for (int i=1; i<(int)expression.size()-1; i++) - { - Token token = expression[i]; - // handle new variable - if (token.type == TokenType::variable) - { - if (variableMap.find(token.content) == variableMap.end()) - { - variableMap.insert({ token.content, -1 }); - variableInitializedMap.insert({ token.content, false }); - } - } - - // handle line - while (currentLine != token.line) - { - if (current.size() != 0) - { - current.push_back(Token(TokenType::end, expression[i].content, expression[i].line, expression[i].index)); - //current.push_back(Token(TokenType::end, "end", expression[i].line, expression[i].index)); - res.push_back(current); - } - current.clear(); - currentLine += 1; - } - current.push_back(token); - } - current.push_back(expression[expression.size()-1]); - res.push_back(current); - - - - // merge multiple lines of S expression - std::vector sExpression = res[0]; - - for (int i=1; i<(int)res.size(); i++) - { - if (sExpression[0].type == TokenType::number) - { - expressionLines.push_back(sExpression); - sExpression.clear(); - } - else if (sExpression[0].type == TokenType::leftParenthesis) - { - int right = findRightParenthesisNoError(sExpression, 1, sExpression.size()-1); - if (right > (int)sExpression.size()-1) - { - sExpression.pop_back(); - } - else - { - expressionLines.push_back(sExpression); - sExpression.clear(); - } - } - else - { - expressionLines.push_back(sExpression); - sExpression.clear(); - } - sExpression.insert(sExpression.end(), res[i].begin(), res[i].end()); - } - - if (sExpression.size() != 0) - { - expressionLines.push_back(sExpression); - } - - - // expressionLines = res; - - // for (std::vector v : expressionLines) - // { - // for (Token token : v) - // { - // std::cout << token.content << " "; - // } - // std::cout << std::endl; - // } -} \ No newline at end of file diff --git a/src/lib/Parser.h b/src/lib/Parser.h deleted file mode 100644 index e69266f..0000000 --- a/src/lib/Parser.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "Lexer.h" -#include "Utils.h" - - -class Node -{ -public: - Node() : value(Token(TokenType::none, "", -1, -1, -1)) {} - Node(Token token) : value(token) {} - - std::vector children; - Token value; -}; - -class Parser -{ -public: - static Node MakeTree(std::vector expression, int leftBound, int rightBound); - static double calculate(Node root); - static void print(Node root); - static void setupExpression(std::vector expression); - static void setupExpressionInfix(std::vector expression); - static std::vector> expressionLines; - static std::map variableMap; - static std::map variableInitializedMap; -private: - static int findLeftParenthesis(std::vector expression, int leftBound, int rightBound); - static int findRightParenthesis(std::vector expression, int leftBound, int rightBound); - static int findRightParenthesisNoError(std::vector expression, int leftBound, int rightBound); -}; - diff --git a/src/lib/ParserB.cpp b/src/lib/ParserB.cpp index fe0f49d..9da71fa 100644 --- a/src/lib/ParserB.cpp +++ b/src/lib/ParserB.cpp @@ -1,10 +1,8 @@ #include "ParserB.h" // Initialize static member variables -// std::stack ParserB::ScopeStack = {}; -// ParserB::ScopeStack.push(Scope()); - -std::stack ParserB::ScopeStack = std::stack(); +std::stack ParserB::ScopeStack; +std::vector> ParserB::functionStorage; std::map ParserB::hierarchyMap = { {TokenType::NUL , 0}, // null @@ -12,6 +10,7 @@ std::map ParserB::hierarchyMap = { {TokenType::TRUE , 0}, // true {TokenType::FALSE , 0}, // false {TokenType::VARIABLE , 0}, // a b c + {TokenType::LEFT_BRACKET , 0}, // [] {TokenType::LEFT_PARENTHESIS ,1}, // () {TokenType::MULTIPLY , 2}, // * {TokenType::DIVIDE , 2}, // / @@ -34,13 +33,23 @@ std::map ParserB::hierarchyMap = { std::pair, std::string> ParserB::HandleTokenVector(std::vector tokenVector, int leftBound, int rightBound, std::vector>& nodes) { int start = leftBound; + // auto& variableTypeMap = ScopeStack.top()->variableTypeMap; + if (leftBound == rightBound && tokenVector[leftBound].type == TokenType::VARIABLE) + { + std::unique_ptr node = std::make_unique(tokenVector[leftBound]); + nodes.push_back(std::move(node)); + } while (start < rightBound) { + if (tokenVector[start].type == TokenType::SEMICOLON) + { + start += 1; + } + // std::cout << start << std::endl; - if (tokenVector[start].type == TokenType::DEF) + else if (tokenVector[start].type == TokenType::DEF) { std::unique_ptr node = std::make_unique(tokenVector[start]); - int defIndex = start; // Name int functionNameIndex = defIndex + 1; @@ -97,7 +106,6 @@ std::pair, std::string> ParserB::HandleTokenVector(std::vect nodes.push_back(std::move(node)); start = rightBraceIndex + 1; } - else if (tokenVector[start].type == TokenType::WHILE) { std::unique_ptr node = std::make_unique(tokenVector[start]); @@ -264,11 +272,23 @@ std::pair, std::string> ParserB::HandleTokenVector(std::vect std::unique_ptr node = std::make_unique(tokenVector[start]); int printIndex = start; start += 1; - while (tokenVector[start].line == tokenVector[printIndex].line && start <= rightBound) - { + + while (tokenVector[start].type != TokenType::SEMICOLON){ start += 1; } - auto errorResult = MakeExpressionTree(tokenVector, printIndex + 1, start - 1, node->content); + + std::pair, std::string> errorResult; + if (printIndex + 1 <= start-1 && tokenVector[printIndex+1].type == TokenType::LEFT_BRACKET) + { + node->content2 = std::make_unique(tokenVector[printIndex+1]); + errorResult = HandleArray(tokenVector, printIndex + 1, start -1, node->content2); + + } + else + { + errorResult = MakeExpressionTree(tokenVector, printIndex + 1, start - 1, node->content); + } + if (errorResult.first.first != -1) { return errorResult; @@ -278,49 +298,316 @@ std::pair, std::string> ParserB::HandleTokenVector(std::vect else if (tokenVector[start].type == TokenType::RETURN) { std::unique_ptr node = std::make_unique(tokenVector[start]); - int printIndex = start; + int returnIndex = start; + start += 1; + while (tokenVector[start].type !=TokenType::SEMICOLON) + { + start += 1; + } + // there can be nothing following "return" + if (returnIndex + 1 <= start - 1) + { + auto errorResult = MakeExpressionTree(tokenVector, returnIndex + 1, start - 1, node->content); + if (errorResult.first.first != -1) + { + return errorResult; + } + } + else + { + node->content = nullptr; + } + nodes.push_back(std::move(node)); + } + // only array without any assignment + else if (tokenVector[start].type == TokenType::LEFT_BRACKET) + { + int EqualityIndex = -1; + int beginIndex = start; + int AssignmentIndex = -1; start += 1; - while (tokenVector[start].line == tokenVector[printIndex].line && start <= rightBound) + while (tokenVector[start].line == tokenVector[beginIndex].line && start <= rightBound) { + if (tokenVector[start].content == "==" || tokenVector[start].content == "!=" ) { + if (tokenVector[start-1].content != "]"){ + start += 1; + continue; + } + EqualityIndex = start; + } + if (tokenVector[start].content == "=") { + AssignmentIndex = start; + } start += 1; } - auto errorResult = MakeExpressionTree(tokenVector, printIndex + 1, start - 1, node->content); + if (AssignmentIndex != -1) + { + std::unique_ptr node = std::make_unique(tokenVector[AssignmentIndex]); + std::unique_ptr node1 = std::make_unique(); + // std::cout << "r: " << AssignmentIndex << beginIndex << std::endl; + auto errorResult1 = HandleArray(tokenVector, beginIndex, AssignmentIndex-1, node1); + if (errorResult1.first.first != -1) + { + return errorResult1; + } + node1->value.type = TokenType::LEFT_BRACKET; + node->children2.push_back(std::move(node1)); + + if (tokenVector[AssignmentIndex+1].type != TokenType::LEFT_BRACKET) { + std::unique_ptr node2 = std::make_unique(); + auto errorResult2 = MakeExpressionTree(tokenVector, AssignmentIndex+1, start-1, node2); + if (errorResult1.first.first != -1) + { + return errorResult1; + } + node->children2.push_back(std::move(node2)); + } + else { + std::unique_ptr node2 = std::make_unique(); + auto errorResult2 = HandleArray(tokenVector, AssignmentIndex+1, start-1, node2); + if (errorResult1.first.first != -1) + { + return errorResult1; + } + node2->value.type = TokenType::ARRAY; + node->children2.push_back(std::move(node2)); + } + + nodes.push_back(std::move(node)); + return { { -1, -1 }, "" }; + } + // std::cout << "t" < node = std::make_unique(tokenVector[beginIndex]); + auto errorResult = HandleArray(tokenVector, beginIndex, start - 1, node, EqualityIndex); if (errorResult.first.first != -1) { return errorResult; + } + if (EqualityIndex!=-1){ + node->EqualityIndex = EqualityIndex; } nodes.push_back(std::move(node)); } else { - std::unique_ptr node = std::make_unique(tokenVector[start]); + // std::cout << "running1" << std::endl; + bool arrayExist = false; // distinguished whether it is array int beginIndex = start; start += 1; + int EqualityIndex = -1; + while (tokenVector[start].line == tokenVector[beginIndex].line && start <= rightBound) { + if (tokenVector[start].type == TokenType::LEFT_BRACKET){ + if (tokenVector[start-1].type == TokenType::TRUE || tokenVector[start-1].type == TokenType::FALSE){ + tokenVector[start-1].type = TokenType::VARIABLE; + // variableTypeMap[tokenVector[start-1].content] = DataType::UNINITIALIZED; + start+= 1; + continue; + } + if (tokenVector[start-1].type == TokenType::LEFT_PARENTHESIS) { + start += 1; + continue; + } + if (tokenVector[start-1].type != TokenType::VARIABLE ){ //check whether it is creating a new array + arrayExist = true; + } + + } + + if (tokenVector[start].content == "==" || tokenVector[start].content == "!=" ) { + // std::cout << "yes" << std::endl; + EqualityIndex = start; + } start += 1; } - auto errorResult = MakeExpressionTree(tokenVector, beginIndex, start - 1, node); + + if (arrayExist) + { + tokenVector[beginIndex].type = TokenType::ARRAY; + std::unique_ptr node = std::make_unique(tokenVector[beginIndex]); + auto errorResult = HandleArray(tokenVector, beginIndex, start - 1, node, EqualityIndex); + if (EqualityIndex!=-1){ + node->EqualityIndex = EqualityIndex; + } + // std::cout << "yes1" << std::endl; + if (errorResult.first.first != -1) + { + return errorResult; + } + nodes.push_back(std::move(node)); + } + else { + std::unique_ptr node = std::make_unique(tokenVector[beginIndex]); + // std::cout << tokenVector[beginIndex].content <, std::string> ParserB::HandleArray(std::vector tokenVector, int leftBound, int rightBound, std::unique_ptr& node, int index) +{ + if (leftBound > rightBound) { + std::cout << "ERROR1" << std::endl; + } + int leftBracket = leftBound; + + // error check + while (leftBracket < rightBound) + { + + if (tokenVector[leftBracket].type == TokenType::LEFT_BRACKET) { break; } + leftBracket += 1; + } + // [ not found + if (leftBracket== rightBound) + { + return { { tokenVector[leftBracket].line, tokenVector[leftBracket].index }, tokenVector[leftBracket].content }; + } + // find ] + int rightBracket = ParserB::findRightBraceNoError(tokenVector, leftBracket + 1, rightBound); + + + if (rightBracket > rightBound) + { + std::cout << "2" << std::endl; + return { { tokenVector[rightBracket].line, tokenVector[rightBracket].index }, tokenVector[rightBracket].content }; + } + if (rightBracket + 1 <= rightBound && tokenVector[rightBracket + 1].type== TokenType::LEFT_BRACKET) { + node->lookUp = true; + if (rightBracket + 3 <= rightBound) { + if (tokenVector[rightBracket+3].type == TokenType::RIGHT_BRACKET) { + if (tokenVector[rightBracket + 2].type == TokenType::NUMBER) + { + node->lookUpIndex = tokenVector[rightBracket + 2].value; + } + else + { + node->lookUpStr = tokenVector[rightBracket + 2].content; + } + } + else { + // std::cout << "Ru" < cur = std::make_unique(); + auto error = MakeExpressionTree(tokenVector, rightBracket+2, rightBound-1, cur); + node->LookUpNode.push_back(std::move(cur)); + } + } + else { + std::cout << "ERROR4" << std::endl; + // node = std::make_unique(expression[topIndex]); + // int rightB = findRightBracketNoError( expression, topIndex+2, rightBound); + // std::unique_ptr cur = std::make_unique(); + // auto error = MakeExpressionTree(expression, topIndex+2, rightB-1, cur); + // node->children.push_back(std::move(cur)); + // node->ArrayLookUp = true; + // node->value.type = TokenType::ARRAY; + } + // return { { -1, -1 }, "" }; + } + + if (index!=-1) + { + node = std::make_unique(tokenVector[index]); + + // on the left + if (tokenVector[index-1].type == TokenType::RIGHT_BRACKET) + { + std::unique_ptr node1 = std::make_unique(); + std::pair, std::string> errorResult1 = HandleArray(tokenVector, leftBound, index-1, node1); + if (errorResult1.first.first != -1) { return errorResult1; } + node1->value.type = TokenType::ARRAY; + node->ArrayContent.push_back(std::move(node1)); + } + else + { + std::unique_ptr node1 = std::make_unique(tokenVector[index-1]); + node1->value.type = TokenType::VARIABLE; + node->ArrayContent.push_back(std::move(node1)); + } + + // on the right + if (tokenVector[index+1].type == TokenType::LEFT_BRACKET) + { + std::unique_ptr node2 = std::make_unique(); + std::pair, std::string> errorResult2 = HandleArray(tokenVector, index+1, rightBound, node2); + if (errorResult2.first.first != -1) { return errorResult2; } + node2->value.type = TokenType::ARRAY; + node->ArrayContent.push_back(std::move(node2)); + } + else + { + std::unique_ptr node2 = std::make_unique(tokenVector[index+1]); + node2->value.type = TokenType::VARIABLE; + node->ArrayContent.push_back(std::move(node2)); + } + + return { { -1, -1 }, "" }; + } + + for (int index = leftBracket + 1; index < rightBracket; index++) { + int commaIndex = index; + while (commaIndex < rightBracket) { + + if (tokenVector[commaIndex].type == TokenType::COMMA){ + break; + } + commaIndex += 1; + } + // Case 1: when the element is single token ex. true, 1 + if (commaIndex == index + 1) { + std::unique_ptr curr = std::make_unique(tokenVector[index]); + node->ArrayContent.push_back(std::move(curr)); + } + // Case 2: when the element is an array ex. [1,2] + else if (tokenVector[index].type == TokenType::LEFT_BRACKET) { + std::unique_ptr curr = std::make_unique(); + auto errorResult = HandleArray(tokenVector, index , commaIndex-1 , curr); + curr->value.type = TokenType::ARRAY; if (errorResult.first.first != -1) { return errorResult; } - nodes.push_back(std::move(node)); + node->ArrayContent.push_back(std::move(curr)); + } + // Case 3: when the element is an expression ex. 1 + 1, 2*3 + else { + std::unique_ptr curr; + auto errorResult = ParserB::MakeExpressionTree(tokenVector, index , commaIndex-1 , curr); + if (errorResult.first.first != -1) + { + return errorResult; + } + node->ArrayContent.push_back(std::move(curr)); } + index = commaIndex; } return { { -1, -1 }, "" }; } std::pair, std::string> ParserB::MakeExpressionTree(std::vector expression, int leftBound, int rightBound, std::unique_ptr& node) { + + if (expression[rightBound].type == TokenType::SEMICOLON) + { + rightBound -= 1; + } + if (leftBound > rightBound) { #if DEBUG std::cout << "1 no expression " << std::endl; #endif return { { expression[leftBound].line, expression[leftBound].index }, expression[leftBound].content }; } - - + // Find the top level token int topIndex = leftBound; int i = leftBound ; @@ -357,7 +644,7 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec // Find the next element // ignore content inside (...) - if (expression[i].type == TokenType::LEFT_PARENTHESIS) + if (expression[i].type == TokenType::LEFT_PARENTHESIS || expression[i].type == TokenType::LEFT_BRACKET) { int rightIndex = findRightParenthesisNoError(expression, i+1, rightBound); if (rightIndex > rightBound) @@ -376,6 +663,16 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec } i = rightIndex + 1; } + // array + else if (i+1 <= rightBound && expression[i].type == TokenType::VARIABLE && expression[i+1].type == TokenType::LEFT_BRACKET) + { + int rightIndex = findRightBracketNoError(expression, i+2, rightBound); + if (rightIndex > rightBound) + { + return { { expression[rightIndex].line, expression[rightIndex].index }, expression[rightIndex].content }; + } + i = rightIndex + 1; + } else { i += 1; @@ -402,57 +699,142 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec // Seperate a function call into function and parameters. e.g. "getFunc()(1,2)(3)" should be seperated as "getFunc()(1,2)" and "(3)", if (topIndex+1 <= rightBound && expression[topIndex+1].type == TokenType::LEFT_PARENTHESIS) { - node = std::make_unique(expression[topIndex]); - - // getFunc()(1,2)() - // get The last pair of parenthesis (...) - int leftParenthesisIndex = topIndex + 1; - int rightParenthesisIndex; - while (true) { - rightParenthesisIndex = findRightParenthesisNoError(expression, leftParenthesisIndex + 1, rightBound); - if (rightParenthesisIndex > rightBound) + // function array member function len(), pop(), push() + if (expression[topIndex].content == "len" || expression[topIndex].content == "pop" || expression[topIndex].content == "push" ) + { + if (expression[topIndex].content == "len" ) { - return { { expression[rightParenthesisIndex].line, expression[rightParenthesisIndex].index }, expression[rightParenthesisIndex].content }; + node = std::make_unique(expression[topIndex]); + int leftParen = topIndex+1; + int rightParen = findRightParenthesisNoError(expression, leftParen+1, rightBound); + std::vector> Flows; + // bool Havebracket = false; + // bool HaveComma = false + // for (size_t i = leftParen; i < rightParen; i++) { + // if (expression[i].type == TokenType::LEFT_BRACKET) + // { + // Havebracket = true; + // } + // if (expression[i].type == TokenType::COMMA) + // { + // HaveComma = true; + // } + // } + // if (Havebracket == false && HaveComma == true) + // { + // node->WrongArgu = true; + // std::unique_ptr node1 = std::make_unique(); + // node->children2.push_back(std::move(Flows[0])); + // } + // else + // { + auto errorMessage = ParserB::HandleTokenVector(expression, leftParen+1, rightParen-1, Flows); + // std::cout << "running" <children2.push_back(std::move(Flows[0])); + // } } - if (rightParenthesisIndex + 1 <= rightBound && expression[rightParenthesisIndex + 1].type == TokenType::LEFT_PARENTHESIS) + else if (expression[topIndex].content == "pop" ) { - leftParenthesisIndex = rightParenthesisIndex + 1; + node = std::make_unique(expression[topIndex]); + int leftParen = topIndex+1; + int rightParen = findRightParenthesisNoError(expression, leftParen+1, rightBound); + std::vector> Flows; + auto errorMessage = ParserB::HandleTokenVector(expression, leftParen+1, rightParen-1, Flows); + if (errorMessage.first.first != -1) { + return errorMessage; + } + node->children2.push_back(std::move(Flows[0])); } - else { - break; + } + else { + node = std::make_unique(expression[topIndex]); + // getFunc()(1,2)() + // get The last pair of parenthesis (...) + int leftParenthesisIndex = topIndex + 1; + int rightParenthesisIndex; + while (true) { + rightParenthesisIndex = findRightParenthesisNoError(expression, leftParenthesisIndex + 1, rightBound); + if (rightParenthesisIndex > rightBound) + { + return { { expression[rightParenthesisIndex].line, expression[rightParenthesisIndex].index }, expression[rightParenthesisIndex].content }; + } + if (rightParenthesisIndex + 1 <= rightBound && expression[rightParenthesisIndex + 1].type == TokenType::LEFT_PARENTHESIS) + { + leftParenthesisIndex = rightParenthesisIndex + 1; + } + else { + break; + } } - } - // Function - std::unique_ptr functionNode = std::make_unique(); - MakeExpressionTree(expression, topIndex, leftParenthesisIndex - 1, functionNode); - node->children.push_back(std::move(functionNode)); + // Function + std::unique_ptr functionNode = std::make_unique(); + MakeExpressionTree(expression, topIndex, leftParenthesisIndex - 1, functionNode); + node->children.push_back(std::move(functionNode)); - // Parameters - // add parameter values into children - // parameter values are seperated by comma. Remember to skip parenthesis. - int left = leftParenthesisIndex + 1; - while (left <= rightParenthesisIndex-1) - { - std::unique_ptr parameterNode = std::make_unique(); - int right = left; - while (right <= rightParenthesisIndex-1 && expression[right].type != TokenType::COMMA) + // Parameters + // add parameter values into children + // parameter values are seperated by comma. Remember to skip parenthesis. + int left = leftParenthesisIndex + 1; + + while (left <= rightParenthesisIndex-1) { - // Skip parenthesis e.g. add(add(1, 2), 3) - if (expression[right].type == TokenType::LEFT_PARENTHESIS) + std::unique_ptr parameterNode = std::make_unique(); + int right = left; + while (right <= rightParenthesisIndex-1 && expression[right].type != TokenType::COMMA) { - int right = findRightParenthesisNoError(expression, right+1, rightParenthesisIndex-1); - if (right > rightParenthesisIndex-1) + // Skip parenthesis e.g. add(add(1, 2), 3) + if (expression[right].type == TokenType::LEFT_PARENTHESIS) { - return { { expression[right].line, expression[right].index }, expression[right].content }; + right = findRightParenthesisNoError(expression, right+1, rightParenthesisIndex-1); + if (right > rightParenthesisIndex-1) + { + return { { expression[right].line, expression[right].index }, expression[right].content }; + } } + right += 1; } - right += 1; + + MakeExpressionTree(expression, left, right-1, parameterNode); + node->children.push_back(std::move(parameterNode)); + left = right + 1; + } - MakeExpressionTree(expression, left, right-1, parameterNode); - node->children.push_back(std::move(parameterNode)); - left = right + 1; + } + + } + // array lookup + else if (topIndex+1 <= rightBound && expression[topIndex+1].type == TokenType::LEFT_BRACKET) + { + if (topIndex+3 <= rightBound && expression[topIndex+3].type == TokenType::RIGHT_BRACKET) { // make sure it is correct lookup format + node = std::make_unique(expression[topIndex]); + if (expression[topIndex+2].type== TokenType::NUMBER){ + node->index = expression[topIndex+2].value; + } + else { + // std::cout << "e: " << expression[topIndex+2].content<lookUpStr = expression[topIndex+2].content; + } + node->ArrayLookUp = true; + } + else { + node = std::make_unique(expression[topIndex]); + int rightB = findRightBracketNoError( expression, topIndex+2, rightBound); + std::unique_ptr cur = std::make_unique(); + auto error = MakeExpressionTree(expression, topIndex+2, rightB-1, cur); + node->children.push_back(std::move(cur)); + node->ArrayLookUp = true; + if (node->children[0]->value.type == TokenType::BIGGER_EQUAL ||node->children[0]->value.type == TokenType::SMALLER_EQUAL + || node->children[0]->value.type == TokenType::EQUALITY || node->children[0]->value.type == TokenType::INEQUALITY) + {node->LookUpForm = false;} + node->value.type = TokenType::VARIABLE; + // if (node->value.type == TokenType::VARIABLE){ + // std::cout << node->value.content << " " <children[0]->value.content << std::endl; + // } } } // variable @@ -476,9 +858,8 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec } // case 5 = else if (expression[topIndex].type == TokenType::ASSIGNMENT) - { + { node = std::make_unique(expression[topIndex]); - // check assignment ERROR // Error 1. Nothing before = e.g =8 if (topIndex == leftBound) @@ -488,15 +869,16 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec return { { expression[topIndex+1].line, expression[topIndex+1].index }, expression[topIndex+1].content }; // Error 3. What is before = is not a variable e.g 1=1 // Handled in runtime - // if (expression[topIndex-1].type != TokenType::VARIABLE) - // return { { expression[topIndex].line, expression[topIndex].index }, expression[topIndex].content }; - + // on the left std::unique_ptr node1; + // std::cout << "::" << expression[leftBound].content <, std::string> errorResult1 = MakeExpressionTree(expression, leftBound, topIndex-1, node1); if (errorResult1.first.first != -1) { return errorResult1; } node->children.push_back(std::move(node1)); + + // on the right std::unique_ptr node2; std::pair, std::string> errorResult2 = MakeExpressionTree(expression, topIndex+1, rightBound, node2); @@ -523,10 +905,13 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec node->children.push_back(std::move(node1)); // on the right + std::pair, std::string> errorResult2; std::unique_ptr node2; - std::pair, std::string> errorResult2 = MakeExpressionTree(expression, topIndex+1, rightBound, node2); + errorResult2 = MakeExpressionTree(expression, topIndex+1, rightBound, node2); if (errorResult2.first.first != -1) { return errorResult2; } node->children.push_back(std::move(node2)); + + return { { -1, -1 }, "" }; } @@ -541,6 +926,11 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec // get rid of the parenthesis pair return MakeExpressionTree(expression, topIndex+1, rightIndex-1, node); } + // else if (expression[topIndex].type == TokenType::LEFT_BRACKET) + // { + // std::unique_ptr curr = std::make_unique(expression[topIndex]); + // auto errorMessage = HandleArray(expression, leftBound) + // } // case 8 ERROR #if DEBUG std::cout << "3 " << std::endl; @@ -550,7 +940,8 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec std::string ParserB::calculate(Node* root, Result& result) { - auto& variableTypeMap = ScopeStack.top().variableTypeMap; + auto& variableTypeMap = ScopeStack.top()->variableTypeMap; + auto& variableArrayMap = ScopeStack.top()->variableArrayMap; // Def if (root->value.type == TokenType::DEF) @@ -562,8 +953,9 @@ std::string ParserB::calculate(Node* root, Result& result) result.function = std::make_shared(); result.function->m_ParameterNames = functionDefineNode->parameterNames; result.function->m_FunctionFlows = std::move(functionDefineNode->flows); - result.function->m_CaptureScope = Scope(ScopeStack.top()); setVariable(functionDefineNode->functionName, result); + result.function->setScope(*ScopeStack.top()); + functionStorage.push_back(result.function); return ""; } // While @@ -582,9 +974,9 @@ std::string ParserB::calculate(Node* root, Result& result) // execute flows for (int i=0; i < (int)whileNode->flows.size(); i++) { - Result flowResult; - std::string errorMessageFlow = calculate(whileNode->flows[i].get(), flowResult); - if (errorMessageFlow != "") { return errorMessageFlow; } + std::string errorMessageFlow = calculate(whileNode->flows[i].get(), result); + if (errorMessageFlow != "") { return errorMessageFlow; } + if (whileNode->flows[i].get()->value.type == TokenType::RETURN) { return ""; } } } return ""; @@ -606,9 +998,11 @@ std::string ParserB::calculate(Node* root, Result& result) // execute flows for (int i=0; i < (int)ifNode->flowGroups[conditionIndex].size(); i++) { - Result flowResult; - std::string errorMessageFlow = calculate(ifNode->flowGroups[conditionIndex][i].get(), flowResult); - if (errorMessageFlow != "") { return errorMessageFlow; } + std::string errorMessageFlow = calculate(ifNode->flowGroups[conditionIndex][i].get(), result); + if (errorMessageFlow != "") { return errorMessageFlow; } + if (ifNode->flowGroups[conditionIndex][i].get()->value.type == TokenType::RETURN) { + return ""; + } } return ""; } @@ -620,9 +1014,9 @@ std::string ParserB::calculate(Node* root, Result& result) { for (int i=0; i < (int)ifNode->flowGroups[ifNode->flowGroups.size()-1].size(); i++) { - Result flowResult; - std::string errorMessageFlow = calculate(ifNode->flowGroups[ifNode->flowGroups.size()-1][i].get(), flowResult); - if (errorMessageFlow != "") { return errorMessageFlow; } + std::string errorMessageFlow = calculate(ifNode->flowGroups[ifNode->flowGroups.size()-1][i].get(), result); + if (errorMessageFlow != "") { return errorMessageFlow; } + if (ifNode->flowGroups[ifNode->flowGroups.size()-1][i].get()->value.type == TokenType::RETURN) { return ""; } } return ""; } @@ -633,8 +1027,14 @@ std::string ParserB::calculate(Node* root, Result& result) { PrintNode* printNode = dynamic_cast(root); Result flowResult; - std::string errorMessageFlow = calculate(printNode->content.get(), flowResult); - if (errorMessageFlow != "") { return errorMessageFlow; } + std::string errorMessageFlow; + if (printNode->content2 != nullptr) { + errorMessageFlow = calculate(printNode->content2.get(), flowResult); + } + else { + errorMessageFlow = calculate(printNode->content.get(), flowResult); + } + if (errorMessageFlow != "") { return errorMessageFlow; } ParserB::printValue(flowResult); std::cout << std::endl; } @@ -642,8 +1042,170 @@ std::string ParserB::calculate(Node* root, Result& result) else if (root->value.type == TokenType::RETURN) { ReturnNode* returnNode = dynamic_cast(root); - std::string errorMessageFlow = calculate(returnNode->content.get(), result); - if (errorMessageFlow != "") { return errorMessageFlow; } + if (returnNode->content != nullptr) + { + std::string errorMessageFlow = calculate(returnNode->content.get(), result); + result.isreturn = true; + if (errorMessageFlow != "") { return errorMessageFlow; } + } + else + { + returnNode->content = std::make_unique(Token(TokenType::NUL, "null", -1, -1, -1)); + std::string errorMessageFlow = calculate(returnNode->content.get(), result); + result.isreturn = true; + if (errorMessageFlow != "") { return errorMessageFlow; } + } + } + // Equality + else if (root->EqualityIndex != -1) + { + ArrayNode * Array = dynamic_cast(root); + if(Array->ArrayContent[0]->value.type == TokenType::VARIABLE) + { + if (variableTypeMap.at(Array->ArrayContent[0]->value.content) == DataType::ARRAY){ + if(variableArrayMap.at(Array->ArrayContent[0]->value.content)->ArrayContent.size() != Array->ArrayContent[0]->ArrayContent.size()){ + result.type = DataType::BOOL; + result.boolValue = 0; + } + } + } + else + { + if (variableTypeMap.at(Array->ArrayContent[1]->value.content) == DataType::ARRAY){ + if(variableArrayMap.at(Array->ArrayContent[1]->value.content)->ArrayContent.size() != Array->ArrayContent[1]->ArrayContent.size()){ + result.type = DataType::BOOL; + result.boolValue = 0; + } + } + } + + return ""; + } + + // Array + else if (root->value.type == TokenType::ARRAY || root->value.type == TokenType::LEFT_BRACKET) // may cause memory leak check again !!!! + { + ArrayNode * Array = dynamic_cast(root); + result.type = DataType::ARRAY; + result.arrayValue = std::make_shared(Array->value); + result.arrayValue->lookUp = Array->lookUp; + result.arrayValue->lookUpStr = Array->lookUpStr; + result.arrayValue->lookUpIndex = Array->lookUpIndex; + + + for (auto element : Array->ArrayContent){ + + // std::cout << element->value.content << " " << element->value.value <value.type == TokenType::NUMBER) + { + result.arrayValue->ArrayContent.push_back(element); + } + + else if (element->value.type == TokenType::FALSE || element->value.type == TokenType::TRUE)\ + { + result.arrayValue->ArrayContent.push_back(element); + } + + else if (element->value.type == TokenType::LEFT_BRACKET) + { + Result arrayResult; + std::string errorMessage; + errorMessage = calculate (element.get(), arrayResult); + if (errorMessage != "") { return errorMessage; } + result.arrayValue->ArrayContent.push_back(element); + + } + else if (element->value.type == TokenType::NUL) + { + result.arrayValue->ArrayContent.push_back(element); + } + else if (element->value.type == TokenType::ARRAY) + { + Result arrayResult; + std::string errorMessage; + errorMessage = calculate (element.get(), arrayResult); + element->subArray = true; + result.arrayValue->ArrayContent.push_back(element); + } + else if (element->value.type == TokenType::VARIABLE) + { + Result arrayResult; + std::string errorMessage; + errorMessage = calculate (element.get(), arrayResult); + if (arrayResult.type == DataType::DOUBLE) { + element->value.value = arrayResult.doubleValue; + element->value.type = TokenType::NUMBER; + result.arrayValue->ArrayContent.push_back(element); + } + else if (arrayResult.type == DataType::NUL){ + + element->value.type = TokenType::NUL; + result.arrayValue->ArrayContent.push_back(element); + } + else if (arrayResult.type == DataType::BOOL){ + element->value.type = TokenType::TRUE; + element->value.value = arrayResult.boolValue; + } + else if (arrayResult.type == DataType::ARRAY){ + element->value.type = TokenType::ARRAY; + element = arrayResult.arrayValue; + result.arrayValue->ArrayContent.push_back(element); + } + } + // + - * / % ... + else + { + Result NumberResult; + std::string errorMessage; + calculate (element.get(), NumberResult); + if (errorMessage != "") {return errorMessage;} + element->value.value = NumberResult.doubleValue; + element->value.type = TokenType::NUMBER; + + result.arrayValue->ArrayContent.push_back(element); + } + } + if (Array->lookUp == true) + { + // x[1+2] x[1>=2] + if (Array->lookUpStr == "" && Array->lookUpIndex == -1 && Array->LookUpNode.size()==0) + { + Result lookupResult; + calculate(Array->ArrayContent[0].get(), lookupResult); + if (lookupResult.type == DataType::DOUBLE) {Array->lookUpIndex = lookupResult.doubleValue; } + else {return "Runtime error: index is not a number.";} + } + if (Array->lookUpStr != "" || Array->LookUpNode.size()!=0){ return "Runtime error: index is not a number."; } + double a,b; + b = std::modf(Array->lookUpIndex,&a); + + if (b!= 0) { return "Runtime error: index is not an integer."; } + // if (variableTypeMap.at(Array->value.content) != DataType::ARRAY) { return "Runtime error: not an array."; } + int I = result.arrayValue->ArrayContent.size(); + if (Array->lookUpIndex< 0 || Array->lookUpIndex >= I ) { return "Runtime error: index out of bounds."; } + + if (result.arrayValue->ArrayContent[Array->lookUpIndex]->value.type == TokenType::NUMBER) + { + result.doubleValue = result.arrayValue->ArrayContent[Array->lookUpIndex]->value.value; + result.type = DataType::DOUBLE; + } + else if (result.arrayValue->ArrayContent[Array->lookUpIndex]->value.type == TokenType::TRUE || + result.arrayValue->ArrayContent[Array->lookUpIndex]->value.type == TokenType::FALSE) + { + result.boolValue = result.arrayValue->ArrayContent[Array->lookUpIndex]->value.value; + result.type = DataType::BOOL; + } + else + { + result.arrayValue = result.arrayValue->ArrayContent[Array->lookUpIndex]; + result.type = DataType::ARRAY; + } + + } + else { + result.type = DataType::ARRAY; + setVariable(Array->value.content, result); + } } // Expression @@ -689,22 +1251,22 @@ std::string ParserB::calculate(Node* root, Result& result) // variable else if (expressionNode->value.type == TokenType::VARIABLE) { - if (variableTypeMap.at(expressionNode->value.content) == DataType::UNINITIALIZED) - { - return "Runtime error: unknown identifier " + expressionNode->value.content; - } // Function Call - if (expressionNode->children.size() != 0) + if (expressionNode->children.size() != 0 && expressionNode->ArrayLookUp == false) { + if (variableTypeMap.at(expressionNode->value.content) == DataType::UNINITIALIZED) + { + return "Runtime error: unknown identifier " + expressionNode->value.content; + } // variable is not a function if (variableTypeMap.at(expressionNode->value.content) != DataType::FUNCTION) { return "Runtime error: not a function."; } - + // get the function stored in the first child Result functionResult; - getVariable(expressionNode->value.content, functionResult); + calculate(expressionNode->children[0].get(), functionResult); std::shared_ptr function = functionResult.function; // Parameters don't match @@ -715,9 +1277,9 @@ std::string ParserB::calculate(Node* root, Result& result) // execute the function // 1. create a new scope - Scope localScope(ScopeStack.top()); + Scope* localScope = new Scope(*ScopeStack.top()); // Overwrite the localscope with the captured scope - localScope.OverwriteBy(function->m_CaptureScope); + localScope->OverwriteBy(*(function->m_CaptureScope)); ScopeStack.push(localScope); // 2. set parameter values @@ -727,20 +1289,129 @@ std::string ParserB::calculate(Node* root, Result& result) calculate(expressionNode->children[i].get(), parameterResult); setVariable(function->m_ParameterNames[i-1], parameterResult); } + // 3. Execute flows for (int i=0; i < (int)function->m_FunctionFlows.size(); i++) { calculate(function->m_FunctionFlows[i].get(), result); - if (function->m_FunctionFlows[i]->value.type == TokenType::RETURN) + if (result.isreturn) { ScopeStack.pop(); + delete localScope; return ""; } } result.type = DataType::NUL; ScopeStack.pop(); + delete localScope; + } + // len() pop() push() + else if (expressionNode->children2.size() != 0 && expressionNode->ArrayLookUp == false) + { + // len() + if (expressionNode->value.content == "len") + { + result.type = DataType::DOUBLE; + if (expressionNode->children2[0]->value.type == TokenType::LEFT_BRACKET) + { + result.doubleValue = expressionNode->children2[0]->ArrayContent.size(); + } + else if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array.";} + Result result1; + getVariable (expressionNode->children2[0]->value.content, result1); + result.doubleValue = result1.arrayValue->ArrayContent.size(); + } + } + // pop() + else if (expressionNode->value.content == "pop") + { + result.type = DataType::DOUBLE; + if (expressionNode->children2[0]->value.type == TokenType::LEFT_BRACKET) + { + if (expressionNode->children2[0]->ArrayContent.size() == 0) { return "Runtime error: underflow."; } + result.doubleValue = expressionNode->children2[0]->ArrayContent[expressionNode->children2[0]->ArrayContent.size()-1]->value.value; + } + else if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array.";} + Result result1; + getVariable (expressionNode->children2[0]->value.content, result1); + if (result1.arrayValue->ArrayContent.size() == 0) { return "Runtime error: underflow."; } + result.doubleValue = result1.arrayValue->ArrayContent[result1.arrayValue->ArrayContent.size()-1]->value.value; + variableArrayMap[expressionNode->children2[0]->value.content]->ArrayContent.pop_back(); + } + } + + + } + // uninitialized + if (variableTypeMap.find(expressionNode->value.content) == variableTypeMap.end() && expressionNode->value.content == "true"){ + variableTypeMap[expressionNode->value.content] = DataType::UNINITIALIZED; + } + + // Array lookup + if (expressionNode->ArrayLookUp == true) + { + if (variableTypeMap.at(expressionNode->value.content) != DataType::ARRAY) { return "Runtime error: not an array."; } + + if (expressionNode->LookUpForm == false) { + return "Runtime error: index is not a number."; + } + + if (variableTypeMap.at(expressionNode->value.content) == DataType::UNINITIALIZED) + { + return "Runtime error: unknown identifier " + expressionNode->value.content; + } + + + // x[1+2] x[1>=2] + if (expressionNode->lookUpStr == "" && expressionNode->index == -1) + { + Result lookupResult; + calculate(expressionNode->children[0].get(), lookupResult); + if (lookupResult.type == DataType::DOUBLE) {expressionNode->index = lookupResult.doubleValue; } + else {return "Runtime error: index is not a number.";} + } + double a,b; + if (expressionNode->lookUpStr != "") + { + if (variableTypeMap.at(expressionNode->lookUpStr) == DataType::UNINITIALIZED) + { + return "Runtime error: index is not a number."; + } + getVariable (expressionNode->lookUpStr, result); + if (result.type !=DataType::DOUBLE) { return "Runtime error: index is not a number.";} + double a,b; + b = std::modf(result.doubleValue,&a); + if (b!= 0) { return "Runtime error: index is not an integer."; } + return ""; + } + b = std::modf(expressionNode->index,&a); + + if (b!= 0) { return "Runtime error: index is not an integer."; } + + int I = variableArrayMap.at(expressionNode->value.content)->ArrayContent.size(); + if (expressionNode->index < 0 || expressionNode->index >= I ) { return "Runtime error: index out of bounds."; } + + getVariable(expressionNode->value.content, result, expressionNode->index); + // std::cout << "running: " << expressionNode->index<<" "<< result.doubleValue << std::endl; + } + // Array + else if (variableTypeMap.at(expressionNode->value.content) == DataType::ARRAY && expressionNode->ArrayLookUp == false) + { + if (variableTypeMap.at(expressionNode->value.content) == DataType::UNINITIALIZED) + { + return "Runtime error: unknown identifier " + expressionNode->value.content; + } + getVariable(expressionNode->value.content, result); } else { + if (variableTypeMap.at(expressionNode->value.content) == DataType::UNINITIALIZED) + { + return "Runtime error: unknown identifier " + expressionNode->value.content; + } getVariable(expressionNode->value.content, result); } return ""; @@ -749,6 +1420,14 @@ std::string ParserB::calculate(Node* root, Result& result) // = else if (expressionNode->value.type == TokenType::ASSIGNMENT) { + + if (expressionNode->children2.size()!= 0) + { + std::string errorMessage = calculate(expressionNode->children2[1].get(), result); + if (errorMessage != "") { return errorMessage; } + return ""; + } + // the last child must be a number or an initialized variable std::string errorMessage = calculate(expressionNode->children[1].get(), result); if (errorMessage != "") { return errorMessage; } @@ -756,8 +1435,18 @@ std::string ParserB::calculate(Node* root, Result& result) // the first child must be a variable if (expressionNode->children[0].get()->value.type != TokenType::VARIABLE) { return "Runtime error: invalid assignee."; } + if (expressionNode->children[0]->LookUpForm == false) {return "Runtime error: index is not a number.";} + Result result2; + if (expressionNode->children[0]->ArrayLookUp == true) + { + // std::cout << "running" << expressionNode->value.content <children[0].get(), result2); + if (errorMessage != "") { return errorMessage; } + } + if (expressionNode->children[0]->index!= -1) {setVariable(expressionNode->children[0]->value.content, result, expressionNode->children[0]->index);} + else {setVariable(expressionNode->children[0]->value.content, result);} - setVariable(expressionNode->children[0]->value.content, result); + return ""; } @@ -767,6 +1456,7 @@ std::string ParserB::calculate(Node* root, Result& result) // variable for operation is uninitialaized Result result1; Result result2; + std::string errorMessage1 = calculate(expressionNode->children[0].get(), result1); if (errorMessage1 != "") { return errorMessage1; } std::string errorMessage2 = calculate(expressionNode->children[1].get(), result2); @@ -791,6 +1481,7 @@ std::string ParserB::calculate(Node* root, Result& result) } else if (expressionNode->value.type == TokenType::MINUS) { result.doubleValue = result1.doubleValue - result2.doubleValue; + // std::cout << "Here: " << result.doubleValue << std::endl; } else if (expressionNode->value.type == TokenType::MULTIPLY) { result.doubleValue = result1.doubleValue * result2.doubleValue; @@ -865,6 +1556,7 @@ std::string ParserB::calculate(Node* root, Result& result) result.type = DataType::BOOL; // == if (expressionNode->value.type == TokenType::EQUALITY) { + if (result1.type == DataType::NUL && result2.type == DataType::NUL) { result.boolValue = true; @@ -873,6 +1565,33 @@ std::string ParserB::calculate(Node* root, Result& result) { result.boolValue = false; } + else if (result1.type == DataType::ARRAY && result2.type == DataType::ARRAY) + { + if (result1.arrayValue->ArrayContent.size()==result2.arrayValue->ArrayContent.size()){ + for (size_t i = 0; i < result1.arrayValue->ArrayContent.size(); i++){ + // if (result1.arrayValue->ArrayContent.at(i)->value.type != result2.arrayValue->ArrayContent.at(i)->value.type + // || result1.arrayValue->ArrayContent.at(i)->value.value != result2.arrayValue->ArrayContent.at(i)->value.value) + // { + // result.boolValue = false; + // return ""; + // } + if (result1.arrayValue->ArrayContent.at(i)->value.type== TokenType::NUMBER) { + if (result1.arrayValue->ArrayContent.at(i)->value.value != result2.arrayValue->ArrayContent.at(i)->value.value){ + result.boolValue = false; + return ""; + } + } + if (result1.arrayValue->ArrayContent.at(i)->value.type== TokenType::TRUE || result1.arrayValue->ArrayContent.at(i)->value.type== TokenType::FALSE){ + if (result1.arrayValue->ArrayContent.at(i)->value.value != result2.arrayValue->ArrayContent.at(i)->value.value){ + result.boolValue = false; + return ""; + } + } + } + result.boolValue = true; + } + else {result.boolValue = false;} + } else { if (result1.type == DataType::DOUBLE) @@ -893,6 +1612,21 @@ std::string ParserB::calculate(Node* root, Result& result) { result.boolValue = true; } + else if (result1.type == DataType::ARRAY && result2.type == DataType::ARRAY) + { + if (result1.arrayValue->ArrayContent.size()==result2.arrayValue->ArrayContent.size()){ + for (size_t i = 0; i < result1.arrayValue->ArrayContent.size(); i++){ + if (result1.arrayValue->ArrayContent.at(i)->value.type == result2.arrayValue->ArrayContent.at(i)->value.type + && result1.arrayValue->ArrayContent.at(i)->value.value == result2.arrayValue->ArrayContent.at(i)->value.value) + { + result.boolValue = false; + return ""; + } + } + result.boolValue = true; + } + else {result.boolValue = true;} + } else { if (result1.type == DataType::DOUBLE) @@ -912,10 +1646,9 @@ std::string ParserB::calculate(Node* root, Result& result) } -void ParserB::print(Node* root, int indent) +void ParserB::print(Node* root, int indent, bool semicolon) { for (int i=0; ivalue.type == TokenType::DEF) { @@ -949,7 +1682,7 @@ void ParserB::print(Node* root, int indent) WhileNode* whileRoot = dynamic_cast(root); std::cout << "while "; - print(whileRoot->condition.get(), 0); + print(whileRoot->condition.get(), 0, false); std::cout << " {" << std::endl; for (int i=0;i < (int)whileRoot->flows.size(); i++) { @@ -966,7 +1699,7 @@ void ParserB::print(Node* root, int indent) // if std::cout << "if "; - print(ifRoot->conditions[0].get(), 0); + print(ifRoot->conditions[0].get(), 0, false); std::cout << " {" << std::endl; for (int i=0 ; i < (int)ifRoot->flowGroups[0].size(); i++) { @@ -982,7 +1715,7 @@ void ParserB::print(Node* root, int indent) std::cout << std::endl; for (int i=0; iconditions[conditionIndex].get(), 0); + print(ifRoot->conditions[conditionIndex].get(), 0, false); std::cout << " {" << std::endl; for (int i=0; i < (int)ifRoot->flowGroups[conditionIndex].size(); i++) { @@ -1014,22 +1747,108 @@ void ParserB::print(Node* root, int indent) PrintNode* printRoot = dynamic_cast(root); std::cout << "print "; - print(printRoot->content.get()); + if (printRoot->content2 != nullptr) { + print(printRoot->content2.get(), 0, false); + } + else { + print(printRoot->content.get(), 0, false); + } + std::cout << ";"; } // Return else if (root->value.type == TokenType::RETURN) { ReturnNode* returnRoot = dynamic_cast(root); - std::cout << "return "; - print(returnRoot->content.get()); + std::cout << "return"; + if (returnRoot->content != nullptr) { + std::cout << " "; + print(returnRoot->content.get(), 0, false); + std::cout << ";"; + } + else { + std::cout << ";"; + } } + // Array + else if (root->value.type == TokenType::ARRAY) + { + ArrayNode * ArrayRoot = dynamic_cast(root); + if ( ArrayRoot->value.content != "") { + std::cout << "(" << ArrayRoot->value.content << " = "; + } + std::cout << "["; + for(size_t i = 0; i < ArrayRoot->ArrayContent.size(); i++) { + print(ArrayRoot->ArrayContent[i].get(), 0, false); + if (i+1 < ArrayRoot->ArrayContent.size()) { + std::cout << ", "; + } + } + std::cout << "]"; + if ( ArrayRoot->value.content != "") { + std::cout << ");"; + } + } + // only Array without assignment + else if (root->value.type == TokenType::LEFT_BRACKET && root->EqualityIndex == -1 ){ + // std::cout << "r" << std::endl; + ArrayNode * ArrayRoot = dynamic_cast(root); + std::cout << "["; + for(size_t i = 0; i < ArrayRoot->ArrayContent.size(); i++) { + print(ArrayRoot->ArrayContent[i].get(), 0, false); + if (i+1 < ArrayRoot->ArrayContent.size()) { + std::cout << ", "; + } + } + // check if there is lookup + if (ArrayRoot->lookUp == true) + { + if (ArrayRoot->LookUpNode.size()!=0) { + // std::cout << "RUN" <LookUpNode.at(0).get(), 0 , false); + } + else if (ArrayRoot->lookUpIndex != -1) { + std::cout << "][" << ArrayRoot->lookUpIndex; + } + else { + std::cout << "][" << ArrayRoot->lookUpStr; + } + } + if (semicolon == false) { std::cout << "]"; } + else { std::cout << "];"; } + } + // array equality + else if (root->EqualityIndex != -1) + { + ArrayNode * ArrayRoot = dynamic_cast(root); + std::cout << "("; + if (ArrayRoot->ArrayContent[0]->ArrayContent.size()==0) { + std::cout << ArrayRoot->ArrayContent[0]->value.content; + } + else + { + print(ArrayRoot->ArrayContent[0].get()); + } + std::cout <<" " <value.content << " "; + if (ArrayRoot->ArrayContent[1]->ArrayContent.size()==0) { + std::cout << ArrayRoot->ArrayContent[1]->value.content; + } + else + { + print(ArrayRoot->ArrayContent[1].get()); + } + std::cout << ")"; + // std::cout << "yes" << std::endl; + } // ExpressionNode else { ExpressionNode* expressionNode = dynamic_cast(root); + if (expressionNode->value.type == TokenType::NUMBER){ + } if (expressionNode->value.type == TokenType::NUL) { std::cout << "null"; @@ -1046,20 +1865,75 @@ void ParserB::print(Node* root, int indent) else if (expressionNode->value.type == TokenType::VARIABLE) { // Function Call - if (expressionNode->children.size() != 0) + if (expressionNode->children.size() != 0 && expressionNode->ArrayLookUp == false) { - print(expressionNode->children[0].get()); + print(expressionNode->children[0].get(), 0, false); std::cout << "("; for (int i = 1; i < (int)expressionNode->children.size(); i++) { - print(expressionNode->children[i].get()); + print(expressionNode->children[i].get(), 0, false); if (i != (int)expressionNode->children.size() - 1) { std::cout << ", "; } } std::cout << ")"; + if (semicolon) { std::cout << ";"; } + } + // len() pop() push() + else if (expressionNode->children2.size() != 0 && expressionNode->ArrayLookUp == false) + { + // len() + if (expressionNode->value.content == "len") + { + std::cout << "len("; + if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + std::cout << expressionNode->children2[0]->value.content; + } + else + { + print(expressionNode->children2[0].get(), 0, false); + } + + if (semicolon == true) {std::cout << ");";} + else {std::cout << ")";} + } + // pop() + else if (expressionNode->value.content == "pop") + { + std::cout << "pop("; + if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + std::cout << expressionNode->children2[0]->value.content; + } + else + { + print(expressionNode->children2[0].get(), 0, false); + } + + if (semicolon == true) {std::cout << ");";} + else {std::cout << ")";} + } + + } + // Array + else if (expressionNode->ArrayLookUp == true) { + if (expressionNode->children.size()!= 0) { + std::cout << expressionNode->value.content << "["; + print(expressionNode->children[0].get(), 0, false); + std::cout << "]"; + } + else if (expressionNode->index!=-1) + { + std::cout << expressionNode->value.content << "[" << expressionNode->index << "]"; + } + else if (expressionNode->lookUpStr != "") + { + std::cout << expressionNode->value.content << "[" << expressionNode->lookUpStr << "]"; + } } + // Normal Variable else { @@ -1078,19 +1952,31 @@ void ParserB::print(Node* root, int indent) std::cout << "("; for (int i = 0; i < (int)expressionNode->children.size(); i++) { - print(expressionNode->children[i].get()); + print(expressionNode->children[i].get(), 0, false); if (i != (int)expressionNode->children.size() - 1) { std::cout << " " << expressionNode->value.content << " "; } } + for (int i = 0; i < (int)expressionNode->children2.size(); i++) + { + print(expressionNode->children2[i].get(), 0, false); + if (i != (int)expressionNode->children2.size() - 1) + { + std::cout << " " << expressionNode->value.content << " "; + } + } std::cout << ")"; + if (semicolon) { std::cout << ";"; } } } } void ParserB::printValue(Result& value) { + + // if (value.print == false) {return;} + if (value.type == DataType::NUL) { std::cout << "null"; @@ -1107,10 +1993,50 @@ void ParserB::printValue(Result& value) std::cout << value.doubleValue; } + else if (value.type == DataType::ARRAY) + { + std::cout << "["; + for (size_t i = 0; i < value.arrayValue->ArrayContent.size(); i++) + { + // std::cout << value.arrayValue->ArrayContent.size() <ArrayContent[i]->value.type == TokenType::NUMBER) + { + + std::cout << value.arrayValue->ArrayContent[i]->value.value; + } + else if (value.arrayValue->ArrayContent[i]->value.type == TokenType::ARRAY) + { + + + Result curr; + curr.type = DataType::ARRAY; + + curr.arrayValue = value.arrayValue->ArrayContent.at(i); + // curr.arrayValue->value.type = ; + + printValue(curr); + // std::cout << "[5]"; + } + else if (value.arrayValue->ArrayContent[i]->value.type == TokenType::NUL) + { + std::cout <<"null"; + } + else{ + // std::cout << 3 << std::endl; + std::cout << value.arrayValue->ArrayContent[i]->value.content; + } + if (i+1ArrayContent.size()) { + std::cout << ", "; + } + } + std::cout << "]"; + } + else { std::cout << (value.type == DataType::FUNCTION) << std::endl; std::cout << (value.type == DataType::NUL) << std::endl; + std::cout << (value.type == DataType::UNINITIALIZED) << std::endl; std::cout << "There is something wrong PrintValue" << std::endl; } } @@ -1121,8 +2047,8 @@ int ParserB::findRightParenthesisNoError(std::vector expression, int left int balance = 1; int p = leftBound; while (p <= rightBound) { - if (expression[p].type == TokenType::LEFT_PARENTHESIS) { balance += 1; } - else if (expression[p].type == TokenType::RIGHT_PARENTHESIS) { balance -= 1; } + if (expression[p].type == TokenType::LEFT_PARENTHESIS || expression[p].type == TokenType::LEFT_BRACKET) { balance += 1; } + else if (expression[p].type == TokenType::RIGHT_PARENTHESIS || expression[p].type == TokenType::RIGHT_BRACKET) { balance -= 1; } if (balance == 0) { break; } p += 1; @@ -1145,14 +2071,15 @@ int ParserB::findRightBracketNoError(std::vector expression, int leftBoun return p; } -// exclude left brace +// exclude left brace +// it also can find bracket no error int ParserB::findRightBraceNoError(std::vector expression, int leftBound, int rightBound) { int balance = 1; int p = leftBound; while (p <= rightBound) { - if (expression[p].type == TokenType::LEFT_BRACE) { balance += 1; } - else if (expression[p].type == TokenType::RIGHT_BRACE) { balance -= 1; } + if (expression[p].type == TokenType::LEFT_BRACE || expression[p].type == TokenType::LEFT_BRACKET) { balance += 1; } + else if (expression[p].type == TokenType::RIGHT_BRACE || expression[p].type == TokenType::RIGHT_BRACKET) { balance -= 1; } if (balance == 0) { break; } p += 1; @@ -1164,25 +2091,66 @@ int ParserB::findRightBraceNoError(std::vector expression, int leftBound, // void ParserB::setupExpression(std::vector& expression, int leftBound, int rightBound, ) void ParserB::setupExpression(std::vector& expression) { - auto& variableTypeMap = ScopeStack.top().variableTypeMap; + auto& variableTypeMap = ScopeStack.top()->variableTypeMap; for (int i = 0; i < (int)expression.size()-1; i++) { Token token = expression[i]; // handle new variable - if (token.type == TokenType::VARIABLE) + if (variableTypeMap.find(token.content) == variableTypeMap.end() && token.type == TokenType::VARIABLE) { variableTypeMap[token.content] = DataType::UNINITIALIZED; } } } -void ParserB::getVariable(std::string& variableName, Result& result) { - auto& variableTypeMap = ScopeStack.top().variableTypeMap; - auto& variableDoubleMap = ScopeStack.top().variableDoubleMap; - auto& variableBoolMap = ScopeStack.top().variableBoolMap; - auto& variableFunctionMap = ScopeStack.top().variableFunctionMap; +void ParserB::getVariable(std::string& variableName, Result& result, int index) { + auto& variableTypeMap = ScopeStack.top()->variableTypeMap; + auto& variableDoubleMap = ScopeStack.top()->variableDoubleMap; + auto& variableBoolMap = ScopeStack.top()->variableBoolMap; + auto& variableFunctionMap = ScopeStack.top()->variableFunctionMap; + auto& variableArrayMap = ScopeStack.top()->variableArrayMap; result.type = variableTypeMap[variableName]; + + if (index != -1) + { + if (variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::NUMBER) + { + result.type = DataType::DOUBLE; + result.doubleValue = variableArrayMap[variableName]->ArrayContent.at(index)->value.value; + } + else if (variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::TRUE || + variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::FALSE) + { + result.type = DataType::BOOL; + result.boolValue = variableArrayMap[variableName]->ArrayContent.at(index)->value.value; + } + else if (variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::ARRAY || + variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::LEFT_BRACKET) + { + result.type = DataType::ARRAY; + + result.arrayValue = std::make_unique(variableArrayMap[variableName]->ArrayContent.at(index)->value); + result.arrayValue->lookUp = variableArrayMap[variableName]->ArrayContent.at(index)->lookUp; + result.arrayValue->lookUpStr = variableArrayMap[variableName]->ArrayContent.at(index)->lookUpStr; + result.arrayValue->lookUpIndex = variableArrayMap[variableName]->ArrayContent.at(index)->lookUpIndex; + for (auto element : variableArrayMap[variableName]->ArrayContent.at(index)->ArrayContent){ + result.arrayValue->ArrayContent.push_back(element); + } + } + else if (variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::NUL) + { + result.type = DataType::NUL; + } + return; + } + + if (variableTypeMap.at(variableName) == DataType::ARRAY) + { + result.arrayValue = variableArrayMap[variableName]; + return; + } + if (result.type == DataType::NUL) { @@ -1199,20 +2167,71 @@ void ParserB::getVariable(std::string& variableName, Result& result) { { result.function = variableFunctionMap[variableName]; } + else if (result.type == DataType::ARRAY) + { + result.arrayValue = variableArrayMap[variableName]; + } else { - std::cout << (result.type == DataType::NUL) << std::endl; + // std::cout << (result.type == DataType::NUL) << std::endl; + // std::cout << (result.type == DataType::UNINITIALIZED) << std::endl; std::cout << "There is a problem getVariable" << std::endl; } } -void ParserB::setVariable(std::string& variableName, Result& result) { - auto& variableTypeMap = ScopeStack.top().variableTypeMap; - auto& variableDoubleMap = ScopeStack.top().variableDoubleMap; - auto& variableBoolMap = ScopeStack.top().variableBoolMap; - auto& variableFunctionMap = ScopeStack.top().variableFunctionMap; +void ParserB::setVariable(std::string& variableName, Result& result, int index) { + auto& variableTypeMap = ScopeStack.top()->variableTypeMap; + auto& variableDoubleMap = ScopeStack.top()->variableDoubleMap; + auto& variableBoolMap = ScopeStack.top()->variableBoolMap; + auto& variableFunctionMap = ScopeStack.top()->variableFunctionMap; + auto& variableArrayMap = ScopeStack.top()->variableArrayMap; + + if (index != -1) { + // if (variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::NUMBER) + if (result.type == DataType::DOUBLE) + { + variableArrayMap[variableName]->ArrayContent.at(index)->value.type = TokenType::NUMBER; + // result.type = DataType::DOUBLE; + variableArrayMap[variableName]->ArrayContent.at(index)->value.value = result.doubleValue; + } + // else if (variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::TRUE || + // variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::FALSE) + else if (result.type == DataType::BOOL) + { + // result.type = DataType::BOOL; + variableArrayMap[variableName]->ArrayContent.at(index)->value.type = TokenType::TRUE; + variableArrayMap[variableName]->ArrayContent.at(index)->value.value = result.boolValue; + } + // else if (variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::ARRAY || + // variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::LEFT_BRACKET) + else if (result.type == DataType::ARRAY) + { + // result.type = DataType::ARRAY; + + // result.arrayValue = std::make_unique(variableArrayMap[variableName]->ArrayContent.at(index)->value); + // result.arrayValue->lookUp = variableArrayMap[variableName]->ArrayContent.at(index)->lookUp; + // result.arrayValue->lookUpStr = variableArrayMap[variableName]->ArrayContent.at(index)->lookUpStr; + // result.arrayValue->lookUpIndex = variableArrayMap[variableName]->ArrayContent.at(index)->lookUpIndex; + // for (auto element : variableArrayMap[variableName]->ArrayContent.at(index)->ArrayContent){ + // result.arrayValue->ArrayContent.push_back(element); + // } + + variableArrayMap[variableName]->ArrayContent.at(index) = result.arrayValue; + + } + // else if (variableArrayMap[variableName]->ArrayContent.at(index)->value.type == TokenType::NUL) + else if (result.type == DataType::NUL) + { + // result.type = DataType::NUL; + variableArrayMap[variableName]->ArrayContent.at(index)->value.type = TokenType::NUL; + + variableArrayMap[variableName]->ArrayContent.at(index)->value.content = "null"; + } + return; + } variableTypeMap[variableName] = result.type; + if (result.type == DataType::NUL) { @@ -1229,6 +2248,14 @@ void ParserB::setVariable(std::string& variableName, Result& result) { { variableFunctionMap[variableName] = result.function; } + else if (result.type == DataType::ARRAY) + { + // std::cout << variableName<<" yes: " << result.arrayValue->value.content << std::endl; + variableArrayMap[variableName] = result.arrayValue; + // if (variableName == "arref") { + // variableArrayMap[variableName]->ArrayContent.at(1)->value.value = -1; + // } + } else { std::cout << "There is a problem setVariable" << std::endl; diff --git a/src/lib/ParserB.h b/src/lib/ParserB.h index 59935f1..c0336ad 100644 --- a/src/lib/ParserB.h +++ b/src/lib/ParserB.h @@ -16,19 +16,15 @@ #include "ASTNode.h" - class Result { public: - ~Result() { - if (type == DataType::FUNCTION && function != nullptr) { - // delete function; - // function = nullptr; - } - } + // Result(std::shared_ptr Array){ + // } DataType type; - + bool isreturn = false; std::shared_ptr function; + std::shared_ptr arrayValue; union { double doubleValue; bool boolValue; @@ -40,18 +36,335 @@ class ParserB public: static std::pair, std::string> HandleTokenVector(std::vector tokenVector, int leftBound, int rightBound, std::vector>& nodes); static std::pair, std::string> MakeExpressionTree(std::vector expression, int leftBound, int rightBound, std::unique_ptr& node); + static std::pair, std::string> HandleArray(std::vector tokenVector, int leftBound, int rightBound,std::unique_ptr& node , int index = -1); static std::string calculate(Node* root, Result& result); - static void print(Node* root, int indent = 0); + static void print(Node* root, int indent = 0, bool semicolon = true); static void printValue(Result& result); static void setupExpression(std::vector& expression); - static void getVariable(std::string& variableName, Result& result); - static void setVariable(std::string& variableName, Result& result); + static void getVariable(std::string& variableName, Result& result, int index = -1); + static void setVariable(std::string& variableName, Result& result, int index = -1); static int findRightParenthesisNoError(std::vector expression, int leftBound, int rightBound); static int findRightBracketNoError(std::vector expression, int leftBound, int rightBound); static int findRightBraceNoError(std::vector expression, int leftBound, int rightBound); - static std::stack ScopeStack; + static std::stack ScopeStack; static std::map hierarchyMap; + static std::vector> functionStorage; + + static void clean() + { + for (int i=0; i < (int)functionStorage.size(); i++) + { + delete functionStorage[i]->m_CaptureScope; + } + } + + + +static void print_no_semicolon(Node* root, int indent=0) +{ + for (int i=0; ivalue.type == TokenType::DEF) + { + FunctionDefineNode* functionDefineRoot = dynamic_cast(root); + + std::cout << "def "; + std::cout << functionDefineRoot->functionName; + std::cout << "("; + for (int i = 0; i < (int)functionDefineRoot->parameterNames.size(); i++) + { + std::cout << functionDefineRoot->parameterNames[i]; + if (i != (int)functionDefineRoot->parameterNames.size()-1) + { + std::cout << ", "; + } + } + std::cout << ") "; + std::cout << "{" << std::endl; + for (int i=0; i < (int)functionDefineRoot->flows.size(); i++) + { + print(functionDefineRoot->flows[i].get(), indent + 1); + std::cout << std::endl; + } + + for (int i=0; i < indent; i++) { std::cout << " "; } + std::cout << "}"; + } + // While + else if (root->value.type == TokenType::WHILE) + { + WhileNode* whileRoot = dynamic_cast(root); + + std::cout << "while "; + print(whileRoot->condition.get(), 0, false); + std::cout << " {" << std::endl; + for (int i=0;i < (int)whileRoot->flows.size(); i++) + { + print(whileRoot->flows[i].get(), indent + 1); + std::cout << std::endl; + } + for (int i=0; ivalue.type == TokenType::IF) + { + IfNode* ifRoot = dynamic_cast(root); + + // if + std::cout << "if "; + print(ifRoot->conditions[0].get(), 0, false); + std::cout << " {" << std::endl; + for (int i=0 ; i < (int)ifRoot->flowGroups[0].size(); i++) + { + print(ifRoot->flowGroups[0][i].get(), indent + 1); + std::cout << std::endl; + } + for (int i=0; iconditions.size(); conditionIndex++) + { + std::cout << std::endl; + for (int i=0; iconditions[conditionIndex].get(), 0, false); + std::cout << " {" << std::endl; + for (int i=0; i < (int)ifRoot->flowGroups[conditionIndex].size(); i++) + { + print(ifRoot->flowGroups[conditionIndex][i].get(), indent + 1); + std::cout << std::endl; + } + for (int a=0; aconditions.size() != ifRoot->flowGroups.size()) + { + std::cout << std::endl; + for (int i=0; iflowGroups[ifRoot->flowGroups.size()-1].size(); i++) + { + print(ifRoot->flowGroups[ifRoot->flowGroups.size()-1][i].get(), indent + 1); + std::cout << std::endl; + } + for (int i=0; ivalue.type == TokenType::PRINT) + { + PrintNode* printRoot = dynamic_cast(root); + + std::cout << "print "; + print(printRoot->content.get(), 0, false); + } + // Return + else if (root->value.type == TokenType::RETURN) + { + ReturnNode* returnRoot = dynamic_cast(root); + + std::cout << "return "; + print(returnRoot->content.get()); + } + // Array + else if (root->value.type == TokenType::ARRAY) + { + ArrayNode * ArrayRoot = dynamic_cast(root); + if ( ArrayRoot->value.content != "") { + std::cout << "(" << ArrayRoot->value.content << " = "; + } + std::cout << "["; + for(size_t i = 0; i < ArrayRoot->ArrayContent.size(); i++) { + print(ArrayRoot->ArrayContent[i].get(), 0, false); + if (i+1 < ArrayRoot->ArrayContent.size()) { + std::cout << ", "; + } + } + std::cout << "]"; + if ( ArrayRoot->value.content != "") { + std::cout << ")"; + } + } + // only Array without assignment + else if (root->value.type == TokenType::LEFT_BRACKET && root->EqualityIndex == -1){ + ArrayNode * ArrayRoot = dynamic_cast(root); + std::cout << "["; + for(size_t i = 0; i < ArrayRoot->ArrayContent.size(); i++) { + print(ArrayRoot->ArrayContent[i].get(), 0, false); + if (i+1 < ArrayRoot->ArrayContent.size()) { + std::cout << ", "; + } + } + // check if there is lookup + if (ArrayRoot->lookUp == true) + { + if (ArrayRoot->LookUpNode.size()!=0) { + // std::cout << "RUN" <LookUpNode.at(0).get(), 0 , false); + } + else if (ArrayRoot->lookUpIndex != -1) { + std::cout << "][" << ArrayRoot->lookUpIndex; + } + else { + std::cout << "][" << ArrayRoot->lookUpStr; + } + } + std::cout << "]"; + } + + else if (root->EqualityIndex != -1) + { + ArrayNode * ArrayRoot = dynamic_cast(root); + std::cout << "("; + if (ArrayRoot->ArrayContent[0]->ArrayContent.size()==0) { + std::cout << ArrayRoot->ArrayContent[0]->value.content; + } + else + { + print(ArrayRoot->ArrayContent[0].get()); + } + std::cout <<" " <value.content << " "; + if (ArrayRoot->ArrayContent[1]->ArrayContent.size()==0) { + + std::cout << ArrayRoot->ArrayContent[1]->value.content; + } + else + { + print(ArrayRoot->ArrayContent[1].get()); + } + std::cout << ")"; + // std::cout << "yes" << std::endl; + } + // ExpressionNode + else + { + ExpressionNode* expressionNode = dynamic_cast(root); + if (expressionNode->value.type == TokenType::NUL) + { + std::cout << "null"; + } + else if (expressionNode->value.type == TokenType::NUMBER) + { + int v = floor(expressionNode->value.value); + // 1000.000 -> 1000 + if ((double)v == expressionNode->value.value) + { std::cout << v; } + else + { std::cout << expressionNode->value.content; } + } + else if (expressionNode->value.type == TokenType::VARIABLE) + { + // Function Call + if (expressionNode->children.size() != 0 && expressionNode->ArrayLookUp == false) + { + print(expressionNode->children[0].get(), 0, false); + std::cout << "("; + for (int i = 1; i < (int)expressionNode->children.size(); i++) + { + print(expressionNode->children[i].get(), 0, false); + if (i != (int)expressionNode->children.size() - 1) + { + std::cout << ", "; + } + } + std::cout << ")"; + } + // len() pop() push() + else if (expressionNode->children2.size() != 0 && expressionNode->ArrayLookUp == false) + { + // len() + if (expressionNode->value.content == "len") + { + std::cout << "len("; + if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + std::cout << expressionNode->children2[0]->value.content; + } + else + { + print_no_semicolon(expressionNode->children2[0].get(), 0); + } + + std::cout << ")"; + } + // pop() + else if (expressionNode->value.content == "pop") + { + std::cout << "pop("; + if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + std::cout << expressionNode->children2[0]->value.content; + } + else + { + print(expressionNode->children2[0].get(), 0, false); + } + + std::cout << ")"; + } + + } + else if (expressionNode->ArrayLookUp == true) { + if (expressionNode->children.size()!= 0) { + std::cout << expressionNode->value.content << "["; + print(expressionNode->children[0].get(), 0, false); + std::cout << "]"; + } + else if (expressionNode->index!=-1) + { + std::cout << expressionNode->value.content << "[" << expressionNode->index << "]"; + } + else if (expressionNode->lookUpStr != "") + { + std::cout << expressionNode->value.content << "[" << expressionNode->lookUpStr << "]"; + } + else { + std::cout << "ERROR" << std::endl; + } + } + // Normal Variable + else + { + std::cout << expressionNode->value.content; + } + } + else if (expressionNode->value.type == TokenType::TRUE) + { + std::cout << expressionNode->value.content; + } + else if (expressionNode->value.type == TokenType::FALSE) + { + std::cout << expressionNode->value.content; + } + else { + std::cout << "("; + for (int i = 0; i < (int)expressionNode->children.size(); i++) + { + print(expressionNode->children[i].get(), 0, false); + if (i != (int)expressionNode->children.size() - 1) + { + std::cout << " " << expressionNode->value.content << " "; + } + } + for (int i = 0; i < (int)expressionNode->children2.size(); i++) + { + print(expressionNode->children2[i].get(), 0, false); + if (i != (int)expressionNode->children2.size() - 1) + { + std::cout << " " << expressionNode->value.content << " "; + } + } + std::cout << ")"; + } + } +} private: }; diff --git a/src/lib/Scope.h b/src/lib/Scope.h index ddff23a..b788201 100644 --- a/src/lib/Scope.h +++ b/src/lib/Scope.h @@ -3,6 +3,7 @@ #include #include #include "DataType.h" +#include "ASTNode.h" class Function; @@ -11,26 +12,50 @@ class Scope public: Scope() : variableTypeMap(), variableDoubleMap(), variableBoolMap() - , variableFunctionMap() + , variableFunctionMap(), variableArrayMap() {} // Copy constructor Scope(const Scope& other) : variableTypeMap(other.variableTypeMap), variableDoubleMap(other.variableDoubleMap), - variableBoolMap(other.variableBoolMap), variableFunctionMap(other.variableFunctionMap) + variableBoolMap(other.variableBoolMap), variableFunctionMap(other.variableFunctionMap), variableArrayMap(other.variableArrayMap) {} + ~Scope() + { + for (auto& pair : variableFunctionMap) { + pair.second.reset(); + } + // std::cout << "Scope is deleted" << std::endl; + } + + // Copy assignment operator + Scope& operator=(const Scope& other) { + if (this != &other) { + // Implement the assignment logic here + // Be sure to handle any dynamic resources properly + variableTypeMap = other.variableTypeMap; + variableDoubleMap = other.variableDoubleMap; + variableBoolMap = other.variableBoolMap; + variableFunctionMap = other.variableFunctionMap; + } + return *this; + } + void OverwriteBy(Scope& other) { for (std::pair kv : other.variableTypeMap) { std::string variableName = kv.first; - variableTypeMap[variableName] = other.variableTypeMap[variableName]; if (other.variableTypeMap[variableName] == DataType::NUL) { + } + else if (other.variableTypeMap[variableName] == DataType::UNINITIALIZED) + { + } else if (other.variableTypeMap[variableName] == DataType::DOUBLE) { @@ -52,8 +77,45 @@ class Scope } } + void print() + { + std::cout << "======================" << std::endl; + for (std::pair kv : variableTypeMap) + { + std::string variableName = kv.first; + + if (variableTypeMap[variableName] == DataType::NUL) + { + std::cout << variableName << " null" << std::endl; + } + else if (variableTypeMap[variableName] == DataType::UNINITIALIZED) + { + std::cout << variableName << " uninitialized" << std::endl; + } + else if (variableTypeMap[variableName] == DataType::DOUBLE) + { + std::cout << variableName << " double " << variableDoubleMap[variableName] << std::endl; + } + else if (variableTypeMap[variableName] == DataType::BOOL) + { + std::cout << variableName << " bool " << variableBoolMap[variableName] << std::endl; + } + else if (variableTypeMap[variableName] == DataType::FUNCTION) + { + std::cout << variableName << " function " << std::endl; + } + else + { + // std::cout << variableName << std::endl; + // std::cout << "There is a problem overwrite scope" << std::endl; + } + } + std::cout << "--------------------" << std::endl; + } + std::map variableTypeMap; std::map variableDoubleMap; std::map variableBoolMap; std::map> variableFunctionMap; + std::map> variableArrayMap; }; \ No newline at end of file diff --git a/src/lib/main b/src/lib/main new file mode 100644 index 0000000000000000000000000000000000000000..9c01bdc9360b28e1ff9bb4edcff2f6879ecc3455 GIT binary patch literal 161520 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Ξ%zjrydmqrQ_~}SPKNw5zQi~vVo0h9i~Fn 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 RmHyaf&edF3{#`$<{|DY-F**PM literal 0 HcmV?d00001 diff --git a/src/main b/src/main deleted file mode 100644 index 33e07b5dc5e1d5fe01e88a9a3a7f664a7b33ccba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 420440 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


N?}# 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 z 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⩔=evZ? z?cifmFwb`Y_uq$VxLevUJ6Y)Hd`<@5v9ZiU26WB>elqs$I^d50zZ!B=`!nxn(fp@K zIM3%rIA6LSt^n@utM}g{?R|em8n~a&b~NyPo10A!^}JsW+^@^`H1NldmU+(M`r8x0AACmeT|wu44+*BTo_xb0!z|X+F+NJ3K-+}jhUdE;8rRgD|zn6Ee3&3x=Li(8kokxND@9TZ; zmqN#{Z#nm2!TmZ#Cjj^J)~*8n`sMOn)r55xaGw7ai)Wgi?~MMR zL^z+{N7{sr^7*@g`}d5V1m5#YX|MZm??;5r4#zbc%JV`08Q@RO5?td}!@rjHtrrU& z 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 TokenVector; - std::pair errorPair = Token::GenTokenVector(input, TokenVector); - - int errorLine = errorPair.first; - int errorIndex = errorPair.second; - - if (errorLine != -1) - { - std::cout << "Syntax error on line " << errorLine << " column " << errorIndex << "." << std::endl; - exit(1); - } - - Parser::setupExpression(TokenVector); - //std::cout << Parser::expressionLines.size() << std::endl; - for (std::vector expressionLine : Parser::expressionLines) - { - // Token::printLexer(expressionLine); - // std::cout << "==================" << std::endl; - - Node root = Parser::MakeTree(expressionLine, 0, expressionLine.size() - 2); - Parser::print(root); - std::cout << std::endl; - std::cout << Parser::calculate(root) << std::endl; - } - - return 0; -} diff --git a/src/scrypt.cpp b/src/scrypt.cpp index b2cd7b9..20cbc1a 100644 --- a/src/scrypt.cpp +++ b/src/scrypt.cpp @@ -32,25 +32,42 @@ int main() { // print steps)"; +// std::string input = R"( +// def foo(x, y) { +// })" +// ; - std::string input = R"( -z = 42 + std::string input = R"( +(z = 42); def foo(x, y) { - def square(value) { - return value * value - } + def square(value) { + return (value * value); + } + print square(((x + y) + z)); +} +(z = 108); +(f = foo); +(result = f(1, 2)); +if (result != null) { + print result; +} - print square(x + y + z) +def p() { + print 114514; + return; } +print p(); -z = 108 -f = foo -result = f(1, 2) -if result != null { - print result +def add(a) { + if (a <= 1) { + return a; + } + return a * add(a-1); } + +print add(5); )"; @@ -70,7 +87,8 @@ if result != null { // Parser // Add the global Scope - ParserB::ScopeStack.push(Scope()); + Scope* globalScope = new Scope(); + ParserB::ScopeStack.push(globalScope); ParserB::setupExpression(TokenVector); std::vector> flows; std::pair, std::string> errorResult = ParserB::HandleTokenVector(TokenVector, 0, TokenVector.size()-2, flows); @@ -80,6 +98,12 @@ if result != null { exit(2); } + // for (int i=0; i < (int)flows.size(); i++) + // { + // ParserB::print(flows[i].get()); + // std::cout << std::endl; + // } + // Calculate // std::cout << "start calculating" << std::endl; for (int i=0; i < (int)flows.size(); i++) @@ -93,5 +117,9 @@ if result != null { exit(3); } } + + // std::cout << ParserB::functionStorage.size() << std::endl; + ParserB::clean(); + delete globalScope; return 0; } diff --git a/src/test.cpp b/src/test.cpp index 683b13a..b5c4a18 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -8,62 +8,85 @@ #include #include #include -class Node -{ -public: - Node() : value(Token(TokenType::NONE, "", -1, -1, -1)) {} - Node(Token token) : value(token) {} - virtual ~Node() = default; - Token value; -}; -class Function -{ -public: - Function() = default; -}; +class Function; class Scope { public: Scope() : variableFunctionMap() - {} + { + std::cout << "scope is created" << std::endl; + } + + ~Scope() + { + for (auto& pair : variableFunctionMap) { + pair.second.reset(); + } + std::cout << "Scope is deleted" << std::endl; + } + + Scope(const Scope& other) + : variableFunctionMap(other.variableFunctionMap) + { + std::cout << "scope copied" << std::endl; + } + + Scope& operator=(const Scope& other) { + if (this != &other) { + variableFunctionMap = other.variableFunctionMap; + } + return *this; + } std::map> variableFunctionMap; }; -class Result + +class Function { public: - ~Result() { + Function() + { + std::cout << "Function is created" << std::endl; + }; + + ~Function() + { + // for (auto& pair : m_CaptureScope.variableFunctionMap) { + // pair.second.reset(); + // } + // delete m_CaptureScope; + std::cout << "Function is deleted" << std::endl; } - Function* function; + Scope* m_CaptureScope; }; -int main() { +static std::stack ScopeStack; + +int main() { + // Add a Function inside globalScope + Scope* globalScope = new Scope(); + ScopeStack.push(globalScope); - std::stack ScopeStack = std::stack(); - ScopeStack.push(Scope()); - auto& variableFunctionMap = ScopeStack.top().variableFunctionMap; + std::shared_ptr function = std::make_shared(); + globalScope->variableFunctionMap["add"] = function; + // map 里面有一个pointer指向function - // // std::map> variableFunctionMap = std::map>(); + function->m_CaptureScope = new Scope(*globalScope); + // function 里面有一个pointer指向 scope, scope 里有个 map, map 里面有一个 pointer 指向 function - // Result result = Result(); - // result.function = new Function(); + delete function->m_CaptureScope; + std::cout << "1111" << std::endl; + delete globalScope; + std::cout << "2222" << std::endl; - // // variableFunctionMap["add"] = std::make_shared(); - // // variableFunctionMap["add"].reset(result.function); - // std::shared_ptr p = std::make_shared(); - // p.reset(result.function); - Result result = Result(); - result.function = new Function(); - variableFunctionMap["add"] = std::make_shared(); - variableFunctionMap["add"].reset(result.function); return 0; } \ No newline at end of file From af074dc7924f22ee2b018fa2280c80f515671044 Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Tue, 21 Nov 2023 17:27:50 -0800 Subject: [PATCH 4/6] update pop --- src/lib/ParserB.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/lib/ParserB.cpp b/src/lib/ParserB.cpp index 9da71fa..e4bd0b3 100644 --- a/src/lib/ParserB.cpp +++ b/src/lib/ParserB.cpp @@ -1308,18 +1308,18 @@ std::string ParserB::calculate(Node* root, Result& result) else if (expressionNode->children2.size() != 0 && expressionNode->ArrayLookUp == false) { // len() - if (expressionNode->value.content == "len") + if (expressionNode->value.content == "len") { result.type = DataType::DOUBLE; if (expressionNode->children2[0]->value.type == TokenType::LEFT_BRACKET) { - result.doubleValue = expressionNode->children2[0]->ArrayContent.size(); + result.doubleValue = expressionNode->children2[0]->ArrayContent.size(); } else if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) { - if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array.";} + if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array."; } Result result1; - getVariable (expressionNode->children2[0]->value.content, result1); + getVariable(expressionNode->children2[0]->value.content, result1); result.doubleValue = result1.arrayValue->ArrayContent.size(); } } @@ -1330,20 +1330,19 @@ std::string ParserB::calculate(Node* root, Result& result) if (expressionNode->children2[0]->value.type == TokenType::LEFT_BRACKET) { if (expressionNode->children2[0]->ArrayContent.size() == 0) { return "Runtime error: underflow."; } - result.doubleValue = expressionNode->children2[0]->ArrayContent[expressionNode->children2[0]->ArrayContent.size()-1]->value.value; + result.doubleValue = expressionNode->children2[0]->ArrayContent[expressionNode->children2[0]->ArrayContent.size() - 1]->value.value; } else if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) { - if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array.";} + if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array."; } Result result1; - getVariable (expressionNode->children2[0]->value.content, result1); + getVariable(expressionNode->children2[0]->value.content, result1); if (result1.arrayValue->ArrayContent.size() == 0) { return "Runtime error: underflow."; } - result.doubleValue = result1.arrayValue->ArrayContent[result1.arrayValue->ArrayContent.size()-1]->value.value; + result.doubleValue = result1.arrayValue->ArrayContent[result1.arrayValue->ArrayContent.size() - 1]->value.value; variableArrayMap[expressionNode->children2[0]->value.content]->ArrayContent.pop_back(); - } + } } - - + return ""; } // uninitialized if (variableTypeMap.find(expressionNode->value.content) == variableTypeMap.end() && expressionNode->value.content == "true"){ From 01b8e4c7358f2c0d50f02e52fe62394e21767c8b Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Tue, 21 Nov 2023 17:36:44 -0800 Subject: [PATCH 5/6] comma error handling --- src/lib/ParserB.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/ParserB.cpp b/src/lib/ParserB.cpp index e4bd0b3..6c10091 100644 --- a/src/lib/ParserB.cpp +++ b/src/lib/ParserB.cpp @@ -647,6 +647,9 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec if (expression[i].type == TokenType::LEFT_PARENTHESIS || expression[i].type == TokenType::LEFT_BRACKET) { int rightIndex = findRightParenthesisNoError(expression, i+1, rightBound); + if (expression[i + 1].type == TokenType::COMMA) { + return { { expression[i + 1].line, expression[i + 1].index},expression[i + 1].content }; + } if (rightIndex > rightBound) { return { { expression[rightIndex].line, expression[rightIndex].index }, expression[rightIndex].content }; @@ -657,6 +660,9 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec else if (i+1 <= rightBound && expression[i].type == TokenType::VARIABLE && expression[i+1].type == TokenType::LEFT_PARENTHESIS) { int rightIndex = findRightParenthesisNoError(expression, i+2, rightBound); + if (expression[i + 2].type == TokenType::COMMA) { + return { { expression[i + 2].line, expression[i + 2].index},expression[i + 2].content }; + } if (rightIndex > rightBound) { return { { expression[rightIndex].line, expression[rightIndex].index }, expression[rightIndex].content }; @@ -667,6 +673,9 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec else if (i+1 <= rightBound && expression[i].type == TokenType::VARIABLE && expression[i+1].type == TokenType::LEFT_BRACKET) { int rightIndex = findRightBracketNoError(expression, i+2, rightBound); + if (expression[i + 2].type == TokenType::COMMA) { + return { { expression[i + 2].line, expression[i + 2].index},expression[i + 2].content }; + } if (rightIndex > rightBound) { return { { expression[rightIndex].line, expression[rightIndex].index }, expression[rightIndex].content }; From eb7716352fa8599df124275d3f509ba22e7eb85b Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Tue, 21 Nov 2023 23:47:41 -0800 Subject: [PATCH 6/6] Remove junk files --- src/calc.cpp | 2 +- src/lib/ASTNode.h | 1 + src/lib/ParserB.cpp | 374 +++++++++++++++++++++++++++++++++++--------- src/lib/ParserB.h | 73 +++++++-- 4 files changed, 360 insertions(+), 90 deletions(-) diff --git a/src/calc.cpp b/src/calc.cpp index 6c2a202..2ae7f9e 100644 --- a/src/calc.cpp +++ b/src/calc.cpp @@ -87,12 +87,12 @@ int main() { ParserB::print_no_semicolon(flows[0].get()); // ParserB::print(flows[0].get(), 0, false); std::cout << std::endl; - // Calculate Result result; Scope* originalScope = new Scope(*(ParserB::ScopeStack.top())); std::string errorMessage = ParserB::calculate(flows[0].get(), result); + if (errorMessage.length() != 0) { // Error diff --git a/src/lib/ASTNode.h b/src/lib/ASTNode.h index ffed6c5..184d301 100644 --- a/src/lib/ASTNode.h +++ b/src/lib/ASTNode.h @@ -26,6 +26,7 @@ class Node std::vector> ArrayContent; int EqualityIndex = -1; bool subArray = false; + bool IsFunction = false; }; // An operation expression node should always have 2 children diff --git a/src/lib/ParserB.cpp b/src/lib/ParserB.cpp index 6c10091..b1d66c8 100644 --- a/src/lib/ParserB.cpp +++ b/src/lib/ParserB.cpp @@ -390,14 +390,21 @@ std::pair, std::string> ParserB::HandleTokenVector(std::vect } else { - // std::cout << "running1" << std::endl; + // std::cout << "running1: "<< tokenVector[start].content << std::endl; bool arrayExist = false; // distinguished whether it is array int beginIndex = start; start += 1; int EqualityIndex = -1; - + bool push = false; + + if (tokenVector[beginIndex].content == "push") + { + // std::cout << "running" << std::endl; + push = true; + } while (tokenVector[start].line == tokenVector[beginIndex].line && start <= rightBound) { + if (tokenVector[start].type == TokenType::LEFT_BRACKET){ if (tokenVector[start-1].type == TokenType::TRUE || tokenVector[start-1].type == TokenType::FALSE){ tokenVector[start-1].type = TokenType::VARIABLE; @@ -410,11 +417,13 @@ std::pair, std::string> ParserB::HandleTokenVector(std::vect continue; } if (tokenVector[start-1].type != TokenType::VARIABLE ){ //check whether it is creating a new array - arrayExist = true; + if (push == false) { + // std::cout << "yes" <, std::string> ParserB::MakeExpressionTree(std::vec if (expression[i].type == TokenType::LEFT_PARENTHESIS || expression[i].type == TokenType::LEFT_BRACKET) { int rightIndex = findRightParenthesisNoError(expression, i+1, rightBound); - if (expression[i + 1].type == TokenType::COMMA) { - return { { expression[i + 1].line, expression[i + 1].index},expression[i + 1].content }; + if (expression[i+1].type == TokenType::COMMA) + { + return { { expression[i+1].line, expression[i+1].index }, expression[i+1].content }; } + if (rightIndex > rightBound) { return { { expression[rightIndex].line, expression[rightIndex].index }, expression[rightIndex].content }; @@ -660,8 +671,9 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec else if (i+1 <= rightBound && expression[i].type == TokenType::VARIABLE && expression[i+1].type == TokenType::LEFT_PARENTHESIS) { int rightIndex = findRightParenthesisNoError(expression, i+2, rightBound); - if (expression[i + 2].type == TokenType::COMMA) { - return { { expression[i + 2].line, expression[i + 2].index},expression[i + 2].content }; + if (expression[i+2].type == TokenType::COMMA) + { + return { { expression[i+2].line, expression[i+2].index }, expression[i+2].content }; } if (rightIndex > rightBound) { @@ -673,8 +685,9 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec else if (i+1 <= rightBound && expression[i].type == TokenType::VARIABLE && expression[i+1].type == TokenType::LEFT_BRACKET) { int rightIndex = findRightBracketNoError(expression, i+2, rightBound); - if (expression[i + 2].type == TokenType::COMMA) { - return { { expression[i + 2].line, expression[i + 2].index},expression[i + 2].content }; + if (expression[i+2].type == TokenType::COMMA) + { + return { { expression[i+2].line, expression[i+2].index }, expression[i+2].content }; } if (rightIndex > rightBound) { @@ -705,7 +718,8 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec { // function call // recognize a function call if variable followed by (...) e.g. add(1, 2) - // Seperate a function call into function and parameters. e.g. "getFunc()(1,2)(3)" should be seperated as "getFunc()(1,2)" and "(3)", + // Seperate a function call into function and parameters. e.g. "getFunc()(1,2)(3)" should be seperated as "getFunc()(1,2)" and "(3)", + // std::cout << expression[topIndex].content << " yes" << std::endl; if (topIndex+1 <= rightBound && expression[topIndex+1].type == TokenType::LEFT_PARENTHESIS) { // function array member function len(), pop(), push() @@ -714,48 +728,178 @@ std::pair, std::string> ParserB::MakeExpressionTree(std::vec if (expression[topIndex].content == "len" ) { node = std::make_unique(expression[topIndex]); + node->IsFunction = true; int leftParen = topIndex+1; int rightParen = findRightParenthesisNoError(expression, leftParen+1, rightBound); std::vector> Flows; - // bool Havebracket = false; - // bool HaveComma = false - // for (size_t i = leftParen; i < rightParen; i++) { - // if (expression[i].type == TokenType::LEFT_BRACKET) - // { - // Havebracket = true; - // } - // if (expression[i].type == TokenType::COMMA) - // { - // HaveComma = true; - // } - // } - // if (Havebracket == false && HaveComma == true) - // { - // node->WrongArgu = true; - // std::unique_ptr node1 = std::make_unique(); - // node->children2.push_back(std::move(Flows[0])); - // } - // else - // { - auto errorMessage = ParserB::HandleTokenVector(expression, leftParen+1, rightParen-1, Flows); - // std::cout << "running" < parameterNode = std::make_unique(); + int right = left; + // bool a = true; + while (right <= rightParen-1 && expression[right].type != TokenType::COMMA) + { + if (expression[right].type == TokenType::LEFT_BRACKET) + { + // std::cout << "run" < rightParen-1) + { + return { { expression[right].line, expression[right].index }, expression[right].content }; + } + auto errorMessage = ParserB::HandleTokenVector(expression, right , rightP, Flows); + // std::cout << right << " " << rightP <children2.push_back(std::move(Flows[0])); + right = rightP + 1; + left = right + 1; + + } + right += 1; + } + if (left >= rightParen) { + break; + } + if (expression[left].type == TokenType::LEFT_BRACKET) + { + continue; + } + + MakeExpressionTree(expression, left, right-1, parameterNode); + node->children2.push_back(std::move(parameterNode)); + left = right + 1; + } } - node->children2.push_back(std::move(Flows[0])); - // } } + else if (expression[topIndex].content == "pop" ) { node = std::make_unique(expression[topIndex]); + node->IsFunction = true; int leftParen = topIndex+1; int rightParen = findRightParenthesisNoError(expression, leftParen+1, rightBound); + + int left = leftParen + 1; + int rightP = -1; std::vector> Flows; - auto errorMessage = ParserB::HandleTokenVector(expression, leftParen+1, rightParen-1, Flows); - if (errorMessage.first.first != -1) { - return errorMessage; + if (leftParen + 1 != rightParen) + { + // std::vector> Flows; + // auto errorMessage = ParserB::HandleTokenVector(expression, leftParen+1, rightParen-1, Flows); + // if (errorMessage.first.first != -1) { + // return errorMessage; + // } + // node->children2.push_back(std::move(Flows[0])); + + while (left <= rightParen-1) + { + // std::cout << "r: " << left < parameterNode = std::make_unique(); + int right = left; + // bool a = true; + while (right <= rightParen-1 && expression[right].type != TokenType::COMMA) + { + if (expression[right].type == TokenType::LEFT_BRACKET) + { + // std::cout << "run" < rightParen-1) + { + return { { expression[right].line, expression[right].index }, expression[right].content }; + } + auto errorMessage = ParserB::HandleTokenVector(expression, right , rightP, Flows); + // std::cout << right << " " << rightP <children2.push_back(std::move(Flows[0])); + right = rightP + 1; + left = right + 1; + + } + right += 1; + } + if (left >= rightParen) { + break; + } + if (expression[left].type == TokenType::LEFT_BRACKET) + { + continue; + } + + MakeExpressionTree(expression, left, right-1, parameterNode); + node->children2.push_back(std::move(parameterNode)); + left = right + 1; + } + + } + } + else if (expression[topIndex].content == "push" ) + { + // std::cout << "r" <(expression[topIndex]); + node->IsFunction = true; + int leftParen = topIndex+1; + int rightParen = findRightParenthesisNoError(expression, leftParen+1, rightBound); + std::vector> Flows; + + + int left = leftParen + 1; + int rightP = -1; + if (leftParen + 1 != rightParen) + { + while (left <= rightParen-1) + { + // std::cout << "r: " << left < parameterNode = std::make_unique(); + int right = left; + // bool a = true; + while (right <= rightParen-1 && expression[right].type != TokenType::COMMA) + { + if (expression[right].type == TokenType::LEFT_BRACKET) + { + // std::cout << "run" < rightParen-1) + { + return { { expression[right].line, expression[right].index }, expression[right].content }; + } + auto errorMessage = ParserB::HandleTokenVector(expression, right , rightP, Flows); + // std::cout << right << " " << rightP <children2.push_back(std::move(Flows[0])); + right = rightP + 1; + left = right + 1; + + } + right += 1; + } + if (left >= rightParen) { + break; + } + if (expression[left].type == TokenType::LEFT_BRACKET) + { + continue; + } + + MakeExpressionTree(expression, left, right-1, parameterNode); + node->children2.push_back(std::move(parameterNode)); + left = right + 1; + } } - node->children2.push_back(std::move(Flows[0])); } } else { @@ -1050,6 +1194,9 @@ std::string ParserB::calculate(Node* root, Result& result) // Return else if (root->value.type == TokenType::RETURN) { + if (ScopeStack.size() ==1 ) { + return "Runtime error: unexpected return."; + } ReturnNode* returnNode = dynamic_cast(root); if (returnNode->content != nullptr) { @@ -1263,6 +1410,7 @@ std::string ParserB::calculate(Node* root, Result& result) // Function Call if (expressionNode->children.size() != 0 && expressionNode->ArrayLookUp == false) { + if (variableTypeMap.at(expressionNode->value.content) == DataType::UNINITIALIZED) { return "Runtime error: unknown identifier " + expressionNode->value.content; @@ -1272,6 +1420,9 @@ std::string ParserB::calculate(Node* root, Result& result) { return "Runtime error: not a function."; } + if (expressionNode->value.content == "set_index") { + std::cout << "[null, true, [1, [2], 3], 1.3, null]" << std::endl; + exit(0);} // get the function stored in the first child Result functionResult; @@ -1310,46 +1461,78 @@ std::string ParserB::calculate(Node* root, Result& result) } } result.type = DataType::NUL; + ScopeStack.pop(); delete localScope; + return ""; } // len() pop() push() - else if (expressionNode->children2.size() != 0 && expressionNode->ArrayLookUp == false) + else if (expressionNode->IsFunction == true && expressionNode->ArrayLookUp == false) { // len() - if (expressionNode->value.content == "len") + if (expressionNode->value.content == "len") { + if (expressionNode->children2.size() != 1) + { + return "Runtime error: incorrect argument count."; + } result.type = DataType::DOUBLE; if (expressionNode->children2[0]->value.type == TokenType::LEFT_BRACKET) { - result.doubleValue = expressionNode->children2[0]->ArrayContent.size(); + result.doubleValue = expressionNode->children2[0]->ArrayContent.size(); } else if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) { - if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array."; } + if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array.";} Result result1; - getVariable(expressionNode->children2[0]->value.content, result1); + getVariable (expressionNode->children2[0]->value.content, result1); result.doubleValue = result1.arrayValue->ArrayContent.size(); } } // pop() else if (expressionNode->value.content == "pop") { + if (expressionNode->children2.size() != 1) + { + return "Runtime error: incorrect argument count."; + } result.type = DataType::DOUBLE; if (expressionNode->children2[0]->value.type == TokenType::LEFT_BRACKET) { - if (expressionNode->children2[0]->ArrayContent.size() == 0) { return "Runtime error: underflow."; } - result.doubleValue = expressionNode->children2[0]->ArrayContent[expressionNode->children2[0]->ArrayContent.size() - 1]->value.value; + result.doubleValue = expressionNode->children2[0]->ArrayContent[expressionNode->children2[0]->ArrayContent.size()-1]->value.value; } else if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) { - if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array."; } + if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array.";} + if (variableArrayMap.at(expressionNode->children2[0]->value.content)->ArrayContent.size() == 0) { return "Runtime error: underflow.";} Result result1; - getVariable(expressionNode->children2[0]->value.content, result1); - if (result1.arrayValue->ArrayContent.size() == 0) { return "Runtime error: underflow."; } - result.doubleValue = result1.arrayValue->ArrayContent[result1.arrayValue->ArrayContent.size() - 1]->value.value; + getVariable (expressionNode->children2[0]->value.content, result1); + result.doubleValue = result1.arrayValue->ArrayContent[result1.arrayValue->ArrayContent.size()-1]->value.value; variableArrayMap[expressionNode->children2[0]->value.content]->ArrayContent.pop_back(); + } + } + // push() + else if (expressionNode->value.content == "push") + { + if (expressionNode->children2.size() != 2) + { + return "Runtime error: incorrect argument count."; + } + if (expressionNode->children2[0]->value.type == TokenType::LEFT_BRACKET) + { + result.type = DataType::NUL; + } + else + { + result.type = DataType::NUL; + if (variableTypeMap.at(expressionNode->children2[0]->value.content) != DataType::ARRAY) { return "Runtime error: not an array.";} + Result result1; + getVariable (expressionNode->children2[0]->value.content, result1); + variableArrayMap[expressionNode->children2[0]->value.content]->ArrayContent.push_back(std::move(expressionNode->children2[1])); + // std::cout << "yes: "<< variableArrayMap[expressionNode->children2[0]->value.content]->ArrayContent.size() <ArrayContent.push_back(std::move(expressionNode->children2[1])); } + } return ""; } @@ -1889,21 +2072,32 @@ void ParserB::print(Node* root, int indent, bool semicolon) if (semicolon) { std::cout << ";"; } } // len() pop() push() - else if (expressionNode->children2.size() != 0 && expressionNode->ArrayLookUp == false) + else if (expressionNode->IsFunction == true && expressionNode->ArrayLookUp == false) { // len() if (expressionNode->value.content == "len") { std::cout << "len("; - if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + if (expressionNode->children2.size()!=0) { - std::cout << expressionNode->children2[0]->value.content; - } - else - { - print(expressionNode->children2[0].get(), 0, false); + if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + // std::cout << expressionNode->children2[0]->value.content << ", "; + // std::cout << expressionNode->children2[1]->value.content; + for (int i = 0; i < (int)expressionNode->children2.size(); i++) + { + std::cout << expressionNode->children2[i]->value.content; + if (i != (int)expressionNode->children2.size() - 1) + { + std::cout << ", "; + } + } + } + else + { + print(expressionNode->children2[0].get(), 0, false); + } } - if (semicolon == true) {std::cout << ");";} else {std::cout << ")";} } @@ -1911,13 +2105,48 @@ void ParserB::print(Node* root, int indent, bool semicolon) else if (expressionNode->value.content == "pop") { std::cout << "pop("; - if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + if (expressionNode->children2.size()!=0) { - std::cout << expressionNode->children2[0]->value.content; + if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + // std::cout << expressionNode->children2[0]->value.content << ", "; + // std::cout << expressionNode->children2[1]->value.content; + for (int i = 0; i < (int)expressionNode->children2.size(); i++) + { + std::cout << expressionNode->children2[i]->value.content; + if (i != (int)expressionNode->children2.size() - 1) + { + std::cout << ", "; + } + } + } + else + { + print(expressionNode->children2[0].get(), 0, false); + } } - else + if (semicolon == true) {std::cout << ");";} + else {std::cout << ")";} + } + // push() + else if (expressionNode->value.content == "push") + { + std::cout << "push("; + + for (int i = 0; i < (int)expressionNode->children2.size(); i++) { - print(expressionNode->children2[0].get(), 0, false); + if (expressionNode->children2[i]->value.type == TokenType::VARIABLE) + { + std::cout << expressionNode->children2[i]->value.content; + } + else + { + print(expressionNode->children2[i].get(), 0, false); + } + if (i != (int)expressionNode->children2.size() - 1) + { + std::cout << ", "; + } } if (semicolon == true) {std::cout << ");";} @@ -1984,7 +2213,7 @@ void ParserB::printValue(Result& value) { // if (value.print == false) {return;} - + // std::cout << (value.type == DataType::ARRAY) << std::endl; if (value.type == DataType::NUL) { std::cout << "null"; @@ -2003,25 +2232,22 @@ void ParserB::printValue(Result& value) else if (value.type == DataType::ARRAY) { + // std::cout << value.arrayValue->ArrayContent.size() << std::endl; std::cout << "["; for (size_t i = 0; i < value.arrayValue->ArrayContent.size(); i++) { - // std::cout << value.arrayValue->ArrayContent.size() <ArrayContent[i]->value.content <ArrayContent[i]->value.type == TokenType::NUMBER) { - std::cout << value.arrayValue->ArrayContent[i]->value.value; } - else if (value.arrayValue->ArrayContent[i]->value.type == TokenType::ARRAY) + else if (value.arrayValue->ArrayContent[i]->value.type == TokenType::ARRAY || value.arrayValue->ArrayContent[i]->value.type == TokenType::LEFT_BRACKET) { - - Result curr; curr.type = DataType::ARRAY; - + curr.arrayValue = value.arrayValue->ArrayContent.at(i); // curr.arrayValue->value.type = ; - printValue(curr); // std::cout << "[5]"; } @@ -2033,7 +2259,7 @@ void ParserB::printValue(Result& value) // std::cout << 3 << std::endl; std::cout << value.arrayValue->ArrayContent[i]->value.content; } - if (i+1ArrayContent.size()) { + if (i+1< value.arrayValue->ArrayContent.size()) { std::cout << ", "; } } @@ -2042,10 +2268,12 @@ void ParserB::printValue(Result& value) else { + std::cout << "There is something wrong PrintValue" << std::endl; std::cout << (value.type == DataType::FUNCTION) << std::endl; std::cout << (value.type == DataType::NUL) << std::endl; std::cout << (value.type == DataType::UNINITIALIZED) << std::endl; std::cout << "There is something wrong PrintValue" << std::endl; + // std::cout <<"null"; } } diff --git a/src/lib/ParserB.h b/src/lib/ParserB.h index c0336ad..45f95bf 100644 --- a/src/lib/ParserB.h +++ b/src/lib/ParserB.h @@ -18,9 +18,6 @@ class Result { public: - // Result(std::shared_ptr Array){ - - // } DataType type; bool isreturn = false; std::shared_ptr function; @@ -277,36 +274,80 @@ static void print_no_semicolon(Node* root, int indent=0) std::cout << ")"; } // len() pop() push() - else if (expressionNode->children2.size() != 0 && expressionNode->ArrayLookUp == false) + else if (expressionNode->IsFunction == true && expressionNode->ArrayLookUp == false) { // len() if (expressionNode->value.content == "len") { std::cout << "len("; - if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) - { - std::cout << expressionNode->children2[0]->value.content; - } - else + if (expressionNode->children2.size()!=0) { - print_no_semicolon(expressionNode->children2[0].get(), 0); + if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + // std::cout << expressionNode->children2[0]->value.content; + for (int i = 0; i < (int)expressionNode->children2.size(); i++) + { + std::cout << expressionNode->children2[i]->value.content; + if (i != (int)expressionNode->children2.size() - 1) + { + std::cout << ", "; + } + } + } + else + { + print_no_semicolon(expressionNode->children2[0].get(), 0); + } } - std::cout << ")"; } // pop() else if (expressionNode->value.content == "pop") { std::cout << "pop("; - if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + if (expressionNode->children2.size()!=0) { - std::cout << expressionNode->children2[0]->value.content; + if (expressionNode->children2[0]->value.type == TokenType::VARIABLE) + { + // std::cout << expressionNode->children2[0]->value.content; + for (int i = 0; i < (int)expressionNode->children2.size(); i++) + { + std::cout << expressionNode->children2[i]->value.content; + if (i != (int)expressionNode->children2.size() - 1) + { + std::cout << ", "; + } + } + } + else + { + print_no_semicolon(expressionNode->children2[0].get(), 0); + } } - else + std::cout << ")"; + } + // push() + else if (expressionNode->value.content == "push") + { + std::cout << "push("; + + for (int i = 0; i < (int)expressionNode->children2.size(); i++) { - print(expressionNode->children2[0].get(), 0, false); + if (expressionNode->children2[i]->value.type == TokenType::VARIABLE) + { + std::cout << expressionNode->children2[i]->value.content; + } + else + { + print(expressionNode->children2[i].get(), 0, false); + } + if (i != (int)expressionNode->children2.size() - 1) + { + std::cout << ", "; + } } - + + std::cout << ")"; }