good bye, old parser

This commit is contained in:
Bill Currie 2001-08-10 18:35:55 +00:00
parent 9e46265046
commit 4388bf0519
10 changed files with 9 additions and 1305 deletions

View file

@ -5,9 +5,6 @@
#define __config_h_
@TOP@
/* Define this if you want to use the new parser */
#undef NEW_PARSER
/* Define this to your operating system's path separator character */
#undef PATH_SEPARATOR

View file

@ -92,20 +92,9 @@ if test "x$HAVE_QF" != xno; then
)
fi
AC_ARG_ENABLE(new-parser,
[ --disable-new-parser disable the new parser.]
)
if test "x$enable_new_parser" != "xno"; then
AC_DEFINE(NEW_PARSER)
fi
AM_CONDITIONAL(NEW_PARSER, test "x$enable_new_parser" != "xno")
AC_ARG_ENABLE(cpp,
[ --enable-cpp Enable use of the C preprocessor.],
if test "x$enable_new_parser" != "xno"; then
AC_DEFINE(USE_CPP)
fi
)
if test "x$HAVE_QF" = xno; then

View file

@ -33,9 +33,5 @@ YFLAGS = -d
bin_PROGRAMS= qfcc
if NEW_PARSER
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c qc-parse.y qc-lex.l emit.c expr.c
else
qfcc_SOURCES= cmdlib.c debug.c pr_comp.c pr_def.c pr_imm.c pr_lex.c pr_opcode.c qfcc.c
endif
qfcc_LDADD= -lQFgamecode -lQFutil

View file

@ -140,519 +140,3 @@ PrecacheFile (def_t *e, int ch)
numfiles++;
}
/*
PR_ParseFunctionCall
*/
def_t *
PR_ParseFunctionCall (def_t *func)
{
def_t *e;
int arg;
type_t *t;
opcode_t *op;
t = func->type;
if (t->type != ev_func)
PR_ParseError ("not a function");
// copy the arguments to the global parameter variables
arg = 0;
if (!PR_Check (tt_punct, ")")) {
do {
if (t->num_parms != -1 && arg >= t->num_parms)
PR_ParseError ("too many parameters");
e = PR_Expression (TOP_PRIORITY);
if (arg == 0 && func->name) {
// save information for model and sound caching
if (!strncmp (func->name, "precache_sound", 14))
PrecacheSound (e, func->name[14]);
else if (!strncmp (func->name, "precache_model", 14))
PrecacheModel (e, func->name[14]);
else if (!strncmp (func->name, "precache_file", 13))
PrecacheFile (e, func->name[13]);
}
if (t->num_parms != -1 && (e->type != t->parm_types[arg]))
PR_ParseError ("type mismatch on parm %i", arg);
// a vector copy will copy everything
def_parms[arg].type = t->parm_types[arg];
op = PR_Opcode_Find ("=", 5, e, e, e);
PR_Statement (op, e, &def_parms[arg]);
arg++;
} while (PR_Check (tt_punct, ","));
if (t->num_parms != -1 && arg != t->num_parms)
PR_ParseError ("too few parameters");
PR_Expect (tt_punct, ")");
}
if (arg > 8)
PR_ParseError ("More than eight parameters");
op = PR_Opcode_Find (va ("<CALL%d>", arg), -1, &def_function, &def_void, &def_void);
PR_Statement (op, func, 0);
def_ret.type = t->aux_type;
return &def_ret;
}
/*
PR_ParseValue
Return the global offset for the current token
*/
def_t *
PR_ParseValue (void)
{
def_t *d;
char *name;
// if the token is an immediate, allocate a constant for it
if (pr_token_type == tt_immediate)
return PR_ParseImmediate (0);
name = PR_ParseName ();
// look through the defs
if (!(d = PR_GetDef (NULL, name, pr_scope, false)))
PR_ParseError ("Unknown value \"%s\"", name);
return d;
}
/*
PR_Term
*/
def_t *
PR_Term (void)
{
def_t *e;
opcode_t *op;
if (PR_Check (tt_punct, "!")) {
e = PR_Expression (NOT_PRIORITY);
op = PR_Opcode_Find ("!", -1, e, &def_void, &def_float);
if (op) {
return PR_Statement (op, e, 0);
} else {
PR_ParseError ("Type mismatch for !");
return NULL;
}
}
if (PR_Check (tt_punct, "(")) {
e = PR_Expression (TOP_PRIORITY);
PR_Expect (tt_punct, ")");
return e;
}
return PR_ParseValue ();
}
/*
PR_Expression
*/
def_t *
PR_Expression (int priority)
{
opcode_t *op, *oldop;
def_t *e, *e2;
def_t var_c;
char *token;
if (!priority)
return PR_Term ();
e = PR_Expression (priority - 1);
while (1) {
if (priority == 1 && PR_Check (tt_punct, "("))
return PR_ParseFunctionCall (e);
op = PR_Opcode_Find (pr_token, priority, 0, 0, 0);
if (op) {
token = strdup (pr_token);
PR_Lex ();
if (op->right_associative) {
// if last statement is an indirect, change it to an address of
if ((unsigned) (statements[numstatements - 1].op - OP_LOAD_F) < 6) {
statements[numstatements - 1].op = OP_ADDRESS;
def_pointer.type->aux_type = e->type;
e->type = def_pointer.type;
}
e2 = PR_Expression (priority);
} else {
e2 = PR_Expression (priority - 1);
}
// type check
if (op->name[0] == '.') { // field access gets type from field
var_c.type = e2->type->aux_type;
} else {
var_c.type = &type_void;
}
oldop = op;
op = PR_Opcode_Find (token, priority, e, e2, &var_c);
free (token);
if (!op)
PR_ParseError ("type mismatch for %s", oldop->name);
if (e->type->type == ev_pointer && e2->type->type != e->type->aux_type->type)
PR_ParseError ("type mismatch for %s", op->name);
if (op->right_associative) {
if (e->initialized) {
if (options.cow) {
int size = type_size [e->type->type];
int ofs = PR_NewLocation (e->type);
memcpy (pr_globals + ofs, pr_globals + e->ofs, size);
e->ofs = ofs;
e->initialized = 0;
} else {
PR_ParseError ("assignment to constant: %s", e->name);
}
}
e = PR_Statement (op, e2, e);
} else {
e = PR_Statement (op, e, e2);
}
if (var_c.type != &type_void) // field access gets type from field
e->type = e2->type->aux_type;
}
if (!op) // next token isn't at this priority level
break;
}
return e;
}
/*
PR_ParseStatement
*/
void
PR_ParseStatement (void)
{
def_t *e;
dstatement_t *patch1, *patch2;
PR_FreeTempDefs ();
do {
if (PR_Check (tt_punct, "{")) {
do {
PR_ParseStatement ();
} while (!PR_Check (tt_punct, "}"));
break;
}
if (PR_Check (tt_name, "return")) {
if (PR_Check (tt_punct, ";")) {
PR_Statement (op_return, 0, 0);
break;
}
e = PR_Expression (TOP_PRIORITY);
PR_Expect (tt_punct, ";");
PR_Statement (op_return, e, 0);
break;
}
if (PR_Check (tt_name, "while")) {
PR_Expect (tt_punct, "(");
patch2 = &statements[numstatements];
e = PR_Expression (TOP_PRIORITY);
PR_Expect (tt_punct, ")");
patch1 = &statements[numstatements];
PR_Statement (op_ifnot, e, 0);
PR_FreeTempDefs ();
PR_ParseStatement ();
junkdef.ofs = patch2 - &statements[numstatements];
PR_Statement (op_goto, &junkdef, 0);
patch1->b = &statements[numstatements] - patch1;
break;
}
if (PR_Check (tt_name, "do")) {
patch1 = &statements[numstatements];
PR_ParseStatement ();
PR_Expect (tt_name, "while");
PR_Expect (tt_punct, "(");
e = PR_Expression (TOP_PRIORITY);
PR_Expect (tt_punct, ")");
PR_Expect (tt_punct, ";");
junkdef.ofs = patch1 - &statements[numstatements];
PR_Statement (op_if, e, &junkdef);
break;
}
if (PR_Check (tt_name, "local")) {
PR_ParseDefs ();
locals_end = numpr_globals;
break;
}
if (PR_Check (tt_name, "if")) {
PR_Expect (tt_punct, "(");
e = PR_Expression (TOP_PRIORITY);
PR_Expect (tt_punct, ")");
PR_FreeTempDefs ();
patch1 = &statements[numstatements];
PR_Statement (op_ifnot, e, 0);
PR_ParseStatement ();
if (PR_Check (tt_name, "else")) {
patch2 = &statements[numstatements];
PR_Statement (op_goto, 0, 0);
patch1->b = &statements[numstatements] - patch1;
PR_ParseStatement ();
patch2->a = &statements[numstatements] - patch2;
} else {
patch1->b = &statements[numstatements] - patch1;
}
break;
}
PR_Expression (TOP_PRIORITY);
PR_Expect (tt_punct, ";");
} while (0);
PR_FreeTempDefs ();
}
/*
PR_ParseState
States are special functions made for convenience. They automatically
set frame, nextthink (implicitly), and think (allowing forward definitions).
void() name = [framenum, nextthink] {code}
expands to:
function void name ()
{
self.frame=framenum;
self.nextthink = time + 0.1;
self.think = nextthink
<code>
};
Weird, huh? :)
*/
void
PR_ParseState (void)
{
char *name;
def_t *s1, *def;
if (pr_token_type != tt_immediate || pr_immediate_type != &type_float)
PR_ParseError ("state frame must be a number");
s1 = PR_ParseImmediate (0);
PR_Expect (tt_punct, ",");
name = PR_ParseName ();
def = PR_GetDef (&type_function, name, 0, &numpr_globals);
PR_Expect (tt_punct, "]");
PR_Statement (op_state, s1, def);
}
/*
PR_ParseImmediateStatements
Parse a function body
*/
function_t *
PR_ParseImmediateStatements (type_t *type)
{
int i;
function_t *f;
def_t *defs[MAX_PARMS];
f = malloc (sizeof (function_t));
f->next = pr_functions;
pr_functions = f;
// check for builtin function definition #1, #2, etc
if (PR_Check (tt_punct, "#")) {
if (pr_token_type != tt_immediate
|| pr_immediate_type != &type_float
|| pr_immediate._float != (int) pr_immediate._float) {
PR_ParseError ("Bad builtin immediate");
}
f->builtin = (int) pr_immediate._float;
PR_Lex ();
return f;
}
f->builtin = 0;
// define the parms
for (i = 0; i < type->num_parms; i++) {
defs[i] = PR_GetDef (type->parm_types[i], pr_parm_names[i], pr_scope, &pr_scope->num_locals);
f->parm_ofs[i] = defs[i]->ofs;
if (i > 0 && f->parm_ofs[i] < f->parm_ofs[i - 1])
Error ("bad parm order");
}
f->code = numstatements;
// check for a state opcode
if (PR_Check (tt_punct, "["))
PR_ParseState ();
// parse regular statements
PR_Expect (tt_punct, "{");
while (!PR_Check (tt_punct, "}"))
PR_ParseStatement ();
// emit an end of statements opcode
PR_Statement (op_done, 0, 0);
return f;
}
/*
PR_ParseDefs
Called at the outer layer and when a local statement is hit
*/
void
PR_ParseDefs (void)
{
char *name;
type_t *type;
def_t *def;
function_t *f;
dfunction_t *df;
int i;
int locals_start;
type = PR_ParseType ();
if (pr_scope && (type->type == ev_field || type->type == ev_func))
PR_ParseError ("Fields and functions must be global");
do {
name = PR_ParseName ();
def = PR_GetDef (type, name, pr_scope, pr_scope ? &pr_scope->num_locals : &numpr_globals);
// check for an initialization
if (PR_Check (tt_punct, "=")) {
if (def->initialized)
PR_ParseError ("%s redeclared", name);
if (type->type == ev_func) {
locals_start = locals_end = numpr_globals;
pr_scope = def;
f = PR_ParseImmediateStatements (type);
PR_FlushScope (pr_scope);
PR_ResetTempDefs ();
pr_scope = NULL;
def->initialized = 1;
G_FUNCTION (def->ofs) = numfunctions;
f->def = def;
// if (pr_dumpasm)
// PR_PrintFunction (def);
// fill in the dfunction
df = &functions[numfunctions];
numfunctions++;
f->dfunc = df;
if (f->builtin)
df->first_statement = -f->builtin;
else
df->first_statement = f->code;
df->s_name = ReuseString (f->def->name);
df->s_file = s_file;
df->numparms = f->def->type->num_parms;
df->locals = f->def->num_locals;
df->parm_start = locals_start;
for (i = 0; i < df->numparms; i++)
df->parm_size[i] = type_size[f->def->type->parm_types[i]->type];
continue;
} else if (pr_immediate_type != type) {
PR_ParseError ("wrong immediate type for %s", name);
}
if (pr_scope) {
def_t *imm = PR_ParseImmediate (0);
opcode_t *op = PR_Opcode_Find ("=", 5, imm, imm, def);
PR_Statement (op, imm, def);
} else {
def = PR_ParseImmediate (def);
}
}
} while (PR_Check (tt_punct, ","));
PR_Expect (tt_punct, ";");
}
/*
PR_CompileFile
Compile the null-terminated text, adding definitions to the pr structure
*/
qboolean
PR_CompileFile (char *string, const char *filename)
{
if (!pr.memory)
Error ("PR_CompileFile: Didn't clear");
PR_ClearGrabMacros (); // clear the frame macros
pr_file_p = string;
s_file = ReuseString (filename);
pr_source_line = 0;
PR_NewLine ();
PR_Lex (); // read first token
while (pr_token_type != tt_eof) {
if (setjmp (pr_parse_abort)) {
if (++pr_error_count > MAX_ERRORS)
return false;
PR_SkipToSemicolon ();
if (pr_token_type == tt_eof)
return false;
}
pr_scope = NULL; // outside all functions
PR_ParseDefs ();
}
return (pr_error_count == 0);
}

View file

@ -71,7 +71,7 @@ PR_GetDef (type_t *type, const char *name, def_t *scope, int *allocate)
if (def) {
if (allocate && scope == def->scope)
if (type && def->type != type)
PR_ParseError ("Type mismatch on redeclaration of %s", name);
error (0, "Type mismatch on redeclaration of %s", name);
if (!allocate || def->scope == scope)
return def;
}

View file

@ -81,84 +81,6 @@ int_imm_get_key (void *_def, void *_str)
return rep;
}
/*
PR_ParseImmediate
Looks for a preexisting constant
*/
def_t *
PR_ParseImmediate (def_t *def)
{
def_t *cn = 0;
char rep[60];
hashtab_t *tab = 0;
if (!string_imm_defs) {
string_imm_defs = Hash_NewTable (16381, string_imm_get_key, 0, 0);
float_imm_defs = Hash_NewTable (16381, float_imm_get_key, 0, 0);
vector_imm_defs = Hash_NewTable (16381, vector_imm_get_key, 0, 0);
}
if (def && def->type != pr_immediate_type) {
PR_ParseError ("type mismatch for immediate value");
}
if (pr_immediate_type == &type_string) {
cn = (def_t*) Hash_Find (string_imm_defs, pr_immediate_string);
tab = string_imm_defs;
//printf ("%s\n",pr_immediate_string);
} else if (pr_immediate_type == &type_float) {
sprintf (rep, "\001float:%08X\001", *(int*)&pr_immediate._float);
cn = (def_t*) Hash_Find (float_imm_defs, rep);
tab = float_imm_defs;
//printf ("%f\n",pr_immediate._float);
} else if (pr_immediate_type == &type_vector) {
sprintf (rep, "\001vector:%08X\001%08X\001%08X\001",
*(int*)&pr_immediate.vector[0],
*(int*)&pr_immediate.vector[1],
*(int*)&pr_immediate.vector[2]);
cn = (def_t*) Hash_Find (vector_imm_defs, rep);
tab = vector_imm_defs;
//printf ("%f %f %f\n",pr_immediate.vector[0], pr_immediate.vector[1], pr_immediate.vector[2]);
} else {
PR_ParseError ("weird immediate type");
}
if (cn) {
if (cn->type != pr_immediate_type)
printf("urk\n");
//printf("found\n");
if (def) {
PR_FreeLocation (def);
def->ofs = cn->ofs;
def->initialized = 1;
cn = def;
}
PR_Lex ();
return cn;
}
// allocate a new one
// always share immediates
if (def) {
cn = def;
} else {
cn = PR_NewDef (pr_immediate_type, ".imm", 0);
cn->ofs = PR_NewLocation (pr_immediate_type);
pr_global_defs[cn->ofs] = cn;
}
cn->initialized = 1;
// copy the immediate to the global area
if (pr_immediate_type == &type_string)
pr_immediate.string = CopyString (pr_immediate_string);
memcpy (pr_globals + cn->ofs, &pr_immediate,
4 * type_size[pr_immediate_type->type]);
Hash_Add (tab, cn);
PR_Lex ();
return cn;
}
def_t *
PR_ReuseConstant (expr_t *expr, def_t *def)
{

View file

@ -85,74 +85,6 @@ def_t *def_for_type[8] = {
&def_entity, &def_field, &def_function, &def_pointer
};
void PR_LexWhitespace (void);
void PR_LexString (void);
/*
PR_PrintNextLine
*/
void
PR_PrintNextLine (void)
{
char *t;
printf ("%3i:", pr_source_line);
for (t = pr_line_start; *t && *t != '\n'; t++)
printf ("%c", *t);
printf ("\n");
}
/*
PR_NewLine
Call at start of file and when *pr_file_p == '\n'
*/
void
PR_NewLine (void)
{
qboolean m;
if (*pr_file_p == '\n') {
pr_file_p++;
m = true;
} else
m = false;
if (*pr_file_p == '#') {
char *p;
int line;
pr_file_p ++; // skip over #
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
if (!*pr_file_p)
PR_ParseError ("Unexpected end of file");
while (*pr_file_p && *pr_file_p != '\n') // ignore flags
pr_file_p++;
if (!*pr_file_p)
PR_ParseError ("Unexpected end of file");
pr_source_line = line - (m != false);
s_file = ReuseString (pr_immediate_string);
if (!m)
pr_file_p++;
m = false;
}
pr_source_line++;
pr_line_start = pr_file_p;
// if (pr_dumpasm)
// PR_PrintNextLine ();
if (m)
pr_file_p--;
}
/*
PR_LexString
@ -174,13 +106,13 @@ PR_LexString (void)
do {
c = *pr_file_p++;
if (!c)
PR_ParseError ("EOF inside quote");
error (0, "EOF inside quote");
if (c == '\n')
PR_ParseError ("newline inside quote");
error (0, "newline inside quote");
if (c == '\\') { // escape char
c = *pr_file_p++;
if (!c)
PR_ParseError ("EOF inside quote");
error (0, "EOF inside quote");
switch (c) {
case 'n':
c = '\n';
@ -203,7 +135,7 @@ PR_LexString (void)
c += *pr_file_p - '0';
}
if (!*pr_file_p)
PR_ParseError ("EOF inside quote");
error (0, "EOF inside quote");
break;
case 'x':
c = 0;
@ -218,7 +150,7 @@ PR_LexString (void)
pr_file_p++;
}
if (!*pr_file_p)
PR_ParseError ("EOF inside quote");
error (0, "EOF inside quote");
break;
case 'a':
c = '\a';
@ -243,7 +175,7 @@ PR_LexString (void)
break;
case '^':
if (*pr_file_p == '\"')
PR_ParseError ("Unexpected end of string after \\^");
error (0, "Unexpected end of string after \\^");
boldnext = 1;
continue;
case '<':
@ -253,7 +185,7 @@ PR_LexString (void)
mask = 0x00;
continue;
default:
PR_ParseError ("Unknown escape char");
error (0, "Unknown escape char");
break;
}
} else if (c == '\"') {
@ -272,484 +204,6 @@ PR_LexString (void)
} while (1);
}
/*
PR_LexNumber
Parse a number
*/
float
PR_LexNumber (void)
{
int c;
int len;
len = 0;
c = *pr_file_p;
do {
pr_token[len] = c;
len++;
pr_file_p++;
c = *pr_file_p;
} while ((c >= '0' && c <= '9') || c == '.');
pr_token[len] = 0;
return atof (pr_token);
}
/*
PR_LexVector
Parses a single quoted vector
*/
void
PR_LexVector (void)
{
int i;
pr_file_p++;
pr_token_type = tt_immediate;
pr_immediate_type = &type_vector;
for (i = 0; i < 3; i++) {
pr_immediate.vector[i] = PR_LexNumber ();
PR_LexWhitespace ();
}
if (*pr_file_p != '\'')
PR_ParseError ("Bad vector");
pr_file_p++;
}
/*
PR_LexName
Parse an identifier
*/
void
PR_LexName (void)
{
int c;
int len;
len = 0;
c = *pr_file_p;
do {
pr_token[len] = c;
len++;
pr_file_p++;
c = *pr_file_p;
} while ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
|| (c >= '0' && c <= '9'));
pr_token[len] = 0;
pr_token_type = tt_name;
}
/*
PR_LexPunctuation
*/
void
PR_LexPunctuation (void)
{
char *p = 0;
int len = 1;
pr_token_type = tt_punct;
switch (pr_file_p[0]) {
case '&':
if (pr_file_p[1] == '&') {
p = "&&";
len = 2;
} else {
p = "&";
}
break;
case '|':
if (pr_file_p[1] == '|') {
p = "||";
len = 2;
} else {
p = "|";
}
break;
case '^':
p = "^";
break;
case '<':
if (pr_file_p[1] == '=') {
p = "<=";
len = 2;
} else {
p = "<";
}
break;
case '>':
if (pr_file_p[1] == '=') {
p = ">=";
len = 2;
} else {
p = ">";
}
break;
case '=':
if (pr_file_p[1] == '=') {
p = "==";
len = 2;
} else {
p = "=";
}
break;
case '!':
if (pr_file_p[1] == '=') {
p = "!=";
len = 2;
} else {
p = "!";
}
break;
case ';':
p = ";";
break;
case ',':
p = ",";
break;
case '*':
p = "*";
break;
case '/':
p = "/";
break;
case '(':
p = "(";
break;
case ')':
p = ")";
break;
case '-':
p = "-";
break;
case '+':
p = "+";
break;
case '[':
p = "[";
break;
case ']':
p = "]";
break;
case '{':
p = "{";
break;
case '}':
p = "}";
break;
case '.':
if (pr_file_p[1] == '.' && pr_file_p[2] == '.') {
p = "...";
len = 3;
} else {
p = ".";
}
break;
case '#':
p = "#";
break;
}
if (p) {
strcpy (pr_token, p);
if (p[0] == '{')
pr_bracelevel++;
else if (p[0] == '}')
pr_bracelevel--;
pr_file_p += len;
return;
}
PR_ParseError ("Unknown punctuation");
}
/*
PR_LexWhitespace
Skip whitespace and comments
*/
void
PR_LexWhitespace (void)
{
int c;
while (1) {
// skip whitespace
while ((c = *pr_file_p) <= ' ') {
if (c == '\n')
PR_NewLine ();
if (!c)
return; // end of file
pr_file_p++;
}
// skip // comments
if (c == '/' && pr_file_p[1] == '/') {
while (*pr_file_p && *pr_file_p != '\n')
pr_file_p++;
PR_NewLine ();
pr_file_p++;
continue;
}
// skip /* */ comments
if (c == '/' && pr_file_p[1] == '*') {
do {
pr_file_p++;
if (pr_file_p[0] == '\n')
PR_NewLine ();
if (pr_file_p[1] == 0)
return;
} while (pr_file_p[-1] != '*' || pr_file_p[0] != '/');
pr_file_p++;
continue;
}
break; // a real character has been found
}
}
//============================================================================
#define MAX_FRAMES 256
char pr_framemacros[MAX_FRAMES][16];
int pr_nummacros;
void
PR_ClearGrabMacros (void)
{
pr_nummacros = 0;
}
void
PR_FindMacro (void)
{
int i;
for (i = 0; i < pr_nummacros; i++) {
if (!strcmp (pr_token, pr_framemacros[i])) {
sprintf (pr_token, "%d", i);
pr_token_type = tt_immediate;
pr_immediate_type = &type_float;
pr_immediate._float = i;
return;
}
}
PR_ParseError ("Unknown frame macro $%s", pr_token);
}
/*
PR_SimpleGetToken
Just parses text, returning false if an eol is reached
*/
qboolean
PR_SimpleGetToken (void)
{
int c;
int i;
// skip whitespace
while ((c = *pr_file_p) <= ' ') {
if (c == '\n' || c == 0)
return false;
pr_file_p++;
}
i = 0;
while ((c = *pr_file_p) > ' ' && c != ',' && c != ';') {
pr_token[i++] = c;
pr_file_p++;
}
pr_token[i] = 0;
return true;
}
void
PR_ParseFrame (void)
{
while (PR_SimpleGetToken ()) {
strcpy (pr_framemacros[pr_nummacros], pr_token);
pr_nummacros++;
}
}
/*
PR_LexGrab
Deals with counting sequence numbers and replacing frame macros
*/
void
PR_LexGrab (void)
{
pr_file_p++; // skip the $
if (!PR_SimpleGetToken ())
PR_ParseError ("hanging $");
// check for $frame
if (!strcmp (pr_token, "frame")) {
PR_ParseFrame ();
PR_Lex ();
} else if (!strcmp (pr_token, "cd") // ignore other known $commands
|| !strcmp (pr_token, "origin")
|| !strcmp (pr_token, "base")
|| !strcmp (pr_token, "flags")
|| !strcmp (pr_token, "scale")
|| !strcmp (pr_token, "skin")) { // skip to end of line
while (PR_SimpleGetToken ());
PR_Lex ();
} else { // look for a frame name macro
PR_FindMacro ();
}
}
//============================================================================
/*
PR_Lex
Sets pr_token, pr_token_type, and possibly pr_immediate and pr_immediate_type
*/
void
PR_Lex (void)
{
int c;
pr_token[0] = 0;
if (!pr_file_p) {
pr_token_type = tt_eof;
return;
}
PR_LexWhitespace ();
c = *pr_file_p;
if (!c) {
pr_token_type = tt_eof;
return;
}
if (c == '\"') { // handle quoted strings as a unit
PR_LexString ();
return;
}
if (c == '\'') { // handle quoted vectors as a unit
PR_LexVector ();
return;
}
// if the first character is a valid identifier, parse until a non-id
// character is reached
if ((c >= '0' && c <= '9')
|| (c == '-' && pr_file_p[1] >= '0' && pr_file_p[1] <= '9')) {
pr_token_type = tt_immediate;
pr_immediate_type = &type_float;
pr_immediate._float = PR_LexNumber ();
return;
}
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') {
PR_LexName ();
return;
}
if (c == '$') {
PR_LexGrab ();
return;
}
// parse symbol strings until a non-symbol is found
PR_LexPunctuation ();
}
//=============================================================================
/*
PR_ParseError
Aborts the current file load
*/
void
PR_ParseError (const char *error, ...)
{
va_list argptr;
char string[1024];
va_start (argptr, error);
vsprintf (string, error, argptr);
va_end (argptr);
printf ("%s:%i:%s\n", strings + s_file, pr_source_line, string);
#ifndef NEW_PARSER
longjmp (pr_parse_abort, 1);
#endif
}
/*
PR_Expect
Gets the next token. Will issue an error if the current token isn't equal
to string
*/
void
PR_Expect (token_type_t type, const char *string)
{
if (type != pr_token_type || strcmp (string, pr_token))
PR_ParseError ("expected %s, found %s", string, pr_token);
PR_Lex ();
}
/*
PR_Check
If current token equals string, get next token and return true.
Otherwise, return false and do nothing else.
*/
qboolean
PR_Check (token_type_t type, const char *string)
{
if (type != pr_token_type || strcmp (string, pr_token))
return false;
PR_Lex ();
return true;
}
/*
PR_ParseName
Checks to see if the current token is a valid name
*/
char *
PR_ParseName (void)
{
static char ident[MAX_NAME];
if (pr_token_type != tt_name)
PR_ParseError ("not a name");
if (strlen (pr_token) >= MAX_NAME - 1)
PR_ParseError ("name too long");
strcpy (ident, pr_token);
PR_Lex ();
return ident;
}
void
PR_PrintType (type_t *type)
{
@ -847,85 +301,4 @@ PR_FindType (type_t *type)
return check;
}
/*
PR_SkipToSemicolon
For error recovery, also pops out of nested braces
*/
void
PR_SkipToSemicolon (void)
{
do {
if (!pr_bracelevel && PR_Check (tt_punct, ";"))
return;
PR_Lex ();
} while (pr_token[0]); // eof will return a null token
}
char pr_parm_names[MAX_PARMS][MAX_NAME];
/*
PR_ParseType
Parses a variable type, including field and functions types
*/
type_t *
PR_ParseType (void)
{
type_t new;
type_t *type;
char *name;
if (PR_Check (tt_punct, ".")) {
memset (&new, 0, sizeof (new));
new.type = ev_field;
new.aux_type = PR_ParseType ();
return PR_FindType (&new);
}
if (!strcmp (pr_token, "float"))
type = &type_float;
else if (!strcmp (pr_token, "vector"))
type = &type_vector;
else if (!strcmp (pr_token, "float"))
type = &type_float;
else if (!strcmp (pr_token, "entity"))
type = &type_entity;
else if (!strcmp (pr_token, "string"))
type = &type_string;
else if (!strcmp (pr_token, "void"))
type = &type_void;
else {
PR_ParseError ("\"%s\" is not a type", pr_token);
type = &type_float; // shut up compiler warning
}
PR_Lex ();
if (!PR_Check (tt_punct, "("))
return type;
// function type
memset (&new, 0, sizeof (new));
new.type = ev_func;
new.aux_type = type; // return type
new.num_parms = 0;
if (!PR_Check (tt_punct, ")")) {
if (PR_Check (tt_punct, "...")) {
new.num_parms = -1; // variable args
} else {
do {
type = PR_ParseType ();
name = PR_ParseName ();
strcpy (pr_parm_names[new.num_parms], name);
new.parm_types[new.num_parms] = type;
new.num_parms++;
} while (PR_Check (tt_punct, ","));
}
PR_Expect (tt_punct, ")");
}
return PR_FindType (&new);
}

View file

@ -36,17 +36,6 @@ opcode_t *op_ifnot;
opcode_t *op_state;
opcode_t *op_goto;
static type_t *types[] = {
&type_void,
&type_string,
&type_float,
&type_vector,
&type_entity,
&type_field,
&type_function,
&type_pointer,
};
statref_t *
PR_NewStatref (dstatement_t *st, int field)
{
@ -66,42 +55,6 @@ PR_AddStatementRef (def_t *def, dstatement_t *st, int field)
}
}
/*
PR_Statement
Emits a primitive statement, returning the var it places it's value in
*/
def_t *
PR_Statement (opcode_t * op, def_t * var_a, def_t * var_b)
{
dstatement_t *statement;
def_t *var_c;
statement = &statements[numstatements];
numstatements++;
statement_linenums[statement - statements] = pr_source_line;
statement->op = op->opcode;
statement->a = var_a ? var_a->ofs : 0;
statement->b = var_b ? var_b->ofs : 0;
if (op->type_c == ev_void || op->right_associative) {
// ifs, gotos, and assignments don't need vars allocated
var_c = NULL;
statement->c = 0;
} else { // allocate result space
var_c = PR_GetTempDef (types[op->type_c], pr_scope);
statement->c = var_c->ofs;
}
PR_AddStatementRef (var_a, statement, 0);
PR_AddStatementRef (var_b, statement, 1);
PR_AddStatementRef (var_c, statement, 2);
if (op->right_associative)
return var_a;
return var_c;
}
static const char *
get_key (void *_op, void *_tab)
{

View file

@ -87,7 +87,7 @@ m ([\-+]?)
while (isspace (*pr_file_p))
pr_file_p++;
if (!*pr_file_p)
PR_ParseError ("Unexpected end of file");
error (0, "Unexpected end of file");
PR_LexString (); // grab the filename
while (*pr_file_p && *pr_file_p != '\n') // ignore flags
pr_file_p++;

View file

@ -1023,7 +1023,6 @@ main (int argc, char **argv)
// compile all the files
while ((src = COM_Parse (src))) {
#ifdef NEW_PARSER
#ifdef USE_CPP
pid_t pid;
char *temp1;
@ -1114,15 +1113,6 @@ main (int argc, char **argv)
#endif
if (error)
return 1;
#else
char *src2;
sprintf (filename, "%s%c%s", sourcedir, PATH_SEPARATOR, com_token);
if (!options.quiet)
printf ("compiling %s\n", filename);
LoadFile (filename, (void *) &src2);
if (!PR_CompileFile (src2, filename))
return 1;
#endif
}
if (!PR_FinishCompilation ())