As far as I know, if I need to return tokens which is not of integer types (by default) in lex, I have to redefine YYSTYPE to give it the capability to do so.
But I'm getting some strange errors as follows.
I have a file called symbols.h where I put the struct I need, and it's included by both the .l file (lex) and .y file (yacc)
struct type
{
int val;
double dval;
bool bval;
string* sval;
idData* iddata;
int type;
};
// typedef type YYSTYPE;
// #define YYSTYPE type
If I use #define, I'm getting something like this:
duplicate symbol __Z13yylex_destroyv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-7b46a5.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-64e257.o
together with a linking error
and for typedef, it shows me this:
In file included from scanner.l:6:
./y.tab.hpp:146:13: error: typedef redefinition with different types ('int' vs 'type')
typedef int YYSTYPE;
^
./symbols.h:48:14: note: previous definition is here
typedef type YYSTYPE;
^
so how do I do to get self-defined-YYSTYPE work properly?
EDIT:
the declaration part of my parser.y:
%{
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <vector>
#include "symbols.h"
#include <string>
#include "lex.yy.cpp"
#define TRACE_FLAG 1
#define trace(t) if (TRACE_FLAG) cout << "TRACE => " << t <<endl;
using namespace std;
void yyerror(string s);
vector<SymbolTable> stbs;
idData* lookupAll(string s, bool ptr=false);
%}
/* tokens */
%token LESS_EQUAL GREATER_EQUAL EQUAL NOT_EQUAL AND OR ASSIGNMENT
%token BEGIN_LEX BREAK CASE CONST CONTINUE DO ELSE END EXIT FN FOR IF IN LOOP MODULE OF PRINT PRINTLN PROCEDURE READ RECORD REPEAT RETURN THEN TYPE USE UTIL VAR WHILE
%token ARRAY BOOLEAN CHAR INTEGER REAL STRING
%token <sval> IDENTIFIER
%token <val> INT_CONST
%token <bval> BOOL_CONST
%token <dval> REAL_CONST
%token <sval> STR_CONST
/* type declaration for non-terminal symbols */
%type <iddata> constant_value expression
%type <type> var_type
/* precedence */
%left OR
%left AND
%left '~'
%left '<' '>' LESS_EQUAL GREATER_EQUAL EQUAL NOT_EQUAL
%left '+' '-'
%left '*' '/' '%'
%nonassoc UMINUS
/* start of the program */
%start program
for the scanner.l:
%{
#include <iostream>
#include <string>
#include <map>
#include "symbols.h"
#include "y.tab.hpp"
using namespace std;
#define LIST strcat(buf,yytext)
#define SHOW_TOKEN 0
#define token(t) {LIST; if(SHOW_TOKEN) printf("<%s>\n",#t);}
#define tokenInteger(t,i) {LIST; if(SHOW_TOKEN) printf("<%s:%d>\n",t,i); }
#define tokenString(t,s) {LIST; if(SHOW_TOKEN) printf("<%s:%s>\n",t,s);}
#define MAX_LINE_LENG 256
int linenum = 1;
char buf[MAX_LINE_LENG];
string str;
%}
whitespace [ \t]+
digit [0-9]
letter [a-zA-Z]
identifier {letter}({digit}|{letter})*
integer [+-]?{digit}+
real [+-]?{digit}+"."{digit}+([Ee][+-]{digit}+)?
%x COMMENT_MODULA
%x COMMENT_C
%x STR
contents of symbols.h:
#ifndef SYMBOLS_H
#define SYMBOLS_H
#include <iostream>
#include <map>
#include <vector>
#include <stdio.h>
#include <string>
using namespace std;
enum variable_type{
t_INT,
t_BOOL,
t_REAL,
t_STR,
t_ARRAY,
t_VOID
};
struct idData
{
int type = t_VOID; // enum type
/* id value */
int val = 0; // integer
bool bval = false; // boolean
double dval = 0; // float
string* sval = new string(""); // string
vector<idData> aval; // array
int arr_type = t_VOID; // enum type
idData();
idData(int type);
};
void print_id(idData id);
struct type
{
int val;
double dval;
bool bval;
string* sval;
idData* iddata;
int type;
};
// typedef type YYSTYPE;
#define YYSTYPE type
class SymbolTable {
private:
map<string, idData> symbols;
public:
idData* lookup(string s, bool ptr);
bool insert(string s, idData value);
idData* get_id_ptr(string s);
int dump(string function_name);
};
#endif
and finally the makefile: (I'm doing it on a Mac, BTW.)
TARGET = parser
LEX = flex
YACC = yacc
YACCFLAG = -d
CXX = g++
CXXFLAG = -std=c++11 -Wno-deprecated-register
.PHONY: all clean
all: $(TARGET)
y.tab.cpp: parser.y
$(YACC) $(YACCFLAG) -o $@ $^
lex.yy.cpp: scanner.l
$(LEX) -o $@ $^
$(TARGET): lex.yy.cpp y.tab.cpp symbols.cpp symbols.h
$(CXX) $(CXXFLAG) lex.yy.cpp y.tab.cpp symbols.cpp -o $@ -ll -ly
clean:
$(RM) $(TARGET) lex.yy.cpp y.tab.*
yacc is linked to bison on macOS by default, and I've tried with byacc, getting basically the same result.
error message:
g++ -std=c++11 -Wno-deprecated-register lex.yy.cpp y.tab.cpp symbols.cpp -o parser -ll -ly
duplicate symbol __Z13yylex_destroyv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z5yylexv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z10yyget_textv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z9yyget_outv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z12yyget_linenov in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z8yyget_inv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z11yyget_debugv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z10yyget_lengv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z18yypop_buffer_statev in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z6yyfreePv in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _yytext in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _yyout in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _str in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _yylineno in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _yyin in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z9yyreallocPvm in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _linenum in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z7yyallocm in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z14yy_scan_bufferPcm in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z12yyset_linenoi in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z11yyset_debugi in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z13yy_scan_bytesPKci in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z16yy_create_bufferP7__sFILEi in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _yy_flex_debug in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _yyleng in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol _buf in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z19yy_switch_to_bufferP15yy_buffer_state in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z15yy_flush_bufferP15yy_buffer_state in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z16yy_delete_bufferP15yy_buffer_state in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z19yypush_buffer_stateP15yy_buffer_state in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z14yy_scan_stringPKc in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z9yyset_outP7__sFILE in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z9yyrestartP7__sFILE in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
duplicate symbol __Z8yyset_inP7__sFILE in:
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/lex-51b52c.o
/var/folders/50/dhxd49xd3f5c2rkvsdspk7r40000gn/T/y-7ea26f.o
ld: 34 duplicate symbols for architecture x86_64
I think there is probably a better solution, since what you seem to be aiming at is a tagged union, and bison does have some features which allow for that. But in any case, your attempts fail for two different reasons:
The bison-generated header file includes typedef int YYSTYPE
unless you #define YYSTYPE
. (The typedef
is guarded by #ifndef YYSTYPE
.) User typedefs of YYSTYPE
are not supported.
You compile the scanner and the parser independently. So if you also #include "lex.yy.cpp"
into your parser, you end up compiling it twice into your project. Hence the duplicate symbol errors.