Compiler for the PCL Language written in Python.
This is part of the semester assignment for Compilers course taught in ECE NTUA (Spring 2018-2019).
This compiler would have never been born without the orderly contributions of its authors
- Marios Papachristou (papachristoumarios)
- Ioannis Daras (giannisdaras)
PCL is a imperative programming language based on a proper subset of ISO PASCAL, among with some changes. The basic characteristics of PCL include:
- Syntax similar to PASCAL
- Structured functions similar to PASCAL
- Basic data types for integers and real numbers, booleans and characters
- Arrays of fixed or variable size
- Built-in function library
The complete PCL specification is available under docs/pcl2019.pdf
(in Greek).
The compiler comes with a Makefile
for installation. Install it via
make depend
make compiler
Please note that PCL compiler requires Python >=3.6 to work since it has metaprogramming features (due to SLY) to specify lexers and parsers. Older versions won't work.
After you have set up PCL you can use the pclc.py
executable of the PCL compiler.
You can display the usage of pclc.py
via
pclc.py --help
The pcl
executable allows the use of its constituent parts independently. Such parts include
- The lexer
- The parser
- The semantic analyzer
- The codegen module
For instance assume that you have the following PCL program under example.pcl
program dummmy;
var x: integer;
begin
x := 0;
while x < 10 do
begin
writeInteger(x);
writeChar('\n');
x := x + 1;
end;
end.
which prints the numbers 0 to 9. Running
pclc.py example.pcl
will produce IR code at example.imm
, the object file at example.o
and the final (linked) executable at example.out
. If you specify the flag -i
then the program should be read from stdin
and the IR will be emitted to stdout
. So the PCL compiler should be called as
pclc.py -i <example.pcl >example.imm
If one wants to create an object file, he could use UNIX pipes
pclc.py -i <example.pcl | llc -filetype=obj >example.o
Compiling and linking the final can be separately done with the use of gcc
. If one wants static linking with the pcl/builtins.h
library then one should use
gcc -Wall -Werror -fpic -lm example.o /path/to/builtins.c/builtins.c -o example.out
Note that builtins depend on stdio.h
and math.h
so the flag -lm
is used to do dynamic linking with the math library. If one wants to perform dynamic linking with pcl/libbuiltins.so
one should use
gcc -Wall -Werror -fpic -lm -L/path/to/libbuiltins.so -lbuiltins example.o -o example.out
Again, if one wants to use pipes, it is possible via the -x
option as
pclc.py -i <example.pcl | llc -filetype=obj | gcc -Wall -Werror -fpic -lm -L/path/to/libbuiltins.so -lbuiltins -o example.out -x -
The pclc.py
executable produces verified LLVM code, throwing an exception otherwise. Successful compilation exits with code 0.
Furthermore one can specify optimization flags using the -O
argument. More specifically the acceptable values are 0, 1 and 2 according to the LLVM Reference for PassManagerBuilder
. For a complete and fathomable list on the LLVM optimizations performed by the optimizer, we redirect the interested reader to this StackOverflow thread.
For testing individual parts of the compiler, one has to specify the --pipeline
argument as a list containing a subset of the following (in correct order) arguments:
lex
to invoke the lexerparse
to invoke the parsersem
to invoke the semantic analyzercodegen
to invoke the codegen modulepprint
to print the (annotated) AST to stdout.
So in case one wants to do lexical analysis only
pclc.py example.pcl --pipeline lex pprint
to get the tokens to stdout. If one wants to do lexing, parsing and semantic analysis (type checking, label checking) and get the types of the compatible AST nodes.
pclc.py example.pcl --pipeline lex parse sem pprint
More information on the design of the current compiler can be found at the wiki.
This implementation of PCL is developed using the Python language and the following meta-programs
If you want to contribute to the project, please submit a pull request.
The PCL documentation is located at docs/
and the wiki.
You can generate the API docs from the docstrings via
pydoc pcl.submodule
where submodule
is one of the submodules inside pcl/
.
The PCL Language comes with tests built-in for every "independent" part of the compiler. The tests are located in the tests/
directory and the examples used in the examples/
directory. You will need pytest
to run them. You can run the tests via
make test
If you want to dive deeper into our compiler we advise you study the following references
- Ullman, Jeffrey D., and Alfred V. Aho. "Principles of compiler design." Reading: Addison Wesley (1977).
- Skordalakis, Manolis, and Papaspyrou, Nikolaos. "Compilers". Symmetria Publications (2003 - in Greek).
- PCL Specification under
docs/pcl2019.pdf
(in Greek). llvmlite
Reference Manual.SLY
Reference Manual.