Перейти к содержанию
    

Проиндексировать if-then-else

Столкнулся с такой алгоритмической проблемой - проиндексировать if-then-else связки.

if xxx then //0
{ //0
    if xxx then //1
        xxx;
    else //1
    {//1
        if xxx then //2
        {//2
            xxx;
        }//2
        if xxx then //3
        { //3
        }  //3
        if xxx then //4
            xxx;
        else//4
            xxx;
    }//1
}//0
else //0   
    xxx;

Получается как то уродливо и громоздко.

Я разбиваю выражения на токены

switch (current_tok.type)
{
    case If:  
        expr[script_params.expr_size].type = EXPR_TYPE_IF; 
        if_then_else_state = EXPR_TYPE_IF;
        expr[script_params.expr_size].num = if_then_idx;
    break;
    
    case Then: 
        if (if_then_else_state == EXPR_TYPE_IF)
        {
            expr[script_params.expr_size].type = EXPR_TYPE_THEN;
            if_then_else_state = EXPR_TYPE_THEN; 
                    
            expr[script_params.expr_size].num = if_then_idx;
            block_idx = if_then_idx;
            else_idx = if_then_idx;
            if_then_idx++;        
        }
        else
            err = -1;   
    break;
    
    case Else: 
        if (if_then_else_state == EXPR_TYPE_THEN || if_then_else_state == EXPR_TYPE_ENDBLK)   
        {
            expr[script_params.expr_size].type = EXPR_TYPE_ELSE;
           if_then_else_state = EXPR_TYPE_ELSE;
                    
           if (if_then_else_state == EXPR_TYPE_THEN)
               expr[script_params.expr_size].num = else_idx;
                    
           if (prev_expr_type == EXPR_TYPE_ENDBLK)
               //??????
        }
        else
            err = -1;   
    break;

    case BlockStart: 
        if (if_then_else_state == EXPR_TYPE_THEN || if_then_else_state == EXPR_TYPE_ELSE) 
        {
            blocks++;
            expr[script_params.expr_size].type = EXPR_TYPE_STBLK;
            expr[script_params.expr_size].num = block_idx;
            if_then_else_state = EXPR_TYPE_STBLK;
        }
        else
           err = -1;
    break;
    
    case BlockEnd:   
        blocks--;
        expr[script_params.expr_size].type = EXPR_TYPE_ENDBLK;
        //expr[script_params.expr_size].num = ???
     break;

Вопрос как отследить "потерявшиеся" 'else' и '}' без выделения памяти (lifo, look-up table).

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 minutes ago, jenya7 said:

Вопрос как отследить "потерявшиеся" 'else'

Переписать код так, чтобы не пришлось городить такие УЖОСЫ 🥴. Например, структурировать, разбить на отдельные маленькие функции и тп

При подобном ужосе всегда переписываю и всегда получается ))

Если же ваша цель - изобрести некий умный костыль, то я промолчу 😎

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 12/8/2022 at 1:58 PM, Forger said:

Переписать код так, чтобы не пришлось городить такие костыли. Например, структурировать, разбить на отдельные маленькие функции, да и вообще при подобном ужосе всегда переписываю, и всегда получается ))

переписать парсер токенов? по моему вполне логичный, чё в нем ужасного.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 minutes ago, jenya7 said:

по моему вполне логичный, чё в нем ужасного.

логичный это вам кажется в данную минуту,

через неделю он странет трудночитаемым, а через год его вообще невозможно будет понять без полотнищ комментариев

впрочем, допускаю что не конца понимаю всех масштабов вашей грандиозной затеи ))

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Forth в помощь. Делаешь стек(LIFO) параметров на который по токенам выражения(включая токены скобок и ";")  кладешь и анализируешь некие константы(у тебя они уже есть, но надеюсь там enum, а не тупые подстановки препроцессора) отвечающие за тот или иной элемент конструкции.

И да, разбирать токены switch-case-ом как по мне - уродство.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 12/8/2022 at 2:56 PM, artemkad said:

Forth в помощь. Делаешь стек(LIFO) параметров на который по токенам выражения(включая токены скобок и ";")  кладешь и анализируешь некие константы(у тебя они уже есть, но надеюсь там enum, а не тупые подстановки препроцессора) отвечающие за тот или иной элемент конструкции.

И да, разбирать токены switch-case-ом как по мне - уродство.

а размер LIFO? я не знаю какой скрипт зайдёт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 минуты назад, jenya7 сказал:

а размер LIFO? я не знаю какой скрипт зайдёт.

Размер LIFO определяется допустимой глубиной вложения структур. Так или иначе слишком большая глубина должна тоже вызывать ошибку. В принципе, можно попытаться извратиться и воспользоваться имеющимся стеком через рекурсию, но как по мне это будет сложнее и он тоже будет ограничен размером выделенным под стек минус все что там еще вложеного.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 12/8/2022 at 3:16 PM, artemkad said:

Размер LIFO определяется допустимой глубиной вложения структур. Так или иначе слишком большая глубина должна тоже вызывать ошибку. В принципе, можно попытаться извратиться и воспользоваться имеющимся стеком через рекурсию, но как по мне это будет сложнее и он тоже будет ограничен размером выделенным под стек минус все что там еще вложеного.

ну хорошо условие пуш мне понятно, но какое условие поп?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

31 минуту назад, jenya7 сказал:

ну хорошо условие пуш мне понятно, но какое условие поп?

Закрытие блока по {, }, else, ; или конец файла. С  пушем там тоже будет особенность - он должен оставить на стеке признак "конца then" если там был признак "начало then",  этот признак или используется(и снимается) следующим else или просто снимается если дальше if или { или ; или  конец файла.

ЗЫ. then там тоже делает поп признака if, и пуш признака "начало then"... 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А что мешает иметь более структурную конструкцию а-ля

if (условие)

xxx

else // не обязательное

xxx

end

?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 12/8/2022 at 4:08 PM, artemkad said:

А что мешает иметь более структурную конструкцию а-ля

if (условие)

xxx

else // не обязательное

xxx

end

?

а что поменялось? ')' тот же then. можно и а-ля python 

if  условие :

не вижу как это упростит алгоритмику.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 минут назад, jenya7 сказал:

а что поменялось? ')' тот же then

Не, на этой части я не настаиваю - тут без разницы чем ограничивать конец условия.  Там основное отличие - признак конца "end". Т.е. есть начало if конец end и внутри 2 или 3 блока ограниченные then(или скобкой или еще чем)  и else

Т.е. вход должен быть один и один выход. А в текущем варианте много вариантов окончания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 12/8/2022 at 4:20 PM, artemkad said:

Не, на этой части я не настаиваю - тут без разницы чем ограничивать конец условия.  Там основное отличие - признак конца "end". Т.е. есть начало if конец end и внутри 2 или 3 блока ограниченные then(или скобкой или еще чем)  и else

ну можно обязать писателя скрипта обрамлять всё парой {} но хотелось как то по взрослому 🙂 .

хотя помню писал в делфине (паскаль) так там везде begin - end.

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 минут назад, jenya7 сказал:

ну можно обязать писателя скрипта обрамлять всё парой {} но хотелось как то по взрослому

Ну, можно и по-взрослому

<if условие>
  xxx
<else>
  xxx
</if>

или еще взрослее

<if условие>
	<then>  xxx </then> 
  	<else>  xxx </else>
</if>

или уж совсем хардкор

<if>
  	<then  условие1>  xxx </then> 
	<then  условие2>  xxx </then> 
	<then  условие3>  xxx </then> 
	<then  условие4>  xxx </then>  
  	<else>  xxx </else>
</if>

:dash2:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...