Remove nested expressions
[babeltrace.git] / formats / ctf / metadata / ctf-parser.y
index 188f8cd44e0c1d9cce191b9a6ccb37450ffb08f7..1ccc718a0954ff063e72cefc7c3bd69b75ff6961 100644 (file)
@@ -26,6 +26,7 @@
  */
 
 #include <stdio.h>
+#include <ctype.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdlib.h>
@@ -77,32 +78,9 @@ struct gc_string {
 };
 
 static const char *node_type_to_str[] = {
-       [ NODE_UNKNOWN ] = "NODE_UNKNOWN",
-       [ NODE_ROOT ] = "NODE_ROOT",
-       [ NODE_EVENT ] = "NODE_EVENT",
-       [ NODE_ENV ] = "NODE_ENV",
-       [ NODE_STREAM ] = "NODE_STREAM",
-       [ NODE_TRACE ] = "NODE_TRACE",
-       [ NODE_CLOCK ] = "NODE_CLOCK",
-       [ NODE_CALLSITE ] = "NODE_CALLSITE",
-       [ NODE_CTF_EXPRESSION ] = "NODE_CTF_EXPRESSION",
-       [ NODE_UNARY_EXPRESSION ] = "NODE_UNARY_EXPRESSION",
-       [ NODE_TYPEDEF ] = "NODE_TYPEDEF",
-       [ NODE_TYPEALIAS_TARGET ] = "NODE_TYPEALIAS_TARGET",
-       [ NODE_TYPEALIAS_ALIAS ] = "NODE_TYPEALIAS_ALIAS",
-       [ NODE_TYPEALIAS ] = "NODE_TYPEALIAS",
-       [ NODE_TYPE_SPECIFIER ] = "NODE_TYPE_SPECIFIER",
-       [ NODE_TYPE_SPECIFIER_LIST ] = "NODE_TYPE_SPECIFIER_LIST",
-       [ NODE_POINTER ] = "NODE_POINTER",
-       [ NODE_TYPE_DECLARATOR ] = "NODE_TYPE_DECLARATOR",
-       [ NODE_FLOATING_POINT ] = "NODE_FLOATING_POINT",
-       [ NODE_INTEGER ] = "NODE_INTEGER",
-       [ NODE_STRING ] = "NODE_STRING",
-       [ NODE_ENUMERATOR ] = "NODE_ENUMERATOR",
-       [ NODE_ENUM ] = "NODE_ENUM",
-       [ NODE_STRUCT_OR_VARIANT_DECLARATION ] = "NODE_STRUCT_OR_VARIANT_DECLARATION",
-       [ NODE_VARIANT ] = "NODE_VARIANT",
-       [ NODE_STRUCT ] = "NODE_STRUCT",
+#define ENTRY(S)       [S] = #S,
+       FOREACH_CTF_NODES(ENTRY)
+#undef ENTRY
 };
 
 BT_HIDDEN
@@ -131,45 +109,148 @@ static struct gc_string *gc_string_alloc(struct ctf_scanner *scanner,
        return gstr;
 }
 
-/*
- * note: never use gc_string_append on a string that has external references.
- * gsrc will be garbage collected immediately, and gstr might be.
- * Should only be used to append characters to a string literal or constant.
- */
-BT_HIDDEN
-struct gc_string *gc_string_append(struct ctf_scanner *scanner,
-                                  struct gc_string *gstr,
-                                  struct gc_string *gsrc)
+void setstring(struct ctf_scanner *scanner, YYSTYPE *lvalp, const char *src)
 {
-       size_t newlen = strlen(gsrc->s) + strlen(gstr->s) + 1;
-       size_t alloclen;
-
-       /* TODO: could be faster with find first bit or glib Gstring */
-       /* sizeof long to account for malloc header (int or long ?) */
-       for (alloclen = 8; alloclen < sizeof(long) + sizeof(*gstr) + newlen;
-            alloclen *= 2);
+       lvalp->gs = gc_string_alloc(scanner, strlen(src) + 1);
+       strcpy(lvalp->gs->s, src);
+}
 
-       if (alloclen > gstr->alloclen) {
-               struct gc_string *newgstr;
+static
+int str_check(size_t str_len, size_t offset, size_t len)
+{
+       /* check overflow */
+       if (offset + len < offset)
+               return -1;
+       if (offset + len > str_len)
+               return -1;
+       return 0;
+}
 
-               newgstr = gc_string_alloc(scanner, newlen);
-               strcpy(newgstr->s, gstr->s);
-               strcat(newgstr->s, gsrc->s);
-               bt_list_del(&gstr->gc);
-               free(gstr);
-               gstr = newgstr;
-       } else {
-               strcat(gstr->s, gsrc->s);
+static
+int import_basic_string(struct ctf_scanner *scanner, YYSTYPE *lvalp,
+               size_t len, const char *src, char delim)
+{
+       size_t pos = 0, dpos = 0;
+
+       if (str_check(len, pos, 1))
+               return -1;
+       if (src[pos++] != delim)
+               return -1;
+
+       while (src[pos] != delim) {
+               char c;
+
+               if (str_check(len, pos, 1))
+                       return -1;
+               c = src[pos++];
+               if (c == '\\') {
+                       if (str_check(len, pos, 1))
+                               return -1;
+                       c = src[pos++];
+
+                       switch (c) {
+                       case '0':
+                               c = '\0';
+                               break;
+                       case 'a':
+                               c = '\a';
+                               break;
+                       case 'b':
+                               c = '\b';
+                               break;
+                       case 'f':
+                               c = '\f';
+                               break;
+                       case 'n':
+                               c = '\n';
+                               break;
+                       case 'r':
+                               c = '\r';
+                               break;
+                       case 't':
+                               c = '\t';
+                               break;
+                       case 'v':
+                               c = '\v';
+                               break;
+                       case '\\':
+                               c = '\\';
+                               break;
+                       case '\'':
+                               c = '\'';
+                               break;
+                       case '\"':
+                               c = '\"';
+                               break;
+                       case '?':
+                               c = '?';
+                               break;
+                       case 'o':
+                       {
+                               size_t oct_len = 3;
+
+                               if (str_check(len, pos, oct_len))
+                                       return -1;
+                               if (!isdigit((int) src[pos]) || !isdigit((int) src[pos+1]) || !isdigit((int) src[pos+2]))
+                                       return -1;
+                               char oct_buffer[4] = { src[pos], src[pos+1], src[pos+2], '\0' };
+                               c = strtoul(&oct_buffer[0], NULL, 8);
+                               pos += oct_len;
+                               break;
+                       }
+                       case 'x':
+                       {
+                               size_t hex_len = 2;
+
+                               if (str_check(len, pos, hex_len))
+                                       return -1;
+                               if (!isxdigit((int) src[pos]) || !isxdigit((int) src[pos+1]))
+                                       return -1;
+                               char hex_buffer[3] = { src[pos], src[pos+1], '\0' };
+                               c = strtoul(&hex_buffer[0], NULL, 16);
+                               pos += hex_len;
+                               break;
+                       }
+                       default:
+                               return -1;
+                       }
+               }
+               if (str_check(len, dpos, 1))
+                       return -1;
+               lvalp->gs->s[dpos++] = c;
        }
-       bt_list_del(&gsrc->gc);
-       free(gsrc);
-       return gstr;
+
+       if (str_check(len, dpos, 1))
+               return -1;
+       lvalp->gs->s[dpos++] = '\0';
+
+       if (str_check(len, pos, 1))
+               return -1;
+       if (src[pos++] != delim)
+               return -1;
+
+       if (str_check(len, pos, 1))
+               return -1;
+       if (src[pos] != '\0')
+               return -1;
+       return 0;
 }
 
-void setstring(struct ctf_scanner *scanner, YYSTYPE *lvalp, const char *src)
+int import_string(struct ctf_scanner *scanner, YYSTYPE *lvalp,
+               const char *src, char delim)
 {
-       lvalp->gs = gc_string_alloc(scanner, strlen(src) + 1);
-       strcpy(lvalp->gs->s, src);
+       size_t len;
+
+       len = strlen(src) + 1;
+       lvalp->gs = gc_string_alloc(scanner, len);
+       if (src[0] == 'L') {
+               // TODO: import wide string
+               printfl_error(yyget_lineno(scanner),
+                       "Wide string not supported yet.");
+               return -1;
+       } else {
+               return import_basic_string(scanner, lvalp, len, src, delim);
+       }
 }
 
 static void init_scope(struct ctf_scanner_scope *scope,
@@ -948,20 +1029,23 @@ void ctf_scanner_free(struct ctf_scanner *scanner)
  */
 %expect 2
 %start file
-%token CHARACTER_CONSTANT_START SQUOTE STRING_LITERAL_START DQUOTE ESCSEQ CHAR_STRING_TOKEN LSBRAC RSBRAC LPAREN RPAREN LBRAC RBRAC RARROW STAR PLUS MINUS LT GT TYPEASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA CONST CHAR DOUBLE ENUM ENV EVENT FLOATING_POINT FLOAT INTEGER INT LONG SHORT SIGNED STREAM STRING STRUCT TRACE CALLSITE CLOCK TYPEALIAS TYPEDEF UNSIGNED VARIANT VOID _BOOL _COMPLEX _IMAGINARY DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT TOK_ALIGN
+%token INTEGER_LITERAL STRING_LITERAL CHARACTER_LITERAL LSBRAC RSBRAC LPAREN RPAREN LBRAC RBRAC RARROW STAR PLUS MINUS LT GT TYPEASSIGN COLON SEMICOLON DOTDOTDOT DOT EQUAL COMMA CONST CHAR DOUBLE ENUM ENV EVENT FLOATING_POINT FLOAT INTEGER INT LONG SHORT SIGNED STREAM STRING STRUCT TRACE CALLSITE CLOCK TYPEALIAS TYPEDEF UNSIGNED VARIANT VOID _BOOL _COMPLEX _IMAGINARY TOK_ALIGN
 %token <gs> IDENTIFIER ID_TYPE
 %token ERROR
 %union
 {
        long long ll;
+       unsigned long long ull;
        char c;
        struct gc_string *gs;
        struct ctf_node *n;
 }
 
+%type <gs> STRING_LITERAL CHARACTER_LITERAL
+
 %type <gs> keywords
-%type <gs> s_char s_char_sequence c_char c_char_sequence
 
+%type <ull> INTEGER_LITERAL
 %type <n> postfix_expression unary_expression unary_expression_or_range
 
 %type <n> declaration
@@ -1073,41 +1157,6 @@ keywords:
                {       $$ = yylval.gs;         }
        ;
 
-/* 1.5 Constants */
-
-c_char_sequence:
-               c_char
-               {       $$ = $1;                                        }
-       |       c_char_sequence c_char
-               {       $$ = gc_string_append(scanner, $1, $2);         }
-       ;
-
-c_char:
-               CHAR_STRING_TOKEN
-               {       $$ = yylval.gs;                                 }
-       |       ESCSEQ
-               {
-                       reparent_error(scanner, "escape sequences not supported yet");
-               }
-       ;
-
-/* 1.6 String literals */
-
-s_char_sequence:
-               s_char
-               {       $$ = $1;                                        }
-       |       s_char_sequence s_char
-               {       $$ = gc_string_append(scanner, $1, $2);         }
-       ;
-
-s_char:
-               CHAR_STRING_TOKEN
-               {       $$ = yylval.gs;                                 }
-       |       ESCSEQ
-               {
-                       reparent_error(scanner, "escape sequences not supported yet");
-               }
-       ;
 
 /* 2: Phrase structure grammar */
 
@@ -1130,50 +1179,27 @@ postfix_expression:
                        $$->u.unary_expression.type = UNARY_STRING;
                        $$->u.unary_expression.u.string = yylval.gs->s;
                }
-       |       DECIMAL_CONSTANT
+       |       INTEGER_LITERAL
                {
                        $$ = make_node(scanner, NODE_UNARY_EXPRESSION);
                        $$->u.unary_expression.type = UNARY_UNSIGNED_CONSTANT;
-                       sscanf(yylval.gs->s, "%" PRIu64,
-                              &$$->u.unary_expression.u.unsigned_constant);
+                       $$->u.unary_expression.u.unsigned_constant = $1;
                }
-       |       OCTAL_CONSTANT
-               {
-                       $$ = make_node(scanner, NODE_UNARY_EXPRESSION);
-                       $$->u.unary_expression.type = UNARY_UNSIGNED_CONSTANT;
-                       sscanf(yylval.gs->s, "0%" PRIo64,
-                              &$$->u.unary_expression.u.unsigned_constant);
-               }
-       |       HEXADECIMAL_CONSTANT
-               {
-                       $$ = make_node(scanner, NODE_UNARY_EXPRESSION);
-                       $$->u.unary_expression.type = UNARY_UNSIGNED_CONSTANT;
-                       sscanf(yylval.gs->s, "0x%" PRIx64,
-                              &$$->u.unary_expression.u.unsigned_constant);
-               }
-       |       STRING_LITERAL_START DQUOTE
+       |       STRING_LITERAL
                {
                        $$ = make_node(scanner, NODE_UNARY_EXPRESSION);
                        $$->u.unary_expression.type = UNARY_STRING;
-                       $$->u.unary_expression.u.string = "";
+                       $$->u.unary_expression.u.string = $1->s;
                }
-       |       STRING_LITERAL_START s_char_sequence DQUOTE
+       |       CHARACTER_LITERAL
                {
                        $$ = make_node(scanner, NODE_UNARY_EXPRESSION);
                        $$->u.unary_expression.type = UNARY_STRING;
-                       $$->u.unary_expression.u.string = $2->s;
-               }
-       |       CHARACTER_CONSTANT_START c_char_sequence SQUOTE
-               {
-                       $$ = make_node(scanner, NODE_UNARY_EXPRESSION);
-                       $$->u.unary_expression.type = UNARY_STRING;
-                       $$->u.unary_expression.u.string = $2->s;
+                       $$->u.unary_expression.u.string = $1->s;
                }
        |       LPAREN unary_expression RPAREN
                {
-                       $$ = make_node(scanner, NODE_UNARY_EXPRESSION);
-                       $$->u.unary_expression.type = UNARY_NESTED;
-                       $$->u.unary_expression.u.nested_exp = $2;
+                       $$ = $2;
                }
        |       postfix_expression LSBRAC unary_expression RSBRAC
                {
@@ -1225,7 +1251,13 @@ unary_expression:
                postfix_expression
                {       $$ = $1;                                }
        |       PLUS postfix_expression
-               {       $$ = $2;                                }
+               {
+                       $$ = $2;
+                       if ($$->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT
+                               && $$->u.unary_expression.type != UNARY_SIGNED_CONSTANT) {
+                               reparent_error(scanner, "expecting numeric constant");
+                       }
+               }
        |       MINUS postfix_expression
                {
                        $$ = $2;
@@ -2204,15 +2236,10 @@ enumerator:
                        $$ = make_node(scanner, NODE_ENUMERATOR);
                        $$->u.enumerator.id = $1->s;
                }
-       |       STRING_LITERAL_START DQUOTE
+       |       STRING_LITERAL
                {
                        $$ = make_node(scanner, NODE_ENUMERATOR);
-                       $$->u.enumerator.id = "";
-               }
-       |       STRING_LITERAL_START s_char_sequence DQUOTE
-               {
-                       $$ = make_node(scanner, NODE_ENUMERATOR);
-                       $$->u.enumerator.id = $2->s;
+                       $$->u.enumerator.id = $1->s;
                }
        |       IDENTIFIER EQUAL unary_expression_or_range
                {
@@ -2232,17 +2259,11 @@ enumerator:
                        $$->u.enumerator.id = $1->s;
                        bt_list_splice(&($3)->tmp_head, &($$)->u.enumerator.values);
                }
-       |       STRING_LITERAL_START DQUOTE EQUAL unary_expression_or_range
+       |       STRING_LITERAL EQUAL unary_expression_or_range
                {
                        $$ = make_node(scanner, NODE_ENUMERATOR);
-                       $$->u.enumerator.id = "";
-                       bt_list_splice(&($4)->tmp_head, &($$)->u.enumerator.values);
-               }
-       |       STRING_LITERAL_START s_char_sequence DQUOTE EQUAL unary_expression_or_range
-               {
-                       $$ = make_node(scanner, NODE_ENUMERATOR);
-                       $$->u.enumerator.id = $2->s;
-                       bt_list_splice(&($5)->tmp_head, &($$)->u.enumerator.values);
+                       $$->u.enumerator.id = $1->s;
+                       bt_list_splice(&($3)->tmp_head, &($$)->u.enumerator.values);
                }
        ;
 
This page took 0.027292 seconds and 4 git commands to generate.