#include <string>

// TODO: Change This Variable.
std::string input = R"(
var(integer) a;
var(integer) b;
input a;
input b;
output a+b;
)";

#include <string>
using std::__cxx11::to_string;

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>

#include <string>
#include <unordered_set>

#ifndef TOKEN_HPP
#define TOKEN_HPP

/*
A simple implementation of the syntax token.

Member Variables:
- The type of the syntax token.
- The value of the syntax token.

Member Functions:
- ==(const Token &oth)
    Verify whether two Token objects are equal.

- !=(const Token &oth)
    Verify whether two Token objects are not equal.
*/
struct Token {
	std::string type;
	std::string value;
	
	bool operator==(const Token &oth) const {
		return type == oth.type && value == oth.value;
	}
	
	bool operator!=(const Token &oth) const {
		return !(*this == oth);
	}
};

bool equalAsParse(Token a, Token b) {
	if (a.type == "`" || b.type == "`") {
		return true;
	}
	if (a.type == b.type && (a.value == "`" || b.value == "`")) {
		return true;
	}
	return a == b;
}

const Token EOFTOKEN = {"<EOF>", ""}; // The const syntax token of EOF.

#endif
#include <iostream>

#include <string>
#include <unordered_set>

#ifndef LEXER_HPP
#define LEXER_HPP

/*
Implemented object classes for semantic analysis.

Lexer(const std::string &input)
    Get the string line has to lex.
*/
class Lexer {
public:
    Lexer(const std::string& input) : input(input), position(0) {}

    // Get next syntax token.
    Token getNextToken();

private:
    const std::string& input;
    size_t position;

    // A set of all keywords.
    const std::unordered_set<std::string> keywords = {
    	"RUN", // TOP KEYWORD
    	"output", "input", // Terminal Keyword
        "integer", "float", "boolean", "string", // Basic Types
        "var", //Defines
		"if", "else", // Process
		"while", "for", "continue", "break", // Loops
		"true", "false" // Boolean
    };

    // A set of all operators.
    const std::unordered_set<std::string> operators = {
    	"=", // Assignment
        "+", "-", "*", "/", "%", // Basic operation
		"==", "!=", // Equal to relationship
		"<", ">", "<=", ">=", // Size relationship
    };

    // Skip empty charactors.
    void skipWhitespace();

    // Determine whether the input has reached the end
    bool isAtEnd();

    // Determine if it is an alpha
    bool isAlpha(char c);

    // Determine if it is a digit
    bool isDigit(char c);

    // Get identifier or keyword
    Token getIdentifierOrKeyword();

    // Get number(integer or float)
    Token getNumber();

    // Get string
    Token getString();

    // Get chatactor
    Token getChar();

    // Get operator or special symbol
    Token getOperatorOrSpecialSymbol();
};


//---------------------------------------


// Skip empty charactors.
void Lexer::skipWhitespace() {
    while (isspace(input[position])) {
        position++;
    }
}

// Determine whether the input has reached the end
bool Lexer::isAtEnd() {
    return position >= input.length();
}

// Determine if it is an alpha
bool Lexer::isAlpha(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}

// Determine if it is a digit
bool Lexer::isDigit(char c) {
    return c >= '0' && c <= '9';
}

// Get identifier or keyword
Token Lexer::getIdentifierOrKeyword() {
    std::string identifier;
    while (isAlpha(input[position]) || isDigit(input[position])) {
        identifier += input[position];
        position++;
    }
    if (keywords.count(identifier) > 0) {
        return {"<KEYWORD>", identifier};
    }
    return {"<IDENTIFIER>", identifier};
}

// Get number(integer or float)
Token Lexer::getNumber() {
    std::string number;
    bool hasDecimalPoint = false;
    while (isDigit(input[position]) || (!hasDecimalPoint && input[position] == '.')) {
        if (input[position] == '.') hasDecimalPoint = true;
        number += input[position];
        position++;
    }
    if (hasDecimalPoint) {
    	return {"float", number};
    }
    return {"integer", number};
}

// Get string
Token Lexer::getString() {
    std::string stringValue;
    position++; // Skip the double quotation mark at the beginning
    while (input[position]!= '"' &&!isAtEnd()) {
        stringValue += input[position];
        position++;
    }
    position++; // Skip the double quotation mark at the endding
    return {"string", stringValue};
}

// Get chatactor
Token Lexer::getChar() {
    std::string charValue;
    position++; // Skip the opening single quotation mark
    if (input[position] == '\'') {
        position++; 
        return {"charactor", ""};
    }
    charValue += input[position];
    position++;
    if (input[position]!= '\'') {
        // The character should only have one character length. Error situations are handled here
        std::cerr << "Error: Invalid character literal" << std::endl;
        return {};
    }
    position++;
    return {"charactor", charValue};
}

// Get operator or special symbol
Token Lexer::getOperatorOrSpecialSymbol() {
    std::string symbol(1, input[position]);
    position++;
    std::string twoCharSymbol = symbol + input[position];
    if (operators.count(twoCharSymbol) > 0) {
        position++;
        return {"<OPERATOR>", twoCharSymbol};
    } else if (operators.count(symbol) > 0) {
        return {"<OPERATOR>", symbol};
    }
    return {"<SPECIAL>", symbol};
}

Token Lexer::getNextToken() {
    skipWhitespace();
    if (isAtEnd()) {
    	return {"<EOF>", ""};
	}

    char currentChar = input[position];
    if (isAlpha(currentChar)) {
        return getIdentifierOrKeyword();
    } else if (isDigit(currentChar)) {
        return getNumber();
    } else if (currentChar == '"') {
        return getString();
    } else if (currentChar == '\'') {
        return getChar();
    } else {
        return getOperatorOrSpecialSymbol();
    }
}

#endif
#include <iostream>

#ifndef ERROR_HPP
#define ERROR_HPP

// Raise an error.
void error(std::string message) {
	std::cerr << "[!]Error: " << message << std::endl;
	exit(0);
}

#endif

#ifndef PARSER_HPP
#define PARSET_HPP

// Abstract syntax tree node base class
class AstNode {
public:
	virtual ~AstNode() {}
};

// Expression Node Class
class ExpressionNode : public AstNode {
public:
	std::string op;
	Token token;
	std::shared_ptr<ExpressionNode> left;  //Left Child (If has)
	std::shared_ptr<ExpressionNode> right; //Right Child (If has)
	
	ExpressionNode(Token token) : token(token), left(nullptr), right(nullptr) {}
    ExpressionNode(std::string op, std::shared_ptr<ExpressionNode> left, std::shared_ptr<ExpressionNode> right) : op(op), left(left), right(right) {}
};

// Statement Node Class
class StatementNode : public AstNode {
public:
	virtual ~StatementNode() {}
};

class CodeBlockStatementNode : public StatementNode {
public:
	std::vector<std::shared_ptr<StatementNode>> statements;
};

class VarDeclarationStatementNode : public StatementNode {
public:
	std::string varType;
	std::string varName;
	std::shared_ptr<ExpressionNode> varValue;
};

class AssignmentStatementNode : public StatementNode {
public:
	std::string varName;
	std::shared_ptr<ExpressionNode> newValue;	
};

// if Statement Node Class
class IfStatementNode : public StatementNode {
public:
    std::shared_ptr<ExpressionNode> condition;
    std::shared_ptr<CodeBlockStatementNode> thenBlock;
    std::shared_ptr<CodeBlockStatementNode> elseBlock;
};

// while Statement Node Class
class WhileStatementNode : public StatementNode {
public:
    std::shared_ptr<ExpressionNode> condition;
    std::shared_ptr<CodeBlockStatementNode> body;
};

// for Statement Node Class
class ForStatementNode : public StatementNode {
public:
    std::shared_ptr<StatementNode> init;
    std::shared_ptr<ExpressionNode> condition;
    std::shared_ptr<StatementNode> increment;
    std::shared_ptr<CodeBlockStatementNode> body;
};

// input Statement Node Class
class InputStatementNode : public StatementNode {
public:
	std::string varName;
};

// output Statement Node Class
class OutputStatementNode : public StatementNode {
public:
	std::shared_ptr<ExpressionNode> content;
};

// Program Statement Node Class
class ProgramNode : public AstNode {
public:
    std::vector<std::shared_ptr<StatementNode>> statements;
};

// Operator precedence enumeration
enum class Precedence {
    LOWEST,
    LOSERS,
    EQUALS,
    COMPARE_SIZE,
    ADD_SUB,
    MUL_DIV,
    MAXEST
};

// THE PARSER
class Parser {
public:
    Parser(Lexer& lexer);
    std::shared_ptr<ProgramNode> parse();

private:
    Lexer& lexer;
    Token currentToken;
	
    void eat(Token expectedToken);
    std::shared_ptr<StatementNode> parseStatement();
    std::shared_ptr<ExpressionNode> parseExpression(Precedence precedence);
    std::shared_ptr<CodeBlockStatementNode> parseCodeBlockStatement();
    std::shared_ptr<VarDeclarationStatementNode> parseVarDeclarationStatement();
    std::shared_ptr<AssignmentStatementNode> parseAssignmentStatement();
    std::shared_ptr<IfStatementNode> parseIfStatement();
    std::shared_ptr<WhileStatementNode> parseWhileStatement();
    std::shared_ptr<ForStatementNode> parseForStatement();
    std::shared_ptr<InputStatementNode> parseInputStatement();
    std::shared_ptr<OutputStatementNode> parseOutputStatement();
    
    // Operator precedence map
    std::unordered_map<std::string, Precedence> precedenceMap = {
    	{"=", Precedence::LOSERS},
    	{"==", Precedence::EQUALS},
    	{"!=", Precedence::EQUALS},
    	{"<=", Precedence::COMPARE_SIZE},
    	{">=", Precedence::COMPARE_SIZE},
    	{"<", Precedence::COMPARE_SIZE},
    	{">", Precedence::COMPARE_SIZE},
        {"+", Precedence::ADD_SUB},
        {"-", Precedence::ADD_SUB},
        {"*", Precedence::MUL_DIV},
        {"/", Precedence::MUL_DIV},
        {"%", Precedence::MUL_DIV}
    };
};

// Parser constructor
// Receive a Lexer object and retrieve the first lexical unit
Parser::Parser(Lexer &lexer) : lexer(lexer) {
	currentToken = lexer.getNextToken();
}

// Analyze program entry functions
// Analyze the entire program and build the root node (Program Node) of the syntax tree
std::shared_ptr<ProgramNode> Parser::parse() {
	std::shared_ptr<ProgramNode> program = std::make_shared<ProgramNode>();
	
	while (currentToken != EOFTOKEN) {
		program->statements.push_back(parseStatement());
	}
	
	return program;
}

// Eat funtion
// 'Eats' expected token.
void Parser::eat(Token expectedToken) {
	if (equalAsParse(currentToken, expectedToken)) {
		currentToken = lexer.getNextToken();
	} else {
		error("Expected Token{type="+expectedToken.type+";value="+expectedToken.value+"}, got Token{type="+currentToken.type+";value="+currentToken.value+"}");
	}
}

// Parse statement
// Resolve different types of statements based on the current lexical unit type
std::shared_ptr<StatementNode> Parser::parseStatement() {
	if (currentToken == (Token){"<SPECIAL>", "{"}) {
		return parseCodeBlockStatement();
	} else if (currentToken == (Token){"<KEYWORD>", "var"}) {
        return parseVarDeclarationStatement();
    } else if (currentToken == (Token){"<KEYWORD>", "if"}) {
        return parseIfStatement();
    } else if (currentToken == (Token){"<KEYWORD>", "while"}) {
        return parseWhileStatement();
    } else if (currentToken == (Token){"<KEYWORD>", "for"}) {
        return parseForStatement();
    } else if (currentToken == (Token){"<KEYWORD>", "input"}) {
    	return parseInputStatement();
	} else if (currentToken == (Token){"<KEYWORD>", "output"}) {
		return parseOutputStatement();
	} else if (equalAsParse(currentToken, {"<IDENTIFIER>", "`"})) {
    	return parseAssignmentStatement();
	}
    eat({"<SPECIAL>", ";"});
    return nullptr;
}

// Parse expression with precedence handling
std::shared_ptr<ExpressionNode> Parser::parseExpression(Precedence precedence = Precedence::LOWEST) {
    bool flag = false;

    if (currentToken.value == "(") {
        eat(Token{"<SPECIAL>", "("});
        std::shared_ptr<ExpressionNode> innerExpr = parseExpression();
        eat(Token{"<SPECIAL>", ")"});
        return innerExpr;
    }

    std::shared_ptr<ExpressionNode> left = std::make_shared<ExpressionNode>(currentToken);
    eat(currentToken);

    while (true) {
        if (currentToken.type == "<OPERATOR>") {
            Token opToken = currentToken;
            Precedence currentPrecedence = precedenceMap[opToken.value];
            if (precedence < currentPrecedence) {
                eat(opToken);
                if (opToken.value == "(") {
                    std::shared_ptr<ExpressionNode> right = parseExpression();
                    eat(Token{"<SPECIAL>", ")"});
                    left = std::make_shared<ExpressionNode>(opToken.value, left, right);
                } else {
                    std::shared_ptr<ExpressionNode> right = parseExpression(currentPrecedence);
                    left = std::make_shared<ExpressionNode>(opToken.value, left, right);
                }
            } else {
                break;
            }
        } else {
            break;
        }
    }

    return left;
}

// Parse CODEBLOCK Statement.
std::shared_ptr<CodeBlockStatementNode> Parser::parseCodeBlockStatement() {
	eat(Token{"<SPECIAL>", "{"});
    
    std::shared_ptr<CodeBlockStatementNode> resNode = std::make_shared<CodeBlockStatementNode>();
    
    while (currentToken != (Token){"<SPECIAL>", "}"}) {
        resNode->statements.push_back(parseStatement());
    }
    
    eat(Token{"<SPECIAL>", "}"});
    
    return resNode;
}

// Parse var statement
std::shared_ptr<VarDeclarationStatementNode> Parser::parseVarDeclarationStatement() {
	eat(Token{"<KEYWORD>", "var"});
    eat(Token{"<SPECIAL>", "("});
    std::string varType = currentToken.value;
    eat(Token{"<KEYWORD>", "`"});
    eat(Token{"<SPECIAL>", ")"});
    std::string varName = currentToken.value;
    eat(Token{"<IDENTIFIER>", "`"});
    
    std::shared_ptr<ExpressionNode> expr = std::make_shared<ExpressionNode>(Token{varType, "0"});
    
    if (currentToken != (Token){"<SPECIAL>", ";"}) {
		eat(Token{"<OPERATOR>", "="});
    	expr = parseExpression();
	}
    
    std::shared_ptr<VarDeclarationStatementNode> res = std::make_shared<VarDeclarationStatementNode>();
    res->varType = varType;
    res->varName = varName;
    res->varValue = expr;
    
    return res;
}

// Parse Assignment Statement
std::shared_ptr<AssignmentStatementNode> Parser::parseAssignmentStatement() {
	std::string varName = currentToken.value;
	eat(Token{"<IDENTIFIER>", "`"});
	eat(Token{"<OPERATOR>", "="});
	std::shared_ptr<ExpressionNode> newValue = parseExpression();
	
	std::shared_ptr<AssignmentStatementNode> res = std::make_shared<AssignmentStatementNode>();
	
	res->varName = varName;
	res->newValue = newValue;
	
	return res;
}

// Parse if statement
std::shared_ptr<IfStatementNode> Parser::parseIfStatement() {
    eat(Token{"<KEYWORD>", "if"});
    eat(Token{"<SPECIAL>", "("});
    std::shared_ptr<ExpressionNode> condition = parseExpression();
    eat(Token{"<SPECIAL>", ")"});

    std::shared_ptr<IfStatementNode> ifNode = std::make_shared<IfStatementNode>();
    ifNode->condition = condition;
	
	std::shared_ptr<CodeBlockStatementNode> thenBlock = parseCodeBlockStatement();
	ifNode->thenBlock = thenBlock;

    if (currentToken == (Token){"<KEYWORD>", "else"}) {
        eat(Token{"<KEYWORD>", "else"});
        
        std::shared_ptr<CodeBlockStatementNode> elseBlock = parseCodeBlockStatement();
        ifNode->elseBlock = elseBlock;
    }
    
    return ifNode;
}

// Parse while statement
std::shared_ptr<WhileStatementNode> Parser::parseWhileStatement() {
    eat(Token{"<KEYWORD>", "while"});
    eat(Token{"<SPECIAL>", "("});
    std::shared_ptr<ExpressionNode> condition = parseExpression();
    eat(Token{"<SPECIAL>", ")"});

    std::shared_ptr<WhileStatementNode> whileNode = std::make_shared<WhileStatementNode>();
    whileNode->condition = condition;
	
    std::shared_ptr<CodeBlockStatementNode> body = parseCodeBlockStatement();
    whileNode->body = body;
    
    return whileNode;
}

// Parse for statement
std::shared_ptr<ForStatementNode> Parser::parseForStatement() {
    eat(Token{"<KEYWORD>", "for"});
    eat(Token{"<SPECIAL>", "("});

    std::shared_ptr<StatementNode> init = parseStatement();
    eat(Token{"<SPECIAL>", ";"});

    std::shared_ptr<ExpressionNode> condition = parseExpression();
    eat(Token{"<SPECIAL>", ";"});

    std::shared_ptr<StatementNode> increment = parseStatement();
    eat(Token{"<SPECIAL>", ")"});

    std::shared_ptr<ForStatementNode> forNode = std::make_shared<ForStatementNode>();
    forNode->init = init;
    forNode->condition = condition;
    forNode->increment = increment;
	
    std::shared_ptr<CodeBlockStatementNode> body = parseCodeBlockStatement();
    forNode->body = body;
    
    return forNode;
}

// Parse input statement.
std::shared_ptr<InputStatementNode> Parser::parseInputStatement() {
	eat(Token{"<KEYWORD>", "input"});
	
	std::string value;
	
	if (currentToken.type == "<IDENTIFIER>") {
		value = currentToken.value;
	}
	
	eat(Token{"<IDENTIFIER>", "`"});
	
	std::shared_ptr<InputStatementNode> inputNode = std::make_shared<InputStatementNode>();
	inputNode->varName = value;
	
	return inputNode;
}

// Parse output statement.
std::shared_ptr<OutputStatementNode> Parser::parseOutputStatement() {
	eat(Token{"<KEYWORD>", "output"});
	
	std::shared_ptr<ExpressionNode> value = parseExpression();
	
	eat(Token{"`", "`"});
	
	std::shared_ptr<OutputStatementNode> outputNode = std::make_shared<OutputStatementNode>();
	outputNode->content = value;
	
	return outputNode;
}

#endif

#ifndef OPERATORS_HPP
#define OPERATORS_HPP

std::string type(Token a) {
	return a.type;
}

Token operator_plus(Token a, Token b) {
	if (type(a) == "string" && type(b) == "string") {
		// string + string
		return {"string", a.value+b.value};
	}
	if (type(a) == "integer" && type(b) == "integer") {
		// integer + integer
		return {"integer", to_string(stoll(a.value)+stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float + float
		return {"float", to_string(stold(a.value)+stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer + float
		return {"float", to_string(stold(a.value)+stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float + integer
		return {"float", to_string(stold(a.value)+stold(b.value))};
	}
	error("No matching function to call to <operator_plus>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_minus(Token a, Token b) {
	if (type(a) == "integer" && type(b) == "integer") {
		// integer - integer
		return {"integer", to_string(stoll(a.value)-stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float - float
		return {"float", to_string(stold(a.value)-stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer - float
		return {"float", to_string(stold(a.value)-stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float - integer
		return {"float", to_string(stold(a.value)-stold(b.value))};
	}
	error("No matching function to call to <operator_minus>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_times(Token a, Token b) {
	if (type(a) == "integer" && type(b) == "integer") {
		// integer * integer
		return {"integer", to_string(stoll(a.value)*stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float * float
		return {"float", to_string(stold(a.value)*stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer * float
		return {"float", to_string(stold(a.value)*stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float * integer
		return {"float", to_string(stold(a.value)*stold(b.value))};
	}
	error("No matching function to call to <operator_times>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_divide(Token a, Token b) {
	if (type(a) == "integer" && type(b) == "integer") {
		// integer / integer
		return {"integer", to_string(stoll(a.value)/stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float / float
		return {"float", to_string(stold(a.value)/stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer / float
		return {"float", to_string(stold(a.value)/stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float / integer
		return {"float", to_string(stold(a.value)/stold(b.value))};
	}
	error("No matching function to call to <operator_divide>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_mod(Token a, Token b) {
	if (type(a) == "integer" && type(b) == "integer") {
		// integer % integer
		return {"integer", to_string(stoll(a.value)%stoll(b.value))};
	}
	error("No matching function to call to <operator_mod>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_equals(Token a, Token b) {
	if (type(a) == "string" && type(b) == "string") {
		// string == string
		return {"boolean", to_string(a.value == b.value)};
	}
	if (type(a) == "charactor" && type(b) == "charactor") {
		// charactor == charactor
		return {"boolean", to_string(a.value == b.value)};
	}
	if (type(a) == "integer" && type(b) == "integer") {
		// integer == integer
		return {"boolean", to_string(stoll(a.value) == stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float == float
		return {"boolean", to_string(stold(a.value) == stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer == float
		return {"boolean", to_string(stold(a.value) == stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float == integer
		return {"boolean", to_string(stold(a.value) == stold(b.value))};
	}
	error("No matching function to call to <operator_equals>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_notequals(Token a, Token b) {
	if (type(a) == "string" && type(b) == "string") {
		// string != string
		return {"boolean", to_string(a.value != b.value)};
	}
	if (type(a) == "charactor" && type(b) == "charactor") {
		// charactor != charactor
		return {"boolean", to_string(a.value != b.value)};
	}
	if (type(a) == "integer" && type(b) == "integer") {
		// integer != integer
		return {"boolean", to_string(stoll(a.value) != stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float != float
		return {"boolean", to_string(stold(a.value) != stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer != float
		return {"boolean", to_string(stold(a.value) != stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float != integer
		return {"boolean", to_string(stold(a.value) != stold(b.value))};
	}
	error("No matching function to call to <operator_notequals>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_less(Token a, Token b) {
	if (type(a) == "integer" && type(b) == "integer") {
		// integer < integer
		return {"boolean", to_string(stoll(a.value) < stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float < float
		return {"boolean", to_string(stold(a.value) < stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer < float
		return {"boolean", to_string(stold(a.value) < stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float < integer
		return {"boolean", to_string(stold(a.value) < stold(b.value))};
	}
	error("No matching function to call to <operator_less>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_greater(Token a, Token b) {
	if (type(a) == "integer" && type(b) == "integer") {
		// integer > integer
		return {"boolean", to_string(stoll(a.value) > stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float > float
		return {"boolean", to_string(stold(a.value) > stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer > float
		return {"boolean", to_string(stold(a.value) > stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float > integer
		return {"boolean", to_string(stold(a.value) > stold(b.value))};
	}
	error("No matching function to call to <operator_greater>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_less_equals(Token a, Token b) {
	if (type(a) == "integer" && type(b) == "integer") {
		// integer <= integer
		return {"boolean", to_string(stoll(a.value) <= stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float <= float
		return {"boolean", to_string(stold(a.value) <= stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer <= float
		return {"boolean", to_string(stold(a.value) <= stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float <= integer
		return {"boolean", to_string(stold(a.value) <= stold(b.value))};
	}
	error("No matching function to call to <operator_less_equals>("+type(a)+", "+type(b)+")!");
	return {};
}

Token operator_greater_equals(Token a, Token b) {
	if (type(a) == "integer" && type(b) == "integer") {
		// integer >= integer
		return {"boolean", to_string(stoll(a.value) >= stoll(b.value))};
	}
	if (type(a) == "float" && type(b) == "float") {
		// float >= float
		return {"boolean", to_string(stold(a.value) >= stold(b.value))};
	}
	if (type(a) == "integer" && type(b) == "float") {
		// integer >= float
		return {"boolean", to_string(stold(a.value) >= stold(b.value))};
	}
	if (type(a) == "float" && type(b) == "integer") {
		// float >= integer
		return {"boolean", to_string(stold(a.value) >= stold(b.value))};
	}
	error("No matching function to call to <operator_greater_equals>("+type(a)+", "+type(b)+")!");
	return {};
}

#endif

#ifndef INTERPRETER_HPP
#define INTERPRETER_HPP

class Interpreter {
public:
    Interpreter() {}

    // 运行程序,接收抽象语法树的根节点作为参数
    void run(const std::shared_ptr<AstNode>& node, int indent);

private:
    // 存储变量名和对应值的哈希表
    std::unordered_map<std::string, Token> variables;
    
    Token evaluateExpression(const std::shared_ptr<ExpressionNode>& expr);
};

bool trueOrFalse(const std::string &str) {
	return (str == "1" ? true : false); // TODO: CHECK
}

// 辅助函数,用于计算表达式的值
Token Interpreter::evaluateExpression(const std::shared_ptr<ExpressionNode>& expr) {
    if (expr->op.empty()) {
    	if (expr->token.type == "<IDENTIFIER>") {
    		return variables[expr->token.value];
		}
        return expr->token;
    } else {
        // 根据操作符进行相应的计算,这里仅为示例,可以根据实际需求进行扩展
        Token leftValue = evaluateExpression(expr->left);
        Token rightValue = evaluateExpression(expr->right);
        if (expr->op == "+") {
            return operator_plus(leftValue, rightValue);
        } else if (expr->op == "-") {
            return operator_minus(leftValue, rightValue);
        } else if (expr->op == "*") {
            return operator_times(leftValue, rightValue);
        } else if (expr->op == "/") {
        	return operator_divide(leftValue, rightValue);
		} else if (expr->op == "%") {
			return operator_mod(leftValue, rightValue);
		} else if (expr->op == "==") {
			return operator_equals(leftValue, rightValue);
		} else if (expr->op == "!=") {
			return operator_notequals(leftValue, rightValue);
		} else if (expr->op == "<") {
			return operator_less(leftValue, rightValue);
		} else if (expr->op == ">") {
			return operator_greater(leftValue, rightValue);
		} else if (expr->op == "<=") {
			return operator_less_equals(leftValue, rightValue);
		} else if (expr->op == ">=") {
			return operator_greater_equals(leftValue, rightValue);
		}
    }
    
    return {"",""};
}

void Interpreter::run(const std::shared_ptr<AstNode>& node, int indent = 0) {
	if (node == nullptr) return;
    std::string indentStr(indent*2, ' ');
    
	if (auto prgNode = std::dynamic_pointer_cast<ProgramNode>(node)) {
		for (const auto& subStmt : prgNode->statements) {
            run(subStmt, indent + 1);
        }
	} else if (auto stmtNode = std::dynamic_pointer_cast<StatementNode>(node)) {
    	if (auto CodeBlockStmtNode = std::dynamic_pointer_cast<CodeBlockStatementNode>(stmtNode)) {
    		// Interprete Code Blocks.
			for (auto p : CodeBlockStmtNode->statements) {
	    		run(p, indent + 1);
			}
		} else if (auto varStmtNode = std::dynamic_pointer_cast<VarDeclarationStatementNode>(stmtNode)) {
			// Interprete Var Declaration Statements.
			variables[varStmtNode->varName] = Token{varStmtNode->varType, evaluateExpression(varStmtNode->varValue).value}; // TODO: MORE CHANGES
		} else if (auto assStmtNode = std::dynamic_pointer_cast<AssignmentStatementNode>(stmtNode)) {
			// Interprete Var Assignment Statements.
			variables[assStmtNode->varName].value = evaluateExpression(assStmtNode->newValue).value;
		} else if (auto ifStmtNode = std::dynamic_pointer_cast<IfStatementNode>(stmtNode)) {
			// Interprete If Statements.
			if (trueOrFalse(evaluateExpression(ifStmtNode->condition).value)) { // TODO: CHECK
				run(ifStmtNode->thenBlock, indent+1);
			} else {
				run(ifStmtNode->elseBlock, indent+1);
			}
        } else if (auto whileStmtNode = std::dynamic_pointer_cast<WhileStatementNode>(stmtNode)) {
        	// Interprete While Statements.
        	while (trueOrFalse(evaluateExpression(whileStmtNode->condition).value)) { // TODO: CHECK
        		run(whileStmtNode->body, indent+1);
			}
        } else if (auto forStmtNode = std::dynamic_pointer_cast<ForStatementNode>(stmtNode)) {
        	// Interprete For Statements.
			run(forStmtNode->init, indent + 1);
        	while (trueOrFalse(evaluateExpression(forStmtNode->condition).value)) { // TODO: CHECK
				run(forStmtNode->body, indent+1);
        		run(forStmtNode->increment, indent + 1);
			}
        } else if (auto iptStmtNode = std::dynamic_pointer_cast<InputStatementNode>(stmtNode)) {
        	// Interprete Input Statements.
        	std::cin >> variables[iptStmtNode->varName].value; // TODO: NEED MORE TYPE GETS
		} else if (auto optStmtNode = std::dynamic_pointer_cast<OutputStatementNode>(stmtNode)) {
			// Interprete Output Statements.
			std::cout << evaluateExpression(optStmtNode->content).value; // TODO: NEED MORE CHANGES
		}
    }
}

#endif

#include <iostream>
#include <sstream>

int main() {
	
	// 1 语义分析(分析每一个Token的意思)
    Lexer lexer(input);
    
    // 2 语法分析(构建语法树)
    Parser parser(lexer);
    std::shared_ptr<ProgramNode> program = parser.parse();
    
    // 3 解释运行(遍历语法树,实现每一条语句的运行)
    Interpreter interpreter;
    interpreter.run(program);
	
    return 0;
}

// # Synth 1.0.0 文档 单文件版

// 本语言面向对象,分为表达式和语句。

// 事先声明,在下文中语句格式中,无论怎么修改空白字符,都不影响程序的效果。因为本语言以 `;` 分隔语句,而不是 `<next_line>` 或者 `<space>`。

// # 语句
// 大致分为这几种类型的语句。

// > 每种语句后面括号内的是语句在解释器代码语法树中的名称。

// - 代码块(`CodeBlockStatement`)
// - 声明和定义
//   - 变量声明语句(`VarDeclarationStatement`)
// - 控制
//   - 流程型语句
//     - `if-else` 语句(`IfStatement`)
//   - 循环型语句
//     - `while` 语句(`WhileStatement`)
//     - `for` 语句(`ForStatement`)
// - 使用或修改
//   - 变量修改语句(`AssignmentStatement`)

// ## 代码块(`CodeBlockStatement`)
// 代码块是一种特殊的语句。以 `{` 开头 `}` 结尾。

// 下面是代码块语句的格式:

// ```sy
// {
//     <Some Other Statements>
// }
// ```

// 尽管代码块经常被用作其他别的**控制型语句**的附庸,但是并不是说这个语句不能单独使用。代码块单独使用时通常用来限制变量的作用域。

// ## 声明和定义
// ### 变量声明语句(`VarDeclarationStatement`)

// 以 `var` 关键字打头的是变量声明语句。这个语句通常用来声明一个变量。

// 下面是变量声明语句的格式:

// ```sy
// var(<Var Type>) <Var Name>;
// ```

// 其中 `<Var Type>` 是变量的类型,`<Var Name>` 是变量的名称。

// 我们可以在声明变量的时候就给变量赋值。

// ```sy
// var(<Var Type>) <Var Name> = <Var Value>;
// ```

// 当然。如果觉得每次都指定变量类型太麻烦,可以像弱类型一样让解释器自动推断类型:

// ```sy
// var <Var Name> = <Var Value>;
// ```

// 这个功能是 `Synth 1.2.0` 以后的功能。与弱类型语言不同,请务必在使用这种语法的时候指定初始值,不然解释器将无法正常推导变量类型。例如:

// ```sy
// var <Var Name>;
// ```

// 会引发严重错误。

// 另外,请务必在使用变量前声明变量。这与 `JavaScript` 和 `Python` 等语言不同。

// ## 控制
// ### 流程型语句
// #### `if-else` 语句(`IfStatement`)
// 这种语句用于在某种条件下才执行需要执行的语句。

// 格式如下:

// ```sy
// if (<Expression>) <ThenBlock: CodeBlockStatement>
// else <ElseBlock: CodeBlockStatement>
// ```

// 其中 `<Expression>` 指要满足的条件表达式。如果表达式成立,则执行 `<ThenBlock: CodeBlockStatement>` 中的语句。否则执行 `<ElseBlock: CodeBlockStatement>` 中的语句。

// 特别的,`else` 及其后面的内容不是必须的。也就是说,可以在不满足条件的时候什么都不做。

// 请务必保证 `<ThenBlock: CodeBlockStatement>` 和 `<ElseBlock: CodeBlockStatement>` 都是代码块。这与 `C/C++` 等语言不同。

// ### 循环型语句
// #### `while` 语句(`WhileStatement`)
// 这种语句用于在某条件成立的情况下不停执行某些语句。

// 下面是 `while` 语句的格式:

// ```sy
// while (<Expression>) <body: CodeBlockStatement>
// ```

// 如果 `<Expression>` 成立,则不断执行 `<body: CodeBlockStatement>` 中的内容,直到 `<Expression>` 不成立。

// 请务必保证 `<body: CodeBlockStatement>` 是代码块。这与 `C/C++` 等语言不同。

// #### `for-iid` 语句(`ForStatement`)
// 这种语句用于在某条件成立的情况下不停执行某些语句。他和 `while` 语句的区别在于提供了一个循环前初始化的语句填写处和每次执行完毕要执行的语句做的中间处理语句。

// 下面是 `for-iid` 语句的格式:

// ```sy
// for (<InitializeStatement>;<Expression>;<MiddleStatement>) <body: CodeBlockStatement>
// ```

// 先执行 `<InitializeStatement>` 语句。之后如果 `<Expression>` 成立,则不断执行 `<body: CodeBlockStatement>` 中的内容,然后执行 `MiddleStatement`。直到 `<Expression>` 不成立。

// 请务必保证 `<body: CodeBlockStatement>` 是代码块。这与 `C/C++` 等语言不同。

// ### 使用型语句
// #### 变量赋值语句(`AssignmentStatement`)
// 用于给已经声明的变量赋值。

// 格式:

// ```sy
// <Var Name> = <Expression>;
// ```

// 把名为 `<Var Name>` 的变量的值改为 `<Expression>` 的值。