⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
    
    ParserErrorException E_BadParamListOnOps(FileRange location, string stHint)
    {
        return new ParserErrorException(
            Code.cBadParamListOnOps,
            location,
            "Bad parameter list for overloaded operator:" + stHint);   
    }
    
#endregion // Errors    

#region Public Methods for IParser



//-----------------------------------------------------------------------------
// Top level function
// Parse a compile-unit (single source file)
// A program may contain multiple source files
//
// ** rules **
// Program -> NamespaceBody
//-----------------------------------------------------------------------------    
    public NamespaceDecl ParseSourceFile()
    {   
        NamespaceDecl nGlobal = null;

        try
        {
            NamespaceDecl t = null;
            FileRange f = BeginRange();
            t = ParseNamespaceBody(new Identifier("", null));            
            ReadExpectedToken(Token.Type.cEOF); // this could throw an exception...
            t.SetLocation(EndRange(f));
            
            // Only once we know we can't get any errors do we set nGlobal to non-null
            nGlobal = t;
        }
        
        // Strip away parser errors. We must have called ThrowError() to throw
        // this exception, and so we know it's already been reported.
        catch(ParserErrorException)
        {            
        }
        
        // General catch to protect the parsing subsystem
        catch(System.Exception e)
        {
            Blue.Driver.PrintError_InternalError(e, "parse");            
        }   
                        
        return nGlobal;
    }
#endregion

#region Linenumber tracking
//-----------------------------------------------------------------------------
// Helpers to rack line numbers.
// BeginRange returns a filerange to pass to GetCurRange(). Together these 
// provide a FileRange to describe whatever is parsed between Begin & End.
// They can be nested.
//-----------------------------------------------------------------------------
    
    protected FileRange BeginRange()
    {
        Token t = m_lexer.PeekNextToken();
        
        FileRange f = new FileRange(t.Location.Filename,
            t.Location.RowStart, t.Location.ColStart,
            -1, -1);
            
        return f;            
    }
        
    protected FileRange EndRange(FileRange f)
    {   
        // Can't peek at the current token to decide where the end is because
        // it may be on another line.
        // So we store the last token read and use that.        
        f.RowEnd = m_tLastRead.Location.RowEnd;
        f.ColEnd = m_tLastRead.Location.ColEnd;
        return f;            
    }
    
    private Token m_tLastRead;

#endregion

#region Standard Helpers
//-----------------------------------------------------------------------------
// Helper to consume and throw away a token (useful after we peek at it)
//-----------------------------------------------------------------------------
    protected void ConsumeNextToken()
    {
        m_tLastRead = m_lexer.GetNextToken();
    }

//-----------------------------------------------------------------------------
// Helper to read an expected token and throw error if it's not found
//-----------------------------------------------------------------------------
    protected Token ReadExpectedToken(Token.Type tExpected)
    {
        Token tNext = m_lexer.GetNextToken();
        if (tNext.TokenType != tExpected)
        {            
            ThrowError(E_UnexpectedToken(tNext, tExpected));
        }
        m_tLastRead = tNext;
        return tNext;
    }
    
//-----------------------------------------------------------------------------
// Helper to read an identifier and return the string
// Will throw an error if we don't have an identifier.
//-----------------------------------------------------------------------------    
    protected Identifier ReadExpectedIdentifier()
    {
        Token t = ReadExpectedToken(Token.Type.cId);
        return new Identifier(t.Text, t.Location);        
    }

#endregion

#region Parse Declarations
//-----------------------------------------------------------------------------
// 3 sorts of Types.
//-----------------------------------------------------------------------------
    protected enum Genre
    {
        cInterface,
        cClass,
        cStruct
    }
    
//-----------------------------------------------------------------------------
// Parse a namespace.
//
// ** rules **
// Namespace -> 'namespace' id.id.id... '{' NamespaceBody '}'
//-----------------------------------------------------------------------------
    protected NamespaceDecl ParseNamespace()
    {        
        ReadExpectedToken(Token.Type.cNamespace);
        return ParseNamespaceHelper();
        
    }
    
    protected NamespaceDecl ParseNamespaceHelper()
    {   
        Token t;                      
        Identifier i = ReadExpectedIdentifier();
        
        
        t = m_lexer.PeekNextToken();
        if (t.TokenType == Token.Type.cDot)
        {
            ConsumeNextToken();
            NamespaceDecl nInner = ParseNamespaceHelper();
            return new NamespaceDecl(i, null, new NamespaceDecl[] { nInner}, null, null);
        }        
        
        FileRange f = this.BeginRange();
        ReadExpectedToken(Token.Type.cLCurly);        
        NamespaceDecl n = ParseNamespaceBody(i);
        ReadExpectedToken(Token.Type.cRCurly);
        n.SetLocation(this.EndRange(f));
        
        return n;
    }

//-----------------------------------------------------------------------------
// Parse a namespace body (since we're just parsing the body, we have to 
// pass in the name).
// 
// ** rules **
// NamespaceBody-> (UsingDirectives)? (Namespace | ClassDecl)*
//-----------------------------------------------------------------------------
    protected NamespaceDecl ParseNamespaceBody(Identifier idName)
    {
        UsingDirective[] arUsingNodes = ParseUsingDirectives();
                
        //ArrayList alClasses = new ArrayList();
        ArrayList alNestedNamespaces = new ArrayList();
        //ArrayList alEnums = new ArrayList();
        ArrayList alTypes = new ArrayList();

        while(true)
        {                        
            Modifiers mods = ParseModifiers();
            Token t = m_lexer.PeekNextToken();
             
            switch(t.TokenType)
            {
                case Token.Type.cClass:
                {
                    ClassDecl nodeClass = ParseClass(mods);
                    alTypes.Add(nodeClass);
                }
                    break;
                    
                case Token.Type.cStruct:
                {
                    ClassDecl nodeStruct = ParseStruct(mods);
                    alTypes.Add(nodeStruct);                
                }
                    break;                    

                case Token.Type.cInterface:
                {
                    ClassDecl nodeClass = ParseInterface(mods);
                    alTypes.Add(nodeClass);
                }
                    break;
            
                case Token.Type.cNamespace:
                {
                    NamespaceDecl nNested = ParseNamespace();
                    alNestedNamespaces.Add(nNested);
                }
                    break;

                case Token.Type.cEnum:
                {
                    EnumDecl e = ParseEnum(mods);
                    alTypes.Add(e);                    
                }
                    break;
                    
                case Token.Type.cDelegate:
                {
                    DelegateDecl d = ParseDelegate(mods);
                    alTypes.Add(d);
                }
                    break;

                default:
                    // Like to break out of the 'while' here, but a 'break' statement
                    // will just get out of the 'switch', not the while, so use a goto
                    goto Done;

            } // end switch
            
                
            t = m_lexer.PeekNextToken();
        } // end while
Done:
        NamespaceDecl [] arNamespaces = (NamespaceDecl []) alNestedNamespaces.ToArray(typeof(NamespaceDecl));
        TypeDeclBase [] arTypes = (TypeDeclBase []) alTypes.ToArray(typeof(TypeDeclBase));
                    
        return new NamespaceDecl(idName, arUsingNodes, arNamespaces, null, arTypes);    
    }

//-----------------------------------------------------------------------------
// Parse and return an array of using declarations 
// ** rules **
// UsingDirective -> 'using' id:name '=' id_list ';'      // for aliasing
// UsingDirective -> 'using' id_list ';'                  // for namespaces
//-----------------------------------------------------------------------------
    protected UsingDirective[] ParseUsingDirectives()
    {
        Token t;
                       
        t = m_lexer.PeekNextToken();

        ArrayList a = new ArrayList();

        while( t.TokenType == Token.Type.cUsing)
        {
            ConsumeNextToken();
            Exp o = ParseDottedIdList();

            UsingDirective node;

            FileRange f = this.BeginRange();        
            t = m_lexer.PeekNextToken();
            if (t.TokenType == Token.Type.cAssign)
            {
                ConsumeNextToken();
                // o had better be a single identifier
                SimpleObjExp s = o as SimpleObjExp;
                Debug.Assert(s != null);
                string stAlias = s.Name.Text;

                Exp o2 = ParseDottedIdList();
                node = new UsingDirective(stAlias, o2);
            } 
            else 
            {
                node = new UsingDirective(o);
            }
            ReadExpectedToken(Token.Type.cSemi);

            Debug.Assert(node != null);
            node.SetLocation(this.EndRange(f));
            a.Add(node);
            t = m_lexer.PeekNextToken();
        }


        UsingDirective[] arNodes = (UsingDirective[]) a.ToArray(typeof(UsingDirective));
        
        return arNodes;
    }

//-----------------------------------------------------------------------------
// Parse delegate declaration
// --> 'delegate' Type:rettype id:name '(' param_list ')' ';'
//-----------------------------------------------------------------------------
    protected DelegateDecl ParseDelegate(Modifiers mods)
    {
        ReadExpectedToken(Token.Type.cDelegate);
        TypeSig tRetType            = ParseTypeSig();
        Identifier idName           = ReadExpectedIdentifier();        
        ParamVarDecl [] arParams    = ParseParamList(); // includes '(' ... ')'
        ReadExpectedToken(Token.Type.cSemi);
    
        FileRange f = this.BeginRange();
        DelegateDecl node = new DelegateDecl(idName, tRetType, arParams, mods);
        node.SetLocation(this.EndRange(f));
        return node;
    }
    

//-----------------------------------------------------------------------------
// Parse enum declaration
// --> 'enum' id:name '{' enum_decl_list '}'
//-----------------------------------------------------------------------------
    protected EnumDecl ParseEnum(Modifiers modsEnums)
    {
        ReadExpectedToken(Token.Type.cEnum);

        Identifier idName = ReadExpectedIdentifier();
        FileRange f2 = this.BeginRange();
        ReadExpectedToken(Token.Type.cLCurly);
        
        ArrayList a = new ArrayList();

        // All enum fields are Static, Public, Literal
        // and have fieldtype set to type of the enum
        //Modifiers mods = new Modifiers(Modifiers.EFlags.Public | Modifiers.EFlags.Static);
        Modifiers mods = new Modifiers();
        mods.SetPublic();
        mods.SetStatic();
        
        TypeSig tSig = new SimpleTypeSig(new SimpleObjExp(idName));

        Identifier idPrev = null;

        Token t = m_lexer.PeekNextToken();
        while(t.TokenType != Token.Type.cRCurly)
        {
        // Parse fields
            Identifier id = ReadExpectedIdentifier();

            Exp expInit = null;

            t = m_lexer.PeekNextToken();
            if (t.TokenType == Token.Type.cAssign)
            {                
                ConsumeNextToken();
                expInit = ParseExp();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -