Расширение синтаксиса QPILE: Return и Loop
Препроцессор M4 позволяет легко расширять синтаксис языка QPILE. Проиллюстрирую это на примере оператора RETURN
В стандартном варианте этот оператор применяется без параметров. Однако, в большинстве языков программирования этот оператор может иметь возвращаемое значение. Привычка - вторая натура и я частенько по привычке пробую вернуть что-то в этом операторе. Гадость состоит в том, что интерпретатор QPILE спокойно прожевывает конструкцию типа RETURN <VALUE>, но выполняет неправильно (подробнее в статье Оператор RETURN).
Препроцессор легко позволяет как облегчить мне жизнь, чтобы я писал так, как мне привычно, так и обойти ошибку QPILE.
Макрос выглядит тривиально:
define(Return,`ifelse($1,,return,translit($1,`a-z',`A-Z'),RESULT,return,
result = $1
return)')
При нахождении в тексте конструкции Return макрос обращает внимание на его аргумент.
- если аргументов нет, все остается как есть
- если аргумент имеется и совпадает с "result" - он игнорируется
- во всех остальных случаях перед return происходит передача аргумента в переменную result
Исходный текст |
После препроцессора |
---|---|
Return(5*frame) |
result = 5*frame |
Return | return |
Return() | return |
Return(result) | return |
Таким образом, препроцессор позволяет довольно легко расширять синтаксис языка QPILE.
Чуть более сложный пример. В QPILE имеется только один вариант оператора цикла, базовый. Временами нужны иные типы циклов. Их можно создать из базового, причем очень гибко и различные типы. Определяем 4 макроса:
define(Loop,`for m4_loop from 0 to m4_loop')
define(While,`
if $1
else
break
end if
')
define(Until,`
if $1
break
end if
')
define(EndLoop,`end for')
Теперь у нас есть полная свобода в выборе типа цикла:
- Бесконечный цикл:
Loop ... тело цикла ... EndLoop
- Цикл While с проверкой в начале:
Loop while(price<100) ... тело цикла ... EndLoop
- Цикл Until с проверкой в начале:
Loop Until(price <100) ... тело цикла ... EndLoop
- Цикл While с проверкой в конце:
Loop ... тело цикла ... while(price < 100) EndLoop
- Цикл Until с проверкой в конце:
Loop ... тело цикла ... Until(price < 100) EndLoop
- Комбинированный вариант
Loop Until(price1 == 100) While(price2 == 200) ... тело цикла ... EndLoop
- или даже такой:
Loop Until(a>5) Until(b<3) While(c==4) ... тело цикла ... While(d != 8) while(e < 7) Until(c==6) EndLoop
Все эти конструкции препроцессор развернет в допустимые в синтаксисе языка qpile и они будут исправно выполняться интерпретатором. Конечно, все циклы могут быть вложенными друг в друга.
Продолжение в статье Оператор Switch для QPILE.