|
Introduction. This task is
about parsing. You will write a parser for a fragment of the
simple programming language given here.
Task. Write a parser for the
language specified by the CFG below.
INT → ...
BLOCK → { ENE }
ENE → E | E; ENE
E → INT | BLOCK | skip
The starting symbol
is BLOCK. Your parser will take as input a token list,
using the definition of tokens from Task 2
(given here). Your parser
should return a suitable AST (i.e. an instance of the
class Block), provided the input adheres to the syntax
given above. Otherwise it should throw
a SyntaxException given below. As the parser takes a
token list as input, it might be helpful to see the grammar in a
form where terminal symbols are token names. Since the grammar above
does not parse the full language, not all valid tokens are used for
valid programs, e.g. T_Then .
BLOCK → T_LeftCurlyBracket ENE T_RightCurlyBracket
ENE → E | E T_Semicolon ENE
E → T_Integer | BLOCK | T_Skip
Note that you are not asked to
write a parser for the full language
given here, only for the fragment above.
You are free to write the parser in any form you want, whether 'by
hand' or with a parser generator like CUPS, Yacc etc. As the
grammar fragment is so simple, I recommend writing a top-down parser
'by hand'. As explained in the lectures, a top-down parser is
naturally written using recursion rather than loops. If you find
yourself using loop constructs, I recommend to rethink your approach
(note: it is possible to write parsers with loops, I just personally
find this much more cumbersome). If you
use a parser generator to handle this task, I strongly recommend
submitting the generator's source files too. I am unable to
comprehend and comment on auto-generated parsers without source
files: the auto-generated code is too complicated/weird for humans
to comprehend directly.
Your parser has to implement the interface Parser given next.
interface Parser {
public Block parse ( List < Token > input ) throws SyntaxException,
Task3Exception; }
class SyntaxException extends Exception {
public String msg;
public SyntaxException ( String _msg ) { msg = _msg; } }
class Task3Exception extends Exception {
public String msg;
public Task3Exception ( String _msg ) { msg = _msg; } }
Here List<...> is the list class imported from
java.util.List. The AST class Block is
given here. You need to use those classes
and not modify them at all. The class SyntaxException
should be thrown whenever input is encountered that does not adhere
to the syntactic specification. Do not use this exception to
indicate any other form of error -- use Task3Exception
for any other error. Errors should be reported by exception only.
You will also have to implement a
method
create that, when called, returns an instance of the
interface Parser. For this please use the following
fragment, replacing ... with the appropriate code.
class Task3 {
public static Parser create () { ... } }
For your convenience, here are the
remaining definitions in one file.
The necessary Java files for all three tasks can be found for
convenient download here:
Warning. Your code
needs to compile against the signatures given to you
here. Do not change them. You are welcome to add new
classes. For your convenience you can find a
file tester-skeleton3.java
here that you can use to check if
your submission compiles properly. Just download it, added
to the directory containing all the files you want to
submit, and run javac *.java. Note
that tester-skeleton3.java does not test
if you code has the right functionality. You will have to
create and run your own tests to do that.
|