public static Dom AnalyzeDom(string Code) { int[] pos = BracketMatching(Code, true); Dom root = new Dom(); for (int index = 0, nextIndex; index < Code.Length; index = nextIndex + 1) { char tempChar = Code[index]; if (char.IsWhiteSpace(tempChar) == true) { // ignore space nextIndex = index; } else if (tempChar == '<') { nextIndex = AnalyzeDom(root, Code, index, pos, CodeType.Html, false); } else if (tempChar == '@') { nextIndex = AnalyzeDom(root, Code, index, pos, CodeType.Razor, false); } else { nextIndex = AnalyzeDom(root, Code, index, pos, CodeType.Text, false); // throw new Exception("Syntax Error"); } } return(root); }
public static int AnalyzeDom(Dom root, string Code, int sta, int[] pos, CodeType nowType, bool flag) { Dom now = new Dom { Type = nowType }; int end; if (nowType == CodeType.Html) { end = pos[sta]; // '<' at sta, '>' at end if (Code[sta] != '<' || Code[end] != '>') { throw new Exception(); } if (sta + 2 < end && " /".Equals(Code.substring(end - 2, end)) == true || // match <someTag /> sta + 5 < end && "!--".Equals(Code.substring(sta + 1, sta + 4)) == true && "--".Equals(Code.substring(end - 2, end)) == true) { // match <!--...--> (may ignored) now.Begin = Code.substring(sta, end + 1); } else { // may match <someTag> int tempIndex = Code.IndexOf(' ', sta + 2); // fetch someTag : <someTag> or <someTag ...> var someTag = (tempIndex != -1 && tempIndex < end) ? Code.substring(sta + 1, tempIndex) : Code.substring(sta + 1, end); if (IsTag(someTag) == false) { throw new Exception("Syntax Error."); } now.Begin = Code.substring(sta, end + 1); // <someTag...> // then try to find child and </someTag> for (int index = end + 1, nextIndex = -1; index < Code.Length; index = nextIndex + 1) { // find now.child char tempChar = Code[index]; if (tempChar == '<') { // match HTML child or </someTag> if (index + 1 < Code.Length && Code[index + 1] == '/') { // match </someTag> tempIndex = pos[index]; // fetch someTag and check it if (tempIndex < 0 || someTag.Equals(Code.substring(index + 2, tempIndex)) == false) { throw new Exception("Syntax Error."); } end = tempIndex; now.End = Code.substring(index, end + 1); // <someTag ...> ... </someTag> break; } else // match HTML child { nextIndex = AnalyzeDom(now, Code, index, pos, CodeType.Html, false); } } else if (tempChar == '@') { // match Razor child nextIndex = AnalyzeDom(now, Code, index, pos, CodeType.Razor, false); } else // match InnerText child { nextIndex = AnalyzeDom(now, Code, index, pos, CodeType.Text, false); } } } root.AppendChild(now); } else if (nowType == CodeType.Razor) { // may not start at @ if (!(flag == true || Code[sta] == '@' && sta + 1 < Code.Length)) { throw new Exception(); } var isIfElse = false; if (flag == false && Code[sta + 1] == '*') { // rule 7 : @*...*@ end = Code.IndexOf("*@", sta + 2); if (end == -1) { throw new Exception("Syntax Error."); } ++end; now.Begin = Code.substring(sta, end + 1); // @*...*@ (may ignored) } else if (flag == false && Code[sta + 1] == '@') { // rule 3 : @@ end = sta + 1; now.Begin = Code.substring(sta, end + 1); // @@ } else // other rules { if (flag == true) { --sta; // for assuming sta+1 is the first index after @ } int tempIndex = Code.Length - 1; for (int index = sta + 1; index < Code.Length; ++index) { // find the first non-blank char after @ if (char.IsWhiteSpace(Code[index]) == false) { // the first position after space tempIndex = index; break; } } char tempChar = Code[tempIndex]; if (char.IsLetter(tempChar) == true || tempChar == '$' || tempChar == '_') { // rule 1 & 5 (contain rule 6) end = Code.Length - 1; // find the first variable name for (int index = sta + 1; index < Code.Length; ++index) { tempChar = Code[index]; if (char.IsLetter(tempChar) == false && char.IsDigit(tempChar) == false && tempChar != '_' && tempChar != '$') { end = index - 1; break; } } String variable = Code.substring(sta + 1, end + 1); if ("if".Equals(variable) == true || "else".Equals(variable) == true || "for".Equals(variable) == true || "foreach".Equals(variable) || "while".Equals(variable) == true || "do".Equals(variable) == true) { // rule 5 : for() {...} or if(expression) {...} else {...} int leftIndex = Code.IndexOf('{', end + 1); while (leftIndex != -1 && pos[leftIndex] == -2) { leftIndex = Code.IndexOf('{', leftIndex + 1); } if (leftIndex == -1) { throw new Exception("Syntax Error."); } int rightIndex = pos[leftIndex]; now.Begin = Code.substring(tempIndex, leftIndex + 1); for (int index = leftIndex + 1, nextIndex; index < rightIndex; index = nextIndex + 1) { tempChar = Code[index]; if (char.IsWhiteSpace(tempChar) == true) { // ignore space nextIndex = index; } else if (tempChar == '<') { // HTML nextIndex = AnalyzeDom(now, Code, index, pos, CodeType.Html, false); } else // no innerText, all is razor { nextIndex = AnalyzeDom(now, Code, index, pos, CodeType.Razor, true); } } if ("if".Equals(variable) == true) { // check "else" and "else if" isIfElse = true; end = rightIndex; now.End = Code.substring(rightIndex, end + 1); root.AppendChild(now); // prestore if-else-if in nowList.children for (int index = rightIndex + 1; index < Code.Length; index = rightIndex + 1) { // find a whole word "else" tempIndex = Code.IndexOf("else", index); while (tempIndex != -1) { if (tempIndex + 4 < Code.Length) { tempChar = Code[tempIndex + 4]; if (char.IsLetter(tempChar) == false && char.IsDigit(tempChar) == false && tempChar != '_' && tempChar != '$') { break; } } tempIndex = Code.IndexOf("else", tempIndex + 4); } if (tempIndex != -1) { // add "else" or "else if" to nowList rightIndex = AnalyzeDom(root, Code, tempIndex, pos, CodeType.Razor, true); // check "else if" format leftIndex = Code.IndexOf('{', tempIndex + 4); while (leftIndex != -1 && pos[leftIndex] == -2) { leftIndex = Code.IndexOf('{', leftIndex + 1); } /* if(leftIndex == -1) { * throw new Exception("cheng xu chu bug la!"); * } */ int tempIndex2 = Code.Length - 1; for (int index2 = tempIndex + 4; index2 < Code.Length; ++index2) { if (char.IsWhiteSpace(Code[index2]) == false) { tempIndex2 = index2; break; } } if (tempIndex2 + 1 >= leftIndex || "if".Equals(Code.substring(tempIndex2, tempIndex + 2)) == false) { // not "else if", end the condition end = rightIndex; break; } } else { break; } } } else if ("do".Equals(variable) == true) { // check "while (...)" tempIndex = Code.IndexOf('(', rightIndex + 1); while (tempIndex != -1 && pos[tempIndex] == -2) { tempIndex = Code.IndexOf('(', tempIndex + 1); } if (tempIndex == -1) { throw new Exception("Syntax Error."); } end = pos[tempIndex]; now.End = Code.substring(rightIndex, end + 1); } else { end = rightIndex; now.End = Code.substring(rightIndex, end + 1); } } else { // rule 1 : @variable[index].method(parameters) if (end + 1 < Code.Length && Code[end + 1] == '[') { // variable[index] end = pos[end + 1]; } if (end + 1 < Code.Length && Code[end + 1] == '.') { // object.property or object.method ++end; tempIndex = Code.Length - 1; for (int index = end + 1; index < Code.Length; ++index) { tempChar = Code[index]; if (char.IsLetter(tempChar) == false && char.IsDigit(tempChar) == false && tempChar != '_' && tempChar != '$') { tempIndex = index - 1; break; } } end = tempIndex; tempIndex = Code.Length - 1; for (int index = end + 1; index < Code.Length; ++index) { if (char.IsWhiteSpace(Code[index]) == false) { tempIndex = index; break; } } if (Code[tempIndex] == '(') { // object.method() int leftIndex = tempIndex, rightIndex = pos[leftIndex]; end = rightIndex; tempIndex = Code.IndexOf('{', leftIndex + 1); while (tempIndex != -1 && tempIndex < rightIndex && pos[tempIndex] == -2) { tempIndex = Code.IndexOf('{', tempIndex + 1); } if (tempIndex != -1 && tempIndex < rightIndex) { // object.method( {...} ) like loop leftIndex = tempIndex; rightIndex = pos[tempIndex]; now.Begin = Code.substring(sta + 1, leftIndex + 1); for (int index = leftIndex + 1, nextIndex = -1; index < rightIndex; index = nextIndex + 1) { tempChar = Code[index]; if (char.IsWhiteSpace(tempChar) == true) { // ignore space nextIndex = index; } else if (tempChar == '<') { // HTML nextIndex = AnalyzeDom(now, Code, index, pos, CodeType.Html, false); } else // no innerText, all is razor { nextIndex = AnalyzeDom(now, Code, index, pos, CodeType.Razor, true); } } now.End = Code.substring(rightIndex, end + 1); } else // object.method(...) { now.Begin = Code.substring(sta + 1, end + 1); } } else // object.property { now.Begin = Code.substring(sta + 1, end + 1); } } else { now.Begin = Code.substring(sta + 1, end + 1); } } } else if (tempChar == '(') { // rule 2 : @(expression) (mind the "({})") // ( {...} ) not need to split end = pos[tempIndex]; now.Begin = Code.substring(tempIndex, end + 1); // (expression) } else if (tempChar == '{') { // rule 4 : @{JS Code} // {...} not need to split end = pos[tempIndex]; now.Begin = Code.substring(tempIndex, end + 1); } else { throw new Exception("Syntax Error."); } } if (isIfElse == false) { root.AppendChild(now); } } else // nowType == CodeType.Text { if (!(Code[sta] != '<' && Code[sta] != '@')) { throw new Exception(); } int tempIndex1 = Code.IndexOf('<', sta + 1), tempIndex2 = Code.IndexOf('@', sta + 1); while (tempIndex1 != -1 && pos[tempIndex1] < 0) { // skip comparison '<' and inner '<' tempIndex1 = Code.IndexOf('<', tempIndex1 + 1); } // find minimum in {IndexOfMatched('<'), IndexOf('@'), Length} end = Code.Length - 1; if (tempIndex1 != -1) { end = Math.Min(end, tempIndex1 - 1); } if (tempIndex2 != -1) { end = Math.Min(end, tempIndex2 - 1); } now.Begin = Code.substring(sta, end + 1); root.AppendChild(now); } return(end); }
public void AppendChild(Dom dom) { Children.Add(dom); }