[C++] Własny skrypter

Czepek221

Użytkownik
Dołączył
Maj 18, 2010
Posty
26
Witam, próbuję napisać własny system skryptów, lecz utknąłem w dość dziwnej (być może banalnie prostej sytuacji). Problem polega na tym, że nie mam pojęcia jak uwzględniać odstępy w argumentach, np. : jakaśFunkcja(Wiadomość o dwóch wyrazach, Tytuł wiadomości);

Kod:
#include <cstring>
#include <cstdio>
#include <list>
#include <Windows.h>
int main()
{
	std::list<char*> argHandler;
	char stringToParse[] = "script messagebox(Wiadomość_jego_mać,Tytuł_message_boxa)";
	char* buffer = strtok(stringToParse, " ");
	while(buffer != NULL)
	{
		buffer = strtok(NULL, " ");
		if(buffer != NULL)
			argHandler.push_back(buffer);
	};

	std::list<char*>::iterator it;
	for(it = argHandler.begin(); it != argHandler.end(); it++)
	{
		char fullCommand[255];
		sprintf(fullCommand, "%s", *it);
		if(strcmp(*it, "messagebox") > 0)
		{
			char arg1[255], arg2[255];
			char* buf = strtok(fullCommand, "(,)");
			buf = strtok(NULL, "(,)");
			strcpy(arg1, buf);
			buf = strtok(NULL, "(,)");
			strcpy(arg2, buf);
			MessageBoxA(HWND_DESKTOP, arg1, arg2, MB_OK | MB_ICONINFORMATION);
			continue;
		}
	}
	return 0;
}

Pozdrawiam, Czepek!
 

grzonu

Były Moderator
Dołączył
Grudzień 26, 2006
Posty
1390
Zainteresuj się algorytmem ONP ja przy jego pomocy pisałem aplikacje rysujaca funkcje i jej pochodne. I tego algorytmu uzywalem do przetwarzania wyrazen arytmetycznych typu x+2x^2*sin(x*cos(x))
 

RobertG

Użytkownik
Dołączył
Styczeń 3, 2007
Posty
391
Do tworzenia języków, czy też ogólnie parsowania danych o określonej budowie są już gotowe narzędzia i biblioteki, robienie tego samemu to wynajdowanie koła od nowa (i dużo bicia o ścianę). Najlepiej, by stringi w parsowanym tekście brać w cudzysłowy (tak robią praktycznie wszytkie języki programowania i np. część składni XMLa, bez tego parsowanie pliku jest dużo cięższe).

W Spiricie (biblioteka z Boosta do parsowania gramatyk) można by to wtedy rozwiązać tak (zobacz na przykłady, teraz ilość spacji niema znaczenia):

Kod:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>


#include <iostream>
#include <string>


using namespace std;


namespace client
{
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;


    struct prompt
    {
        std::string arg1;
        std::string arg2;
    };
}


BOOST_FUSION_ADAPT_STRUCT(
    client::prompt,
    (std::string, arg1)
    (std::string, arg2)
)


namespace client
{
    template <typename Iterator>
    struct prompt_parser : qi::grammar<Iterator, prompt(), ascii::space_type>
    {
        prompt_parser() : prompt_parser::base_type(start)
        {
            using qi::lit;
            using qi::lexeme;
            using ascii::char_;


            quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];


            start %=
                lit("messagebox")
                >> '('
                >>  quoted_string >> ','
                >>  quoted_string
                >>  ')'
                ;
        }


        qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
        qi::rule<Iterator, prompt(), ascii::space_type> start;
    };
}


int main()
{
    using boost::spirit::ascii::space;
    typedef std::string::const_iterator iterator_type;
    typedef client::prompt_parser<iterator_type> employee_parser;


    employee_parser g; // Our grammar
    
    {
        client::prompt emp;
        string str = "messagebox(\"ala\", \"janusz\")";
        std::string::const_iterator iter = str.begin();
        std::string::const_iterator end = str.end();
        bool r = phrase_parse(iter, end, g, space, emp);
        if (r && iter == end)
        {
            cout << "okienko z: <" << emp.arg1 << "> i <" << emp.arg2 << ">" << endl;
        }
        else {
            cout << "parsowanie sie nie powiodlo" << endl;
        }
    }


    // inny przyklad
    {
        client::prompt emp;
        string str = "       messagebox  (  \"zielone i czarne\",\"hello\"  )         ";
        std::string::const_iterator iter = str.begin();
        std::string::const_iterator end = str.end();
        bool r = phrase_parse(iter, end, g, space, emp);
        if (r && iter == end)
        {
            cout << "okienko z: <" << emp.arg1 << "> i <" << emp.arg2 << ">" << endl;
        }
        else {
            cout << "parsowanie sie nie powiodlo" << endl;
        }
    }


}

Kod:
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf"/usr/bin/make"  -f nbproject/Makefile-Debug.mk dist/Debug/GNU-MacOSX/yellowlang
mkdir -p build/Debug/GNU-MacOSX
rm -f build/Debug/GNU-MacOSX/main.o.d
g++    -c -g -I/opt/local/include -MMD -MP -MF build/Debug/GNU-MacOSX/main.o.d -o build/Debug/GNU-MacOSX/main.o main.cpp
mkdir -p dist/Debug/GNU-MacOSX
g++     -L/opt/local/lib -lboost_program_options -o dist/Debug/GNU-MacOSX/yellowlang build/Debug/GNU-MacOSX/main.o build/Debug/GNU-MacOSX/Parser.o -L/opt/local/var/macports/software/boost/1.46.1_0/opt/local/include 


BUILD SUCCESSFUL (total time: 14s)

Kod:
okienko z: <ala> i <janusz>
okienko z: <zielone i czarne> i <hello>


RUN SUCCESSFUL (total time: 153ms)

Powyższy przykład to przerobiony na szybko kod z dokumentacji Spirita: http://www.boost.org/doc/libs/1_46_0/libs/spirit/example/qi/employee.cpp

W Haskellu dość ciekawą biblioteką ku temu jest Parsec, niestety jego dokumentacja pozostawia bardzo dużo do życzenia.

W C można się posłużyć yacc + lex.
 
Ostatnia edycja:

Czepek221

Użytkownik
Dołączył
Maj 18, 2010
Posty
26
Boost wydaje się być najlepszym rozwiązaniem, dzięki za podpowiedź. Całkiem zapomniałem o dużych opcjach tej biblioteki, a na dodatek jeszcze portable.

Pozdrawiam, Czepek!
 
Do góry Bottom