Reputation: 373
Suppose I want my Lex and Yacc program to parse the command line arguments like:
./a.out show memory
I want lex to parse the string "show memory". How do I accomplish this?
Upvotes: 1
Views: 5358
Reputation: 816
My blog article Parsing command line parameters with Yacc & Flex explains this with a working example. There is no need to concatenate the argument string. The reason is given in the article.
The blurb is:
Every once in a while someone comes along and asks how to parse command line parameters with Yacc & Flex. This is rather straight forward, but requires some knowledge of the generated code to get right.
Here we present a source template that does this. The user only has to edit the grammar and scanning rules. Some knowledge of C, Yacc and Flex is assumed.
The code is WTFPL licensed
The template is written for Berkeley Yacc and the reflex variant of Flex. It may be made to work with GNU Bison and SourceForge Flex, possibly with a few changes.
What you get is a template where you can just insert your lexical and grammar specification.
Please ask questions about the using and adapting the template itself to the blog comments.
Upvotes: 0
Reputation: 21
int main(int argc, char **argv) {
if(argc > 1) {
if(argv[1])
yy_scan_string(argv[1]);
}
yyparse();
return 0;
}
Upvotes: 2
Reputation: 399703
You'll need to concatenate all the arguments into a big string, by inserting whitespace between them. Then feed the remaining text buffer to Lex/Yacc, by re-defining the YY_INPUT
macro so it reads input from your text buffer.
The start could be something like:
#include <stdio.h>
#include <string.h>
char *argbuf;
size_t arglen;
int main(int argc, char *argv[])
{
int i;
// Compute total length of all arguments, with a single space between.
arglen = 0;
for(i = 1; argv[i] != NULL; i++)
arglen += 1 + strlen(argv[i]);
// Allocate buffer space.
argbuf = malloc(arglen);
if(argbuf == NULL)
{
fprintf(stderr, "No memory for argument buffer, aborting");
exit(1);
}
// Concatenate all arguments. This is inefficient, but simple.
argbuf[0] = 0;
for(i = 1; argv[i] != NULL; i++)
{
if(i > 1)
strcat(argbuf, " ");
strcat(argbuf, argv);
}
// Here we should be ready to call yyparse(), if we had implemented YY_INPUT().
return 0;
}
Upvotes: 2
Reputation: 5491
What's wrong with doing it the old fashioned way?:
if(argc > 1 && !strcmp(argv[1],"show"))
{
if(argc > 2)
{
if(!strcmp(argv[2],"memory"))
...
else if(!strcmp(argv[2],"cpu"))
...
else ...
}
}
Besides, getopt()
and friends are more appropriate.
Upvotes: 0