Оператор Switch для QPILE
Продолжение статьи Расширение синтаксиса QPILE
В синтаксисе QPILE отсутствует оператор Switch. Иногда такое отсутствие неприятно и приходится создавать списки из операторов If, которые могут занимать целый экран, а то и не один. Тем не менее, используя имеющиеся конструкции языка QPILE и препроцессор, не составляет особого труда создать этот оператор.
Определяем макросы:
define(`Switch',`ifelse($1,,`err'print(Error __file__ line __line__: Missing SWITCH argument
),pushdef(`m4_switch',$1) pushdef(`m4_first_switch',0) pushdef(`m4_was_default',0) Loop)')
define(`m4_close_choice',`ifelse(m4_first_switch,0,popdef(`m4_first_switch') pushdef(`m4_first_switch',1),break
end if)')
define(`Case',`ifelse($1,,`err'print(Error __file__ line __line__: Missing CASE argument
),m4_close_choice
if m4_switch == $1)')
define(`Default',`ifelse($1,,m4_close_choice popdef(`m4_was_default') pushdef(`m4_was_default',1),`err'print(Error __file__ line __line__: Excess parameter(s) in DEFAULT
))')
define(`EndSwitch',`ifelse(m4_was_default,0,break
end if)
break
EndLoop
popdef(`m4_was_default')
popdef(`m4_switch')')
Макросы Loop и EndLoop описаны здесь. Проверяем, как это работает. Пишем исходный текст
Switch(a)
Case(1)
.. операторы если а ==1..
Case(2)
.. операторы если а ==2..
Default
.. операторы для всех остальных случаев..
EndSwitch
Получаем:
for m4_loop_counter from 0 to m4_loop_counter
if a == 1
.. операторы если а ==1..
break
end if
if a == 2
.. операторы если а ==2..
break
end if
.. операторы для всех остальных случаев..
break
end for
Все честно, как и должно быть. Проверим вложенные операторы Switch:
Switch(a)
Case(1)
.. операторы если а ==1..
Switch(aaaaaaa)
Case(100)
.. операторы если aaaaaaа ==100..
Case(200)
.. операторы если аaaaaaa ==200..
EndSwitch
Case(2)
.. операторы если а ==2..
Default
.. операторы для всех остальных случаев..
EndSwitch
Результат:
for m4_loop_counter from 0 to m4_loop_counter
if a == 1
.. операторы если а ==1..
for m4_loop_counter from 0 to m4_loop_counter
if aaaaaaa == 100
.. операторы если aaaaaaа ==100..
break
end if
if aaaaaaa == 200
.. операторы если аaaaaaa ==200..
break
end if
break end for
break
end if
if a == 2
.. операторы если а ==2..
break
end if
.. операторы для всех остальных случаев..
break end for
И здесь все нормально. Можно пользоваться.
Если внимательно присмотреться к макросам, то станет видно, что между операторам Switch и первым Casе можно вставить произвольные операторы и результат все равно будет допустимым. Я не вижу смысла запрещать эту возможность.
P.S. Осталось только проверить, чтобы выбор Default был последним в списке возможных значений. Это нетрудно, оставляю это заинтересованному читателю.
См. также:
Комментарии
define(`CaseIn',`ifelse($#,2,m4_close_choice
if m4_switch > = $1 and m4_switch < = $2,`err'print(I nvalid number of parameters in CASEIN choice))')
define(`CaseList',`indir(`m4_close_choice')
pushdef(`m4_list_num')foreach(`X',`ifelse(indir(`m4_list_num'),,if,or) popdef(`m4_list _num')pushdef(` m4_list_num',1) indir(`m4_switc h') == X',$*)')
итого вот как может выглядеть оператор Switch в тексте на qpile
Switch(a)
Case(1)
.. операторы если а ==1..
CaseIn(2,15)
.. операторы если а между 2 и 15..
CaseList(33,44, 55,66)
.. операторы если a==33 или a=44 или a==55 или a==66
Default
.. операторы для всех остальных случаев..
EndSwitch
Что характерно, Case есть вариант Caselist с одним параметром. Но пусть остается как есть, для читабельности
RSS лента комментариев этой записи