2015-01-27 2 views
1

mathicssymja과 같은 프로젝트를 본 후 C++에서 flex 및 bison을 사용하여 Wolfram 언어 용 오픈 소스 파서를 구현하려고합니다. 들소 -d를 호출하고하는 것은 ++은 어떤 문제를 제기하지 않는 플렉스,하지만 난 g ++ 사용할 때, 나는 다음과 같은 오류 메시지가 얻을 : 여기 flex, bison, C++에서 Wolfram 언어 구현

parser.tab.cpp:1242:16: error: use of undeclared identifier 'yylex' 
    yychar = YYLEX; 
     ^
parser.tab.cpp:598:16: note: expanded from macro 'YYLEX' 
# define YYLEX yylex() 
     ^
1 error generated. 

는 참조

렉서 내 .lpp 및 .ypp 파일입니다을. 어떤 도움을 주시면 감사하겠습니다

%{ 
#include <iostream> 
#include <string> 

using namespace std; 

extern "C" 
{ 
    int yyparse(void); 
} 
void yyerror(const char *s); 
%} 

%union { 
    double dval; 
    char *str; 
} 

%token <dval> NUM; 
%token <str> RBRACE; 
%token <str> LBRACE; 
%% 

expr: 
    NUM  { cout << $1 << endl;} 
    | NUM "+" NUM { cout << $1 + $3} 
    | NUM "-" NUM { cout << $1 - $3} 
    | NUM "*" NUM { cout << $1 * $3} 
    | NUM "/" NUM { cout << $1/$3} 
    ; 
%% 

int main(int argc, char **argv) 
{ 
    yyparse(); 
} 

void yyerror(const char *s) 
{ 
    cout << s << endl; 
} 

LPP

%{ 
#include <iostream> 
#include "parser.tab.hpp" 
using namespace std; 

extern "C" 
{ 
    int yylex(void); 
} 

%} 

%option c++ 
%option noyywrap 

%% 
[1-9][0-9]*(.[0-9]*)?  { return NUM; } 
"\["  { return LBRACE; } 
"\]"  cout << "rBrace" << endl; 
"\("  cout << "lParen" << endl; 
"\)"  cout << "rParen" << endl; 
"\{"  cout << "lBracket" << endl; 
"\}"  cout << "rBracket" << endl; 
","   cout << "comma" << endl; 

"@@"  cout << "apply" << endl; 
"Apply\[" cout << "apply" << endl; 
"/@"  cout << "map" << endl; 
"Map\["  cout << "map" << endl; 
"/."  cout << "rule" << endl; 

"==="  cout << "sameQ" << endl; 
"SameQ\[" cout << "sameQ" << endl; 

"+"   cout << "plus" << endl; 
"-"   cout << "minus" << endl; 
"*"   cout << "times" << endl; 
"/"   cout << "divide" << endl; 
"^"   cout << "power" << endl; 
"Power\[" cout << "power" << endl; 

--Abbreviated-- 

.   ECHO; 
%% 

int main() 
{ 
    FlexLexer* lexer = new yyFlexLexer; 
    while(lexer->yylex() != 0) 
    ; 

    return 0; 
} 

parser.ypp. 고맙습니다!

답변

1

yylex은 생성 된 스캐너에서 정의되고 생성 된 파서에서 (자동으로) 사용됩니다. 결과는 보통의 C (++)이기 때문에 마법은 없습니다. 파일에 yylex을 사용하는 경우 해당 파일에서이를 선언해야합니다.

bison이 선언을 자동으로 포함 할 것으로 예상 할 수 있지만 실제로는 포함되지 않을 수도 있습니다. 한 가지는, 당신이 (불필요하고 아마도 쓸데없이) 선언문을 extern "C" {...}에 감싸고 싶었던 것이 전혀 모를 것입니다.


또한 C++ 인터페이스에 문제가있을 것입니다. yylex은 flex C++ API의 멤버 함수이므로 extern "C"으로 선언 할 수 없으며 외부 파일에서 yylex으로 호출 할 수도 없습니다.

YMMV하지만 개인적으로 C++로 완벽하게 잘 컴파일되는 일반 (안정적이고 잘 문서화 된) C API를 사용하여 extern "C" 선언이 필요하지 않습니다.

전역을 피하려면 재진입 스캐너/순수 구문 분석기 인터페이스를 사용하십시오.

마지막으로 flex에는 명령 줄에 -d을 지정하여 거의 제로 비용으로 사용할 수있는 완벽하게 훌륭한 디버그 옵션이 제공됩니다. 이 플래그로 생성 된 스캐너는 스캔 된 모든 토큰에 대한 유익한 메시지를 자동으로 출력하므로 전체 flex 설명을 편집하는 것보다 명령 행 플래그를 제거하는 것이 훨씬 쉽습니다.

bison도 비슷한 메커니즘을 가지고 있지만 자동 실행은 아닙니다. 파서를 생성 할 때 활성화해야하며 런타임 플래그를 설정하여 켜야합니다. 둘 다 각각의 설명서에 잘 설명되어 있습니다.