PA 1: IC Lexical Analysis

Due: 10pm, Wednesday, Sep. 30

Learning Objectives

After this assignment, you will be able to:

Overview

In this programming assignment, you will implement the scanner for your IC compiler. The IC language specification document is available on the course web page. You will write the scanner as a slex spec file: ic.slex, at the root of your repository, declares IC’s tokens as an ordered list of regular-expression rules with action blocks, and slex’s engine applies maximal munch and first-rule-wins to do the rest — exactly the ideas we have studied with regular expressions and NFAs, made concrete in one file. The slex tutorial is required reading before you start; the rule-priority laws and the action idioms it presents are most of this assignment.

A note on realism: we use a lex-style library here — one whose engine you can readily read and understand, as it builds on your homework questions. Production compilers such as clang and rustc hand-write their lexers, primarily for the quality of their error messages. The action code in this assignment is where you will see why.

Implementation Details

You will specify the IC token rules, build a driver program for the lexer, and write a test suite. You are required to implement the following:

Output Format

As mentioned above, you are free to print out the relevant information about tokens in any reasonable way provided that you print them out one per line with no blank lines between them. The exact content of error messages is left to you. In addition, the last line printed by your code should be either

Success.

or

Failed.

depending on whether or not any lexical errors were found. Please match those lines exactly to ensure my test scripts can properly validate your code. For similar reasons, the output should not contain any other text beyond what is specified here.

Utility Functions

I have provided a few utility methods in the ic.Util class. You are free to (and should!) use these methods in your code. In particular, make use of Util.debug to print diagnostic messages for debugging. Also, use Scala’s assert function to assert that specific conditions (e.g.: preconditions, postconditions, invariants) are always true at run time.

Code Structure

All of the classes you write should be in or under the package ic, containing the following:

The slex library sources are included in the starter; you can read them but should not need to modify them. Your ic.slex sits at the project root, next to build.sbt; the build compiles its action blocks automatically, so type errors in a block appear (in sbt and in VSCode) at the spec file’s own line numbers.

Testing the scanner

You must test your lexer. You should develop a thorough test suite that tests all legal tokens and as many lexical errors as you can think of. There are two types of tests that you should consider writing:

When a test lexes wrongly and staring at the spec does not explain why, make the scanner narrate: tokenize(src, trace = true) on the one failing line prints, munch by munch, which rules were alive, who accepted, and why the winner won (the tutorial’s Watching It Scan section, and HW 2 problem 2, show you how to read it).

We will test your lexer against our own test cases.

Submission

You will develop your code, with version control, in your GitHub repository — push your final version of your code and supporting files to GitHub by the deadline, with a descriptive message such as “pa1 submission”. For grading, you will then submit your project to Gradescope by the deadline.

As in any other large program, much of the value in a compiler is in how easily it can be maintained. For this reason, a high value will be placed here on both clarity and brevity – both in documentation and code. Make sure your code structure is well-documented.

Also include a brief summary of your project in README.md. At this, simply describe your basic code structure and testing strategy. Also mention any known bugs and other information that may be useful when grading your assignment.

Your project directory should be organized as follows:

Once you have pushed what you believe to be your final version, please verify all of your code has been added and committed properly. You can do this by simply inspecting the files through the server’s web interface, but the most reliable way is to clone a new copy of your project into a temporary directory, build it, and run it in a few short examples.