2

I am using Python 2.7, and trying to walk through the study guide Learn Python The Hard Way. I am having a problem when I try Exercise 49.

Python 2.7.10 (default, Jul 14 2015, 19:46:27) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

>>> from ex48.parser import *
>>> x = parse_sentence([('verb', 'run'), ('direction', 'north')])
>>> x.subject
'player'
>>> x.verb
'run'
>>> x.object
'north'
>>> x = parse_sentence([('noun', 'bear'), ('verb', 'eat'), ('stop', 'the'), ('noun', 'honey')])
>>> x.subject
'bear'
>>> x.verb
'eat'
>>> x.object
'honey'

When I do:

from ex48.parser import *
x = parse_sentence([('verb', 'run'), ('direction', 'north')])

Windows PowerShell gives me:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'parse_sentence' is not defined

My file structure is:

../lexicon
     bin/
     docs/
     ex48/
         __init__.py
         lexicon.py
         parser.py
     setup.py
     tests/
         lexicon_tests.py
         __init__.py

Here is code in parser.py

class ParserError(Exception):
    pass

class Sentence(object):
    def __init__(self, subject, verb, obj):
        #remember we take ('noun', 'princess') tuples and convert them
        self.subject = subject[1]
        self.verb = verb[1]
        self.object = obj[1]

    def peek(word_list):
        if word_list:
            word = word_list[0]
            return word[0]
        else:
            return None

    def match(word_list, expecting):
        if word_list:
            word = word_list.pop(0)

            if word[0] == expecting:
                return word
            else:
                return None
        else:
            return None

    def skip(word_list, word_type):
        while peek(word_list) == word_type:
            match(word_list, word_type)

    def parse_verb(word_list):
        skip(word_list, 'stop')

        if peek(word_list) == 'verb':
            return match(word_list, 'verb')
        else:
            raise ParserError("Expected a verb next")

    def parse_object(word_list):
        skip(word_list, 'stop')
        next_word = peek(word_list)

        if next_word == 'noun':
            return match(word_list, 'noun')
        elif next_word == 'direction':
            return match(word_list, 'direction')
        else:
            raise ParserError("Expected a noun or direction next.")

    def parse_subject(word_list):
        skip(word_list, 'stop')
        next_word = peek(word_list)

        if next_word == 'noun':
            return match(word_list, 'noun')
        elif next_word == 'verb':
            return ('noun', 'player')
        else:
            raise ParserError("Expected a verb next.")

    def parse_sentence(word_list):
        subj = parse_subject(word_list)
        verb = parse_verb(word_list)
        obj = parse_object(word_list)

        return Sentence(subj, verb, obj)
5
  • 1
    It should work, assuming that parse_sentence is defined in parser.py. Can you show what that file contains? Commented Dec 29, 2015 at 19:13
  • It depends both on the contents of the file parser.py and your current directory. Ensure that you're running Python from the directory called lexicon. Commented Dec 29, 2015 at 19:17
  • @Vlad, I just add contents in parser.py Commented Dec 29, 2015 at 19:41
  • Indentation level counts. Commented Dec 29, 2015 at 19:41
  • @steinar, I tried again to make sure I run Python under lexicon directory, not any sub-directories. No luck so far Commented Dec 29, 2015 at 19:42

2 Answers 2

1

Bad Ident. only first function in part of class.

class ParserError(Exception):
    pass

class Sentence(object):
    def __init__(self, subject, verb, obj):
        #remember we take ('noun', 'princess') tuples and convert them
        self.subject = subject[1]
        self.verb = verb[1]
        self.object = obj[1]

def peek(word_list):
    if word_list:
        word = word_list[0]
        return word[0]
    else:
        return None

def match(word_list, expecting):
    if word_list:
        word = word_list.pop(0)

        if word[0] == expecting:
            return word
        else:
            return None
    else:
        return None

def skip(word_list, word_type):
    while peek(word_list) == word_type:
        match(word_list, word_type)

def parse_verb(word_list):
    skip(word_list, 'stop')

    if peek(word_list) == 'verb':
        return match(word_list, 'verb')
    else:
        raise ParserError("Expected a verb next")

def parse_object(word_list):
    skip(word_list, 'stop')
    next_word = peek(word_list)

    if next_word == 'noun':
        return match(word_list, 'noun')
    elif next_word == 'direction':
        return match(word_list, 'direction')
    else:
        raise ParserError("Expected a noun or direction next.")

def parse_subject(word_list):
    skip(word_list, 'stop')
    next_word = peek(word_list)

    if next_word == 'noun':
        return match(word_list, 'noun')
    elif next_word == 'verb':
        return ('noun', 'player')
    else:
        raise ParserError("Expected a verb next.")

def parse_sentence(word_list):
    subj = parse_subject(word_list)
    verb = parse_verb(word_list)
    obj = parse_object(word_list)

    return Sentence(subj, verb, obj)
Sign up to request clarification or add additional context in comments.

1 Comment

It is work as keeping some data together. like struct in c
0

parse_sentence() appears to be a method on Sentence. Either you want to unindent it so it's a top-level function in the file, or make it, for example, a @staticmethod and call it as Sentence.parse_sentence().

2 Comments

Thanks @Vlad, I found that all the methods should be on Sentence except __init__(). Unindent them works, but what is the point of Class Sentence()?
I think it's meant to group together the results, so you can access results like x.verb rather than e.g. x[1] if they had returned a tuple directly (e.g. return (subj, verb, obj)) in parser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.