case opid1('+'):
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
- parseerror(parser, "Cannot add type %s and %s",
+ parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
}
if (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) {
- parseerror(parser, "type error: %s - %s not defined",
+ parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
break;
default:
- parseerror(parser, "type error: cannot add type %s to %s",
+ parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
break;
case opid1('-'):
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
- parseerror(parser, "type error: cannot subtract type %s from %s",
+ parseerror(parser, "invalid types used in expression: cannot subtract type %s from %s",
type_name[exprs[1]->expression.vtype],
type_name[exprs[0]->expression.vtype]);
return false;
}
if (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) {
- parseerror(parser, "type error: %s - %s not defined",
+ parseerror(parser, "invalid types used in expression: cannot subtract type %s from %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
break;
default:
- parseerror(parser, "type error: cannot subtract type %s from %s",
+ parseerror(parser, "invalid types used in expression: cannot subtract type %s from %s",
type_name[exprs[1]->expression.vtype],
type_name[exprs[0]->expression.vtype]);
return false;
exprs[1]->expression.vtype != TYPE_VECTOR &&
exprs[1]->expression.vtype != TYPE_FLOAT)
{
- parseerror(parser, "type error: cannot multiply type %s by %s",
+ parseerror(parser, "invalid types used in expression: cannot multiply types %s and %s",
type_name[exprs[1]->expression.vtype],
type_name[exprs[0]->expression.vtype]);
return false;
out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
break;
default:
- parseerror(parser, "type error: cannot multiplye type %s by %s",
+ parseerror(parser, "invalid types used in expression: cannot multiply types %s and %s",
type_name[exprs[1]->expression.vtype],
type_name[exprs[0]->expression.vtype]);
return false;
break;
case opid1('/'):
if (NotSameType(TYPE_FLOAT)) {
- parseerror(parser, "type error: cannot divide types %s and %s",
+ parseerror(parser, "invalid types used in expression: cannot divide types %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
case opid1('|'):
case opid1('&'):
if (NotSameType(TYPE_FLOAT)) {
- parseerror(parser, "type error: cannot perform bit operations on types %s and %s",
+ parseerror(parser, "invalid types used in expression: cannot perform bit operations between types %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
case opid2('&','&'):
generated_op += INSTR_AND;
if (NotSameType(TYPE_FLOAT)) {
- parseerror(parser, "type error: cannot apply logical operation on types %s and %s",
+ parseerror(parser, "invalid types used in expression: cannot perform logical operations between types %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
parseerror(parser, "TODO: logical ops for arbitrary types using INSTR_NOT");
case opid2('<', '='):
generated_op += INSTR_LE;
if (NotSameType(TYPE_FLOAT)) {
- parseerror(parser, "type error: cannot compare types %s and %s",
+ parseerror(parser, "invalid types used in expression: cannot perform comparison between types %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
break;
case opid2('!', '='):
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
- parseerror(parser, "type error: cannot compare types %s and %s",
+ parseerror(parser, "invalid types used in expression: cannot perform comparison between types %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
break;
case opid2('=', '='):
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
- parseerror(parser, "type error: cannot compare types %s and %s",
+ parseerror(parser, "invalid types used in expression: cannot perform comparison between types %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
break;
case opid2('+','='):
if (exprs[0]->expression.vtype != exprs[1]->expression.vtype) {
- parseerror(parser, "Cannot add type %s and %s",
+ parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
}
if (exprs[0]->expression.vtype != TYPE_VECTOR && exprs[0]->expression.vtype != TYPE_FLOAT) {
- parseerror(parser, "type error: %s - %s not defined",
+ parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
}
+ if (ast_istype(exprs[0], ast_entfield))
+ assignop = type_storep_instr[exprs[0]->expression.vtype];
+ else
+ assignop = type_store_instr[exprs[0]->expression.vtype];
switch (exprs[0]->expression.vtype) {
case TYPE_FLOAT:
- out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
+ out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_ADD_F, exprs[0], exprs[1]);
break;
case TYPE_VECTOR:
- out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
+ out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_ADD_V, exprs[0], exprs[1]);
break;
default:
- parseerror(parser, "type error: cannot add type %s to %s",
+ parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
type_name[exprs[0]->expression.vtype],
type_name[exprs[1]->expression.vtype]);
return false;
return true;
}
+static bool parser_parse_dowhile(parser_t *parser, ast_block *block, ast_expression **out)
+{
+ ast_loop *aloop;
+ ast_expression *cond, *ontrue;
+
+ lex_ctx ctx = parser_ctx(parser);
+
+ /* skip the 'do' and get the body */
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected loop body");
+ return false;
+ }
+ ontrue = parser_parse_statement_or_block(parser);
+ if (!ontrue)
+ return false;
+
+ /* expect the "while" */
+ if (parser->tok != TOKEN_KEYWORD ||
+ strcmp(parser_tokval(parser), "while"))
+ {
+ parseerror(parser, "expected 'while' and condition");
+ ast_delete(ontrue);
+ return false;
+ }
+
+ /* skip the 'while' and check for opening paren */
+ if (!parser_next(parser) || parser->tok != '(') {
+ parseerror(parser, "expected 'while' condition in parenthesis");
+ ast_delete(ontrue);
+ return false;
+ }
+ /* parse into the expression */
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected 'while' condition after opening paren");
+ ast_delete(ontrue);
+ return false;
+ }
+ /* parse the condition */
+ cond = parser_expression_leave(parser);
+ if (!cond)
+ return false;
+ /* closing paren */
+ if (parser->tok != ')') {
+ parseerror(parser, "expected closing paren after 'while' condition");
+ ast_delete(ontrue);
+ ast_delete(cond);
+ return false;
+ }
+ /* parse on */
+ if (!parser_next(parser) || parser->tok != ';') {
+ parseerror(parser, "expected semicolon after condition");
+ ast_delete(ontrue);
+ ast_delete(cond);
+ return false;
+ }
+
+ if (!parser_next(parser)) {
+ parseerror(parser, "parse error");
+ ast_delete(ontrue);
+ ast_delete(cond);
+ return false;
+ }
+
+ aloop = ast_loop_new(ctx, NULL, NULL, cond, NULL, ontrue);
+ *out = (ast_expression*)aloop;
+ return true;
+}
+
static bool parser_parse_for(parser_t *parser, ast_block *block, ast_expression **out)
{
ast_loop *aloop;
{
return parser_parse_while(parser, block, out);
}
+ else if (!strcmp(parser_tokval(parser), "do"))
+ {
+ return parser_parse_dowhile(parser, block, out);
+ }
else if (!strcmp(parser_tokval(parser), "for"))
{
+ if (opts_standard == COMPILER_QCC) {
+ if (parsewarning(parser, WARN_EXTENSIONS, "for loops are not recognized in the original Quake C standard, to enable try an alternate standard --std=?"))
+ return false;
+ }
return parser_parse_for(parser, block, out);
}
parseerror(parser, "Unexpected keyword");