forked from ElektraInitiative/libelektra
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.y
218 lines (171 loc) · 4.88 KB
/
parser.y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/**
* @file parser.y
*
* @brief Contains the bison parser.
*
* @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
*
*/
%code requires{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <kdbhelper.h>
#include "error.h"
#include "scalar.h"
#include "driver.h"
#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
#define yylval_param lval
#define yylloc_param lloc
#define YY_DECL int yylex (YYSTYPE* lval, YYLTYPE * lloc, Driver * driver, yyscan_t yyscanner)
}
%define api.pure full
%lex-param { Driver * driver } { yyscan_t yyscanner }
%parse-param { Driver * driver } { yyscan_t yyscanner }
%locations
%define parse.error verbose
%code provides{
YY_DECL;
int yyerror(YYLTYPE * lloc, Driver * driver, yyscan_t yyscanner, const char* message);
}
%union {
Scalar* scalar;
}
%token <scalar> COMMENT
%token <scalar> DECIMAL
%token <scalar> HEXADECIMAL
%token <scalar> OCTAL
%token <scalar> BINARY
%token <scalar> FLOAT
%token <scalar> BOOLEAN
%token <scalar> BARE_STRING
%token <scalar> LITERAL_STRING
%token <scalar> BASIC_STRING
%token <scalar> MULTI_LITERAL_STRING
%token <scalar> MULTI_BASIC_STRING
%token <scalar> OFFSET_DATETIME
%token <scalar> LOCAL_DATETIME
%token <scalar> LOCAL_DATE
%token <scalar> LOCAL_TIME
%token NEWLINE
%token EQUAL
%token DOT
%token COMMA
%token BRACKETS_OPEN
%token BRACKETS_CLOSE
%token CURLY_OPEN
%token CURLY_CLOSE
%type <scalar> Scalar
%type <scalar> IntegerScalar
%type <scalar> BooleanScalar
%type <scalar> FloatScalar
%type <scalar> StringScalar
%type <scalar> DateScalar
%type <scalar> QuotedKey
%type <scalar> UnquotedKey
%destructor { freeScalar($$); } <scalar>
%start Toml
%%
Toml : NewlinesLeading Nodes NewlinesTrailing { driverExitToml(driver); }
| %empty
;
Nodes : Node
| Nodes NewlinesBetweenNodes Node
;
Node : COMMENT { driverExitComment (driver, $1); }
| Table OptComment { driverExitOptCommentTable (driver); }
| KeyPair OptComment { driverExitOptCommentKeyPair (driver); }
;
OptComment : COMMENT { driverExitComment (driver, $1); }
| %empty
;
NewlinesBetweenNodes : NEWLINE /* Not counted because it's the normal line ending newline between nodes, not one indicating an empty line.*/
| NewlinesBetweenNodes NEWLINE { yynerrs = 1*yynerrs; /* dummy use of yynerrs to suppress unused warning */ driverExitNewline (driver); }
;
NewlinesLeading : %empty
| NewlinesLeading NEWLINE { driverExitNewline(driver); }
;
NewlinesTrailing : NewlinesBetweenNodes
| %empty
;
Table : TableSimple
| TableArray
;
TableSimple : BRACKETS_OPEN { driverEnterSimpleTable(driver); } TopKey { driverExitSimpleTable(driver); } BRACKETS_CLOSE
;
TableArray : BRACKETS_OPEN BRACKETS_OPEN { driverEnterTableArray(driver); } TopKey { driverExitTableArray(driver); } BRACKETS_CLOSE BRACKETS_CLOSE
;
KeyPair : TopKey EQUAL Value { driverExitKeyValue (driver); }
;
TopKey : { driverEnterKey (driver); } Key { driverExitKey (driver); }
;
Key : SimpleKey
| SimpleKey DottedKeys
;
DottedKeys : DOT SimpleKey
| DottedKeys DOT SimpleKey
;
SimpleKey : QuotedKey { driverExitSimpleKey (driver, $1); }
| UnquotedKey { driverExitSimpleKey (driver, $1); }
;
QuotedKey : BASIC_STRING { $$ = $1; }
| LITERAL_STRING { $$ = $1; }
;
UnquotedKey : BARE_STRING { $$ = $1; }
;
Value : Scalar { driverExitValue (driver, $1); }
| InlineTable
| Array
;
InlineTable : CURLY_OPEN { driverEnterInlineTable(driver); } InlineTableList CURLY_CLOSE { driverExitInlineTable (driver); }
| CURLY_OPEN CURLY_CLOSE { driverEmptyInlineTable(driver); }
;
InlineTableList : KeyPair
| InlineTableList COMMA KeyPair
;
Array : ArrayEmpty
| ArrayNonEmpty
;
ArrayNonEmpty : BRACKETS_OPEN { driverEnterArray (driver); } ArrayList ArrayEpilogue BRACKETS_CLOSE { driverExitArray (driver); };
ArrayEmpty : BRACKETS_OPEN BRACKETS_CLOSE { driverEmptyArray (driver); };
ArrayList : AnyCommentNL ArrayElement
| ArrayList COMMA AnyCommentNL ArrayElement
;
ArrayElement : { driverEnterArrayElement(driver); } Value { driverExitArrayElement (driver); }
;
ArrayEpilogue : AnyCommentNL
| COMMA AnyCommentNL
;
AnyCommentNL : AnyCommentNL NEWLINE { driverExitNewline (driver); }
| AnyCommentNL COMMENT NEWLINE { driverExitComment (driver, $2); }
| %empty
;
Scalar : IntegerScalar { $$ = $1; }
| BooleanScalar { $$ = $1; }
| FloatScalar { $$ = $1; }
| StringScalar { $$ = $1; }
| DateScalar { $$ = $1; }
;
IntegerScalar : DECIMAL { $$ = $1; }
| HEXADECIMAL { $$ = $1; }
| OCTAL { $$ = $1; }
| BINARY { $$ = $1; }
;
BooleanScalar : BOOLEAN { $$ = $1; }
;
FloatScalar : FLOAT { $$ = $1; }
;
StringScalar : LITERAL_STRING { $$ = $1; }
| BASIC_STRING { $$ = $1; }
| MULTI_LITERAL_STRING { $$ = $1; }
| MULTI_BASIC_STRING { $$ = $1; }
;
DateScalar : OFFSET_DATETIME { $$ = $1; }
| LOCAL_DATETIME { $$ = $1; }
| LOCAL_DATE { $$ = $1; }
| LOCAL_TIME { $$ = $1; }
;
%%