В статье рассмотрим полезный инструмент облегчающий сбор данных с сетевых устройств. Для работы скриптов с командной строкой по SSH на языке Python нужно использовать множество сторонних модулей, а вернее множество зависимостей одного модуля (привет paramiko), а если на машине где будет работать скрипт нет интернета или нет возможности установить Python последних версий, то задача запуска скрипта становится практически невозможной. Для решения подобной проблемы был разработан SSH Picker с возможностью подключения дополнительных модулей через AMQP протокол.
Рубрика «parsers»
SSH Picker в ежедневной работе сетевого инженера
2022-01-22 в 12:57, admin, рубрики: automatization, Go, golang, parsers, RabbitMQ, ssh, Сетевые технологии, системное администрированиеScala: parser combinators на примере парсера формул
2017-04-03 в 1:16, admin, рубрики: kotlin так не может, packrat parsers, parser combinators, parsers, scala, функциональное программированиеВремя от времени у меня возникает желание придумать свой собственный маленький язык программирования и написать интерпретатор. В этот раз я начал писать на scala, узнал про библиотеку parser combinators, и был поражён: оказывается, можно писать парсеры легко и просто. Чтобы не превращать статью в пособие по "рисованию совы", ниже приведёна реализация разбора и вычисления выражений типа "1 + 2 * sin(pi / 2)"
.
Сам парсинг и вычисление выражения занимают всего лишь 43 непустых строчки — не то чтобы я сильно стремился сократить их количество, но выглядит это реально просто и лаконично. Проект на github.
Для сравнения:
Итак, если вам не терпится увидеть результат:
object FormulaParser extends RegexParsers with PackratParsers {
def id: Parser[Id] = "[a-zA-Z][a-zA-Z0-9_]*".r ^^ Id
def number: Parser[Number] = "-" ~> number ^^ (n => Number(-n.value)) |
("[0-9]+\.[0-9]*".r | "[0-9]+".r) ^^ (s => Number(s.toDouble))
def funcCall: Parser[FuncCall] = id ~ ("(" ~> expression <~ ")") ^^ (pair => FuncCall(pair._1, pair._2))
def value: Parser[Expression] = number | funcCall | id | ("(" ~> expression <~ ")")
lazy val term: PackratParser[Expression] = term ~ ("*" | "/") ~ value ^^ binOperation | value
lazy val expression: PackratParser[Expression] = expression ~ ("+" | "-") ~ term ^^ binOperation | term
...
}
Посмотрите на следущую строчку:
def value: Parser[Expression] = number | funcCall | id | ("(" ~> expression <~ ")")
Она подозрительно похожа на описание грамматики, но это валидный код, в котором среда разработки может сразу же обнаружить и подсветить большинство ошибок.
Это возможно по следующим причинам:
- В scala разрешено давать методам замечательные названия типа
"~", "~>", "<~", "|", "^^"
. Комбинация парсеровp
иq
записывается какp~q
, а возможность выбрать один из них:p|q
. Читается намного лучше, чемp.andThen(q)
илиp.or(q)
- Благодаря неявным преобразованиям (implicits) и строчка
"abc"
и регулярное выражение"[0-9]+".r
при необходимости превращаются в парсеры. - В языке мощная статическая система типов, которая позволяет ловить ошибки сразу.
Думаю, мне удалось Вас заинтересовать, поэтому дальше всё будет по порядку.