home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
APPS
/
hl10osrc.lzh
/
Lib
/
ParseExpr.y
< prev
next >
Wrap
Text File
|
1992-02-29
|
7KB
|
289 lines
/* -*- Mode: C -*- */
/* ParseExpr.y - Paser for -only expressions (used by print functions)
* Created by Robert Heller on Fri Feb 28 23:20:45 1992
*
* ------------------------------------------------------------------
* Home Libarian by Deepwoods Software
* Common Class library implementation code
* ------------------------------------------------------------------
* Modification History:
* ------------------------------------------------------------------
* Contents:
* ------------------------------------------------------------------
*
*
* Copyright (c) 1991,1992 by Robert heller (D/B/A Deepwoods Software)
* All Rights Reserved
*
*/
%{
#include <stream.h>
#include <common.h>
#include <ctype.h>
#include <Card.h>
#include <PTree.h>
static Tree* result = 0;
static const struct {
const char* n;
Fields f;
} FieldNames[] = {
{ "TYPE", TypeField },
{ "AUTHOR", AuthorField },
{ "TITLE", TitleField },
{ "PUBLISHER", PublisherField },
{ "CITY", CityField },
{ "VOLUME", VolumeField },
{ "YEAR", YearField }
};
const NumFields = sizeof(FieldNames) / sizeof(FieldNames[0]);
enum TypeErrors {OK, TyOK, NoConstant, NoField, MisMatch};
static TypeErrors TypeCheck(Node* a, Node* b)
{
if (a->type == FieldNode && b->type == FieldNode) return(NoConstant);
else if (a->type != FieldNode && b->type != FieldNode) return(NoField);
else if (a->type != FieldNode) return(TypeCheck(b,a));
else switch (a->value._field) {
case TypeField: if (b->type == CardTypeNode) return(TyOK);
else return(MisMatch);
break;
case AuthorField:
case TitleField:
case PublisherField:
case CityField: if (b->type == StringNode) return(OK);
else return(MisMatch);
break;
case VolumeField:
case YearField: if (b->type == IntNode) return(OK);
else return(MisMatch);
break;
}
}
#define MakeNode(v) (new Node(v))
#define MakeTree(o,l,r) (new Tree(o,l,r))
#if YYDEBUG != 0
int yydebug = 0;
#endif
%}
%start result
%union {
int ival;
char* sval;
Fields fval;
CardType tval;
Tree* trval;
Node* nval;
}
%token <ival> INTEGER
%token <sval> STRING
%token <fval> FIELD
%token <tval> CARDTYPE
%token BADWORD
%type <nval> term
%type <trval> expression
%token NOTEQ LESSEQ GREATEREQ
%nonassoc '<' '>' '=' NOTEQ LESSEQ GREATEREQ
%left '&' '|'
%right '!'
%%
result : expression
{ result = $1; }
;
expression : '(' expression ')'
{ $$ = $2; }
| '!' expression
{ $$ = MakeTree(Not,MakeNode($2),0); }
| expression '|' expression
{ $$ = MakeTree(Or,MakeNode($1),MakeNode($3)); }
| expression '&' expression
{ $$ = MakeTree(And,MakeNode($1),MakeNode($3)); }
| term '=' term
{
switch (TypeCheck($1,$3)) {
case NoConstant: yyerror("Missing constant!");
YYABORT;
case NoField: yyerror("Missing field!");
YYABORT;
case MisMatch: yyerror("Type mismatch!");
YYABORT;
case TyOK:
case OK: $$ = MakeTree(Equal,$1,$3);
}
}
| term NOTEQ term
{
switch (TypeCheck($1,$3)) {
case NoConstant: yyerror("Missing constant!");
YYABORT;
case NoField: yyerror("Missing field!");
YYABORT;
case MisMatch: yyerror("Type mismatch!");
YYABORT;
case TyOK:
case OK: $$ = MakeTree(NotEqual,$1,$3);
}
}
| term '<' term
{
switch (TypeCheck($1,$3)) {
case NoConstant: yyerror("Missing constant!");
YYABORT;
case NoField: yyerror("Missing field!");
YYABORT;
case MisMatch: yyerror("Type mismatch!");
YYABORT;
case TyOK: yyerror("< not allowed for Type");
YYABORT;
case OK: $$ = MakeTree(Less,$1,$3);
}
}
| term '>' term
{
switch (TypeCheck($1,$3)) {
case NoConstant: yyerror("Missing constant!");
YYABORT;
case NoField: yyerror("Missing field!");
YYABORT;
case MisMatch: yyerror("Type mismatch!");
YYABORT;
case TyOK: yyerror("> not allowed for Type");
YYABORT;
case OK: $$ = MakeTree(Greater,$1,$3);
}
}
| term LESSEQ term
{
switch (TypeCheck($1,$3)) {
case NoConstant: yyerror("Missing constant!");
YYABORT;
case NoField: yyerror("Missing field!");
YYABORT;
case MisMatch: yyerror("Type mismatch!");
YYABORT;
case TyOK: yyerror("<= not allowed for Type");
YYABORT;
case OK: $$ = MakeTree(LessEqual,$1,$3);
}
}
| term GREATEREQ term
{
switch (TypeCheck($1,$3)) {
case NoConstant: yyerror("Missing constant!");
YYABORT;
case NoField: yyerror("Missing field!");
YYABORT;
case MisMatch: yyerror("Type mismatch!");
YYABORT;
case TyOK: yyerror(">= not allowed for Type");
YYABORT;
case OK: $$ = MakeTree(GreaterEqual,$1,$3);
}
}
;
term : STRING
{ $$ = MakeNode($1); }
| INTEGER
{ $$ = MakeNode($1); }
| FIELD
{ $$ = MakeNode($1); }
| CARDTYPE
{ $$ = MakeNode($1); }
| BADWORD
{ yyerror("Unknown word"); YYABORT; }
;
%%
static char* original;
static char* curpointer;
Tree* ParseOnly(char* string)
{
ParseExpr parser;
original = string;
curpointer = original;
if (parser.yyparse() == 0) return(result);
else return(0);
}
void ParseExpr::yyerror(char* message)
{
cout << message << "\n";
cout << original << "\n";
for (int pos = curpointer-original; pos > 0; pos--) cout << '.';
cout << "^\n";
}
int ParseExpr::yylex()
{
static char word[256];
while (*curpointer != 0 && *curpointer <= ' ') curpointer++;
if (*curpointer == 0) return(YYEOF);
else if (isdigit(*curpointer)) {
char* p = word;
while (isdigit(*curpointer)) *p++ = *curpointer++;
*p++ = 0;
yylval.ival = atoi(word);
return(INTEGER);
} else if (*curpointer == '"') {
curpointer++;
char* p = word;
while (*curpointer != '"') {
if (*curpointer == '\\') curpointer++;
*p++ = *curpointer++;
}
curpointer++;
*p++ = 0;
yylval.sval = new char[strlen(word)+1];
strcpy(yylval.sval,word);
return(STRING);
} else if (isalpha(*curpointer)) {
char* p = word;
while (isalpha(*curpointer)) {
char c = *curpointer++;
if (islower(c)) *p++ = toupper(c);
else *p++ = c;
}
*p++ = 0;
if (CardTypeNameP(word)) {
yylval.tval = NameType(word);
return(CARDTYPE);
} else {
for (int i = 0; i < NumFields; i++) {
if (strcmp(word,FieldNames[i].n) == 0) {
yylval.fval = FieldNames[i].f;
return(FIELD);
}
}
return(BADWORD);
}
} else if (*curpointer == '!' && *(curpointer+1) == '=') {
curpointer += 2;
return(NOTEQ);
} else if (*curpointer == '<' && *(curpointer+1) == '=') {
curpointer += 2;
return(LESSEQ);
} else if (*curpointer == '>' && *(curpointer+1) == '=') {
curpointer += 2;
return(GREATEREQ);
} else return(*curpointer++);
}