You are here:   ArielOrtiz.info > Software Design and Architecture > Lab 8: Domain-Specific Language Pattern

Lab 8: Domain-Specific Language Pattern

Objectives

During this lab session:

This activity helps students develop the following skills, values and attitudes: ability to analyze and synthesize, capacity for identifying and solving problems, and efficient use of computer systems.

Activity Description

IMPORTANT NOTE: The lab activities can be developed individually or in pairs. The lab report must be developed individually.

  1. Create a folder called dsl. Inside this folder, create two files called: jankenpon.rb and tc_jankenpon.rb.

    All Ruby source files must start with a comment containing the lab’s title, date, and the authors’ personal information. For example:

    # Lab 8: Domain-Specific Language Pattern
    # Date: 3-Apr-2013
    # Authors:
    # 456654  Thursday Rubinstein 
    # 1160611 Anthony Stark
    
  2. In the jankenpon.rb source file, implement an internal Domain-Specific Language (DSL) that allows you to see the results of a Rock-Paper-Scissors-Lizard-Spock (a.k.a. Jan-ken-pon five-weapon expansion) hand game.

    The rules of this game are as follows:

    • Scissors cut Paper
    • Paper covers Rock
    • Rock crushes Lizard
    • Lizard poisons Spock
    • Spock smashes Scissors
    • Scissors decapitate Lizard
    • Lizard eats Paper
    • Paper disproves Spock
    • Spock vaporizes Rock
    • Rock crushes Scissors

    These rules are summarized in the following image:

    Your DSL should support five “literal” values: Rock, Paper, Scissors, Lizard, and Spock. These values can be combined with the plus (+), minus (-) and parenthesis operators to conform complex expressions. Let A and B be expressions. The expression “A + B” returns the winner between A and B, while “A - B” returns the loser. Additionally, whenever the + and - operators execute the rule being applied is displayed on the standard output. Precedence and associativity of the operators follow Ruby’s rules.

    For example, this DSL code:

    show Spock - (Lizard + Paper)
    

    should display the following:

    Lizard eats Paper (winner Lizard)
    Lizard poisons Spock (loser Spock)
    Result = Spock

    The show command is responsible for the last line of the output, showing the result of the expression it takes as input.

    Notice that the result and effect of “A + B” are the same as “B + A”. The same is true for “A - B” and “B - A”.

    It’s possible to have a tie. This code:

    show Spock + Spock
    

    should generate this output:

    Spock tie (winner Spock)
    Result = Spock
  3. The following unit tests verify the correct behavior of your DSL. Place the test class in the tc_jankenpon.rb source file.

    # File: tc_jankenpon.rb
    
    require 'test/unit'
    require 'stringio'
    require 'jankenpon'
    
    class JakenponTest < Test::Unit::TestCase
    
      def setup
        @old_stdout = $stdout
        @out = $stdout = StringIO.new
      end
    
      def teardown
        $stdout = @old_stdout
      end
    
      def test_simple_cases_plus
        assert_equal Scissors, (Scissors + Paper)
        assert_equal Scissors, (Paper + Scissors)
        assert_equal Paper,    (Paper + Rock)
        assert_equal Paper,    (Rock + Paper)
        assert_equal Rock,     (Rock + Lizard)
        assert_equal Rock,     (Lizard + Rock)
        assert_equal Lizard,   (Lizard + Spock)
        assert_equal Lizard,   (Spock + Lizard)
        assert_equal Spock,    (Spock + Scissors)
        assert_equal Spock,    (Scissors + Spock)
        assert_equal Scissors, (Scissors + Lizard)
        assert_equal Scissors, (Lizard + Scissors)
        assert_equal Lizard,   (Lizard + Paper)
        assert_equal Lizard,   (Paper + Lizard)
        assert_equal Paper,    (Paper + Spock)
        assert_equal Paper,    (Spock + Paper)
        assert_equal Spock,    (Spock + Rock)
        assert_equal Spock,    (Rock + Spock)
        assert_equal Rock,     (Rock + Scissors)
        assert_equal Rock,     (Scissors + Rock)
        assert_equal Scissors, (Scissors + Scissors)
        assert_equal Paper,    (Paper + Paper)
        assert_equal Rock,     (Rock + Rock)
        assert_equal Lizard,   (Lizard + Lizard)
        assert_equal Spock,    (Spock + Spock)
      end
    
      def test_simple_cases_minus
        assert_equal Paper,    (Scissors - Paper)
        assert_equal Paper,    (Paper - Scissors)
        assert_equal Rock,     (Paper - Rock)
        assert_equal Rock,     (Rock - Paper)
        assert_equal Lizard,   (Rock - Lizard)
        assert_equal Lizard,   (Lizard - Rock)
        assert_equal Spock,    (Lizard - Spock)
        assert_equal Spock,    (Spock - Lizard)
        assert_equal Scissors, (Spock - Scissors)
        assert_equal Scissors, (Scissors - Spock)
        assert_equal Lizard,   (Scissors - Lizard)
        assert_equal Lizard,   (Lizard - Scissors)
        assert_equal Paper,    (Lizard - Paper)
        assert_equal Paper,    (Paper - Lizard)
        assert_equal Spock,    (Paper - Spock)
        assert_equal Spock,    (Spock - Paper)
        assert_equal Rock,     (Spock - Rock)
        assert_equal Rock,     (Rock - Spock)
        assert_equal Scissors, (Rock - Scissors)
        assert_equal Scissors, (Scissors - Rock)
        assert_equal Scissors, (Scissors - Scissors)
        assert_equal Paper,    (Paper - Paper)
        assert_equal Rock,     (Rock - Rock)
        assert_equal Lizard,   (Lizard - Lizard)
        assert_equal Spock,    (Spock - Spock)
      end
    
      def test_dsl_1
        #---------
        show Spock
        #---------
        assert_equal "Result = Spock\n", @out.string
      end
    
      def test_dsl_2
        #------------------
        show Spock + Lizard
        #------------------
        assert_equal "Lizard poisons Spock (winner Lizard)\n" \
                     "Result = Lizard\n", \
                     @out.string
      end
    
      def test_dsl_3
        #------------------
        show Spock - Lizard
        #------------------
        assert_equal "Lizard poisons Spock (loser Spock)\n" \
                     "Result = Spock\n", \
                     @out.string
      end
    
      def test_dsl_4
        #-------------------------
        show Spock + Lizard + Rock
        #-------------------------
        assert_equal "Lizard poisons Spock (winner Lizard)\n" \
                     "Rock crushes Lizard (winner Rock)\n" \
                     "Result = Rock\n", \
                     @out.string
      end
    
      def test_dsl_5
        #---------------------------
        show Spock + (Lizard + Rock)
        #---------------------------
        assert_equal "Rock crushes Lizard (winner Rock)\n" \
                     "Spock vaporizes Rock (winner Spock)\n" \
                     "Result = Spock\n", \
                     @out.string
      end
    
      def test_dsl_6
        #--------------------------------------------
        show Rock + Paper + Scissors + Lizard + Spock
        #--------------------------------------------
        assert_equal "Paper covers Rock (winner Paper)\n" \
                     "Scissors cut Paper (winner Scissors)\n" \
                     "Scissors decapitate Lizard (winner Scissors)\n" \
                     "Spock smashes Scissors (winner Spock)\n" \
                     "Result = Spock\n", \
                     @out.string
      end
    
      def test_dsl_7
        #--------------------------------------------
        show Rock - Paper - Scissors - Lizard - Spock
        #--------------------------------------------
        assert_equal "Paper covers Rock (loser Rock)\n" \
                     "Rock crushes Scissors (loser Scissors)\n" \
                     "Scissors decapitate Lizard (loser Lizard)\n" \
                     "Lizard poisons Spock (loser Spock)\n" \
                     "Result = Spock\n", \
                     @out.string
      end
    
      def test_dsl_8
        #-------------------------------------------------
        show((Rock + Paper) - (Scissors + Lizard) + Spock)
        #-------------------------------------------------
        assert_equal "Paper covers Rock (winner Paper)\n" \
                     "Scissors decapitate Lizard (winner Scissors)\n" \
                     "Scissors cut Paper (loser Paper)\n" \
                     "Paper disproves Spock (winner Paper)\n" \
                     "Result = Paper\n", \
                     @out.string
      end
    
      def test_dsl_9
        #---------------------------------------------
        show Paper + ((Spock + Paper) - Lizard + Rock)
        #---------------------------------------------
        assert_equal "Paper disproves Spock (winner Paper)\n" \
                     "Lizard eats Paper (loser Paper)\n" \
                     "Paper covers Rock (winner Paper)\n" \
                     "Paper tie (winner Paper)\n" \
                     "Result = Paper\n", \
                     @out.string
      end
      
    end
    

Deliverables

To hand in your individual lab work, follow these instructions.

Due date is Tuesday, April 9.

Evaluation

This activity will be evaluated using the following criteria:

50% Implementation of functional requirements.
50% Lab report.
DA The program and/or report was plagiarized.