The parser builds a parse tree. This language supports assignment statements, function declarations, and print statements. Identifiers are essentially declared by being assigned to. There are conditional expressions, and function invocations, but no control statements. Notice that I no longer separate out Boolean expressions from other expressions. Attempting to use the grammar definition to perform type checking does not work very well in general. The equivalent of a loop must be implemented by recursion, in the style of a functional language. Our information on what is declared is now more complex, due to the fact that formal parameters are local to the function body of a function declaration. In fact we can never get more than two levels of scope, because we cannot declare functions inside function declarations. However, in a full language, it is possible to have multiple scope levels. The constructs that look like if statements are in fact expressions, and return values. The code for other kinds of expressions is similar to those in the previous examples. Function declarations create an entry in the environment table, with a mapping from the function identifier to a "function value". A function value is composed of the names of the formal parameters, the code for the body of the function (just an expression, in this simple language), and a reference to the environment in which the function was declared, since it is the variables and functions in this environment that are referred to by identifiers not corresponding to formal parameters.