2013-03-08 2 views
1

Я собираюсь создать инструмент командной строки. Я хочу, чтобы пользователь вводил текст/строку (функция/команда). Затем инструмент My преобразует эту строку в функцию/переменную C++.Как преобразовать входную строку в функцию()

[Они будут работать мои пользовательские данные типа, мою собственную функцию, не работает система функция]

Ex: Тип пользователя

>> myVar = c(123,456,789) 

Мой инструмент будет знать, что myVar это имя переменной , и c(123,456,789) - это массив из integer. И Он преобразует эти строки в нечто вроде этого:

int myVar[] = {123,456,789}; 

и пользователь может вызвать функцию тоже:

Вход:

>> myPrintf(myVar[0]); 

Выход

<< 123 

И мое решение: я стро класс, который может быть, как это:

public class cVariable 
{ 
    public string varName; // the variable name 
    private varType; // the variable data-type 
    public string varData; // the value of this variable 
} 

И я буду использовать if/else заявления, чтобы узнать, какие данные типа/функции я должен работать.

Но я думаю, что этот путь не очень хорош.

+1

Вы пытаетесь построить компилятор. Удачи. – SLaks

+0

Рассмотрите возможность использования LLVM. – SLaks

+0

Ваш единственный фактический вопрос, похоже, называется «как преобразовать входную строку в функцию()?». Я рекомендую библиотеку 'boost :: spirit' - вам будет сложно научиться, но как только вы это поймете, вы сможете более легко и более совершенствовать свою программу. Если вы хотите быстро начать, использование регулярных выражений может помочь вам проверить назначение и вызовы функций, извлечь значения аргументов и т. Д. Еще более базовые, вы можете использовать 'sscanf()'. «Я думаю, что этот путь не очень хорош» - если вы объясните свои проблемы, люди могут прокомментировать. Наиболее очевидный комментарий: используйте ruby ​​/ perl/etc. –

ответ

3

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

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

Если вам ознакомиться со следующими темами вы будете иметь представление о том, сколько вариантов доступны для вас:

  • Компиляция & Linking
    • Dynamic Linking
  • Отражение
  • Языки программирования и скрипты
    • Язык Bindings
  • Генерация кода

Для вашей программы, чтобы иметь знания о своей собственной структуры и идентификаторов языка требует функцию под названием Reflection. Стандарт C++ не имеет этой функции (в то время как многие другие). К моменту компиляции кода уже нет строковых идентификаторов для ваших функций, типов или аргументов.

См следующий вопрос для обсуждения отражения типа поведения в C/C++: How can I add reflection to a C++ application?

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

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

Если вы открыты для использования существующего языка сценариев, вы можете исследовать генерацию привязок к коду C++ с указанного языка. Вот некоторые ресурсы для Python, например: http://wiki.python.org/moin/IntegratingPythonWithOtherLanguages.

+0

Спасибо за ваши ключевые слова Они действительно полезны. Я не очень разбираюсь в Reflection, Dynamic Linking ... Думаю, мне сейчас нужно провести исследование. спасибо – hungdoan

2

Написание собственного языка - довольно сложная задача, если вы намереваетесь делать что-то относительно полное. Тысячи строк кода, безусловно, возможны. Я принимал участие в различных формах этого за свои 30 лет профессиональной и хобби жизни - от написания простого анализатора команд в отладчике или аналогичного достаточно хорошо работающего «мини-базового» интерпретатора и небольшого интерпретатора Lisp. Я также создал много «псевдоязыков», где текстовый файл используется как вход для программы, но это не полноценный язык программирования - существует только ограниченный набор переменных.

Еще одна вещь, которую я сделал довольно много, - это «программирование на основе таблиц», где фактический «код» встроен в программу в виде таблиц.

Во всех этих случаях существуют различные формы «У меня есть некоторый ввод/данные, которые я хочу перевести в действие по отношению к другому объекту».

Основным механизмом, как вы описали, является сохранение имени и некоторых других данных (таких как тип) в некоторой структуре данных. std::map<std::string, cVariable> будет одним из способов относительно легко получить данные из имени (строки) в переменную этого имени.

Вы можете четко сделать то же самое для функций. Разумеется, вы также должны каким-то образом передать аргументы в функцию. Именно то, как вы решаете, это то, что каждый язык должен был решить, и обычно он становится своего рода «стек».

Возможно, у вас есть map<std::string, function>, который переводится от имени к функции - определение функции может содержать некоторую информацию о количестве и типах аргументов, которые выполняет функция.

Для «встроенных» функций, вы можете также иметь тип argc, argv[] подхода типа, где аргументы передаются в cVariable [где один вариант constant или expression], чтобы обеспечить myPrint(myVar[0] + 100), что, конечно, не является истинным переменная, но результат содержимого переменной, добавленной к константе.

Если вы не написали что-то, что действует как калькулятор с переменными, это, вероятно, будет хорошей отправной точкой.

Многие языки типа «сценарий» имеют переменные, которые являются «полиморфными», то есть значение может использоваться как число или как строка без фактического запроса переменной, подлежащей преобразованию.

0

за титул «преобразовать строку в функцию()» вы могли бы добиться этого с указателями на функции:

назначить функцию в соответствии со значением:

int (*p)(char*,...) = printf; 

использовать указатель на функцию вызов функции:

char* str = "hello function pointer"; 
p("say %s", str); 

Но это только половина вашей проблемы, сначала нужно сделать лексический análisis для разбора ввода и acording определенных правил определения того, какими токен (символы, которые составляют язык вашего инструмента командной строки), такие как DIGIT, BRACKETS, ASSIGNMENTS и т. д. Затем вам нужен синтаксический анализатор, который устанавливает правила для значения синтаксиса в ваших командах. Это в основном делается с государственными машинами, но это сложная задача, и я думаю, что вы не хотите ее реализовать самостоятельно? посмотрите на Flex и Bisson инструменты для автоматизации генерации парсера.

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

Смежные вопросы