class GParser: def __init__(self, gramma): self.gl = Glex(open(gramma).read()) self.lexer = Lexer() self.classes = [] self.rules = {} def gnt(self): self.nt = self.gl.nextToken() def tis(self, t, v=None): if not self.nt: return False return self.nt[0] == t and (not v or self.nt[1] == v) def tass(self, t, v=None): if self.tis(t, v): return if v: raise ParseError("Expected '%s'" % v, self.nt) else: raise ParseError("Expected %s" % t, self.nt) def parseType(self): self.tass(TLIT) # Name t = GType(self.nt) self.gnt() if self.tis(KEYWORD, "["): # In an array self.gnt() self.tass(KEYWORD, "]") t.isArray = True self.gnt() return t def parseExpr(self): if self.tis(TLIT): c = GConstructorCall(self.nt) self.gnt() self.tass(KEYWORD, "(") self.gnt() if not self.tis(KEYWORD, ")"): while True: c.arguments.append(self.parseExpr()) if not self.tis(KEYWORD, ","): break self.gnt() self.tass(KEYWORD, ")") self.gnt() return c if self.tis(KEYWORD, "this"): x = GThislookup(self.nt) else: self.tass(GLIT) x = GVarlookup(self.nt) self.gnt() while True: if not self.tis(KEYWORD, "."): break self.gnt() self.tass(GLIT) x = GClasslookup(x, self.nt) self.gnt() return x def parseBlock(self): b = GBlock() while True: if self.tis(KEYWORD, "var"): v = GVar() self.gnt() self.tass(GLIT) v.name = self.nt self.gnt() self.tass(KEYWORD, ":") self.gnt() self.tass(TLIT) v.type = self.nt self.gnt() self.tass(KEYWORD, ";") self.gnt() b.stmts.append(v) continue if self.tis(KEYWORD, "return"): self.gnt() b.stmts.append(GReturn(self.parseExpr())) self.tass(KEYWORD, ";") self.gnt() continue if not self.tis(GLIT) and not self.tis(TLIT) and not self.tis(KEYWORD, "this"): break e = self.parseExpr() if self.tis(KEYWORD, "+="): self.gnt() e = GAppend(e, self.parseExpr()) elif self.tis(KEYWORD, "="): self.gnt() e = GAssign(e, self.parseExpr()) self.tass(KEYWORD, ";") self.gnt() b.stmts.append(e) return b def parseClass(self): self.gnt() self.tass(TLIT) # Name c = GClass(self.nt) self.gnt() if self.tis(KEYWORD, "("): self.gnt() while True: self.tass(TLIT) # Extend name c.extends.append(self.nt) self.gnt() if not self.tis(KEYWORD, ","): break self.gnt() self.tass(KEYWORD, ")") self.gnt() self.tass(KEYWORD, "{") self.gnt() while True: if self.tis(KEYWORD, "construct"): con = GConstructor() self.gnt() self.tass(KEYWORD, "(") self.gnt() if not self.tis(KEYWORD, ")"): while True: self.tass(GLIT) # Name n = self.nt self.gnt() self.tass(KEYWORD, ":") self.gnt() t = self.parseType() con.arguments.append((n, t)) if not self.tis(KEYWORD, ","): break self.gnt() self.tass(KEYWORD, ")") self.gnt() self.tass(KEYWORD, "{") self.gnt() con.block = self.parseBlock() self.tass(KEYWORD, "}") self.gnt() c.constructors.append(con) elif self.tis(KEYWORD, "var"): self.gnt() self.tis(GLIT) n = self.nt self.gnt() self.tass(KEYWORD, ":") self.gnt() ty = self.parseType() self.tass(KEYWORD, ";") self.gnt() c.vardecls.append(GClassVarDecl(n, ty)) else: break self.tass(KEYWORD, "}") self.gnt() return c def parseContinuation(self): r = GContinuation() while True: if self.tis(KEYWORD, "{"): self.gnt() r.items.append(self.parseBlock()) self.tass(KEYWORD, "}") self.gnt() continue x = None if self.tis(KEYWORD, "("): self.gnt() x = self.parseConjunction() self.tass(KEYWORD, ")") self.gnt() else: if self.tis(SLIT): x = GTokenRef(self.nt) v = self.nt[1][1:-1] x.tname = self.lexer.addKeyword(v) x.displayName = "'%s'" % v self.gnt() elif self.tis(TLIT): x = GTokenRef(self.nt) self.gnt() if self.tis(KEYWORD, "["): self.gnt() if self.tis(SLIT): x.displayName = self.nt[1][1:-1] else: x.displayName = self.nt[1] self.gnt() self.tass(KEYWORD, "]") self.gnt() elif self.tis(KEYWORD, "recover"): self.gnt() self.tass(TLIT) x = GTokenRef(self.nt, True) self.gnt() elif self.tis(GLIT): x = GGrammaRef(self.nt) self.gnt() else: break if self.tis(KEYWORD, ":"): self.gnt() self.tass(GLIT) x.name = self.nt self.gnt() if self.tis(KEYWORD, "*"): x = GStar(x) self.gnt() if self.tis(KEYWORD, "*"): x.captureAll = True self.gnt() elif self.tis(KEYWORD, "+"): x = GPlus(x) self.gnt() elif self.tis(KEYWORD, "?"): x = GOpt(x) self.gnt() r.items.append(x) return r def parseConjunction(self): r = self.parseContinuation() if self.tis(KEYWORD, "|"): c = GConjunction() c.items.append(r) r = c while self.tis(KEYWORD, "|"): self.gnt() r.items.append(self.parseContinuation()) return r def parse(self): try: self.gnt() while self.nt: if self.tis(TLIT): v = self.nt[1] self.gnt() self.tass(KEYWORD, ":=") r = self.gl.nextRegexp() self.lexer.addClass(v, r) self.gnt() continue if self.tis(KEYWORD, "class"): self.classes.append(self.parseClass()) continue self.tass(GLIT) v = self.nt self.gnt() self.tass(KEYWORD, ":=") self.gnt() self.rules[v[1]] = (v, self.parseConjunction()) self.tass(KEYWORD, ";") self.gnt() except ParseError, e: print "ParseError: %s\nat %s" % (e.msg, self.gl.tloc(e.tok))