smm.py
author Eugen Sawin <sawine@me73.com>
Mon, 16 May 2011 21:43:50 +0200
changeset 2 710650dc4db6
parent 1 a7ca3e23ff41
child 3 75562290a4d3
permissions -rw-r--r--
Syntax tree construction.
     1 """
     2 Name: 
     3 
     4 Author: Eugen Sawin <sawine@informatik.uni-freiburg.de>
     5 """
     6 from os import path
     7 import os
     8 import re
     9 import token
    10 
    11 NOT = "~"
    12 AND = "&"
    13 OR = "|"
    14 IMP = "->"
    15 EQ = "<->"
    16 BOX = "[]"
    17 DIAMOND = "<>"
    18 VARIABLE = "p"
    19 LB = "("
    20 RB = ")"
    21 
    22 class Operator(object):
    23     def __init__(self, id):
    24         self.id = id  
    25     def __str__(self):
    26         return self.id
    27 
    28 class Not(Operator):
    29     arity = 1
    30     def __init__(self, values):
    31         Operator.__init__(self, NOT)
    32         self.value = values[0]
    33     def __call__(self):
    34         pass
    35 
    36 class And(Operator):
    37     arity = 2
    38     def __init__(self, values):
    39         Operator.__init__(self, AND)
    40         self.value = values
    41 
    42 class Or(Operator):
    43     arity = 2
    44     def __init__(self, values):
    45         Operator.__init__(self, OR)
    46         self.value = values
    47 
    48 class Imp(Operator):
    49     arity = 2
    50     def __init__(self):
    51         Operator.__init__(self, IMP)
    52     
    53 class Eq(Operator):
    54     arity = 2
    55     def __init__(self):
    56         Operator.__init__(self, EQ)
    57     
    58 class Box(Operator):
    59     arity = 1
    60     def __init__(self, values):
    61         Operator.__init__(self, BOX)
    62         self.value = values[0]
    63 
    64 class Diamond(Operator):
    65     arity = 1
    66     def __init__(self):
    67         Operator.__init__(self, DIAMOND)
    68     
    69 class Variable(Operator):
    70     arity = 0
    71     def __init__(self, values):
    72         Operator.__init__(self, VARIABLE)
    73 
    74 class Lb(Operator):
    75     arity = -1
    76     def __init__(self, values):
    77         Operator.__init__(self, LB)
    78 
    79 class Rb(Operator):
    80     arity = -1
    81     def __init__(self, values):
    82         Operator.__init__(self, RB)
    83 
    84 class Formula(object):
    85     def __init__(self):
    86         pass
    87         
    88 
    89 TOKENS = {re.compile("\("): Lb,
    90           re.compile("\)"): Rb,
    91           re.compile("~"): Not,
    92           re.compile("&"): And,
    93           re.compile("\|"): Or,
    94           re.compile("->"): Imp,
    95           re.compile("<->"): Eq,
    96           re.compile("\[\]"): Box,
    97           re.compile("<>"): Diamond,
    98           re.compile("[a-z]+"): Variable}
    99          
   100 class Scanner(object):
   101     def __init__(self, tokens, source=None):
   102         self.tokens = tokens
   103         self.reset(source)
   104     def next(self):         
   105         while self.i < len(self.source):           
   106             for p, token in self.tokens.iteritems():
   107                 m = p.match(self.source[self.i:])               
   108                 if m:                  
   109                     self.i += m.end(0)
   110                     value = m.group(0)
   111                     return (token, value)
   112             self.i += 1
   113         return (None, None)
   114     def reset(self, source):
   115         self.i = 0
   116         self.source = source
   117 
   118 S = Formula
   119 A = "A"
   120 #0 S: (Variable,),
   121 #1 S: (Not, S),
   122 #2 S: (Lb, A, Rb),
   123 #3 S: (Box, S),
   124 #4 S: (Diamond, S),
   125 #5 A: (S, And, S),
   126 #6 A: (S, Or, S),
   127 #7 A: (S, Imp, S),
   128 #8 A: (S, Eq, S)
   129 SYNTAX = ((Variable,),
   130           (Not, S),
   131           (Lb, A, Rb),
   132           (Box, S),
   133           (Diamond, S),
   134           (S, And, S),
   135           (S, Or, S),
   136           (S, Imp, S),
   137           (S, Eq, S))
   138 
   139 class Node(object):
   140     def __init__(self, parent, value):
   141         self.parent = parent
   142         self.value = value
   143         self.children = []
   144     def addChild(self, value):
   145         self.children.append(self, node)
   146 
   147 class Parser(object):
   148     def __init__(self, syntax, scanner):
   149         self.syntax = syntax
   150         self.scanner = scanner
   151     def parse(self, source):
   152         table = {(S, Variable): 0,
   153                  (S, Not): 1,
   154                  (S, Lb): 2,
   155                  (S, Box): 3,
   156                  (S, Diamond): 4,
   157                  (A, S, And): 5,
   158                  (A, S, Or): 6,
   159                  (A, S, Imp): 7,
   160                  (A, S, Eq): 8,
   161                  (A, Variable, And): 5,
   162                  (A, Variable, Or): 6,
   163                  (A, Variable, Imp): 7,
   164                  (A, Variable, Eq): 8}
   165         stack = [S]
   166         trash = []
   167         out = []
   168         self.scanner.reset(source)
   169         (token, value) = self.scanner.next()
   170         (lookahead, _) = self.scanner.next()
   171         accepted = True      
   172         while token and len(stack):
   173             top = stack[-1]  
   174             #print
   175             #print "stack ", top
   176             #print "token ", token
   177             #print "lookahead ", lookahead            
   178             if top == token:
   179                 trash.append(stack.pop())
   180                 token = lookahead
   181                 (lookahead, _) = self.scanner.next()
   182             else:
   183                 action = None
   184                 if (top, token) in table:
   185                     action = table[(top, token)]
   186                 elif (top, token, lookahead) in table:
   187                     action = table[(top, token, lookahead)]
   188                 #print "action ", action, " replace ", self.syntax[action] 
   189                 if action is None:
   190                     accepted = False
   191                     break
   192                 out.append(action)
   193                 stack.pop()
   194                 stack.extend(reversed(self.syntax[action]))
   195         accepted = accepted and not len(stack)
   196         return (accepted, out, trash)                
   197         
   198 
   199 def main():
   200     args = parse_arguments()
   201     scanner = Scanner(TOKENS)
   202     parser = Parser(SYNTAX, scanner)
   203     (accepted, out, trash) = parser.parse(args.formula)
   204     print (accepted, out, trash)
   205     table = []
   206     unfinished = []
   207     for t in reversed(trash):
   208         if t.arity >= 0:
   209             print "\nt ", t
   210             print "arity ", t.arity
   211             print "table ", table
   212             if len(table) < t.arity:
   213                 unfinished.append(t)
   214             else:
   215                 args = table[:t.arity]
   216                 print "args ", args
   217                 table = table[t.arity:]
   218             
   219                 node = t(args)
   220                 print "node ", node
   221                 table.append(node)
   222             if len(unfinished) and unfinished[-1].arity <= len(table):
   223                 args = table[:unfinished[-1].arity]
   224                 print "unfinished args ", args
   225                 table = table[unfinished[-1].arity:]
   226                 node = unfinished[-1](args)
   227                 print "unfinished node ", node
   228                 table.append(node)
   229                 unfinished.pop()
   230 
   231     print "\n", table
   232 
   233 from argparse import ArgumentParser
   234 
   235 def parse_arguments():
   236     parser = ArgumentParser(description="Parses simple modal logic syntax.")
   237     parser.add_argument("formula", help="your formula") 
   238     return parser.parse_args()
   239 
   240 if __name__ == "__main__":
   241     main()