static void process_token(token_t t, String data) { if (t != token_t.eol && t != token_t.eof && !(wait_next.Count == 0) && !wait_next.Contains(t)) { throw new Exception("Unexpected token"); } switch (t) { case token_t.unknown: break; case token_t._operator: case token_t.mute: case token_t.keyword: case token_t.token: state = t; wait_next.Clear(); wait_next.Add(token_t.ident); break; case token_t.ident: // получен идентификатор switch (state) { case token_t._operator: case token_t.mute: case token_t.keyword: case token_t.token: // Name must be unique foreach (token_description item in token_descs) { if (item.name == data) { throw new Exception("Token name must be unique"); } } // do some descr.type = state; descr.name = data; wait_next.Clear(); wait_next.Add(token_t.expr); break; } break; case token_t.expr: // получено выражение switch (state) { case token_t._operator: case token_t.mute: case token_t.keyword: case token_t.token: { // do some descr.expr = data; token_descs.Add(descr); wait_next.Clear(); } break; } break; case token_t.eof: case token_t.eol: state = token_t.unknown; wait_next.Clear(); break; } }
static public int Gen(String src, out String header, out String body, String UnitName) { RegularGenerator gen = new RegularGenerator(); String tmp = ""; bool first = true; StringBuilder ss = new StringBuilder(); foreach (char ch in UnitName) { if ('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || '0' <= ch && ch <= '9' || ch == '_') { if (first && '0' <= ch && ch <= '9') { ss.Append('_', 1); } ss.Append(ch); } if (ch == ' ') { ss.Append('_'); } first = false; } if (ss.Length == 0) { UnitName = "untitled"; } else { UnitName = ss.ToString(); } init(ref gen); int i = 0; int j; int line = 1; int line_begin = -1; bool mute_expr = false; // обработка while (i < src.Length) { // ищем начало for (; i < src.Length && RegularGenerator.ws(src[i]); i++) { if (src[i] == '\n') { // просто начало строки (вместо разделения точкой с запятой) process_token(token_t.eol, "\n"); mute_expr = false; line++; line_begin = i; } } if (i == src.Length) { break; } j = i; switch (src[i]) { case '#': // комментарий for (i++; i < src.Length && src[i] != '\n'; i++) { ; } continue; // начало выражения case '(': { if (mute_expr) { break; } // начало выражения потом его в собственный компилятор загоним int brack = 1; bool screen = false; for (i++; i < src.Length && brack > 0 && src[i] != '\n'; i++) { if (screen) { // экранироване действует лишь на один символ // что конкретно экранируется сейчас не особо важно screen = false; } else { // не экранированные символы участвуют в подсчете if (src[i] == '(') { brack++; } else if (src[i] == ')') { brack--; } else if (src[i] == '\\') { screen = true; } } } tmp = src.Substring(j, i - j); // очищаем от внешних скобок они больше не нужны if (brack > 1) { // где-то в выражении есть незакрытые скобки ErrStr += $"[ERROR] unbalanced brackets at {line}:{j - line_begin}"; header = ""; body = ""; return(-1); } else if (brack == 1) { // одну скобку мы можем закрыть, так как точно знаем что это за скобка // (с неё начинается любое регулярное выражение) ErrStr += $"[WARNING] expression not closed at {line}:{j - line_begin}"; } else { tmp = tmp.Remove(tmp.Length - 1); } tmp = tmp.Remove(0, 1); // отправляем на дальнейшую обработку try { process_token(token_t.expr, tmp); } catch (Exception e) { ErrStr += $"[ERROR] {e.Message} \"{tmp}\" at {line}:{i - line_begin - tmp.Length}"; header = ""; body = ""; return(-1); } continue; } } // найдем идентификатор for (; i < src.Length && !RegularGenerator.ws(src[i]); i++) { ; } tmp = src.Substring(j, i - j); // уточним найденный идентификатор (ключевое слово/идентификатор) token_t token = recognize(tmp); // отправка на обраотку try { process_token(token, tmp); } catch (Exception e) { ErrStr += $"[ERROR] {e.Message} \"{tmp}\" at {line}:{i - line_begin - tmp.Length}"; header = ""; body = ""; return(-1); } } process_token(token_t.eof, tmp); // Компиляция включаемых файлов token_descs.Sort(ItemCmp); Int32 id = 0; foreach (token_description item in token_descs) { try { // добавить ветвь в дерево состояний if (item.type != token_t.sysyem) { if (item.type == token_t.mute) { gen.add_branch(item.expr, 0); } else { gen.add_branch(item.expr, id); } } id++; } catch (EIndeterminate e) { ErrStr = $"[ERROR] {e.Message} \"{tmp}\" at {line}:{i - line_begin - tmp.Length}"; header = ""; body = ""; return(-1); } catch (Exception e) { ErrStr = $"[ERROR] {e.Message}"; header = ""; body = ""; return(-1); } } // Заголовочный файл write_header(out header, UnitName); // Конеченный автомат и вспомогательные функци write_source_file(out body, UnitName, ref gen); return(0); }