Using variant in Bison and Flex - c++

I've been rewriting a parser from c to c++, and as such I am trying to use variant with my code. However, I am not sure how to integrate it with flex, and I keep getting esoteric error messages.
My bison file looks like
%require "3"
%language "c++"
%{
// declarations
%}
%define api.value.type {std::variant<double, std::string>}
%token COMMENT
%token <double> DOUBLE
%token <std::string> STRING
// grammar
and my lexer looks like
%{
#include "y.tab.h"
%}
%option noyywrap
ID [a-zA-Z][a-zA-Z0-9_]*
%%
[ \t\n ]+ ;
\-?[0-9]+ |
\-?[0-9]+\. |
\-?[0-9]+\.[0-9]+ |
\-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
// other tokens
zA-Z][\.a-zA-Z0-9_]* { yylval.emplace<std::string>(yytext); return STRING;}
%%
I am not sure of my usage of yylval, I am trying to access the variant as I would have with the %union.
I get the following error:
y.tab.h:125:18: error: ‘variant’ in namespace ‘std’ does not name a template type
typedef std::variant<double, std::string> semantic_type;
^~~~~~~
y.tab.h:197:27: error: ‘semantic_type’ does not name a type
const semantic_type& v);
^~~~~~~~~~~~~
y.tab.h:212:7: error: ‘semantic_type’ does not name a type
semantic_type value;
^~~~~~~~~~~~~
my_mdl.l: In function ‘int yylex()’:
my_mdl.l:16:3: error: ‘yylval’ was not declared in this scope
\-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
^~~~~~
my_mdl.l:16:3: note: suggested alternative: ‘yylex’
\-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
^~~~~~
yylex
my_mdl.l:16:18: error: expected primary-expression before ‘double’
\-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
^~~~~~
my_mdl.l:16:53: error: ‘DOUBLE’ was not declared in this scope
\-?\.[0-9]+ { yylval.emplace<double>(std::atof(yytext)); return DOUBLE;}
^~~~~~
my_mdl.l:18:10: error: ‘COMMENT’ was not declared in this scope
"//".* { return COMMENT;}
^~~~~~~
my_mdl.l:37:29: error: expected primary-expression before ‘>’ token
[a-zA-Z][\.a-zA-Z0-9_]* { yylval.emplace<std::string>(yytext); return STRING;}
^
my_mdl.l:37:47: error: ‘STRING’ was not declared in this scope
[a-zA-Z][\.a-zA-Z0-9_]* { yylval.emplace<std::string>(yytext); return STRING;}
^~~~~~
I also get a few hundred lines of errors from my .y file such as
my_mdl.y:88:79: error: no matching function for call to ‘MOVE::MOVE(<brace-enclosed initializer list>)’
p.add_command(Command{in_place_index<5>, MOVE( {{$2, $3, $4}}, $5)});
^
In file included from parsing/symt.h:7:0,
from my_mdl.y:10:
parsing/cmd.h:44:5: note: candidate: MOVE::MOVE(const Scalable<double, 3>&, const string&)
MOVE(const Scalable<double, 3> &params, const std::string &scaleFactorName);
^~~~
MOVE is a struct defined as
struct MOVE {
MOVE(const Scalable<double, 3> &params, const std::string &scaleFactorName);
Scalable<double, 3> params; // todo equationify
std::string scale_factor_name;
};
and it is one of the types in the variant (std::variant<MOVE, etc...> Command). The strange thing is that this works normally in my code if I write
p.add_command(Command{in_place_index<5>, MOVE{{{x, y, z}}, "asdfads"}});

You have not included enough of your program to allow for a precise answer. Please see the SO help page on preparing a [mcse]. But it seems likely that you get the error
y.tab.h:125:18: error: ‘variant’ in namespace ‘std’ does not name a template type
because you haven't arranged for #include <variant> to be in your flex file.
The typedef itself is from the generated code in the header file produced by bison, but bison cannot guess what #include directives it might need, so it leaves it up to you to insert them. You must ensure that all types needed by your semantic type have been defined before you #include the bison-generated header. You could insert appropriate #include directives in the prologue block in your flex file, or you could use a %code requires block in your bison file. (Since you are using bison 3, the latter is probably the best solution.)
I have no idea what SAVE means in the errors from your bison file. I assume it is a macro you have (or have not defined), so the error would be a result of the macro expansion.

Bison actually provides its own custom type called 'variant', which is not the C++ std::variant, and supports it nicely.
https://www.gnu.org/software/bison/manual/bison.html#C_002b_002b-Variants
Bison provides a variant based implementation of semantic values for C++. This alleviates all the limitations reported in the previous section, and in particular, object types can be used without pointers.
To enable variant-based semantic values, set the %define variable api.value.type to variant (see %define Summary). Then %union is ignored; instead of using the name of the fields of the %union to “type” the symbols, use genuine types.
For instance, instead of:
%union
{
int ival;
std::string* sval;
}
%token <ival> NUMBER;
%token <sval> STRING;
write:
%token <int> NUMBER;
%token <std::string> STRING;
STRING is no longer a pointer, which should fairly simplify the user actions in the grammar and in the scanner (in particular the memory management).
To enable it, you simply specify
%define api.value.type variant
However this will also affect your lexer. I put together a small demo C++ flex/bison skeleton using the latest flex/bison binaries under Ubuntu:
https://github.com/kfsone/flub
highlights being:
/* lexer */
{string} yylval->emplace<std::string>(yytext); return Token::STRING;
/* parser */
%language "C++"
%skeleton "lalr1.cc"
%require "3.8.2"
%define api.value.type variant
/*
%define api.value.automove // use with care
*/
%define parse.assert
%define parse.trace
%define parse.error detailed
%define parse.lac full
/* ... */
/*
NB: You now use the TYPE rather than union-member name
*/
%token <std::string> STRING
/*
// ditto for nterms, but I now prefer putting them by the production itself.
%nterm <string::string> string_literal
*/
%%
/* ... */
/* Declare the type of this non-terminal, to be done here in the
productions section, you need a trailing semicolon */
%nterm <std::string> using_file;
using_file
: "using" STRING
{ $$ = $2; }
;
You can then use a much more modern AST-building approach, one thing I found helpful was to have a wrapper type of my own that captured a value AND its location.
template<typename ValueType>
struct ParsedType
{
location mLoc; // or YourParserType::location_type
ValueType mValue;
};
using ParsedString = ParsedType<std::string>;
/* ... */
%nterm <ParsedString> using_file;
using_file
: "using" STRING
{ $$ = ParsedString(#2, $2); }

Related

doctest CHECK_TROWS_AS unused argument

I'd like to doctest some conversion expression with C++ doctest.
I'm using a code similar to the following
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
#include "doctest.h"
TEST_CASE("operator int()") {
CHECK_THROWS_AS(int(2), std::invalid_argument);
int i;
CHECK_THROWS_AS(i = int(2), std::invalid_argument);
}
However in both case I get a warning:
dd.cpp:7:7: warning: variable 'i' set but not used [-Wunused-but-set-variable]
int i;
^
dd.cpp:6:19: warning: expression result unused [-Wunused-value]
CHECK_THROWS_AS(int(2), std::invalid_argument);
^ ~
How do I silence the warning in proper C++ (not using a particular compiler feature).
By the way, in my real code, 2 is actually replaced by an object of a class whose int operator may throw.

Typedef not a member of namespace

So, I'm attempting to fork some open source code and upon compilation I am greeted with these errors:
C2039 'TransactionId': is not a member of 'CryptoNote'
C2061 syntax error: identifier 'TransactionId'
I'm relatively inexperienced with C++ usually confining myself to the realms of C#, however, I can clearly see that TransactionId is a typedef declared in a different file like so:
namespace CryptoNote {
typedef size_t TransactionId;
typedef size_t TransferId;
//more code
And the line throwing the error is:
void sendTransactionCompleted(CryptoNote::TransactionId _id, bool _error, const QString& _error_text);
To my inexperienced eyes, that looks as though TransactionID is definitly a member of Cryptonote is it not?
Any ideas what's going on?
The repo is here: https://github.com/hughesjs/Incendium_GUI
And the necessary submodule is here: https://github.com/hughesjs/Incendium_Crypt
Those typedefs are defined in Incendium_Crypt/include/IWalletLegacy.h.
void sendTransactionCompleted(CryptoNote::TransactionId _id, bool _error, const QString& _error_text);`
is defined in Incendium_GUI/src/gui/SendFrame.h, which includes IWallet.h. However, IWallet.h does not in turn include IWalletLegacy.h. Hence, those typedefs are unknown to SendFrame.h.
It's difficult to say without seeing all the code but a few things come to mind:
Firstly is this the first error you get. Compilation errors with C++ tend to result in a bunch of secondary errors. For example the following results in a similar error to what you see but fails to compile because size_t has not been defined:
namespace CryptoNote {
typedef size_t TransactionId;
typedef size_t TransferId;
}
int main(void)
{
CryptoNote::TransactionId id;
return 0;
}
$ g++ -std=c++11 namespace.cxx -o namespace
namespace.cxx:4:9: error: ‘size_t’ does not name a type
typedef size_t TransactionId;
^~~~~~
namespace.cxx:5:9: error: ‘size_t’ does not name a type
typedef size_t TransferId;
^~~~~~
namespace.cxx: In function ‘int main()’:
namespace.cxx:11:17: error: ‘TransactionId’ is not a member of ‘CryptoNote’
CryptoNote::TransactionId id;
^~~~~~~~~~~~~
See http://www.cplusplus.com/reference/cstring/size_t/ for a list of headers that define size_t.
Is CryptoNote nested inside another namespace?
Is there another CryptoNote defined in the namespace your function is declared in?
Are these in the same header file? If not, is the header file where the namespace is defined included in the header file containing the function declaration?

Expansion of Nested Macros with reinterpret cast in c++

I stumbled across the below code and really found it complex to understand the nested macro and type casting in it.
Also when i tried to compile the code , i have encountered an error
Would need an explanantion of the below code.
why BEGIN_STATE_MAP and END_STATE_MAP set as labels in Motor.h , This is really new to me
Thanks in advance
Motor.h
// the Motor state machine class
class Motor : public StateMachine
{
public:
Motor() : StateMachine(ST_MAX_STATES) {}
// external events taken by this state machine
void Halt();
void SetSpeed(MotorData*);
private:
// state machine state functions
void ST_Idle();
void ST_Stop();
void ST_Start(MotorData*);
void ST_ChangeSpeed(MotorData*);
// state map to define state function order
BEGIN_STATE_MAP
STATE_MAP_ENTRY(ST_Idle)
STATE_MAP_ENTRY(ST_Stop)
STATE_MAP_ENTRY(ST_Start)
STATE_MAP_ENTRY(ST_ChangeSpeed)
END_STATE_MAP
// state enumeration order must match the order of state
// method entries in the state map
enum E_States {
ST_IDLE = 0,
ST_STOP,
ST_START,
ST_CHANGE_SPEED,
ST_MAX_STATES
};
};
#endif //MOTOR_H
what are BEGIN_STATE_MAP and END_STATE_MAP, This definition i found i really new,
BEGIN_STATE_MAP and END_STATE_MAP are the Macros defined in the below header file.
StateMachine.h
#ifndef STATE_MACHINE_H
#define STATE_MACHINE_H
#include <stdio.h>
#include "EventData.h"
struct StateStruct;
// base class for state machines
class StateMachine
{
public:
StateMachine(int maxStates);
virtual ~StateMachine() {}
protected:
enum { EVENT_IGNORED = 0xFE, CANNOT_HAPPEN };
unsigned char currentState;
void ExternalEvent(unsigned char, EventData* = NULL);
void InternalEvent(unsigned char, EventData* = NULL);
virtual const StateStruct* GetStateMap() = 0;
private:
const int _maxStates;
bool _eventGenerated;
EventData* _pEventData;
void StateEngine(void);
};
typedef void (StateMachine::*StateFunc)(EventData *);
struct StateStruct
{
StateFunc pStateFunc;
};
#define BEGIN_STATE_MAP \
public:\
const StateStruct* GetStateMap() {\
static const StateStruct StateMap[] = {
#define STATE_MAP_ENTRY(entry)\
{ reinterpret_cast<StateFunc>(entry) },
#define END_STATE_MAP \
{ reinterpret_cast<StateFunc>(NULL) }\
}; \
return &StateMap[0]; }
#define BEGIN_TRANSITION_MAP \
static const unsigned char TRANSITIONS[] = {\
#define TRANSITION_MAP_ENTRY(entry)\
entry,
#define END_TRANSITION_MAP(data) \
0 };\
ExternalEvent(TRANSITIONS[currentState], data);
#endif
EventData.h
#ifndef EVENT_DATA_H
#define EVENT_DATA_H
class EventData
{
public:
virtual ~EventData() {};
};
#endif //EVENT_DATA_H
While i tried to compile the code above.Below is the error that was encountered
Error
-------------- Build: Debug in StateMachine (compiler: GNU GCC Compiler)---------------
mingw32-g++.exe -Wall -fexceptions -g -pedantic -Wzero-as-null-pointer-constant -std=c++0x -Wextra -Wall -c C:\Users\xprk569\StateMachine\main.cpp -o obj\Debug\main.o
In file included from C:\Users\xprk569\StateMachine\main.cpp:2:0:
C:\Users\xprk569\StateMachine\Motor.h: In member function 'virtual const StateStruct* Motor::GetStateMap()':
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
{ reinterpret_cast<StateFunc>(entry) },
^
C:\Users\xprk569\StateMachine\Motor.h:29:9: note: in expansion of macro 'STATE_MAP_ENTRY'
STATE_MAP_ENTRY(ST_Idle)
^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
{ reinterpret_cast<StateFunc>(entry) },
^
C:\Users\xprk569\StateMachine\Motor.h:30:9: note: in expansion of macro 'STATE_MAP_ENTRY'
STATE_MAP_ENTRY(ST_Stop)
^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
{ reinterpret_cast<StateFunc>(entry) },
^
C:\Users\xprk569\StateMachine\Motor.h:31:9: note: in expansion of macro 'STATE_MAP_ENTRY'
STATE_MAP_ENTRY(ST_Start)
^
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the '&' ?)
{ reinterpret_cast<StateFunc>(entry) },
^
C:\Users\xprk569\StateMachine\Motor.h:32:9: note: in expansion of macro 'STATE_MAP_ENTRY'
STATE_MAP_ENTRY(ST_ChangeSpeed)
^
C:\Users\xprk569\StateMachine\StateMachine.h:43:39: error: invalid cast from type 'int' to type 'StateFunc {aka void (StateMachine::*)(EventData*)}'
{ reinterpret_cast<StateFunc>(NULL) }\
^
C:\Users\xprk569\StateMachine\Motor.h:33:5: note: in expansion of macro 'END_STATE_MAP'
END_STATE_MAP
^
Process terminated with status 1 (0 minute(s), 0 second(s))
5 error(s), 0 warning(s) (0 minute(s), 0 second(s))
Can some please explain why is the macro written that way in Motor.h,
why is it declared like that in StateMachine.h and
why is the error being thrown ?
Thanks in Advance
It looks like this code depends on some nonstandard compiler extensions/errors.
To get it to compile (no idea if it will actually work) you need to replace the function names with full qualified member function pointers:
e.g.
BEGIN_STATE_MAP
STATE_MAP_ENTRY(&Motor::ST_Idle)
STATE_MAP_ENTRY(&Motor::ST_Stop)
STATE_MAP_ENTRY(&Motor::ST_Start)
STATE_MAP_ENTRY(&Motor::ST_ChangeSpeed)
END_STATE_MAP
After that, you need to figure out a way to overcome the non-conforming cast:
/tmp/gcc-explorer-compiler116314-75-1uiyu0/example.cpp: In member function 'virtual const StateStruct* Motor::GetStateMap()':
44 : error: invalid cast from type 'long int' to type 'StateFunc {aka void (StateMachine::*)(EventData*)}'
{ reinterpret_cast<StateFunc>(NULL) }\
^
83 : note: in expansion of macro 'END_STATE_MAP'
This cast is completely illegal. If I were you I would throw the code in the trash and rewrite - or use a proven state machine framework like boost meta state machine or boost statechart.
So you're quickly learning why Macros are no-nos in readable C++. If you get an error, you must expand the macro out to identify where the error is, also you cannot debug into them in most IDEs.
Anyway that said lets get to the expanding, their all the same error so we'll just look at the first one:
C:\Users\xprk569\StateMachine\Motor.h:29:9: note: in expansion of macro STATE_MAP_ENTRY
STATE_MAP_ENTRY(ST_Idle)
C:\Users\xprk569\StateMachine\StateMachine.h:40:40: error: invalid use of member (did you forget the & ?)
{ reinterpret_cast<StateFunc>(entry) },
So this is complaining about line 29: STATE_MAP_ENTRY(ST_Idle) So lets expand that:
{ reinterpret_cast<StateFunc>(entry) },
Obviously this is bad syntax all together outside the scoping of BEGIN_STATE_MAP and END_STATE_MAP, so in debugging many Macros you'd also have to look at the scoping macros... sometimes they may not be clearly named or delineated unfortunately, but let's finish defining the line we got the error on first. What is this StateFunc we're trying to cast to?
typedef void (StateMachine::*StateFunc)(EventData *);
It's a pointer to a member function which returns a void and accepts an EventData *. And alarm bells should be going off. You cannot cast to that! ST_Idle is of the format: void (StateMachine::*)() so you cannot cast to void (StateMachine::*StateFunc)(EventData *). This is the same problem for all your functions passed into the macros none of them return a void and take an EventData*, so even if you fix the syntax, these reinterpret_casts will always return a pointer to a method which is invalid to call, meaning this entire block of Macros is pointless at best and toxic at worst. In the current state you may just as well use none of these Macros or if you need to define the method just do:
BEGIN_STATE_MAP
END_STATE_MAP
But if you were going to change your method declarations to something more like:
void ST_Idle(EventData*);
Then you'd need to use this syntax:
STATE_MAP_ENTRY(&Motor::ST_Idle)
If you're not down with the method pointers they are quite complex. I've typed up a quick example here: http://ideone.com/nL0HnQ Feel free to comment with questions.
EDIT:
To expand the Macros here we'll get:
public: // BEGIN_STATE_MAP
const StateStruct* GetStateMap() { // BEGIN_STATE_MAP
static const StateStruct StateMap[] = { // BEGIN_STATE_MAP
{ reinterpret_cast<StateFunc>(ST_Idle) } // STATE_MAP_ENTRY(ST_Idle)
{ reinterpret_cast<StateFunc>(ST_Stop) } // STATE_MAP_ENTRY(ST_Stop)
{ reinterpret_cast<StateFunc>(ST_Start) } // STATE_MAP_ENTRY(ST_Start)
{ reinterpret_cast<StateFunc>(ST_ChangeSpeed) } // STATE_MAP_ENTRY(ST_ChangeSpeed)
{ reinterpret_cast<StateFunc>(NULL) } // END_STATE_MAP
}; // END_STATE_MAP
return &StateMap[0]; } // END_STATE_MAP
So this set of macros will:
Set the scope to public
Declare the method GetStateMap
Declare StateMap statically local to GetStateMap, it will be an array of StateStructs
On the first call of the GetStateMap method StateMap will be initialized to contain method pointers to ST_Idle, ST_Stop, ST_Start, ST_ChangeSpeed, and NULL reinterpret_cast to StateFuncs
Define GetStateMap to return the StateMap array

Missing type specifier on a static function with a type

My question relates to three files and how they relate to each other:
In one file I have a bunch of predefined types such as Uint, int32, etc.
In the other two I have a class that is used to categories exceptions (which is mostly static functions) and definitions for the class.
All of the types are in the file Types.h, with a macro which allows the types to be defined globally:
namespace Enigma {
//Omitted Types
typedef std::uint32_t Uint32;
typedef std::string string;
//Omitted Types
}
#if defined(USING_GLOBAL_TYPES)
using namespace aNamespace;
#endif
In the other files I have the following (or similar to it anyway):
Header file:
#include "Types.h"
namespace Enigma {
class ExceptionCategory {
typedef Uint32 CategoryID;
static CategoryID GetIDFromName(const string& name) noexcept;
};
}
Source file:
Engima::ExceptionCategory::CategoryID Enigma::ExceptionCategory::GetIDFromName(const string& name) noexcept {
//Omitted Code
}
Now the problem lies within the Source file according to the error messages the Compiler is throwing at me which include the following:
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2143: syntax error: missing ',' before '&'
error C2511: 'Enigma::ExceptionCategory::IDType Enigma::ExceptionCategory::GetIDFromName(const int) noexcept': overloaded member function not found in 'Enigma::ExceptionCategory'
Edit: Major Rewording
In the cpp file, remove the double colon before the namespace.
aNamespace::int32 aNamespace::aClass::aStaticFunction() noexcept {
//does a thing
}
Quite a simple mistake:
Was missing the namespace Enigma before string in the source code.
It's unusual because it has been working fine for ages until suddenly it stopped working
Engima::ExceptionCategory::CategoryID Enigma::ExceptionCategory::GetIDFromName(const Enigma::string& name) noexcept {
//Omitted Code
}

Errors in making a re-entrant parser

I have tried a lot, but could not figure out what the errors are.
Any detailed explanation about the this will be very helpful.
So basically i am trying to write a re-entrant parser and these are my files.
Lex1.ll
%{
#include "Globals.h"
#include "yac1.tab.hh"
extern "C"
{
int yylex(void);
}
%}
alpha [A-Za-z]
digit [0-9]
%option case-insensitive
%option bison-bridge
%option reentrant
%option noyywrap
%%
"DELETE ALL" return DELALL;
"INSERT" return INSERT;
DELETE return DELETE;
FIND return FIND;
(\+|\-)?[0-9]+ { return INT; }
\n { return ENDL; }
. ;
%%
yac1.yy
%{
#include <stdio.h>
#include "Globals.h"
%}
%pure-parser
%error-verbose
%{
#define YYPARSE_PARAM parm
#define YYLEX_PARAM ((struct parsed_vals *)parm)->scanner
#define cast ((struct parsed_vals *) parm)
void yyerror(struct parsed_vals * parm,const char *s)
{
fprintf(stderr, "error: %s\n", s);
}
extern "C"
{
int yylex(void );
// int yywrap()
// {
// return 1;
// }
}
%}
%token INSERT DELETE DELALL FIND ENDL
%union {
int ival;
float fval;
char *sval;
}
%token <ival> INT
%token <fval> FLOAT
%token <sval> STRING
%%
S:T
T: INSERT val {cast->cmd=INSERT_CMD;}
| DELETE val {cast->cmd=DELETE_CMD;}
;
val : INT ENDL {cast->type=INT_TYPE;
(cast->data).int_data=$1;}
|
FLOAT ENDL {cast->type=FLOAT_TYPE;
(cast->data).float_data=$1;}
|
STRING ENDL {cast->type=STRING_TYPE;
(cast->data).str_data=$1;}
;
%%
My main function testlex.cc
#include <stdio.h>
#include "Globals.h"
#include "lexheader.h"
#include "yac1.tab.hh"
int yyparse(void *);
yyscan_t scanner;
main()
{
struct parsed_vals foo;
const char * buffer = "inseRt 4\n";
yylex_init(&(foo.scanner));
yyset_extra(&foo, foo.scanner);
YY_BUFFER_STATE bp = yy_scan_string( buffer, foo.scanner );
yy_switch_to_buffer(bp, foo.scanner);
int a;
int ret_val = yyparse(&foo);
yy_delete_buffer(bp, foo.scanner);
if(ret_val!=0) printf("False");
printf ("hello %d\n",foo.data.int_data);
printf ("hello %d\n",foo.type);
yylex_destroy(foo.scanner);
}
Globals.h
/*
* File: Globals.h
* Author: atghosh
*
* Created on 3 August, 2013, 8:39 PM
*/
#ifndef GLOBALS_H
#define GLOBALS_H
enum CMD {INSERT_CMD=1, DELETE_CMD, FIND_CMD, DELALL_CMD};
enum TYPE {INT_TYPE=5, FLOAT_TYPE, STRING_TYPE};
struct parsed_vals{
int cmd;
int type;
union{
int int_data;
float float_data;
char *str_data;
} data;
void * scanner;
};
#endif /* GLOBALS_H */
Makefile
parser: lex1.ll yac1.yy testlex.cc
bison -d yac1.yy
flex --header-file="lexheader.h" lex1.ll
g++ -o parser yac1.tab.cc lex.yy.c testlex.cc -lfl
clean:
rm -rf *.o parser lexheader.h lex.yy.c lex.yy.cc parser yac1.tab.cc yac1.tab.hh
And my error list
bison -d yac1.yy
flex --header-file="lexheader.h" lex1.ll
g++ -o parser yac1.tab.cc lex.yy.c testlex.cc -lfl
yac1.tab.cc: In function ‘int yyparse(void*)’:
yac1.tab.cc:1302:16: error: too many arguments to function ‘int yylex()’
yac1.yy:20:13: note: declared here
yac1.tab.cc:1510:24: error: cannot convert ‘const char*’ to ‘parsed_vals*’ for argument ‘1’ to ‘void yyerror(parsed_vals*, const char*)’
yac1.tab.cc:1625:35: error: cannot convert ‘const char*’ to ‘parsed_vals*’ for argument ‘1’ to ‘void yyerror(parsed_vals*, const char*)’
In file included from testlex.cc:3:0:
lexheader.h:278:1: error: ‘YYSTYPE’ does not name a type
lexheader.h:280:18: error: variable or field ‘yyset_lval’ declared void
lexheader.h:280:18: error: ‘YYSTYPE’ was not declared in this scope
lexheader.h:280:28: error: ‘yylval_param’ was not declared in this scope
lexheader.h:280:51: error: expected primary-expression before ‘yyscanner’
lexheader.h:328:17: warning: ‘yylex’ initialized and declared ‘extern’ [enabled by default]
lexheader.h:328:17: error: ‘YYSTYPE’ was not declared in this scope
lexheader.h:328:27: error: ‘yylval_param’ was not declared in this scope
lexheader.h:328:50: error: expected primary-expression before ‘yyscanner’
lexheader.h:328:59: error: expression list treated as compound expression in initializer [-fpermissive]
make: *** [parser] Error 1
I am just not able to figure out what is going wrong.
Expecting detailed reply and no links.
I have already referred to these links
http://www.phpcompiler.org/articles/reentrantparser.html
http://plindenbaum.blogspot.in/2009/12/parsing-genetic-code-using-flex-and_14.html
Here's a number of issues and the corresponding fixes.
Erase the prototype of yylex from both lex1.ll and yac1.yy. You shouldn't have to define it yourself anywhere.
Add two #include's near the beginning of yac1.yy:
#include "yac1.tab.hh"
#include "lexheader.h"
Make sure you have them in this order, as the first one defines YYSTYPE which is used by the second one. This is a known issue with flex/bison lexers and parsers.
Fix the prototype and the definition of yyerror in yac1.yy. It should be:
void yyerror(const char *s);
If you need an extra parameter there, for your own purpose from your own calls, you
cannot expect the parser to provide it. In this case, define your own error handler
and use a different name.
After all this, your program compiles using your Makefile. Whether it works as expected or not, I cannot tell.