smm.py
author Eugen Sawin <sawine@me73.com>
Mon, 16 May 2011 20:23:22 +0200
changeset 1 a7ca3e23ff41
parent 0 59ddda9665be
child 2 710650dc4db6
permissions -rw-r--r--
First working parser.
     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     def __init__(self):
    30         Operator.__init__(self, NOT)
    31     def __call__(self):
    32         pass
    33 
    34 class And(Operator):
    35     def __init__(self):
    36         Operator.__init__(self, AND)
    37     
    38 class Or(Operator):
    39     def __init__(self):
    40         Operator.__init__(self, OR)
    41     
    42 class Imp(Operator):
    43     def __init__(self):
    44         Operator.__init__(self, IMP)
    45     
    46 class Eq(Operator):
    47     def __init__(self):
    48         Operator.__init__(self, EQ)
    49     
    50 class Box(Operator):
    51     def __init__(self):
    52         Operator.__init__(self,BOX )
    53     
    54 class Diamond(Operator):
    55     def __init__(self):
    56         Operator.__init__(self, DIAMOND)
    57     
    58 class Variable(Operator):
    59     def __init__(self):
    60         Operator.__init__(self, VARIABLE)
    61 
    62 class Formula(object):
    63     def __init__(self, f):
    64         self.f = f
    65 
    66 TOKENS = {re.compile("\("): LB,
    67           re.compile("\)"): RB,
    68           re.compile("~"): Not,
    69           re.compile("&"): And,
    70           re.compile("\|"): Or,
    71           re.compile("->"): Imp,
    72           re.compile("<->"): Eq,
    73           re.compile("\[\]"): Box,
    74           re.compile("<>"): Diamond,
    75           re.compile("[a-z]+"): Variable}
    76          
    77 class Scanner(object):
    78     def __init__(self, tokens, source=None):
    79         self.tokens = tokens
    80         self.reset(source)
    81     def next(self):         
    82         while self.i < len(self.source):           
    83             for p, token in self.tokens.iteritems():
    84                 m = p.match(self.source[self.i:])               
    85                 if m:                  
    86                     self.i += m.end(0)
    87                     value = m.group(0)
    88                     return token
    89             self.i += 1
    90     def reset(self, source):
    91         self.i = 0
    92         self.source = source
    93 
    94 S = Formula
    95 A = "A"
    96 #S: (Variable,),
    97 #S: (Not, S),
    98 #S: (LB, A, RB),
    99 #S: (Box, S),
   100 #S: (Diamond, S),
   101 #A: (S, And, S),
   102 #A: (S, Or, S),
   103 #A: (S, Imp, S),
   104 #A: (S, Eq, S)
   105 SYNTAX = ((Variable,),
   106           (Not, S),
   107           (LB, A, RB),
   108           (Box, S),
   109           (Diamond, S),
   110           (S, And, S),
   111           (S, Or, S),
   112           (S, Imp, S),
   113           (S, Eq, S))
   114 
   115 class Parser(object):
   116     def __init__(self, syntax, scanner):
   117         self.syntax = syntax
   118         self.scanner = scanner
   119     def parse(self, source):
   120         table = {(S, Variable): 0,
   121                  (S, Not): 1,
   122                  (S, LB): 2,
   123                  (S, Box): 3,
   124                  (S, Diamond): 4,
   125                  (A, S, And): 5,
   126                  (A, S, Or): 6,
   127                  (A, S, Imp): 7,
   128                  (A, S, Eq): 8,
   129                  (A, Variable, And): 5,
   130                  (A, Variable, Or): 6,
   131                  (A, Variable, Imp): 7,
   132                  (A, Variable, Eq): 8}
   133         stack = [S]
   134         out = []
   135         self.scanner.reset(source)
   136         token = self.scanner.next()
   137         lookahead = self.scanner.next()
   138         accepted = True
   139         while token and len(stack):
   140             top = stack[-1]  
   141             #print
   142             #print "stack ", top
   143             #print "token ", token
   144             #print "lookahead ", lookahead            
   145             if top == token:
   146                 stack.pop()
   147                 token = lookahead
   148                 lookahead = self.scanner.next()
   149             else:
   150                 action = None
   151                 if (top, token) in table:
   152                     action = table[(top, token)]
   153                 elif (top, token, lookahead) in table:
   154                     action = table[(top, token, lookahead)]
   155                 #print "action ", action, " replace ", self.syntax[action] 
   156                 if action is None:
   157                     accepted = False
   158                     break
   159                 out.append(action)
   160                 stack.pop()
   161                 stack.extend(reversed(self.syntax[action]))
   162         return (accepted and not len(stack), out)
   163                 
   164         
   165 
   166 def main():
   167     args = parse_arguments()
   168     scanner = Scanner(TOKENS)
   169     parser = Parser(SYNTAX, scanner)
   170     print parser.parse(args.formula)
   171 
   172 from argparse import ArgumentParser
   173 
   174 def parse_arguments():
   175     parser = ArgumentParser(description="Parses Simple Modal Logic syntax.")
   176     parser.add_argument("formula", help="your formula") 
   177     return parser.parse_args()
   178 
   179 if __name__ == "__main__":
   180     main()