For Loop parsing:
Private bool parsecontrol_for (context CTX, sourcecode SRC, context. locationinfo LOC) {SRC. skipspace (); If (SRC. currentchar! = '(') If (! Policyerror (CTX, getlocation (loc. firstline, loc. firstpos, SRC. absoluteline, SRC. absolutepos), parsingerrortype. syntaxerror, "'(' is expected. ") return false; // The Code sourcecode stmt = getparenthesiscode (SRC); List <sourcecode> stmtlist = stmt. splitstatement (); // required if (stmtlist. count! = 3) if (! Policyerror (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); // initialize context stxinit = new context (); stxfor. addchild (stxinit); If (! Parsestatement (stxinit, stmtlist [0]) return false; // condition determines if (! Parseexpression (stxinit, stmtlist [1], ref stxfor. condition) return false; // iterator 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 = new block (); stxfor. addchild (Block); bool res = parse (Block, stmt); stxfor. location. lastline = stmt. absoluteline; stxfor. location. lastpos = stmt. absolutepos; return res ;}
The complexity is 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; }
Expression Parsing is divided into two steps. The first step is to generate a Statement object and then parse it based on this object.
Step 1:
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; }
Step 2:
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