예제 #1
0
        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;
            }
        }
예제 #2
0
        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);
        }