quakeforge/tools/qfcc/source/qc-lex.l

386 lines
9.5 KiB
Text
Raw Normal View History

%{
2001-09-28 07:09:38 +00:00
/*
qc-lex.l
2001-09-28 07:09:38 +00:00
lexer for quakec
2001-09-28 07:09:38 +00:00
Copyright (C) 2001 Bill Currie <bill@taniwha.org>
2001-09-28 07:09:38 +00:00
Author: Bill Currie <bill@taniwha.org>
Date: 2001/06/12
2001-09-28 07:09:38 +00:00
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
2002-06-01 04:41:25 +00:00
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
static __attribute__ ((used)) const char rcsid[] =
"$Id$";
2002-06-01 04:41:25 +00:00
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include <ctype.h>
#include <QF/dstring.h>
#include <QF/hash.h>
#include <QF/sys.h>
#include "qfcc.h"
#include "class.h"
#include "debug.h"
2002-06-01 05:30:16 +00:00
#include "expr.h"
#include "grab.h"
2002-06-04 18:44:03 +00:00
#include "immediate.h"
#include "options.h"
#include "struct.h"
2002-01-23 20:50:25 +00:00
#include "type.h"
#include "qc-parse.h"
2003-04-16 19:41:52 +00:00
#ifndef YY_PROTO
# define YY_PROTO(x) x
#else
# define YY_FLEX_REALLOC_HACK
#endif
int yyget_lineno (void);
FILE *yyget_in (void);
FILE *yyget_out (void);
int yyget_leng (void);
char *yyget_text (void);
void yyset_lineno (int line_number);
void yyset_in (FILE * in_str);
void yyset_out (FILE * out_str);
int yyget_debug (void);
void yyset_debug (int bdebug);
int yylex_destroy (void);
#define YY_NO_UNPUT
#define YY_DECL int yylex YY_PROTO(( void ))
YY_DECL;
2003-04-16 19:41:52 +00:00
static int type_or_name (char *token);
extern YYSTYPE yylval;
%}
DIGIT [0-9]
2002-10-26 03:23:19 +00:00
XDIGIT [0-9a-fA-F]
ID [a-zA-Z_][a-zA-Z_0-9]*
FLOAT {DIGIT}+"."{DIGIT}*
NUM ({DIGIT}+("."{DIGIT}*)?)
s [ \t]
m ([\-+]?)
2007-04-06 08:19:58 +00:00
FRAMEID {ID}(\.{ID})*
%x GRAB_FRAME GRAB_OTHER COMMENT
%%
grab_frame = GRAB_FRAME;
grab_other = GRAB_OTHER;
"/*" { BEGIN (COMMENT); }
<COMMENT>"/*" { warning (0, "nested /* in comment"); }
<COMMENT>"*/" { BEGIN (INITIAL); }
<COMMENT>\r*\n { pr.source_line++; }
<COMMENT>. /* nothing to do */
<COMMENT><<EOF>> { error (0, "EOF in comment"); return 0; }
"//".* /* nothing to do */
^#{s}+{DIGIT}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); }
2007-04-06 11:27:03 +00:00
^#line{s}+{DIGIT}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 5); }
^{s}*#{s}*pragma.*$ /* skip */
2010-12-23 10:32:28 +00:00
{DIGIT}+[uU]? {
const char *c = yytext + yyleng - 1;
int uint = 0;
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
yylval.integer_val = atoi (yytext);
2010-12-23 10:32:28 +00:00
if (*c == 'u' || *c == 'U')
uint = 1;
return uint ? UINT_VAL : INT_VAL;
}
2010-12-23 10:32:28 +00:00
0[xX]{XDIGIT}+[uU]? {
2002-10-26 03:23:19 +00:00
const char *c = yytext + 2;
2010-12-23 10:32:28 +00:00
int uint = 0;
yylval.uinteger_val = 0;
2002-10-26 03:23:19 +00:00
while (*c) {
2010-12-23 10:32:28 +00:00
if (*c == 'u' || *c == 'U') {
uint = 1;
break;
}
yylval.uinteger_val *= 16;
yylval.uinteger_val += *c - '0';
2002-10-26 03:23:19 +00:00
if (*c > '9')
2010-12-23 10:32:28 +00:00
yylval.uinteger_val -= 'A' - '9' - 1;
2002-10-26 03:23:19 +00:00
if (*c > 'F')
2010-12-23 10:32:28 +00:00
yylval.uinteger_val -= 'a' - 'A';
2002-10-26 03:23:19 +00:00
c++;
}
2010-12-23 10:32:28 +00:00
return uint ? UINT_VAL : INT_VAL;
2002-10-26 03:23:19 +00:00
}
{FLOAT}* {
yylval.float_val = atof (yytext);
return FLOAT_VAL;
}
2001-06-12 22:26:10 +00:00
{ID} return type_or_name(yytext);
@{ID} {
int tok = type_or_name(yytext);
if (tok == '@')
REJECT;
return tok;
}
@ return '@';
\"(\\.|[^"\\])*\" {
2007-03-31 15:27:36 +00:00
yylval.string_val = make_string (yytext, 0);
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.quaternion_val[0],
&yylval.quaternion_val[1],
&yylval.quaternion_val[2],
&yylval.quaternion_val[3]);
2002-01-04 08:45:24 +00:00
return QUATERNION_VAL;
}
'(\\[^xX0-7\r\n]|[^'\r\n]|\\[xX][0-9A-Fa-f]+|\\[0-7]+)*' {
2007-03-31 15:27:36 +00:00
const char *str = make_string (yytext, 0);
2002-01-04 08:45:24 +00:00
if (str[1])
warning (0, "multibyte char constant");
yylval.integer_val = *str;
return INT_VAL;
}
[+\-*/&|^%]= {
yylval.op = yytext[0];
return ASX;
}
"<<=" {
yylval.op = SHL;
return ASX;
}
">>=" {
yylval.op = SHR;
return ASX;
}
[!(){}.*/&|^~+\-=\[\];,#%?:] {
return yytext[0];
}
"..." return ELLIPSIS;
"<<" return SHL;
">>" return SHR;
"&&" return AND;
"||" return OR;
"==" return EQ;
"!=" return NE;
"<=" return LE;
">=" return GE;
"<" return LT;
">" return GT;
"++" {
yylval.op = '+';
return INCOP;
}
"--" {
yylval.op = '-';
return INCOP;
}
2007-04-06 08:19:58 +00:00
"$"{s}*{FRAMEID} {
int ret = do_grab (yytext);
if (ret >= 0) {
yylval.integer_val = ret;
return INT_VAL;
} else {
BEGIN (-ret);
}
}
<GRAB_FRAME>{FRAMEID} add_frame_macro (yytext);
<GRAB_OTHER>[^\r\n]* /* skip */
<*>\r*\n {
pr.source_line++;
BEGIN (INITIAL);
}
<*>{s}* /* skip */
2001-06-28 21:26:40 +00:00
<*>. error (0, "all your typo are belong to us");
%%
int
yywrap (void)
{
return 1;
}
typedef struct {
const char *name;
int value;
type_t *type;
2003-04-17 00:01:48 +00:00
unsigned int traditional;
unsigned int version;
} keyword_t;
static keyword_t keywords[] = {
{"void", TYPE, &type_void, 1, PROG_ID_VERSION},
{"float", TYPE, &type_float, 1, PROG_ID_VERSION},
{"string", TYPE, &type_string, 1, PROG_ID_VERSION},
{"vector", TYPE, &type_vector, 1, PROG_ID_VERSION},
{"entity", TYPE, &type_entity, 1, PROG_ID_VERSION},
{"quaternion", TYPE, &type_quaternion, 0, PROG_VERSION},
{"integer", TYPE, &type_integer, 0, PROG_VERSION},
{"unsigned", TYPE, &type_uinteger, 0, PROG_VERSION},
{"function", TYPE, &type_function, 0, PROG_VERSION},
2002-05-09 06:37:40 +00:00
{"id", TYPE, &type_id, 0, PROG_VERSION},
{"Class", TYPE, &type_Class, 0, PROG_VERSION},
// {"Protocol", TYPE, &type_Protocol, 0, PROG_VERSION},
{"Method", TYPE, &type_Method, 0, PROG_VERSION},
2003-05-15 05:58:31 +00:00
{"Super", TYPE, &type_Super, 0, PROG_VERSION},
2002-05-17 19:47:15 +00:00
{"SEL", TYPE, &type_SEL, 0, PROG_VERSION},
{"IMP", TYPE, &type_IMP, 0, PROG_VERSION},
{"local", LOCAL, 0, 1, PROG_ID_VERSION},
{"return", RETURN, 0, 1, PROG_ID_VERSION},
{"while", WHILE, 0, 1, PROG_ID_VERSION},
{"do", DO, 0, 1, PROG_ID_VERSION},
{"if", IF, 0, 1, PROG_ID_VERSION},
{"else", ELSE, 0, 1, PROG_ID_VERSION},
{"for", FOR, 0, 0, PROG_ID_VERSION},
{"break", BREAK, 0, 1, PROG_ID_VERSION},
{"continue", CONTINUE, 0, 0, PROG_ID_VERSION},
{"switch", SWITCH, 0, 0, PROG_ID_VERSION},
{"case", CASE, 0, 0, PROG_ID_VERSION},
{"default", DEFAULT, 0, 0, PROG_ID_VERSION},
{"NIL", NIL, 0, 0, PROG_ID_VERSION},
{"struct", STRUCT, 0, 0, PROG_VERSION},
2002-06-20 20:28:01 +00:00
{"union", UNION, 0, 0, PROG_VERSION},
{"enum", ENUM, 0, 0, PROG_ID_VERSION},
{"typedef", TYPEDEF, 0, 0, PROG_ID_VERSION},
2002-05-17 19:47:15 +00:00
{"super", SUPER, 0, 0, PROG_VERSION},
{"@class", CLASS, 0, 0, PROG_VERSION},
{"@defs", DEFS, 0, 0, PROG_VERSION},
{"@encode", ENCODE, 0, 0, PROG_VERSION},
{"@end", END, 0, 0, PROG_VERSION},
{"@implementation", IMPLEMENTATION, 0, 0, PROG_VERSION},
{"@interface", INTERFACE, 0, 0, PROG_VERSION},
{"@private", PRIVATE, 0, 0, PROG_VERSION},
{"@protected", PROTECTED, 0, 0, PROG_VERSION},
{"@protocol", PROTOCOL, 0, 0, PROG_VERSION},
{"@public", PUBLIC, 0, 0, PROG_VERSION},
{"@reference", REFERENCE, 0, 0, PROG_VERSION},
{"@selector", SELECTOR, 0, 0, PROG_VERSION},
{"@self", SELF, 0, 0, PROG_VERSION},
{"@this", THIS, 0, 0, PROG_VERSION},
{"@args", ARGS, 0, 0, PROG_VERSION},
{"@va_list", TYPE, &type_va_list, 0, PROG_VERSION},
{"@param", TYPE, &type_param, 0, PROG_VERSION},
{"@extern", EXTERN, 0, 1, PROG_ID_VERSION},
{"@static", STATIC, 0, 1, PROG_ID_VERSION},
{"@system", SYSTEM, 0, 1, PROG_ID_VERSION},
2002-08-18 04:08:02 +00:00
{"@sizeof", SIZEOF, 0, 0, PROG_VERSION},
{"@overload", OVERLOAD, 0, 0, PROG_VERSION},
};
static const char *
keyword_get_key (void *kw, void *unused)
{
return ((keyword_t*)kw)->name;
}
static int
type_or_name (char *token)
{
static hashtab_t *keyword_tab;
keyword_t *keyword;
typedef_t *typename;
2002-08-18 04:08:02 +00:00
class_t *class;
if (!keyword_tab) {
size_t i;
keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0);
for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++)
if (keywords[i].traditional >= options.traditional
&& keywords[i].version <= options.code.progsversion)
2001-08-07 16:50:22 +00:00
Hash_Add (keyword_tab, &keywords[i]);
}
keyword = Hash_Find (keyword_tab, token);
if (keyword) {
if (!options.traditional && token[0] == '@'
&& !class_Class.super_class)
class_init ();
yylval.type = keyword->type;
return keyword->value;
}
if (token[0] == '@') {
return '@';
}
if ((typename = get_typedef (token))) {
yylval.typename = typename;
return TYPE_NAME;
}
if (!get_enum (token)) {
if ((class = get_class (token, 0))) {
yylval.string_val = save_string (token);
return CLASS_NAME;
}
2002-08-18 04:08:02 +00:00
}
yylval.string_val = save_string (token);
return NAME;
}
2003-04-16 19:41:52 +00:00
#ifdef YY_FLEX_REALLOC_HACK
2008-07-19 05:40:57 +00:00
static __attribute__ ((used)) void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc;
2003-04-17 00:25:55 +00:00
#else
2008-07-19 05:40:57 +00:00
static __attribute__ ((used)) void (*yyunput_hack)(int, char*) = yyunput;
static __attribute__ ((used)) int (*input_hack)(void) = input;
2003-04-17 00:14:13 +00:00
#endif