Я хочу создать простое приложение для проверки концепции (REPL), которое принимает число, а затем обрабатывает команды для этого числа.
Пример: я начинаю с 1. Затем я пишу " add 2
", это дает мне 3. Затем я пишу " multiply 7
", это дает мне 21. Затем я хочу знать, если это простое число, поэтому я пишу " is prime
" (на текущем номере - 21), это дает мне ложь. " is odd
" дал бы мне правду. И так далее.
Теперь, для простого приложения с несколькими командами, даже простое switch
будет подходить для обработки команд. Но если мне нужна расширяемость, как мне нужно реализовать эту функциональность? Я использую шаблон команды? Создаю ли я простой парсер / интерпретатор для языка? Что делать, если я хочу более сложные команды, такие как " multiply 5 until >200
"? Что может быть простым способом расширить его (добавить новые команды) без перекомпиляции?
Изменить: чтобы прояснить некоторые вещи, моя конечная цель будет не сделать что-то похожее на WolframAlpha, а скорее процессор списка (чисел). Но сначала я хочу начать медленно (с одного номера).
Я имею в виду нечто похожее на то, как можно использовать Haskell для обработки списков, но очень простая версия. Мне интересно, будет ли достаточно что-то вроде шаблона команды (или его эквивалента), или мне нужно будет создать новый мини-язык и парсер для этого для достижения моих целей?
Edit2: Спасибо за все ответы, все были очень полезны для меня, но Эммад Карим помог мне больше всего, поэтому я выберу его в качестве ответа. Еще раз спасибо!
источник
Ответы:
Это звучит как переводчик. Похоже, вы беспокоитесь о реализации больше, чем о детальной функциональности (я только догадываюсь здесь). Этот проект в случае его расширения не является тривиальной задачей. Убедитесь, что вы четко изучили область применения, так как для этого требуется инженерный подход, а не специальный подход к разработке, чтобы получить надежный продукт, а не продукт с 1000 исправлений, который работает только иногда.
Определитесь с синтаксисом и будьте готовы проанализировать его и выполнить необходимые проверки синтаксиса. Эта ссылка может помочь вам в этом: Создайте свой собственный анализатор .
Посмотрите: эта тема затрагивает различные аспекты работы, а также есть хорошие ссылки, которые могут вам помочь (особенно ответ RMK). Создание переводчика языка . Возможно, вы захотите увидеть пример симпатичного проекта, похожего на: Ultimate Programmable Scientific Calculator . Вы можете найти исходный код и рабочую программу для интерпретатора командной строки C # здесь: Командная строка-Реализация-C # -Made-for-Teaching . Использование компилятора для выполнения сложных задач, таких как синтаксический анализ, типизирование переменных и т. Д., Может быть разумным способом избежать сложностей написания всего этого самостоятельно. Также есть опция Mono, которая предоставляет функцию оболочки charp, на которую вы можете взглянуть: CsharpRepl .
источник
Если вы не заинтересованы в написании настоящего парсера для себя, я бы посоветовал взглянуть на одну из сред генератора парсера. Для C у вас есть YACC или Bison , но должны быть другие альтернативы для других языков, если вы предпочитаете.
Это устраняет сложности анализа сложных грамматик и позволяет вам сосредоточиться на задаче, которую вы хотите выполнить. Конечно, это может быть излишним для грамматики, которую вы предлагаете в этом вопросе, но, поскольку вы упомянули о возможности расширения до более сложной грамматики позже, по крайней мере, стоит получить некоторое вдохновение от этих структур.
источник
То, что вы описываете, очень близко к языку стека .
Например, в Факторе, что вы описываете, будет сделано как
Или вы можете определить свои собственные слова, а затем использовать их, как
С этими определениями приведенный выше пример становится
Обычно языки стека разбираются тривиально, потому что они используют отдельные слова, разделенные пробелом. Я предлагаю вам взглянуть на фактор - это может быть именно то, что вы хотите. Должно быть легко определить слова, которые выполняют необходимую вам обработку.
РЕДАКТИРОВАТЬ : Если вы действительно хотите создать похожий язык, я предлагаю вам поиграть с одним из них в любом случае. Разбор языка стека тривиален - вы разбиваете пробелы, и наивная реализация обработки проста: вам просто нужно позаботиться о том, что происходит в стеке.
источник
Ты не должен. Расширяемость создает много сложностей за очень небольшой выигрыш. Тем не менее, вам нужно будет подключить существующее состояние. Способ просмотра состояния, изменения состояния и предоставления механизма для возврата других результатов (печать на экран). Вам нужно, чтобы основной код обнаруживал модули, загружал их и отправлял им команды.
Вы можете, но это, вероятно, не подходит.
Вы не собираетесь брать весь ввод и отправлять его для обработки, но вместо этого анализируете ввод, отправляете его правильному обработчику и позволяете ему выполнять свою работу. Команда не меняется в этом общении; так что никакой шаблон команды.
Вам нужно что-то, чтобы справиться с разбиением входа на токены. Для расширяемого решения вы, вероятно, не будете делать намного больше. Для четко определенного решения наличие полного дерева разбора обеспечит лучшую производительность, обработку ошибок и возможность отладки.
Тогда, возможно, вам стоит взглянуть на язык LISt Processing . Сопоставление кода и данных должно хорошо соответствовать тому, что вы описываете.
источник