LINUX.ORG.RU

Написание собственного интерпретатора

 


0

1

Задача: мне нужен простенький язык для парсинга правил (rule engine). Первое что я нагуглил была статья про польскую нотацию, а там была статья на описание алгоритма сортировочной станции (он годится только для математических выражений), потом прочитал про метод рекурсивного спуска, набросал простой пример:

https://gist.github.com/codedumps/3c953bf7795fe70d5700476c06149fdd

Код вроде работает, методом тыка реализовал. Так вот вопрос как улучшить этот код? Мне он не нравится.

★★

А что не нравится? Вроде неплохо.

monk ★★★★★
()

Ты хоть бы комментарии написал что он делает, как это запускать, что подавать на вход и что должно быть на выходе.

crutch_master ★★★★★
()

Сделай на s-expr - там будет все совсем просто. Парсер такого языка на парсер-комбинаторах - всего несколько строчек.

Минимальный эвал можно уместить ещё в строк 10.

Хватит и динамического связывания - просто map.

Вообще, мой матрикс есть в профиле - можешь написать, я уже писал подобные вещи.

nihirash ★★★
()
Ответ на: комментарий от crutch_master

нельзя же. эти правила редактировать будут менегеры всякие, а там могут натворить что угодно. тут 4 токена всего, но легко расширяется до полноценного интерпретатора, можно добавить списки и словари кучу операторов. приоритет оператора тем ниже чем раньше функция вызывается. легко можно построить ast, но мне это не нужно. абстрактное синтаксическое дерево нужно если есть циклы и объявление функций.

tz4678 ★★
() автор топика
Ответ на: комментарий от tz4678

Так ты можешь просто распарсить любой текст в js и сделать eval.

эти правила редактировать будут менегеры всякие

Не, это сразу провал. Надо делать гуй, чтобы они мышкой таскали или сосисками своими и физически не смогли нажать не туда. Если бы манагеры в принципе могли писать скрипты, можно было бы и js какой-нибудь дать с repl и отладкой.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от tz4678

Ну так не делай while (true); кто тебя заставляет. Это для тебя же всё, а не для юзеров.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от tz4678

Ну так не давай доступ к fs. Да и вообще зачем непрограммистам код, они всё равно не поймут ничего. Сделай гуй и чтобы можно было мышкой, не извращайся, никто не оценит. Тут формулы, с приличной либой, сделаешь для бухов, так они русскую а вместо латинской впишут.

crutch_master ★★★★★
()
Ответ на: комментарий от nihirash

s-expression это lisp имеется в виду? ну такое реализуется элементарно:

onst evaluate = input => {
  const tokens = input.replace(/[-+*/()]/g, ' $& ').trim().split(/\s+/)
  if (tokens.shift() !== '(') {
    throw new Error('excpected: "("')
  }
  const parse = () => {
    const fn = {
      '+': (a, b) => a + b,
      '-': (a, b) => a - b,
      '*': (a, b) => a * b,
      '/': (a, b) => a / b,
    }[tokens.shift()]
    if (fn === undefined) {
      throw new Error('invalid operator')
    }
    const values = []
    while (tokens.length > 0) {
      const token = tokens.shift()
      if (token === '(') {
        values.push(parse())
      } else if (token === ')') {
        if (values.length === 0) {
          throw new Error()
        }
        return values.reduce(fn, values.shift())
      } else if (!isNaN(token)) {
        values.push(+token)
      } else {
        throw new Error('unexpected token')
      }
    }
    throw new Error('excpected: ")"')
  }
  return parse()
}

evaluate('(+1(*2 3))') // 7

никаких алгоритмов не требует, но синтаксис из скобочек уродлив. тем более интерпретатор выражений я доделал, там осталось только добавить оператор точку, объявление массивов и словарей и вызов функций. этот функционал покроет 99% задач.

tz4678 ★★
() автор топика
Ответ на: комментарий от nihirash

я добавил массивы, взятие по индексву и вызов функций. криво, но работает:

$ node expr.js "['foo', 42, 8==3][2]"
false
$ node expr.js "len(['foo', 42, 8==3][0])"
3

в качестве прототипа сойдет.

tz4678 ★★
() автор топика
Ответ на: комментарий от nihirash

даже питоновские слайсы можно реализовать:

$ node expr.js "'hello'[0:-1]"
hell
tz4678 ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.