Fix: add semantic check in grammar
[babeltrace.git] / formats / ctf / metadata / ctf-parser.y
index 3ae0bc237120009363d6eedfe2d815dd3b879dcf..58ea245b8d30f2b43b17cb26b7a8a72594bd0dc2 100644 (file)
  *
  * The above copyright notice and this permission notice shall be included in
  * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
  */
 
 #include <stdio.h>
@@ -31,7 +39,7 @@
 #include "ctf-parser.h"
 #include "ctf-ast.h"
 
-__attribute__((visibility("protected")))
+BT_HIDDEN
 int yydebug;
 
 /* Join two lists, put "add" at the end of "head".  */
@@ -47,16 +55,20 @@ _bt_list_splice_tail (struct bt_list_head *add, struct bt_list_head *head)
        }
 }
 
-__attribute__((visibility("protected")))
+BT_HIDDEN
 int yyparse(struct ctf_scanner *scanner);
-__attribute__((visibility("protected")))
+BT_HIDDEN
 int yylex(union YYSTYPE *yyval, struct ctf_scanner *scanner);
-__attribute__((visibility("protected")))
+BT_HIDDEN
 int yylex_init_extra(struct ctf_scanner *scanner, yyscan_t * ptr_yy_globals);
-__attribute__((visibility("protected")))
+BT_HIDDEN
 int yylex_destroy(yyscan_t yyscanner);
-__attribute__((visibility("protected")))
+BT_HIDDEN
 void yyrestart(FILE * in_str, yyscan_t scanner);
+BT_HIDDEN
+int yyget_lineno(yyscan_t yyscanner);
+BT_HIDDEN
+char *yyget_text(yyscan_t yyscanner);
 
 struct gc_string {
        struct bt_list_head gc;
@@ -72,6 +84,7 @@ static const char *node_type_to_str[] = {
        [ 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",
@@ -92,7 +105,7 @@ static const char *node_type_to_str[] = {
        [ NODE_STRUCT ] = "NODE_STRUCT",
 };
 
-__attribute__((visibility("protected")))
+BT_HIDDEN
 const char *node_type(struct ctf_node *node)
 {
        if (node->type < NR_NODE_TYPES)
@@ -123,7 +136,7 @@ static struct gc_string *gc_string_alloc(struct ctf_scanner *scanner,
  * gsrc will be garbage collected immediately, and gstr might be.
  * Should only be used to append characters to a string literal or constant.
  */
-__attribute__((visibility("protected")))
+BT_HIDDEN
 struct gc_string *gc_string_append(struct ctf_scanner *scanner,
                                   struct gc_string *gstr,
                                   struct gc_string *gsrc)
@@ -202,7 +215,7 @@ static int lookup_type(struct ctf_scanner_scope *s, const char *id)
        return ret;
 }
 
-__attribute__((visibility("protected")))
+BT_HIDDEN
 int is_type(struct ctf_scanner *scanner, const char *id)
 {
        struct ctf_scanner_scope *it;
@@ -237,13 +250,14 @@ static struct ctf_node *make_node(struct ctf_scanner *scanner,
                return NULL;
        memset(node, 0, sizeof(*node));
        node->type = type;
+       node->lineno = yyget_lineno(scanner->scanner);
        BT_INIT_LIST_HEAD(&node->tmp_head);
        bt_list_add(&node->gc, &ast->allocated_nodes);
        bt_list_add(&node->siblings, &node->tmp_head);
 
        switch (type) {
        case NODE_ROOT:
-               fprintf(stderr, "[error] %s: trying to create root node\n", __func__);
+               printfn_fatal(node, "trying to create root node");
                break;
 
        case NODE_EVENT:
@@ -261,6 +275,9 @@ static struct ctf_node *make_node(struct ctf_scanner *scanner,
        case NODE_CLOCK:
                BT_INIT_LIST_HEAD(&node->u.clock.declaration_list);
                break;
+       case NODE_CALLSITE:
+               BT_INIT_LIST_HEAD(&node->u.callsite.declaration_list);
+               break;
 
        case NODE_CTF_EXPRESSION:
                BT_INIT_LIST_HEAD(&node->u.ctf_expression.left);
@@ -320,8 +337,7 @@ static struct ctf_node *make_node(struct ctf_scanner *scanner,
 
        case NODE_UNKNOWN:
        default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) type);
+               printfn_fatal(node, "unknown node type '%d'", (int) type);
                break;
        }
 
@@ -347,6 +363,9 @@ static int reparent_ctf_expression(struct ctf_node *node,
        case NODE_CLOCK:
                _bt_list_splice_tail(&node->tmp_head, &parent->u.clock.declaration_list);
                break;
+       case NODE_CALLSITE:
+               _bt_list_splice_tail(&node->tmp_head, &parent->u.callsite.declaration_list);
+               break;
        case NODE_FLOATING_POINT:
                _bt_list_splice_tail(&node->tmp_head, &parent->u.floating_point.expressions);
                break;
@@ -377,8 +396,7 @@ static int reparent_ctf_expression(struct ctf_node *node,
 
        case NODE_UNKNOWN:
        default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) parent->type);
+               printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
                return -EINVAL;
        }
        return 0;
@@ -405,6 +423,9 @@ static int reparent_typedef(struct ctf_node *node, struct ctf_node *parent)
        case NODE_CLOCK:
                _bt_list_splice_tail(&node->tmp_head, &parent->u.clock.declaration_list);
                break;
+       case NODE_CALLSITE:
+               _bt_list_splice_tail(&node->tmp_head, &parent->u.callsite.declaration_list);
+               break;
        case NODE_VARIANT:
                _bt_list_splice_tail(&node->tmp_head, &parent->u.variant.declaration_list);
                break;
@@ -432,8 +453,7 @@ static int reparent_typedef(struct ctf_node *node, struct ctf_node *parent)
 
        case NODE_UNKNOWN:
        default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) parent->type);
+               printfn_fatal(node, "unknown node type %d", parent->type);
                return -EINVAL;
        }
        return 0;
@@ -460,6 +480,9 @@ static int reparent_typealias(struct ctf_node *node, struct ctf_node *parent)
        case NODE_CLOCK:
                _bt_list_splice_tail(&node->tmp_head, &parent->u.clock.declaration_list);
                break;
+       case NODE_CALLSITE:
+               _bt_list_splice_tail(&node->tmp_head, &parent->u.callsite.declaration_list);
+               break;
        case NODE_VARIANT:
                _bt_list_splice_tail(&node->tmp_head, &parent->u.variant.declaration_list);
                break;
@@ -487,8 +510,7 @@ static int reparent_typealias(struct ctf_node *node, struct ctf_node *parent)
 
        case NODE_UNKNOWN:
        default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) parent->type);
+               printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
                return -EINVAL;
        }
        return 0;
@@ -508,6 +530,7 @@ static int reparent_type_specifier(struct ctf_node *node,
        case NODE_ENV:
        case NODE_TRACE:
        case NODE_CLOCK:
+       case NODE_CALLSITE:
        case NODE_VARIANT:
        case NODE_STRUCT:
        case NODE_TYPEDEF:
@@ -528,8 +551,7 @@ static int reparent_type_specifier(struct ctf_node *node,
 
        case NODE_UNKNOWN:
        default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) parent->type);
+               printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
                return -EINVAL;
        }
        return 0;
@@ -557,6 +579,9 @@ static int reparent_type_specifier_list(struct ctf_node *node,
        case NODE_CLOCK:
                bt_list_add_tail(&node->siblings, &parent->u.clock.declaration_list);
                break;
+       case NODE_CALLSITE:
+               bt_list_add_tail(&node->siblings, &parent->u.callsite.declaration_list);
+               break;
        case NODE_VARIANT:
                bt_list_add_tail(&node->siblings, &parent->u.variant.declaration_list);
                break;
@@ -592,8 +617,7 @@ static int reparent_type_specifier_list(struct ctf_node *node,
 
        case NODE_UNKNOWN:
        default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) parent->type);
+               printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
                return -EINVAL;
        }
        return 0;
@@ -626,6 +650,7 @@ static int reparent_type_declarator(struct ctf_node *node,
        case NODE_ENV:
        case NODE_TRACE:
        case NODE_CLOCK:
+       case NODE_CALLSITE:
        case NODE_VARIANT:
        case NODE_STRUCT:
        case NODE_TYPEALIAS:
@@ -643,8 +668,7 @@ static int reparent_type_declarator(struct ctf_node *node,
 
        case NODE_UNKNOWN:
        default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) parent->type);
+               printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
                return -EINVAL;
        }
        return 0;
@@ -667,7 +691,7 @@ static int set_parent_node(struct ctf_node *node,
 
        switch (node->type) {
        case NODE_ROOT:
-               fprintf(stderr, "[error] %s: trying to reparent root node\n", __func__);
+               printfn_fatal(node, "trying to reparent root node");
                return -EINVAL;
 
        case NODE_EVENT:
@@ -705,6 +729,13 @@ static int set_parent_node(struct ctf_node *node,
                        return -EPERM;
                }
                break;
+       case NODE_CALLSITE:
+               if (parent->type == NODE_ROOT) {
+                       _bt_list_splice_tail(&node->tmp_head, &parent->u.root.callsite);
+               } else {
+                       return -EPERM;
+               }
+               break;
 
        case NODE_CTF_EXPRESSION:
                return reparent_ctf_expression(node, parent);
@@ -775,20 +806,21 @@ static int set_parent_node(struct ctf_node *node,
 
        case NODE_UNKNOWN:
        default:
-               fprintf(stderr, "[error] %s: unknown node type %d\n", __func__,
-                       (int) parent->type);
+               printfn_fatal(node, "unknown node type '%d'", (int) parent->type);
                return -EINVAL;
        }
        return 0;
 }
 
-__attribute__((visibility("protected")))
+BT_HIDDEN
 void yyerror(struct ctf_scanner *scanner, const char *str)
 {
-       fprintf(stderr, "error %s\n", str);
+       printfl_error(yyget_lineno(scanner->scanner),
+               "token \"%s\": %s\n",
+               yyget_text(scanner->scanner), str);
 }
  
-__attribute__((visibility("protected")))
+BT_HIDDEN
 int yywrap(void)
 {
        return 1;
@@ -796,7 +828,7 @@ int yywrap(void)
 
 #define reparent_error(scanner, str)                           \
 do {                                                           \
-       yyerror(scanner, YY_("reparent_error: " str "\n"));     \
+       yyerror(scanner, YY_("reparent_error: " str));  \
        YYERROR;                                                \
 } while (0)
 
@@ -825,6 +857,7 @@ static struct ctf_ast *ctf_ast_alloc(void)
        BT_INIT_LIST_HEAD(&ast->root.u.root.stream);
        BT_INIT_LIST_HEAD(&ast->root.u.root.event);
        BT_INIT_LIST_HEAD(&ast->root.u.root.clock);
+       BT_INIT_LIST_HEAD(&ast->root.u.root.callsite);
        return ast;
 }
 
@@ -834,6 +867,7 @@ static void ctf_ast_free(struct ctf_ast *ast)
 
        bt_list_for_each_entry_safe(node, tmp, &ast->allocated_nodes, gc)
                free(node);
+       free(ast);
 }
 
 int ctf_scanner_append_ast(struct ctf_scanner *scanner)
@@ -855,7 +889,7 @@ struct ctf_scanner *ctf_scanner_alloc(FILE *input)
 
        ret = yylex_init_extra(scanner, &scanner->scanner);
        if (ret) {
-               fprintf(stderr, "yylex_init error\n");
+               printf_fatal("yylex_init error");
                goto cleanup_scanner;
        }
        /* Start processing new stream */
@@ -878,7 +912,7 @@ struct ctf_scanner *ctf_scanner_alloc(FILE *input)
 cleanup_lexer:
        ret = yylex_destroy(scanner->scanner);
        if (!ret)
-               fprintf(stderr, "yylex_destroy error\n");
+               printf_fatal("yylex_destroy error");
 cleanup_scanner:
        free(scanner);
        return NULL;
@@ -893,7 +927,7 @@ void ctf_scanner_free(struct ctf_scanner *scanner)
        ctf_ast_free(scanner->ast);
        ret = yylex_destroy(scanner->scanner);
        if (ret)
-               fprintf(stderr, "yylex_destroy error\n");
+               printf_error("yylex_destroy error");
        free(scanner);
 }
 
@@ -901,6 +935,7 @@ void ctf_scanner_free(struct ctf_scanner *scanner)
 
 %define api.pure
        /* %locations */
+%error-verbose
 %parse-param {struct ctf_scanner *scanner}
 %lex-param {struct ctf_scanner *scanner}
 /*
@@ -913,7 +948,7 @@ 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 CLOCK TYPEALIAS TYPEDEF UNSIGNED VARIANT VOID _BOOL _COMPLEX _IMAGINARY DECIMAL_CONSTANT OCTAL_CONSTANT HEXADECIMAL_CONSTANT TOK_ALIGN
+%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 <gs> IDENTIFIER ID_TYPE
 %token ERROR
 %union
@@ -935,6 +970,7 @@ void ctf_scanner_free(struct ctf_scanner *scanner)
 %type <n> env_declaration
 %type <n> trace_declaration
 %type <n> clock_declaration
+%type <n> callsite_declaration
 %type <n> integer_declaration_specifiers
 %type <n> declaration_specifiers
 %type <n> alias_declaration_specifiers
@@ -1031,6 +1067,8 @@ keywords:
                {       $$ = yylval.gs;         }
        |       CLOCK
                {       $$ = yylval.gs;         }
+       |       CALLSITE
+               {       $$ = yylval.gs;         }
        |       TOK_ALIGN
                {       $$ = yylval.gs;         }
        ;
@@ -1187,21 +1225,25 @@ unary_expression:
                postfix_expression
                {       $$ = $1;                                }
        |       PLUS postfix_expression
-               {       $$ = $2;                                }
-       |       MINUS postfix_expression
                {
                        $$ = $2;
-                       if ($$->u.unary_expression.type != UNARY_SIGNED_CONSTANT
-                               && $$->u.unary_expression.type != UNARY_UNSIGNED_CONSTANT)
+                       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;
                        if ($$->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT) {
                                $$->u.unary_expression.type = UNARY_SIGNED_CONSTANT;
                                $$->u.unary_expression.u.signed_constant =
                                        -($$->u.unary_expression.u.unsigned_constant);
-                       } else {
+                       } else if ($$->u.unary_expression.type == UNARY_UNSIGNED_CONSTANT) {
                                $$->u.unary_expression.u.signed_constant =
                                        -($$->u.unary_expression.u.signed_constant);
+                       } else {
+                               reparent_error(scanner, "expecting numeric constant");
                        }
                }
        ;
@@ -1232,6 +1274,8 @@ declaration:
                {       $$ = $1;        }
        |       clock_declaration
                {       $$ = $1;        }
+       |       callsite_declaration
+               {       $$ = $1;        }
        |       declaration_specifiers TYPEDEF declaration_specifiers type_declarator_list SEMICOLON
                {
                        struct ctf_node *list;
@@ -1399,6 +1443,29 @@ clock_declaration_end:
                {       pop_scope(scanner);     }
        ;
 
+callsite_declaration:
+               CALLSITE callsite_declaration_begin callsite_declaration_end
+               {
+                       $$ = make_node(scanner, NODE_CALLSITE);
+               }
+       |       CALLSITE callsite_declaration_begin ctf_assignment_expression_list callsite_declaration_end
+               {
+                       $$ = make_node(scanner, NODE_CALLSITE);
+                       if (set_parent_node($3, $$))
+                               reparent_error(scanner, "trace_declaration");
+               }
+       ;
+
+callsite_declaration_begin:
+               LBRAC
+               {       push_scope(scanner);    }
+       ;
+
+callsite_declaration_end:
+               RBRAC SEMICOLON
+               {       pop_scope(scanner);     }
+       ;
+
 integer_declaration_specifiers:
                CONST
                {
This page took 0.03021 seconds and 4 git commands to generate.