powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Парсер математических выражений
8 сообщений из 8, страница 1 из 1
Парсер математических выражений
    #39817221
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Скажем есть выражение
авторIF DIR0==2 AND POS0>POS1 AND POS0-POS1>20 THEN VAR0-=100 AND VAR1+=100;

Я разбиваю на лемксемы.
авторName: IF Type: If
Name: DIR0 Type: Alphanumeric Var Type: 3 Num: 0
Name: == Type: Compare
Name: 2 Type: Number
Name: AND Type: Logic
Name: POS0 Type: Alphanumeric Var Type: 4 Num: 0
Name: > Type: Compare
Name: POS1 Type: Alphanumeric Var Type: 4 Num: 1
Name: AND Type: Logic
Name: POS0 Type: Alphanumeric Var Type: 4 Num: 0
Name: - Type: Operator
Name: POS1 Type: Alphanumeric Var Type: 4 Num: 1
Name: > Type: Compare
Name: 20 Type: Number
Name: THEN Type: Then
Name: VAR0 Type: Alphanumeric Var Type: 12 Num: 0
Name: -= Type: Operator
Name: 100 Type: Number
Name: ; Type: End

И потом работаю с массивом лексем.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
for (i = 0; i < expr_count; i++)
{
    switch (script_state)
    {
        case ST_IF:
            script_state = ST_IN_EXPR;
        break;
        case ST_IN_EXPR:
            switch (expr[i].type)
            {
                case EXPR_TYPE_THEN:
                    if (result == true) //if (true) – goto then
                        script_state = ST_OUT_EXPR;
                    else  //goto next if
                       script_state = ST_IF; 
                break;
                case EXPR_TYPE_OPERATOR: operator = expr[i].val;  break;
                case EXPR_TYPE_COMPARE:   compare = expr[i].val;  break;
                case EXPR_TYPE_LOGIC:        logic = expr[i].val;        break;
                case EXPR_TYPE_END:           script_state = ST_IF;   break;

                default:  //variable or number

                    variable = GetVar(expr[i].type, expr[i].num);

                    if (compare == 0)
                    {
                        switch (operator)
                        {
                           case 0: g_val = variable; break; //first variable?
                           case OP_PLS:    g_val = g_val + variable; break;
                           case OP_MIN:    g_val = g_val - variable;  break;
                           case OP_MUL:   g_val = g_val * variable;  break;
                           case OP_DIV:    g_val = g_val / variable;  break;
                           case OP_BAND: g_val = g_val & variable; break;
                           case OP_BOR:   g_val = g_val | variable;  break;
                        }
                        operator = 0;
                     }
                     else
                     {
                        switch (compare)
                        {
                            case 0: break;
                            default:
                                result = ProcessCompare(g_val, variable, compare);
                            break;
                        }
                        compare = 0;
                     }

                     if (logic == NONE || logic == OP_LOR)
                         result |= result;
                     else if (logic == Defines.OP_LAND)
                         result &= result;

                     break;
            break;
         
         }

        break;       
    }
}



При простом выражении, cкажем POS0>POS1 AND POS0-POS1>20, все работает хорошо.
Но вот такое выражение VAR0=POS0+POS1 уже не работает. Правая часть не присваевается аккумулятивно.
Как мне улучшить алгоритм?
...
Рейтинг: 0 / 0
Парсер математических выражений
    #39817505
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7Как мне улучшить алгоритм?
Написать заново
Начать с описания грамматики языка
...
Рейтинг: 0 / 0
Парсер математических выражений
    #39817526
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропилjenya7Как мне улучшить алгоритм?
Написать заново
Начать с описания грамматики языка
вот поэтому обратился. нужен хороший алгоритм разбирать лексемы.
...
Рейтинг: 0 / 0
Парсер математических выражений
    #39817539
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7,

Рекурсивный спуск
...
Рейтинг: 0 / 0
Парсер математических выражений
    #39818633
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7,
Посмотри в сторону ANTLR .
...
Рейтинг: 0 / 0
Парсер математических выражений
    #39818636
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
jenya7Скажем есть выражение
IF DIR0==2 AND POS0>POS1 AND POS0-POS1>20 THEN VAR0-=100 AND VAR1+=100;

При простом выражении, cкажем POS0>POS1 AND POS0-POS1>20, все работает хорошо.
Но вот такое выражение VAR0=POS0+POS1 уже не работает. Правая часть не присваевается аккумулятивно.
Как мне улучшить алгоритм?
Смотри. Математическое выражение это
Код: sql
1.
1+2*3


В студенческих лабах обычно ограничиваются решением этой задачки черезе ПОЛИЗ.
Это просто трансфомация инфиксной формы в стековую (кажется постфикс).
И лаба сдаётся.

То что ты написал - выходит далеко за рамки просто выражения. Это почти язык где есть conditions.
Языки пишутся на генераторах парсеров (lex/yacc/bison/antlr/javacc). Это тема нудная и сложная.
Вряд-ли у тебя хватит квалификации быстро это сделать (если это не курсовой проект конечно).

Поэтому тебе надо срочно идти к преподу и спрашивать как глубоко тебе надо это делать.

Если все-все выражения который к тебе придут будут иметь вид.
Код: sql
1.
IF condition [AND condition] THEN operator [AND operator];


Тогда твою задачу наверное можно решить на регулярках или на тех псевдо-парсерах как ты делаешь.
Но надо точно знать какие еще варианты придут на вход. Это сильно повлияет на твою лабу или курсовую.

Комплексность решения сильно зависит от этих кейсов.
...
Рейтинг: 0 / 0
Парсер математических выражений
    #39818672
Фотография Малыхин Сергей
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лексемы в массив это совсем не вариант.

Выражение имеет иерархическую суть.Чета раньше чета позже чета в скобках чета нет. Следовательно бинарные деревья тебе в руки
к примеру https://www.google.com/search?q=syntax tree&oq=syntax tree&aqs=chrome..69i57j0l5.1095j0j7&sourceid=chrome&ie=UTF-8

А проще взять что нибудь готовое например http://esprima.org/demo/parse.html#
...
Рейтинг: 0 / 0
Парсер математических выражений
    #39819623
jenya7
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Малыхин СергейЛексемы в массив это совсем не вариант.

Выражение имеет иерархическую суть.Чета раньше чета позже чета в скобках чета нет. Следовательно бинарные деревья тебе в руки
к примеру https://www.google.com/search?q=syntax tree&oq=syntax tree&aqs=chrome..69i57j0l5.1095j0j7&sourceid=chrome&ie=UTF-8

А проще взять что нибудь готовое например http://esprima.org/demo/parse.html#
ну почему не вариант?

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
public void Run(Expr[] expr, int expr_count, int idx, int trig, RichTextBox rtb)
        {
            int i = idx;
            int variable;

            switch (script_state)
            {
                case ST_IDLE:
                case ST_IF:
                    if (expr[i].type == Defines.EXPR_TYPE_IF)
                    {
                        if (rtb != null)
                            rtb.AppendText("IF ");

                        script_params.result = false;
                        script_params.oper = 0;
                        script_params.compare = 0;

                        var_state = VAR_ST_LGROUP;
                        script_state = ST_IN_EXPR;
                    }
                   
                    if (expr[i].type == Defines.EXPR_TYPE_THEN)
                    {
                        if (rtb != null)
                            rtb.AppendText(" THEN ");

                        script_state = ST_IN_EXPR;
                    }
                    break;

                case ST_IN_EXPR:
                    switch (expr[i].type)
                    {
                        case Defines.EXPR_TYPE_THEN:
                            if (script_params.result == true)
                            {
                                if (rtb != null)
                                    rtb.AppendText(" THEN ");

                                var_state = VAR_ST_LGROUP;
                                script_params.oper = 0;
                            }
                            else
                            {
                                if (rtb != null)
                                    rtb.AppendText(" FALSE" + Environment.NewLine);

                                script_state = ST_IF;
                            }
                            break;

                        case Defines.EXPR_TYPE_STGR:
                            if (rtb != null)
                                rtb.AppendText("(");
                            script_params.group_oper = script_params.oper;
                            script_params.oper = 0;
                            var_state = VAR_ST_RGROUP;
                            break;

                        case Defines.EXPR_TYPE_ENDGR:
                            if (rtb != null)
                                rtb.AppendText(")");
                            var_state = VAR_ST_LGROUP;
                            break;

                        case Defines.EXPR_TYPE_END:
                            rtb.AppendText(";" + Environment.NewLine);
                            script_state = ST_IF;
                            break;

                        case Defines.EXPR_TYPE_OPER:  //get operator
                            script_params.oper = expr[i].val;

                            if (rtb != null)
                                rtb.AppendText(parser.OperatorToStr(script_params.oper));
                            break;

                        case Defines.EXPR_TYPE_COMP:  //get compare
                            script_params.compare = expr[i].val;

                            if (rtb != null)
                                rtb.AppendText(parser.CompareToStr(script_params.compare));

                            break;

                        case Defines.EXPR_TYPE_LOG:  //get logic
                            script_params.logic = expr[i].val;

                            if (rtb != null)
                                rtb.AppendText(" " + parser.LogicToStr(script_params.logic) + " ");
                            break;

                        default:  //variable or number

                            if (rtb != null)
                            {
                                if (expr[i].type == Defines.EXPR_TYPE_NUM)
                                    rtb.AppendText(expr[i].val.ToString());
                                else
                                    rtb.AppendText(parser.VarToStr(expr[i].type, expr[i].num));
                            }

                            if (expr[i].type == Defines.EXPR_TYPE_NUM)
                                variable = expr[i].val;
                            else
                                variable = GetVar(expr[i].type, expr[i].num);

                            ProcessVariable(expr[i].type, expr[i].num, variable, expr[i + 1].type);

                            break;
                    }
                    break;
            }
        }



Вполне себе работает. Одна проблема - много места занимает. Даже если хранить в текстовом варианте и парсить при поднятии микроконтролера. Оригинально скрипт должен бежать на микроконтролере.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Парсер математических выражений
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]