Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AST interpreter?

I have an AST (abstract syntax tree) and now i want to test my compiler by giving it 2 or more numbers and expect an output with the result of math operations (like a calculator).

My question is, what is the best way to build the interpreter? The visiting of the AST nodes is recursive, so i don't know how many encapsulated calculations exists until i get to the end of the tree. But since this is done iteration by iteration, how can i make all the operations in the end?

Thank you

like image 298
Nitrate Avatar asked May 11 '12 16:05

Nitrate


People also ask

What is AST interpreter?

An AST interpreter interprets an Abstract Syntax Tree (AST) produced by a Syntax Analyzer. Compiler/AST interpreter. You are encouraged to solve this task according to the task description, using any language you may know.

What is an AST programming?

An Abstract Syntax Tree, or AST, is a tree representation of the source code of a computer program that conveys the structure of the source code. Each node in the tree represents a construct occurring in the source code.

What does AST mean in python?

Source code: Lib/ast.py. The ast module helps Python applications to process trees of the Python abstract syntax grammar. The abstract syntax itself might change with each Python release; this module helps to find out programmatically what the current grammar looks like.

Is AST native to python?

ast is a module in the python standard library. Python codes need to be converted to an Abstract Syntax Tree (AST) before becoming “byte code”(. pyc files). Generating AST is the most important function of ast, but there are more ways one can use the module.


1 Answers

Intepreters are pretty easy to code, once you have an AST:

 int interpret(tree t)
 { /* left to right, top down scan of tree */
   switch (t->nodetype) {
     case NodeTypeInt:
        return t->value;
     case NodeTypeVariable:
        return t->symbtable_entry->value
     case NodeTypeAdd:
        { int leftvalue= interpret(t->leftchild);
          int rightvalue= interpret(t->rightchild);
          return leftvalue+rightvalue;
        }
     case NodeTypeMultiply:
        { int leftvalue= interpret(t->leftchild);
          int rightvalue= interpret(t->rightchild);
          return leftvalue*rightvalue;
        }
     ...
     case NodeTypeStatementSequence: // assuming a right-leaning tree
        { interpret(t->leftchild);
          interpret(t->rightchild);
          return 0;
        }
     case NodeTypeAssignment:
        { int right_value=interpret(t->rightchild);
          assert: t->leftchild->Nodetype==NodeTypeVariable;
          t->leftchild->symbtable_entry->value=right_value;
          return right_value;
        }
     case NodeTypeCompareForEqual:
        { int leftvalue= interpret(t->leftchild);
          int rightvalue= interpret(t->rightchild);
          return leftvalue==rightvalue;
        }
     case NodeTypeIfThenElse
        { int condition=interpret(t->leftchild);
          if (condition) interpret(t->secondchild);
          else intepret(t->thirdchild);
          return 0;
     case NodeTypeWhile
        { int condition;
          while (condition=interpret(t->leftchild))
                interpret(t->rightchild);
          return 0;

     ...
   }
 }

What's annoying to do is "goto", because this changes the point of attention of the interpreter. To implement goto or function calls, one has to search the tree for the label or the function declaration, and continue execution there. [ One can speed this up by prescanning the tree and collecting all the label locations/function declarations in a lookup table. This is the first step towards building a compiler.] Even this isn't quite enough; you have to adjust the recursion stack, which we hid in function calls so it isn't easy to do. If one converts this code to a iterative loop with an explicitly managed recursion stack, it is a lot easier to fix up the stack.

like image 120
Ira Baxter Avatar answered Sep 30 '22 19:09

Ira Baxter