2014-10-02 2 views
1

Boost Spirit을 사용하여 계산기를 구현하는 방법에 대한 온라인 예제가 많이 있습니다. 예를 들어 this one과 같이 지수 연산자를 추가하는 방법에 대한 대답도 있습니다.부등호 연산자를 사용한 표현 문법 부스트 스피릿을 사용한 단항 부정 연산자

그러나 지수 연산자와 단항 부정 연산자를 조합하면 이러한 예제가 실패합니다.

는 다음과 같은 식을 고려하십시오

-4^2

- (12/3)^2

당신이 대답을해야한다고 생각합니까? 모든 제정신의 수학자는 -16을 대답합니다. 지수 연산은 단항 부정 연산보다 우선하기 때문에.

그러나 웹에서 공유의 예에서 문법 규칙을 구현하는 계산기는 16

그러나이 더욱 놀라운 응답 할 것이다는 Microsoft Excel에서이 수식을 입력하려고합니다. 당신이 얻게 될 것은 16입니다! (감탄 부호, 계승이 아님). 이 Microsoft의 "예외"규칙에 대해서도 note in Wikipedia입니다.

하지만 엔지니어링 애플리케이션을 개발하는 개발자는 물론 받아 들일 수 없습니다. -16이되어야합니다. 그렇지 않으면 비행기가 떨어져 나올 것입니다. 그래서, 문제는 그것을 따라갈 예제 문법 규칙을 조정하는 방법입니다. Excel을 일치하면서, 받아 들일 수,

 definition(calculator const & self) { 
     expression 
      = factor 
      >> *(('+' >> factor)[self.add_op] 
       | ('-' >> factor)[self.sub_op] 
       ) 
      ; 

     factor 
      = powerterm 
      >> *(('*' >> powerterm)[self.mult_op] 
       | ('/' >> powerterm)[self.div_op] 
       ) 
      ; 

      powerterm 
      = term 
      >> *(('^' >> powerterm)[self.exp_op] 
       | ("**" >> powerterm)[self.exp_op] 
       ) 
      ; 

     term 
      = boost::spirit::classic::real_p[self.real_op] 
      | '(' >> expression >> ')' 
      | ('-' >> term)[self.neg_op] 
      | ('+' >> term) 
      ; 
    } 

가 생성 출력 :

info = parse("-4^2", calc, scspirit::space_p); 
// generates PUSH(-4);PUSH(2);EXPONENTIATE; which is 16 

info = parse("-(12/3)^2", calc, scspirit::space_p); 
// generates PUSH(12);PUSH(3);DIVIDE;NEGATE;PUSH(2);EXPONENTIATE; which is 16 

답변

1

몇 가지를 수행해야합니다 여기

는 계산기의 우리의 버전 "클래식"부스트 성령을 사용하고 원래 코드.

"용어"를 표현할 때, 음수 (및 양수) 연산은 "용어"가 아니라 "요소"에 적용되어야합니다.

둘째, boost :: spirit :: classic :: real_p를 사용하는 대신 boost :: spirit :: classic :: u real_p, 서명되지 않은 변형을 사용하십시오.

 term 
      = boost::spirit::classic::ureal_p[self.real_op] 
      | '(' >> expression >> ')' 
      | ('-' >> factor)[self.neg_op] 
      | ('+' >> factor) 
      ; 

이제 출력 적절한이다

info = parse("-4^2", calc, scspirit::space_p); 
// generates PUSH(4);PUSH(2);EXPONENTIATE;NEGATE; which is -16 

info = parse("-(12/3)^2", calc, scspirit::space_p); 
// generates PUSH(12);PUSH(3);DIVIDE;PUSH(2);EXPONENTIATE;NEGATE; which is -16 

전성이 회복된다. 여기

는 형식적인 문법입니다 :

'수'양수 물론

expression ::= expression [{ ('+'|'-') factor}]; 
factor ::= powerterm [{ ('*'|'/') factor}]; 
powerterm ::= powerterm [{('^'|'**') powerterm}]; 
term ::= number | '(' expression ')' | '-' factor | '+' factor; 

, 엑셀, 여전히 문제이며, 그것은 널리 금융 부문에서 사용되기 때문에 우리 경제는 뒤죽박죽이다.

+0

라이브러리의 사용되지 않는 부분 (2008 년 8 월 14 일부터 사용되지 않음)을 사용하여 "복구"할 수있었습니다. (http://www.boost.org/users/ history/version_1_36_0.html) **). – sehe

+0

sehe : 이것은 사실이지만 여기의 문제는 boost :: spirit 프레임 워크가 아니라 잘못된 문법 규칙입니다. 모든 파서에 적용 할 수 있습니다. –

+0

오케이. 이것은 호언 장담이나 공개 서한처럼 보이지만, 알았습니다. downvote를 제거하십시오. – sehe