Exemple #1
0
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))