Гость
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Парсер математических выражений / 8 сообщений из 8, страница 1 из 1
23.05.2019, 15:48
    #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
24.05.2019, 09:51
    #39817505
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Парсер математических выражений
jenya7Как мне улучшить алгоритм?
Написать заново
Начать с описания грамматики языка
...
Рейтинг: 0 / 0
24.05.2019, 10:09
    #39817526
jenya7
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Парсер математических выражений
Изопропилjenya7Как мне улучшить алгоритм?
Написать заново
Начать с описания грамматики языка
вот поэтому обратился. нужен хороший алгоритм разбирать лексемы.
...
Рейтинг: 0 / 0
24.05.2019, 10:23
    #39817539
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Парсер математических выражений
jenya7,

Рекурсивный спуск
...
Рейтинг: 0 / 0
27.05.2019, 10:29
    #39818633
ЕвгенийВ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Парсер математических выражений
jenya7,
Посмотри в сторону ANTLR .
...
Рейтинг: 0 / 0
27.05.2019, 10:40
    #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
27.05.2019, 11:41
    #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
29.05.2019, 09:22
    #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]