quakeforge/tools/qfcc/source/qc-lex.l
Bill Currie c248372e20 Initial integer type support. qfcc /is/ partially broken when it comes to
integer constants and float function args/return values.

pr_comp.h:
	o  add the integer opcodes to pr_opcode_e
pr_edict.c:
	o  add "quaternion" and "integer" to type_name[]
	o  support quatnernion and integers types when printing values
	o  support the integer opcodes when bounds checking
pr_exec.c
	o  enable the integer opcodes
pr_opcode:
	o  add the integer opcodes to the opcode table
	o  logical operators all result in an integer rather than a value
expr.h:
	o  rename int_val to integer_val
qfcc.h:
	o  kill another magic number
expr.c:
	o  move the opcode to string conversion out of type_mismatch and into
	   get_op_string
	o  rename int_val to integer_val
	o  general integer type support.
	o  generate an internal comipiler error for null opcodes rather than
	   segging.
pr_imm.c:
	o  rename int_val to integer_val
	o  support integer constants, converting to float when needed.
pr_lex.c:
	o  magic number death and support quaternions and integers in type_size[]
qc-lex.l
	o  rename int_val to integer_val
	o  support quaternion and integer type keywords
qc-parse.y:
	o  rename int_val to integer_val
	o  use binary_expr instead of new_binary_expr for local initialized
	   variables
builtins.c:
	o  rename int_val to integer_val
	o  fix most (all?) of the INT related FIXMEs
defs.qc:
	o  use integer instead of float where it makes sense
main.c:
	o  read_result is now integer rather than float
main.qc:
	o  float -> integer where appropriate
	o  new test for int const to float arg
2001-07-23 01:31:22 +00:00

281 lines
5.2 KiB
Text

%{
#include <QF/hash.h>
#include "qfcc.h"
#include "scope.h"
#include "qc-parse.h"
#define YY_NO_UNPUT
int type_or_name (char *token);
int do_grab (char *token);
void add_frame_macro (char *token);
char *make_string (char *token);
extern YYSTYPE yylval;
%}
DIGIT [0-9]
ID [a-zA-Z_][a-zA-Z_0-9]*
FLOAT {DIGIT}+"."{DIGIT}*
NUM ({DIGIT}+("."{DIGIT}*)?)
s [ \t]
m ([\-+]?)
%x grab_frame grab_other
%%
"/*" {
int c;
do {
while ((c = input ()) != '*' && c != EOF
&& c != '\n')
;
while (c == '*')
c = input ();
if (c == EOF)
error (0, "EOF in comment");
if (c == '\n')
pr_source_line++;
} while (c != '/' && c != EOF);
}
"//".* /* nothing to do */
{DIGIT}+ {
yylval.integer_val = atoi (yytext);
return INT_VAL;
}
{FLOAT}* {
yylval.float_val = atof (yytext);
return FLOAT_VAL;
}
{ID} return type_or_name(yytext);
\"(\\.|[^"])*\" {
yylval.string_val = make_string (yytext);
return STRING_VAL;
}
'{s}*{m}{NUM}{s}+{m}{NUM}{s}+{m}{NUM}{s}*' {
sscanf (yytext, "' %f %f %f '",
&yylval.vector_val[0], &yylval.vector_val[1],
&yylval.vector_val[2]);
return VECTOR_VAL;
}
'{s}*{m}{NUM}{s}+{m}{NUM}{s}+{m}{NUM}{s}+{m}{NUM}{s}*' {
sscanf (yytext, "' %f %f %f %f '",
&yylval.vector_val[0], &yylval.vector_val[1],
&yylval.vector_val[2], &yylval.vector_val[3]);
return VECTOR_VAL;
}
^#{s}+{DIGIT}+{s}+\"(\.|[^"])*\".*$ {
char *p;
int line;
pr_file_p = yytext + 1;
line = strtol (pr_file_p, &p, 10);
pr_file_p = p;
while (isspace (*pr_file_p))
pr_file_p++;
if (!*pr_file_p)
PR_ParseError ("Unexpected end of file");
PR_LexString (); // grab the filename
while (*pr_file_p && *pr_file_p != '\n') // ignore flags
pr_file_p++;
pr_source_line = line - 1;
s_file = ReuseString (pr_immediate_string);
}
"!"|"("|")"|"{"|"}"|"."|"*"|"/"|"&"|"|"|"+"|"-"|"="|"["|"]"|";"|","|"#" return yytext[0];
"..." return ELIPSIS;
"&&" return AND;
"||" return OR;
"==" return EQ;
"!=" return NE;
"<=" return LE;
">=" return GE;
"<" return LT;
">" return GT;
"$"{s}*{ID} {
int ret = do_grab(yytext);
if (ret > 0)
return ret;
else
BEGIN (-ret);
}
<grab_frame>{ID} add_frame_macro (yytext);
<grab_other>[^\n]* /* skip */
<*>\n {
pr_source_line++;
BEGIN (INITIAL);
}
<*>{s}* /* skip */
<*>. error (0, "all your typo are belong to us");
%%
int
yywrap (void)
{
return 1;
}
typedef struct {
const char *name;
int value;
type_t *type;
} keyword_t;
static keyword_t keywords[] = {
{"void", TYPE, &type_void },
{"float", TYPE, &type_float },
{"string", TYPE, &type_string },
{"vector", TYPE, &type_vector },
{"entity", TYPE, &type_entity },
{"quaternion", TYPE, &type_quaternion},
{"integer", TYPE, &type_integer },
{"local", LOCAL, 0 },
{"return", RETURN, 0 },
{"while", WHILE, 0 },
{"do", DO, 0 },
{"if", IF, 0 },
{"else", ELSE, 0 },
{"for", FOR, 0 },
};
static const char *
keyword_get_key (void *kw, void *unused)
{
return ((keyword_t*)kw)->name;
}
int
type_or_name (char *token)
{
static int initialized = 0;
static hashtab_t *keyword_tab;
keyword_t *keyword;
if (!initialized) {
int i;
keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0);
for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++)
Hash_Add (keyword_tab, &keywords[i]);
initialized = 1;
}
keyword = Hash_Find (keyword_tab, token);
if (keyword) {
yylval.type = keyword->type;
return keyword->value;
}
yylval.string_val = strdup (token);
return NAME;
}
static hashtab_t *frame_tab;
static hashtab_t *grab_tab;
typedef struct {
const char *name;
int num;
} frame_t;
static frame_t grab_list[] = {
{"cd", 0},
{"origin", 0},
{"base", 0},
{"flags", 0},
{"scale", 0},
{"skin", 0},
};
static const char *
frame_get_key (void *f, void *unused)
{
return ((frame_t*)f)->name;
}
static void
frame_free (void *f, void *unused)
{
free ((char*)((frame_t*)f)->name);
free (f);
}
int
do_grab (char *token)
{
static int initialized;
frame_t *frame;
if (!initialized) {
int i;
initialized = 1;
frame_tab = Hash_NewTable (1021, frame_get_key, frame_free, 0);
grab_tab = Hash_NewTable (1021, frame_get_key, 0, 0);
for (i = 0; i < sizeof (grab_list) / sizeof (grab_list[0]); i++)
Hash_Add (grab_tab, &grab_list[i]);
}
while (isspace (*++token)) // advance over $ and leading space
;
if (!strcmp (token, "frame"))
return -grab_frame;
if (Hash_Find (grab_tab, token))
return -grab_other;
frame = Hash_Find (frame_tab, token);
if (frame) {
yylval.integer_val = frame->num;
return INT_VAL;
}
return 0;
}
static int frame_number;
void
add_frame_macro (char *token)
{
frame_t *frame = malloc (sizeof (frame_t));
frame->name = strdup (token);
frame->num = frame_number++;
Hash_Add (frame_tab, frame);
}
void
clear_frame_macros (void)
{
frame_number = 0;
if (frame_tab)
Hash_FlushTable (frame_tab);
}
char *
make_string (char *token)
{
char *str;
pr_file_p = token;
PR_LexString ();
str = malloc (pr_token_len + 1);
memcpy (str, pr_token, pr_token_len + 1);
return str;
}