LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Blogs > astrogeek
User Name
Password

Notices


Rate this Entry

Parser: Simple Bison Template

Posted 08-19-2017 at 03:17 AM by astrogeek

Flex / Bison Project Template, Bison parser source.

Save this source to a file named fbproject.y in the same directory with other project files.

This file defines a Bison parser which along with the Flex lexer source and Makefile will allow you to quickly build a working project template with the essential features required by many projects, as described in the project README file.

Code:
%code top {
/* Flex/Bison Tutorial Skeleton Parser
   Robert Allen April 16, 2017
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include "fbproject.lex.h"
#define YYDEBUG 1
}

%union {
/* Always declare a union, even for a single type
   This keeps typing explicit and simplifies later addition of new types
   */
        int ival;
        char *sval;
}

%locations
%code requires {
/* If you redefine YYLTYPE do it inside a %code requires {...} block!
        See info bison, 3.1.2 Prologue Alternatives */
char *filename;
#define YYLTYPE YYLTYPE
typedef struct YYLTYPE
{
int first_line;
int first_column;
int last_line;
int last_column;
char *filename;
} YYLTYPE;
}

%code provides {
/* Add custom error handler for lexer */
void lyyerror (char *s, ...);

}

%code {
/* We must define location aware yyerror */
void yyerror (const char *s, ...);
void doprompt ();
void usage ();
int isinteractive=0;
}

/* Token and type definitions */
%token QUIT DBG EOL ERRTOK HELP
%token <sval> QSTRING

/* Define destructors for semantic types and/or symbol names to prevent memory leaks!
   Destructors are called any time a symbol is automatically discarded
   Most important when error rules are defined which discard symbols during recovery
   Optionally report action when yydebug is set
        */
%destructor { free $$; if(yydebug) fprintf(stderr, "   %%destructor: free <sval>\n"); } <sval>

%%

sentence : /* empty */
 | sentence QSTRING EOL { printf("%s\n",$2); free($2); doprompt(); }
 | sentence HELP EOL { usage(); doprompt(); }
 | sentence QUIT EOL { printf("Bye!\n"); return 0; }
 | sentence DBG EOL { yydebug = !yydebug; printf("Debug state:%i\n",yydebug); doprompt(); }
 | sentence EOL {/* Naked newline... continue */ doprompt();  }
 | sentence error EOL { /* Pop and proceed to EOL */ yyerrok; doprompt(); }
 ;
%%

int main(int argc, char **argv)
{
        yydebug=0;
        //int i=0;
        int ex=0;

        int option_index=0;
        int verbose=0;
        int c=0;
        /*
        getopt option definitions and their targets
        long_name, has_arg, *flag, val
        has_arg: no_argument | required_argument | optional_argument
        *flag: pointer to int | 0 (NULL pointer)
        val: value written to *flag | option identifier
                If flag==0 option identifier is short opt ident, add to
                short_options string below, add handler to switch
        */
        const struct option long_options[] = {
                        {"verbose", no_argument,        &verbose, 1},
                        {"debug", no_argument,        &yydebug, 1},
                        {"help", no_argument,        0, 'h'},
                         {0, 0, 0, 0}
                };
        const char *short_options="dhv";
        while(1){
                c = getopt_long (argc, argv, short_options,
                                long_options, &option_index);
                if (c == -1)
                        break;
                switch (c)
                {
                        case 0: //long option which set a flag, do nothing
                                //If long_options[option_index].name set flag AND req's arg,
                                //set here from optarg
                                //else handled by option identifier case from val
                                break;
                        case 'd': yydebug=1;
                                  break;
                        case 'h': usage();
                                return 0;
                        case 'v': verbose=1;
                                  break;
                        case '?': /* getopt_long already printed an error message. */
                        default:
                                return 1;
                }
        }
        if (optind >= argc){ /* Read from STDIN */
                filename="stdin";
                isinteractive=1;
                doprompt();
                return yyparse()!=0;
        }
        while (optind < argc)
                { /* Read from file(s) */
                filename=argv[optind++];
                FILE *f = fopen(filename, "r");
                if (!f){
                        perror(filename);
                        return 1;
                }
                yyrestart(f);
                yylineno=1;
                ex=yyparse()!=0;
                fclose(f);
                if (ex!=0)
                        return 1;
                }
        return 0;
}
void yyerror (const char *s, ...) {
        va_list ap;
        va_start(ap, s);
        if(yylloc.first_line)
                fprintf (stderr, "%s: %d.%d-%d.%d: error ", yylloc.filename, yylloc.first_line, yylloc.first_column, \
                yylloc.last_line, yylloc.last_column);
        vfprintf(stderr, s, ap);
        fprintf(stderr, "\n");
        va_end(ap);
}
void lyyerror (char *s, ...) {
        /* Error handler for lexer, other, no default pefix text */
        va_list ap;
        va_start(ap, s);
        vfprintf(stderr, s, ap);
        fprintf(stderr, "\n");
        va_end(ap);
}
void doprompt(){
        if(isinteractive>0)
                putchar('>');
}
void usage(){
        /* Skeleton usage function */
        printf("Usage: %s [OPTIONS] [filename ...]\n\tReads input from filename(s) if given, else STDIN\n\
\t\tInteractive Commands (one per line only):\n\td|db|debug\tToggle debug mode (Bison trace output)\n\
\tq[uit]   \tQuit program\n\
\t\"string\"\tWrites double-quoted string value to STDOUT\n\
\t?|h|help   \tPrint this help information\n\
\t/* comment */\tC-style multi-line comments ignored\n\
\t# comment    \tShell style comment ignored (must be first non-space character on line)\n\
\t\tInvocation OPTIONS:\n\t-d, --debug\tStart in debug mode (Bison trace output)\n\
\t-h, --help\tPrint this help message and exit\n\
\t-v, --verbose\tStart in verbose mode\n"\
, "fbproject");
}
« Prev     Main     Next »
Total Comments 0

Comments

 

  



All times are GMT -5. The time now is 03:21 AM.

Main Menu
Advertisement
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration