2017-11-06 5 views
0

그래서 C++ 프로그램을 구문 분석하기 위해 BNF-Convertor (BNFC)을 사용하여 문법을 작성했습니다. C++ 프로그램은 다음과 같습니다.C++ 프로그램 용 BNFC 문법 작성

// a small C++ program 
#include <iostream> 

int main() 
{ 
    std::cout << "i"; 
    return 0; 
} 

내가 작성한 BNF 문법은 다음과 같습니다.

PDefs. Program ::= [Def] ; 
terminator Def "" ; 
comment "//" ; 
comment "/*" "*/" ; 
comment "#" ; 
DFun. Def ::= Type Id "(" [Arg] ")" "{" [Stm] "}" ; 
separator Arg "," ; 
terminator Stm "" ; 
separator nonempty Id "::" ; 
ADecl. Arg ::= Type Id ; 
SExp. Stm ::= Exp ";"    ; 
Sids. Stm ::= Id     ; 
SDecl. Stm ::= Type Id ";"   ; 
SDecls. Stm ::= Type Id "," [Id] ";" ; 
SInit. Stm ::= Type Id "=" Exp ";" ; 
SReturn. Stm ::= "return" Exp ";"  ; 
SWhile. Stm ::= "while" "(" Exp ")" Stm ; 
SBlock. Stm ::= "{" [Stm] "}" ; 
SIfElse. Stm ::= "if" "(" Exp ")" Stm "else" Stm ; 
EInt. Exp15 ::= Integer ; 
EDouble. Exp15 ::= Double ; 
ETrue. Exp15 ::= "true" ; 
EFalse. Exp15 ::= "false" ; 
EId.  Exp15 ::= Id ; 
EApp. Exp15 ::= Id "(" [Exp] ")" ; 
EStr. Exp15 ::= "\"" Id "\""; 
EPIncr. Exp14 ::= Exp15 "++" ; 
EPDecr. Exp14 ::= Exp15 "--" ; 
EIncr. Exp13 ::= "++" Exp14 ; 
EDecr. Exp13 ::= "--" Exp14 ; 
ETimes. Exp12 ::= Exp12 "*" Exp13 ; 
EDiv. Exp12 ::= Exp12 "/" Exp13 ; 
EPlus. Exp11 ::= Exp11 "+" Exp12 ; 
EMinus. Exp11 ::= Exp11 "-" Exp12 ; 
ELs.  Exp9 ::= Exp9 "<<" Exp10 ; 
ERs.  Exp9 ::= Exp9 ">>" Exp10 ; 
ELt.  Exp9 ::= Exp9 "<" Exp10 ; 
EGt.  Exp9 ::= Exp9 ">" Exp10 ; 
ELtEq. Exp9 ::= Exp9 "<=" Exp10 ; 
EGtWq. Exp9 ::= Exp9 ">=" Exp10 ; 
EEq.  Exp8 ::= Exp8 "==" Exp9 ; 
ENEq. Exp8 ::= Exp8 "!=" Exp9 ; 
EAnd. Exp4 ::= Exp4 "&&" Exp5 ; 
EOr.  Exp3 ::= Exp3 "||" Exp4 ; 
EAss. Exp2 ::= Exp3 "=" Exp2 ; 
coercions Exp 15 ; 
separator Exp "," ; 
separator Id "," ; 
Tbool. Type ::= "bool" ; 
Tdouble. Type ::= "double" ; 
Tint. Type ::= "int" ; 
Tvoid. Type ::= "void" ; 
token Id (letter (letter | digit | '_')*) ; 
token Ids (letter)* ; 

둘 다 ::에 대한 규칙을 작성한와 여기 <<>> 오른쪽 시프트 연산자 시프트 연산자 왼쪽하지만 어떤 이유로 제대로 구문 분석 아닙니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

내 이해에 따르면이 작동합니다하지만이 오류를 제공합니다.

syntax error at line 6 before << "i" ; return 
+1

그건 BNF가 아닙니다. – melpomene

+3

Google에서 "C++ bnf"를 검색하여 [하이퍼 링크 C++ BNF 문법] (http://nongnu.org/hcb/)을 발견했습니다. 언뜻 보면 인상적입니다. C로 실험 한 결과, C 언어는 컨텍스트가없는 것을 기억합니다. (예 : 괄호 안의 표현식을 캐스트 연산자와 구별하기 위해 몇 가지 트릭이 필요했습니다.) 내가들은 바에 따르면 C++에서는 훨씬 더 심각합니다. – Scheff

+0

@rici 어떻게 생각 하나? – Zeist

답변

1

귀하의 문제는 std::coutId되지 않는 것입니다. 그것은 [Id] 수 있습니다 - 때문에 선언

separator nonempty Id "::" ; 

의하지만 나중에 선언이 선언 충돌이

separator Id "," ; 

나에 대해 충분히 알고하지 않습니다 - 즉, Id의 목록입니다 BNFC는 그 충돌의 결과를 예측하지만, 결과가 당신이 원하는 것이라고 상상하기는 어렵습니다.

식의 구문에는 [Id]이 사용되지 않습니다. 그것은 단지 Id 수 있습니다 :

EId.  Exp15 ::= Id ; 
EApp. Exp15 ::= Id "(" [Exp] ")" ; 

그래서 정규화 된 이름 std::coutExp15으로 해석하지 않을.

Id의 목록을 사용하려는 두 가지 문맥이 매우 다릅니다. 구문 적으로나 의미 적으로 모두 다릅니다. 따라서 두 가지 모두에 대해 [Id]을 사용할 수는 없습니다.

네임 스페이스 이름을 처리 할 수 ​​있기를 원했기 때문에 의 비어 있지 않은 :: - 분리 된 목록으로 명시 적으로 Name을 정의 할 것을 제안합니다. 물론 자신의 정의 대신 [Id] 매크로를 사용할 수 있습니다. 그건 정말 스타일의 판단입니다. 나에게 그것은 분명하지 않지만 맛은 다양하다.

기타 문맥 - 선언문 - [Id]의 사용은 귀하의 단순화 된 문법으로는 충분하지만 실제로는 올바르지 않습니다. 여기에 새로운 Declarator 비 터미널을 사용하는 것이 좋습니다. 처음에는 Id으로 정의 할 수 있지만 결국에는 포인터 선언 자 (*foo), 배열 선언자 (foo[3]) 및 함수 선언자를 포함하도록 확장하려고합니다.Declarator 비 터미널로, 당신은

separator nonempty Declarator "," 
SDecls. Stm ::= Type [Declarator] ";" ; 

참고로

SDecl. Stm ::= Type Id ";"   ; 
SDecls. Stm ::= Type Id "," [Id] ";" ; 

을 대체 할 수있는 다음 "LBNF 문법 형식주의"에서, 섹션 7 (매크로) :

separator nonempty Stm ";" ; 

수단

(:[]). [Stm] ::= Stm ; 
(:). [Stm] ::= Stm ";" [Stm] ; 
+0

이것을 다음과 같이 추가했습니다 : separator nonempty Ident "::"; Sname. Ids :: = [Ident]; Eids. Exp9 :: = Ids; EL. Exp9 :: = Exp9 "<<"Exp11; 응급실. Exp9 :: = Exp9 ">>"Exp11; 여전히 구문 분석이 올바르지 않습니다. – Zeist

+0

@zeist : 주석의 코드는 읽을 수 없으며 (b) yor 질문과 매우 다릅니다. ('Ident'는 무엇인가? 우선 순위 10에서 15까지 어떻게 된 것인가?) 그리고 "아직도 정확하게 파싱하지 못했다"는 것은 모호하다. 같은 장소에서 같은 오류가 발생합니까? 아니면 다른 오류가 발생합니까? 보통 가장 좋은 방법은 정확한 세부 사항을 가진 새로운 질문을하는 것입니다. – rici

+0

동일한 줄에 같은 오류가 나타납니다. 그래서 Ident라는 새로운 식별자를 추가했고 10에서 15까지의 우선 순위 레벨이 여전히 존재합니다 .. – Zeist