C ++ 코드로 lex / yacc를 컴파일하기 어려움
lex.yy.c 및 y.tab.c를 C ++ 코드로 컴파일하려고합니다. 여기에 Make 상태가 있습니다.
(base) rajatkmitra@spider:~/modeler> make
flex ./src/lex.l
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o main.o ./src/main.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o convertFloatToFixed.o ./src/convertFloatToFixed.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o convertProductFloatToFixed.o ./src/convertProductFloatToFixed.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o printer.o ./src/printer.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o vectorToString.o ./src/vectorToString.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o printFixedPointProduct.o ./src/printFixedPointProduct.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o fixedPointFormatter.o ./src/fixedPointFormatter.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o tokenize.o ./src/tokenize.cc
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o y.tab.o y.tab.c
bison -y -d ./src/bison.y
./src/bison.y: warning: 4 shift/reduce conflicts [-Wconflicts-sr]
g++ -I ./ -c -Wall -Wreorder -Wno-write-strings -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm -c -o lex.yy.o lex.yy.c
###############################################################################
# Building main.o convertFloatToFixed.o convertProductFloatToFixed.o printer.o vectorToString.o
printFixedPointProduct.o fixedPointFormatter.o tokenize.o y.tab.c lex.yy.c
###############################################################################
g++ -Wno-write-strings -I ./ main.o convertFloatToFixed.o convertProductFloatToFixed.o printer.o vectorToString.o printFixedPointProduct.o fixedPointFormatter.o tokenize.o y.tab.c lex.yy.c -o lynx -lm
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: /tmp/cc8jVMLM.o: in function `yylex()':
lex.yy.c:(.text+0x343): undefined reference to `yyerror(char*)'
collect2: error: ld returned 1 exit status
make: *** [Makefile:71: lynx] Error 1
----Makefile----
####################################################################
# Library Paths
####################################################################
####################################################################
#Sources, use vpath and $CC/$LEX/$YACC should have arguments $<
#debug %make --just-print should show simulate make procedure
####################################################################
INCLUDE=-I ./
LEXSRC=lex.l
YACCSRC=bison.y
SRC=main.cc convertFloatToFixed.cc convertProductFloatToFixed.cc \
printer.cc vectorToString.cc printFixedPointProduct.cc fixedPointFormatter.cc \
tokenize.cc y.tab.c lex.yy.c
vpath %cc ./src
vpath %l ./src
vpath %y ./src
#####################################################################
#Compiler Settings
#####################################################################
OBJCC=$(SRC:.cc=.o) OBJC=$(SRC:.c=.o)
EXE=lynx
DEFINE=#-D _XOPEN_SOURCE
CFLAGS=$(INCLUDE) $(DEFINE) $(LIBPATH) -c -Wall -Wreorder -Wno-write-strings \ -Wno-unused-variable -Wno-unused-function -Wno-sign-compare -g -lm CXXFLAGS=$(CFLAGS)
CC=g++
LEX=flex
YACC=bison -y -d
######################################################################
#Build Rules
######################################################################
new: all
all:$(SRC) $(EXE)
# These dependency rules indicate that (1) lex.yy.o depends on
# lex.yy.c and y.tab.h and (2) lex.yy.o and y.tab.o depend on calc.h.
# Make uses the dependencies to figure out what rules must be run when
# a file has changed.
lex.yy.o: lex.yy.c y.tab.h
lex.yy.o y.tab.o:
## This rule will use yacc to generate the files y.tab.c and y.tab.h
## from our file $(YACCSRC).y y.tab.c y.tab.h: $(YACCSRC)
$(YACC) $<
## this is the make rule to use lex to generate the file lex.yy.c from
## our file $(LEXSRC).lex lex.yy.c: $(LEXSRC)
$(LEX) $<
## for lex.yy.c and y.tab.c
%.c.o:
$(CC) $(CFLAGS) $< -o $@
## all other C++ files
%.cc.o:
$(CC) $(CFLAGS) $< -o $@
$(EXE):$(OBJCC) $(OBJC) @echo \############################################################################### @echo \# Building $(OBJCC)
@echo \###############################################################################
$(CC) -Wno-write-strings $(INCLUDE) $(OBJCC) $(LIBPATH) $(LIB) -o $@ -lm
clean:
rm -rf $(EXE) *~ *.o lex.yy.c y.tab.h
자 여기 문법 파일 bison.y가 있습니다.
%{
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
int yylex();
void yyerror(const char *s);
/*|--------------------------
for global parsing
-----------------------------|*/
unsigned int attributeFlag;
%}
/*Possible types from lexer*/
%union {
int ival;
double fval;
const char *sval;
}
/*Possible tokens*/
%token KWREAL
%token <ival> INTEGER
%token <fval> FLOAT;
%token <sval> VARIABLE
/*associativity*/
%left GE LE EQ NE '>' '<'
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
/*parse rules*/
%%
description:
description decl_attributes {}
| description stmt_list {}
| description real_variable_decl {}
| decl_attributes {}
| stmt_list {}
| real_variable_decl {}
;
decl_attributes:
attribute {}
| decl_attributes attribute {}
;
attribute:
open_attribute several_attribute_assignments close_attribute
real_variable_decl
{
attributeFlag = 0;
}
;
open_attribute:
'(' '*' {attributeFlag = 1;}
;
close_attribute:
'*' ')' {}
;
several_attribute_assignments:
integer_assignment {}
| continued_attribute_assignments integer_assignment {}
;
continued_attribute_assignments:
integer_assignment ',' {}
| continued_attribute_assignments integer_assignment ',' {}
;
real_variable_decl:
KWREAL VARIABLE ';'
{
}
;
stmt_list:
stmt { }
| stmt_list stmt { }
;
stmt:
VARIABLE '=' expr ';' {printf("%s\n\n",$1); }
| integer_assignment ';' { }
;
integer_assignment:
VARIABLE '=' INTEGER
{
if(attributeFlag==1){
if(strcmp($1, "S")==0){ //attrContainer.isSigned = $3;
}else if(strcmp($1, "IB")==0){ //attrContainer.intBits = $3;
}else if(strcmp($1, "FB")==0){ //attrContainer.fracBits = $3;
}
}
}
;
expr:
VARIABLE { printf("%s\n",$1); } | FLOAT { printf("%f\n",$1); }
| '-' expr %prec UMINUS { }
| expr '+' expr { }
| expr '-' expr { }
| expr '*' expr { }
| expr '/' expr { }
| expr '<' expr { }
| expr '>' expr { }
| expr GE expr { }
| expr LE expr { }
| expr NE expr { }
| expr EQ expr { }
| '(' expr ')' { }
;
%%
/*|-----------------------------------------------------
Parsing Functions
-----------------------------------------------------|*/
/*Definition of yyerror*/
void yyerror(const char *s)
{
extern int yylineno; // defined and maintained in lex.c
extern char *yytext; // defined and maintained in lex.c
printf("ERROR: %s on line %d\n", yytext, yylineno);
}
그리고 어휘 분석기-
%{
#include <stdlib.h>
#include <stdio.h>
#include "y.tab.h"
void yyerror(char *);
%}
%%
"real" return KWREAL;
[a-zA-Z][a-zA-Z]* {
//yylval.sval= *yytext - 'a';
yylval.sval = strdup(yytext);
return VARIABLE;
}
0 {
yylval.ival = atoi(yytext);
return INTEGER;
}
[1-9][0-9]* {
yylval.ival = atoi(yytext);
return INTEGER;
}
(([0-9]*\.[0-9]*)([eE][-+]?[0-9]+)?) {
yylval.fval = atof(yytext);
return FLOAT;
}
[-()<>=+*/;,{}.] {
return *yytext;
}
">=" return GE;
"<=" return LE;
"==" return EQ;
"!=" return NE;
#[^\n]* { /* Discard preprocessor comments. */ }
"//"[^\n]* { /* Discard c99 comments. */ }
[ \t\n]+ ; /* ignore whitespace */
. yyerror("Unknown character");
%%
int yywrap(void) {
return 1;
}
이것이 메인 루틴 main.cc입니다.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
/*------------------------------------------------
Front end parser
------------------------------------------------*/
extern void yyparse(void);
extern FILE *yyin;
int main(int argc, char **argv)
{
/*------------------------
parse the file
------------------------*/
/*open file handle to a file of interest*/
if(argc < 2){
printf("Usage: main <filename> \n");
exit(-1);
}
yyin = fopen(argv[1],"r");
if(yyin==NULL){
printf("Could not open file !\n");
exit(-1);
}
/*Parse the design*/
do{
yyparse();
}while(!feof(yyin));
}
그래서 당신은 간다! 최소 재현 가능한 예제를 추가했습니다. g ++로 모든 것을 컴파일하면 yylex ()에서 yyerror () 루틴을 찾지 못하는 링커 오류가 발생합니다.
g++ -Wno-write-strings -I ./ y.tab.o lex.yy.o main.o -o lynx -lm -lfl -
std = c ++ 11 /usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld : lex.yy.o : in function yylex()': /home/rajatkmitra/modeler/minimal/lex.l:46: undefined reference to
yyerror (char *) '/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld : / usr / lib64 / gcc /x86_64-suse-linux/7/../../../../lib64/libfl.so :`yylex '에 대한 정의되지 않은 참조 collect2 : 오류 : ld가 1 종료 상태를 리턴 함 make : *** [Makefile : 68 : lynx] 오류 1
Changes Made to get this environment to work -
(1) Compile ALL sources including the output from lex and yacc with g++
(2) yyerror arguments are (char *s) and NOT (const char *s)
(2) do not link with -lfl as this is not not required with g++
답변
다음은 문제를 보여주는 최소한의 예입니다.
파일 : yyerror.c
#include <iostream>
void yyerror(const char* msg) {
std::cout << msg;
}
파일 : main.c
void yyerror(char* msg);
int main(void) {
char* msg[] = "Hello, world";
yyerror(msg);
}
빌드하려고
$ g++ -Wall -o main main.c yyerror.c
/tmp/cc4xbjus.o: In function `main':
main.c:(.text+0x5f): undefined reference to `yyerror(char*)'
collect2: error: ld returned 1 exit status
참고 선언 있음 yyerror
에는 main.c
의 정의와 다르다 yyerror
에서 yyerror.c
. 당신은 C로이 파일을 컴파일하고 이후 ++,이 문제는 : C ++에서 함수 이름은 다른 인수 형식 오버로드 될 수 있으며, const char*
이외의 다른 인수 유형입니다 char*
. 따라서 두 파일을 성공적으로 연결할 수 없습니다. yyerror
선언 된 의 오버로드는 main.c
어디에도 정의 되어 있지 않습니다.
yyerror
렉서 파일에 배치 한 선언을 표시하지는 않지만 컴파일러에서 생성 한 오류 메시지를 기반으로 내 예제와 동일하다고 가정합니다. 오류 메시지는 링크 할 수없는 함수의 전체 이름 (인수 유형 포함)을 나타냅니다.