I'm writing a fairly simple program with LEX, that after parsing a few files, parses input from a user.
Now, with the files, everything works like a charm. However, when it comes to user input from stdin, LEX rules won't run until an EOF (via ctrl+D) character is sent. When I do that, LEX parses all I wrote and then waits for more input. A second consecutive EOF terminates the scanner.
Thing is, I want the program to react on \n, outputting some data. Is there a way to force a scan from inside a rule, or to configure LEX buffering somehow to match this behaviour?
Solved! This did the trick:
%option always-interactive
I'm leaving this here for future reference, in case... well, who knows.
Here is a snippet from a unix shell I did with lex and yacc. I think it'll do the trick.
"\n" |
";" {
//yylval.sb = getsb(yytext); for yacc stuff
fprintf(stderr,"EOL\n");
return(EOL);
}
Related
I am trying to read a string given in console using getchar(). I have given a string of length 20k in which i am able to read only 4094 characters, and loop is getting breaked after that. used the below lines of code.
while ((c = getchar()) != '\n') {
}
I have tested your code in Ubuntu and it seems to be an issue with pasting the string on the shell rather than an issue with the code.
Next, make sure you compare c for EOF character as mentioned above.
In order to fix your problem or to reproduce it first, I created a 20000 character file using Python and then copied the 20000 characters.
When I pasted the characters on the shell, it doesn't give correct output but gives 4094 as you mentioned, meaning it is a shell limitation.
My solution is to paste the output to a file and then redirect it to the output.
On Linux, I did this: cat longfile20000 | ./a.out
One blog I found shows this and suggests a workaround but using a file seems better.
http://blog.chaitanya.im/4096-limit#:~:text=The%20reason%20for%20this%20discrepancy%20as%20I%20later,instead%20of%20taking%20input%20from%20the%20command%20line.
You don't mention your operating system, but its console I/O is probably limited to 4096 bytes (see for example this). And with the newline and null terminator, you are seeing 4094 bytes.
There is no machine-independent way to change this limit, as far as I can see. And in any case, it just feels wrong to use console I/O on large amounts of data. I suggest a re-design, perhaps using the suggestion in #VaibhavDS's answer.
By the way, what happpens if you call getchar after exiting the loop? I expect that the input data has been lost, but it might still be there.
Edited to add: You might find something useful at this answer.
I want to read a text file wich contains C++ code. I want to add some code at the end of the function. The problem is that I don't really know how to get to the end of the function, because there can be if statements and strings and whatever containing "}". So how should I do this? Regex?
You should use some tools like Lex and YACC, I Think Lex is enough for your requirement.
Here you can find lex and it's tutorial.
Lex Tutorial
I find it hard to explain but I will try my best. Some times in Linux- in the Terminal- things get printed but you can still write over them. eg when using wget you get a progress bar like this:
[===================> ]
Now if you type something while it is doing this it will 'overwrite' it. My question is how to recreate this in c++.
Will you use something like
cout <<
or something else?
I hope you understand what I am getting at...
btw I am using the most recent version of Arch with xfce4
Printing a carriage return character \r is typically interpreted in Linux as returning you to the beginning of the line. Try this, for example:
std::cout << "Hello\rJ";
The output will be:
Jello
This does depend on your terminal, however, so you should look up the meaning of particular control characters for your terminal.
For a more cross-platform solution and the ability to do more complex text-based user interfaces, take a look at ncurses.
You can print the special character \b to go back one space. Then you can print a space to blank it out, or another character to overwrite what was there. You can also use \r to return to the beginning of the current output line and write again from there.
Controlling the terminal involved sending various escape sequences to it, in order to move the cursor around and such.
http://www.ibiblio.org/pub/historic-linux/ftp-archives/tsx-11.mit.edu/Oct-07-1996/info/vt102.codes
You could also use ncurses to do this.
I am trying to design a server app which will read a command line over a socket stream (one character at a time). Obviously the simple way is to read characters up to the EOL and execute the command contained in the receive buffer.
Instead, I want to have it so that when a user starts entering a command line and then enters "?", the app will generate a list of all the parameters which are syntactically correct from that point in the parsing of the command line (this is similar to the way it is in some embedded devices that I have seen, like Cisco and Netscreen routers).
For example,
$ set interface ?
would display
> set interface [option] -- displays information about the specified interface.
>
> [option] must be one of the following:
> address [ip-addr]
> port [port-no]
> protocol [tcp|udp]
So basically, I would need to know where we were in the grammar, and what symbols are expected from that point forward.
It would also be nice if it could support simple line editing commands (BS, DEL, insert, left-arrow, right-arrow), and maybe even up-arrow/down-arrow for command history.
Can this be done using the boost spirit parser?
EDIT:
Simply put: Is there a simple way to create a boost spirit parser which (in addition to having a set of rules), immediately executes an action anytime '?' is encountered on the input stream (without having to explicitly encode the token '?' into the rules)?
I am using a C lexer that is Flex-generated, and a C++ parser that is Bison-generated. I have modified the parser to acccept only string input.
I am calling the parser function yyparse() in a loop, and reading line by line of user input. I stop the loop if the input is "quit".
The problem I am facing is that when input doesn't match any rule, then the parser stops abruptly, and at next iteration starts off at same state, expecting the rule which was stopped (due to syntax error) to complete.
It works fine if the input is valid and matches a parser rule.
On syntax error I have redefined the yyerror() function, that displays a simple error message.
How do I clear the state of the parser when the input doesn't match any parser rule, so that at next iteration the parser starts afresh?
According to my Lex & Yacc book there is a function yyrestart(file) .
Else (and I quote a paragraph of the book:
This means that you cannot restart a lexer just by calling yylex(). You have to reset it into the default state using BEGIN INITIAL, discard any input text buffered up by unput(), and otherwise arrange so that the next call to input() will start reading the new input.
Interesting question - I have a parser that can be compiled with Bison, Byacc, MKS Yacc or Unix Yacc, and I don't do anything special to deal with resetting the grammar whether it fails or succeeds. I don't use a Flex or Lex tokenizer; that is hand-coded, but it works strictly off strings. So, I have to agree with Gamecat; the most likely cause of the trouble is the lexical analyzer, rather than the parser proper.
(If you want to obtain my code, you can download SQLCMD from the IIUG (International Informix User Group) web site. Although the full product requires Informix ESQL/C, the grammar can, in principle, be converted into a standalone test program. Sadly, however, it appears I've not run that test for a while - there are some issues with the test compilation. Some structure element names changed in April 2006, plus there are linkage issues. I will need to re-reorganize the code so that the grammar can be tested standalone again.)