Flex、Bison、C++ 尽在 Xcode
Flex, Bison, C++ all in Xcode
我正在处理 。它在我的机器上编译和运行得很好。不过我想做的是使用 C++ STL。每当我尝试包含 CPP header 时,它都会说找不到。在 Goog 上只有少数关于此的问题。有没有人有这种设置的工作示例,或者我可能实施的解决方案?
如有任何帮助,我们将不胜感激。
谢谢!
EDIT 因此,出于某种原因,我必须在构建设置中添加任何 header 的包含路径。一定是由于此人示例的自定义 makefile。它在我的 pay-grade 之上。无论如何,我现在可以在 main 中使用 STL 库了。
我真正想做的是将 FLEX/BISON 与 CPP 一起使用,如果我尝试在除主要内容之外的任何地方包含 STL HEADERS,我会收到错误消息 "HEADER NOT FOUND".
不过我可以包含 C-headers 就好了。
这是链接主题中另一个答案的作者的回答。
我已将我的示例改编为 work with C++。
重点是:
我正在使用最近的 Flex / Bison:brew install flex
和 brew install bison
。不确定是否同样适用于默认 OSX/Xcode 的 flex/bison
.
生成的 flex/bison 文件应具有 C++ 扩展名(lexer.[hpp|mm]、解析器.[hpp|mm]),以便 Xcode 获取 C++ 代码.
有一个 Xcode 的构建阶段运行 Make
。
所有相关文件如下,但我建议您查看示例项目。
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:
%{
#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
:
%{
#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", );
[consumer parserDidParseString:];
free();
}
| Token_Number {
printf("[Parser, number]\n");
[consumer parserDidParseNumber:];
}
%%
Makefile
:
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
我正在处理
如有任何帮助,我们将不胜感激。
谢谢!
EDIT 因此,出于某种原因,我必须在构建设置中添加任何 header 的包含路径。一定是由于此人示例的自定义 makefile。它在我的 pay-grade 之上。无论如何,我现在可以在 main 中使用 STL 库了。
我真正想做的是将 FLEX/BISON 与 CPP 一起使用,如果我尝试在除主要内容之外的任何地方包含 STL HEADERS,我会收到错误消息 "HEADER NOT FOUND".
不过我可以包含 C-headers 就好了。
这是链接主题中另一个答案的作者的回答。
我已将我的示例改编为 work with C++。
重点是:
我正在使用最近的 Flex / Bison:
brew install flex
和brew install bison
。不确定是否同样适用于默认 OSX/Xcode 的flex/bison
.生成的 flex/bison 文件应具有 C++ 扩展名(lexer.[hpp|mm]、解析器.[hpp|mm]),以便 Xcode 获取 C++ 代码.
有一个 Xcode 的构建阶段运行
Make
。
所有相关文件如下,但我建议您查看示例项目。
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:
%{
#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
:
%{
#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", );
[consumer parserDidParseString:];
free();
}
| Token_Number {
printf("[Parser, number]\n");
[consumer parserDidParseNumber:];
}
%%
Makefile
:
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