Source

BrainMachine / LangParse.py

Full commit
#!/usr/bin/env python

from TxtParse import TxtParse
import OpcodeDef
import NameSpace
import VarDefine

class LangParse():
    def __init__(self, s, pos):
        self.tp = TxtParse(s, pos)
        self.langdef = None

    def LoopParse(self):
        tp = self.tp
        while True:
            tp.SkipEmptyLines()
            if tp.ReachEndPos():
                return
            savpos = tp.pos
            sIdent = tp.SkipIdent()
            if self.langdef.fLikePython:
                if len(sIdent) < len(self.ns.sIden): #out level
                    tp.pos = savpos
                    return
                if sIdent != self.ns.sIden:
                    print '<%s>\n<%s>' % (sIdent, self.ns.sIden)
                    assert False
                del sIdent

            self.MainParseTP()


    def MainParseTP(self):
        tp = self.tp
        wd = tp.SkipOneWord()


        if wd:
            if wd == 'class' and self.langdef.fLikePython: #shall try move the judge in lang define
                self.Parse_Class_likepython()
                return

            if wd == 'def':
                self.Parse_Def()
                return

            if wd == 'if':
                self.Parse_If()
                return
            if wd == 'return':
                self.Parse_Return()
                return
            if wd == 'print': #assume we know print
                self.Parse_Print()
                return

            self.ParseAfterWord(wd)
            return

        self.ns.tem_char_in(tp.PickChar())
        tp.pos += 1

    def ParseAfterWord(self, wd):
        tp = self.tp
        c = tp.PickChar()
        if c == '.':
            tp.SkipChar()
            var1 = VarDefine.NameToken(wd)
            wd2 = tp.SkipOneWord()
            assert wd2
            var2 = VarDefine.NameToken(wd2)
            v = VarDefine.CombineToken(var1, var2, '.')
            self.ParseAfterToken(v)
            return
        verb = self.CheckIfStartWith(self.langdef.opverbs)
        if verb:
            tp.SkipTheWord(verb)
            vleft = VarDefine.NameToken(wd)
            vright = self.ExpectVRight()
            op = OpcodeDef.Opcode_AopB(vleft, vright, verb)
            self.ns.oplist.append(op)
            return

    def CheckIfStartWith(self, tbl):
        tp = self.tp

        for verb in tbl:
            if tp.s.startswith(verb, tp.pos):
                return verb
        return None

    def ParseAfterToken(self, v):
        tp = self.tp

        verb = self.CheckIfStartWith(self.langdef.opverbs)
        if not verb:
            return
        tp.SkipTheWord(verb)

        vright = self.ExpectVRight()

        op = OpcodeDef.Opcode_AopB(v, vright, verb)

        self.ns.oplist.append(op)

    def ExpectVRight(self):
        v = self.ExpectOneToken()
        tokenstack = [v]
        self.Complete_CombineToken(tokenstack)
        assert len(tokenstack) == 1
        return tokenstack[0]

    def Complete_CombineToken(self, tokenstack):
        tp = self.tp
        while True:
            if tp.IsLineEnd():
                break
            c = tp.PickChar()
            if c == '(':
                params = self.ParseParams()
                tokenstack[-1] = VarDefine.FuncToken(tokenstack[-1], params)
                continue
            verb = self.CheckIfStartWith(self.langdef.linkverbs)
            if not verb:
                break
            self.Complete_CombineToken_verb(tokenstack, verb)
            tp.SkipTheWord(verb)
            tokenstack.append(verb)
            vright = self.ExpectOneToken()
            tokenstack.append(vright)
        self.Complete_CombineToken_verb(tokenstack, None)

    def Complete_CombineToken_verb(self, tokenstack, verb):
        def func1():
            v = VarDefine.CombineToken(tokenstack[-3], tokenstack[-1], tokenstack[-2])
            tokenstack[-3:] = [v]

        while True:
            if len(tokenstack) == 1:
                break
            if not verb:
                if len(tokenstack) >= 3:
                    func1()
                    continue
                assert False
            if len(tokenstack) >= 3:
                verb0 = tokenstack[-2]
                from VarDefine import CheckOpPriority
                b = CheckOpPriority(verb0, verb)
                if b:
                    func1()
                    continue
                break
            assert False

    def ExpectOneToken(self):
        tp = self.tp
        tp.SkipWhiteSpace()
        wd = tp.SkipOneWord()
        if wd:
            return VarDefine.NameToken(wd)
        c = tp.PickChar()
        if c == "'":
            s = tp.PopString("'")
            return VarDefine.StringToken(s)
        if c == '(':
            tp.SkipChar('(')
            v = self.ExpectVRight()
            tp.SkipChar(')')
            return v
        assert False

    def Parse_Class_likepython(self):
        tp = self.tp
        name = tp.SkipOneWord()
        assert name
        tp.AssertChar('(')
        params = self.ParseParams()

        sIdent, savns = self.DoIdent()

        classNS = NameSpace.ClassNS(name)
        classNS.sIden = sIdent

        op = OpcodeDef.Opcode_ClassDef(classNS)
        self.ns.oplist.append(op)

        self.ns = classNS

        self.LoopParse()

        self.ns = savns

    def ParseParams(self):
        tp = self.tp
        params = []
        tp.SkipChar('(')
        #should use regular expression
        while True:
            if tp.PickChar() == ')':
                tp.SkipChar(), tp.SkipWhiteSpace()
                return params
            tp.SkipWhiteSpace()
            wd = tp.SkipOneWord()
            params.append(wd)
            if tp.PickChar() == ',':
                tp.SkipChar(), tp.SkipWhiteSpace()

    def Parse_Def(self):
        tp = self.tp
        name = tp.SkipOneWord()
        assert name
        tp.AssertChar('(')
        params = self.ParseParams()

        sIdent, savns = self.DoIdent()

        funcNS = NameSpace.FuncNS(name, params)
        funcNS.sIden = sIdent

        op = OpcodeDef.Opcode_FuncDef(funcNS)
        self.ns.oplist.append(op)

        self.ns = funcNS

        self.LoopParse()

        self.ns = savns

    def Parse_If(self):
        tp = self.tp
        v = self.ExpectVRight()

        sIdent, savns = self.DoIdent()

        ifNS = NameSpace.BranchNS('if')
        ifNS.sIden = sIdent

        op = OpcodeDef.Opcode_If(v, ifNS)
        self.ns.oplist.append(op)

        self.ns = ifNS

        self.LoopParse()

        self.ns = savns

    def DoIdent(self):
        tp = self.tp
        tp.SkipChar(':')
        tp.SkipEmptyLines()
        pos = tp.pos
        sIdent = tp.SkipIdent()
        assert sIdent
        assert len(sIdent) > len(self.ns.sIden)
        tp.pos = pos
        savns = self.ns
        return sIdent, savns

    def Parse_Return(self):
        tp = self.tp
        v = self.ExpectVRight()
        op = OpcodeDef.Opcode_Return(v)
        self.ns.oplist.append(op)

    def Parse_Print(self):
        tp = self.tp
        v = self.ExpectVRight()
        op = OpcodeDef.Opcode_Print(v)
        self.ns.oplist.append(op)