ajai
ajai

Reputation: 373

Parse command line arguments in Lex

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

Answers (4)

Johann Oskarsson
Johann Oskarsson

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

Lin
Lin

Reputation: 21

int main(int argc, char **argv) {
    if(argc > 1) {
    if(argv[1])
        yy_scan_string(argv[1]);
    }
    yyparse();
    return 0;
} 

Upvotes: 2

unwind
unwind

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

Wernsey
Wernsey

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

Related Questions