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 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 caseValDict = new Dictionary();
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 '
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