Grades and deadlines
-
Initial deadline: 23:59 on Wednesday 30 September
-
How to submit: Turn in your completed
lab2.2.ymlfile, along with everything in thesrc/mainfolder of your maven project.You must submit via the command line in order to preserve the folder structure. Use either of these two commands to do it:
club -csi413 -plab2.2 -f lab2.2.yml src/main aichat.mdor
submit -c=si413 -p=lab2.2 lab2.2.yml src/main aichat.md(you can download the club tool here)
-
Collaboration and AI: Recall the course policy on collaboration and AI usage. For this lab:
-
You can collaborate with freely with any classmate who is working on a different language from you, as long as that is cited and you do your own work.
-
You may use the class Gemini Gem as long as you cite where/how you used it and you turn in a complete transcript of all relevant conversations.
-
You may not use other AI tools besides the course-specific Gemini Gem. If you think there is something useful that you aren’t able to do with the Gem, talk to your instructor!
-
-
Grading:
In this lab you will complete the following tasks:
- Choose one of the winning languages by your classmates from last week’s lab
- Write a working interpreter in Java using ANTLR and Apache maven
- Thoroughly test your interpreter yourself on a wide variety of statements and small programs in your language, so you are confident it works 100%.
If your submission meets the requirements for each task, you will receive 10 points towards your total lab grade.
-
Resubmissions:
We will follow the same resubmission policy for all labs this semester. For any given deadline you must at leat demonstrate significant progress or you get a zero that cannot be revised. The initial deadline for this lab is the same regardless of any other pending resubmissions on previous labs. If your work is not yet up to the standard, you will receive a new deadline of one week later (up to the end of the semester) and a chance to revise for full credit.
Getting started: files
Make a new directory for this lab.
Download the yaml file for today into your lab directory and be sure to fill it in with your language name.
Copy everything from the calc folder into your new folder.
You should already have downloaded the calc language interpreter in
our in-class exercise with the calc language and ANTLR
This will be your “starter code” for this week’s lab. But the language you are implementing will be vastly different from the calc language! So you will end up ripping out much of what’s there and replacing it with new token specs, grammar, and parse tree visit methods corresponding to your language for this lab.
Task 1: Choose a language
Here are specs for the winning languages invented by your classmates in last week’s lab. During lab, your section leader will run a “draft” to decide who works on what language.
Example Program
I recommend you start by writing some example program in your language, but it doesn’t need to be comprehensive and you don’t need to turn it in. If you write a small program that you have in mind as your first target for interpreting, you could tokenize it and build the parse tree by hand, which will help you think about how your initial interpreter should work to evaluate that program.
Task 3: Writing your interpreter
Write a complete, working interpreter for your programming language, in
Java, using the Tokenizer class provided and the ANTLR parser
generator.
I will compile and run your code like
mvn compile
./run.sh input-program.txt
Critical files for your implementation
There are really three files you should be focusing on for your implementation:
-
src/main/resources/si413/tokenSpec.txtcontains the scanner specification, which is a prioritized list of token names and corresponding Java regexes.This file is read in by the
Tokenizerclass before processing the source code and producing a token stream. -
src/main/antlr4/si413/Grammar.g4contains a specification for the ANTLR parser generator. That specification amounts to a listing of the tokens (which should match those in yourtokenSpec.txt), and then a context-free grammar where each production rule is tagged with a#UniqueName.When you compile your project using maven, it starts by running the ANTLR tool to read this
.g4file and produce java classes for the actual custom parser it generates for your language. -
src/main/java/si413/Interpreter.javais the actual Java code you will be writing to make the interpreter work. It consists of a few “Visitor” classes, what contain code to be called on every node in the parse tree in order to execute the statements and evaluate the expressions.The existing methods from the calc language won’t make sense anymore, but you will replace them with methods corresponding to the rules in your grammar.
Tips on how to proceed
Start with the syntax specification (tokens and grammar).
You actually have this already from the language specs, you just need to
copy it into into your folder and add labels to the grammar rules,
like #ThisIsALabel
Next, I recommend removing all the parse tree node visiting methods from
the inner classes in Interpreter.java, since the names of those
methods will all need to change anyway compared to the calc language.
Your goal is to get a minimal interpreter that compiles even though it
won’t actually do anything beyond parsing the input file.
Once you get that to compile, your interpreter should be able to read in any valid program in the target language. But it won’t do anything yet, because you haven’t written the visit methods to actually go through and execute the parse tree.
So, the last thing to do is gradually fill in those methods, starting with just the few methods needed to execute the simplest possible program, and testing everything as you go.
Error handling
Depending on the language, some programmer errors will be possible, for
example, using a variable name before assigning it a value. The
Errors.java class is there to help you with this — your interpreter
should call Errors.error("some explanation") when it identifies a
run-time error in the target language.
We won’t focus on the error handling too much in this unit, however. So it’s okay to mostly make sure your interpreter works correctly for valid programs.
Task 3: Testing
Ideally you should be testing as you go, building up some example programs of your own that work out each part of the language as you add the methods to support it. With that kind of approach, you should have confidence your interpreter works 100% at the end.
Moreover, as our languages get bigger, it will be harder to quickly check every possible language construct in a few lines. So you will want to stay organized and make sure you don’t break old features when you add the code for new ones.