Skip to content

Instantly share code, notes, and snippets.

@andrewjl
Created September 2, 2011 22:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewjl/1190148 to your computer and use it in GitHub Desktop.
Save andrewjl/1190148 to your computer and use it in GitHub Desktop.
Unit Testing Question Code
class Lexicon
Pair = Struct.new(:token, :word)
Direction = %w(north south east west down up left right back)
Verb = %w(go stop kill eat)
Stop = %w(the in of from at it)
Noun = %w(door bear princess cabinet)
def initialize()
end
def scan(phrase)
word_set = phrase.split(' ')
result = []
for word in word_set
if Direction.include?(word)
result.push(Pair.new(:direction, word))
elsif Verb.include?(word)
result.push(Pair.new(:verb, word))
elsif Stop.include?(word)
result.push(Pair.new(:stop, word))
elsif Noun.include?(word)
result.push(Pair.new(:noun, word))
elsif convert_number(word) != nil
word = convert_number(word)
result.push(Pair.new(:number, word))
else
result.push(Pair.new(:error, word))
end
end
return result
end
def convert_number(s)
begin
Integer(s)
rescue ArgumentError
nil
end
end
end
class ParserError < Exception
end
class Sentence
def initialize(subject, verb, object)
# remember we take Pair.new(:noun, "princess") structs and convert them
@subject = subject.word
@verb = verb.word
@object = object.word
end
end
def peek(word_list)
begin
word_list.first.token
rescue
nil
end
end
def match(word_list, expecting)
word = word_list.shift
if word.token == expecting
word
else
nil
end
end
def skip_word(word_list, token)
while peek(word_list) == token
match(word_list, token)
end
end
def parse_verb(word_list)
skip_word(word_list, :stop)
if peek(word_list) == :verb
return match(word_list, :verb)
else
raise ParserError.new("Expected a verb next.")
end
end
def parse_object(word_list)
skip_word(word_list, :stop)
next_word = peek(word_list)
if next_word == :noun
return match(word_list, :noun)
end
if next_word == :direction
return match(word_list, :direction)
else
raise ParserError.new("Expected a noun or direction next.")
end
end
def parse_subject(word_list, subj)
verb = parse_verb(word_list)
obj = parse_object(word_list)
return Sentence.new(subj, veb, obj)
end
def parse_sentence(word_list)
skip_word(word_list, :stop)
start = peek(word_list)
if start == :noun
subj = match(word_list, :noun)
return parse_subject(word_list, subj)
elsif start == :verb
# assume the subject is the player then
return parse_subject(word_list, Pair.new(:noun, "player"))
else
return ParserError.new("Must start with subject, object, or verb not: #{start}")
end
end
require 'test/unit'
require_relative '../lib/lexicon'
require_relative '../lib/sentence'
class SentenceTests < Test::Unit::TestCase
Pair = Lexicon::Pair
def test_peek
assert_equal(peek([Pair.new(:verb, 'go')]), :verb)
end
def test_match
test_list = [Pair.new(:verb, 'go')]
assert_equal(match(test_list, :verb), Pair.new(:verb, 'go'))
big_list = [Pair.new(:verb, 'go'), Pair.new(:noun, 'king'), Pair.new(:stop, 'is')]
assert_equal(match(big_list, :noun), nil)
end
def test_skip_word
small_list = [Pair.new(:verb, 'go'), Pair.new(:verb, 'do')]
skip_word(small_list, :verb)
assert_equal([],small_list)
big_list = [Pair.new(:verb, 'go'), Pair.new(:noun, 'king')]
skip_word(big_list, :verb)
assert_equal([Pair.new(:noun, 'king')], big_list)
end
def test_parse_verb
list_one = [Pair.new(:verb, 'go'), Pair.new(:noun, 'king')]
assert_equal(parse_verb(list_one), Pair.new(:verb, 'go'))
list_two = [Pair.new(:noun, 'player') ,Pair.new(:verb, 'go'), Pair.new(:noun, 'king')]
assert_raise(ParserError.new("Expected a noun or direction next.")) {parse_verb(list_two)}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment