https://github.com/jeroenk/Anagopos3D
Revision d1be8ad4505c5a42c4f8a1a3d5a97fa28d912074 authored by Jeroen Ketema on 24 June 2011, 11:43:25 UTC, committed by Jeroen Ketema on 24 June 2011, 12:01:57 UTC
1 parent 87f8963
Raw File
Tip revision: d1be8ad4505c5a42c4f8a1a3d5a97fa28d912074 authored by Jeroen Ketema on 24 June 2011, 11:43:25 UTC
Add file with examples from Anagapos paper
Tip revision: d1be8ad
lambda_parser.py
from LambdaTermClass import LambdaAbs, LambdaApp, LambdaVar

position  = None
string_in = None
symbol    = None

class Term:
    def toString(self):
        raise Exception("Not implemented")

    def getFreeVars(self):
        raise Exception("Not implemented")

    def convert(self, free_vars):
        raise Exception("Not implemented")

    def __str__(self):
        return self.toString()

class Application(Term):
    def __init__(self, left, right):
        self.left  = left
        self.right = right

    def toString(self):
        return "(" + self.left.toString() + ")(" + self.right.toString() + ")"

    def getFreeVars(self):
        left_free  = self.left.getFreeVars()
        right_free = self.right.getFreeVars()
        return left_free | right_free

    def convert(self, free_vars):
        left  = self.left.convert(free_vars)
        right = self.right.convert(free_vars)
        return LambdaApp(left, right)

class Abstraction(Term):
    def __init__(self, var):
        self.variable = var
        self.subterm  = None

    def setSubterm(self, subterm):
        self.subterm = subterm

    def toString(self):
        return "\\" + self.variable.toString() + ".(" \
            + self.subterm.toString() + ")"

    def getFreeVars(self):
        subterm_free = self.subterm.getFreeVars()
        var_var      = self.variable.toString()
        return subterm_free - set([var_var])

    def convert(self, free_vars):
        free_vars_new = free_vars[:]
        var_var       = self.variable.toString()

        if var_var in free_vars_new:
            free_vars_new.remove(var_var)

        free_vars_new.insert(0, var_var)
        return LambdaAbs(self.subterm.convert(free_vars_new))

class Variable(Term):
    def __init__(self, string):
        self.string = string

    def toString(self):
        return self.string

    def getFreeVars(self):
        return set([self.string])

    def convert(self, free_vars):
        if self.string in free_vars:
            return LambdaVar(free_vars.index(self.string))
        else:
            raise Exception("Non-convertible variable found")

def get_symbol():
    global position, symbol

    while position != len(string_in) \
            and (string_in[position] == ' ' \
                     or string_in[position] == '\t' \
                     or string_in[position] == '\n' \
                     or string_in[position] == '\r'):
        position += 1

    if position == len(string_in):
       symbol = '\0'
       return

    symbol = string_in[position]
    position += 1

def variable():
    if not (symbol >= 'a' and symbol <= 'z'):
        raise Exception("Invalid symbol on input: " + symbol)

    string = symbol[:]
    get_symbol() # consumes letter

    while (symbol >= '0' and symbol <= '9'):
        string += symbol
        get_symbol() # consumes number

    var = Variable(string)
    return var

def abstraction():
    if symbol != '\\':
        raise Exception("Invalid symbol on input: " + symbol)

    get_symbol() # consumes abstraction symbol
    var = variable()
    top = bottom = Abstraction(var)

    while symbol != '.':
        var = variable()
        ab  = Abstraction(var)
        bottom.setSubterm(ab)
        bottom = ab

    get_symbol() # consumes dot
    subterm = term()
    bottom.setSubterm(subterm)
    return top

def term():
    if symbol != '(' \
            and not (symbol >= 'a' and symbol <= 'z') \
            and symbol != '\\':
        raise Exception("Invalid symbol on input: " + symbol)

    first = True

    while symbol == '(' \
            or (symbol >= 'a' and symbol <= 'z') \
            or symbol == '\\':
        if symbol == '(':
            get_symbol() # consumes open parenthesis
            subterm = term()

            if symbol != ')':
                raise Exception("Invalid symbol on in: " + symbol)

            get_symbol() # consumes closing parenthesis
        elif (symbol >= 'a' and symbol <= 'z'):
            subterm = variable()
        elif symbol == '\\':
            subterm = abstraction()

        if first:
            top = subterm
            first = False
        else:
            top = Application(top, subterm)

    return top

def parse(string):
    global string_in, position

    string_in = string
    position = 0
    get_symbol()
    whole_term = term()

    if symbol != '\0':
        raise Exception("Symbols left on input: " + string_in[position:])

    free_vars = []

    for var in whole_term.getFreeVars():
        free_vars.append(var)

    return whole_term.convert(free_vars)

def test():
    test_term = "  \\x.  xy23 z\\y d12.w d12"
    t = parse(test_term)
    print t
back to top