Esempio n. 1
0
void printAST(struct ast_node *node){
	int i;
	struct set_iterator si;
	int value;

	if(node->leafNumber >= 0){
		printf("%d: nullable:[%s] ", node->leafNumber, node->nullable ? "YES" : "NO");
		printf("firstpos:[ ");
		si = setIterator(node->firstpos);
		while(nextSetItem(&si, &value)){
			printf("%d ", value);
		}
		printf("] lastpos:[ ");
		si = setIterator(node->lastpos);
		while(nextSetItem(&si, &value)){
			printf("%d ", value);
		}
		printf("] followpos:[ ");
		si = setIterator(node->followpos);
		while(nextSetItem(&si, &value)){
			printf("%d ", value);
		}
		printf("]\n");
	}
	if(node->child0){
		printAST(node->child0);
	}
	if(node->child1){
		printAST(node->child1);
	}
}
Esempio n. 2
0
// Pretty-prints a lisp AST
std::string printAST(Node ast, bool printMetadata) {
    if (ast.type == TOKEN) return ast.val;
    std::string o = "(";
    if (printMetadata) {
         o += ast.metadata.file + " ";
         o += unsignedToDecimal(ast.metadata.ln) + " ";
         o += unsignedToDecimal(ast.metadata.ch) + ": ";
    }
    o += ast.val;
    std::vector<std::string> subs;
	for (unsigned i = 0; i < ast.args.size(); i++) {
        subs.push_back(printAST(ast.args[i], printMetadata));
    }
	unsigned k = 0;
    std::string out = " ";
    // As many arguments as possible go on the same line as the function,
    // except when seq is used
    while (k < subs.size() && o != "(seq") {
		if (subs[k].find("\n") != std::string::npos || (out + subs[k]).length() >= 80) break;
        out += subs[k] + " ";
        k += 1;
    }
    // All remaining arguments go on their own lines
    if (k < subs.size()) {
        o += out + "\n";
        std::vector<std::string> subsSliceK;
		for (unsigned i = k; i < subs.size(); i++) subsSliceK.push_back(subs[i]);
        o += indentLines(joinLines(subsSliceK));
        o += "\n)";
    }
    else {
        o += out.substr(0, out.size() - 1) + ")";
    }
    return o;
}
Esempio n. 3
0
/* print tree */
void printAST(ASTTREE tree)
{
    if(tree)
    {

        printf("[%p] NodeType=%s, ival=%d, type=", tree, humanReadableState(tree->typeNoeud), tree->ival);
        if(tree->type == NULL) printf("NULL");
        else printf("%s",tree->type);
        printf(" sval =");
        if (tree->sval == NULL) printf("NULL");
        else printf("'%s'", tree->sval);
        printf(", up=%p, down=%p, left=%p, right=%p, numLine =%d\n", tree->up, tree->down, tree->left, tree->right,tree->numLine);
        printAST(tree->up);
        printAST(tree->down);
        printAST(tree->left);
        printAST(tree->right);
    }
}
Esempio n. 4
0
void printAST(is_node* node, int tabs)
{	
	if(node->type != NoNode)
	{	
		int i;
		for(i = 0; i < tabs; i++)
			printf("  ");

		if(node->id)
			printf("%s(%s)\n", types[node->type], node->id);
		else
			printf("%s\n", types[node->type]);
	}

	if(node->child)
		printAST(node->child, tabs + 1);
	
	if(node->next)
		printAST(node->next, tabs);
}
Esempio n. 5
0
  void ClangInternalState::store() {
    // Cannot use the stack (private copy ctor)
    llvm::OwningPtr<llvm::raw_fd_ostream> m_LookupTablesOS;
    llvm::OwningPtr<llvm::raw_fd_ostream> m_IncludedFilesOS;
    llvm::OwningPtr<llvm::raw_fd_ostream> m_ASTOS;
    llvm::OwningPtr<llvm::raw_fd_ostream> m_LLVMModuleOS;
    llvm::OwningPtr<llvm::raw_fd_ostream> m_MacrosOS;

    m_LookupTablesOS.reset(createOutputFile("lookup",
                                            &m_LookupTablesFile));
    m_IncludedFilesOS.reset(createOutputFile("included",
                                             &m_IncludedFilesFile));
    m_ASTOS.reset(createOutputFile("ast", &m_ASTFile));
    m_LLVMModuleOS.reset(createOutputFile("module", &m_LLVMModuleFile));
    m_MacrosOS.reset(createOutputFile("macros", &m_MacrosFile));

    printLookupTables(*m_LookupTablesOS.get(), m_ASTContext);
    printIncludedFiles(*m_IncludedFilesOS.get(), 
                       m_ASTContext.getSourceManager());
    printAST(*m_ASTOS.get(), m_ASTContext);
    printLLVMModule(*m_LLVMModuleOS.get(), m_Module);
    printMacroDefinitions(*m_MacrosOS.get(), m_Preprocessor);
  }
Esempio n. 6
0
int main(int argc, char* argv[]) {
  if (argc != 2) { 
    fprintf(stderr, "usage: %s <filename>\n", argv[0]);
    exit(1);
  }
  
  char pgm[120];
  strcpy(pgm, argv[1]);
  if (strchr(pgm, '.') == NULL)
    strcat(pgm, ".cm");
    
  source = fopen(pgm, "r");
  if (source == NULL) { 
    fprintf(stderr, "File %s not found\n", pgm);
    exit(1);
  }
  
  listing = stdout;
  
#if NO_PARSE
  while (getToken() != ENDFILE);
#else
  ASTNode* root = parse();
  if (TraceParse) {
    fprintf(listing,"\nSyntax tree:\n");
    printAST(root);
  }
#endif
  if (!Error) {
    int fnlen = strcspn(pgm,".");
    char* codefile = (char *) calloc(fnlen+1, sizeof(char));
    strncpy(codefile,pgm,fnlen);
    codeGen(root, codefile);
  }
  fclose(source);
  return 0;
}
Esempio n. 7
0
int main(int argv, char** argc) {
    if (argv == 1) {
        std::cerr << "Must provide a command and arguments! Try parse, rewrite, compile, assemble\n";
        return 0;
    }
    std::string flag = "";
    std::string command = argc[1];
    std::string input;
    std::string secondInput;
    if (std::string(argc[1]) == "-s") {
        flag = command.substr(1);
        command = argc[2];
        input = "";
        std::string line;
        while (std::getline(std::cin, line)) {
            input += line + "\n";
        }
        secondInput = argv == 3 ? "" : argc[3];
    }
    else {
        if (argv == 2) {
            std::cerr << "Not enough arguments for serpent cmdline\n";
            throw(0);
        }
        input = argc[2];
        secondInput = argv == 3 ? "" : argc[3];
    }
    bool haveSec = secondInput.length() > 0;
    if (command == "parse" || command == "parse_serpent") {
        std::cout << printAST(parseSerpent(input), haveSec) << "\n";
    }
    else if (command == "rewrite") {
        std::cout << printAST(rewrite(parseLLL(input, true)), haveSec) << "\n";
    }
    else if (command == "compile_to_lll") {
        std::cout << printAST(compileToLLL(input), haveSec) << "\n";
    }
    else if (command == "build_fragtree") {
        std::cout << printAST(buildFragmentTree(parseLLL(input, true))) << "\n";
    }
    else if (command == "compile_lll") {
        std::cout << binToHex(compileLLL(parseLLL(input, true))) << "\n";
    }
    else if (command == "dereference") {
        std::cout << printAST(dereference(parseLLL(input, true)), haveSec) <<"\n";
    }
    else if (command == "pretty_assemble") {
        std::cout << printTokens(prettyAssemble(parseLLL(input, true))) <<"\n";
    }
    else if (command == "pretty_compile_lll") {
        std::cout << printTokens(prettyCompileLLL(parseLLL(input, true))) << "\n";
    }
    else if (command == "pretty_compile") {
        std::cout << printTokens(prettyCompile(input)) << "\n";
    }
    else if (command == "assemble") {
        std::cout << assemble(parseLLL(input, true)) << "\n";
    }
    else if (command == "serialize") {
        std::cout << binToHex(serialize(tokenize(input, Metadata(), false))) << "\n";
    }
    else if (command == "flatten") {
        std::cout << printTokens(flatten(parseLLL(input, true))) << "\n";
    }
    else if (command == "deserialize") {
        std::cout << printTokens(deserialize(hexToBin(input))) << "\n";
    }
    else if (command == "compile") {
        std::cout << binToHex(compile(input)) << "\n";
    }
    else if (command == "encode_datalist") {
        std::vector<Node> tokens = tokenize(input);
        std::vector<std::string> o;
        for (int i = 0; i < (int)tokens.size(); i++) {
            o.push_back(tokens[i].val);
        }
        std::cout << binToHex(encodeDatalist(o)) << "\n";
    }
    else if (command == "decode_datalist") {
        std::vector<std::string> o = decodeDatalist(hexToBin(input));
        std::vector<Node> tokens;
        for (int i = 0; i < (int)o.size(); i++)
            tokens.push_back(token(o[i]));
        std::cout << printTokens(tokens) << "\n";
    }
    else if (command == "tokenize") {
        std::cout << printTokens(tokenize(input));
    }
    else if (command == "biject") {
        if (argv == 3)
             std::cerr << "Not enough arguments for biject\n";
        int pos = decimalToUnsigned(secondInput);
        std::vector<Node> n = prettyCompile(input);
        if (pos >= (int)n.size())
             std::cerr << "Code position too high\n";
        Metadata m = n[pos].metadata;
        std::cout << "Opcode: " << n[pos].val << ", file: " << m.file << 
             ", line: " << m.ln << ", char: " << m.ch << "\n";
    }
}
Esempio n. 8
0
void printAST(AST_node root, int lev)
{
    std::string *space = new std::string(lev, '\t');
    if (root != NULL)
    {
        switch (root->ast_type)
        {
        case TERMINAL:
            std::cout << *space << "Terminal\t" << root->lex_symbol << "\t";
            if (root->lex_symbol == NUM)
            {
                std::cout << root->val.value << std::endl;
            }
            else
            {
                std::cout << *(root->val.ident) << std::endl;
            }
            break;
        case CONSTDECL:
            std::cout << *space << "ConstDecl" << std::endl;
            break;
        case PROGRAM:
            std::cout << *space << "Program" << std::endl;
            break;
        case CONSTDEF:
            std::cout << *space << "ConstDef" << std::endl;
            break;
        case CONST:
            std::cout << *space << "Const" << std::endl;
            break;
        case VAR:
            std::cout << *space << "VAR" << std::endl;
            break;
        case VARDECL:
            std::cout << *space << "VarDecl" << std::endl;
            break;
        case VARDEF:
            std::cout << *space << "VarDef" << std::endl;
            break;
        case PRODECL:
            std::cout << *space << "Procedure Declaration" << std::endl;
            break;
        case PROHEAD:
            std::cout << *space << "Procedure Head Declaration" << std::endl;
            break;
        case FUNDECL:
            std::cout << *space << "Function Declaration" << std::endl;
            break;
        case FUNHEAD:
            std::cout << *space << "Function Head Declaration" << std::endl;
            break;
        case ARGLIST:
            std::cout << *space << "Arglist" << std::endl;
            break;
        case ARGS:
            std::cout << *space << "Args" << std::endl;
            break;
        case EXPRESSION:
            std::cout << *space << "Expression" << std::endl;
            break;
        case CONDITION:
            std::cout << *space << "Condition" << std::endl;
            break;
        case TERM:
            std::cout << *space << "Term" << std::endl;
            break;
        case FACTOR:
            std::cout << *space << "Factor" << std::endl;
            break;

        default:
            break;
        }
        if (root->children->size() == 0)
        {
            return;
        }
        for (std::vector<AST_node>::iterator i = root->children->begin(); i != root->children->end(); i++)
        {
            printAST(*i, lev + 1);
        }
    }
    return;
}
Esempio n. 9
0
int main(int argc, const char* argv[]) {
  try {
    TCLAP::CmdLine cmd("Xylene", ' ', "pre-release");
    
    TCLAP::SwitchArg asXML("", "xml", "Read file using the XML parser", cmd);
    
    TCLAP::SwitchArg printTokens("", "tokens", "Print token list", cmd);
    TCLAP::SwitchArg printAST("", "ast", "Print AST (if applicable)", cmd);
    TCLAP::SwitchArg printIR("", "ir", "Print LLVM IR (if applicable)", cmd);
    
    TCLAP::SwitchArg doNotParse("", "no-parse", "Don't parse the token list", cmd);
    TCLAP::SwitchArg doNotRun("", "no-run", "Don't execute the AST", cmd);
    
    std::vector<std::string> runnerValues {"llvm-lli", "llvm-llc"};
    TCLAP::ValuesConstraint<std::string> runnerConstraint(runnerValues);
    TCLAP::ValueArg<std::string> runner("r", "runner", "How to run this code", false,
      "llvm-lli", &runnerConstraint, cmd, nullptr);
    
    TCLAP::ValueArg<std::string> code("e", "eval", "Code to evaluate", false,
      std::string(), "string", cmd, nullptr);
    TCLAP::ValueArg<std::string> filePath("f", "file", "Load code from this file",
      false, std::string(), "path", cmd, nullptr);
    cmd.parse(argc, argv);
    
    if (code.getValue().empty() && filePath.getValue().empty()) {
      TCLAP::ArgException arg("Must specify either option -e or -f");
      cmd.getOutput()->failure(cmd, arg);
    }
    
    std::unique_ptr<AST> ast;
    
    if (asXML.getValue()) {
      if (doNotParse.getValue()) return NORMAL_EXIT;
      if (filePath.getValue().empty()) {
        TCLAP::ArgException arg("XML option only works with files");
        cmd.getOutput()->failure(cmd, arg);
      }
      ast = std::make_unique<AST>(XMLParser().parse(rapidxml::file<>(filePath.getValue().c_str())).getTree());
    } else {
      std::string input;
      if (!filePath.getValue().empty()) {
        std::ifstream file(filePath.getValue());
        std::stringstream buffer;
        buffer << file.rdbuf();
        input = buffer.str();
      } else {
        input = code.getValue();
      }
      
      auto lx = Lexer();
      lx.tokenize(input, filePath.getValue().empty() ? "<cli-eval>" : filePath.getValue());
      if (printTokens.getValue()) for (auto tok : lx.getTokens()) println(tok);
      
      if (doNotParse.getValue()) return NORMAL_EXIT;
      ast = std::make_unique<AST>(TokenParser().parse(lx.getTokens()).getTree());
    }
    
    if (printAST.getValue()) ast->print();
    if (doNotRun.getValue()) return NORMAL_EXIT;
    
    CompileVisitor::Link v = CompileVisitor::create("Command Line Module", *ast);
    v->visit();
    if (printIR.getValue()) v->getModule()->dump();
        
    if (runner.getValue() == "llvm-lli") {
      return Runner(v).run();
    } else if (runner.getValue() == "llvm-llc") {
      println("Not yet implemented!");
      // TODO
    }
  } catch (const TCLAP::ExitException& arg) {
    return CLI_ERROR;
  } catch (const TCLAP::ArgException& arg) {
    println("TCLAP error", arg.error(), "for", arg.argId());
    return TCLAP_ERROR;
  } catch (const Error& err) {
    println(err.what());
    return USER_PROGRAM_ERROR;
  }
  // If we're debugging, crash the program on InternalError
  #ifndef CRASH_ON_INTERNAL_ERROR
  catch (const InternalError& err) {
    println(err.what());
    return INTERNAL_ERROR;
  }
  #endif
  return 0;
}
Esempio n. 10
0
int main(int argc, char** argv)
{

	////////////////Basic Printing/////////////////////////
	//printf("Submitted by Batch No. 06:\n%30s\t(%s)\n%30s\t(%s)\n\n\n", "Abhinav Bhatia", "2011A7PS371P", "Mukul Bhutani ", "2011A7PS343P");
	
	printf("LEVEL %d: %s", 3, "AST/Symbol Table/Type checking/Symantic Rules modules work\n");
	printf("Code generation implemented for most constructs\n\n");
	////////////////Basic Printing End/////////////////////

	FILE* pSourceFile = NULL;
	int choice;
	int isParsed = PARSER_NOT_INVOKED;


	if (argc > 1)
	{
		pSourceFile = fopen(argv[1], "r");
	}
	else if (argc == 1)
	{
		printf("\nLess number of arguments ...Two arguments required....\n");
		printf("1. Source Code File.\n");
		printf("2. File for printing parse tree.\n");

		char c;
		scanf("%c", &c);
		return 0;
	}

	if (pSourceFile == NULL)
	{
		printf("\nError: No Input File!\nExiting...........");
		char c;
		scanf("%c", &c);
		return -1;
	}

	FILE* pKeywordsFile = fopen(KEYWORDS_INPUT_FILENAME, "r");
	if (!pKeywordsFile)
	{
		printf("\nError: keywords file \"%s\" not found.\nExiting..........", KEYWORDS_INPUT_FILENAME);
		char c;
		scanf("%c", &c);
		return -1;
	}
	FILE* grammarInputFile = fopen(GRAMMAR_INPUT_FILENAME, "r");
	if (!grammarInputFile)
	{
		printf("\nError: Grammar file \"%s\" not found.\nExiting..........", GRAMMAR_INPUT_FILENAME);
		char c;
		scanf("%c", &c);
		return -1;
	}
	FILE* astRulesFile = fopen(AST_RULES_FILENAME, "r");
	if (!astRulesFile)
	{
		printf("\nError: AST Rules file \"%s\" not found.\nExiting..........", AST_RULES_FILENAME);
		char c;
		scanf("%c", &c);
		return -1;
	}

	Parser parser;
	Lexer lex = lexer_createNew(pSourceFile, pKeywordsFile);


	printf("\n\nPlease enter your choice\n");
	printf("1. Print list of tokens.\n");
	printf("2. Verify syntactic correctness of input source code.\n");
	printf("3. Print Abstract Syntax Tree.\n");
	printf("4. Print Symbol Table.\n");
	printf("5. Verify syntactic and semantic correctness.\n");
	printf("6. Produce Assembly Code.\n");
	printf("7. Exit.\n");

	char flushChar;
	scanf("%d%c", &choice, &flushChar);
	switch (choice)
	{
	case 1:
		lexer_runLexicalAnalyses(lex);
		break;
	case 2:
		parser = parser_initialise(grammarInputFile, astRulesFile);

		isParsed = printOnlyParsetree(&parser, lex, DEFAULT_OUTPUT_PARSE_TREE_FILE, isParsed);
		break;
	case 3:
		parser = parser_initialise(grammarInputFile, astRulesFile);
		isParsed = parseOnlySourceCode(&parser, lex);
		if (isParsed == PARSED_SUCCESSFULLY)
		{
			Tree ast = createAst(parser);
			printAST(ast);
		}
		break;
	case 4:
		parser = parser_initialise(grammarInputFile, astRulesFile);
		isParsed = parseOnlySourceCode(&parser, lex);
		if (isParsed == PARSED_SUCCESSFULLY)
		{
			Tree ast = createAst(parser);
			createSymbolTables(ast);
			turnOnReportingSemanticErrors(FALSE);
			typeExtractorandChecker(ast);
			printSymbolTable();
		}
		break;
	case 5:
		parser = parser_initialise(grammarInputFile, astRulesFile);
		isParsed = parseOnlySourceCode(&parser, lex);
		if (isParsed == PARSED_SUCCESSFULLY)
		{
			Tree ast = createAst(parser);
			createSymbolTables(ast);
			printf("\n\nRunning semantic analysis....");
			turnOnReportingSemanticErrors(TRUE);
			if (typeExtractorandChecker(ast))
			{
				printf("\n\nCode compiles successfully..........:)");
			}
		}
		break;
	case 6:
		parser = parser_initialise(grammarInputFile, astRulesFile);
		isParsed = parseOnlySourceCode(&parser, lex);
		if (isParsed == PARSED_SUCCESSFULLY)
		{
			Tree ast = createAst(parser);
			createSymbolTables(ast);
			turnOnReportingSemanticErrors(TRUE);
			if (typeExtractorandChecker(ast))
			{
				printf("\n\nCode compiles successfully..........:)");
				printf("\n\nGenerating Code......");
				FILE* asmm = fopen(argv[2], "w");
				generateCode(ast, asmm);
				printf("\n\nFinished code generation.");
				//Call code generation here
			}
		}
		break;
	case 7:
		return 0;
		break;
	default:
		printf("Invalid Choice...please enter correct choice (1-7)");
		break;
	}

	char c;
	scanf("%c", &c);
	return 0;
}
Esempio n. 11
0
//TODO: Get rid of this
static void printAST(size_t indent, scripting::ASTNode *node)
{
    std::cout << "--------------------------------\n";

    for (size_t i = 0; i < indent; ++i)
    {
        std::cout << "    ";
    }

    switch (node->type)
    {
    case scripting::ASTNode::Assign:
    {
        std::cout << "Assign:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Add:
    {
        std::cout << "Add:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Subtract:
    {
        std::cout << "Subtract:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Multiply:
    {
        std::cout << "Multiply:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Divide:
    {
        std::cout << "Divide:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Modulo:
    {
        std::cout << "Modulo:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Less:
    {
        std::cout << "Less:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Greater:
    {
        std::cout << "Greater:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Equal:
    {
        std::cout << "Equal:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::NotEqual:
    {
        std::cout << "NotEqual:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::LessEqual:
    {
        std::cout << "LessEqual:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::GreaterEqual:
    {
        std::cout << "GreaterEqual:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::BoolAnd:
    {
        std::cout << "BoolAnd:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::BoolOr:
    {
        std::cout << "BoolOr:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::BitAnd:
    {
        std::cout << "BitAnd:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::BitOr:
    {
        std::cout << "BitOr:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::BitXOr:
    {
        std::cout << "BitXOr:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::LeftShift:
    {
        std::cout << "LeftShift:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::RightShift:
    {
        std::cout << "RightShift:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Comma:
    {
        std::cout << "Comma (should not be here):\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::StatementSplit:
    {
        std::cout << "StatementSplit (should not be here):\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::GetMember:
    {
        std::cout << "GetMember:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::GetMethod:
    {
        std::cout << "GetMethod:\n";
        printAST(indent+1, ((scripting::LROpNode *)node)->left);
        printAST(indent+1, ((scripting::LROpNode *)node)->right);
        break;
    }
    case scripting::ASTNode::Call:
    {
        scripting::CallNode *cnode = (scripting::CallNode *)node;
        std::cout << "Call:\n";

        printAST(indent+1, cnode->callable);

        for (size_t i = 0; i < cnode->args.getCount(); ++i)
        {
            printAST(indent+1, cnode->args[i]);
        }
        break;
    }
    case scripting::ASTNode::BoolNot:
    {
        std::cout << "BoolNot:\n";
        printAST(indent+1, ((scripting::SingleOperandNode *)node)->operand);
        break;
    }
    case scripting::ASTNode::BitNot:
    {
        std::cout << "BitNot:\n";
        printAST(indent+1, ((scripting::SingleOperandNode *)node)->operand);
        break;
    }
    case scripting::ASTNode::Class:
    {
        std::cout << "Class:\n";
        printAST(indent+1, ((scripting::SingleOperandNode *)node)->operand);
        break;
    }
    case scripting::ASTNode::Throw:
    {
        std::cout << "Throw:\n";
        printAST(indent+1, ((scripting::SingleOperandNode *)node)->operand);
        break;
    }
    case scripting::ASTNode::Return:
    {
        std::cout << "Return:\n";
        printAST(indent+1, ((scripting::SingleOperandNode *)node)->operand);
        break;
    }
    case scripting::ASTNode::Negate:
    {
        std::cout << "Negate:\n";
        printAST(indent+1, ((scripting::SingleOperandNode *)node)->operand);
        break;
    }
    case scripting::ASTNode::Function:
    {
        std::cout << "Function:\n";

        scripting::FunctionNode *fnode = (scripting::FunctionNode *)node;

        for (size_t i = 0; i < fnode->args.getCount(); ++i)
        {
            for (size_t j = 0; j <= indent; ++j)
            {
                std::cout << "    ";
            }

            std::cout << fnode->args[i].getData() << '\n';
        }

        printAST(indent+1, fnode->body);
        break;
    }
    case scripting::ASTNode::TryExcept:
    {
        std::cout << "TryExcept:\n";

        scripting::TryExceptNode *tenode = (scripting::TryExceptNode *)node;

        printAST(indent+1, tenode->try_);
        printAST(indent+1, tenode->except);
        break;
    }
    case scripting::ASTNode::If:
    {
        std::cout << "If:\n";

        scripting::IfNode *inode = (scripting::IfNode *)node;

        printAST(indent+1, inode->ifCond);
        printAST(indent+1, inode->if_);

        for (size_t i = 0; i < inode->elifs.getCount(); ++i)
        {
            printAST(indent+1, inode->elifConds[i]);
            printAST(indent+1, inode->elifs[i]);
        }

        if (inode->else_ != nullptr)
        {
            printAST(indent+1, inode->else_);
        }
        break;
    }
    case scripting::ASTNode::While:
    {
        std::cout << "While:\n";

        scripting::WhileNode *whileNode = (scripting::WhileNode *)node;

        printAST(indent+1, whileNode->cond);
        printAST(indent+1, whileNode->block);
        break;
    }
    case scripting::ASTNode::Identifier:
    {
        std::cout << "Identifier:\n";

        for (size_t j = 0; j <= indent; ++j)
        {
            std::cout << "    ";
        }

        std::cout << ((scripting::IdentifierNode *)node)->name.getData() << std::endl;
        break;
    }
    case scripting::ASTNode::Integer:
    {
        std::cout << "Integer:\n";

        for (size_t j = 0; j <= indent; ++j)
        {
            std::cout << "    ";
        }

        std::cout << ((scripting::IntegerNode *)node)->value << std::endl;
        break;
    }
    case scripting::ASTNode::Float:
    {
        std::cout << "Float:\n";

        for (size_t j = 0; j <= indent; ++j)
        {
            std::cout << "    ";
        }

        std::cout << ((scripting::FloatNode *)node)->value << std::endl;
        break;
    }
    case scripting::ASTNode::String:
    {
        std::cout << "String:\n";

        for (size_t j = 0; j <= indent; ++j)
        {
            std::cout << "    ";
        }

        std::cout << ((scripting::StringNode *)node)->content.getData() << std::endl;
        break;
    }
    case scripting::ASTNode::Statements:
    {
        std::cout << "Statements:\n";

        scripting::StatementsNode *snode = (scripting::StatementsNode *)node;

        for (size_t i = 0; i < snode->statements.getCount(); ++i)
        {
            printAST(indent+1, snode->statements[i]);
        }
        break;
    }
    case scripting::ASTNode::True:
    {
        std::cout << "True\n";
        break;
    }
    case scripting::ASTNode::False:
    {
        std::cout << "False\n";
        break;
    }
    case scripting::ASTNode::Nil:
    {
        std::cout << "Nil\n";
        break;
    }
    }
}