ProjectsFall 2012 - MyWeb at WIT by linxiaoqin


									Comp 501 Projects – Fall 2012

COMP501 Introduction to Programming Languages
Projects - Fall 2012 - Prof. M Werner

Project 1 - Research Paper - Compare another language to Java

Select one of the languages in the University of Michigan’s CIS 400 Programming Languages
Guide or
from Wikipedia’s language list: and compare it to C++
according to the criteria listed below. All work is individual, and no more than two people can
compare the same language.
You are expected to use informed opinion as a part of your rating justifications. References
should be cited in the text of your essay (eg. Wirth, 1978). A complete reference list should
appear at the paper's end.

Chapters 1 - 3 from Sebesta provide a good starting point. An Internet search will yield valuable
material. However, you must use additional sources from the library. We currently receive a
number of periodicals including ACM SIGPLAN Notices, ACM Communications, IEEE
Computer, ACM Computer Surveys. We also have access, through the library, to a number of
on-line databases.

You must have at least one paragraph comparing your language to Java for each of the criteria
below. Hence, besides a brief introduction your paper will consist of numbered sections by

Criteria for Language Design Evaluation:

1.    Efficiency (translation and execution)
2.    Simplicity (readability and writability)
3.    Reliability
4.    Expressivity (does the language facilitate translating a program design into code?)
5.    Abstraction facilities (data and procedural)
6.    Portability (can the programs be ported to different hardware and operating systems?)
7.    Tools availability (is there a unified development environment with an editor, compiler and
8.    Major application areas (scientific, systems, business, etc.)
9.    Extent of current use of the language
10.   Reverse engineering (Can the source code be easily recovered from the run-time code?)
11.   Exception handling
12.   Support for object orientation
13.   Support for web programming

Please let me know by Sep 12th what language you are planning to compare to C++. You may
send me e-mail or tell me in class. I must formally approve your request before you begin. No
more than 2 evaluations of the same language will be approved (so choose early).

Revised 1/28/2013                                 1                               Prof. M Werner
Comp 501 Projects – Fall 2012

Project 2 - Parser for Dots Graphical Description Language

Dots is a graphical description language developed by Eleftherios Koutsofios and
        Stephen C. North at AT&T Bell Laboratories. A paper describing it is available
        at . Here is a simple example of a dots
        description and graph.

Revised 1/28/2013                           2                            Prof. M Werner
Comp 501 Projects – Fall 2012

Here is a fancy graph.

Revised 1/28/2013               3   Prof. M Werner
Comp 501 Projects – Fall 2012

Here is the grammar used for making fancy graphs:

A Graph File Grammar

The following is an abstract grammar of graph files. Double-line brackets [ and ] enclose
       optional items. Vertical bars | separate alternatives. Curly braces { } enclose
       items repeated zero or more times.

graph -> [strict] ( digraph | graph ) id {stmt-list}
stmt-list -> [stmt [;] [stmt-list ] ]
stmt -> attr-stmt | node-stmt | edge-stmt | subgraph | id = id
attr-stmt -> (graph | node | edge) [ [ attr-list ] ]
attr-list -> id=id [attr-list ]
node-stmt -> node-id [ opt-attrs ]
node-id -> id [: id ]
opt-attrs -> [attr-list]
edge-stmt -> (node-id | subgraph) edgeRHS [opt-attrs ]
edgeRHS -> edgeop ( node-id | subgraph ) [edgeRHS ]
subgraph -> [subgraph id] { stmt-list } | subgraph id

An id is any alphanumeric string not beginning with a digit, but possibly including
        underscores; or a number; or any quoted string possibly containing escaped

An edgeop is -> in directed graphs and -- in undirected graphs.

Semicolons aid readability but are not required except in the rare case that a named
      subgraph with no body immediate preceeds an anonymous subgraph, because
      under precedence rules this sequence is parsed as a subgraph with a heading and a

A dot graph consists of a collection of nodes and a collection of edges. Nodes are
       identified by their id, which is unique. A node is created the first time its name
       appears in the file. Hence, when a node name appears, it is first checked to see if
       it matches an already created node, if not, a new node is created. Edges are
       created when nodes are joined by the edge operator -> or --.

Dot graphs may also have a collection of subgraphs, which are themselves dot graphs.
       Drawing a dot graph requires recursively drawing subgraphs.

Preparing the .jj file for processing by JavaCC.

Consider the production:

Revised 1/28/2013                             4                            Prof. M Werner
Comp 501 Projects – Fall 2012

graph -> [strict] ( digraph | graph ) id {stmt-list}

It contains a mix of reserved words and symbols, tokens and nonterminals. The goal is to
        build a Java program to parse the language. Since Java doesn’t allow hyphens in
        identifiers, change stmt-list to stmt_list.

Enclose reserved words and symbols in double quotes. EBNF metasymbols [,],(,) are left
       unchanged. Nonterminals are shown as methods. The production will be used to
       define the method for parsing its LHS, in this case graph. Here is the way the
       production is represented in the .jj file.

void graph() :
       //Initialization area
       [ "strict" ] ("digraph" | "graph") <ID> "{" stmt_list() "}"

Terminals must be defined as tokens. So this production requires tokens: <STRICT>,
      <DIGRAPH>, <GRAPH>, <ID>, <LBRACE> AND <RBRACE>. Nonterminals
      appearing in the RHS of an EBNF production become method calls. So in this
      case stmt_list() will need to be defined elsewhere in the .jj file.

EBNF uses braces to indicate repetition as in {…}. In JavaCC braces have other uses,
     repetition is indicated using parentheses and * as in (…)*.

Actions are inserted into the .jj file using braces. Here is an example:

void graph() :
         //Initialization area
         String graphType;
         Token t;
    [ "strict" ]
    ("digraph" {graphType = "Digraph";}| "graph" graphType = "Graph";})
    t= <ID>
    {System.out.println("Parsing a "+graphType+" named "+ t.image);}
    "{" stmt_list() "}"

Project 2 Deliverables:

Revised 1/28/2013                              5                           Prof. M Werner
Comp 501 Projects – Fall 2012

1.     Modify the fancy graph grammar by stripping away extra features, so that it is
       adequate to describe simple graphs. Call this the SimpleDots grammar.

2.     Use JavaCC to build a parser to recognize the SimpleDots language.

3.     Add actions to the parser, so that it builds a parse tree. This requires building a
       class for each nonterminal in your grammar. Each production should return an
       object of its matching class. The object represents an interior node of the parse
       tree. It has fields set to point to its children. Here is an example taken from a .jj
//EdgeRHS = EdgeOp Nodeid [EdgeRHS ]

EdgeRHS EdgeRHS() :
{//initialization section
         EdgeRHS edgeRHS = new EdgeRHS();
         EdgeOp edgeOp;
         Nodeid nodeid;
         EdgeRHS nextEdge;
         edgeOp = EdgeOp() {edgeRHS.setEdgeOp(edgeOp);}
         nodeid = Nodeid() {edgeRHS.setToNode(nodeid);}
         [nextEdge = EdgeRHS() {edgeRHS.setEdgeRHS(nextEdge);} ]
         {return edgeRHS;}

4.     Build Java classes for Graph, Node and Edge. The Graph class contains a hash
       table named nodes for keeping its collection of Node objects. (We are assuming
       that all nodes have distinct labels.) It has a print() method, which prints all the
       Nodes in a graph.

The Node class has a field named label, which is also used as the hash key. It also has
      vectors named outgoing and incoming for keeping track of edges. It has a method
      print(), which prints a Node object as follows:

Node: execute
Incoming edges from: parse
Outgoing edges to: make_string, compare, printf

5.     Do a traversal of the parse tree to identify the nodes in the graph. When a node is
       discovered, construct a new Node object and put it in the hash table. Since it is a
       hash table, there will be no duplicates.

Revised 1/28/2013                             6                              Prof. M Werner
Comp 501 Projects – Fall 2012

       Do a second traversal of the parse tree to identify edges. When you find an edge,
       construct a new Edge object and add it to both the outgoing collection of its
       source node and the incoming collection of its target node.

       Test your program by parsing at least two simple graphs, and printing out the
       nodes using the Graph::print() method.

Note: Project 2 consists of parts 1 - 5 above. The parts below will be assigned in the
       second half of the course. Some of these will be for extra credit.

6.     You will now write a program to draw a Graph object. The first job is to lay out
       the nodes on a canvas. The simplest way is to use a square grid without regard to
       the overlapping of edges. So, for example, if there are 10 nodes, the next highest
       perfect square is 16. Hence, use a 4 by 4 grid with 4 nodes in row 1, 4 in row 2,
       and 2 in row 3. Draw the nodes as ellipses, draw the labels on top, and draw the
       edges below the nodes from center to center. Draw the arrowheads in the middle
       of the edges.

7.     Improve on Part 5. Place the arrows where the edge strikes the target node. Make
       the ellipses the right size to hold their labels. Perhaps improve the layout.

8.     Make the graph interactive. The user should be able to drag any node, with the
       links following it.

9.     Provide a facility for users to add nodes and edges by clicking and dragging.

10.    (extra credit - mucho). Build a parser and graph drawer for the FancyGraph
       language, including many of the features described in the article.
(Optional – Extra Credit)

Project 3 Build a Postscript Interpreter

Postscript is a stack-based programming language used primarily for preparing
       documents for printing. Luc Devroye, a professor in the School of Computer
       Science at McGill University, provides a useful set of links for someone
       interested in learning about Postscript.

The Adobe company is the authoritative source. In particular, the Blue book contains
      tutorial and sample scripts.

Revised 1/28/2013                             7                            Prof. M Werner
Comp 501 Projects – Fall 2012

3.1 Build a postfix interpreter in Java

The interpreter opens a text file containing a stream of numbers and operators. It uses a
       stack. When a number is scanned it is pushed on the stack. When an operator is
       scanned, its operands are popped from the stack, the operation applied, and the
       result is pushed. The operators are:

Arithmetic Operators

div – Division resulting in a floating point answer
idiv – Division resulting in an integer answer

Stack Operators

clear – Removes all stack contents
dup - Duplicates top of stack
exch – Reverses the order of top two items on stack
pop – Removes top of stack
== - Destructively prints top of stack

Lines starting with % are comments

3.2 Expand the interpreter to handle defined constants and procedures

A definition looks like this:

/mil 0.001 def //defines the name mil to mean 0.001


/square {dup mul} def //defines the procedure square to mean duplicate the top of the
// and multiply

When a definition is made it is stored in a dictionary. The dictionary entry associates a
      key (the word being defined) with a definition. It is convenient to implement
      dictionaries using a hash table. Postscript allows multiple dictionaries to be

Revised 1/28/2013                            8                             Prof. M Werner
Comp 501 Projects – Fall 2012

When a defined name is scanned from the input, its definition is retrieved from the (top)
      dictionary. If it is a number it is pushed. If it is a procedure it is scanned token by
      token from the definition and interpreted.

For example, the script:

/five 5 def
/square {dup mul} def

should produce 25 as an output

You may wish to use this grammar for simplified postscript

<program> -> {<entry>} "end"
<entry> -> <number_entry> | <def> | <name> | <string>
<number_entry> -> <number>
<literal> -> "/" <IDENTIFIER>
<name> -> <builtin_operator> | <user_defined_operator>
<user_defined_operator> -> <IDENTIFIER>
<string> -> <STRING>
<procedure> -> <PROCEDURE>
<number> -> <NUMBER>
<builtin_operator> -> <arithmetic_operator> | <stack_operator> | <graphic_operator>
<arithmetic_operator> -> <add> <mul> <sub> <div>
<stack_operator> -> <clear> | <dup> | <exch> | <pop> | <top>
<graphic_operator> -> <lineto> | <moveto> | <stroke>
<add> -> "add"
<mul> -> "mul"
<sub> -> "sub"
<div> -> "div"
<clear> -> "clear"
<dup> -> "dup"
<pop> -> "pop"
<top> -> "=="

<lineto> -> "lineto"
<moveto> -> "moveto"
<stroke> -> "stroke"

<def> -> <literal> ( <number> | <procedure> ) "def"

<NUMBER> -> ["1"-"9"] (["0"-"9"])* | (["0"-"9"])+ "." (["0"-"9"])*

Revised 1/28/2013                            9                              Prof. M Werner
Comp 501 Projects – Fall 2012

<IDENTIFIER> -> ["a"-"z","A"-"Z"] (["a"-"z","A"-"Z"])*
<STRING> -> "(" ( ( ~["(",")","\"","\\","\n","\r"]))+ ")"
<PROCEDURE> -> "{" ( ( ~["{","}"]))+ "}"

Tokens for simplified postscript

<NUMBER> - Either integer or floating point. Stored as f.p.

Literals are words being defined inside a def operation.
The definition is stored in a dictionary.

Design to enter tokens from a defined procedure into the stream

When a literal is parsed, the definition is stored as a string in a dictionary
When an Identifier is parsed, its definition is looked up in the dictionary. The string
      found is then tokenized and processed.

Here are two approaches to do this:

1) Instantiate a new parser to read from the string sr = new str ); r = new sr );

XXX parser = new XXX( r );

When this string is consumed this parser is destroyed and parsing resumes from the file.

The same DoubleStack is used for both parsers. This is done by making it static.

Note: To make this work I needed to introduce lexical states.

The IN_DEFINITION state used the PROCEDURE token above. I entered this state on
      reaching a slash and left it on reaching a "def".
The DEFAULT state was used elsewhere, in particular when parsing a string to prevent
      the entire string being matched by <PROCEDURE>

2) Interpret the .ps file in two passes.

Revised 1/28/2013                            10                             Prof. M Werner
Comp 501 Projects – Fall 2012

   i.     Enter all definitions into the dictionary and expand all defined words using
          their definitions. The first pass writes out an intermediary file stripped of
          definitions and with all defined words expanded.
The second pass is a straightforward interpretation of the remaining postscript

3.3 Add graphics to handle simple postscript files (Extra Credit)

Here is a script that draws a simplified Wentworth logo.


        /Helvetica findfont
        12 scalefont setfont
        /thick 25 def
        .8 setgray
        /inch {144 mul } def
        /box { 1 inch 0 rlineto 0 1 inch rlineto -1 inch 0 rlineto 0 -1 inch rlineto } def

        200 200 moveto box stroke
        /inch { 108 mul } def
        218 218 moveto box fill

        .0 setgray
        232 331 moveto (INSTITUTE OF) show
        331 314 moveto
        -90 rotate (TECHNOLOGY) show
        90 rotate
        213 231 moveto
        90 rotate (WENTWORTH) show
        -90 rotate
        250 210 moveto
        /Helvetica findfont
        9 scalefont setfont
        (FOUNDED) show
        260 202 moveto (1904) show


        To interpret a script like this you will need to add graphics operations such as
        moveto, rlineto, stroke, rotate, etc. (See the official postscript documentation)
        You will then need to open a canvas inside a frame to draw on. The commands
        need to be interpreted, properly translating postscripts coordinate system to

Revised 1/28/2013                             11                               Prof. M Werner
Comp 501 Projects – Fall 2012

Project 4, 5 and 6 – Parser for PGN Chess Language

This project involves parsing standardized chess notation. Of course, you will need to
       know how to play chess in order to build the parser. See The Rules of Chess.

PGN - Portable Game Notation is a standard designed for the representation of chess
      game data using ASCII text files. PGN is structured for easy reading and writing
      by human users and for easy parsing and generation by computer programs. A
      text file composed exclusively of PGN data records should have a file name with
      ".pgn" as the suffix. More information can be found at this site.

                                                   - above quoted from

Below is an article showing the description of a chess game using PGN:

        From Mark Weeks,
              Your Guide
              to Chess.

Portable Game Notation (PGN)

Downloading games is a popular chess activity on the Internet. PGN makes
     it simple.

Computers and the Internet have had a profound impact on        Related Resorces
     the game of chess. Opening & game databases,
     tactical calculation, endgame tablebases, online &
                                                               • Chess game downloads
     email play, computer vs. computer, vs. human,
     algorithm & game theory, have all been with us for
     less than an average human lifetime.

The advances in chess have paralleled the advances in computing. The first
      mainframes to play chess knew little more than how the pieces moved. The
      best programs today, running on tiny processors, easily beat all but the best
      human players. One of the greatest advances in the last ten years has been
      the ability to exchange game scores in digital formats. This has led to
      databases of millions of games that can be searched in a few seconds.

All commercial chess database software is built around some database format which
       is proprietary to that software. Databases in that format can be exchanged

Revised 1/28/2013                          12                             Prof. M Werner
Comp 501 Projects – Fall 2012

       only between owners of the software. A more general exchange of data
       between owners of incompatible software packages requires a neutral format
       which is understood by both packages.

Fortunately for the chess world a neutral format was created in the mid-1990s and
       caught on quickly. It's called Portable Game Notation (PGN). Files using PGN
       encoding are usually assigned the extension *.PGN. Here's a sample game in
       PGN format.

[Event "chp"]
      [Site "USA"]
      [Date "1956.??.??"]
      [Round "?"]
      [White "Byrne, D."]
      [Black "Fischer, R."]
      [Result "0-1"]

1.Nf3 Nf6 2.c4 g6 3.Nc3 Bg7 4.d4 O-O 5.Bf4 d5 6.Qb3 dxc4 7.Qxc4 c6 8.e4
      Nbd7 9.Rd1 Nb6 10.Qc5 Bg4 11.Bg5 Na4 12.Qa3 Nxc3 13.bxc3 Nxe4
      14.Bxe7 Qb6 15.Bc4 Nxc3 16.Bc5 Rfe8+ 17.Kf1 Be6 18.Bxb6 Bxc4+
      19.Kg1 Ne2+ 20.Kf1 Nxd4+ 21.Kg1 Ne2+ 22.Kf1 Nc3+ 23.Kg1 axb6
      24.Qb4 Ra4 25.Qxb6 Nxd1 26.h3 Rxa2 27.Kh2 Nxf2 28.Re1 Rxe1
      29.Qd8+ Bf8 30.Nxe1 Bd5 31.Nf3 Ne4 32.Qb8 b5 33.h4 h5 34.Ne5
      Kg7 35.Kg1 Bc5+ 36.Kf1 Ng3+ 37.Ke1 Bb4+ 38.Kd1 Bb3+ 39.Kc1
      Ne2+ 40.Kb1 Nc3+ 41.Kc1 Rc2+ 0-1

Here's a diagram showing the two character notation for each square on the

Revised 1/28/2013                        13                          Prof. M Werner
Comp 501 Projects – Fall 2012

The format is defined in a document called the PGN Specification and
       Implementation Guide which can be found by following the 'Chess game
       downloads' link in the right sidebar of this article. The document defines all
       necessary formats for encoding chess game data using text files.

A PGN game score has two sections, formally known as the:-

Tag pair section and
Movetext section
The tag pairs are the lines enclosed in square brackets ('[' and ']'). Each tag pair
       consists of a tag name plus its value. In the tag pair '[Event "chp"]', 'Event' is
       the tag name and 'chp' is its value. It's clear from the tags that the game
       score is the well-known 'Game of the century' which 13-year old Bobby
       Fischer won against Donald Byrne in the 1956 U.S. Championship.

The movetext section is the game score in algebraic notation, which the PGN
       document calls Standard Algebraic Notation (SAN). The document defines
       details like 'O-O' instead of '0-0' for castling, and '=' for promotions ('c8=Q').
The tags in the Byrne - Fischer example ('Event', 'Site', 'Date', 'Round', 'White',
       'Black', & 'Result') are collectively known as the Seven Tag Roster (STR). [In
       the computer world everything gets an acronym. There's the famous story of
       the technician who was confused by the meaning of 'FAN' on a schematic until
       he was told to look it up in the dictionary.]

Revised 1/28/2013                          14                            Prof. M Werner
Comp 501 Projects – Fall 2012

Every PGN game score is required to have those seven tags. The PGN document
       says, 'The interpretation of these tags is fixed as is the order in which they
       appear. Although the definition and use of additional tag names and
       semantics is permitted and encouraged when needed, the STR is the common
       ground that all programs should follow for public data interchange.' If the
       value of one of the seven tags is unknown, it is filled with '?', as seen in the
       'Round' tag from the example.
Other tags in common use are 'ECO', which gives the ECO classification, and
       'Annotator', which gives the name of the person annotating the game. Yes,
       the PGN document standardizes the format for game comments. It also
       doesn't require a game to start from the initial position. The 'FEN' tag
       (Forsyth-Edwards Notation), described in the document, can be used to
       specify any legal chess position.
The great advantage of PGN is that it can be read and easily understood by people
       and by computers. Written in 1994 by Steven J. Edwards, the PGN
       document saw widespread distribution via the Internet and within a few years
       had become *the* standard. Today it is rare to see a text file using any other
What are the disadvantages of the PGN standard? One common complaint is that its
       text-based encoding is not particularly efficient. The same data in ChessBase
       format uses about half the disk space. Web site operators with large chess
       databases often prefer to distribute their data in ChessBase or other format to
       save on disk costs. Even when compressed using ZIP, the space savings of a
       chess-specific format are substantial.

Another disadvantage is that there are no general guidelines for the values. The
       'Site' tag value is often crammed into the 'Event' tag or vice versa. The values
       can be terse to the point of incomprehensible : [Event "ct"] means a
       candidates tournament. Players names are not written uniformly in all
       databases and not every chess program knows that Chirov and Shirov can be
       the same person.
But these problems are insignificant compared to the advantages of PGN. Searching
       and downloading game files is one of the most popular chess activities on the
       Internet, and PGN can take a lot of credit for this popularity. The quote from
       the introduction to the PGN document...
If now, while they are one people, all speaking the same language, they have started to do
       this, nothing will later stop them from doing whatever they propose to do. -
       Genesis XI, v.6 apt indeed.

The PGN standard is described here:
and in HTML format:

Here is the grammar as taken from the PGN standard.

18. Formal syntax

<PGN-database> ::= <PGN-game> <PGN-database>
<PGN-game> ::= <tag-section> <movetext-section>
<tag-section> ::= <tag-pair> <tag-section>

Revised 1/28/2013                          15                             Prof. M Werner
Comp 501 Projects – Fall 2012

<tag-pair> ::= [ <tag-name> <tag-value> ]
<tag-name> ::= <identifier>
<tag-value> ::= <string>
<movetext-section> ::= <element-sequence> <game-termination>
<element-sequence> ::= <element> <element-sequence>
                       <recursive-variation> <element-sequence>
<element> ::= <move-number-indication>
<recursive-variation> ::= ( <element-sequence> )
<game-termination> ::= 1-0
<empty> ::=

Project 4 – Build an interpreter for games stored as PGN files.

1a)    Use JavaCC to build a parser to recognize the PGN language using the PGN
       grammar described above.


1b)    Use the parser provided by Martin Rademacher found here. You will find a .jj
       file ready to be compiled by JavaCC. However, the grammar used is a bit
       different than that given above. So if you choose this option you need to write
       down the EBNF grammar that matches the .jj file.

2)     Create a data structure to represent a chess board. i.e. You could use an 8 X 8
       array to hold either blank squares or game pieces.

3)     Write a Java application to interpret a PGN file by reenacting a game. The frame
       would have a move button and a screen showing the board. When the user pushes
       the move button the move is shown in a text window and the board is refreshed.

Project 5 – Build a converter from PGN to Descriptive Notation

Prior to PGN, chess games were recorded using an older “descriptive notation”. In the
        older system the squares on the board were labeled in 2 ways as shown below.
        So, the square that from white’s point of view is labeled KB3 is known as KB6
        from black’s point of view.

Revised 1/28/2013                          16                             Prof. M Werner
Comp 501 Projects – Fall 2012

Here is part of a game using descriptive notation:

1.P-K4 P-K4 2.N-KB3 N-QB3 3.B-N5 KN-K2 4.O-O P-QR3 5.BxN QPxB

This game is taken from an article by Mark Weeks. It is a good reference for descriptive

The project is to write a translator that reads in a PGN file and outputs the game(s) in
       descriptive notation. The tag section at the beginning can remain the same.

Project 6 - Build a converter from Descriptive Notation to PGN

Similar to Project 5 but the other way around. The problem with descriptive notation is
       that it is very abbreviated. For example, in move 5 we see “BxN” followed by
       “QPxB”. For “BxN” there was no need to specify which bishop takes which
       knight, meaning given the state of the game there was only one bishop in place to
       take exactly one knight, but in “QPxB” it was necessary to qualify that it is the
       queen pawn which takes the bishop.

From Mark Weeks: Ambiguous moves are generally distinguished by indicating whether
     the queenside or kingside piece is moving. Instead of 'N-B3', we write 'QN-B3' or

Revised 1/28/2013                            17                             Prof. M Werner
Comp 501 Projects – Fall 2012

       'KN-B3' to show which Knight is moving. If it is no longer simple to determine
       whether a piece was initially on the queenside or kingside, the square from which
       the piece is moving can be entered, for example, 'N/2-K4' or 'R/QB3-K3'.

If you do both 5 and 6 you can test by doing round-trip conversions to see if the original
        file is recovered.

PGN       Descriptive      PGN

Descriptive    PGN       Descriptive

Revised 1/28/2013                           18                             Prof. M Werner

To top