2016-10-30 2 views
2

나는 Problems with reentrant Flex and Bison을 통해 작업하고 있습니다. 그것은 컴파일하고 내 컴퓨터에서 잘 실행됩니다. 내가하고 싶은 것은 C++ STL을 사용하는 것이다. CPP 헤더를 포함하려고 할 때마다 찾을 수 없다고합니다. Goog에 대한 몇 가지 질문 만 있습니다. 누구나 이런 종류의 설치 또는 구현할 수있는 솔루션의 작동 예제가 있습니까?Xcode의 Flex, Bison, C++ 모두

도움을 주시면 감사하겠습니다.

감사합니다.

EDIT 그래서 한 가지 이유 때문에 빌드 설정에 헤더의 포함 경로를 추가해야합니다. 이 사람의 예제의 사용자 정의 메이크 파일 때문일 것입니다. 내 급료 이상입니다. 어쨌든 이제 main 내부에서 STL 라이브러리를 사용할 수 있습니다.

내가 정말로하고 싶은 것은 CPP로 플렉스/바이슨을 사용하며, 메인이 아닌 STL 헤더를 포함 시키려면 "헤더를 찾을 수 없음"오류가 발생합니다.

그래도 C 헤더를 포함 할 수 있습니다.

+0

Flex 및 bison은 기본적으로 C 코드를 생성하므로 C++ 헤더를 사용할 수 없습니다. C++ 호환 코드를 생성하는 방법에 대한 자세한 내용은 해당 설명서를 참조하십시오. –

+1

나는 동의하지 않는다. bison 파일의 프롤로그 안에 CPP 헤더가있는 명령 줄에서 코드를 실행할 수 있습니다. –

답변

3

링크 된 주제의 다른 답변 작성자의 답변입니다.

예를 work with C++으로 변경했습니다.

핵심 포인트는 내가 최근 플렉스/들소를 사용하고

  • : brew install flexbrew install bison. 동일한 OSX/Xcode의 flex/bison으로 작동하는지 확실하지 않습니다.

  • 생성 된 flex/bison 파일은 Xcode에서 C++ 코드를 선택하기 위해 C++ 확장 (lexer. [hpp | mm], 파서. [hpp | mm])을 가져야합니다.

  • Make을 실행하는 Xcode의 빌드 단계가 있습니다.

아래의 모든 관련 파일이 있지만 예제 프로젝트를 확인하는 것이 좋습니다.

%{ 

#include <iostream> 
#include <cstdio> 

#include "ParserConsumer.h" 

#include "parser.hpp" 
#include "lexer.hpp" 

int yylex(); 
void yyerror(id <ParserConsumer> consumer, const char *msg); 

%} 

%output "Parser/Generated Code/parser.mm" 
%defines "Parser/Generated Code/parser.hpp" 

    //%define api.pure full 
%define parse.error verbose 

%parse-param { id <ParserConsumer> consumer } 

%union { 
    char *stringValue; 
    int numericValue; 
} 

%token <stringValue> Token_String 
%token <numericValue> Token_Number 

%% 

/* http://www.tldp.org/HOWTO/Lex-YACC-HOWTO-6.html 6.2 Recursion: 'right is wrong' */ 
tokens: /* empty */ 
     | tokens token 

token: 
    Token_String { 

     std::cout << "Parser says: Hello from C++\n"; 

     printf("[Parser, string] %s\n", $1); 

     [consumer parserDidParseString:$1]; 

     free($1); 
    } 
    | Token_Number { 
     printf("[Parser, number]\n"); 

     [consumer parserDidParseNumber:$1]; 
    } 
%% 

Makefile :

%{ 

#include "ParserConsumer.h" 
#include "parser.hpp" 

#include <iostream> 
#include <cstdio> 

int yylex(void); 
void yyerror(id <ParserConsumer> consumer, const char *msg); 

%} 

%option header-file = "./Parser/Generated Code/lexer.hpp" 
%option outfile  = "./Parser/Generated Code/lexer.mm" 
%option noyywrap 

NUMBER [0-9]+ 
STRING [A-Z]+ 
SPACE \x20 

%% 

{NUMBER} { 
    yylval.numericValue = (int)strtoul(yytext, NULL, 10); 

    std::cout << "Lexer says: Hello from C++\n"; 
    printf("[Lexer, number] %s\n", yytext); 

    return Token_Number; 
} 

{STRING} { 
    yylval.stringValue = strdup(yytext); 

    printf("[Lexer, string] %s\n", yytext); 

    return Token_String; 
} 

{SPACE} { 
    // Do nothing 
} 

<<EOF>> { 
    printf("<<EOF>>\n"); 

    return 0; 
} 

%% 

void yyerror (id <ParserConsumer> consumer, const char *msg) { 
    printf("%s\n", msg); 

    abort(); 
} 

Parser.ym :


main.mm의 코드는

#include "parser.hpp" 
#include "lexer.hpp" 

extern YY_BUFFER_STATE yy_scan_string(const char * str); 
extern void yy_delete_buffer(YY_BUFFER_STATE buffer); 

ParserConsumer *parserConsumer = [ParserConsumer new]; 

char input[] = "RAINBOW UNICORN 1234 UNICORN"; 

YY_BUFFER_STATE state = yy_scan_string(input); 
yyparse(parserConsumer); 
yy_delete_buffer(state); 

Lexer.lm입니다

generate-parser: clean flex bison 

clean: 
    rm -rf './Parser/Generated Code' 
    mkdir -p './Parser/Generated Code' 

flex: 
    # brew install flex 
    /usr/local/bin/flex ./Parser/Lexer.lm 

bison: 
    # brew install bison 
    /usr/local/bin/bison -d ./Parser/Parser.ym 
+0

가장 가까운 필자는 각 flex/bison 파일의 에필로그 내에서 전역 선언을 만들 수 있었지만이 방법이 효과적입니다. 고맙습니다!. –