mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-19 10:51:26 +00:00
851 lines
15 KiB
Text
851 lines
15 KiB
Text
|
/* You need Bison (or maybe Yacc) to rebuild the .c file from this grammar.
|
||
|
* Or you could rewrite it to use Lemon, since the ZDoom source comes with Lemon.
|
||
|
* Since I have Bison, and the existing code works fine, there's no motivation
|
||
|
* for me to rewrite it.
|
||
|
*/
|
||
|
|
||
|
%{
|
||
|
#include "xlat.h"
|
||
|
#include <malloc.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
// verbose doesn't seem to help all that much
|
||
|
//#define YYERROR_VERBOSE 1
|
||
|
|
||
|
int yyerror (char *s);
|
||
|
int yylex (void);
|
||
|
|
||
|
typedef struct _Symbol
|
||
|
{
|
||
|
struct _Symbol *Next;
|
||
|
int Value;
|
||
|
char Sym[1];
|
||
|
} Symbol;
|
||
|
|
||
|
static bool FindToken (char *tok, int *type);
|
||
|
static void AddSym (char *sym, int val);
|
||
|
static bool FindSym (char *sym, Symbol **val);
|
||
|
|
||
|
static int EnumVal;
|
||
|
|
||
|
struct ListFilter
|
||
|
{
|
||
|
WORD filter;
|
||
|
BYTE value;
|
||
|
};
|
||
|
|
||
|
typedef struct _morefilters
|
||
|
{
|
||
|
struct _morefilters *next;
|
||
|
struct ListFilter filter;
|
||
|
} MoreFilters;
|
||
|
|
||
|
typedef struct _morelines
|
||
|
{
|
||
|
struct _morelines *next;
|
||
|
BoomArg arg;
|
||
|
} MoreLines;
|
||
|
|
||
|
%}
|
||
|
|
||
|
%union {
|
||
|
int val;
|
||
|
char sym[80];
|
||
|
char string[80];
|
||
|
struct
|
||
|
{
|
||
|
BYTE addflags;
|
||
|
BYTE args[5];
|
||
|
} args;
|
||
|
struct ListFilter filter;
|
||
|
MoreFilters *filter_p;
|
||
|
struct
|
||
|
{
|
||
|
BYTE constant;
|
||
|
WORD mask;
|
||
|
MoreFilters *filters;
|
||
|
} boomarg;
|
||
|
Symbol *symval;
|
||
|
BoomArg boomline;
|
||
|
MoreLines *boomlines;
|
||
|
}
|
||
|
|
||
|
%token <val> NUM
|
||
|
%token <symval> SYMNUM
|
||
|
%token <sym> SYM
|
||
|
%token <string> STRING
|
||
|
|
||
|
%type <val> exp
|
||
|
%type <args> special_args
|
||
|
%type <filter> list_val
|
||
|
%type <filter_p> arg_list
|
||
|
%type <boomarg> boom_args
|
||
|
%type <val> boom_op
|
||
|
%type <val> boom_selector
|
||
|
%type <boomline> boom_line
|
||
|
%type <boomlines> boom_body
|
||
|
%type <val> maybe_argcount
|
||
|
|
||
|
%token DEFINE
|
||
|
%token INCLUDE
|
||
|
%token TAG
|
||
|
%token LINEID
|
||
|
%token SPECIAL
|
||
|
%token FLAGS
|
||
|
%token ARG2
|
||
|
%token ARG3
|
||
|
%token ARG4
|
||
|
%token ARG5
|
||
|
%token OR_EQUAL
|
||
|
%token ENUM
|
||
|
%token PRINT
|
||
|
%token ENDL
|
||
|
|
||
|
%left '|'
|
||
|
%left '^'
|
||
|
%left '&'
|
||
|
%left '-' '+'
|
||
|
%left '*' '/'
|
||
|
%left NEG
|
||
|
|
||
|
%start translation_unit
|
||
|
|
||
|
%%
|
||
|
|
||
|
exp:
|
||
|
NUM
|
||
|
| SYMNUM { $$ = $1->Value; }
|
||
|
| exp '+' exp { $$ = $1 + $3; }
|
||
|
| exp '-' exp { $$ = $1 - $3; }
|
||
|
| exp '*' exp { $$ = $1 * $3; }
|
||
|
| exp '/' exp { $$ = $1 / $3; }
|
||
|
| exp '|' exp { $$ = $1 | $3; }
|
||
|
| exp '&' exp { $$ = $1 & $3; }
|
||
|
| exp '^' exp { $$ = $1 ^ $3; }
|
||
|
| '-' exp %prec NEG { $$ = -$2 }
|
||
|
| '(' exp ')' { $$ = $2; }
|
||
|
;
|
||
|
|
||
|
translation_unit: /* empty line */
|
||
|
| translation_unit external_declaration
|
||
|
;
|
||
|
|
||
|
external_declaration:
|
||
|
define_statement
|
||
|
| include_statement
|
||
|
| print_statement
|
||
|
| enum_statement
|
||
|
| linetype_declaration
|
||
|
| boom_declaration
|
||
|
| special_declaration
|
||
|
;
|
||
|
|
||
|
print_statement:
|
||
|
PRINT '(' print_list ')'
|
||
|
{
|
||
|
printf ("\n");
|
||
|
}
|
||
|
;
|
||
|
|
||
|
print_list:
|
||
|
/* EMPTY */
|
||
|
| print_item
|
||
|
| print_item ',' print_list
|
||
|
;
|
||
|
|
||
|
print_item:
|
||
|
STRING { printf ("%s", $1); }
|
||
|
| exp { printf ("%d", $1); }
|
||
|
| ENDL { printf ("\n"); }
|
||
|
;
|
||
|
|
||
|
define_statement:
|
||
|
DEFINE SYM '(' exp ')' { AddSym ($2, $4); }
|
||
|
;
|
||
|
|
||
|
include_statement:
|
||
|
INCLUDE STRING { IncludeFile ($2); }
|
||
|
;
|
||
|
|
||
|
enum_statement:
|
||
|
ENUM '{' { EnumVal = 0; } enum_list '}'
|
||
|
;
|
||
|
|
||
|
enum_list:
|
||
|
/* empty */
|
||
|
| single_enum
|
||
|
| single_enum ',' enum_list
|
||
|
;
|
||
|
|
||
|
single_enum:
|
||
|
SYM { AddSym ($1, EnumVal++); }
|
||
|
| SYM '=' exp { AddSym ($1, EnumVal = $3); }
|
||
|
;
|
||
|
|
||
|
/* special declarations work just like they do for ACS, so
|
||
|
* specials can be defined just by including zspecial.acs
|
||
|
*/
|
||
|
special_declaration:
|
||
|
SPECIAL special_list ';'
|
||
|
;
|
||
|
|
||
|
special_list:
|
||
|
/* empty */
|
||
|
| special_def
|
||
|
| special_def ',' special_list
|
||
|
;
|
||
|
|
||
|
special_def:
|
||
|
exp ':' SYM '(' maybe_argcount ')' { AddSym ($3, $1); }
|
||
|
| exp ':' SYMNUM
|
||
|
{ printf ("%s, line %d: %s is already defined\n", SourceName, SourceLine, $3->Sym); }
|
||
|
'(' maybe_argcount ')'
|
||
|
;
|
||
|
|
||
|
maybe_argcount:
|
||
|
/* empty */ { $$ = 0; }
|
||
|
| exp
|
||
|
| exp ',' exp
|
||
|
;
|
||
|
|
||
|
linetype_declaration:
|
||
|
exp '=' exp ',' exp '(' special_args ')'
|
||
|
{
|
||
|
Simple[$1].NewSpecial = $5;
|
||
|
Simple[$1].Flags = $3 | $7.addflags;
|
||
|
Simple[$1].Args[0] = $7.args[0];
|
||
|
Simple[$1].Args[1] = $7.args[1];
|
||
|
Simple[$1].Args[2] = $7.args[2];
|
||
|
Simple[$1].Args[3] = $7.args[3];
|
||
|
Simple[$1].Args[4] = $7.args[4];
|
||
|
}
|
||
|
| exp '=' exp ',' SYM '(' special_args ')'
|
||
|
{
|
||
|
printf ("%s, line %d: %s is undefined\n", SourceName, SourceLine, $5);
|
||
|
}
|
||
|
;
|
||
|
|
||
|
boom_declaration:
|
||
|
'[' exp ']' '(' exp ',' exp ')' '{' boom_body '}'
|
||
|
{
|
||
|
if (NumBoomish == MAX_BOOMISH)
|
||
|
{
|
||
|
MoreLines *probe = $10;
|
||
|
|
||
|
while (probe != NULL)
|
||
|
{
|
||
|
MoreLines *next = probe->next;
|
||
|
free (probe);
|
||
|
probe = next;
|
||
|
}
|
||
|
printf ("%s, line %d: Too many BOOM translators\n", SourceName, SourceLine);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
int i;
|
||
|
MoreLines *probe;
|
||
|
|
||
|
Boomish[NumBoomish].FirstLinetype = $5;
|
||
|
Boomish[NumBoomish].LastLinetype = $7;
|
||
|
Boomish[NumBoomish].NewSpecial = $2;
|
||
|
|
||
|
for (i = 0, probe = $10; probe != NULL; i++)
|
||
|
{
|
||
|
MoreLines *next = probe->next;;
|
||
|
if (i < MAX_BOOMISH_EXEC)
|
||
|
{
|
||
|
Boomish[NumBoomish].Args[i] = probe->arg;
|
||
|
}
|
||
|
else if (i == MAX_BOOMISH_EXEC)
|
||
|
{
|
||
|
printf ("%s, line %d: Too many commands for this BOOM translator\n", SourceName, SourceLine);
|
||
|
}
|
||
|
free (probe);
|
||
|
probe = next;
|
||
|
}
|
||
|
if (i < MAX_BOOMISH_EXEC)
|
||
|
{
|
||
|
Boomish[NumBoomish].Args[i].bDefined = 0;
|
||
|
}
|
||
|
NumBoomish++;
|
||
|
}
|
||
|
}
|
||
|
;
|
||
|
|
||
|
boom_body:
|
||
|
/* empty */
|
||
|
{
|
||
|
$$ = NULL;
|
||
|
}
|
||
|
| boom_line boom_body
|
||
|
{
|
||
|
$$ = malloc (sizeof(MoreLines));
|
||
|
$$->next = $2;
|
||
|
$$->arg = $1;
|
||
|
}
|
||
|
;
|
||
|
|
||
|
boom_line:
|
||
|
boom_selector boom_op boom_args
|
||
|
{
|
||
|
$$.bDefined = 1;
|
||
|
$$.bOrExisting = ($2 == OR_EQUAL);
|
||
|
$$.bUseConstant = ($3.filters == NULL);
|
||
|
$$.ArgNum = $1;
|
||
|
$$.ConstantValue = $3.constant;
|
||
|
$$.AndValue = $3.mask;
|
||
|
|
||
|
if ($3.filters != NULL)
|
||
|
{
|
||
|
int i;
|
||
|
MoreFilters *probe;
|
||
|
|
||
|
for (i = 0, probe = $3.filters; probe != NULL; i++)
|
||
|
{
|
||
|
MoreFilters *next = probe->next;
|
||
|
if (i < 15)
|
||
|
{
|
||
|
$$.ResultFilter[i] = probe->filter.filter;
|
||
|
$$.ResultValue[i] = probe->filter.value;
|
||
|
}
|
||
|
else if (i == 15)
|
||
|
{
|
||
|
yyerror ("Lists can only have 15 elements");
|
||
|
}
|
||
|
free (probe);
|
||
|
probe = next;
|
||
|
}
|
||
|
$$.ListSize = i > 15 ? 15 : i;
|
||
|
}
|
||
|
}
|
||
|
;
|
||
|
|
||
|
boom_selector:
|
||
|
FLAGS { $$ = 4; }
|
||
|
| ARG2 { $$ = 0; }
|
||
|
| ARG3 { $$ = 1; }
|
||
|
| ARG4 { $$ = 2; }
|
||
|
| ARG5 { $$ = 3; }
|
||
|
;
|
||
|
|
||
|
boom_op:
|
||
|
'=' { $$ = '='; }
|
||
|
| OR_EQUAL { $$ = OR_EQUAL; }
|
||
|
;
|
||
|
|
||
|
boom_args:
|
||
|
exp
|
||
|
{
|
||
|
$$.constant = $1;
|
||
|
$$.filters = NULL;
|
||
|
}
|
||
|
| exp '[' arg_list ']'
|
||
|
{
|
||
|
$$.mask = $1;
|
||
|
$$.filters = $3;
|
||
|
}
|
||
|
;
|
||
|
|
||
|
arg_list:
|
||
|
list_val
|
||
|
{
|
||
|
$$ = malloc (sizeof (MoreFilters));
|
||
|
$$->next = NULL;
|
||
|
$$->filter = $1;
|
||
|
}
|
||
|
| list_val ',' arg_list
|
||
|
{
|
||
|
$$ = malloc (sizeof (MoreFilters));
|
||
|
$$->next = $3;
|
||
|
$$->filter = $1;
|
||
|
}
|
||
|
;
|
||
|
|
||
|
list_val:
|
||
|
exp ':' exp { $$.filter = $1; $$.value = $3; }
|
||
|
;
|
||
|
|
||
|
special_args:
|
||
|
/* EMPTY LINE */
|
||
|
{
|
||
|
$$.addflags = 0;
|
||
|
memset ($$.args, 0, 5);
|
||
|
}
|
||
|
| TAG
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT1;
|
||
|
memset ($$.args, 0, 5);
|
||
|
}
|
||
|
| TAG ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT1;
|
||
|
$$.args[0] = 0;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| TAG ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT1;
|
||
|
$$.args[0] = 0;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| TAG ',' exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT1;
|
||
|
$$.args[0] = 0;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| TAG ',' exp ',' exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT1;
|
||
|
$$.args[0] = 0;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = $9;
|
||
|
}
|
||
|
|
||
|
| TAG ',' TAG
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HAS2TAGS;
|
||
|
$$.args[0] = $$.args[1] = 0;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| TAG ',' TAG ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HAS2TAGS;
|
||
|
$$.args[0] = $$.args[1] = 0;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| TAG ',' TAG ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HAS2TAGS;
|
||
|
$$.args[0] = $$.args[1] = 0;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| TAG ',' TAG ',' exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HAS2TAGS;
|
||
|
$$.args[0] = $$.args[1] = 0;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = $9;
|
||
|
}
|
||
|
|
||
|
| LINEID
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASLINEID;
|
||
|
memset ($$.args, 0, 5);
|
||
|
}
|
||
|
| LINEID ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASLINEID;
|
||
|
$$.args[0] = 0;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| LINEID ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASLINEID;
|
||
|
$$.args[0] = 0;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| LINEID ',' exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASLINEID;
|
||
|
$$.args[0] = 0;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| LINEID ',' exp ',' exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASLINEID;
|
||
|
$$.args[0] = 0;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = $9;
|
||
|
}
|
||
|
|
||
|
| exp
|
||
|
{
|
||
|
$$.addflags = 0;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = 0;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' exp
|
||
|
{
|
||
|
$$.addflags = 0;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = 0;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = 0;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' exp ',' exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = 0;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = $9;
|
||
|
}
|
||
|
|
||
|
| exp ',' TAG
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT2;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = 0;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' TAG ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT2;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = 0;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' TAG ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT2;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = 0;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' TAG ',' exp ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT2;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = 0;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = $9;
|
||
|
}
|
||
|
|
||
|
| exp ',' exp ',' TAG
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT3;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' exp ',' TAG ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT3;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' exp ',' TAG ',' exp ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT3;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = 0;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = $9;
|
||
|
}
|
||
|
|
||
|
| exp ',' exp ',' exp ',' TAG
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT4;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
| exp ',' exp ',' exp ',' TAG ',' exp
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT4;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = 0;
|
||
|
$$.args[4] = $9;
|
||
|
}
|
||
|
|
||
|
| exp ',' exp ',' exp ',' exp ',' TAG
|
||
|
{
|
||
|
$$.addflags = SIMPLE_HASTAGAT5;
|
||
|
$$.args[0] = $1;
|
||
|
$$.args[1] = $3;
|
||
|
$$.args[2] = $5;
|
||
|
$$.args[3] = $7;
|
||
|
$$.args[4] = 0;
|
||
|
}
|
||
|
;
|
||
|
|
||
|
%%
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
int yylex (void)
|
||
|
{
|
||
|
char token[80];
|
||
|
int toksize;
|
||
|
int buildup;
|
||
|
int c;
|
||
|
|
||
|
loop:
|
||
|
while (Source == NULL)
|
||
|
{
|
||
|
if (!EndFile ())
|
||
|
return 0;
|
||
|
}
|
||
|
while (isspace (c = fgetc (Source)) && c != EOF)
|
||
|
{
|
||
|
if (c == '\n')
|
||
|
SourceLine++;
|
||
|
}
|
||
|
|
||
|
if (c == EOF)
|
||
|
{
|
||
|
if (EndFile ())
|
||
|
goto loop;
|
||
|
return 0;
|
||
|
}
|
||
|
if (isdigit (c))
|
||
|
{
|
||
|
buildup = c - '0';
|
||
|
if (c == '0')
|
||
|
{
|
||
|
c = fgetc (Source);
|
||
|
if (c == 'x' || c == 'X')
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
c = fgetc (Source);
|
||
|
if (isdigit (c))
|
||
|
{
|
||
|
buildup = (buildup<<4) + c - '0';
|
||
|
}
|
||
|
else if (c >= 'a' && c <= 'f')
|
||
|
{
|
||
|
buildup = (buildup<<4) + c - 'a' + 10;
|
||
|
}
|
||
|
else if (c >= 'A' && c <= 'F')
|
||
|
{
|
||
|
buildup = (buildup<<4) + c - 'A' + 10;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ungetc (c, Source);
|
||
|
yylval.val = buildup;
|
||
|
return NUM;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ungetc (c, Source);
|
||
|
}
|
||
|
}
|
||
|
while (isdigit (c = fgetc (Source)))
|
||
|
{
|
||
|
buildup = buildup*10 + c - '0';
|
||
|
}
|
||
|
ungetc (c, Source);
|
||
|
yylval.val = buildup;
|
||
|
return NUM;
|
||
|
}
|
||
|
if (isalpha (c))
|
||
|
{
|
||
|
token[0] = c;
|
||
|
toksize = 1;
|
||
|
while (toksize < 79 && (isalnum (c = fgetc (Source)) || c == '_'))
|
||
|
{
|
||
|
token[toksize++] = c;
|
||
|
}
|
||
|
token[toksize] = 0;
|
||
|
if (toksize == 79 && isalnum (c))
|
||
|
{
|
||
|
while (isalnum (c = fgetc (Source)))
|
||
|
;
|
||
|
}
|
||
|
ungetc (c, Source);
|
||
|
if (FindToken (token, &buildup))
|
||
|
{
|
||
|
return buildup;
|
||
|
}
|
||
|
if (FindSym (token, &yylval.symval))
|
||
|
{
|
||
|
return SYMNUM;
|
||
|
}
|
||
|
strcpy (yylval.sym, token);
|
||
|
return SYM;
|
||
|
}
|
||
|
if (c == '/')
|
||
|
{
|
||
|
c = fgetc (Source);
|
||
|
if (c == '*')
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
while ((c = fgetc (Source)) != '*' && c != EOF)
|
||
|
{
|
||
|
if (c == '\n')
|
||
|
SourceLine++;
|
||
|
}
|
||
|
if (c == EOF)
|
||
|
return 0;
|
||
|
if ((c = fgetc (Source)) == '/')
|
||
|
goto loop;
|
||
|
if (c == EOF)
|
||
|
return 0;
|
||
|
ungetc (c, Source);
|
||
|
}
|
||
|
}
|
||
|
else if (c == '/')
|
||
|
{
|
||
|
while ((c = fgetc (Source)) != '\n' && c != EOF)
|
||
|
;
|
||
|
if (c == '\n')
|
||
|
SourceLine++;
|
||
|
else if (c == EOF)
|
||
|
return 0;
|
||
|
goto loop;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ungetc (c, Source);
|
||
|
return '/';
|
||
|
}
|
||
|
}
|
||
|
if (c == '"')
|
||
|
{
|
||
|
int tokensize = 0;
|
||
|
while ((c = fgetc (Source)) != '"' && c != EOF)
|
||
|
{
|
||
|
yylval.string[tokensize++] = c;
|
||
|
}
|
||
|
yylval.string[tokensize] = 0;
|
||
|
return STRING;
|
||
|
}
|
||
|
if (c == '|')
|
||
|
{
|
||
|
c = fgetc (Source);
|
||
|
if (c == '=')
|
||
|
return OR_EQUAL;
|
||
|
ungetc (c, Source);
|
||
|
return '|';
|
||
|
}
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
static Symbol *FirstSym;
|
||
|
|
||
|
static void AddSym (char *sym, int val)
|
||
|
{
|
||
|
Symbol *syme = malloc (strlen (sym) + sizeof(Symbol));
|
||
|
syme->Next = FirstSym;
|
||
|
syme->Value = val;
|
||
|
strcpy (syme->Sym, sym);
|
||
|
FirstSym = syme;
|
||
|
}
|
||
|
|
||
|
static bool FindSym (char *sym, Symbol **val)
|
||
|
{
|
||
|
Symbol *syme = FirstSym;
|
||
|
|
||
|
while (syme != NULL)
|
||
|
{
|
||
|
if (strcmp (syme->Sym, sym) == 0)
|
||
|
{
|
||
|
*val = syme;
|
||
|
return 1;
|
||
|
}
|
||
|
syme = syme->Next;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static bool FindToken (char *tok, int *type)
|
||
|
{
|
||
|
static const char tokens[][8] =
|
||
|
{
|
||
|
"endl", "print", "include", "special", "define", "enum",
|
||
|
"arg5", "arg4", "arg3", "arg2", "flags", "lineid", "tag"
|
||
|
|
||
|
};
|
||
|
static const short types[] =
|
||
|
{
|
||
|
ENDL, PRINT, INCLUDE, SPECIAL, DEFINE, ENUM,
|
||
|
ARG5, ARG4, ARG3, ARG2, FLAGS, LINEID, TAG
|
||
|
};
|
||
|
int i;
|
||
|
|
||
|
for (i = sizeof(tokens)/sizeof(tokens[0])-1; i >= 0; i--)
|
||
|
{
|
||
|
if (strcmp (tok, tokens[i]) == 0)
|
||
|
{
|
||
|
*type = types[i];
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int yyerror (char *s)
|
||
|
{
|
||
|
if (SourceName != NULL)
|
||
|
printf ("%s, line %d: %s\n", SourceName, SourceLine, s);
|
||
|
else
|
||
|
printf ("%s\n", s);
|
||
|
return 0;
|
||
|
}
|