Assignment 1, csc431, Spring 2018
1 Goal
Develop a compiler for a simple language with straight-line variable declarations.
2 Repo Creation
https://classroom.github.com/g/hDXd8I8-
3 Language
Our language for the first milestone will be a (very very small) subset of the "Mini" language described by Professor Keen in his course materials. Here’s the EBNF for our restricted language:
| ‹program› | ::= | ‹mainfunction› |
| ‹mainfunction› | ::= | fun main ( ) int { ‹declaration›* ‹assignment›* ‹ret› } |
| ‹declaration› | ::= | int ‹id-list› ; |
| ‹id-list› | ::= | ‹id› {, ‹id›}* |
| ‹assignment› | ::= | ‹id› = ‹expression› ; |
| ‹ret› | ::= | return ‹expression› ; |
| ‹expression› | ::= | ‹term› {{+ | -} ‹term›}* |
| ‹term› | ::= | ‹unary› {{* | /} ‹unary›}* |
| ‹unary› | ::= | -* ‹factor› |
| ‹factor› | ::= | ( ‹expression› ) | ‹id› | ‹number› |
This grammar assumes existing definitions for the ‹id› and ‹number› nonterminals.
So, for instance, you might write
fun main () int { |
int w,x,y,z; |
x = 3+4; |
y = x+(4/3); |
return x+y; |
} |
Since this syntax is a subset of the "Mini" language, I would encourage you to use the parser provided for that language. It can produce an AST directly if you’re working in one of the languages that Antlr supports, and can generate JSON if you’re not.
For this assignment, we’re assuming a "C"-like semantics for arithmetic, where division denotes integer division, and overflows lead to unspecified behavior.
It’s an error to use an uninitialized or undeclared variable, and your program must signal an error in these cases.
It’s fine to declare a variable more than once in the same block, as long as it’s given the same type each time.
4 Compilation Strategy
Your compiler should follow these steps:
Parse, to produce an AST,
check that all used variables are declared,
check that no variables are used before initialization,
convert to A-normal form as discussed in lecture,
generate assembly, and
compile and link the assembly with the given C wrapper.
5 Deliverables
Your repo should contain a README indicating how to compile the compiler. This should produce a "consieuten" executable.
After this, calling
consieuten <file.co> |
should produce a compiled executable named "a.out" in the current directory.
6 Testing Plan
For the purposes of evaluation, we’re breaking down the functionality into six separate "tiers". Each one is worth a fraction of the overall points for correctness, as follows:
(4 pts) return a constant: return 8;
(4 pts) return a simple binop, e.g. return 3+8;, return 18 / 5;, etc.
- (2 pts) bindings for constants, e.g.
x = 3;
y = 4;
return x+y;
- (2 pts) bindings to simple binops, e.g.
a = 3;
b = a + 4;
c = b/a;
return a*c;
- (2 pts) nested binops, all correct programs, e.g.
a = 6+(8/2);
b = a + (a*7) + 8;
return a+(2*b);
(2 pts) all error checking