Example #1
0
    // Parse a single Crst type definition.
    void ParseCrst()
    {
        // The next token had better be an identifier (the Crst type name).
        Token token = NextToken();

        if (token.Id != KeywordId.Id)
        {
            throw new UnexpectedTokenError(token, KeywordId.Id);
        }

        // The Crst instance might already exist in the dictionary (forward references to a Crst type cause
        // these entries to auto-vivify). But in that case the entry better not be marked as 'Defined' which
        // would indicate a double declaration.
        CrstType crst;

        if (m_crsts.ContainsKey(token.Text))
        {
            crst = m_crsts[token.Text];
            if (crst.Defined)
            {
                throw new ParseError(String.Format("Duplicate definition for CrstType '{0}'", token.Text), token);
            }
        }
        else
        {
            // Otherwise this Crst type hasn't been seen thus far so we allocate a new instance and add it to
            // the dictionary.
            crst = new CrstType(token.Text);
            m_crsts.Add(crst.Name, crst);
        }

        // We're defining, not just referencing this type.
        crst.Defined = true;

        // Parse any attributes inside this definition (until we see an 'End' token).
        bool parsingCrst = true;

        while (parsingCrst)
        {
            // Get the next token. Either some attribute keyword or 'End'.
            token = NextToken();
            List <CrstType> list;

            switch (token.Id)
            {
            case KeywordId.AcquiredBefore:
                // Simply parse the following list of Crst types into the current type's AcquiredBefore list.
                ParseList(crst.AcquiredBeforeList);
                break;

            case KeywordId.AcquiredAfter:
                // AcquiredAfter is trickier. To make the ranking algorithm's life easier we actually
                // normalize all rules to the AcquiredBefore form (see LevelCrsts() for the reasoning). So we
                // capture the list of Crst types that follow the AcquiredAfter keyword and then append the
                // current type to the AcquiredBefore list of each type found.
                list = new List <CrstType>();
                ParseList(list);
                foreach (CrstType priorCrst in list)
                {
                    priorCrst.AcquiredBeforeList.Add(crst);
                }
                break;

            case KeywordId.SameLevelAs:
                // Parse the following list of Crst types them let the CrstTypeGroup class handle the
                // resulting updates to the type groups we're currently maintaining. See the comments for the
                // CrstTypeGroup class for more details.
                list = new List <CrstType>();
                ParseList(list);
                foreach (CrstType sameLevelCrst in list)
                {
                    CrstTypeGroup.Join(crst, sameLevelCrst);
                }
                break;

            case KeywordId.Unordered:
                crst.Level = CrstType.CrstUnordered;
                break;

            case KeywordId.End:
                parsingCrst = false;
                break;

            default:
                throw new UnexpectedTokenError(token,
                                               KeywordId.AcquiredBefore,
                                               KeywordId.AcquiredAfter,
                                               KeywordId.SameLevelAs,
                                               KeywordId.Unordered);
            }
        }
    }