Wizard

COMP 524: Programming Language Concepts

Spring, 2008
Jeff Terrell
jsterrel AT cs.unc.edu
(919) 962-1791 (office: Sitterson 138)

View Source of program2.php

In the interest of open source, and in the interest of keeping Mr. Webmaster honest, here is the PHP source of program2.php. (This encourages him to write clean, easy-to-understand code...well, relatively clean and easy-to-understand, that is.) If you become interested in PHP, you can read more about it at PHP: Hypertext Preprocessor. You will also see plenty of HTML code, which is what makes the World Wide Web go 'round. You can read more about HTML (and CSS, another technology used on this site) here, at the official page of the very official World Wide Web Consortium (W3C). Anyway, enough rambling, here's the code!


<?php include("header1.php"); ?>
<?php $THIS_FILE 
"program2.php"?>
  <title>COMP 524-S08 - Program 2 (Evaluator)</title>
  <link rel="stylesheet" href="local.css" type="text/css" charset="iso-8859-1" title="Default" />
<?php include("header2.php"); ?>
<?php 
include("localheader.php"); ?>

<h1>COMP 524 Program 2 (Evaluator)</h1>

<p>With thanks to Felix Hernandez-Campos.</p>

<h2>General Instructions</h2>
<p>First, review the assignment submission policy in the <a href="syllabus.php">syllabus</a>.  Note that there is <strong>no collaboration</strong> allowed.</p>
<p>This assignment is <strong>due at 11:59pm on Tuesday, April 15<sup>th</sup></strong>.  Submit assignments to me via email.  All of your code should be included in two files: 'turtle.py', and 'lsystem.py'.  These two files should be the only thing that you turn in.  When I am finished grading your assignment, I will email you your grade and any comments that I have.  There are a total of 100 points.</p>
<p>Remember: <strong>start early</strong>!  I guarantee my availability during office hours, but not at 11pm the night it is due.</p>
<p>When you turn in your files, there should be no statements at the top level that produce output or require input.  Merely provide the required functions and anything the functions need--do not include any code related to your testing or debugging.  When I import your functions into another script, I want the import to be silently successful.  Thank you.</p>
<p><strong>Warning:</strong> your programs must work on the example programs for you to receive credit!  If the deadline comes around and they don't work on the example programs, you should take the 5% late penalty and keep working.</p>

<p>My solutions are now available: <a href="turtle.py">turtle.py</a> and <a href="lsystem.py">lsystem.py</a>.</p>

<h3>Overview</h3>
<p>In this assignment, you will get some practice implementing an evaluator.  Along the way, you'll create some pretty nifty line drawings.</p>

<h3>Part 0: Graphics in Python</h3>
<p>This part does not count towards your grade.  It's just background on how to do simple graphics with the Tk library in Python.</p>
<p>Your main function should look something like this:</p>
<pre class="code">from Tkinter import *
import sys

def main(argv=None):
  global canvas
  # Initialize the graphical toolkit
  root = Tk()
  canvas = Canvas(root, width=300, height=300)
  canvas.pack(side=TOP)
  #say_hello()

  # parse the Turtle input
  if argv is None:
    argv = sys.argv
  if len(argv) != 2:
    sys.stderr.write('Error: specify the filename to read as input\n')
    sys.exit()

  # Evaluate!
  evaluate(parse(scan(argv[1])))

  # Display the canvas
  # This must come last, after all line-drawing commands
  root.mainloop()

global canvas

# So, main() will only get called if this program is run directly, but not when
# it's imported somewhere else.  Nifty, eh?
if __name__ == "__main__":
  main()</pre>

<p>Then, before you call <code>root.mainloop()</code>, you can draw a line with <code>canvas.create_line(X1, Y1, X2, Y2)</code>, where <code>(X1,Y1)</code> and <code>(X2,Y2)</code> are the endpoints of the line.</p>

<p>If you're running Mac OS X, to get Tkinter to work, you might need to download <a href="http://developer.apple.com/opensource/tools/X11.html">X11</a> and run your Python program from within an Xterm window in X11.  If you run into problems getting Tkinter to work, ask me or the list for help.</p>


<h3>Part 1: Turtle Evaluator (65 points)</h3>
<p>In this part of the assignment, you will implement a simple interpreter for an extended version of the turtle graphics language (Turtle++).  Your parser has to follow a recursive descent strategy, and the scanner must use Python's regular expressions library.</p>
<p>Turtle++ is a simple computer language used to control a drawing turtle. The turtle responds to simple orders like DRAW_FORWARD 10 by drawing a line with a length of 10 pixels. The state of the turtle is given by a tuple (x, y, alpha), where x is the horizontal location of the turtle in the canvas, y is its vertical location, and alpha is the orientation of the turtle in degrees. The initial state of the turtle in a canvas of 300 by 300 pixels is (150, 300, 90). The following two sample programs illustrate the semantics of this language:</p>

<p>This code:</p>
<div class="code">VAR step 20<br/>
MOVE_FORWARD 150<br/>
REPEAT 12<br/>
&nbsp; DRAW_FORWARD step<br/>
&nbsp; ROTATE COUNTERCLOCKWISE 90<br/>
&nbsp; DRAW_FORWARD step<br/>
&nbsp; ROTATE COUNTERCLOCKWISE 90<br/>
&nbsp; ADD step 20<br/>
END_REPEAT</div>
<p>...produces this output (source: Felix Hernandez-Campos):<br/>
  <img src="spiral.gif"/>
</p>

<p>And this code:</p>
<div class="code">MOVE_FORWARD 250<br/>
ROTATE CLOCKWISE 198<br/>
REPEAT 5 DRAW_FORWARD 200 ROTATE COUNTERCLOCKWISE 144 END_REPEAT</div>

<p>...produces this output (source: ibid):<br/>
  <img src="star.gif"/>
</p>

<p>The LL(1) grammar of Turtle++ is given by the following production rules:</p>
<pre class="code">program              ::= statement_list EOF
statement_list       ::= statement statement_list | e
statement            ::= turtle_action | repeat_statement
                      |  variable_declaration | variable_operation
turtle_action        ::= DRAW_FORWARD argument 
                      |  MOVE_FORWARD argument
                      |  ROTATE direction argument 
                      |  SAVE_STATE 
                      |  RECOVER_STATE
direction            ::= CLOCKWISE | COUNTERCLOCKWISE
repeat_statement     ::= REPEAT argument statement_list END_REPEAT
variable_declaration ::= VAR IDENTIFIER argument
variable_operation   ::= MUL IDENTIFIER argument
                      |  ADD IDENTIFIER argument
                      |  SUB IDENTIFIER argument
                      |  DIV IDENTIFIER argument
argument             ::= IDENTIFIER | INTEGER
</pre>

<p>Note that this is a free format language, so tokens can be separated by one or more whitespaces, tabs and end of line characters. The two literals <code>IDENTIFIER</code> and <code>INTEGER</code> are generated by the following regular expressions:</p>

<pre class="code">IDENTIFIER           ::= letter { letter | digit | _ } *
INTEGER              ::= [ + | - ] ? digit { digit } *
</pre>

<p>Your interpreter must be able to execute any syntactically correct program.  Do not worry about elaborate error-checking.  I will not give you any illegal Turtle programs.</p>

<p>The semantics of the language is straightforward. Rotation angles are given in degrees. <code>SAVE_STATE</code> saves the current state of the turtle, defined by the tuple (x, y, alpha), and the current set of variables. <code>RECOVER_STATE</code> will restore the state and the variables saved in the most recent call to <code>SAVE_STATE</code>. Note that that these two statements can be nested, and they work in a first-in, last-out fashion. The arithmetic operators receive two parameters, a variable name and an argument. The result of the operation is stored in the variable. For instance,</p>

<div class="code">VAR x 10<br/>
ADD x 5
</div>
<p>makes the values of x equal to 15.</p>

<p>The interpreter will be invoked with <code>python turtle.py program_name</code>, where program_name is the name of a file containing the Turtle++ source code to be executed. After this, you program should create a visualization of the given turtle program.</p>

<p><strong>Warning</strong>: you cannot use Python's turtle graphics module in this assignment.</p>

<h4>Program structure</h4>
<p>You must implement the scanner, parser, and evaluator <strong>individually</strong>.  Your <code>scan</code> function should accept a filename and return a list of tokens.  Your <code>parse</code> function should accept a token list and return a parse tree.  (Use recursive-descent parsing.)  Your <code>evaluate</code> function should accept a parse tree and return void, with the side effect of drawing the lines as indicated by the given parse tree.</p>

<h3>Part 2: Lindenmayer Systems Translator (35 points)</h3>
<p>In this part of the assignment, you will implement a translator that, given a definition file specifying a Lindenmayer system (L-System), will generate a Turtle++ program. This program will correspond to a visualization of the L-system at a given depth.</p>

<p>An L-system is a mathematical formalism, invented by biologist Aristid Lindenmayer in 1968, that is used to describe growth patterns, such as the way in which a plant grows. They provide a remarkably compact way of describing fractal structures. L-system descripions consist of several elements:</p>

<ul>
  <li>an axiom</li>
  <li>a set of production rules (i.e. string substitutions)</li>
  <li>a rotation angle in degrees</li>
  <li>an initial segment length in pixels</li>
</ul>

<p>For instance, the L-System:</p>

<pre class="code">Axiom: B
Rules: 
  B -&gt; F[-B]+B
  F -&gt; FF
Angle: 20
Initial Length: 20
</pre>

<p>at depth 0 results in the string <code>B</code> (the axiom). At depth one, this axiom is replaced using the first rule, resulting in <code>F[-B]+B</code>. At depth two, the first rule is applied to substitute <code>B</code> by <code>F[-B]+B</code>, and the second rules is applied to substitute <code>F</code> by <code>FF</code>. The results is therefore <code>FF[-F[-B]+B]+F[-B]+B</code>. Note that the production rules are applied simultaneously.</p>

<p>The resulting string directly maps to actions in the Turtle language:</p>

<ul>
  <li>B means do nothing</li>
  <li>F means <code>DRAW_FORWARD Current_Length</code></li>
  <li>G means <code>MOVE_FORWARD Current_Length</code></li>
  <li>+ means <code>ROTATE CLOCKWISE Angle</code></li>
  <li>- means <code>ROTATE COUNTERCLOCKWISE Angle</code></li>
  <li>[ means <code>SAVE_STATE</code></li>
  <li>] means <code>RECOVER_STATE</code></li>
  <li>| means reduce the <code>Current_Length</code> to 65% and <code>DRAW_FORWARD Current_Length</code></li>
</ul>

<p>The <code>Initial Length</code> field in the L-system definition provides the initial value of <code>Current_Length</code>. The following figures show the expected visualization of the L-System specified above (source: ibid):</p>

<p>Depth 1:<br/>
  <img src="lsystem-d1.gif"/>
</p>

<p>Depth 2:<br/>
  <img src="lsystem-d2.gif"/>
</p>

<p>Depth 3:<br/>
  <img src="lsystem-d3.gif"/>
</p>

<p>Depth 4:<br/>
  <img src="lsystem-d4.gif"/>
</p>

<p>Here are two more examples, thanks to Felix Hernandez-Campos:</p>

<p>Weed:</p>
<pre class="code">Axiom: F
Rules: 
  F -&gt; |[-F]|[+F]F
Angle: 25
Initial Length: 150</pre>
<p>...produces at depth 4:<br/>
  <img src="weed2-4.gif" />
</p>

<p>Koch Curve:</p>
<pre class="code">Axiom: F++F++F
Rules: 
  F -&gt; F-F++F-F
Angle: 60
Initial Length: 9</pre>
<p>...produces at depth 3:<br/>
  <img src="koch-3.gif" /><br/>
  Note that a 30-degree rotation was manually added in the last example to center the curve.
</p>

<p>Your L-system translator program should be invoked with <code>python lsystem.py input_definition depth output_program</code>, where <code>input_definition</code> is the name of a file containing an L-system definition, <code>depth</code> is the expected depth of the visualization, and <code>output_program</code> is the name of the file where your L-system translator should put the generated Turtle++ program (that produces an image of the input L-system at depth depth).</p>

<p>Note: you are free to parse the L-system specification however you like.  You can create a grammar, scanner, and parser if you want, but you do not need to.</p>

<?php include("footer.php"); ?>
viewsource.php: Last Modified: 02/06/08@14:19:08 | Size: 2795 bytes | View Source Valid XHTML 1.1 Valid CSS