Subversion Repositories programming

Rev

Rev 165 | Rev 167 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#!/usr/bin/env python
# Copyright: Ira W. Snyder
# Start Date: 2005-11-18
# End Date:
# License: Public Domain
#
# Changelog Follows:
#
# 2005-11-18
# * Just getting the basics in place, since we haven't been given
#   the whole description of the project yet.
#
# 2005-11-26
# * Got the whole class working, now to implement pretty-printing
#

# Check for <Python-2.3 compatibility (boolean values)
try:
  True, False
except NameError:
  (True, False) = (1, 0)

import sys

class Queue:
    """Implements a basic FIFO queue"""

    def __init__(self):
        self.q = []

    def empty(self):
        """Empty the queue"""
        self.q = []

    def enqueue(self, elem):
        """Enqueue an element"""
        self.q.append(elem)

    def dequeue(self):
        """Get the object at the front of the queue"""
        elem = self.q[0]
        self.q = self.q[1:]
        return elem

class RecursiveDescentParser:
    def __init__(self):
        self.__clear()

    def __clear(self):
        self.str = ""   # the string of input to test
        self.strpos = 0 # the current position in str
        self.derivation = ""

    def __replace_sym(self, to_repl, with_this):
        """Replace a string in the derivation with another string"""

        pos = s.find(to_repl)
    
        if pos == -1:
            raise ValueError
    
        self.derivation = s[:pos] + str(with_this) + s[pos+len(to_repl):]

    def __input_test_str(self):
        self.str = raw_input("input str: ")

    def main_menu(self):

        done = False

        while not done:
            print 'Menu:'
            print '========================================'
            print '1. Test a string'
            print '2. Quit'
            print
            s = raw_input('Choice >>> ')
            print

            if s == '1':
                self.__clear()
                self.__input_test_str()
                self.__test_str()
            elif s == '2':
                done = True
            else:
                print 'Bad Selection'
                print

    def __test_str(self):
        print 'Parsing: %s' % ((self.procE() and len(self.str) == self.strpos) and 'Completed' or 'Failed', )
        print

    def procE(self):
        print 'procE(%s) ->' % (self.str[self.strpos:])

        # Catch the exception generated below if we don't have enough
        # input to 'look ahead'
        try:
            return self.procT() and self.procEprm()
        except IndexError:
            print 'Not enough input to continue, failed.'
            return False

    def procEprm(self):
        # Check empty str
        if self.strpos >= len(self.str):
            return True

        print 'procEprm(%s) ->' % (self.str[self.strpos:])

        # Check +
        if self.str[self.strpos] == '+':
            self.strpos += 1
            return self.procT() and self.procEprm()

        # Check -
        if self.str[self.strpos] == '-':
            self.strpos += 1
            return self.procT() and self.procEprm()

        # We accept empty str, so take it
        return True

    def procT(self):
        print 'procT(%s) ->' % (self.str[self.strpos:])

        return self.procP() and self.procTprm()

    def procTprm(self):
        # Check empty str
        if self.strpos >= len(self.str):
            return True

        print 'procTprm(%s) ->' % (self.str[self.strpos:])

        # Check *
        if self.str[self.strpos] == '*':
            self.strpos += 1
            return self.procP() and self.procTprm()

        # we accept empty str, so take it
        return True

    def procP(self):
        print 'procP(%s) ->' % (self.str[self.strpos:])

        return self.procF() and self.procPprm()

    def procPprm(self):
        # Check empty str
        if self.strpos >= len(self.str):
            return True

        print 'procPprm(%s) -> ' % (self.str[self.strpos:])

        # check exp symbol
        if self.str[self.strpos] == '^':
            self.strpos += 1
            return self.procF() and self.procPprm()

        # we accept empty str, so take it
        return True

    def procF(self):
        print 'procF(%s) ->' % (self.str[self.strpos:])

        # Check x
        if self.str[self.strpos] == 'x':
            self.strpos += 1
            return self.procV()

        # Check (E)
        if self.str[self.strpos] == '(':
            self.strpos += 1

            if self.procE():
                if self.str[self.strpos] == ')':
                    self.strpos += 1
                    return True

                return False

            return False

        # Must be a number
        return self.procN()

    def procN(self):
        print 'procN(%s) ->' % (self.str[self.strpos:])

        if self.procD(): # we have one digit
            if self.procD(): # two digits
                return True

            return True

        return False

    def procV(self):
        print 'procV(%s) ->' % (self.str[self.strpos:])

        return self.procD()

    def procD(self):
        print 'procD(%s) ->' % (self.str[self.strpos:])

        try:
            # Check if we are a single digit
            if self.str[self.strpos] in '0123456789':
                self.strpos += 1
                return True
        except IndexError: # ran out of input
            return False

        return False

if __name__ == '__main__':
    rdp = RecursiveDescentParser()
    rdp.main_menu()