9c06c07c4a90a1eeed05a9a072727576db6e346d
[oweals/jsonpath.git] / parser.y
1 /*
2  * Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 %token_type {struct jp_opcode *}
18 %extra_argument {struct jp_state *s}
19
20 %left T_AND.
21 %left T_OR.
22 %left T_UNION.
23 %nonassoc T_EQ T_NE T_GT T_GE T_LT T_LE.
24 %right T_NOT.
25
26 %include {
27 #include <assert.h>
28 #include <stddef.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "ast.h"
33 #include "lexer.h"
34 #include "parser.h"
35
36 #define alloc_op(type, num, str, ...) \
37         jp_alloc_op(s, type, num, str, ##__VA_ARGS__, NULL)
38
39 }
40
41 %syntax_error {
42         int n = sizeof(tokennames) / sizeof(tokennames[0]);
43         int l = strlen("Expecting ");
44         int c = 0;
45         int i;
46
47         for (i = 0; i < n; i++)
48         {
49                 if (yy_find_shift_action(yypParser, (YYCODETYPE)i) < YYNSTATE + YYNRULE)
50                         l += strlen(tokennames[i]) + 4;
51         }
52
53         s->error = malloc(l);
54
55         if (s->error)
56         {
57                 s->erroff = s->off;
58                 strcpy(s->error, "Expecting ");
59
60                 for (i = 0; i < n; i++)
61                 {
62                         if (yy_find_shift_action(yypParser, (YYCODETYPE)i) < YYNSTATE + YYNRULE)
63                         {
64                                 if (c++)
65                                         strcat(s->error, " or ");
66
67                                 strcat(s->error, tokennames[i]);
68                         }
69                 }
70         }
71 }
72
73
74 input ::= expr(A).                                                                      { s->path = A; }
75
76 expr(A) ::= T_LABEL(B) T_EQ path(C).                            { A = B; B->down = C; }
77 expr(A) ::= path(B).                                                            { A = B; }
78
79 path(A) ::= T_ROOT segments(B).                                         { A = alloc_op(T_ROOT, 0, NULL, B); }
80 path(A) ::= T_THIS segments(B).                                         { A = alloc_op(T_THIS, 0, NULL, B); }
81
82 segments(A) ::= segments(B) segment(C).                         { A = append_op(B, C); }
83 segments(A) ::= segment(B).                                                     { A = B; }
84
85 segment(A) ::= T_DOT T_LABEL(B).                                        { A = B; }
86 segment(A) ::= T_DOT T_WILDCARD(B).                                     { A = B; }
87 segment(A) ::= T_BROPEN union_exps(B) T_BRCLOSE.        { A = B; }
88
89 union_exps(A) ::= union_exp(B).                                         { A = B->sibling ? alloc_op(T_UNION, 0, NULL, B) : B; }
90
91 union_exp(A) ::= union_exp(B) T_UNION or_exps(C).       { A = append_op(B, C); }
92 union_exp(A) ::= or_exps(B).                                            { A = B; }
93
94 or_exps(A) ::= or_exp(B).                                                       { A = B->sibling ? alloc_op(T_OR, 0, NULL, B) : B; }
95
96 or_exp(A) ::= or_exp(B) T_OR and_exps(C).                       { A = append_op(B, C); }
97 or_exp(A) ::= and_exps(B).                                                      { A = B; }
98
99 and_exps(A) ::= and_exp(B).                                                     { A = B->sibling ? alloc_op(T_AND, 0, NULL, B) : B; }
100
101 and_exp(A) ::= and_exp(B) T_AND cmp_exp(C).                     { A = append_op(B, C); }
102 and_exp(A) ::= cmp_exp(B).                                                      { A = B; }
103
104 cmp_exp(A) ::= unary_exp(B) T_LT unary_exp(C).          { A = alloc_op(T_LT, 0, NULL, B, C); }
105 cmp_exp(A) ::= unary_exp(B) T_LE unary_exp(C).          { A = alloc_op(T_LE, 0, NULL, B, C); }
106 cmp_exp(A) ::= unary_exp(B) T_GT unary_exp(C).          { A = alloc_op(T_GT, 0, NULL, B, C); }
107 cmp_exp(A) ::= unary_exp(B) T_GE unary_exp(C).          { A = alloc_op(T_GE, 0, NULL, B, C); }
108 cmp_exp(A) ::= unary_exp(B) T_EQ unary_exp(C).          { A = alloc_op(T_EQ, 0, NULL, B, C); }
109 cmp_exp(A) ::= unary_exp(B) T_NE unary_exp(C).          { A = alloc_op(T_NE, 0, NULL, B, C); }
110 cmp_exp(A) ::= unary_exp(B).                                            { A = B; }
111
112 unary_exp(A) ::= T_BOOL(B).                                                     { A = B; }
113 unary_exp(A) ::= T_NUMBER(B).                                           { A = B; }
114 unary_exp(A) ::= T_STRING(B).                                           { A = B; }
115 unary_exp(A) ::= T_WILDCARD(B).                                         { A = B; }
116 unary_exp(A) ::= T_POPEN or_exps(B) T_PCLOSE.           { A = B; }
117 unary_exp(A) ::= T_NOT unary_exp(B).                            { A = alloc_op(T_NOT, 0, NULL, B); }
118 unary_exp(A) ::= path(B).                                                       { A = B; }