SharpC-A-C-Interpreter-In-C-1001

8次阅读

共计 17807 个字符,预计需要花费 45 分钟才能阅读完成。

在了解词法分析之前,先看看对单词的定义:

/// <summary>
/// A structure for the result of word parsing.
/// </summary>
public class Word
{
    public int AbsoluteLine;
    public int AbsoluteStartPos;
    public int AbsoluteEndPos;
    public int Offset;
    public int Column;
    public string Text;

    public bool IsAvailable;
    public Context.LocationInfo Location; 
}

注意为了方便计,实现中并未将所有词语都标记为单词,比如操作符。仅有关键字、变量名和函数名被标记为单词。
为了更好的分析源代码,创建了一个 SourceCode 类,以进行词法分析工作:

public class SourceCode
{
    // 各种标记
    public static char[] MultiLineCommentsStartMark = new char[] {'/', '*'};
    public static char[] HexMark = new char[] {'x', 'X'};
    public static char[] ExponentialMark = new char[] {'e', 'E'};
    public static char[] FloatMark = new char[] {'f', 'F'};
    public static char[] PlusMinusMark = new char[] {'-', '+'};

    public string Text = "";
    public int Line = 0;
    public int ColumnOfCurrentLine = 0;
    public int PosOffset = 0;
    public int LineOffset = 0;
    public int Column;
    public Word LastWord;

    public SourceCode() {}

    public SourceCode(string txt);

    public void LoadFromFile(string path);

    public bool Eof;
    // 当前位置在整个代码中的绝对位置
    public int AbsolutePos;
    // 当前行在整个代码中的绝对行
    public int AbsoluteLine;

    public Context.LocationInfo Location;

    public char CurrentChar;

    // 重置位置索引(局部位置索引)public void ResetPos();
    // 检测下一个字符是否与指定的字符匹配
    public bool TestNextChar(char c);
    // 检测下一个字符是否在指定的字符集中
    public bool TestNextChar(char[] chars);
    // 获取下一个字符,默认会跳过前面的空格
    public void NextChar(bool skipSpace = true);
    // 获取从当前位置开始的剩余代码
    public string Tail;

    public static bool IsDigit(char ch);

    public static bool IsLetter(char ch);

    public static bool IsSpace(char ch);

    public static bool IsOperator(char ch);

    public static bool IsBracket(char ch);
    public void SkipSpace();

    // 以 ';' 为分隔符,划分代码片断
    public List<SourceCode> SplitStatement();
    // 以 ',' 为分隔符,划分多个变量定义片断
    public List<SourceCode> SplitMultiDeclaration();
    // 划分参数
    public List<SourceCode> SplitParameter();
    // 获取一个单词
    public static Word GetWord(SourceCode src);
    // 获取括号内的代码
    public static SourceCode GetBracketCode(char leftBracket, char rightBracket, SourceCode src);
}

更复杂的分析,与语法分析一道,整合到 Parser 类中。
Parser 类用于对 C 代码进行语法分析并构造语法树。

/// <summary>
/// Parser class parses the simple C source code to build
/// the syntax serial.
/// </summary>
public class Parser
{
  public enum ParsingErrorType
  {
      Warning,
      UnknownError,
      UndefinedVariable,
      UnexpectedKeyword,
      TokenExpected,
      SyntaxError,
      TypeError,
      FormatError,
      FunctionBodyUndefined
  };

  public class ParsingEventArg
  {public Context Context;}

  public class ParsingWarningEventArg
  {
      public Context Context;
      public Context.LocationInfo Location;
      public string Description;
  }

  public class ParsingErrorEventArg
  {
      public Context Context;
      public Context.LocationInfo Location;
      public ParsingErrorType Error;
      public string Description;
      public bool Continue;
  }

  public event EventHandler<ParsingEventArg>          OnParsing;
  public event EventHandler<ParsingWarningEventArg>   OnParsingWarning;
  public event EventHandler<ParsingErrorEventArg>    OnParsingError;

  ///////////////////////////////
  // Private member variables
  ///////////////////////////////
  private SourceCode m_sourceCode = null;
  private Word m_lastWord = null;
  private Expression.ExpressionNode m_lastExpNode = null;
  private Dictionary<char, char> m_escapeCharDict = new Dictionary<char, char>();
  private int m_errorCount = 0;
  private int m_warningCount = 0;

  public String Source
  {get { return m_sourceCode.Text;}
  }

  public bool HasError
  {get { return m_errorCount > 0;}
  }

  public bool HasWarning
  {get { return m_warningCount > 0;}
  }

  public int ErrorCount
  {get { return m_errorCount;}
  }

  public int WarningCount
  {get { return m_warningCount;}
  }

  public int MaxError = 0;

  public int MaxWarning = 65535;

  public Context Parse(SourceCode src)
  {
      m_sourceCode = src;

      Context ctx = new Context();

      if (Parse(ctx, src))
      {
          // 语法分析完成后,校验是否有未使用的变量或函数,以及对申明而未定义函数的使用
          if (ValidateContextReference(ctx))
              return ctx;
      }

      return null;
  }
  ...

语法分析的主要方法定义如下:

private bool Parse(Context ctx, SourceCode src)
{
    bool res = true;

    ctx.Location.FirstLine = src.AbsoluteLine;
    ctx.Location.FirstPos = src.AbsolutePos;

    foreach (SourceCode stmt in src.SplitStatement()) // 逐语句进行处理
    {
        try
        {
            // 检测 do...while 的 while 部分
            if (ctx.Children.Count > 0 && ctx.Children.Last() is ControlFlow.DoWhileLoop)
            {if ((ctx.Children.Last() as ControlFlow.DoWhileLoop).Condition == null)
                {Word wordOfWhile = GetWord(stmt);

                    if (wordOfWhile.Text != "while")
                    {if (!NotifyError(ctx, wordOfWhile.Location, ParsingErrorType.SyntaxError, "\"while\"is expected."))
                            return false;
                    }
                    else
                    {res = ParseControl_While(ctx, stmt, new Context.LocationInfo()
                        {
                            FirstLine = wordOfWhile.AbsoluteLine,
                            FirstPos = wordOfWhile.AbsoluteStartPos
                        });

                        if (!res)
                            return false;
                        else
                            continue;
                    }
                }
            }

            if (stmt.Text.EndsWith(";")) // 语句
            {res = ParseStatement(ctx, stmt);
            }
            else
            {if (stmt.Text.EndsWith("}")) // 函数体或块
                {if (stmt.Text.StartsWith("{")) // 块
                    {SourceCode blockSrc = new SourceCode()
                        {
                            LineOffset = stmt.AbsoluteLine,
                            PosOffset = stmt.AbsolutePos,
                            Text = stmt.Text.Substring(1, stmt.Text.Length - 2)
                        };

                        Block block = new Block()
                        {Name = Context.GetAnonymousName("block"),
                            Location = new Context.LocationInfo()
                            {
                                FirstLine = stmt.AbsoluteLine,
                                FirstPos = stmt.AbsolutePos
                            }
                        };

                        ctx.AddChild(block);

                        res = Parse(block, blockSrc);

                        block.Location.LastLine = stmt.AbsoluteLine;
                        block.Location.LastPos = stmt.AbsolutePos;
                    }
                    else
                    {   // 函数
                        // 过滤控制结构
                        Word wordOfControlFlow = GetWord(stmt);

                        if (Context.IsControlFlow(wordOfControlFlow.Text))
                        {res = ParseControlFlow(ctx, stmt, wordOfControlFlow);
                        }
                        else
                        {stmt.ResetPos();

                            res = ParseFunction(ctx, stmt, wordOfControlFlow.Location);
                        }
                    }
                }
            }
        }
        catch (ParseException pe)
        {if (!NotifyError(ctx, ctx.Location, ParsingErrorType.SyntaxError, pe.Message))
                return false;
        }

        if (!res)
            return false;
    } // for

    ctx.Location.LastLine = src.AbsoluteLine;
    ctx.Location.LastPos = src.AbsolutePos;

    return true;
}

语句处理,分三种情况:申明、控制结构及表达式。

private bool ParseStatement(Context ctx, SourceCode src)
{Word firstWord = GetWord(src);

    if (Context.IsDataType(firstWord.Text)) // 以类型打头
    {
        // 变量或函数申明
        return ParseDeclare(ctx, src, firstWord);
    }
    else
        if (Context.IsControlFlow(firstWord.Text)) // 控制结构
        {
            //Control 
            return ParseControlFlow(ctx, src, firstWord);
        }
        else
        {
            // 表达式
            src.ResetPos();
            return ParseExpression(ctx, src, firstWord.Location);
        }
}

函数解析的实现如下:

private bool ParseFunction(Context ctx, SourceCode src, Context.LocationInfo loc)
{
    // 定位函数体
    while (!src.Eof && src.CurrentChar != '{')
        src.NextChar();

    // 头部位置信息
    Context.LocationInfo headerLoc = loc;

    headerLoc.LastPos = src.AbsolutePos - 1;

    // 函数头部
    SourceCode funcHeader = new SourceCode()
    {
        PosOffset = loc.FirstPos,
        LineOffset = loc.FirstLine,
        Text = src.Text.Substring(0, src.Column)
    };

    // 解析头部
    // 如成功, 一个 FunctionDefine 将被添加到当前 Context 的尾
    if (!ParseStatement(ctx, funcHeader)) 
        return false;

    src.NextChar(); // skip '{'

    // 函数体
    SourceCode bodyStmt = new SourceCode()
    {
        PosOffset = src.AbsolutePos,
        LineOffset = src.AbsoluteLine,
        Text = src.Text.Substring(src.Column, src.Text.Length - src.Column - 1)
    };

    // 函数对象
    Function.FunctionDefine funcDef = ctx.Children.Last() as Function.FunctionDefine;

    funcDef.AddChild(new Block()
    {Name = Context.GetAnonymousName("block")
    });

    // 递归解析函数体
    if (Parse(funcDef.Body, bodyStmt))
    {
        funcDef.Location = headerLoc;

        return true;
    }

    return false;
}


控制结构的解析如下:private bool ParseControlFlow(Context ctx, SourceCode src, Word wordOfControlFlow)
{
    bool res = false;

    switch (wordOfControlFlow.Text)
    {case "if": res = ParseControl_If(ctx, src, wordOfControlFlow.Location); break;
        case "else": res = ParseControl_Else(ctx, src, wordOfControlFlow.Location); break;
        case "for": res = ParseControl_For(ctx, src, wordOfControlFlow.Location); break;
        case "do": res = ParseControl_DoWhile(ctx, src, wordOfControlFlow.Location); break;
        case "while": res = ParseControl_While(ctx, src, wordOfControlFlow.Location); break;
        case "switch": res = ParseControl_Switch(ctx, src, wordOfControlFlow.Location); break;
        case "continue": res = ParseControl_Continue(ctx, src, wordOfControlFlow.Location); break;
        case "break": res = ParseControl_Break(ctx, src, wordOfControlFlow.Location); break;
        case "return": res = ParseControl_Return(ctx, src, wordOfControlFlow.Location); break;
        default:
            {
                // Unsupported control flow.
                if (!NotifyError(ctx, wordOfControlFlow.Location, ParsingErrorType.SyntaxError, "Unsupported keyword."))
                    return false;
            }
            break;
    } // switch

    if (res)
        NotifyParsing(ctx.Children.Last());

    return res;
}

以 if/else 为例,说明控制结构的解析过程。
先看 if 部分:

private bool ParseControl_If(Context ctx, SourceCode src, Context.LocationInfo loc)
{src.SkipSpace(); // get '('

    if (src.CurrentChar != '(')
        if (!NotifyError(ctx, GetLocation(loc.FirstLine, loc.FirstPos, src.AbsoluteLine, src.AbsolutePos), ParsingErrorType.SyntaxError, "'(' is expected."))
            return false;

    // 获取判断表达式
    SourceCode condition = GetParenthesisCode(src);

    ControlFlow.IfThen stxIf = new ControlFlow.IfThen()
    {Location = new Context.LocationInfo()
        {
            FirstLine = loc.FirstLine,
            FirstPos = loc.FirstPos
        }
    };

    ctx.AddChild(stxIf);

    // 解析判断表达式
    if (!ParseExpression(stxIf, condition, ref stxIf.Condition))
        return false;

    // 尝试解析 then 部分代码
    src.SkipSpace();

    bool res = false;
    Block ThenBlock = new Block();

    stxIf.AddChild(ThenBlock);

    if (src.CurrentChar == '{') // 块?{SourceCode code = GetBlockCode(src);

        res = Parse(ThenBlock, code);

        stxIf.Location.LastLine = src.AbsoluteLine;
        stxIf.Location.LastPos = src.AbsolutePos;
    }
    else
    {   // 单个语句?SourceCode stmt = new SourceCode()
        {
            PosOffset = src.AbsolutePos,
            LineOffset = src.AbsoluteLine,
            Text = src.Text.Substring(src.Column)
        };

        res = Parse(ThenBlock, stmt);

        stxIf.Location.LastLine = stmt.AbsoluteLine;
        stxIf.Location.LastPos = stmt.AbsolutePos;
    }

    // else 另案处理
    return res;
}

再看 else 部分:

private bool ParseControl_Else(Context ctx, SourceCode src, Context.LocationInfo loc)
{
    // else 不能单独出现,前面必须有个 if。这种处理方式也解决了 else 与 if 的就近匹配问题。if (!(ctx.Children.Last() is ControlFlow.IfThen))
        if (!NotifyError(ctx, loc, ParsingErrorType.SyntaxError, "\"else\"should not appear here."))
            return false;

    // 上一个语法可能是多重 if/then
    Context lastStx = ctx.Children.Last();

    while (lastStx.Children.Count > 2) // Children 数大于 2,表示具有 else 部分,则尝试取得最后一个 if/then
    {lastStx = lastStx.Children.Last();
    }

    // 再次检测 if/then
    if (!(lastStx is ControlFlow.IfThen))
        if (!NotifyError(ctx, loc, ParsingErrorType.SyntaxError, "Can't find matched \"if\"."))
            return false;

    ControlFlow.IfThen stxIf = lastStx as ControlFlow.IfThen;

    src.SkipSpace();

    bool res = false;
    Block elseBlock = new Block();

    stxIf.AddChild(elseBlock);

    // Block
    if (src.CurrentChar == '{')
    {SourceCode code = GetBlockCode(src);

        res = Parse(elseBlock, code);

        lastStx.Location.LastLine = src.AbsoluteLine;
        lastStx.Location.LastPos = src.AbsolutePos;
    }
    else
    {   // Statement
        SourceCode stmt = new SourceCode()
        {
            PosOffset = src.AbsolutePos,
            LineOffset = src.AbsoluteLine,
            Text = src.Text.Substring(src.Column)
        };

        res = Parse(elseBlock, stmt);

        lastStx.Location.LastLine = stmt.AbsoluteLine;
        lastStx.Location.LastPos = stmt.AbsolutePos;
    }

    return res;
}

for 循环的解析:

private bool ParseControl_For(Context ctx, SourceCode src, Context.LocationInfo loc)
{src.SkipSpace();

    if (src.CurrentChar != '(')
        if (!NotifyError(ctx, GetLocation(loc.FirstLine, loc.FirstPos, src.AbsoluteLine, src.AbsolutePos), ParsingErrorType.SyntaxError, "'(' is expected."))
            return false;

    // 括号内的代码
    SourceCode stmt = GetParenthesisCode(src);
    List<SourceCode> stmtList = stmt.SplitStatement();

    // 三部分,必须的
    if (stmtList.Count != 3)
        if (!NotifyError(ctx, GetLocation(loc.FirstLine, loc.FirstPos, src.AbsoluteLine, src.AbsolutePos), ParsingErrorType.SyntaxError, "Syntax error."))
            return false;

    ControlFlow.ForLoop stxFor = new ControlFlow.ForLoop()
    {Location = new Context.LocationInfo()
        {
            FirstLine = loc.FirstLine,
            FirstPos = loc.FirstPos
        }
    };

    ctx.AddChild(stxFor);

    // 初始化
    Context stxInit = new Context();
    stxFor.AddChild(stxInit);

    if (!ParseStatement(stxInit, stmtList[0]))
        return false;

    // 条件判断
    if (!ParseExpression(stxInit, stmtList[1], ref stxFor.Condition))
        return false;

    // 迭代器
    if (!ParseExpression(stxInit, stmtList[2], ref stxFor.Iterator))
        return false;

    src.SkipSpace();

    // 循环体
    if (src.CurrentChar == '{')
    {stmt = GetBlockCode(src);
    }
    else
    {stmt = new SourceCode()
        {
            PosOffset = src.AbsolutePos,
            LineOffset = src.AbsoluteLine,
            Text = src.Text.Substring(src.Column)
        };
    }

    Block block = new Block();

    stxFor.AddChild(block);

    bool res = Parse(block, stmt);

    stxFor.Location.LastLine = stmt.AbsoluteLine;
    stxFor.Location.LastPos = stmt.AbsolutePos;

    return res;
}

复杂的是 switch:

private bool ParseControl_Switch(Context ctx, SourceCode src, Context.LocationInfo loc)
{
    // Check condition
    src.SkipSpace();

    if (src.CurrentChar != '(')
        if (!NotifyError(ctx, GetLocation(loc.FirstLine, loc.FirstPos, src.AbsoluteLine, src.AbsolutePos), ParsingErrorType.SyntaxError, "Expecte a'('."))
            return false;

    ControlFlow.Switch stxSwitch = new ControlFlow.Switch()
    {Location = new Context.LocationInfo()
        {
            FirstLine = loc.FirstLine,
            FirstPos = loc.FirstPos
        }
    };

    ctx.AddChild(stxSwitch);

    // Parse condition expression
    if (!ParseExpression(stxSwitch, GetParenthesisCode(src), ref stxSwitch.Condition))
    {ctx.Children.RemoveAt(ctx.Children.Count - 1);
        return false;
    }

    // Add body
    stxSwitch.AddChild(new Block());

    ControlFlow.Case stxDefault = new ControlFlow.Case(); // default part

    stxSwitch.Body.AddChild(stxDefault);

    // Check '{'
    src.SkipSpace();

    if (src.CurrentChar != '{')
        if (!NotifyError(ctx, GetLocation(loc.FirstLine, loc.FirstPos, src.AbsoluteLine, src.AbsolutePos), ParsingErrorType.SyntaxError, "Expecte a'{'."))
            return false;

    // Parse body
    SourceCode switchBodyStmt = GetBlockCode(src);
    Dictionary<object, bool> caseValDict = new Dictionary<object, bool>();

    while (!switchBodyStmt.Eof)
    {switchBodyStmt.SkipSpace();

        Word word = GetWord(switchBodyStmt);

        switch(word.Text)
        {
            case "case":
                {ControlFlow.Case stxCase = new ControlFlow.Case()
                    {Location = new Context.LocationInfo()
                        {
                            FirstLine = word.AbsoluteLine,
                            FirstPos = word.AbsoluteStartPos
                        }
                    };

                    switchBodyStmt.SkipSpace();

                    if (switchBodyStmt.CurrentChar == '\'') // char
                    {Expression.Operand.Value charVal = GetCharValue(stxSwitch, switchBodyStmt);

                        if (charVal == null)
                            if (!NotifyError(ctx, GetLocation(word.AbsoluteLine, word.AbsoluteStartPos, switchBodyStmt.AbsoluteLine, switchBodyStmt.AbsolutePos), ParsingErrorType.SyntaxError, "Expecte a expression."))
                                return false;

                        stxCase.Value = charVal;
                    }
                    else
                    {if (SourceCode.IsDigit(switchBodyStmt.CurrentChar)) // number
                        {stxCase.Value = GetNumberValue(ctx, switchBodyStmt);

                            if ((stxCase.Value.GetTypeInfo(ctx).Type & PrimitiveDataType.BaseTypeMask) == PrimitiveDataType.FloatType)
                                if (!NotifyError(ctx, GetLocation(word.AbsoluteLine, word.AbsoluteStartPos, switchBodyStmt.AbsoluteLine, switchBodyStmt.AbsolutePos), ParsingErrorType.SyntaxError, "Expression must be an integral constant value."))
                                    return false;
                        }
                        else
                            if (!NotifyError(ctx, GetLocation(word.AbsoluteLine, word.AbsoluteStartPos, switchBodyStmt.AbsoluteLine, switchBodyStmt.AbsolutePos), ParsingErrorType.SyntaxError, "Expression must have a constant value."))
                                return false;
                    }

                    if (caseValDict.ContainsKey(stxCase.Value.AsInt))
                    {if (!NotifyError(ctx, GetLocation(word.AbsoluteLine, word.AbsoluteStartPos, switchBodyStmt.AbsoluteLine, switchBodyStmt.AbsolutePos), ParsingErrorType.SyntaxError, "Case label value has appeared in this switch."))
                            return false;
                    }
                    else
                        caseValDict.Add(stxCase.Value.AsInt, true);

                    stxSwitch.Body.AddChild(stxCase);

                    // Parse case body
                    switchBodyStmt.SkipSpace();

                    if (switchBodyStmt.CurrentChar != ':')
                        if (!NotifyError(ctx, GetLocation(word.AbsoluteLine, word.AbsoluteStartPos, switchBodyStmt.AbsoluteLine, switchBodyStmt.AbsolutePos), ParsingErrorType.SyntaxError, "identifier is undefined."))
                            return false;

                    switchBodyStmt.NextChar(); // skip ':'

                    stxCase.Location.LastLine = switchBodyStmt.AbsoluteLine;
                    stxCase.Location.LastPos = switchBodyStmt.AbsolutePos;

                    NotifyParsing(stxCase);

                    stxCase.AddChild(new Block());

                    if (!Parse(stxCase.Body, GetCaseBodyCode(ctx, switchBodyStmt)))
                        return false;
                }
                break;
            case "default":
                {if (stxDefault.Children.Count > 0)
                        if (!NotifyError(ctx, GetLocation(word.AbsoluteLine, word.AbsoluteStartPos, switchBodyStmt.AbsoluteLine, switchBodyStmt.AbsolutePos), ParsingErrorType.SyntaxError, "default label has already appeared in this switch."))
                            return false;

                    // Check ':'
                    switchBodyStmt.SkipSpace();
                    if (switchBodyStmt.CurrentChar != ':')
                        if (!NotifyError(ctx, GetLocation(word.AbsoluteLine, word.AbsoluteStartPos, switchBodyStmt.AbsoluteLine, switchBodyStmt.AbsolutePos), ParsingErrorType.SyntaxError, "':' is expected."))
                            return false;

                    switchBodyStmt.NextChar(); // skip ':'

                    stxDefault.AddChild(new Block()
                    {Location = new Context.LocationInfo()
                        {
                            FirstLine = word.AbsoluteLine,
                            FirstPos = word.AbsoluteStartPos,
                            LastLine = src.AbsoluteLine,
                            LastPos = src.AbsolutePos
                        }
                    });

                    if (!Parse(stxDefault.Body, GetCaseBodyCode(ctx, switchBodyStmt)))
                        return false;
                }
                break;
            default:
                if (!NotifyError(ctx, GetLocation(word.AbsoluteLine, word.AbsoluteStartPos, switchBodyStmt.AbsoluteLine, switchBodyStmt.AbsolutePos), ParsingErrorType.SyntaxError, "\"case\"is expected but get \"" + word.Text + "\"."))
                    return false;
                break;
        }
    } // while

    stxSwitch.Body.RemoveChild(stxDefault);
    stxSwitch.Body.AddChild(stxDefault);

    stxSwitch.Location.LastLine = src.AbsoluteLine;
    stxSwitch.Location.LastPos = src.AbsolutePos;
    return true;
}

表达式解析分为两步,第一步先生成 Statement 对象,再以此对象为基础进行解析。
第一步:

private bool ParseExpression(Context ctx, SourceCode src, Context.LocationInfo loc)
{Statement stmtStx = new Statement()
    {Name = Context.GetAnonymousName("statement"),
        Location = loc
    };

    if (!ParseExpression(ctx, src, ref stmtStx.TargetExpression))
        return false;

    ctx.AddChild(stmtStx);

    stmtStx.Location.LastLine = src.AbsoluteLine;
    stmtStx.Location.LastPos = src.AbsolutePos;

    NotifyParsing(stmtStx);

    return true;
}

第二步:

private bool ParseExpression(Context ctx, SourceCode src, ref Expression.ExpressionNode expTree)
{
    bool res = true;

    while (!src.Eof && res)
    {src.SkipSpace();

        switch (src.CurrentChar)
        {
            case ',':
                {src.NextChar(); // skip ','

                    Statement stxExp = new Statement();

                    if (ctx.Parent != null)
                        ctx.Parent.AddChild(stxExp);
                    else
                        ctx.AddChild(stxExp);

                    res = ParseExpression(ctx, src, ref stxExp.TargetExpression);
                }
                break;
            case ';': src.NextChar(); break; // End of statement
            case '=': res = ParseExpression_Equal(ctx, src, ref expTree); break;
            case '+': res = ParseExpression_Plus(ctx, src, ref expTree); break;
            case '-': res = ParseExpression_Minus(ctx, src, ref expTree); break;
            case '*': res = ParseExpression_Mul(ctx, src, ref expTree); break;
            case '/': res = ParseExpression_Div(ctx, src, ref expTree); break;
            case '%': res = ParseExpression_Mod(ctx, src, ref expTree); break;
            case '&': res = ParseExpression_And(ctx, src, ref expTree); break;
            case '|': res = ParseExpression_Or(ctx, src, ref expTree); break;
            case '^': res = ParseExpression_Xor(ctx, src, ref expTree); break;
            case '!': res = ParseExpression_Not(ctx, src, ref expTree); break;
            case '~': res = ParseExpression_BitwiseNot(ctx, src, ref expTree); break;
            case '<': res = ParseExpression_Less(ctx, src, ref expTree); break;
            case '>': res = ParseExpression_Greater(ctx, src, ref expTree); break;
            case '(': res = ParseExpression_Parentheses(ctx, src, ref expTree); break;
            case '\'': res = ParseExpression_CharValue(ctx, src, ref expTree); break;
            case '"':
                {
                    // const string
                    res = ParseExpression_ConstStringValue(ctx, src, ref expTree);
                    //if (!FireParsingFailedEvent(ctx, src, ParsingErrorType.SyntaxError, "String is not supported."))
                    //    return false;
                }
                break;
            default:
                {
                    Expression.ExpressionNode lastNode = m_lastExpNode;

                    if (SourceCode.IsDigit(src.CurrentChar))
                    {res = ParseExpression_NumberValue(ctx, src, ref expTree);
                    }
                    else
                        if (SourceCode.IsLetter(src.CurrentChar))
                        {res = ParseExpression_Var(ctx, src, ref expTree);
                        }
                        else
                            if (!NotifyError(ctx, src.Location, ParsingErrorType.SyntaxError, "Syntax error.")) 
                                return false;

                    if (!ValidateOperator(ctx, src, lastNode))
                        return false;
                }
                break;
        } // switch
    } // while !Eof

    return res;
} // func ParseExpression

正文完
 0