Каждый разработчик рано или поздно сталкивается с предметно-ориентированными языками (DSL). Мы разберемся, зачем же нам нужны DSL, и какие проблемы они нам помогают решать. Поймем, в каких случаях нам стоит разрабатывать свой язык, а в каких — использовать уже существующий. Попробуем провести грань и решить, где у нас просто библиотека, а где — предметно ориентированный язык. Придумаем свой DSL и сравним различные подходы к работе с ним в Python. Увидим, как работают лексический и синтаксический анализаторы. Обязательно поговорим про то, как облегчить жизнь пользователям нашего языка. Как сделать информативными сообщения об ошибках? Как тестировать сценарии, написанные на нашем языке? На эти вопросы мы сможем дать ответ.
15. – Мартин Фаулер
Предметно-ориентированный язык — это
язык программирования с ограниченными
выразительными возможностями,
ориентированный на некую конкретную
предметную область
33. number = value_of('DIGIT') >> int
unit = number + value_of('UNIT') >> to_bytes
operand = unit | number
makeop = lambda s, f: skip_token(s) >> const(f)
add = makeop('PLUS', operator.add)
sub = makeop('MINUS', operator.sub)
mul = makeop('MUL', operator.mul)
div = makeop('DIV', operator.floordiv)
mul_op = mul | div
add_op = add | sub
funcparserlib
58. Сообщения об ошибках
Traceback (most recent call last):
File "size_parser/on_ply.py", line 100, in parse
return parser.parse(string)
File "size_parser/on_ply.py", line 94, in parse
p = self._parser.parse(data, debug=self._debug)
File ".env/site-packages/ply/yacc.py", line 331, in parse
return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
File ".env/site-packages/ply/yacc.py", line 1049, in parseopt_notrack
lookahead = get_token() # Get the next token
File ".env/site-packages/ply/lex.py", line 396, in token
raise LexError("Illegal character '%s' at index %d" % (lexdata[lexpos], lexpos), lexdata[lexpos:])
ply.lex.LexError: Illegal character '_' at index 5
59. Traceback (most recent call last):
File "size_parser/on_ply.py", line 100, in parse
return parser.parse(string)
File "size_parser/on_ply.py", line 94, in parse
p = self._parser.parse(data, debug=self._debug)
File ".env/site-packages/ply/yacc.py", line 331, in parse
return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
File ".env/site-packages/ply/yacc.py", line 1049, in parseopt_notrack
lookahead = get_token() # Get the next token
File ".env/site-packages/ply/lex.py", line 396, in token
raise LexError("Illegal character '%s' at index %d" % (lexdata[lexpos], lexpos), lexdata[lexpos:])
ply.lex.LexError: Illegal character '_' at index 5
Сообщения об ошибках
64. Что же выбрать?
PLY
funcparserlib
pyparsing
✤ Хочу как в учебнике
✤ Скорость работы - главное!
✤ Хочу легко все описать
✤ Быстродействие не главное
✤ Люблю функциональное
программирование
✤ Быстродействие не главное
65. И что в итоге?
✤ Для простых задач попробуйте:
✤ Средства самого языка
✤ Регулярные выражения
✤ Если задача сложная:
✤ Внутренние DSL
✤ Yaml, Json, XML, …
✤ Внешние DSL