gift-parser 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
 - data/LICENCE +23 -0
 - data/README +18 -0
 - data/RakeFile +39 -0
 - data/VERSION +1 -0
 - data/gift-parser.gemspec +57 -0
 - data/github.com +0 -0
 - data/lib/gift.rb +267 -0
 - data/lib/gift_parser.rb +3242 -0
 - data/src/gift_parser.treetop +207 -0
 - data/test/GIFT-examples.rb +400 -0
 - data/test/GIFT-examples.txt +27 -0
 - data/test/gift_semantic_test.rb +179 -0
 - data/test/gift_syntax_test.rb +243 -0
 - data/test/gift_test.rb +55 -0
 - metadata +79 -0
 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            // true/false
         
     | 
| 
      
 2 
     | 
    
         
            +
            ::Q1:: 1+1=2 {T}
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            // multiple choice with specified feedback for right and wrong answers
         
     | 
| 
      
 5 
     | 
    
         
            +
            ::Q2:: What's between orange and green in the spectrum? 
         
     | 
| 
      
 6 
     | 
    
         
            +
            { =yellow # right; good! ~red # wrong, it's yellow ~blue # wrong, it's yellow }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            // fill-in-the-blank
         
     | 
| 
      
 9 
     | 
    
         
            +
            ::Q3:: Two plus {=two =2} equals four.
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            // matching
         
     | 
| 
      
 12 
     | 
    
         
            +
            ::Q4:: Which animal eats which food? { =cat -> cat food =dog -> dog food }
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            // math range question
         
     | 
| 
      
 15 
     | 
    
         
            +
            ::Q5:: What is a number from 1 to 5? {#3:2}
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            // math range specified with interval end points
         
     | 
| 
      
 18 
     | 
    
         
            +
            ::Q6:: What is a number from 1 to 5? {#1..5}
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            // multiple numeric answers with partial credit and feedback
         
     | 
| 
      
 21 
     | 
    
         
            +
            ::Q7:: When was Ulysses S. Grant born? {#
         
     | 
| 
      
 22 
     | 
    
         
            +
                     =1822:0      # Correct! Full credit.
         
     | 
| 
      
 23 
     | 
    
         
            +
                     =%50%1822:2  # He was born in 1822. Half credit for being close.
         
     | 
| 
      
 24 
     | 
    
         
            +
            }
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            // essay
         
     | 
| 
      
 27 
     | 
    
         
            +
            ::Q8:: How are you? {}
         
     | 
| 
         @@ -0,0 +1,179 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Tests for GIFT parser
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # This only tests that the input is parsed.
         
     | 
| 
      
 5 
     | 
    
         
            +
            # so far does not test output.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'test/unit/ui/console/testrunner'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            require File.expand_path('../../lib/gift',  __FILE__)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            class GiftSemanticTest < Test::Unit::TestCase
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
              attr_accessor :parser
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def setup
         
     | 
| 
      
 18 
     | 
    
         
            +
                @parser = GiftParser.new
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def assert_can_parse(string)
         
     | 
| 
      
 22 
     | 
    
         
            +
                string << "\n\n" # Insert a blank line at end of string
         
     | 
| 
      
 23 
     | 
    
         
            +
                assert !@parser.parse(string).nil?, "Failed on:\n#{string}\n Reason:\n#{@parser.failure_reason.inspect}\n"
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              
         
     | 
| 
      
 26 
     | 
    
         
            +
              def assert_cannot_parse(string)
         
     | 
| 
      
 27 
     | 
    
         
            +
                string << "\n\n" # Insert a blank line at end of string
         
     | 
| 
      
 28 
     | 
    
         
            +
                p = @parser.parse(string)
         
     | 
| 
      
 29 
     | 
    
         
            +
                assert p.nil?, "Failed on:\n#{string}\n Reason:\nThis should not be correctly parsed, but was.\nParser Output:\n#{p.inspect}"
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
              
         
     | 
| 
      
 32 
     | 
    
         
            +
              def test_description_question
         
     | 
| 
      
 33 
     | 
    
         
            +
                q = @parser.parse("This is a description.\n\n").questions[0]
         
     | 
| 
      
 34 
     | 
    
         
            +
                assert q.class == Gift::DescriptionQuestion
         
     | 
| 
      
 35 
     | 
    
         
            +
                assert q.text == "This is a description."
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              def test_essay_question
         
     | 
| 
      
 39 
     | 
    
         
            +
                q = @parser.parse("Write an essay on the toic of your choice{ }\n\n").questions[0]
         
     | 
| 
      
 40 
     | 
    
         
            +
                assert q.class == Gift::EssayQuestion
         
     | 
| 
      
 41 
     | 
    
         
            +
                assert q.text == "Write an essay on the toic of your choice"
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
              
         
     | 
| 
      
 44 
     | 
    
         
            +
              def test_true_false_question_true
         
     | 
| 
      
 45 
     | 
    
         
            +
                q = @parser.parse("Is the sky blue?{T}\n\n").questions[0]
         
     | 
| 
      
 46 
     | 
    
         
            +
                assert q.class == Gift::TrueFalseQuestion
         
     | 
| 
      
 47 
     | 
    
         
            +
                assert q.text == "Is the sky blue?"
         
     | 
| 
      
 48 
     | 
    
         
            +
                assert q.answers == [{:value => true, :correct => true, :feedback => nil}]
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
              
         
     | 
| 
      
 51 
     | 
    
         
            +
              def test_true_false_question_false
         
     | 
| 
      
 52 
     | 
    
         
            +
                q = @parser.parse("Is the sky green?{F}\n\n").questions[0]
         
     | 
| 
      
 53 
     | 
    
         
            +
                assert q.text == "Is the sky green?"
         
     | 
| 
      
 54 
     | 
    
         
            +
                assert q.answers == [{:value => false, :correct => true, :feedback => nil}]
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
              
         
     | 
| 
      
 57 
     | 
    
         
            +
              def test_tf_with_feedback
         
     | 
| 
      
 58 
     | 
    
         
            +
                q = @parser.parse("Is the sky green?{F#No It's blue.}\n\n").questions[0]
         
     | 
| 
      
 59 
     | 
    
         
            +
                assert q.text == "Is the sky green?"
         
     | 
| 
      
 60 
     | 
    
         
            +
                assert q.answers == [{:value => false, :correct => true, :feedback => "No It's blue."}]
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
              
         
     | 
| 
      
 63 
     | 
    
         
            +
              def test_multiple_choice_question
         
     | 
| 
      
 64 
     | 
    
         
            +
                q = @parser.parse("What color is the sky?{=blue ~green ~red}\n\n").questions[0]
         
     | 
| 
      
 65 
     | 
    
         
            +
                assert q.class == Gift::MultipleChoiceQuestion
         
     | 
| 
      
 66 
     | 
    
         
            +
                assert q.text == "What color is the sky?"
         
     | 
| 
      
 67 
     | 
    
         
            +
                assert q.answers ==  [{:value => "blue", :correct => true, :feedback => nil}, 
         
     | 
| 
      
 68 
     | 
    
         
            +
                                     {:value => "green", :correct => false, :feedback => nil},
         
     | 
| 
      
 69 
     | 
    
         
            +
                                     {:value => "red", :correct => false, :feedback => nil}]
         
     | 
| 
      
 70 
     | 
    
         
            +
                
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
              
         
     | 
| 
      
 73 
     | 
    
         
            +
              def test_multiple_choice_question_with_feedback
         
     | 
| 
      
 74 
     | 
    
         
            +
                q = @parser.parse("What color is the sky?{=blue#Correct ~green#Wrong! ~red}\n\n").questions[0]
         
     | 
| 
      
 75 
     | 
    
         
            +
                assert q.answers ==  [{:value => "blue", :correct => true, :feedback => "Correct"}, 
         
     | 
| 
      
 76 
     | 
    
         
            +
                                     {:value => "green", :correct => false, :feedback => "Wrong!"},
         
     | 
| 
      
 77 
     | 
    
         
            +
                                     {:value => "red", :correct => false, :feedback => nil}]
         
     | 
| 
      
 78 
     | 
    
         
            +
                
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
              
         
     | 
| 
      
 81 
     | 
    
         
            +
              def test_multiple_choice_question_with_weights
         
     | 
| 
      
 82 
     | 
    
         
            +
                q = @parser.parse("What color is the sky?{=blue#Correct ~%50%green#Wrong! ~red}\n\n").questions[0]
         
     | 
| 
      
 83 
     | 
    
         
            +
                assert q.answers ==  [{:value => "blue", :correct => true, :feedback => "Correct"}, 
         
     | 
| 
      
 84 
     | 
    
         
            +
                                     {:value => "green", :correct => false, :feedback => "Wrong!", :weight => 50.0},
         
     | 
| 
      
 85 
     | 
    
         
            +
                                     {:value => "red", :correct => false, :feedback => nil}]
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
              
         
     | 
| 
      
 88 
     | 
    
         
            +
              def test_short_answer_question
         
     | 
| 
      
 89 
     | 
    
         
            +
                q = @parser.parse("Who's buried in Grant's tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}\n\n").questions[0]
         
     | 
| 
      
 90 
     | 
    
         
            +
                assert q.class == Gift::ShortAnswerQuestion
         
     | 
| 
      
 91 
     | 
    
         
            +
                assert q.text == "Who's buried in Grant's tomb?"
         
     | 
| 
      
 92 
     | 
    
         
            +
                assert q.answers == [{:feedback => nil, :value => "Grant", :correct => true}, 
         
     | 
| 
      
 93 
     | 
    
         
            +
                                     {:feedback => nil, :value => "Ulysses S. Grant", :correct => true}, 
         
     | 
| 
      
 94 
     | 
    
         
            +
                                     {:feedback => nil, :value => "Ulysses Grant" , :correct => true}]
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
              
         
     | 
| 
      
 97 
     | 
    
         
            +
              def test_short_answer_question_with_weights
         
     | 
| 
      
 98 
     | 
    
         
            +
                q = @parser.parse("Name three colors of the rainbow?{=%33.3%red =%33.3%orange =%33.3%yellow =%33.3%green =%33.3%blue =%33.3%indigo =%33.3%violet }\n\n").questions[0]
         
     | 
| 
      
 99 
     | 
    
         
            +
                q.answers.each do |a|
         
     | 
| 
      
 100 
     | 
    
         
            +
                  assert a[:weight] == 33.3
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
              end
         
     | 
| 
      
 103 
     | 
    
         
            +
              
         
     | 
| 
      
 104 
     | 
    
         
            +
              def test_numeric_question
         
     | 
| 
      
 105 
     | 
    
         
            +
                q = @parser.parse("What is 3 + 4?{#7}\n\n").questions[0]
         
     | 
| 
      
 106 
     | 
    
         
            +
                assert q.class == Gift::NumericQuestion
         
     | 
| 
      
 107 
     | 
    
         
            +
                assert q.answers == [{:maximum => 7.0, :minimum => 7.0}]
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
              
         
     | 
| 
      
 110 
     | 
    
         
            +
              def test_numeric_with_tolerance
         
     | 
| 
      
 111 
     | 
    
         
            +
                q = @parser.parse("What is the value of PI?{#3.1:0.5}\n\n").questions[0]
         
     | 
| 
      
 112 
     | 
    
         
            +
                assert q.answers == [{:maximum => 3.6, :minimum => 2.6}]
         
     | 
| 
      
 113 
     | 
    
         
            +
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
              
         
     | 
| 
      
 115 
     | 
    
         
            +
              def test_numeric_range
         
     | 
| 
      
 116 
     | 
    
         
            +
                q = @parser.parse("What is a number from 1 to 5? {#1..5}\n\n").questions[0]
         
     | 
| 
      
 117 
     | 
    
         
            +
                assert q.answers == [{:maximum => 1.0, :minimum => 5.0}]
         
     | 
| 
      
 118 
     | 
    
         
            +
              end
         
     | 
| 
      
 119 
     | 
    
         
            +
              
         
     | 
| 
      
 120 
     | 
    
         
            +
              def test_numeric_multiple_answers
         
     | 
| 
      
 121 
     | 
    
         
            +
                q = @parser.parse("What is the value of PI?{#3.1415 =%50%3.1 =%25%3 }\n\n").questions[0]
         
     | 
| 
      
 122 
     | 
    
         
            +
                assert q.answers == [{:maximum => 3.1415, :minimum => 3.1415}, 
         
     | 
| 
      
 123 
     | 
    
         
            +
                                     {:maximum => 3.1, :minimum => 3.1},
         
     | 
| 
      
 124 
     | 
    
         
            +
                                     {:maximum => 3.0, :minimum => 3.0}]
         
     | 
| 
      
 125 
     | 
    
         
            +
              end
         
     | 
| 
      
 126 
     | 
    
         
            +
              
         
     | 
| 
      
 127 
     | 
    
         
            +
              def test_numeric_neagitve_numbers
         
     | 
| 
      
 128 
     | 
    
         
            +
                q = @parser.parse("Calculate 2 - 6.{#-4.0}\n\n").questions[0]
         
     | 
| 
      
 129 
     | 
    
         
            +
                assert q.answers == [{:maximum => -4.0, :minimum => -4.0}]
         
     | 
| 
      
 130 
     | 
    
         
            +
              end
         
     | 
| 
      
 131 
     | 
    
         
            +
              
         
     | 
| 
      
 132 
     | 
    
         
            +
              def test_matching_question
         
     | 
| 
      
 133 
     | 
    
         
            +
                q = @parser.parse("Match the names. { =Charlie -> Chaplin =Groucho -> Marx =Buster -> Keaton  =Stan -> Laurel }\n\n").questions[0]
         
     | 
| 
      
 134 
     | 
    
         
            +
                assert q.class == Gift::MatchQuestion 
         
     | 
| 
      
 135 
     | 
    
         
            +
                assert q.text == "Match the names."
         
     | 
| 
      
 136 
     | 
    
         
            +
                assert q.answers == {'Charlie' => 'Chaplin', 'Groucho' => 'Marx', 'Buster' => 'Keaton', 'Stan' => 'Laurel'}
         
     | 
| 
      
 137 
     | 
    
         
            +
              end
         
     | 
| 
      
 138 
     | 
    
         
            +
              
         
     | 
| 
      
 139 
     | 
    
         
            +
              def test_fill_in_question
         
     | 
| 
      
 140 
     | 
    
         
            +
                q = @parser.parse("There were {=three} little pigs.\n\n").questions[0]
         
     | 
| 
      
 141 
     | 
    
         
            +
                assert q.class == Gift::FillInQuestion
         
     | 
| 
      
 142 
     | 
    
         
            +
                assert q.text == "There were %% little pigs."
         
     | 
| 
      
 143 
     | 
    
         
            +
                assert q.answers == [{:value => 'three', :correct => true, :feedback => nil}]
         
     | 
| 
      
 144 
     | 
    
         
            +
              end
         
     | 
| 
      
 145 
     | 
    
         
            +
              
         
     | 
| 
      
 146 
     | 
    
         
            +
              def test_title
         
     | 
| 
      
 147 
     | 
    
         
            +
                q = @parser.parse("::Essay One:: Write an essay on the toic of your choice{ }\n\n").questions[0]
         
     | 
| 
      
 148 
     | 
    
         
            +
                assert q.title == "Essay One"
         
     | 
| 
      
 149 
     | 
    
         
            +
              end 
         
     | 
| 
      
 150 
     | 
    
         
            +
              
         
     | 
| 
      
 151 
     | 
    
         
            +
              def test_title_from_question
         
     | 
| 
      
 152 
     | 
    
         
            +
                q = @parser.parse("Write an essay on the toic of your choice{ }\n\n").questions[0]
         
     | 
| 
      
 153 
     | 
    
         
            +
                assert q.title == q.text
         
     | 
| 
      
 154 
     | 
    
         
            +
              end
         
     | 
| 
      
 155 
     | 
    
         
            +
              
         
     | 
| 
      
 156 
     | 
    
         
            +
              def test_comment
         
     | 
| 
      
 157 
     | 
    
         
            +
                q = @parser.parse("//Here's an easy one\nWrite an essay on the toic of your choice{ }\n\n").questions[0]
         
     | 
| 
      
 158 
     | 
    
         
            +
                assert q.comment == "Here's an easy one"
         
     | 
| 
      
 159 
     | 
    
         
            +
              end
         
     | 
| 
      
 160 
     | 
    
         
            +
              
         
     | 
| 
      
 161 
     | 
    
         
            +
              def test_command
         
     | 
| 
      
 162 
     | 
    
         
            +
                q = @parser.parse("$COMMAND=1\n\nQuestion{}\n\n")
         
     | 
| 
      
 163 
     | 
    
         
            +
                assert q.commands == ["COMMAND=1"]
         
     | 
| 
      
 164 
     | 
    
         
            +
              end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
         
     | 
| 
      
 166 
     | 
    
         
            +
              def test_category_setting
         
     | 
| 
      
 167 
     | 
    
         
            +
                q = @parser.parse("$CATEGORY: food \n\nIs apple a food?{T}\n\n$CATEGORY: drink \n\nIs water drinkable?{T}\n\n" )
         
     | 
| 
      
 168 
     | 
    
         
            +
                assert q.questions[0].category == "food"
         
     | 
| 
      
 169 
     | 
    
         
            +
                assert q.questions[1].category == "drink"
         
     | 
| 
      
 170 
     | 
    
         
            +
              end
         
     | 
| 
      
 171 
     | 
    
         
            +
              
         
     | 
| 
      
 172 
     | 
    
         
            +
              def test_markup_type
         
     | 
| 
      
 173 
     | 
    
         
            +
                q = @parser.parse("[textile] This *essay* is marked up in textile.{}\n\n").questions[0]
         
     | 
| 
      
 174 
     | 
    
         
            +
                assert q.markup == "textile"
         
     | 
| 
      
 175 
     | 
    
         
            +
              end
         
     | 
| 
      
 176 
     | 
    
         
            +
              
         
     | 
| 
      
 177 
     | 
    
         
            +
            end
         
     | 
| 
      
 178 
     | 
    
         
            +
             
     | 
| 
      
 179 
     | 
    
         
            +
            Test::Unit::UI::Console::TestRunner.run(GiftSemanticTest)
         
     | 
| 
         @@ -0,0 +1,243 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Tests for GIFT parser
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # This only tests that the input is parsed.
         
     | 
| 
      
 5 
     | 
    
         
            +
            # so far does not test output.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'test/unit'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'test/unit/ui/console/testrunner'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            require File.expand_path('../../lib/gift',  __FILE__)
         
     | 
| 
      
 12 
     | 
    
         
            +
            require File.expand_path('../GIFT-examples.rb', __FILE__)
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            class GiftSyntaxTest < Test::Unit::TestCase
         
     | 
| 
      
 16 
     | 
    
         
            +
              
         
     | 
| 
      
 17 
     | 
    
         
            +
              attr_accessor :parser
         
     | 
| 
      
 18 
     | 
    
         
            +
              
         
     | 
| 
      
 19 
     | 
    
         
            +
              def setup
         
     | 
| 
      
 20 
     | 
    
         
            +
                @parser = GiftParser.new
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              def assert_can_parse(string)
         
     | 
| 
      
 24 
     | 
    
         
            +
                string << "\n\n" # Insert a blank line at end of string
         
     | 
| 
      
 25 
     | 
    
         
            +
                assert !@parser.parse(string).nil?, "Failed on:\n#{string}\n Reason:\n#{@parser.failure_reason.inspect}\n"
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
              
         
     | 
| 
      
 28 
     | 
    
         
            +
              def assert_cannot_parse(string)
         
     | 
| 
      
 29 
     | 
    
         
            +
                string << "\n\n"
         
     | 
| 
      
 30 
     | 
    
         
            +
                p = @parser.parse(string)
         
     | 
| 
      
 31 
     | 
    
         
            +
                assert p.nil?, "Failed on:\n#{string}\n Reason:\nThis should not be correctly parsed, but was.\nParser Output:\n#{p.inspect}"
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
              
         
     | 
| 
      
 34 
     | 
    
         
            +
              def test_essay_question
         
     | 
| 
      
 35 
     | 
    
         
            +
                assert_can_parse("Write an essay about something.{}")
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              def test_description_question
         
     | 
| 
      
 39 
     | 
    
         
            +
               assert_can_parse("This is simply a description")
         
     | 
| 
      
 40 
     | 
    
         
            +
              end 
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              def test_true_false_questions
         
     | 
| 
      
 43 
     | 
    
         
            +
                assert_can_parse("The sky is blue.{T}")
         
     | 
| 
      
 44 
     | 
    
         
            +
                assert_can_parse("The sky is blue.{TRUE}")
         
     | 
| 
      
 45 
     | 
    
         
            +
                assert_can_parse("The sky is green.{F}")
         
     | 
| 
      
 46 
     | 
    
         
            +
                assert_can_parse("The sky is blue.{FALSE}")
         
     | 
| 
      
 47 
     | 
    
         
            +
              end 
         
     | 
| 
      
 48 
     | 
    
         
            +
              
         
     | 
| 
      
 49 
     | 
    
         
            +
              def test_feedback
         
     | 
| 
      
 50 
     | 
    
         
            +
                assert_can_parse("Grant is buried in Grant's tomb.{FALSE#No one is buried in Grant's tomb.}")       
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
              
         
     | 
| 
      
 53 
     | 
    
         
            +
              def test_multiple_choice_question
         
     | 
| 
      
 54 
     | 
    
         
            +
                assert_can_parse("What color is the sky?{ = Blue ~Green ~Red }")
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
              
         
     | 
| 
      
 57 
     | 
    
         
            +
              def test_multiple_choice_question_with_feedback
         
     | 
| 
      
 58 
     | 
    
         
            +
                assert_can_parse('What color is the sky?{ = Blue#Right ~Green ~Red#Very wrong}')
         
     | 
| 
      
 59 
     | 
    
         
            +
              end                                                    
         
     | 
| 
      
 60 
     | 
    
         
            +
              
         
     | 
| 
      
 61 
     | 
    
         
            +
              def test_multiple_choice_on_multiple_lines
         
     | 
| 
      
 62 
     | 
    
         
            +
                test_text= <<EOS
         
     | 
| 
      
 63 
     | 
    
         
            +
                What color is the sky?{ 
         
     | 
| 
      
 64 
     | 
    
         
            +
                = Blue#Right 
         
     | 
| 
      
 65 
     | 
    
         
            +
                ~Green 
         
     | 
| 
      
 66 
     | 
    
         
            +
                ~Red
         
     | 
| 
      
 67 
     | 
    
         
            +
                #Very wrong
         
     | 
| 
      
 68 
     | 
    
         
            +
                }
         
     | 
| 
      
 69 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 70 
     | 
    
         
            +
                assert_can_parse(test_text)
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
              
         
     | 
| 
      
 73 
     | 
    
         
            +
              def test_multiple_choice_with_weights
         
     | 
| 
      
 74 
     | 
    
         
            +
                assert_can_parse('Which of these are primary colors?{ ~%33%Blue ~%33%Yellow ~Beige ~%33%Red}')
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
                
         
     | 
| 
      
 77 
     | 
    
         
            +
              def test_numeric_question
         
     | 
| 
      
 78 
     | 
    
         
            +
                assert_can_parse("How many pounds in a kilogram?{#2.2:0.1}")
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
              
         
     | 
| 
      
 81 
     | 
    
         
            +
              def test_numeric_question_with_multiple_answer
         
     | 
| 
      
 82 
     | 
    
         
            +
                assert_can_parse("How many pounds in a kilogram?{# =2.2:0.1 =%50%2 }")
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
              
         
     | 
| 
      
 85 
     | 
    
         
            +
              def test_numeric_range_question
         
     | 
| 
      
 86 
     | 
    
         
            +
                assert_can_parse("::Q5:: What is a number from 1 to 5? {#1..5}")
         
     | 
| 
      
 87 
     | 
    
         
            +
              end 
         
     | 
| 
      
 88 
     | 
    
         
            +
              
         
     | 
| 
      
 89 
     | 
    
         
            +
              def test_numeric_negative_number
         
     | 
| 
      
 90 
     | 
    
         
            +
                assert_can_parse("What is 6 - 10?{#-4}")
         
     | 
| 
      
 91 
     | 
    
         
            +
              end
         
     | 
| 
      
 92 
     | 
    
         
            +
               
         
     | 
| 
      
 93 
     | 
    
         
            +
              def test_short_answer
         
     | 
| 
      
 94 
     | 
    
         
            +
                assert_can_parse("Who's buried in Grant's tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}")
         
     | 
| 
      
 95 
     | 
    
         
            +
              end
         
     | 
| 
      
 96 
     | 
    
         
            +
              
         
     | 
| 
      
 97 
     | 
    
         
            +
              def test_matching_question
         
     | 
| 
      
 98 
     | 
    
         
            +
                test_text= <<EOS
         
     | 
| 
      
 99 
     | 
    
         
            +
                Match the following countries with their corresponding capitals. {
         
     | 
| 
      
 100 
     | 
    
         
            +
                   =Canada -> Ottawa
         
     | 
| 
      
 101 
     | 
    
         
            +
                   =Italy  -> Rome
         
     | 
| 
      
 102 
     | 
    
         
            +
                   =Japan  -> Tokyo
         
     | 
| 
      
 103 
     | 
    
         
            +
                   =India  -> New Delhi
         
     | 
| 
      
 104 
     | 
    
         
            +
                   }
         
     | 
| 
      
 105 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 106 
     | 
    
         
            +
                 assert_can_parse(test_text) 
         
     | 
| 
      
 107 
     | 
    
         
            +
              end
         
     | 
| 
      
 108 
     | 
    
         
            +
              
         
     | 
| 
      
 109 
     | 
    
         
            +
              def test_fill_in_question
         
     | 
| 
      
 110 
     | 
    
         
            +
                assert_can_parse("Little {~blue =red ~green } riding hood.\n") 
         
     | 
| 
      
 111 
     | 
    
         
            +
                assert_can_parse("Two plus two equals {=four =4}.\n")
         
     | 
| 
      
 112 
     | 
    
         
            +
              end
         
     | 
| 
      
 113 
     | 
    
         
            +
              
         
     | 
| 
      
 114 
     | 
    
         
            +
              def test_question_with_title
         
     | 
| 
      
 115 
     | 
    
         
            +
                assert_can_parse('::Colors 1:: Which of these are primary colors?{ ~%33%Blue ~%33%Yellow ~Beige ~%33%Red}')
         
     | 
| 
      
 116 
     | 
    
         
            +
              end
         
     | 
| 
      
 117 
     | 
    
         
            +
              
         
     | 
| 
      
 118 
     | 
    
         
            +
              def test_question_with_comment
         
     | 
| 
      
 119 
     | 
    
         
            +
                assert_can_parse("//This is an easy one\n Which of these are primary colors?{ ~%33%Blue ~%33%Yellow ~Beige ~%33%Red}")
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
              
         
     | 
| 
      
 122 
     | 
    
         
            +
              def test_multiline_comments
         
     | 
| 
      
 123 
     | 
    
         
            +
                 assert_can_parse("//This is an easy one\n//With more than one line of comment\nWhich of these are primary colors?{ ~%33%Blue ~%33%Yellow ~Beige ~%33%Red}")
         
     | 
| 
      
 124 
     | 
    
         
            +
              end
         
     | 
| 
      
 125 
     | 
    
         
            +
              
         
     | 
| 
      
 126 
     | 
    
         
            +
              def test_that_questions_must_be_separated 
         
     | 
| 
      
 127 
     | 
    
         
            +
                test_text = <<EOS
         
     | 
| 
      
 128 
     | 
    
         
            +
                Who's buried in Grant's tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}
         
     | 
| 
      
 129 
     | 
    
         
            +
                Which of these are primary colors?{ ~%33%Blue ~%33%Yellow ~Beige ~%33%Red}
         
     | 
| 
      
 130 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 131 
     | 
    
         
            +
                assert_cannot_parse(test_text)
         
     | 
| 
      
 132 
     | 
    
         
            +
                
         
     | 
| 
      
 133 
     | 
    
         
            +
                test_text = <<EOS
         
     | 
| 
      
 134 
     | 
    
         
            +
                    Who's buried in Grant's tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}
         
     | 
| 
      
 135 
     | 
    
         
            +
                    
         
     | 
| 
      
 136 
     | 
    
         
            +
                    Which of these are primary colors?{ ~%33%Blue ~%33%Yellow ~Beige ~%33%Red}
         
     | 
| 
      
 137 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 138 
     | 
    
         
            +
                 assert_can_parse(test_text)
         
     | 
| 
      
 139 
     | 
    
         
            +
              end
         
     | 
| 
      
 140 
     | 
    
         
            +
              
         
     | 
| 
      
 141 
     | 
    
         
            +
              def test_escape_left_bracket
         
     | 
| 
      
 142 
     | 
    
         
            +
                assert_can_parse('Can a \{ be escaped?{=Yes ~No}')
         
     | 
| 
      
 143 
     | 
    
         
            +
                assert_can_parse('Can a \{ be escaped?{=Yes ~No\{ }')
         
     | 
| 
      
 144 
     | 
    
         
            +
                
         
     | 
| 
      
 145 
     | 
    
         
            +
              end
         
     | 
| 
      
 146 
     | 
    
         
            +
              
         
     | 
| 
      
 147 
     | 
    
         
            +
              def test_escape_right_bracket
         
     | 
| 
      
 148 
     | 
    
         
            +
                assert_can_parse('Can a \} be escaped?{=Yes \} can be escaped. ~No}') 
         
     | 
| 
      
 149 
     | 
    
         
            +
                
         
     | 
| 
      
 150 
     | 
    
         
            +
              end
         
     | 
| 
      
 151 
     | 
    
         
            +
              
         
     | 
| 
      
 152 
     | 
    
         
            +
              def test_escape_tilde
         
     | 
| 
      
 153 
     | 
    
         
            +
                assert_can_parse('Can a \~ be escaped?{=Yes ~No \~ can\'t}')
         
     | 
| 
      
 154 
     | 
    
         
            +
              end
         
     | 
| 
      
 155 
     | 
    
         
            +
              
         
     | 
| 
      
 156 
     | 
    
         
            +
              def test_escape_hash
         
     | 
| 
      
 157 
     | 
    
         
            +
                assert_can_parse('Can a \# be escaped?{=Yes \# can ~No}')
         
     | 
| 
      
 158 
     | 
    
         
            +
              end 
         
     | 
| 
      
 159 
     | 
    
         
            +
              
         
     | 
| 
      
 160 
     | 
    
         
            +
              def test_escape_equals
         
     | 
| 
      
 161 
     | 
    
         
            +
                assert_can_parse('Can a \= be escaped?{=Yes ~No}')
         
     | 
| 
      
 162 
     | 
    
         
            +
              end
         
     | 
| 
      
 163 
     | 
    
         
            +
              
         
     | 
| 
      
 164 
     | 
    
         
            +
              def test_escape_colon
         
     | 
| 
      
 165 
     | 
    
         
            +
                assert_can_parse('Can a \: be escaped?{=Yes \: can be escaped. ~No}')
         
     | 
| 
      
 166 
     | 
    
         
            +
              end
         
     | 
| 
      
 167 
     | 
    
         
            +
              
         
     | 
| 
      
 168 
     | 
    
         
            +
              def test_escapes_in_title
         
     | 
| 
      
 169 
     | 
    
         
            +
                assert_can_parse('::\{This is in\: Brackets\}::Who\'s buried in Grant\'s tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}')
         
     | 
| 
      
 170 
     | 
    
         
            +
              end
         
     | 
| 
      
 171 
     | 
    
         
            +
              
         
     | 
| 
      
 172 
     | 
    
         
            +
              def test_escapes_in_comment
         
     | 
| 
      
 173 
     | 
    
         
            +
                assert_can_parse("//Escapes in comments are redundant \\: since they end in a \n Question?{}")
         
     | 
| 
      
 174 
     | 
    
         
            +
              end
         
     | 
| 
      
 175 
     | 
    
         
            +
              
         
     | 
| 
      
 176 
     | 
    
         
            +
              def test_crlf_support
         
     | 
| 
      
 177 
     | 
    
         
            +
                assert_can_parse("Can we have DOS style line breaks?{\r\n=yes \r\n~no}\r\n \r\n And is it seen as a line_break?{TRUE}")
         
     | 
| 
      
 178 
     | 
    
         
            +
              end
         
     | 
| 
      
 179 
     | 
    
         
            +
              
         
     | 
| 
      
 180 
     | 
    
         
            +
              def test_comment_line_break
         
     | 
| 
      
 181 
     | 
    
         
            +
                 assert_can_parse("//Comment\nWho's buried in Grant's tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}")
         
     | 
| 
      
 182 
     | 
    
         
            +
                 assert_can_parse("//Comment\r\nWho's buried in Grant's tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}")
         
     | 
| 
      
 183 
     | 
    
         
            +
              end
         
     | 
| 
      
 184 
     | 
    
         
            +
              
         
     | 
| 
      
 185 
     | 
    
         
            +
              def test_dealing_with_blank_lines_at_top_of_file
         
     | 
| 
      
 186 
     | 
    
         
            +
                assert_can_parse("\n    \n//Comment\nWho's buried in Grant's tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}")
         
     | 
| 
      
 187 
     | 
    
         
            +
              end
         
     | 
| 
      
 188 
     | 
    
         
            +
              
         
     | 
| 
      
 189 
     | 
    
         
            +
              def test_dealing_with_blank_lines_at_end_of_file
         
     | 
| 
      
 190 
     | 
    
         
            +
                assert_can_parse("//Comment\nWho's buried in Grant's tomb?{=Grant =Ulysses S. Grant =Ulysses Grant}\n \n    \n ")
         
     | 
| 
      
 191 
     | 
    
         
            +
              end
         
     | 
| 
      
 192 
     | 
    
         
            +
              
         
     | 
| 
      
 193 
     | 
    
         
            +
              def test_title_line_breaks
         
     | 
| 
      
 194 
     | 
    
         
            +
               test_text= <<EOS
         
     | 
| 
      
 195 
     | 
    
         
            +
                 ::Title::
         
     | 
| 
      
 196 
     | 
    
         
            +
                 Match the following countries with their corresponding capitals. {
         
     | 
| 
      
 197 
     | 
    
         
            +
                 =Canada -> Ottawa
         
     | 
| 
      
 198 
     | 
    
         
            +
                 =Italy  -> Rome
         
     | 
| 
      
 199 
     | 
    
         
            +
                 =Japan  -> Tokyo
         
     | 
| 
      
 200 
     | 
    
         
            +
                 =India  -> New Delhi
         
     | 
| 
      
 201 
     | 
    
         
            +
                 }
         
     | 
| 
      
 202 
     | 
    
         
            +
                 
         
     | 
| 
      
 203 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 204 
     | 
    
         
            +
                 assert_can_parse(test_text) 
         
     | 
| 
      
 205 
     | 
    
         
            +
              end
         
     | 
| 
      
 206 
     | 
    
         
            +
              
         
     | 
| 
      
 207 
     | 
    
         
            +
              
         
     | 
| 
      
 208 
     | 
    
         
            +
              def test_single_short_answer
         
     | 
| 
      
 209 
     | 
    
         
            +
               test_text = <<EOS
         
     | 
| 
      
 210 
     | 
    
         
            +
               // ===Short Answer===
         
     | 
| 
      
 211 
     | 
    
         
            +
               What is your favorite color?{=blue}
         
     | 
| 
      
 212 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 213 
     | 
    
         
            +
              assert_can_parse(test_text)
         
     | 
| 
      
 214 
     | 
    
         
            +
              end
         
     | 
| 
      
 215 
     | 
    
         
            +
              
         
     | 
| 
      
 216 
     | 
    
         
            +
              def test_multiple_short_answer
         
     | 
| 
      
 217 
     | 
    
         
            +
              test_text = <<EOS
         
     | 
| 
      
 218 
     | 
    
         
            +
                   ::Multiple Short Answer::
         
     | 
| 
      
 219 
     | 
    
         
            +
                   What are your four favorite colors?{
         
     | 
| 
      
 220 
     | 
    
         
            +
                     =%25%Blue
         
     | 
| 
      
 221 
     | 
    
         
            +
                     =%25% Red
         
     | 
| 
      
 222 
     | 
    
         
            +
                     =%25% Green
         
     | 
| 
      
 223 
     | 
    
         
            +
                     =%25% pink
         
     | 
| 
      
 224 
     | 
    
         
            +
                     =%25% azure
         
     | 
| 
      
 225 
     | 
    
         
            +
                     =%25% gold
         
     | 
| 
      
 226 
     | 
    
         
            +
                     }
         
     | 
| 
      
 227 
     | 
    
         
            +
            EOS
         
     | 
| 
      
 228 
     | 
    
         
            +
              assert_can_parse(test_text)
         
     | 
| 
      
 229 
     | 
    
         
            +
              end
         
     | 
| 
      
 230 
     | 
    
         
            +
              
         
     | 
| 
      
 231 
     | 
    
         
            +
              def test_moodle_examples
         
     | 
| 
      
 232 
     | 
    
         
            +
                 GiftExamples.examples.each do |key, value|
         
     | 
| 
      
 233 
     | 
    
         
            +
                   assert_can_parse value
         
     | 
| 
      
 234 
     | 
    
         
            +
                 end                                                
         
     | 
| 
      
 235 
     | 
    
         
            +
              end
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
              def test_can_have_commands
         
     | 
| 
      
 238 
     | 
    
         
            +
                assert_can_parse("$COMMAND=1\n\nQuestion text{}")
         
     | 
| 
      
 239 
     | 
    
         
            +
              end
         
     | 
| 
      
 240 
     | 
    
         
            +
            end
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
            Test::Unit::UI::Console::TestRunner.run(GiftSyntaxTest)
         
     | 
| 
      
 243 
     | 
    
         
            +
                
         
     |