Assignment Program Representation

Pt04

Note: You have to do this assignment individually.

Introduction

In this assignment, you will use the infrastructure of Stratego/XT to implement a syntax definition, and generate a parser, tree grammar and pretty-printer for a small language of predicate logic formulae. Thus, you will implement all the components used in a program transformation pipeline, except for the actual transformations. The following are examples of predicate logic formulae in the language you will implement.

not (exists a : Man(a) /\ Woman(a))

forall a : forall b : not(a /\ b) <-> (not a \/ not b)

(A) Syntax Definition

Write a syntax definition that defines a syntax for predicate logic formulae such that the abstract syntax trees which it generates correspond to the abstract syntax defined by the tree grammar in the subsection 'Abstract Syntax'. Use at least two modules in your syntax definition. Create a shell script generate.sh. In this script, apply the parse table generator to generate a parse table from your syntax definition. If the parse table generator gives warnings, then fix these.

Testing

Use parse-unit testsuite(s) to test if your syntax definition defines the right language. Apply your testsuites in the same shell script (see resources if you are not familiar with shell scripting). You should disable the heuristic filters of SGLR in the invocation of parse-unit (and later sglri). Write some larger tests in separate .plf files and include them in the testsuite. We will use these separate files later.

Disambiguation

You should solve all possible ambiguities in this syntax definition. For example, test if the formulae true is ambiguous and if so, solve this ambiguity.

The priorities of the operators are not specified, but some can be derived from the two examples. Just use your common sense for the cases where the priority is not defined by the examples. The same holds for associativity.

Feel free to add language features to illustrate more disambiguation problems.

Abstract Syntax

The abstract syntax of our predicate logic language is defined by the following tree grammar:

regular tree grammar
start Form
productions
  Form -> True()
        | False()
        | Prop(Id)
        | Pred(Id, FormList)
        | Not(Form)
        | And(Form, Form)
        | Or(Form, Form)
        | Equiv(Form, Form)
        | ForAll(Id, Form)
        | Exists(Id, Form)

  FormList -> <cons> (Form, FormList)
            | <nil> ()

  Id -> <string>

Thus, the syntax definition should parse the formulae mentioned in the introduction and produce the following abstract syntax trees:

Not(
  Exists("a"
  , And(
      Pred("Man", [Prop("a")])
    , Pred("Woman", [Prop("a")])
    )
  )
)

Forall("a"
, Forall("b"
  , Equiv(
      Not(And(Prop("a"),Prop("b")))
    , Or(Not(Prop("a")),Not(Prop("b")))
    )
  )
)

(B) Tree Grammar

Generate a tree grammar PLF.rtg from your syntax definition. The tree language defined by the generated tree grammar should be very similar to the tree grammar above. There will be some differences in the definition of lists. Try to find out how the definition of lists works in the generated rtg.

In your shell script, check that all the .plf files you created after parsing have the right format, i.e. conform to the generated tree grammar. You will probably get no errors. Just for fun, modify an abstract syntax tree by hand and see what the format-check tool does (optionally, use --vis to visualize the problem).

(C) Pretty-print table

Generate a pretty-print table PLF.pp for the language. Copy thisgenerated pretty-print table to PLF-pretty.pp and adapt it to produce pretty formulae, or at least formulae that are parsed in the same way as the original.

Most pretty-print rules are trivial. Modify the pretty-print rules of the exists and forall constructs to produce a more fancy layout:

forall a :
  forall b :
    not(a /\ b) <-> (not a \/ not b)

Check the correctness of your pipeline (see the Script section for a more detailed description of this).

Parentheses

Most likely, you will have a problem with parentheses. Use the sdf2parenthesize tool to generate a Stratego program PLF-parenthesize.str that inserts Parenthetical nodes. Add a pretty-print rule for this constructor to the pretty-print table.

Pass the following arguments to sdf2parenthesize (besides -i and -o):

  • --lang PLF
  • --omod PLF-parenthesize
  • -m PLF

The parenthesize tool needs a so-called Stratego Signature, which you can generate from the .rtg using rtg2sig. We have not discussed Stratego compilation yet, so you get that part for free.

$ rtg2sig -i PLF.rtg -o PLF.str
$ strc -i PLF-parenthesize.str -m io-PLF-parenthesize -Cl stratego-lib

You can now invoke PLF-parenthesize in your pipeline. It is an executable PLF ATerm to ATerm tool.

(D) Script

Using the Stratego/XT tools, write a script that generates a packed syntax definition, a parse table, a tree grammar, a pretty-print table, and a parenthesize tool from the syntax definition. Then, for all files with extension .plf in the current working directory, it should parse, implode, pretty-print, and subsequently parse and implode the pretty-printed texts. Finally, it should check that the original abstract syntax trees and those produced from the pretty-printed files are equivalent. Apply the script to the syntax definition developed above and to the examples and testsuites you have defined.

Submission

Files

Submit the following files in a zip or tar.gz

  • *.sdf: SDF modules
  • *.plf: example files
  • *.testsuite: parse-unit testsuites
  • PLF-pretty.pp: modified pretty-print table
  • generate.sh (the script)

Assuming that Stratego/XT is installed in the path, the script should generate:

  • PLF.def
  • PLF.tbl
  • PLF.rtg
  • PLF.pp
  • PLF.str
  • PLF-parenthesize.str

And for each base.plf file in the directory (should be extendable) the following pipeline should be checked: parse, pretty-print, parse, pretty-print. Check that the result of both parses are equivalent. The easiest way to do that, is to add some layout to the aterms using pp-aterm and diff the result of that. You can, for example, store the intermediate results in the following files:

  • base.ast
  • base.txt (pretty-printed ast)
  • base-pretty.ast (parse of base.txt)
  • base-pretty.txt (pp of base-pretty.ast)

So, the script should verify that base.ast and base-pretty.ast are equivalent.

Email

Send your solution by email to martin@cs.uu.nl at least 15 minutes before the lecture of Tuesday, i.e. 8:45. Please include the text pt-submit in the topic of your email. The same day, you will get a short notification that I've received your solution. If you don't get this reply, then please contact me.

Questions

After the lab session you can still send questions to pt@cs.uu.nl or join #stratego at irc.freenode.com.

Additional Resources