2012-10-28 3 views
2

저는 현재 부스트 스피릿에 관심이 있으며 뭔가를 구축하려고합니다. Spirit을 사용하여 C++에서 const와 같은 것을 구현할 수 있습니까? 예를 들어 사용자는 다음과 같은 항목을 정의합니다.Boost Spirit에 const를 어떻게 구현할 수 있습니까?

constant var PROG_LANG="Java"; 

"constant var"는 이상하게 보입니다.하지만 받아 들일 만하지만 아이디어가 있습니다. 나는 인터넷을 수색했으나 그것에 대해 아무 것도 발견 할 수 없었다. 내가 제대로 질문을하지 않는

+0

당신 ** 알고있다 **'const' 키워드있어 C++에서는 그렇습니까? –

+0

물론 나는이 질문과 관련이 있는지 어떻게 알 수 있습니까? 어떻게 내 작은 언어로 상수를 구현할 수 있습니까? –

+1

@userXXX 아, 그래서 당신은 당신의 언어에 대해 묻고 있습니다! 이 캐스케이프에서는 컴파일러에서'const' 값에 대한 할당을 금지하는 체크를 구현합니다. –

답변

3

1,239,382,은 무엇 bigboss에게하는 것은

만 나는 의미 조치없이 할 것 :)했다 - 그것은 ... 훨씬 덜 장황 (도 Boost Spirit: "Semantic actions are evil"? 참조) 만들기 : 전부

vdef = 
    ("constant" >> attr(true) | attr(false)) >> 
    "var" >> identifier >> '=' >> identifier_value >> ';' ; 

. 기본값 (누락 된 constant 키워드)을 설명하기 위해 qi::attr을 사용합니다. 여기

는 출력 전체 데모입니다 :

http://liveworkspace.org/code/c9e4bef100d2249eb4d4b88205f85c4b

출력 :

parse success: 'var myvariable = "has some value";' 
data: false;myvariable;has some value; 
parse success: 'constant var myvariable = "has some value";' 
data: true;myvariable;has some value; 

코드 :

#include <boost/fusion/adapted.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/karma.hpp> 

namespace qi = boost::spirit::qi; 
namespace karma = boost::spirit::karma; 
namespace phx = boost::phoenix; 

struct var_definition { 
    bool is_constant; 
    std::string name; 
    std::string value; 

    var_definition() : is_constant(false) {} 
}; 

BOOST_FUSION_ADAPT_STRUCT(var_definition, (bool, is_constant)(std::string, name)(std::string, value)) 


void doParse(const std::string& input) 
{ 
    typedef std::string::const_iterator It; 

    qi::rule<It, std::string()> identifier, identifier_value; 
    qi::rule<It, var_definition(), qi::space_type> vdef; 

    { 
     using namespace qi; 

     identifier_value = '"' >> lexeme [ +~char_('"') ] > '"'; 
     identifier  = lexeme [ +graph ]; 
     vdef    = 
      ("constant" >> attr(true) | attr(false)) >> 
      "var" >> identifier >> '=' >> identifier_value >> ';' ; 
    } 

    var_definition data; 

    It f(std::begin(input)), l(std::end(input)); 
    bool ok = qi::phrase_parse(f,l,vdef,qi::space,data); 
    if (ok) 
    { 
     std::cout << "parse success: '" << input << "'\n"; 
     std::cout << "data: " << karma::format_delimited(karma::auto_, ';', data) << "\n"; 
    } 
} 

int main() 
{ 
    doParse("var myvariable = \"has some value\";"); 
    doParse("constant var myvariable = \"has some value\";"); 
} 
+0

답장을 보내 주셔서 감사합니다. 나는 집에 도착한 후 이것을 적용하고 답을 수락 할 것입니다. 당신은 제 2의 질문에 대답하고 있습니다. (나는 매일 과제 때문에 정신을 바라 볼 수 없다) 나는 5 번이나 투표 할 수 있기를 바란다. 다시 한 번 감사드립니다. –

+0

그리고 어떻게 정신 전문가가 되었습니까? 나는 모든 제나라의 설명서를 읽고 예제를보고 있지만 어려운 예제를 이해하는 데 어려움을 겪고 있습니까? 의견 있으십니까? –

+0

@ user1662800 필자는 필자가 필요할 때 설명서를 읽음으로써 기본적으로 배웠다. 그리고 나서 많은 연습을했습니다. (기본적으로 모든 파싱 필요에 대해 Spirit을 사용했습니다. 가장 적합한 방법은 아니지만). 나는 그 예들에 어떤 관심도 지불하지 않았다는 것을 인정해야한다. 그래서 나는 그들이 얼마나 '힘든'것인지 모른다. – sehe

1

, spirit은 파서이며 그것은 단지 그것을 구문 분석 할 수 constant의 의미와는 아무 상관이없는,하지만 당신은 constant 같은 옵션 변수를 구문 분석 의미한다면 그것은 뭔가 줄 수 있습니다 : 물론

namespace qi = boost::spirit::qi; 
namespace phx = boost::phoenix; 

typedef std::string::const_iterator it; 
struct var_definition { 
    bool is_constant; 
    std::string name; 
    std::string value; 
    var_definition() : is_constant(false) {} 
}; 
qi::rule<it, std::string()> identifier; 
qi::rule<it, std::string()> identifier_value; 
qi::rule<it, var_definition(), boost::spirit::ascii::space_type> vdef; 

void mark_var_as_constant(var_definition& vd) {vd.is_constant=true;} 
void set_var_name(var_definition& vd, std::string const& val) {vd.name=val;} 
void set_var_value(var_definition& vd, std::string const& val) {vd.value=val;} 

vdef %= 
    -qi::lit("constant")[phx::bind(mark_var_as_constant, qi::_val)] >> 
    qi::lit("var") >> 
    identifier[phx::bind(set_var_name, qi::_val, qi::_1)] >> 
    qi::char_('=') >> 
    identifier_value[phx::bind(set_var_value, qi::_val, qi::_1)] >> 
    qi::char_(';'); 

가 다른 방법으로는, 예를 들어, 다음과 같습니다

(qi::lit("constant")[phx::bind(mark_var_as_constant, qi::_val)] | qi::eps) 

그리고 가장 쉬운 방법은 다음과 같습니다

+0

당신의'vdef' 규칙은 문제가 있습니다 :'char_' 표현식은 모두 리터럴이어야하고/또는 일반 규칙 할당 (_auto-rule_'operator % ='대신'operator =')이 사용되어야합니다. (phoenix와의 모든 수동 바인딩없이 이것을 작성하는 좀 더 간결한 방법은 내 대답을 참조하십시오). – sehe

관련 문제