c语言skipspace,C语言解释器-17 语法分析(2)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值