C語言解譯器-19 文法分析(4)

來源:互聯網
上載者:User

以+操作符為例,說明操作符分析的過程:

private bool ParseExpression_Plus(Context ctx, SourceCode src, ref Expression.ExpressionNode expTree)        {            if (src.TestNextChar('=')) // +=            {                src.NextChar();                src.NextChar(); // skip '+='                return AddOperatorNode(ref expTree, new Expression.Operator.Binary.AddAssign());            }            else            {                if (src.TestNextChar('+')) // self ++                {                    src.NextChar();                    src.NextChar(); // skip '++'                    if (expTree == null)                    {                        return AddOperatorNode(ref expTree, new Expression.Operator.Unary.PrefixIncrease());                    }                    else                    {                        if (m_lastExpNode == null || (m_lastExpNode != null && m_lastExpNode.Token is Expression.Operator.Operator)) //                         {                            return AddOperatorNode(ref expTree, new Expression.Operator.Unary.PrefixIncrease());                        }                        else                            return AddOperatorNode(ref expTree, new Expression.Operator.Unary.PostfixIncrease());                    }                }                else                {                    src.NextChar(); // skip '+'                    if (m_lastExpNode == null || (m_lastExpNode != null && m_lastExpNode.Token is Expression.Operator.Operator))                        return AddOperatorNode(ref expTree, new Expression.Operator.Unary.Plus());                    else                        return AddOperatorNode(ref expTree, new Expression.Operator.Binary.Add());                }            }        }

最後,是擷取實值型別的方法:

private Expression.Operand.Value GetNumberValue(Context ctx, SourceCode src)        {            // Test '0x'            if (src.CurrentChar == '0' && src.TestNextChar(SourceCode.HexMark))            {                return GetHexValue(ctx, src);            }            else            {                return GetIntOrFloatValue(ctx, src);            }        }        private Expression.Operand.Value GetHexValue(Context ctx, SourceCode src)        {            int start = src.Column;            src.NextChar(); // skip '0'            src.NextChar(); // skip 'x'            do            {                if (SourceCode.IsDigit(src.CurrentChar) ||                    (src.CurrentChar >= 'a' && src.CurrentChar <= 'f') ||                    (src.CurrentChar >= 'A' && src.CurrentChar <= 'F'))                {                    src.NextChar();                }                else                {                    break;                }            } while (true);            if (src.Column - start < 3)                if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid hex format."))                    return null;            if (src.Column - start > 10)                if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid hex format."))                    return null;            string hexStr = src.Text.Substring(start + 2, src.Column - start - 2);            UInt32 val = UInt32.Parse(hexStr, System.Globalization.NumberStyles.HexNumber);            if (hexStr.Length < 3) // 0xFF                return new Expression.Operand.Value()                {                    DataType = PrimitiveDataType.CharType | PrimitiveDataType.UnsignedType,                    DataField = (byte)val                };            else                if (hexStr.Length < 5) // 0xFFFF                    return new Expression.Operand.Value()                        {                            DataType = PrimitiveDataType.ShortType | PrimitiveDataType.UnsignedType,                            DataField = (ushort)val                        };                else // 0xFFFFFFFF                    return new Expression.Operand.Value()                    {                        DataType = PrimitiveDataType.IntType,                        DataField = (ushort)val                    };        }        private Expression.Operand.Value GetIntOrFloatValue(Context ctx, SourceCode src)        {            bool isUnsigned = false;            int pointNum = 0;            int expNum = 0;            int floatMark = 0;            int start = src.Column;            src.NextChar(); // skip first digit            while (!src.Eof)            {                bool stop = false;                switch (src.CurrentChar)                {                    case '.':                        {                            pointNum++;                            if (pointNum > 1)                                if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid float format."))                                    return null;                            if (src.TestNextChar(SourceCode.ExponentialMark))                                if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid float format."))                                    return null;                            src.NextChar();                        }                        break;                    case 'e':                    case 'E':                        {                            expNum++;                            if (expNum > 1)                                if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid float format."))                                    return null;                            if (src.TestNextChar(SourceCode.PlusMinusMark))                                if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid float format."))                                    return null;                            src.NextChar(); // skip 'e/E'                            src.NextChar(); // skip '+/-'                        }                        break;                    case 'f':                    case 'F':                        {                            floatMark++;                            if (floatMark > 1)                                if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid float format."))                                    return null;                            if (src.Eof)                                if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid float format."))                                    return null;                            src.NextChar(); // skip 'f/F'                            stop = true;                        }                        break;                    default:                        {                            if (!SourceCode.IsDigit(src.CurrentChar))                            {                                stop = true;                                if (src.CurrentChar == 'u' || src.CurrentChar == 'U')                                {                                    if (pointNum > 0 || expNum > 0 || floatMark > 0)                                    {                                        if (!NotifyError(ctx, src.Location, ParsingErrorType.FormatError, "Invalid float format"))                                            return null;                                    }                                    src.NextChar(); // skip 'U'                                    isUnsigned = true;                                }                            }                            else                                src.NextChar();                        }                        break;                } // switch                if (src.Eof || stop)                    break;            } // while            string valStr = src.Text.Substring(start, src.Column - start);            if (pointNum > 0 || expNum > 0 || floatMark > 0)            {                float val = float.Parse(valStr);                return new Expression.Operand.Value()                {                    DataType = PrimitiveDataType.FloatType,                    DataField = val                };            }            else            {                int val = int.Parse(valStr);                if (val < 65535)                {                    return new Expression.Operand.Value()                    {                        DataType = PrimitiveDataType.ShortType | (isUnsigned ? PrimitiveDataType.UnsignedType : PrimitiveDataType.SignedType),                        DataField = (short)val                    };                }                else                    return new Expression.Operand.Value()                    {                        DataType = PrimitiveDataType.IntType | (isUnsigned ? PrimitiveDataType.UnsignedType : PrimitiveDataType.SignedType),                        DataField = val                    };            }        }        private Expression.Operand.Value GetCharValue(Context ctx, SourceCode src)        {            src.NextChar(); // skip '\''            char val = src.CurrentChar;            if (src.CurrentChar == '\\') // escape            {                src.NextChar(); // skip escape                if (m_escapeCharDict.Count == 0)                {                    m_escapeCharDict.Add('a', '\a');    // Bell (alert)                    m_escapeCharDict.Add('b', '\b');    // Backspace                    m_escapeCharDict.Add('f', '\f');    // Formfeed                    m_escapeCharDict.Add('n', '\n');    // New line                    m_escapeCharDict.Add('r', '\r');    // Carriage return                    m_escapeCharDict.Add('t', '\t');    // Horizontal tab                    m_escapeCharDict.Add('v', '\v');    // Vertical tab                    m_escapeCharDict.Add('\'', '\'');    // Single quotation mark                    // m_escapeCharDict.Add('\"  Double quotation mark                    m_escapeCharDict.Add('\\', '\\');   // Backslash                    m_escapeCharDict.Add('?', (char)63);   // Literal question mark                }                if (SourceCode.IsDigit(src.CurrentChar)) // Digit                {                    bool octal = src.CurrentChar == '0';                    int start = src.Column;                    while (!src.Eof && SourceCode.IsDigit(src.CurrentChar))                        src.NextChar(false);                    if (!src.Eof)                    {                        if (src.CurrentChar == '\'')                        {                            string str = src.Text.Substring(start, src.Column - start);                            val  = (char)int.Parse(str, System.Globalization.NumberStyles.Integer);                        }                        else                            if (!NotifyError(ctx, src.Location, ParsingErrorType.SyntaxError, "Invalid char value."))                                return null;                    }                }                else                {                    // Hex                    if (src.CurrentChar == 'x' || src.CurrentChar == 'X')                    {                        src.NextChar(); // skip x                        int start = src.Column;                        while (!src.Eof && (SourceCode.IsDigit(src.CurrentChar) || (src.CurrentChar >= 'a' && src.CurrentChar <= 'f') || (src.CurrentChar >= 'A' && src.CurrentChar <= 'F')))                            src.NextChar(false);                        if (!src.Eof)                        {                            if (src.CurrentChar == '\'')                            {                                string str = src.Text.Substring(start, src.Column - start);                                val = (char)int.Parse(str, System.Globalization.NumberStyles.HexNumber);                            }                            else                                if (!NotifyError(ctx, src.Location, ParsingErrorType.SyntaxError, "Invalid hexadecimal number."))                                    return null;                        }                                            }                    else                    {                        if (!m_escapeCharDict.ContainsKey(src.CurrentChar))                            if (!NotifyError(ctx, src.Location, ParsingErrorType.SyntaxError, "Unrecognized character escape sequence."))                                return null;                        val = m_escapeCharDict[src.CurrentChar];                    }                }            }            src.NextChar(); // skip value field            if (src.CurrentChar != '\'')                if (!NotifyError(ctx, src.Location, ParsingErrorType.SyntaxError, "Missing close quote."))                    return null;            // skip '\''            src.NextChar();            return new Expression.Operand.Value()            {                DataType = PrimitiveDataType.CharType,                DataField = (byte)val            };        }        private Expression.Operand.Operand GetStringValue(Context ctx, SourceCode src)        {            src.NextChar(); // skip '"'            int startPos = src.Column;            int startPosOfLine = src.ColumnOfCurrentLine;            int startLineNo = src.Line;            StringBuilder strBuilder = new StringBuilder();            while (!src.Eof)            {                if (src.CurrentChar == '\\')                {                    src.NextChar();                    src.NextChar(); // skip Escape and char                }                else                    if (src.CurrentChar == '"')                    {                        strBuilder.Append(src.Text.Substring(startPos, src.Column - startPos));                        src.NextChar(); // skip '"'                        src.SkipSpace();                        if (!src.Eof && src.CurrentChar == '"')                        {                            src.NextChar();                            // String followed by string                            startPos = src.Column;                        }                        else                            break;                    }                    else                        src.NextChar();            }            // The const variable            Variable stxConstVar = new Variable()            {                TypeInfo = new DataTypeInfo()                {                    Type = PrimitiveDataType.CharType | PrimitiveDataType.PointerType,                    PointerCount = 1                },                ReferenceCount = 1            };            stxConstVar.Name = Context.GetAnonymousName(stxConstVar.TypeInfo);            int byteArrayLen = Encoding.ASCII.GetByteCount(strBuilder.ToString()) + 1;            ConstantInitialize stxConstInit = new ConstantInitialize()            {                Name = Context.GetAnonymousName("const_init"),                VariableName = stxConstVar.Name,                InitialValue = new byte[byteArrayLen]            };                        char[] charArray = strBuilder.ToString().ToCharArray();            Encoding.ASCII.GetBytes(charArray, 0, charArray.Length, stxConstInit.InitialValue, 0);            stxConstInit.InitialValue[byteArrayLen - 1] = 0;                        ctx.GlobalContex.AddChildAtFirst(stxConstInit);            ctx.GlobalContex.AddChildAtFirst(stxConstVar);            return new Expression.Operand.ValueOfVariableReference()            {                Name = stxConstInit.VariableName            };        }

到此,文法分析的基本架構已成。

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.