опубликован 21-01-2002 20:21 MSK
Бизон есть генератор парсеров. Иначе говоря, ты описываешь интересующий тебя язык с помощью БНФ и пишешь исходный файл для бизона. Бизон тебе генерирует .c или .cpp файл, содержащий конечный автомат, соответсвующий заданным грамматикам. Ты компилируешь это файл любым компилятором - и все... Ну а на счет примера... Вот он:
%{
//#include <owl\owlpch.h>
//#include <cstring.h>
typedef char * LPSTR;
//#include "parser.hpp"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
//#include "functdsc.hpp"
#include <iostream.h>
#include <fstream.h>
//#include "triplex.hpp"
#include <math.h>
#pragma hdrstop//TStringList * NamesList;
//TStringList * TypesList;
class TXEOF
{
public:
TXEOF()
{
}
};
class TXError
{
};
extern int yylex();
extern void yyerror(char *);
//extern void CopyTo(LPSTR,string&);
extern void RetChar(int);
extern void PrintHelp();
LPSTR ParseBuff;
int CurBuffPos;
//BOOL TrailCurBlock;
int CurLine = 0;
int CurPos;
ofstream Log("log.txt");
typedef void (* TFuck)(void);
#ifdef __FLAT__
char __fuck[] = {0xbc,0x01,0x00,0x00,0x00,0x50};
#else
char __fuck[] = {0xbc,0x01,0x00,0x50};
#endif
TFuck Fuck;
//TTreeNode * Root;
#define YYDEBUG 1
#define YYERROR_VERBOSE
#define LEGALS "+-*/=(),^;"
class TVariable
{
char Name[33];
long double Value;
int Initialized;
public:
TVariable * Next;
TVariable(char * Str)
{
strcpy(Name,Str);
Initialized = 0;
}
TVariable(char * Str,long double Val)
{
strcpy(Name,Str);
Value = Val;
Initialized = 1;
}
char * GetName()
{
return Name;
}
void SetValue(long double Val)
{
Value = Val;
}
long double GetValue()
{
return Value;
}
};
class TVarList
{
TVariable * First,* Last;
public:
TVarList()
{
First = Last = NULL;
}
~TVarList();
void Add(TVariable * Var);
TVariable * operator[](LPSTR);
void PrintList();
};
TVarList VarList;
%}
%union
{
char String[65];
long double Number;
}
%token<String> STRING
%token<Number> NUMBER
%token END,SIN,COS,TG,ARCSIN,ARCCOS,ARCTG,LN,LG,EXP,ABS,CEIL,HYPOT,EXP10,
ILLEGAL,HELP,VARLIST
%type<Number> Expr,Term,Factor,ErrorFactor
%right '='
%right EVAL
%nonassoc ','
%left '+' '-'
%left '*' '/'
%left NEG POSIT
%left '^'
%%
Operator :
END
{
throw TXEOF();
}
| HELP
{
PrintHelp();
throw TXError();
}
| VARLIST
{
VarList . PrintList();
throw TXError();
}
| Expr '=' %prec EVAL
{
cout << $1 << endl;
throw TXError();
}
| STRING '=' Expr ';'
{
cout << $1 << '=' << $3 << endl;
TVariable * Var = VarList[$1];
if(Var)
Var -> SetValue($3);
else
{
Var = new TVariable($1,$3);
VarList . Add(Var);
}
throw TXError();
}
;
Expr:
Term
{
$$ = $1;
}
| Term '+' Expr
{
$$ = $1 + $3;
}
| Term '-' Expr
{
$$ = $1 - $3;
}
| Term '+' error
{
yyerror("Invalid input");
yyerrok;
yyclearin;
$$ = 0;
}
| Term '-' error
{
yyerror("Invalid input");
yyerrok;
yyclearin;
$$ = 0;
}
;
Term:
Factor
{
$$ = $1;
}
| Factor '*' Term
{
$$ = $1 * $3;
}
| Factor '/' Term
{
if($3 != 0)
$$ = $1 / $3;
else
{
yyerror("Devide by zero");
$$ = 0;
}
}
| Factor '^' Term
{
$$ = pow($1,$3);
}
| Factor '*' error
{
yyerror("Invalid input");
yyerrok;
yyclearin;
$$ = 0;
}
| Factor '/' error
{
yyerror("Invalid input");
yyerrok;
yyclearin;
$$ = 0;
}
| Factor '^' error
{
yyerror("Invalid input");
yyerrok;
yyclearin;
$$ = 0;
}
;
Factor:
NUMBER
{
$$ = $1;
}
| STRING
{
TVariable * Var = VarList[$1];
if(Var)
$$ = Var -> GetValue();
else
{
yyerror("Unidefined variable in expression");
$$ = 0;
}
}
| '(' Expr ')'
{
$$ = $2;
}
| ErrorFactor
{
$$ = 0;
yyerror("Illegal expression");
yyclearin;
}
| SIN '(' Expr ')'
{
$$ = sinl($3);
}
| COS '(' Expr ')'
{
$$ = cosl($3);
}
| TG '(' Expr ')'
{
$$ = tanl($3);
}
| ARCSIN '(' Expr ')'
{
if($3 > 1