What is the best way to flex and bison to stop processing when an error is encountered. If I call yyerror, it does not stop scanning and parsing my file. While the input is syntactically correct, there is an user error, such as they tried to load the same file twice. Once I am out of flex/bison, then my program will return an error to the user and the program should keep running. I assume that throwing a C++ exception would probably break something?
YYABORT is the standard way of getting out; it causes yyparse to return immediately with a failure (1). You can then throw an exception or do whatever you want. You'll need to reset flex's input if you want to parse something else, but if you do, you can just call yyparse again and parsing will start over from the beginning.
YYACCEPT stop parse and return 0.
Related
There is a cpp application where I want to read following type of compressed file-
file_name.gz
file_name.Z
file_name.tar.gz
For this purpose, I check the file extension and choose decompression technique accordingly. E.g. file_name.gz will be decompressed using "gunzip -C file_name.gz".
I want to get the FILE handle for decompressed file. I use popen() API for it. Now, there might be a case where gunzip/uncompress/tar fails while decompressing the file due to memory issues. How do I capture the failure in my CPP application. There is way to check if popen failed or not. What about command passed to popen().
Please help. I tried to find it at various places but could not get satisfactory solution.
When a process terminates normally, it is expected to return the exit code of 0 (legally, EXIT_SUCCESS) to the parent. Otherwise, in the case of a crash or any other abnormal termination, a non-zero value is expected to be returned. You can obtain the exit code by calling pclose(). If the code is 0, the child process most probably terminated successfully.
I don't find anything in Protocol Buffers documentation for exception handling in C++. In Javadoc it has clearly defined ones like InvalidProtocolBufferException, but not in C++.
Sometimes I ran my program and it crashes when it finds missing fields in what it thinks a valid message, then it simply stops and throws errors like this:
[libprotobuf FATAL google/protobuf/message_lite.cc:273] CHECK failed:
IsInitialized(): Can't serialize message of type "XXX" because it is
missing required fields: YY, ZZ
unknown file: Failure
C++ exception with description "CHECK failed: IsInitialized(): Can't
serialize message of type "XXX" because it is missing required fields:
YY, ZZ" thrown in the test body.
The source code of message_lite.cc all wrapped around with "GOOGLE_DCHECK" or "InitializationErrorMessage"...
My application does not allow exceptions like this to halt the program (not sure what the term is in C++ but basically no UncheckedExceptions), so I really need a way to catch these, log errors, and return gracefully, in case some messages got severely corrupted. Is there anyway doing that? Why do I see this post indicating some sort of google::protobuf::FatalException but I couldn't find documentations around it (only FatalException probably not enough also).
Thanks!
The failure you are seeing indicates that there is a bug in your program -- the program has requested to serialize a message without having filled in all the required fields first. Think of this like a segmentation fault. You shouldn't try to catch this exception -- you should instead fix your app so that the exception never happens in the first place.
Note that the check is a DCHECK, meaning it is only checked in debug builds. In your release builds (when NDEBUG is defined), this check will be skipped and the message will be written even though it is not valid. So, you don't have to worry about this crashing your application in production, only while debugging.
(Technically you could catch google::protobuf::FatalException, but the Protobuf code was not originally designed to be exception-safe. Originally, check failures would simply abort the program. It looks like FatalException was added recently, but since the code is not exception-safe, it's likely that you'll have memory leaks any time a FatalException is thrown. So, you probably should treat it like an abort().)
I solved that
my problem was same you.
if another thread change size of proto item while you do serialization then FatalException throw
then at first I copy that in another proto item then I do serialize that.
ProtoInput item; // it is global object
.
.
.
fstream output("myfile",
ios::out | ios::trunc | ios::binary);
ProtoInput in;
in.CopyFrom(item);
size_t size = in.ByteSizeLong();
void *buffer = malloc(size);
if (in.SerializeToArray(buffer, size) == true) {
output.write((char *) buffer, size);
}
output.close();
free(buffer);
I'm making a compiler in BNFC and it's got to a stage where it already compiles some stuff and the code works on my device. But before shipping it, I want my compiler to return proper error messages when the user tries to compile an invalid program.
I found how bison can write error on the stderr stream and I'm able to catch those. Now suppose the user's code has no syntax error, it just references an undefined variable, I'm able to catch this in my visitor, but I can't know what the line number was, how can I find the line number?
In bison you can access the starting and ending position of the current expression using the variable #$, which contains a struct with the members first_column, first_line, last_column and last_line. Similarly #1 etc. contain the same information for the sub-expressions $1 etc. respectively.
In order to have access to the same information later, you need to write it into your ast. So add a field to your AST node types to store the location and then set that field when creating the node in your bison file.
(previous answer is richer) but in some simple parsers if we declare
%option yylineno
in flex, and print it in yyerror,
yyerror(char *s) {
fprintf(stderr,"ERROR (line %d):before '%s'\n-%s",yylineno, yytext,s);
}
sometimes it help...
I create a simple file, using flex, it generate a file lex.yy.c, for now, I want to put it to C++ program.
%{
#include < stdio.h>
%}
%%
stop printf("Stop command received\n");
start printf("Start command received\n");
%%
When I type start or stop in command line, there is a output. What I want to do is to give the input by my C++ program, and the output of it should be sent to a variable in my program, is it possible? Thanks a lot!
I know the code I post is quite simple, but the result I imagine is:
create c file by flex and bison, and I use it as a header, so in the c++ program, I just need to call a function lex_yacc() to use it. ex. lex_yacc() is a calculator, so I sent an expression with evariables to this function, and it will return the result. I want to use this function in a C++ program, I am confused...Thanks a lot!
See the section about multiple input buffers in the manual. Especially the section about yy_scan_string and yy_scan_bytes.
For the "output", of course the is "output" when you give "stop" or "start" as input, you explicitly do that (i.e. the printf calls). You can put any code you want there.
Im trying to parse a file using Bison/Yacc but i want to pause the parsing for a while. The reason i want to do this is that i want to process a huge file sequentially and simulate a java iterator using hasNext() and next() methods.
A trivial example would be, splitting a file by line using yacc so i could call:
while(myYaccObj.hasNext())
{
std::string line = myYaccObj.next()
}
I cant find how to "pause" the file scanning. Is there a way to do that?
The easiest way is just to do the pause directly in you action code. For example, you could have a rule:
rule: whatever { Pause(); }
;
This would call your Pause function which could pause and/or do whatever you want. When you want to continue parsing, simply have the Pause function return.
In fact pausing for me means "keep the state and finish the yyparse" call. For example in my gramar I would do:
rule:
SaveLine;
Pause;
And then the control is returned to my code. I do what i have to do and then I call:
yyparse_resume();
and the parsing continues until another pause or EOF.