diff --git a/gerlang.py b/gerlang.py index 25320a0..dd2e62a 100644 --- a/gerlang.py +++ b/gerlang.py @@ -30,11 +30,17 @@ class StringAnalyzer(Analyzer): 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 self.next()[0] != end: + 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"] @@ -51,6 +57,7 @@ class Lexer: 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 = "" @@ -60,6 +67,12 @@ class Lexer: 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 @@ -108,25 +121,34 @@ class Parser: if ta.next()[0] != Lexer.KEYWORD or ta.next()[1] != "auf": raise ParserException("missing auf after identifier") ta.take() - term = self.__parseTerm(ta.takeUntilType(Lexer.NEWLINE)) - 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.IDENT: - return IdentifierTerm(t[1]) - elif t[0] == Lexer.INT or t[0] == Lexer.FLOAT: + if t[0] == Lexer.INT or t[0] == Lexer.FLOAT: return ValueTerm(t[1]) + elif t[0] == Lexer.IDENT: + return IdentifierTerm(t[1]) else: - raise ParseException("Unexpected token %s" % t) + return ValueTerm(0) class Context(): pass @@ -134,10 +156,23 @@ class Context(): class SubContext(Context): pass -class Term: +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 @@ -169,6 +204,17 @@ class PrintTerm(Term): 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 = [] @@ -186,12 +232,9 @@ def main(): context = {} while True: code = raw_input(">>> ") - try: - tokens = Lexer().lex(code) - term = Parser().parse(tokens) - term.run(context) - except Exception, e: - print e + tokens = Lexer().lex(code) + term = Parser().parse(tokens) + term.run(context) if __name__ == '__main__': main() \ No newline at end of file