2010-03-31 3 views
3

Я использую следующий код консоли win32, чтобы попытаться разобрать грамматику B B, встроенную в C++, используя шаблон грамматики Boost Spirit. Я относительно новый пользователь Boost. Код компилируется, но когда я запускаю .exe-файл, созданный VC++ 2008, программа частично анализирует входной файл. Я считаю, что проблема связана с моим определением грамматики или функциями, закрепленными в качестве семантических атак.Помощь с Boost Grammar

код приведен ниже:

// BIFAnalyser.cpp : Defines the entry point for the console application. 
// 
// 
/*============================================================================= 
    Copyright (c) Temitope Jos Onunkun 2010 
    http://www.dcs.kcl.ac.uk/pg/onun/ 

    Use, modification and distribution is subject to the Boost Software 
    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 
    http://www.boost.org/LICENSE_1_0.txt) 
=============================================================================*/ 
//////////////////////////////////////////////////////////////////////////// 
//                  // 
// B Machine parser using the Boost "Grammar" and "Semantic Actions". // 
//                  // 
//////////////////////////////////////////////////////////////////////////// 

#include <boost/spirit/core.hpp> 
#include <boost/tokenizer.hpp> 
#include <iostream> 
#include <string> 
#include <fstream> 
#include <vector> 
#include <utility> 

/////////////////////////////////////////////////////////////////////////////////////////// 
using namespace std; 
using namespace boost::spirit; 

/////////////////////////////////////////////////////////////////////////////////////////// 
// 
// Semantic actions 
// 
//////////////////////////////////////////////////////////////////////////// 
vector<string> strVect; 


namespace 
{ 
//semantic action function on individual lexeme 
    void do_noint(char const* str, char const* end) 
    { 
     string s(str, end); 

    if(atoi(str)) 
    { 
    ; 
    } 
    else 
    { 
    strVect.push_back(s); 
     cout << "PUSH(" << s << ')' << endl; 
    } 
    } 

//semantic action function on addition of lexemes 
void do_add(char const*, char const*)  
{ 
cout << "ADD" << endl; 
for(vector<string>::iterator vi = strVect.begin(); vi < strVect.end(); ++vi) 
    cout << *vi << " "; 
} 

//semantic action function on subtraction of lexemes 
void do_subt(char const*, char const*) 
{ 
cout << "SUBTRACT" << endl; 
for(vector<string>::iterator vi = strVect.begin(); vi < strVect.end(); ++vi) 
    cout << *vi << " "; 
} 

//semantic action function on multiplication of lexemes 
void do_mult(char const*, char const*) 
{ 
cout << "\nMULTIPLY" << endl; 
for(vector<string>::iterator vi = strVect.begin(); vi < strVect.end(); ++vi) 
    cout << *vi << " "; 
cout << "\n"; 
} 

//semantic action function on division of lexemes 
void do_div(char const*, char const*)  
{ 
cout << "\nDIVIDE" << endl; 
for(vector<string>::iterator vi = strVect.begin(); vi < strVect.end(); ++vi) 
    cout << *vi << " "; 
} 

//semantic action function on simple substitution 
void do_sSubst(char const* str, char const* end)  
{ 
    string s(str, end); 

    //use boost tokenizer to break down tokens 
typedef boost::tokenizer<boost::char_separator<char> > Tokenizer; 
boost::char_separator<char> sep("-+/*:=()"); // default char separator 
     Tokenizer tok(s, sep); 
Tokenizer::iterator tok_iter = tok.begin(); 

pair<string, string > dependency; //create a pair object for dependencies 

    //save first variable token in simple substitution 
dependency.first = *tok.begin(); 

    //create a vector object to store all tokens 
vector<string> dx; 
    // 
     for(; tok_iter != tok.end(); ++tok_iter) //save all tokens in vector 
    { 
    dx.push_back(*tok_iter); 
    } 

vector<string> d_hat; //stores set of dependency pairs 

string dep; //pairs variables as string object 



for(int unsigned i=1; i < dx.size()-1; i++) 
{ 
     dependency.second = dx.at(i); 
    dep = dependency.first + "|->" + dependency.second + " "; 
    d_hat.push_back(dep); 
} 


cout << "PUSH(" << s << ')' << endl; 

for(int unsigned i=0; i < d_hat.size(); i++) 
    cout <<"\n...\n" << d_hat.at(i) << " "; 

cout << "\nSIMPLE SUBSTITUTION\n"; 

} 

    //semantic action function on multiple substitution 
void do_mSubst(char const* str, char const* end)  
{ 
    string s(str, end); 

    //use boost tokenizer to break down tokens 
    typedef boost::tokenizer<boost::char_separator<char> > Tok; 
    boost::char_separator<char> sep("-+/*:=()"); // default char separator 
    Tok tok(s, sep); 
    Tok::iterator tok_iter = tok.begin(); 

// string start = *tok.begin(); 

    vector<string> mx; 

    for(; tok_iter != tok.end(); ++tok_iter) //save all tokens in vector 
    { 
mx.push_back(*tok_iter); 
    } 

mx.push_back("END\n"); //add a marker "end" 

for(unsigned int i=0; i<mx.size(); i++) 
{ 
    // if(mx.at(i) == "END" || mx.at(i) == "||") 
    // break; 
    // else if(mx.at(i) == "||") 
    // do_sSubst(str, end); 
    // else 
    // { 
    // do_sSubst(str, end); 

    // } 

    cout << "\nTokens ... " << mx.at(i) << " "; 
} 


    cout << "PUSH(" << s << ')' << endl; 
    cout << "MULTIPLE SUBSTITUTION\n"; 
} 

} 

//////////////////////////////////////////////////////////////////////////// 
// 
// Simple Substitution Grammar 
// 
//////////////////////////////////////////////////////////////////////////// 

// Simple substitution grammar parser with integer values removed 
struct Substitution : public grammar<Substitution> 
{ 
    template <typename ScannerT> 
    struct definition 
    { 
     definition(Substitution const&) 
     { 
    multi_subst 
     = (simple_subst [&do_mSubst] 
     >> +(str_p("||") >> simple_subst [&do_mSubst]) 
     ) 
     ; 

    simple_subst 
    = (Identifier >> str_p(":=") 
>> expression)[&do_sSubst] 
     ; 

    Identifier 
    = alpha_p >> +alnum_p//[do_noint] 
    ; 

      expression 
        = term 
        >> *( ('+' >> term)[&do_add] 
         | ('-' >> term)[&do_subt] 
         ) 
        ; 

      term 
        = factor 
        >> *( ('*' >> factor)[&do_mult] 
         | ('/' >> factor)[&do_div] 
         ) 
        ; 

      factor 
       = lexeme_d[((alpha_p >> +alnum_p) | +digit_p)[&do_noint]] 
       | '(' >> expression >> ')' 
       | ('+' >> factor) 
       ; 
     } 
rule<ScannerT> expression, term, factor, Identifier, simple_subst, 
    multi_subst ; 

     rule<ScannerT> const& 
     start() const 
    { 
    return multi_subst; 
    } 
    }; 
}; 

//////////////////////////////////////////////////////////////////////////// 
// 
// Main program 
// 
//////////////////////////////////////////////////////////////////////////// 
int 
main() 
{ 
    cout << "************************************************************\n\n"; 
    cout << "\t\t...Machine Parser...\n\n"; 
    cout << "************************************************************\n\n"; 
    // cout << "Type an expression...or [q or Q] to quit\n\n"; 

//prompt for file name to be input 
cout << "Please enter a filename...or [q or Q] to quit:\n\n "; 
char strFilename[256]; //file name store as a string object 
cin >> strFilename; 

ifstream inFile(strFilename); // opens file object for reading 
    //output file for truncated machine (operations only) 


Substitution elementary_subst; // Simple substitution parser object 

string str, next; 
// inFile.open(strFilename); 
while (inFile >> str) 
    { 
    getline(cin, next); 

    str += next; 

     if (str.empty() || str[0] == 'q' || str[0] == 'Q') 
      break; 

     parse_info<> info = parse(str.c_str(), elementary_subst, space_p); 

     if (info.full) 
     { 
      cout << "\n-------------------------\n"; 
      cout << "Parsing succeeded\n"; 
      cout << "\n-------------------------\n"; 
     } 
     else 
     { 
      cout << "\n-------------------------\n"; 
      cout << "Parsing failed\n"; 
      cout << "stopped at: \": " << info.stop << "\"\n"; 
      cout << "\n-------------------------\n"; 
     } 
    } 
    cout << "Please enter a filename...or [q or Q] to quit\n"; 
    cin >> strFilename; 


    return 0; 
} 

The contents of the file I tried to parse, which I named "mf7.txt" is given below: 

debt:=(LoanRequest+outstandingLoan1)*20 || newDebt := loanammount-paidammount 


The output when I execute the program is: 

************************************************************ 
       ...Machine Parser... 
************************************************************ 
Please enter a filename...or [q or Q] to quit: 
c:\tplat\mf7.txt 
PUSH(LoanRequest) 
PUSH(outstandingLoan1) 
ADD 
LoanRequest outstandingLoan1 
MULTIPLY 
LoanRequest outstandingLoan1 
PUSH(debt:=(LoanRequest+outstandingLoan1)*20) 
... 
debt|->LoanRequest 
... 
debt|->outstandingLoan1 
SIMPLE SUBSTITUTION 
Tokens ... debt 
Tokens ... LoanRequest 
Tokens ... outstandingLoan1 
Tokens ... 20 
Tokens ... END 
PUSH(debt:=(LoanRequest+outstandingLoan1)*20) 
MULTIPLE SUBSTITUTION 
------------------------- 
Parsing failedstopped at: ": " 
------------------------- 

Мое намерение захватить только переменные в файле, который мне удалось сделать вплоть до «||» строка. Очевидно, что программа не анализируется за пределами «||» string во входном файле. Я буду признателен за помощь в исправлении грамматики. SOS, пожалуйста.

+4

Слишком много кода. По возможности попробуйте сократить его до соответствующих частей. – Macke

ответ

4

Я считаю, что все с вашим кодом в порядке. После синтаксического совпадения синтаксический анализ завершится с ошибкой. Причина в том, что функция parse() не выполняет шаг после пропусков (т. Е. Он не вызывает анализатор пропусков после последнего сопоставимого парсера). Самый простой способ обойти это, чтобы присоединять !end_p к вашей грамматике:

parse_info<> info = parse(str.c_str(), elementary_subst >> !end_p, space_p); 

, который заставляет требуемый пропуск и делает, что ваш вход был сопоставляются в полном объеме.

+0

Спасибо hkaiser. Я сделал модификацию: добавление «>>! End_p» к моему объекту грамматики. К сожалению, результат все тот же, что и был. По-видимому, у меня все еще есть проблема либо с определением грамматики, либо с прилагаемыми функциями. – Decmanc04

+0

Ta hkaiser. Я применил ваши предложения и с небольшой модификацией грамматики, теперь он отлично работает, и все переменные захватываются. Ключевая часть продукции является: долг | -> LoanRequest ... долг | -> outstandingLoan1 ... долг | -> outstandingLoan1 SIMPLE ЗАМЕНА PUSH (loanammount) PUSH (paidammount) SUBTRACT PUSH (newDebt: = loanammount-paidammount) ... newDebt | -> loanammount ... newDebt | -> paidammount SIMPLE ЗАМЕНА Хотя пара "долг | -> outstandingLoan1" зависимость дублируется, я должен быть в состоянии исправить это при проверке кода позже. Еще раз СПАСИБО. – Decmanc04

+0

Эй, хакайзер, Боюсь, я снова попал в проблему. После устранения дублирования в зависимости пары "долг | -> outstandingLoan1", я масштабируется до грамматики, чтобы включать в себя, в частности, machine_subst \t \t \t \t = ((simple_subst \t \t \t \t | multi_subst \t \t \t \t | выбор \t \t \t \t | multi_choice \t \t \t \t | выберите \t \t \t \t | условное \t \t \t \t | условно) \t \t \t \t >> * (ch_p (';') >> machine_subst)); и используется «machine_subst» в качестве символа начала. Затем синтаксический анализатор завершился неудачей на "||" еще раз. Когда я изменил символ начала на «multi_subst», он прошел, но мне нужно использовать «machine_subst». – Decmanc04

0

по какой-то причине я не уверен, грамматика правильно разобралась, когда я изменил правило machine_subst на ... "machine_subst = (((simple_subst) | (multi_subst) | (choice) | (multi_choice) | (select) | (conditional) | (preconditional))". Я подозреваю, что каждое из подправил в круглых скобках явно указывает, что параметры находятся между каждым из подправил, а не их частью. Любая идея, почему определение грамматики ведет себя таким образом, будет оценена, но это не критично для моего текущего проекта, так как это работает для меня, как есть.

1

я переработан грамматику следующим образом, и что, кажется, исправили проблему:

Подст = multi_choice | machine_subst ;

 multi_choice 
       = machine_subst 
       >> +(str_p("[]") >> machine_subst) 
       ; 


     machine_subst 
       = ( multi_subst 
       | simple_subst 
       | if_select_pre_subst 
       | unbounded_choice)[&do_machSubst] 
       ; 

... ...

multi_subst = (simple_subst

+ (str_p ("||") >> simple_subst) ) [& do_mSubst] ;

 simple_subst 
       = (identifier 
       >> str_p(":=") >> arith_expr) [&do_sSubst] 
       ; 

     expression 
       = predicate 
       | logic_expr 
       | arith_expr 
       ; 

     predicate 
       = (logic_expr 
       >> +((str_p("&") >> logic_expr) 
       |  (str_p("OR") >> logic_expr)))[&do_predicate] 
       ; 

     logic_expr 
       = (identifier 
       >> ((str_p("<") >> arith_expr) 
       | (str_p(">") >> arith_expr) 
       | (str_p("/:") >> arith_expr) 
       | (str_p("<:") >> arith_expr) 
       | (str_p("/<:") >> arith_expr) 
       | (str_p("<<:") >> arith_expr) 
       | (str_p("/<<:") >> arith_expr) 
       | (str_p("<=") >> arith_expr) 
       | (str_p("=") >> arith_expr) 
       | (str_p(">=") >> arith_expr) 
       | (str_p("=>") >> arith_expr)) 
       ) [&do_logicExpr] 
       ; 

... ... я теперь использовать правило запуска "Подст" для файлов f1.txt и f2.txt и "выражение" для f3.txt и f4.txt.

начало() const { return subst; // return machine_subst; // return expression; // return if_select_pre_subst; // return multi_choice; // return unbounded_choice; }

Я все еще строю грамматику, поэтому, если у меня возникнут какие-либо другие проблемы, я отправлю ее.

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