/** * 어휘 분석이 끝난 계층 트리의 구조를 보여준다. * * @param units * @param level */ public void viewHierarchy(Lextree tree, int level) { string space = ""; foreach (int i in Enumerable.Range(0, level)) { space += " "; } foreach (int i in Enumerable.Range(0, tree.branch.Count)) { // 새 가지일 때 if (tree.branch[i].hasBranch) { //Sys.print(space + "<begin>\n"); viewHierarchy(tree.branch[i], level + 1); //Sys.print(space + "<end>\n"); } // 어휘 데이터일 때 else { if (tree.branch[i].lexData.Count < 1) { continue; } string buffer = ""; foreach (int j in Enumerable.Range(0, tree.branch[i].lexData.Count)) { Token token = tree.branch[i].lexData[j]; buffer += token.value.Trim() + "@" + token.type; if (j != tree.branch[i].lexData.Count - 1) { buffer += ", "; } } //Sys.print(space + buffer + "\n"); } } }
public Lextree analyze(string code) { processingLine = 1; // 어휘 트리를 생성한다. Lextree tree = new Lextree(true, processingLine); // 문자열 처리 상태 변수를 초기화한다. bool isString = false; string buffer = ""; int i = -1; while (++i < code.Length) { char _char = code[i]; // 줄바꿈 문자일 경우 줄 번호를 하나 증가시킨다. if (_char == '\n') { processingLine++; } // 문자열의 시작과 종결 부분을 감지하여 상태를 업데이트한다. if (_char == '\"') { isString = !isString; buffer += _char; continue; } // 모든 문자열 정보는 버퍼에 저장한다. if (isString) { buffer += _char; continue; } // 주석을 제거한다. if (_char == '/' && i + 1 < code.Length) { int j = 2; // 단일 행 주석일 경우 if (code[i + 1] == '/') { // 문장의 끝(줄바꿈 문자)를 만날 때까지 넘긴다. while (i + j <= code.Length) { if (code[i + (j++)] == '\n') { break; } } i += j - 1; processingLine++; continue; } // 여러 행 주석일 경우 else if (code[i + 1] == '*') { // 종결 문자열 시퀸스('*/')를 만날 때까지 넘긴다. while (i + j < code.Length) { if (code[i + j] == '\n') { processingLine++; } if (code[i + (j++)] == '*') { if (code[i + (j++)] == '/') { break; } } } i += j - 1; continue; } } // 세미콜론을 찾으면 진행 상황을 스택에 저장한다. if (_char == ';') { // 진행 상황을 스택에 저장한다. if (buffer.Length > 0) { Lextree lextree = new Lextree(false, processingLine); lextree.lexData = tokenize(buffer); tree.branch.Add(lextree); } // 버퍼를 초기화한다. buffer = ""; } // 중괄호 열기 문자('{')를 찾으면 괄호로 묶인 그룹을 재귀적으로 처리하여 저장한다. else if (_char == '{') { // 중괄호 앞의 데이터를 저장한다. if (buffer.Length > 0) { Lextree lextree = new Lextree(false, processingLine); lextree.lexData = tokenize(buffer); tree.branch.Add(lextree); } // 괄호의 끝을 찾는다. int j = 1; int depth = 0; while (i + j <= code.Length) { char __char = code[i + (j++)]; if (__char == '{') { depth++; } else if (__char == '}') { depth--; } else if (__char == '\n') { processingLine++; } if (depth < 0) { break; } } // 괄호의 전체 내용에 대해 구문 분석을 수행한 후, 유닛에 추가한다. (시작, 끝 괄호 제외) Lextree block = analyze(code.Substring(i + 1, i + j - 1 - (i + 1))); tree.branch.Add(block); // 다음 과정을 준비한다. buffer = ""; i += j - 1; } // 처리하지 않는 문자일 경우 버퍼에 쓴다. else { buffer += _char; } } // 맨 뒤의 데이터도 쓴다. if (buffer.Length > 0) { Lextree lextree = new Lextree(false, processingLine); lextree.lexData = tokenize(buffer); tree.branch.Add(lextree); } // 분석 결과를 리턴한다. return(tree); }