2013-04-26 3 views
-1

Я создаю CLI и у меня возникают проблемы при разборе кода:C++ - Parse like C++?

io.print("Hello World!"); 

Как бы я идти о разборе что-то вроде этого, не оскорбительно, используя, если операторы для разбора через код полукокса по полукокса?

Я хочу консоль, чтобы напечатать это на окне:

Hello World! 
+1

Обычно вы начинаете с написания токенизатора (или нахождения подходящего) и грамматики, которая объединяет токены в AST или иначе «понимает» синтаксис, а затем оценивает этот синтаксис. – Useless

+0

Я написал свой токенизатор, используя строковый вектор и строковые теги. Так что все, что я могу сделать, это использовать инструкции IF? – hCon

+0

Нет, грамматика - это не просто утверждения 'if'. Вы можете использовать что-то вроде ANTLR напрямую или искать что-то вроде «анализатора грамматики C++». – Useless

ответ

0

Это как бы вы написать HelloWorld в C++:

#include <iostream> 

int main() { 
    std::cout << "Hello World!"; 
    return 0; 
} 

строка будет анализироваться во время компиляции, так что нет необходимости беспокоиться о том, что он напечатан неэффективно.

Если я неправильно понял ваш вопрос (я знаю только CLI для интерфейса командной строки), и вы действительно хотите проанализировать исходный код C++. Я предлагаю вам прочитать учебное пособие по поводу инструмента, такого как yacc, и начать с грамматики C с открытым исходным кодом.

Это хороший Yacc учебник: http://www.ds9a.nl/lex-yacc/cvs/lex-yacc-howto.html

Это является хорошей отправной точкой для грамматики: http://www.computing.surrey.ac.uk/research/dsrg/fog/CxxGrammar.y

+2

Я думаю, он пытается написать программу на C++, которая анализирует и выполняет код на другом (вероятно, ad-hoc) языке. – delnan

2

Технически это решает проблему, как описано:

std::map< std::string, std::function<void()> > program_map; 

void define_programs() { 
    program_map[ "io.print("Hello World!");\n" ] = []{ 
    std::cout << "Hello World!\n"; 
    }; 
    program_map[ "io.print("Goodbye World!");\n" ] = []{ 
    std::cout << "Goodbye World!\n"; 
    }; 
}; 

int main() { 
    // load parser: 
    define_programs(); 
    // read program from user: 
    std::string s; 
    std::cin >> s; 
    // compile and execute: 
    if (program_map.find(s) != program_map.end()) { 
    (*program_map.find(s))(); 
    } else { 
    std::cout << "ERROR: unknown program.\n"; 
    } 
} 

, но это вероятно, не решает проблему, которую вы хотите решить.

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

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

Разработка грамматики и запись лексера (или обучение предварительно написанному лексеру) для вашей грамматики должны идти рука об руку.

Когда я проектирую языки игрушек, я обычно делаю их LISP такими, потому что LISP, как и языки, очень прост в работе. Таким образом, у вас есть инициализатор команды (, команда, список аргументов (который может быть более поздним ( 'd), и команда выполняется, когда вы достигаете соответствия ).

Так эквивалент кода будет:

(io print "Hello World") 

и теперь у меня есть команда io (и экземпляры объектов будут виды «команд») с помощью метода печати (который он считывает из слота-) и аргументы к указанному методу «Hello World». Результатом этого, если бы я чувствовал себя функциональным, была бы программа, которая напечатала Hello World - если нет, это будет делать это как побочный эффект и вернуть либо код ошибки, либо ничего.

Я бы написал среду вокруг нее, которая определяет некоторые команды (в том числе «сделать объект»), возможно, какой-то синтаксис цитирования (чтобы я мог определить lambdas) и т. Д. Я бы закончил с языком, который представляет собой плохо разработанную, субоптимальную, ограниченную реализацию небольшой части обычного lisp, которая является традиционной.

Только после того, как я смог бы сделать что-то вроде выше, я бы рассмотрел возможность написания парсера для более сложного анализа языка, такого как C/C++. И даже тогда я сначала переписал вышеупомянутый игрушечный язык в рамки lexing/parsing, а затем напишу свой язык на C/C++ в той же структуре.

+0

+1, хороший ответ. – JBentley