public GSTParser(String text) { _root = ParsingHelper.ParseToTree(text); GstNode member = new GstNode(); _main = parseToGst(_root, member); }
/// <summary> /// 현재 노드와 상위노드에서 검색하여 해당 이름을 가진 노드를 리턴한다. 없으면 null /// 변수를 미리 define했을 때에 그 변수가 해당 범위안에 있는지를 알아내는 함수이다. /// </summary> /// <param name="name">찾을 Name</param> /// <returns>해당 Name을 가진 노드</returns> public ContextTree getActiveMember(String name) { for (int i = 0; i < Children.Count; i++) { if (Children[i].Name.Equals(name)) { return(Children[i]); } } ContextTree m = Parent.getActiveMember(name); if (m != null) { return(m); } else { return(null); } }
/// <summary> /// 구문을 Tree구조로 parsing함. /// </summary> /// <param name="orgStr">parsing할 구문</param> /// <param name="lineFinalizer">구문완료문자. 기본값은 ";".ToCharArray()</param> /// <param name="finalBracket">문맥괄호. 기본값은 "{}".ToCharArray()</param> /// <returns>Tree구조로 분리된 구문</returns> public static ContextTree ParseToTree(String orgStr, Char[] lineFinalizer = null, Char[] finalBracket = null, String lineComment = "//", Char lineEndHeader = '#') { int OPEN = 0; int CLOSE = 1; int seeker = 0; orgStr = orgStr.Replace("\r", ""); orgStr = orgStr.Replace("\t", " "); if (finalBracket == null) { finalBracket = "{}".ToCharArray(); } if (lineFinalizer == null) { lineFinalizer = ";".ToCharArray(); } ContextTree root = new ContextTree(0, 0, ""); ContextTree openNode = root; ContextTree newNode = new ContextTree(0, 0, "", root); ContextTree commentBaseNode = newNode; String cup = ""; bool isBracketClosed = false; bool isStringOpen = false; int lineIndex = 0; while (seeker < orgStr.Length) { if (orgStr[seeker] == '\n') { lineIndex++; } if (isStringOpen == true) //따옴표의 안에서는 문법이 무의미함. 그냥 진행. { if (orgStr[seeker] == '"' && orgStr[seeker - 1] != '\\') { isStringOpen = false; } cup += orgStr[seeker]; seeker++; continue; } if (isStringOpen == false && orgStr[seeker] == '"') { isStringOpen = true; seeker++; continue; } if (cup.Trim().Length == 0 && orgStr[seeker] == lineEndHeader) //이 문자가 라인의 가장 앞에 오면 끝문자와 상관없이 라인을 마무리한다. { int endOfLine = orgStr.IndexOf('\n', seeker); newNode.Header = orgStr.Substring(seeker, endOfLine - seeker).Trim(); openNode.Children.Add(newNode); newNode = new ContextTree(seeker, lineIndex, "", openNode); seeker = endOfLine + 1; lineIndex++; continue; } if (orgStr.Length > seeker + 1 && orgStr[seeker] == '/' && orgStr[seeker + 1] == '/') //주석 등장. { int endOfLine = orgStr.IndexOf('\n', seeker); if (orgStr.Length > seeker + 2 && orgStr[seeker + 2] == '@') //gst 설명변수. Footer에 저장. { commentBaseNode.Comment = orgStr.Substring(seeker, endOfLine - seeker).Trim(); } seeker = endOfLine + 1; lineIndex++; continue; } if (orgStr[seeker] != finalBracket[OPEN] && orgStr[seeker] != finalBracket[CLOSE]) //i { cup += orgStr[seeker]; if (cup.Trim().Length > 0) { commentBaseNode = newNode; //한글자라도 있으면 그 다음에 오는 주석은 이 라인을 위한 것이다. } if (isBracketClosed == false && ArrayCompare(lineFinalizer, orgStr[seeker])) //구문완료문자 { newNode.Header = cup.Trim().Replace("\n", " "); openNode.Children.Add(newNode); newNode = new ContextTree(seeker, lineIndex, "", openNode); cup = ""; } } else if (orgStr[seeker] == finalBracket[OPEN]) //finalbracket이 열릴 때 { newNode.Header = cup.Trim().Replace("\n", " "); openNode = newNode; newNode = new ContextTree(seeker, lineIndex, "", openNode); cup = ""; } else if (isBracketClosed == false) //finalbracket이 닫힐 때 { isBracketClosed = true; //isBracketClosed는 bracket이 닫히고 그 줄이 끝날때까지를 위한 변수이다. 실제 열리고 닫힌 상태와는 관계없다. } if (isBracketClosed && (ArrayCompare(lineFinalizer, orgStr[seeker]) || orgStr[seeker] == '\n')) { openNode.Footer = cup.Trim().Replace("\n", " "); cup = ""; openNode.Parent.Children.Add(openNode); if (openNode.Parent != null) { openNode = openNode.Parent; } else { return(openNode); } newNode = new ContextTree(seeker, lineIndex, "", openNode); isBracketClosed = false; } seeker++; } return(openNode); }
public ContextTree(int charIndex, int lineIndex, String header, ContextTree parent = null, String name = "", Object relativeObject = null) : base(name, relativeObject, parent) { this.CharIndex = charIndex; this.Header = header; this.Parent = parent; }
GstNode parseToGst(ContextTree tree, GstNode member) { String title;// String type, name; int size; GstNode aNode; if (tree.Children.Count == 0) //변수지정이나 할당. 한 줄에 끝나는 구문. GST파일에서는 GST가 유일하다. { title = tree.Header.Trim(); name = ParsingHelper.getAllocTokens(title, out type, out size); if (type.Contains("struct") && member.Kind == ContextKind.VARIABLE) //depth가 깊어짐. { aNode = member.getActiveStruct(type); //같은 struct타입을 가져와서 넣어준다. foreach (GstNode node in aNode.Children) { member.addChild(node); } } return(null); } else if (tree.Header.Trim().Length == 0) //main { foreach (ContextTree aChild in tree.Children) { title = aChild.Header.Trim(); if (title.Split(" ".ToCharArray()).Length == 2) //struct { aNode = new GstNode(aChild.Header.Trim(), member); member.addChild(aNode); parseToGst(aChild, aNode); } else //gst { name = ParsingHelper.getAllocTokens(title, out type, out size); aNode = new GstNode(type, name, member); member.addChild(aNode); parseToGst(aChild, aNode); } } } else if (tree.Header.Contains("struct"))//struct { //for (int i = 0; i < tree.Child.Count; i++) foreach (ContextTree aChild in tree.Children) { title = aChild.Header.Trim(); name = ParsingHelper.getAllocTokens(title, out type, out size); if (type.Contains("struct")) //depth가 깊어짐. { aNode = new GstNode(type, name, member); member.addChild(aNode); parseToGst(aChild, aNode); } else //struct가 아닐 경우, 일반 변수나 배열 { if (size > 0)//배열 { for (int i = 0; i < size; i++) { aNode = new GstNode(member.TypeFromStr(type), name + "[" + i + "]", member); member.addChild(aNode); } } else //일반 변수 { aNode = new GstNode(member.TypeFromStr(type), name, member); member.addChild(aNode); } } } } else { throw new Exception("구문분석 오류.."); } return(member); }