示例#1
0
static void ParseUnion (void)
{
	const char	*name;
	type_t	*type;
	int	startFieldOffset;
	int	highestFieldOffset;

	LX_Require("{");
	startFieldOffset = pr.size_fields;
	highestFieldOffset = startFieldOffset;
	do
	{
		if (LX_CheckFetch("struct"))
		{
			pr.size_fields = startFieldOffset;
			LX_Require("{");
			do
			{
				type = ParseUnionType();
				do
				{
					name = PR_ParseName();
					PR_GetDef(type, name, pr_scope, true);
				} while (TK_CHECK(TK_COMMA));

				LX_Require(";");
			} while (pr_tokenclass != TK_RBRACE);

			LX_Require("}");
			LX_Require(";");
			if (pr.size_fields > highestFieldOffset)
			{
				highestFieldOffset = pr.size_fields;
			}
		}
		else
		{
			type = ParseUnionType();
			do
			{
				name = PR_ParseName();
				pr.size_fields = startFieldOffset;
				PR_GetDef(type, name, pr_scope, true);
				if (pr.size_fields > highestFieldOffset)
				{
					highestFieldOffset = pr.size_fields;
				}
			} while (TK_CHECK(TK_COMMA));

			LX_Require(";");
		}
	} while (pr_tokenclass != TK_RBRACE);

	LX_Require("}");
	LX_Require(";");
	pr.size_fields = highestFieldOffset;
}
示例#2
0
文件: pr_lex.cpp 项目: luaman/zq
type_t *PR_ParseFunctionType (type_t *returnType)
{
	type_t	newtype;
	memset (&newtype, 0, sizeof(newtype));
	newtype.type = ev_function;
	newtype.aux_type = returnType;
	newtype.num_parms = 0;

	if (PR_Check (")")) {
		// empty args
		return PR_GetType (&newtype);
	}

	do {
		if (PR_Check ("...")) {
			// variable args
			PR_Expect (")");
			newtype.num_parms |= VA_BIT;
			return PR_GetType (&newtype);
		}

		if (newtype.num_parms >= MAX_PARMS)
			PR_ParseError ("too many parameters (max. %d allowed)", (int)MAX_PARMS);

		type_t *type = PR_ParseType ();
		char *name = PR_ParseName ();
		strlcpy (pr_parm_names[newtype.num_parms], name, sizeof(pr_parm_names[newtype.num_parms]));
		newtype.parm_types[newtype.num_parms] = type;
		newtype.num_parms++;
	} while (PR_Check (","));

	PR_Expect (")");

	return PR_GetType(&newtype);
}
示例#3
0
/*
============
PR_ParseValue

Returns the global ofs 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 ();
	
	name = PR_ParseName ();
	
// look through the defs
	d = PR_GetDef (NULL, name, pr_scope, false);
	if (!d)
		PR_ParseError ("Unknown value \"%s\"", name);	
	return d;
}
示例#4
0
文件: pr_comp.cpp 项目: luaman/zq
/*
============
PR_ParseValue

Returns the global ofs 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 ();

	name = PR_ParseName ();

// look through the defs
	d = PR_FindDef (name, pr_scope);
	if (!d)
		PR_ParseError ("'%s' : undeclared identifier", name);
	return d;
}
示例#5
0
/*
==============
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>
// };
==============
*/
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 ();
	
	PR_Expect (",");

	name = PR_ParseName ();
	def = PR_GetDef (&type_function, name,0, true);
		
	PR_Expect ("]");
	
	PR_Statement (&pr_opcodes[OP_STATE], s1, def);
}
示例#6
0
void CO_ParseDefs (void)
{
	int		i;
	const char	*name;
	def_t	*def;
	type_t	*type;
	int	elementCount;
	gofs_t	offset;

	type = PR_ParseType();

	if (type == &type_union)
	{
		if (pr_scope)
		{
			PR_ParseError("unions must be global");
		}
		ParseUnion();
		return;
	}

	if (pr_scope && (type->type == ev_field || type->type == ev_function))
	{
		PR_ParseError("fields and functions must be global");
	}

	do
	{
		name = PR_ParseName();
		if (TK_CHECK(TK_LPAREN))
		{
			ParseCStyleFunctionDef(name, type);
			return;
		}

		elementCount = 0;
		if (TK_CHECK(TK_LBRACKET))
		{
			def = GetArrayDef(name, type, &elementCount);
		}
		else
		{
			def = PR_GetDef(type, name, pr_scope, true);
		}

		// Check for initialization
		if (TK_CHECK(TK_ASSIGN))
		{
			if (def->initialized)
			{
				PR_ParseError("'%s' : redefinition", name);
			}
			if (type->type == ev_field)
			{
				PR_ParseError("fields cannot be initialized");
			}

			if (elementCount != 0)
			{
				LX_Require("{");
				i = 0;
				offset = def->ofs;
				do
				{
					if (pr_token_type != tt_immediate)
					{
						PR_ParseError("immediate type required for %s", name);
					}
					if (pr_immediate_type->type != type->type)
					{
						PR_ParseError("wrong immediate type for %s", name);
					}
					memcpy(pr_globals+offset, &pr_immediate, 4*type_size[pr_immediate_type->type]);
					offset += type_size[pr_immediate_type->type];
					i++;
					LX_Fetch();
				} while (TK_CHECK(TK_COMMA));

				LX_Require("}");
				if (i != elementCount)
				{
					PR_ParseError("element count mismatch in array"
							" initialization");
				}
				def->initialized = 1;
				continue;
			}
			else if (type->type == ev_function)
			{
				ParseFunctionDef(def, type);
				continue;
			}
			else if (pr_immediate_type != type)
			{
				PR_ParseError("wrong immediate type for %s", name);
			}
			def->initialized = 1;
			memcpy(pr_globals+def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
			LX_Fetch();
		}
		else if (elementCount != 0 && type->type != ev_field)
		{
			memset(pr_globals+def->ofs, 0, elementCount*4*type_size[type->type]);
			def->initialized = 1;
		}
	} while (TK_CHECK(TK_COMMA));

	LX_Require(";");
}
示例#7
0
static void ParseState (void)
{
	const char	*name;
	def_t	*def;
	def_t	*s1, *s2;
	int	frame1, frame2;
	int	direction;
	qboolean	weapon;

	if (pr_token_type == tt_name)
	{
		FrameIndex++;

		// Stuff a float for CO_ParseImmediate()
		pr_token_type = tt_immediate;
		pr_immediate_type = &type_float;
		pr_immediate._float = (float)FrameIndex;
		s1 = CO_ParseImmediate();

		pr_token_type = tt_name;
		name = PR_ParseName();
		def = PR_GetDef(&type_function, name, 0, true);
		LX_Require("]");
		CO_GenCode(&pr_opcodes[OP_STATE], s1, def);
		return;
	}
	else if (pr_tokenclass == TK_INC || pr_tokenclass == TK_DEC)
	{
		direction = pr_tokenclass;
		weapon = false;
		LX_Fetch();
		if (TK_CHECK(TK_LPAREN))
		{
			if (LX_Check("w"))
			{
				LX_Fetch();
			}
			else
			{
				LX_Require("W");
			}
			LX_Require(")");
			weapon = true;
		}
		if (pr_token_type != tt_immediate
			|| pr_immediate_type != &type_float)
		{
			PR_ParseError("state frame must be a number");
		}
		frame1 = (int)pr_immediate._float;
		s1 = CO_ParseImmediate();
		LX_Fetch();
		LX_Require("..");
		if (pr_token_type != tt_immediate
			|| pr_immediate_type != &type_float)
		{
			PR_ParseError("state frame must be a number");
		}
		frame2 = (int)pr_immediate._float;
		s2 = CO_ParseImmediate();
		LX_Fetch();
		if (direction == TK_INC)
		{
			if (frame1 > frame2)
			{
				PR_ParseError("bad frame order in state cycle");
			}
		}
		else if (frame1 < frame2)
		{
			PR_ParseError("bad frame order in state cycle");
		}
		LX_Require("]");
		if (weapon == true)
		{
			CO_GenCode(&pr_opcodes[OP_CWSTATE], s1, s2);
		}
		else
		{
			CO_GenCode(&pr_opcodes[OP_CSTATE], s1, s2);
		}
		return;
	}

	if (pr_token_type != tt_immediate
		|| pr_immediate_type != &type_float)
	{
		PR_ParseError("state frame must be a number");
	}
	FrameIndex = (int)pr_immediate._float;
	s1 = CO_ParseImmediate();
	LX_Fetch();
	if (pr_tokenclass == TK_COMMA)
	{
		LX_Fetch();
	}
	name = PR_ParseName();
	def = PR_GetDef(&type_function, name, 0, true);

	LX_Require("]");
	CO_GenCode(&pr_opcodes[OP_STATE], s1, def);
}
示例#8
0
static void ParseCStyleFunctionDef (const char *funcName, type_t *type)
{
	int		i;
	const char	*name = NULL;	// FIXME: init to NULL, avoid compiler warning
	type_t	newType;
	type_t	*funcType;
	def_t	*def;
	function_t	*f;
	dfunction_t	*df;
	int	locals_start;
	char	funcIdent[MAX_NAME];
	int	initClass;

	strcpy(funcIdent, funcName);
	memset(&newType, 0, sizeof(newType));
	newType.type = ev_function;
	newType.aux_type = type; // Return type
	newType.num_parms = 0;
	if (!TK_CHECK(TK_RPAREN))
	{
		if (TK_CHECK(TK_ELLIPSIS))
		{ // Variable args
			newType.num_parms = -1;
		}
		else if (!LX_CheckFetch("void"))
		{
			do
			{
				type = PR_ParseType();
				name = PR_ParseName();
				strcpy(pr_parm_names[newType.num_parms], name);
				newType.parm_types[newType.num_parms] = type;
				newType.num_parms++;
			} while (TK_CHECK(TK_COMMA));
		}
		LX_Require(")");
	}

	funcType = PR_FindType(&newType);
	def = PR_GetDef(funcType, funcIdent, pr_scope, true);

	if (def->initialized)
	{
		PR_ParseError("%s redeclared", funcName);
	}

	if (TK_TEST(TK_LBRACE)
		|| TK_TEST(TK_LBRACKET)
		|| TK_TEST(TK_COLON))
	{
		initClass = pr_tokenclass;
		if (def->initialized)
		{
			PR_ParseError("%s redeclared", name);
		}
		locals_start = locals_end = numpr_globals;
		pr_scope = def;
		f = ParseImmediateStatements(funcType);
		pr_scope = NULL;
		def->initialized = 1;
		G_FUNCTION(def->ofs) = numfunctions;
		f->def = def;
		df = &functions[numfunctions];
		numfunctions++;
		if (f->builtin)
		{
			df->first_statement = -f->builtin;
			def->referenceCount++;
		}
		else
		{
			df->first_statement = f->code;
		}
		df->s_name = CopyString(f->def->name);
		df->s_file = s_file;
		df->numparms =  f->def->type->num_parms;
		df->locals = locals_end - locals_start;
		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];
		}
		if (initClass == TK_COLON)
		{
			LX_Require(";");
		}
	}
	else
	{
		LX_Require(";");
	}
}
示例#9
0
/*
================
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_function) )
		PR_ParseError ("Fields and functions must be global");
		
	do
	{
		name = PR_ParseName ();

		def = PR_GetDef (type, name, pr_scope, true);
		
// check for an initialization
		if ( PR_Check ("=") )
		{
			if (def->initialized)
				PR_ParseError ("%s redeclared", name);
	
			if (type->type == ev_function)
			{
				locals_start = locals_end = numpr_globals;
				pr_scope = def;
				f = PR_ParseImmediateStatements (type);
				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++;
				if (f->builtin)
					df->first_statement = -f->builtin;
				else
					df->first_statement = f->code;
				df->s_name = CopyString (f->def->name);
				df->s_file = s_file;
				df->numparms =  f->def->type->num_parms;
				df->locals = locals_end - locals_start;
				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);
	
			def->initialized = 1;
			memcpy (pr_globals + def->ofs, &pr_immediate, 4*type_size[pr_immediate_type->type]);
			PR_Lex ();
		}
		
	} while (PR_Check (","));

	PR_Expect (";");
}
示例#10
0
文件: pr_comp.cpp 项目: luaman/zq
/*
==============
PR_Expression
==============
*/
def_t *PR_Expression (int priority)
{
	opcode_t	*op, *oldop;
	def_t		*e, *e2;
	etype_t		type_a, type_b, type_c;

	if (priority == 0)
		return PR_Term ();

	e = PR_Expression (priority-1);

	while (1)
	{
		if (priority == 1 && PR_Check ("(") )
			return PR_ParseFunctionCall (e);

		for (op=pr_opcodes ; op->name ; op++)
		{
			if (op->priority != priority)
				continue;
			if (!PR_Check (op->name))
				continue;

			if (op->name[0] == '.')
			{
				char *name = PR_ParseName ();

				if (e->type != &type_entity)
					PR_ParseError ("left of '.%s' must have entity type", name);

				e2 = PR_FindDef (name, pr_scope);
				if (!e2 || e2->type->type != ev_field)
					PR_ParseError ("'%s' is not a field", name);

				type_c = e2->type->aux_type->type;

				// we still allow ".void foo" so need to check
				if (type_c == ev_void)
					PR_ParseError ("tried to access a 'void' field");

				assert (type_c != ev_pointer && type_c != ev_void);
				while (type_c != op->type_c) {
					op++;
					assert (op->name);
				}

				e = PR_Statement (op, e, e2);

				// field access gets type from field
				e->type = e2->type->aux_type;
				break;
			}

			if (op->right_associative)
			{
				if (e->type->constant)
					PR_ParseError ("assignment to constant");

			// 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 = (unsigned short)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
			type_a = e->type->type;
			type_b = e2->type->type;

			oldop = op;
			while (type_a != op->type_a || type_b != op->type_b )
			{
				op++;
				if (!op->name || strcmp (op->name , oldop->name))
					PR_ParseError ("type mismatch for %s", oldop->name);
			}

			if (type_a == ev_pointer && type_b != e->type->aux_type->type)
				PR_ParseError ("type mismatch for %s", op->name);

#if 0
			if (e->type->constant && e2->type->constant) {
				// try to calculate the expression at compile time
				eval_t result;
				if (PR_Calc(op - pr_opcodes, (eval_t *)(pr_globals + e->ofs),
						(eval_t *)(pr_globals + e2->ofs), &result))
				{
//					printf ("line %i: folding %s %s %s into %s\n", pr_source_line, e->name, op->name, e2->name,
//						PR_ValueString(op->type_c, &val));

					type_t *resulttype;
					switch (op->type_c) {
						case ev_float: resulttype = &type_const_float; break;
						//case ev_string: resulttype = &type_const_string; break;
						case ev_vector: resulttype = &type_const_vector; break;
						default: assert (false);
					}

					e = PR_GetImmediate (resulttype, result);
					break;
				}
			}
#endif

			if (op->right_associative)
				e = PR_Statement (op, e2, e);
			else
				e = PR_Statement (op, e, e2);

			break;
		}
		if (!op->name)
			break;	// next token isn't at this priority level
	}

	return e;
}
示例#11
0
文件: pr_comp.cpp 项目: luaman/zq
/*
================
PR_ParseDefs

Called at the outer layer and when a local statement is hit
================
*/
void PR_ParseDefs (void)
{
	type_t *type = PR_ParseType ();

	if (pr_scope && type->type == ev_field)
		PR_ParseError ("'%s': local field definitions are illegal", pr_token);

	int	c_defs = 0;
	bool qc_style_function_def = false;

	// functions are always global
	def_t *defscope = (type->type == ev_function) ? NULL : pr_scope;

	do
	{
		char *name = PR_ParseName ();

		if (type->type != ev_function && PR_Check("(")) {
			// C-style function declaration

			char functionName[MAX_NAME];

			if (strlen(name) >= (size_t)MAX_NAME)
				PR_ParseError ("name of function \"%s\" is too long (max. %d chars)", name, (int)(MAX_NAME - 1));

			strcpy (functionName, name);

			type_t *functionType = PR_ParseFunctionType (type);

			def_t *def = PR_GetDef (functionType, functionName, NULL, pr_scope);

			if ((!c_defs && !strcmp(pr_token, "{")) || PR_Check("=")) {
				// C-style function definition (including builtin function definition #1, #2, etc.)
				PR_ParseFunctionBody (functionType, functionName, def);
				while (PR_Check(";"))
					;	// skip redundant semicolons
				return;
			}

			continue;
		}

		def_t *def = PR_GetDef (type, name, defscope, pr_scope);

		if (type->type == ev_void) {
			// end_sys_globals and end_sys_fields are special flags for structure dumping
			if (strcmp(name, "end_sys_globals") && strcmp(name, "end_sys_fields"))
				PR_ParseError ("'%s' : illegal use of type 'void'", name);
		}

		// check for an initialization
		if (PR_Check("=")) {
			if (type->type == ev_function) {
				// QuakeC-style function definition
				qc_style_function_def = true;
				PR_ParseFunctionBody (type, name, def);
			}
			else
				// variable initialization
				PR_ParseInitialization (type, name, def);
		}

	} while (c_defs++, PR_Check (","));

	if (qc_style_function_def && c_defs == 1)
		;	// allow void() func = {} without semicolon
	else
		PR_Expect (";");

	while (PR_Check(";"))
		;	// skip redundant semicolons
}
示例#12
0
type_t *PR_ParseType (void)
{
	const char	*name;
	type_t	newtype;
	type_t	*type;

	if (TK_CHECK(TK_PERIOD))
	{
		if (LX_CheckFetch("union"))
		{
			return &type_union;
		}
		memset(&newtype, 0, sizeof(newtype));
		newtype.type = ev_field;
		newtype.aux_type = PR_ParseType();
		return PR_FindType(&newtype);
	}

	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
	}
	LX_Fetch();

	if (!TK_CHECK(TK_LPAREN))
	{
		return type;
	}

	// Function type
	memset(&newtype, 0, sizeof(newtype));
	newtype.type = ev_function;
	newtype.aux_type = type; // Return type
	newtype.num_parms = 0;
	if (!TK_CHECK(TK_RPAREN))
	{
		if (TK_CHECK(TK_ELLIPSIS))
		{
			newtype.num_parms = -1;	// variable args
		}
		else
		{
			do
			{
				type = PR_ParseType();
				name = PR_ParseName();
				strcpy (pr_parm_names[newtype.num_parms], name);
				newtype.parm_types[newtype.num_parms] = type;
				newtype.num_parms++;
			} while (TK_CHECK(TK_COMMA));
		}
		LX_Require(")");
	}
	return PR_FindType(&newtype);
}