Как мне реализовать приложение для обработки команд?

9

Я хочу создать простое приложение для проверки концепции (REPL), которое принимает число, а затем обрабатывает команды для этого числа.

Пример: я начинаю с 1. Затем я пишу " add 2", это дает мне 3. Затем я пишу " multiply 7", это дает мне 21. Затем я хочу знать, если это простое число, поэтому я пишу " is prime" (на текущем номере - 21), это дает мне ложь. " is odd" дал бы мне правду. И так далее.

Теперь, для простого приложения с несколькими командами, даже простое switchбудет подходить для обработки команд. Но если мне нужна расширяемость, как мне нужно реализовать эту функциональность? Я использую шаблон команды? Создаю ли я простой парсер / интерпретатор для языка? Что делать, если я хочу более сложные команды, такие как " multiply 5 until >200"? Что может быть простым способом расширить его (добавить новые команды) без перекомпиляции?

Изменить: чтобы прояснить некоторые вещи, моя конечная цель будет не сделать что-то похожее на WolframAlpha, а скорее процессор списка (чисел). Но сначала я хочу начать медленно (с одного номера).

Я имею в виду нечто похожее на то, как можно использовать Haskell для обработки списков, но очень простая версия. Мне интересно, будет ли достаточно что-то вроде шаблона команды (или его эквивалента), или мне нужно будет создать новый мини-язык и парсер для этого для достижения моих целей?

Edit2: Спасибо за все ответы, все были очень полезны для меня, но Эммад Карим помог мне больше всего, поэтому я выберу его в качестве ответа. Еще раз спасибо!

Нини Майклс
источник
2
Я не получаю отрицательных голосов. Пожалуйста, укажите причину, чтобы я мог лучше сформулировать свой вопрос в следующий раз.
Нини Майклз
2
Мне очень нравится этот вопрос. С нетерпением жду, чтобы увидеть, какие проекты люди предлагают. Вы специально ищете объектно-ориентированный дизайн (вы упоминаете шаблон команд, который является шаблоном OO)?
Бьярке Фрейнд-Хансен
спасибо :) да, я бы предпочел ООП, но я не буду возражать, если будут предложены другие методы!
Нини Майклз
2
Кажется, реализация Reverse Polish Notation , очень крутой предмет программирования!
Альберто де Каро
2
Вы, вероятно, не согласны с положением книги. Какие вопросы мне не следует задавать здесь? в FAQ, т. е. если вы можете представить целую книгу, которая отвечает на ваш вопрос, вы спрашиваете слишком много .
Марк Бут

Ответы:

5

Это звучит как переводчик. Похоже, вы беспокоитесь о реализации больше, чем о детальной функциональности (я только догадываюсь здесь). Этот проект в случае его расширения не является тривиальной задачей. Убедитесь, что вы четко изучили область применения, так как для этого требуется инженерный подход, а не специальный подход к разработке, чтобы получить надежный продукт, а не продукт с 1000 исправлений, который работает только иногда.

Определитесь с синтаксисом и будьте готовы проанализировать его и выполнить необходимые проверки синтаксиса. Эта ссылка может помочь вам в этом: Создайте свой собственный анализатор .

Посмотрите: эта тема затрагивает различные аспекты работы, а также есть хорошие ссылки, которые могут вам помочь (особенно ответ RMK). Создание переводчика языка . Возможно, вы захотите увидеть пример симпатичного проекта, похожего на: Ultimate Programmable Scientific Calculator . Вы можете найти исходный код и рабочую программу для интерпретатора командной строки C # здесь: Командная строка-Реализация-C # -Made-for-Teaching . Использование компилятора для выполнения сложных задач, таких как синтаксический анализ, типизирование переменных и т. Д., Может быть разумным способом избежать сложностей написания всего этого самостоятельно. Также есть опция Mono, которая предоставляет функцию оболочки charp, на которую вы можете взглянуть: CsharpRepl .

Без шансов
источник
Спасибо, ваши ссылки действительно полезны! Поэтому я думаю, что переводчик был бы лучшим выбором, если бы я хотел легко его расширить.
Нини Майклз
Спасибо за отзыв, я думаю, что начинать со ссылки на CodeProject может быть хорошей идеей.
NoChance
2

Если вы не заинтересованы в написании настоящего парсера для себя, я бы посоветовал взглянуть на одну из сред генератора парсера. Для C у вас есть YACC или Bison , но должны быть другие альтернативы для других языков, если вы предпочитаете.

Это устраняет сложности анализа сложных грамматик и позволяет вам сосредоточиться на задаче, которую вы хотите выполнить. Конечно, это может быть излишним для грамматики, которую вы предлагаете в этом вопросе, но, поскольку вы упомянули о возможности расширения до более сложной грамматики позже, по крайней мере, стоит получить некоторое вдохновение от этих структур.

Harald
источник
1
Проблема большинства генераторов синтаксических анализаторов заключается в том, что их артефакты являются статическими и не поддаются расширению. Я думаю, что OP лучше использовать с чем-то вроде механизма правил, где «правила» (ключевые слова и синтаксис) хранятся в гибкой структуре данных и оцениваются после каждого ввода.
TMN
2

То, что вы описываете, очень близко к языку стека .

Например, в Факторе, что вы описываете, будет сделано как

1
2 +
7 *
even? not

Или вы можете определить свои собственные слова, а затем использовать их, как

: add ( x y -- sum ) + ;
: multiply ( x y -- product ) * ;
: odd? ( n -- ? ) even? not ;

С этими определениями приведенный выше пример становится

1
2 add
7 multiply
odd?

Обычно языки стека разбираются тривиально, потому что они используют отдельные слова, разделенные пробелом. Я предлагаю вам взглянуть на фактор - это может быть именно то, что вы хотите. Должно быть легко определить слова, которые выполняют необходимую вам обработку.

РЕДАКТИРОВАТЬ : Если вы действительно хотите создать похожий язык, я предлагаю вам поиграть с одним из них в любом случае. Разбор языка стека тривиален - вы разбиваете пробелы, и наивная реализация обработки проста: вам просто нужно позаботиться о том, что происходит в стеке.

Andrea
источник
Это звучит довольно легко, и это хорошее место для начала. Спасибо!
Нини Майклз
1

Но если мне нужна расширяемость, как мне нужно реализовать эту функциональность?

Ты не должен. Расширяемость создает много сложностей за очень небольшой выигрыш. Тем не менее, вам нужно будет подключить существующее состояние. Способ просмотра состояния, изменения состояния и предоставления механизма для возврата других результатов (печать на экран). Вам нужно, чтобы основной код обнаруживал модули, загружал их и отправлял им команды.

Я использую шаблон команды?

Вы можете, но это, вероятно, не подходит.

Вы не собираетесь брать весь ввод и отправлять его для обработки, но вместо этого анализируете ввод, отправляете его правильному обработчику и позволяете ему выполнять свою работу. Команда не меняется в этом общении; так что никакой шаблон команды.

Создаю ли я простой парсер / интерпретатор для языка?

Вам нужно что-то, чтобы справиться с разбиением входа на токены. Для расширяемого решения вы, вероятно, не будете делать намного больше. Для четко определенного решения наличие полного дерева разбора обеспечит лучшую производительность, обработку ошибок и возможность отладки.

а точнее список (чисел) процессора

Тогда, возможно, вам стоит взглянуть на язык LISt Processing . Сопоставление кода и данных должно хорошо соответствовать тому, что вы описываете.

Telastyn
источник
Спасибо за предложения. Что касается LISP, я знаком с ним и даже больше знаком с Haskell, который вдохновил меня на эту идею. Однако, хотя я, возможно, немного изобретаю колесо, я хочу испачкать руки при обработке команд и их интерпретации. Так что у него также есть образовательная цель помимо фактической «обработки списка» :)
Нини Майклз
Конечно, @NiniMichaels, но в плане дизайна для расширяемости использование организации / цепочки кода / данных lisp не является плохим вариантом.
Теластин