In the previous phases of the class project, you used the flex and bison tools to create a lexical analyzer and a parser for the "MINI-L" programming language. In this phase of the class project, you will take a syntactically-correct MINI-L program (a program that can be parsed without any syntax errors), verify that it has no semantic errors, and then generate its corresponding intermediate code. The generated code can then be executed (using a tool we will provide) to run the compiled MINI-L program.
[The MINI-L source-code language is described in detail here (this is the same as for the prior project phases).]
You should perform one-pass code generation and directly output the generated code. There is no need to build/traverse a syntax tree. However, you will need to maintain a symbol table during code generation.
The intermediate code you will generate is called "MIL" code. We will provide you with an
interpreter called mil_run
that can be used to execute the MIL code.
[The MIL intermediate code representation is described in detail here.]
[Download the mil_run
MIL interpreter here.]
The output of your code generator will be a file containing the generated MIL code. If any semantic errors are encountered by the code generator, then appropriate error messages should be emitted and no other output should be produced.
[The required output format for your code generator is described here.]
mil_run
MIL interpreter
We are providing an interpreter for MIL intermediate code (mil_run), which can be
used to execute the MIL code generated by your code generator. The mil_run
interpreter requires an input file to be specified that contains the MIL code that should be executed. For
example, if you have MIL code contained in a file called mil_code.mil
, then
you can execute the MIL code with the following command:
mil_run mil_code.mil
If the MIL code itself requires some input data, this input data can be written to a file
and then redirected to the executing MIL code. For example, if the input values are
written to a text file called input.txt
, then it can be passed to the
executing MIL program as follows:
mil_run mil_code.mil < input.txt
The mil_run
interpreter will generate a file called milRun.stat
that contains some statistics about the MIL code that was just executed. You may
ignore this file.
mil_run
makes the following assumptions.
You must ensure that your generated MIL code meets the above three requirements.
mil_run
is a linux executable and can be run on bolt.
mil_run
MIL interpreter to test your implementation.
For each program written in MINI-L source code, compile it down to MIL code using
your implementation. Then invoke the MIL code using mil_run
to verify
that the compiled program behaves as expected.
There are some errors that cannot always be captured at compile-time and may only
happen at run-time. These errors include those such as array index out-of-bounds
errors, and division by zero. Your implementation need not handle these errors.
You may assume that when we grade your programs, we will not use any MINI-L programs
that would lead to run-time errors. Note also that the mil_run
MIL interpreter
we are providing may have unexpected behavior if you try to run it on a program
that can lead to run-time problems (such as an out-of-bounds array access).
Thus, when you are testing your implementation, try to make sure your MINI-L programs
will not cause any run-time errors.
Suppose your code generator is in the executable named my_compiler
. Then for
the MINI-L program fibonacci.min (which is syntactically and semantically
correct), your code generator should be invoked as follows:
cat fibonacci.min | my_compiler
The file fibonacci.mil should then be created and should contain the generated MIL code
(it is okay if your generated code looks slightly different, but it should have the same behavior when executed).
Next, you can test your generated code using the mil_run
MIL interpreter to ensure that
it behaves as expected. Suppose we want to run the compiled fibonacci
program with input "5":
echo 5 > input.txt
mil_run fibonacci.mil < input.txt
When the compiled fibonacci
program is executed with the above input "5", then the fifth fibonacci number is printed to the screen:
cat twosum.min | my_compiler
The file twosum.mil should then be created and should contain the generated MIL code
(it is okay if your generated code looks slightly different, but it should have the same behavior when executed).
Next, you can test your generated code using the mil_run
MIL interpreter to ensure that
it behaves as expected. Suppose we want to run the compiled twosum
program with input "123 456":
echo "123 456" > input.txt
mil_run twosum.mil < input.txt
When the compiled twosum
program is executed with the above input "123 456", then the sum of 123 and 456 is printed to the screen:
579