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

📄 parser.cs

📁 charp compiler
💻 CS
📖 第 1 页 / 共 5 页
字号:
                ThrowError(E_UnexpectedToken(t));
            }
        
            t = m_lexer.PeekNextToken();
        } // end member decl list
        
        ReadExpectedToken(Token.Type.cRCurly);    
        
        MethodDecl [] arMethods = MethodDeclFromArray(alMethods);
        FieldDecl [] arFields = FieldDeclFromArray(alFields);
        PropertyDecl [] arProperties = PropertyDeclFromArray(alProperties);
        
        EventDecl [] arEvents = (EventDecl[]) alEvents.ToArray(typeof(EventDecl));
        
        TypeDeclBase[] arNestedTypes = new TypeDeclBase[alNestedTypes.Count];
        for(int i = 0; i < alNestedTypes.Count; i++)
            arNestedTypes[i] = (TypeDeclBase) alNestedTypes[i];
        
        return new ClassDecl(
            stClassName, 
            arBase, 
            arMethods,
            arProperties,
            arFields,
            arEvents,
            arNestedTypes,
            modsClass,
            fIsClass
        );
    }

#region Array conversions
//-----------------------------------------------------------------------------
// Helpes to convert from ArrayLists to normal arrays
// Have to do this until mscorlib works the bugs out of its array conversion
// stuff.
//-----------------------------------------------------------------------------
    protected ParamVarDecl[] ParamVarDeclFromArray(ArrayList alParams)
    {
        ParamVarDecl[] v = new ParamVarDecl[alParams.Count];
        for(int i = 0; i < alParams.Count; i++)            
            v[i] = (ParamVarDecl) alParams[i];
            
        return v;
    }
    
    protected LocalVarDecl[] LocalVarDeclFromArray(ArrayList alParams)
    {
        LocalVarDecl[] v = new LocalVarDecl[alParams.Count];
        for(int i = 0; i < alParams.Count; i++)            
            v[i] = (LocalVarDecl) alParams[i];
            
        return v;
    }
    
    protected FieldDecl[] FieldDeclFromArray(ArrayList alParams)
    {
        FieldDecl[] v = new FieldDecl[alParams.Count];
        for(int i = 0; i < alParams.Count; i++)            
            v[i] = (FieldDecl) alParams[i];
            
        return v;
    }
    
    protected PropertyDecl [] PropertyDeclFromArray(ArrayList alProperties)
    {
        PropertyDecl [] v = new PropertyDecl[alProperties.Count];
        for(int i = 0; i < alProperties.Count; i++)
            v[i] = (PropertyDecl) alProperties[i];
            
        return v;
    }
    
    protected Statement[] StatementFromArray(ArrayList alParams)
    {
        Statement[] v = new Statement[alParams.Count];
        for(int i = 0; i < alParams.Count; i++)            
            v[i] = (Statement) alParams[i];
            
        return v;
    }
    
    protected MethodDecl[] MethodDeclFromArray(ArrayList alParams)
    {
        MethodDecl[] v = new MethodDecl[alParams.Count];
        for(int i = 0; i < alParams.Count; i++)            
            v[i] = (MethodDecl) alParams[i];
            
        return v;
    }
#endregion
    
//-----------------------------------------------------------------------------
// Parse a parameter list (including opening & closing parens)
// -> '(' (''|'ref'|'out') typesig id ',' typesig id ',' ... ')'
//-----------------------------------------------------------------------------

// @todo - allow out,ref
    protected ParamVarDecl [] ParseParamList()
    {
        ReadExpectedToken(Token.Type.cLParen);

        // Read parameter list. Keep looping until we get the closing ')'
        // param-> Typesig id
        // paramlist-> <comma separated list of 'param'>
        ArrayList alParams = new ArrayList();
    
        Token t = m_lexer.PeekNextToken();
        
        if (t.TokenType == Token.Type.cRParen)
            ConsumeNextToken();
        
        bool fUsedParams = false;
        while (t.TokenType != Token.Type.cRParen)
        {
            Debug.Assert(!fUsedParams, "@todo - 'params' only allowed on last thing");
            t = m_lexer.PeekNextToken();
            // Check for flow modifier
            AST.EArgFlow eFlow = EArgFlow.cIn;
            if (t.TokenType == Token.Type.cRef)
                eFlow = EArgFlow.cRef;
            else if (t.TokenType == Token.Type.cOut)
                eFlow = EArgFlow.cOut;  
            
            // Allow 'params' modifier for a vararg on last parameter
            else if (t.TokenType == Token.Type.cParams)
            {
                fUsedParams = true;   
                ConsumeNextToken();
                t = m_lexer.PeekNextToken();
            }                              
                
            if (eFlow != EArgFlow.cIn) {
                ConsumeNextToken();                
            }
            
            
            // param-> Typesig id
            NonRefTypeSig type = ParseTypeSig();
            Identifier stName = ReadExpectedIdentifier();
        
            VarDecl nodeDecl = new ParamVarDecl(stName, type, eFlow);
            alParams.Add(nodeDecl);
        
            t = m_lexer.GetNextToken();
            
            CheckError_UnexpectedToken(t, new Token.Type [] { Token.Type.cComma, Token.Type.cRParen } );            
        }        
        
    
        ParamVarDecl [] arParams = ParamVarDeclFromArray(alParams);

        return arParams;
    }

//-----------------------------------------------------------------------------
// Partial parse an Indexer decl
//
// ** rules **
// IndexerDecl  -> mods type 'this' '[' param_list ']' '{' property_body '}'
//-----------------------------------------------------------------------------
    protected PropertyDecl PartialParseIndexerDecl(
        Modifiers mods, 
        TypeSig typeReturn, 
        Identifier stMemberName
    )
    {
        Debug.Assert(stMemberName.Text == "this");
        
        // @todo - Change name to 'Item'
        
        FileRange f = this.BeginRange();
        ReadExpectedToken(Token.Type.cLSquare);
        // @todo  - For now, we only support one parameter
        NonRefTypeSig t = this.ParseTypeSig();
        Identifier idParam = this.ReadExpectedIdentifier();   
             
        ReadExpectedToken(Token.Type.cRSquare);
                
        BlockStatement stmtGet;
        BlockStatement stmtSet;
                        
        bool fHasGet;
        bool fHasSet;
                        
        ParseAccessors(mods.IsAbstract, stMemberName,
            out stmtGet, out fHasGet,
            out stmtSet, out fHasSet);
        
        PropertyDecl p = new PropertyDecl(
            stMemberName, typeReturn,
            new ParamVarDecl(idParam, t, EArgFlow.cIn), 
            stmtGet, fHasGet, 
            stmtSet, fHasSet, 
            mods);
          
        p.SetLocation(this.EndRange(f));            
        return p;            
    }

//-----------------------------------------------------------------------------
// Partial parse an event
// ** rules **
// EventDecl -> mods 'event' type id ';'
//-----------------------------------------------------------------------------
    protected EventDecl PartialParseEventDecl(
        Modifiers mods)
    {
        
        FileRange f = this.BeginRange();
        ReadExpectedToken(Token.Type.cEvent);
        
        NonRefTypeSig t = ParseTypeSig();
        Identifier idName = ReadExpectedIdentifier();
        ReadExpectedToken(Token.Type.cSemi);


        EventDecl node = new EventDecl(idName, t, mods);            
        node.SetLocation(this.EndRange(f));
        
        return node;
    }        

//-----------------------------------------------------------------------------
// Partial parse a property decl.
// We've already parsed the modifiers, return type & member name, so
// pass those in as parameters. Start parsing at '{'
// Note that indexers are just properties that take parameters.
//
// ** rules **
// PropertyDecl -> mods type id '{' property_body '}'
//-----------------------------------------------------------------------------
    protected PropertyDecl PartialParsePropertyDecl(
        Modifiers mods, 
        TypeSig typeReturn, 
        Identifier stMemberName
    )
    {   
        // Note that properties can be abstract, in which case their bodyStmt is null.
        // Also note that both get & set have the same modifiers        
                
        FileRange f = this.BeginRange();
                        
        BlockStatement stmtGet;
        BlockStatement stmtSet;
                        
        bool fHasGet;
        bool fHasSet;
                        
        ParseAccessors(mods.IsAbstract, stMemberName,
            out stmtGet, out fHasGet,
            out stmtSet, out fHasSet);
                
        PropertyDecl p = new PropertyDecl(
            stMemberName, typeReturn, 
            stmtGet, fHasGet, 
            stmtSet, fHasSet, 
            mods); 
        
        p.SetLocation(this.EndRange(f));
        return p;
    }
    
//-----------------------------------------------------------------------------
// Parse accessors
//
// *** rules ***
// propertyBody -> 'get' block | 'set' block  | 
//                 'get' block 'set' block | 
//                 'set' block 'get' block
//
// For an abstract property:
// PropertyBody -> 'get' ';' | 'set' ';' | 
//                 'get' ';' 'set' ';' | 
//                 'set' ';' 'get' ';'
//-----------------------------------------------------------------------------    
    protected void ParseAccessors(
        bool fIsAbstract,
        Identifier stMemberName,
        out BlockStatement stmtGet,
        out bool fHasGet,
        out BlockStatement stmtSet,
        out bool fHasSet
    )
    {    
        // We've already parsed everything up until, but not including, the '{'
        ReadExpectedToken(Token.Type.cLCurly);
                
        stmtGet = null;
        stmtSet = null;
                        
        fHasGet = false;
        fHasSet = false;
        
        Token t  = m_lexer.GetNextToken();
        
        // Parse the get/set accesssors
        while(t.TokenType != Token.Type.cRCurly)
        {                            
            switch(t.TokenType)
            {
                case Token.Type.cGet:
                    if (fHasGet)
                        ThrowError(E_AccessorAlreadyDefined(stMemberName, true));
                    
                    fHasGet = true;
                    if (fIsAbstract)
                        ReadExpectedToken(Token.Type.cSemi);
                    else
                        stmtGet = ParseStatementBlock();
                    break;
                
                case Token.Type.cSet:
                    if (fHasSet)
                        ThrowError(E_AccessorAlreadyDefined(stMemberName, false));

                    fHasSet = true;
                    if (fIsAbstract)
                        ReadExpectedToken(Token.Type.cSemi);
                    else                        
                        stmtSet = ParseStatementBlock();
                    break;
                
                default: // error
                    //this.ThrowError_UnexpectedToken(t, new Token.Type [] { Token.Type.cGet, Token.Type.cSet } );
                    ThrowError(E_UnexpectedToken(t, Token.Type.cGet, Token.Type.cSet));
                    break;
            }
            
            t = m_lexer.GetNextToken();
        }
        
        // Already consumed the closing '}', so we're done. 
        // So just do some error checks & create the ast node
        
        if (!fHasGet && !fHasSet)
            ThrowError(E_MissingAccessor(stMemberName));
    }        
        

//-----------------------------------------------------------------------------
// Parse for overloaded operator
// -> mods type 'operator' op '(' paramlist ')' '{' statementlist '}'
//-----------------------------------------------------------------------------
    protected MethodDecl PartialParseOverloadedOp(    
        Modifiers mods, // must be public & static
        TypeSig typeReturn
    )
    {
        /*
        Modifiers modsLegal = new Modifiers(Modifiers.EFlags.Public | Modifiers.EFlags.Static);
        if (modsLegal.Flags != mods.Flags)
            ThrowError_BadModsOnOps(typeReturn.Location);
        */
        if (!mods.IsStatic || !mods.IsPublic)
            ThrowError(E_BadModsOnOps(typeReturn.Location));
        
            
        ReadExpectedToken(Token.Type.cOperator);
        
        // Get the operator

⌨️ 快捷键说明

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