class Analyzer: def __init__(self, itr): self.itr = itr def next(self,amount=1): if len(self.itr) == 0: return None if amount == 1: return self.itr[0] return self.itr[:amount] def take(self,amount=1): m, self.itr = self.next(amount), self.itr[amount:] return m def __len__(self): return len(self.itr) class StringAnalyzer(Analyzer): def nextOrd(self): m = self.next() if m is None: return None return ord(m) def between(self,cmin,cmax): c = self.nextOrd() if c is None: return False return c >= ord(cmin) and c <= ord(cmax) def is_a(self,c): return self.next() == c class TokenListAnalyzer(Analyzer): def takeUntilType(self,end): return self.takeUntil(lambda t: t[0] == end) def takeUntil(self,condition, dropEnd=True): t = [] while self.next() is not None and not condition(self.next()): t.append( self.take() ) if dropEnd and self.next() is not None: self.take() return t class Lexer: keywords = ["setze","auf","durch","schreibe"] operators = ["plus","minus","mal","geteilt"] IDENT = 0 KEYWORD = 1 INT = 2 FLOAT = 3 OP = 4 BRACE_OPEN = 5 BRACE_CLOSE = 6 NEWLINE = 7 def lex(self, source): tokens = [] sa = StringAnalyzer(source) braces = 0 stack = 0 while len(sa) != 0: if sa.between('a', 'z') or sa.between('A', 'Z'): #identifier or keyword ident = "" while sa.between('a', 'z') or sa.between('A', 'Z') or sa.between('0', '9') or sa.is_a('_'): ident += sa.take() if ident.lower() in self.keywords: tokens.append( (self.KEYWORD,ident.lower()) ) elif ident.lower() in self.operators: tokens.append( (self.OP,ident.lower()) ) elif ident.lower() == "wenn": tokens.append( ( self.KEYWORD, "wenn", stack ) ) stack += 1 elif ident.lower() == "ende": stack -= 1 tokens.append( ( self.KEYWORD, "ende", stack ) ) else: tokens.append( (self.IDENT,ident) ) elif sa.between('0', '9'): #number num = "" t = (self.INT, int) while sa.between('0', '9'): num += sa.take() if sa.is_a(','): t = (self.FLOAT, float) sa.take() num += "." while sa.between('0', '9'): num += sa.take() tokens.append( (t[0],t[1](num)) ) elif sa.is_a('('): tokens.append( (self.BRACE_OPEN,braces) ) braces+=1 elif sa.is_a(')'): braces-=1 tokens.append( (self.BRACE_CLOSE,braces) ) elif sa.is_a('\n'): tokens.append( (self.NEWLINE,) ) sa.take() elif sa.is_a(' ') or sa.is_a('\t') or sa.is_a('\r'): sa.take() else: raise ParserException("WTF is %s" % sa.take() ) return tokens class ParserException(Exception): pass class Parser: def parse(self,tokens): block = BlockTerm() ta = TokenListAnalyzer(tokens) while len(ta) > 0: if ta.next()[0] == Lexer.KEYWORD: if ta.next()[1] == "setze": ta.take() if ta.next()[0] != Lexer.IDENT: raise ParseException("missing identifier after setze") ident = ta.take()[1] if ta.next()[0] != Lexer.KEYWORD or ta.next()[1] != "auf": raise ParserException("missing auf after identifier") ta.take() term = self.__parseTerm(ta.takeUntil(lambda t: t[0] == Lexer.NEWLINE)) block.append(AssignmentTerm(ident,term)) elif ta.next()[1] == "schreibe": ta.take() term = self.__parseTerm(ta.takeUntilType(Lexer.NEWLINE)) block.append(PrintTerm(term)) elif ta.next()[1] == "wenn": stack = ta.next()[2] ta.take() condition = ta.takeUntil(lambda t: t[0] == Lexer.NEWLINE) b = ta.takeUntil(lambda t: t[0] == Lexer.KEYWORD and t[1] == "ende" and t[2] == stack) block.append( ConditionalTerm(self.__parseTerm(condition), self.parse(b) ) ) else: raise Exception("what? %s" % str(ta.next())) elif ta.next()[0] == Lexer.NEWLINE: ta.take() else: raise Exception("huh? %s" % str(ta.next())) return block def __parseTerm(self,tokens): t = tokens[0] if t[0] == Lexer.INT or t[0] == Lexer.FLOAT: return ValueTerm(t[1]) elif t[0] == Lexer.IDENT: return IdentifierTerm(t[1]) else: return ValueTerm(0) class Context(): pass class SubContext(Context): pass class Term(object): def run(self,context): raise Exception("get_value must be overwritten") class Operator2(Term): token = None priority = 0 def __init__(self, left, right): self.left = left self.right = right def run(self,context): return self.calc( self.left.run(context), self.right.run(context) ) def calc(self, r, l): raise Exception("calc not implemented") class IdentifierTerm: def __init__(self, ident): self.ident = ident def run(self,context): return context[self.ident] class ValueTerm: def __init__(self, value): self.value = value def run(self,context): return self.value class AssignmentTerm(Term): def __init__(self,ident,term): self.ident = ident self.term = term def run(self,context): context[self.ident] = self.term.run(context) return None class PrintTerm(Term): def __init__(self,term): self.term = term def run(self,context): print self.term.run(context) return None class ConditionalTerm(Term): def __init__(self,condition,block): self.condition = condition self.block = block def run(self,context): m = self.condition.run(context) if m != 0: self.block.run(context) class BlockTerm(Term): def __init__(self): self.terms = [] def append(self,item): self.terms.append(item) def run(self,context): result = None for term in self.terms: result = term.run(context) return result def main(): context = {} while True: code = raw_input(">>> ") tokens = Lexer().lex(code) term = Parser().parse(tokens) term.run(context) if __name__ == '__main__': main()