help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Flex-Bison string processing


From: Hans Aberg
Subject: Re: Flex-Bison string processing
Date: Tue, 5 Dec 2000 11:35:20 +0100

At 18:34 +0300 0-12-04, Vladimir Rykov wrote:
>Actually my problem is to parse and convert into XML file a Math notations
>like this:
>
>         k <= n implies k <= n +m
>
>or
>
>      (for x holds x c- X iff  x c- Y ) implies X = Y
>
>                                        ("iff" - if and only if - to and
>back and "c-" means membership)

You could write "x in X" for set membership...

For such a problem, it could be worth checking out the Internet if not
already has done the stuff you are about to embark on:

You could check MathML and XML mailing lists at http://www.w3.org/. The
comp.tex something newsgroups may provide inputs as well. There is a
package HaXml at http://www.cs.york.ac.uk/fp/HaXml/icfp99.html
for processing XML using Haskell http://haskell.org,
http://haskell.org/hugs. For use with Haskell there are parser generators
(happy)
and scanner generators (alex) available. -- Such a high level language may
be simpler to use for string processing.

For use with Flex/Bison, it might be better to use C++ instead of C,
because one can use the std::string and std::stringstream classes, which
are very convenient for handling strings.

When I used Flex with C++, I had to do some editing of the files
FlexLexer.h, flex.skl, and skel.c: Prefixing "std::" to the names
  istream  ostream  cin  cout  cerr  exit
(Possibly some more chasnges; I do not recall.)

Below is an example of a simple calculator for use with the Flex C++ option
& Bison. Bison outputs a .c file which should be compiled as C++; or tweak
the Bison as I suggested here or in bugs-bison, to make Bison output the
same file but with a .cc suffix.

-- Calculator.lm, flex -PCalculator ---------------------------------------


%{

#include "Calculator.h"

#define yylval Calculatorlval

#include "Calculator.tab.h"

#include <iostream>
#include <string>
#include <strstream>

%}

%option noyywrap
%option c++

digit           [0-9]
number          {digit}+\.?|{digit}*\.{digit}+
identifier  [a-zA-Z]+

%%

[ ]                      { /* Skip blanks. */ }
{number}         { /* sscanf(yytext, "%lf", &yylval.value); */
                           std::istrstream(yytext, yyleng) >> yylval.value;
                           return NUMBER; }
"sqrt"           { yylval.f = &sqrt; return ELEMENTARY_FUNCTION; }
"exp"            { yylval.f = &exp; return ELEMENTARY_FUNCTION; }
"log"            { yylval.f = &log; return ELEMENTARY_FUNCTION; }
"exp2"           { yylval.f = &exp2; return ELEMENTARY_FUNCTION; }
"log2"           { yylval.f = &log2; return ELEMENTARY_FUNCTION; }
"exit"           { return EXIT; }
{identifier} { yylval.name = std::string(yytext, yyleng).c_str(); return
IDENTIFIER; }
\n|\r        { return '\n'; }
.                        { return yytext[0]; }
<<EOF>>          { return Eof; }

%%

-- Calculator.y, bison --defines --name-prefix=Calculator -------------------


%{
    /* Creating C++ syntax for a Bison and Flex calculator. */

#include <iostream>

#include "Calculator.h"

#define yyFlexLexer CalculatorFlexLexer
#include "FlexLexer.h"

FlexLexer* flexLexer;

inline int yylex() { return flexLexer->yylex(); }

double parse_value = 0;

%}

%token NUMBER
%token ELEMENTARY_FUNCTION
%token IDENTIFIER
%token Eof
%token EXIT

%left '+' '-'
%right ELEMENTARY_FUNCTION
%left '*' '/'
%right '^'
%right IDENTIFIER
%right UMINUS

%%
lines:  lines expr '\n' { parse_value = $2.value; return 0; }
    |   lines expr Eof  { parse_value = $2.value; return 0; }
    |   lines EXIT '\n' { throw Exit(0, "Exit: Bye, bye!"); }
    |   lines EXIT Eof  { throw Exit(0, "Exit: Bye, bye!"); }
    |   lines '\n'
    |   lines Eof       { throw Exit(0, "End of file."); }
    |
    |   error '\n'      { cout << "Please re-enter last line:\n";
                          yyerrok; }
    |   error Eof       { throw Exit(1, "Exit: Error!"); }
    ;

expr:   expr '+' expr   { $$.value = $1.value + $3.value }
    |   expr '-' expr   { $$.value = $1.value - $3.value }
    |   expr '*' expr   { $$.value = $1.value * $3.value }
    |   expr '/' expr   { $$.value = $1.value / $3.value }
    |   expr '^' expr   { $$.value = pow($1.value, $3.value) }
    |   '(' expr ')'    { $$.value = $2.value }
    |   '-' expr  %prec UMINUS { $$.value = -$2.value }
    |   IDENTIFIER expr { $$.value = sqrt($2.value) }
    |   ELEMENTARY_FUNCTION expr    { $$.value = (*$1.f)($2.value) }
    |   NUMBER
    ;

%%


Parser::Parser(std::istream* ip, std::ostream* op)
 : isp(ip), osp(op)
{   lex = new yyFlexLexer(isp, osp);   }

Parser::~Parser() { delete lex; }


std::istream& Parser::operator>>(double& val) {
    lex->yyrestart(isp);
    flexLexer = lex;
    yyparse();
    val = parse_value;
    return *isp;
}



#if 0
#include <ctype.h>
#include <stdio.h>


#if __MWERKS__ && macintosh
#include <SIOUX.h>
#endif

int main() {
#if __MWERKS__ && macintosh
    SIOUXSettings.asktosaveonclose = 0;
    SIOUXSettings.autocloseonquit = 1;
#endif
    return yyparse();
}
#endif

int yyerror(char* errstr) {
    cerr << "Error: " << errstr << endl;
    return EXIT_FAILURE;
}

-- Calculator.h --------------------------------------------------------


#ifndef Calculator_h
#define Calculator_h


#include <math.h>
#include <iostream>
#include <string>

class FlexLexer;

#if __MWERKS__ && macintosh
#include <unix.h>
#endif


typedef union calc_type {
    double value;
    const char* name;
    double (*f)(double);
} calc_type;


#define YYSTYPE calc_type

int yyerror(char* errstr);



class Parser {
    std::istream* isp;  // istream being parsed
    std::ostream* osp;  // ostream being output to
    FlexLexer* lex;     // Lexical analyzer to use;
public:
    Parser(std::istream* ip = 0, std::ostream* op = 0);
    ~Parser();

    std::istream& operator>>(double&);
    std::ostream& operator<<(double&);

    Parser& operator>>(Parser& (*manipulator)(Parser&))
    {   return manipulator(*this);   }
    Parser& operator<<(Parser& (*manipulator)(Parser&))
    {   return manipulator(*this);   }

friend Parser& operator<<(ostream& ost, Parser& parser);
friend Parser& operator>>(std::istream& ist, Parser& parser);
};


#if 0
inline std::istream& Parser::operator>>(double& val) {
    val = sentence(*isp);
    return *isp;
}
#endif

#if 0
inline std::ostream& Parser::operator<<(double& val) {
    return (*osp) << val;
}
#endif


inline Parser& operator<<(ostream& ost, Parser& parser) {
    parser.osp = &ost;
    return parser;
}

inline Parser& operator>>(std::istream& ist, Parser& parser) {
    parser.isp = &ist;
    return parser;
}



Parser& inprompt(Parser& syn);
Parser& outprompt(Parser& syn);

class Exit {
    int error;
    string message;
public:
    Exit(int err, string mess) : error(err), message(mess) { }
    int status() { return error; }
    string what() { return message; }
};

#endif

-- main.cc ----------------------------------------------------------------


    // Creating C++ syntax for a Bison and Flex calculator.

#include <cstdlib>
#include <fstream>
#include <iostream>

#include "Calculator.h"


#if __MWERKS__ && macintosh
#include <SIOUX.h>
#endif

int main() {
#if __MWERKS__ && macintosh
    SIOUXSettings.asktosaveonclose = 0;
    SIOUXSettings.autocloseonquit = 0;
#endif

    Parser calc;
    double d;

    std::ifstream ifs("Input", ios_base::in | ios_base::binary);

    if (!ifs)
        cout << "Could not open input file." << endl;
    else {
    //  ifs.exceptions(ios_base::eofbit);
    //  while (ifs && !ifs.eof())
        try { for (;;) {
            ifs >> calc >> d;
            std::cout << d << endl;
            }
        }
        catch (Exit& ex) {
            std::cout << ex.what() << endl;
            std::cout << "Status: " << ex.status() << endl;
        }
        catch (...) {
            cout << "Exception: ..." << endl;
        }
    }

    while (cin) {
        try {
            std::cin >> calc >> d;
            std::cout << d << endl;
        }
        catch (Exit& ex) {
            std::cout << ex.what() << endl;
            return ex.status();
        }
    }

    return EXIT_SUCCESS;
}

--------------------------------------------------------------------------





  Hans Aberg





reply via email to

[Prev in Thread] Current Thread [Next in Thread]