From 66305c676aa986478a52a41926f21473e80ba8dd Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Wed, 24 Apr 2013 16:07:31 +0200 Subject: [PATCH] Allow string concatenation in the parser as well, for now only for immediate strings and __FUNC__, maybe later -fpermissive or somethign could allow it on const-delcared string variables --- ast.c | 1 + ast.h | 1 + parser.c | 26 ++++++++++++++++++++++++-- tests/predef_func.qc | 6 ++++++ tests/predef_func.tmpl | 2 +- tests/predef_func_concat.tmpl | 5 +++++ 6 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 tests/predef_func_concat.tmpl diff --git a/ast.c b/ast.c index aa70509..3e5d304 100755 --- a/ast.c +++ b/ast.c @@ -316,6 +316,7 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t) self->isfield = false; self->cvq = CV_NONE; self->hasvalue = false; + self->isimm = false; self->uses = 0; memset(&self->constval, 0, sizeof(self->constval)); diff --git a/ast.h b/ast.h index 14d38d8..bae07db 100755 --- a/ast.h +++ b/ast.h @@ -177,6 +177,7 @@ struct ast_value_s int cvq; /* const/var qualifier */ bool isfield; /* this declares a field */ + bool isimm; /* an immediate, not just const */ bool hasvalue; union { double vfloat; diff --git a/parser.c b/parser.c index d480e1f..a19db28 100755 --- a/parser.c +++ b/parser.c @@ -217,6 +217,7 @@ static ast_value* parser_const_float(parser_t *parser, double d) out = ast_value_new(ctx, "#IMMEDIATE", TYPE_FLOAT); out->cvq = CV_CONST; out->hasvalue = true; + out->isimm = true; out->constval.vfloat = d; vec_push(parser->imm_float, out); return out; @@ -279,6 +280,7 @@ static ast_value* parser_const_string(parser_t *parser, const char *str, bool do out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING); out->cvq = CV_CONST; out->hasvalue = true; + out->isimm = true; out->constval.vstring = parser_strdup(str); vec_push(parser->imm_string, out); util_htseth(parser->ht_imm_string, str, hash, out); @@ -296,6 +298,7 @@ static ast_value* parser_const_vector(parser_t *parser, vector v) out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_VECTOR); out->cvq = CV_CONST; out->hasvalue = true; + out->isimm = true; out->constval.vvec = v; vec_push(parser->imm_vector, out); return out; @@ -2182,8 +2185,27 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma wantop = true; } else { - parseerror(parser, "expected operator or end of statement"); - goto onerr; + /* in this case we might want to allow constant string concatenation */ + bool concatenated = false; + if (parser->tok == TOKEN_STRINGCONST && vec_size(sy.out)) { + ast_expression *lexpr = vec_last(sy.out).out; + if (ast_istype(lexpr, ast_value)) { + ast_value *last = (ast_value*)lexpr; + if (last->isimm == true && last->cvq == CV_CONST && + last->hasvalue && last->expression.vtype == TYPE_STRING) + { + char *newstr = NULL; + util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser)); + vec_last(sy.out).out = (ast_expression*)parser_const_string(parser, newstr, false); + mem_d(newstr); + concatenated = true; + } + } + } + if (!concatenated) { + parseerror(parser, "expected operator or end of statement"); + goto onerr; + } } if (!parser_next(parser)) { diff --git a/tests/predef_func.qc b/tests/predef_func.qc index ec17cd0..e8c260b 100644 --- a/tests/predef_func.qc +++ b/tests/predef_func.qc @@ -1,3 +1,9 @@ void main() { +#ifdef SIMPLE print(__FUNC__, "\n"); +#elifdef CONCATENATED + print(__FUNC__ "\n"); +#else +# error this is wrong +#endif } diff --git a/tests/predef_func.tmpl b/tests/predef_func.tmpl index 6944138..ef9f8d4 100644 --- a/tests/predef_func.tmpl +++ b/tests/predef_func.tmpl @@ -1,5 +1,5 @@ I: predef_func.qc D: simple __FUNC__ case T: -execute -C: -std=fte -fftepp-predefs +C: -std=fteqcc -DSIMPLE M: main diff --git a/tests/predef_func_concat.tmpl b/tests/predef_func_concat.tmpl new file mode 100644 index 0000000..bb1bb43 --- /dev/null +++ b/tests/predef_func_concat.tmpl @@ -0,0 +1,5 @@ +I: predef_func.qc +D: concatenated __FUNC__ case +T: -execute +C: -std=fteqcc -DCONCATENATED +M: main -- 2.39.2