1 /*
2  *
3   ***** BEGIN LICENSE BLOCK *****
4 
5   Copyright (C) 2009-2020 Olof Hagsand
6   Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate)
7 
8   This file is part of CLIXON.
9 
10   Licensed under the Apache License, Version 2.0 (the "License");
11   you may not use this file except in compliance with the License.
12   You may obtain a copy of the License at
13 
14     http://www.apache.org/licenses/LICENSE-2.0
15 
16   Unless required by applicable law or agreed to in writing, software
17   distributed under the License is distributed on an "AS IS" BASIS,
18   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   See the License for the specific language governing permissions and
20   limitations under the License.
21 
22   Alternatively, the contents of this file may be used under the terms of
23   the GNU General Public License Version 3 or later (the "GPL"),
24   in which case the provisions of the GPL are applicable instead
25   of those above. If you wish to allow use of your version of this file only
26   under the terms of the GPL, and not to allow others to
27   use your version of this file under the terms of Apache License version 2,
28   indicate your decision by deleting the provisions above and replace them with
29   the  notice and other provisions required by the GPL. If you do not delete
30   the provisions above, a recipient may use your version of this file under
31   the terms of any one of the Apache License version 2 or the GPL.
32 
33   ***** END LICENSE BLOCK *****
34 
35  * Yang parser. Hopefully useful but not complete
36  * @see https://tools.ietf.org/html/rfc6020 YANG 1.0
37  * @see https://tools.ietf.org/html/rfc7950 YANG 1.1
38  *
39  * How identifiers map
40  * IDENTIFIER     = [A-Za-z_][A-Za-z0-9_\-\.]
41  * prefix         = IDENTIFIER
42  * identifier_arg = IDENTIFIER
43  * identifier_ref = prefix : IDENTIFIER
44  * node_identier  = prefix : IDENTIFIER
45  *
46  * Missing args (just strings);
47  * - length-arg-str
48  * - path-arg-str
49  * - date-arg-str
50  */
51 
52 %start file
53 
54 %union {
55     char *string;
56 }
57 
58 %token MY_EOF
59 %token SQ           /* Single quote: ' */
60 %token SEP          /* Separators (at least one) */
61 %token <string>   CHARS
62 %token <string>   IDENTIFIER
63 %token <string>   BOOL
64 %token <string>   INT
65 
66 %type <string>    ustring
67 %type <string>    qstrings
68 %type <string>    qstring
69 %type <string>    string
70 %type <string>    integer_value_str
71 %type <string>    identifier_ref
72 %type <string>    abs_schema_nodeid
73 %type <string>    desc_schema_nodeid_strs
74 %type <string>    desc_schema_nodeid_str
75 %type <string>    desc_schema_nodeid
76 %type <string>    node_identifier
77 %type <string>    identifier_str
78 %type <string>    identifier_ref_str
79 %type <string>    bool_str
80 
81 
82 /* rfc 6020 keywords
83    See also enum rfc_6020 in clicon_yang.h. There, the constants have Y_ prefix instead of K_
84  * Wanted to unify these (K_ and Y_) but gave up for several reasons:
85  * - Dont want to expose a generated yacc file to the API
86  * - Cant use the symbols in this file because yacc needs token definitions
87  */
88 %token K_ACTION
89 %token K_ANYDATA
90 %token K_ANYXML
91 %token K_ARGUMENT
92 %token K_AUGMENT
93 %token K_BASE
94 %token K_BELONGS_TO
95 %token K_BIT
96 %token K_CASE
97 %token K_CHOICE
98 %token K_CONFIG
99 %token K_CONTACT
100 %token K_CONTAINER
101 %token K_DEFAULT
102 %token K_DESCRIPTION
103 %token K_DEVIATE
104 %token K_DEVIATION
105 %token K_ENUM
106 %token K_ERROR_APP_TAG
107 %token K_ERROR_MESSAGE
108 %token K_EXTENSION
109 %token K_FEATURE
110 %token K_FRACTION_DIGITS
111 %token K_GROUPING
112 %token K_IDENTITY
113 %token K_IF_FEATURE
114 %token K_IMPORT
115 %token K_INCLUDE
116 %token K_INPUT
117 %token K_KEY
118 %token K_LEAF
119 %token K_LEAF_LIST
120 %token K_LENGTH
121 %token K_LIST
122 %token K_MANDATORY
123 %token K_MAX_ELEMENTS
124 %token K_MIN_ELEMENTS
125 %token K_MODIFIER
126 %token K_MODULE
127 %token K_MUST
128 %token K_NAMESPACE
129 %token K_NOTIFICATION
130 %token K_ORDERED_BY
131 %token K_ORGANIZATION
132 %token K_OUTPUT
133 %token K_PATH
134 %token K_PATTERN
135 %token K_POSITION
136 %token K_PREFIX
137 %token K_PRESENCE
138 %token K_RANGE
139 %token K_REFERENCE
140 %token K_REFINE
141 %token K_REQUIRE_INSTANCE
142 %token K_REVISION
143 %token K_REVISION_DATE
144 %token K_RPC
145 %token K_STATUS
146 %token K_SUBMODULE
147 %token K_TYPE
148 %token K_TYPEDEF
149 %token K_UNIQUE
150 %token K_UNITS
151 %token K_USES
152 %token K_VALUE
153 %token K_WHEN
154 %token K_YANG_VERSION
155 %token K_YIN_ELEMENT
156 
157 
158 %lex-param     {void *_yy} /* Add this argument to parse() and lex() function */
159 %parse-param   {void *_yy}
160 
161 %{
162 /* Here starts user C-code */
163 
164 /* typecast macro */
165 #define _YY ((clixon_yang_yacc *)_yy)
166 
167 #define _YYERROR(msg) {clicon_debug(1, "YYERROR %s '%s' %d", (msg), clixon_yang_parsetext, _YY->yy_linenum); YYERROR;}
168 
169 /* add _yy to error parameters */
170 #define YY_(msgid) msgid
171 
172 #include "clixon_config.h"
173 
174 #include <stdio.h>
175 #include <string.h>
176 #include <stdint.h>
177 #include <stdlib.h>
178 #include <errno.h>
179 #include <ctype.h>
180 #include <sys/types.h>
181 #include <sys/socket.h>
182 #include <netinet/in.h>
183 #include <net/if.h>
184 
185 #include <cligen/cligen.h>
186 
187 #include "clixon_queue.h"
188 #include "clixon_hash.h"
189 #include "clixon_handle.h"
190 #include "clixon_err.h"
191 #include "clixon_log.h"
192 #include "clixon_yang.h"
193 #include "clixon_yang_parse_lib.h"
194 #include "clixon_yang_parse.h"
195 
196 extern int clixon_yang_parseget_lineno  (void);
197 
198 /*
199    clixon_yang_parseerror
200    also called from yacc generated code *
201 */
202 void
clixon_yang_parseerror(void * _yy,char * s)203 clixon_yang_parseerror(void *_yy,
204 		       char *s)
205 {
206     clicon_err(OE_YANG, 0, "%s on line %d: %s at or before: '%s'",
207 	       _YY->yy_name,
208 	       _YY->yy_linenum ,
209 	       s,
210 	       clixon_yang_parsetext);
211   return;
212 }
213 
214 int
yang_parse_init(clixon_yang_yacc * yy)215     yang_parse_init(clixon_yang_yacc *yy)
216 {
217     return 0;
218 }
219 
220 
221 int
yang_parse_exit(clixon_yang_yacc * yy)222 yang_parse_exit(clixon_yang_yacc *yy)
223 {
224     return 0;
225 }
226 
227 /*! Pop a yang parse context on stack
228  * @param[in]  yy        Yang yacc argument
229  */
230 int
ystack_pop(clixon_yang_yacc * yy)231 ystack_pop(clixon_yang_yacc *yy)
232 {
233     struct ys_stack *ystack;
234 
235     if ((ystack = yy->yy_stack) == NULL){
236 	clicon_err(OE_YANG, 0, "ystack is NULL");
237 	return -1;
238     }
239     yy->yy_stack = ystack->ys_next;
240     free(ystack);
241     return 0;
242 }
243 
244 /*! Push a yang parse context on stack
245  * @param[in]  yy        Yang yacc argument
246  * @param[in]  yn        Yang node to push
247  */
248 struct ys_stack *
ystack_push(clixon_yang_yacc * yy,yang_stmt * yn)249 ystack_push(clixon_yang_yacc *yy,
250 	    yang_stmt        *yn)
251 {
252     struct ys_stack *ystack;
253 
254     if ((ystack = malloc(sizeof(*ystack))) == NULL) {
255 	clicon_err(OE_YANG, errno, "malloc");
256 	return NULL;
257     }
258     memset(ystack, 0, sizeof(*ystack));
259     ystack->ys_node = yn;
260     ystack->ys_next = yy->yy_stack;
261     yy->yy_stack = ystack;
262     return ystack;
263 }
264 
265 /*! Add a yang statement to existing top-of-stack.
266  *
267  * @param[in]  yy        Yang yacc argument
268  * @param[in]  keyword   Yang keyword
269  * @param[in]  argument  Yang argument
270  * @param[in]  extra     Yang extra for cornercases (unknown/extension)
271 
272  * @note consumes 'argument' and 'extra' which assumes it is malloced and not freed by caller
273  */
274 static yang_stmt *
ysp_add(clixon_yang_yacc * yy,enum rfc_6020 keyword,char * argument,char * extra)275 ysp_add(clixon_yang_yacc *yy,
276 	enum rfc_6020     keyword,
277 	char             *argument,
278     	char             *extra)
279 {
280     struct ys_stack *ystack = yy->yy_stack;
281     yang_stmt       *ys = NULL;
282     yang_stmt       *yn;
283 
284     ystack = yy->yy_stack;
285     if (ystack == NULL){
286 	clicon_err(OE_YANG, errno, "No stack");
287 	goto err;
288     }
289     if ((yn = ystack->ys_node) == NULL){
290 	clicon_err(OE_YANG, errno, "No ys_node");
291 	goto err;
292     }
293     if ((ys = ys_new(keyword)) == NULL)
294 	goto err;
295     /* NOTE: does not make a copy of string, ie argument is 'consumed' here */
296     yang_argument_set(ys, argument);
297     if (yn_insert(yn, ys) < 0) /* Insert into hierarchy */
298 	goto err;
299     if (ys_parse_sub(ys, extra) < 0)     /* Check statement-specific syntax */
300 	goto err2; /* dont free since part of tree */
301 //  done:
302     return ys;
303   err:
304     if (ys)
305 	ys_free(ys);
306   err2:
307     return NULL;
308 }
309 
310 /*! Add a yang statement to existing top-of-stack and then push it on stack
311  *
312  * @param[in]  yy        Yang yacc argument
313  * @param[in]  keyword   Yang keyword
314  * @param[in]  argument  Yang argument
315  * @param[in]  extra     Yang extra for cornercases (unknown/extension)
316  */
317 static yang_stmt *
ysp_add_push(clixon_yang_yacc * yy,enum rfc_6020 keyword,char * argument,char * extra)318 ysp_add_push(clixon_yang_yacc *yy,
319 	     enum rfc_6020     keyword,
320 	     char             *argument,
321     	     char             *extra)
322 {
323     yang_stmt *ys;
324 
325     if ((ys = ysp_add(yy, keyword, argument, extra)) == NULL)
326 	return NULL;
327     if (ystack_push(yy, ys) == NULL)
328 	return NULL;
329     return ys;
330 }
331 
332 /*! Join two string with delimiter.
333  * @param[in] str1   string 1 (will be freed) (optional)
334  * @param[in] del    delimiter string (not freed) cannot be NULL (but "")
335  * @param[in] str2   string 2 (will be freed)
336  */
337 static char*
string_del_join(char * str1,char * del,char * str2)338 string_del_join(char *str1,
339 		char *del,
340 		char *str2)
341 {
342     char *str;
343     int   len;
344 
345     len = strlen(str2) + 1;
346 
347     if (str1)
348 	len += strlen(str1);
349     len += strlen(del);
350     if ((str = malloc(len)) == NULL){
351 	clicon_err(OE_UNIX, errno, "malloc");
352 	return NULL;
353     }
354     if (str1){
355 	snprintf(str, len, "%s%s%s", str1, del, str2);
356 	free(str1);
357     }
358     else
359 	snprintf(str, len, "%s%s", del, str2);
360     free(str2);
361     return str;
362 }
363 
364 %}
365 
366 %%
367 
368 /*
369    statement = keyword [argument] (";" / "{" *statement "}")
370    The argument is a string
371    recursion: right is wrong
372    Let subststmt rules contain an empty rule, but not stmt rules
373 */
374 
375 file          : module_stmt MY_EOF
376                        { clicon_debug(3,"file->module-stmt"); YYACCEPT; }
377               | submodule_stmt MY_EOF
378                        { clicon_debug(3,"file->submodule-stmt"); YYACCEPT; }
379               ;
380 
381 /* module identifier-arg-str */
382 module_stmt   : K_MODULE identifier_str
383                   { if ((_YY->yy_module = ysp_add_push(_yy, Y_MODULE, $2, NULL)) == NULL) _YYERROR("module_stmt");
384                         }
385                 '{' module_substmts '}'
386                   { if (ystack_pop(_yy) < 0) _YYERROR("module_stmt");
387 		    clicon_debug(3,"module_stmt -> id-arg-str { module-substmts }");}
388               ;
389 
390 module_substmts : module_substmts module_substmt
391                       {clicon_debug(3,"module-substmts -> module-substmts module-substm");}
392               | module_substmt
393                       { clicon_debug(3,"module-substmts ->");}
394               ;
395 
396 module_substmt : module_header_stmts { clicon_debug(3,"module-substmt -> module-header-stmts");}
397                | linkage_stmts       { clicon_debug(3,"module-substmt -> linake-stmts");}
398                | meta_stmts          { clicon_debug(3,"module-substmt -> meta-stmts");}
399                | revision_stmts      { clicon_debug(3,"module-substmt -> revision-stmts");}
400                | body_stmts          { clicon_debug(3,"module-substmt -> body-stmts");}
401                | unknown_stmt        { clicon_debug(3,"module-substmt -> unknown-stmt");}
402                |                     { clicon_debug(3,"module-substmt ->");}
403                ;
404 
405 /* submodule */
406 submodule_stmt : K_SUBMODULE identifier_str
407                     { if ((_YY->yy_module = ysp_add_push(_yy, Y_SUBMODULE, $2, NULL)) == NULL) _YYERROR("submodule_stmt"); }
408                 '{' submodule_substmts '}'
409                     { if (ystack_pop(_yy) < 0) _YYERROR("submodule_stmt");
410 			clicon_debug(3,"submodule_stmt -> id-arg-str { submodule-substmts }");}
411               ;
412 
413 submodule_substmts : submodule_substmts submodule_substmt
414                        { clicon_debug(3,"submodule-stmts -> submodule-substmts submodule-substmt"); }
415               | submodule_substmt
416                        { clicon_debug(3,"submodule-stmts -> submodule-substmt"); }
417               ;
418 
419 submodule_substmt : submodule_header_stmts
420                               { clicon_debug(3,"submodule-substmt -> submodule-header-stmts"); }
421                | linkage_stmts  { clicon_debug(3,"submodule-substmt -> linake-stmts");}
422                | meta_stmts     { clicon_debug(3,"submodule-substmt -> meta-stmts");}
423                | revision_stmts { clicon_debug(3,"submodule-substmt -> revision-stmts");}
424                | body_stmts     { clicon_debug(3,"submodule-stmt -> body-stmts"); }
425                | unknown_stmt   { clicon_debug(3,"submodule-substmt -> unknown-stmt");}
426                |                { clicon_debug(3,"submodule-substmt ->");}
427               ;
428 
429 /* linkage */
430 linkage_stmts : linkage_stmts linkage_stmt
431                        { clicon_debug(3,"linkage-stmts -> linkage-stmts linkage-stmt"); }
432               | linkage_stmt
433                        { clicon_debug(3,"linkage-stmts -> linkage-stmt"); }
434               ;
435 
436 linkage_stmt  : import_stmt  { clicon_debug(3,"linkage-stmt -> import-stmt"); }
437               | include_stmt { clicon_debug(3,"linkage-stmt -> include-stmt"); }
438               ;
439 
440 /* module-header */
441 module_header_stmts : module_header_stmts module_header_stmt
442                   { clicon_debug(3,"module-header-stmts -> module-header-stmts module-header-stmt"); }
443               | module_header_stmt   { clicon_debug(3,"module-header-stmts -> "); }
444               ;
445 
446 module_header_stmt : yang_version_stmt
447                                { clicon_debug(3,"module-header-stmt -> yang-version-stmt"); }
448               | namespace_stmt { clicon_debug(3,"module-header-stmt -> namespace-stmt"); }
449               | prefix_stmt    { clicon_debug(3,"module-header-stmt -> prefix-stmt"); }
450               ;
451 
452 /* submodule-header */
453 submodule_header_stmts : submodule_header_stmts submodule_header_stmt
454                   { clicon_debug(3,"submodule-header-stmts -> submodule-header-stmts submodule-header-stmt"); }
455               | submodule_header_stmt
456                   { clicon_debug(3,"submodule-header-stmts -> submodule-header-stmt"); }
457               ;
458 
459 submodule_header_stmt : yang_version_stmt
460                   { clicon_debug(3,"submodule-header-stmt -> yang-version-stmt"); }
461               | belongs_to_stmt { clicon_debug(3,"submodule-header-stmt -> belongs-to-stmt"); }
462               ;
463 
464 /* yang-version-stmt = yang-version-keyword  yang-version-arg-str */
465 yang_version_stmt : K_YANG_VERSION string stmtend
466 		{ if (ysp_add(_yy, Y_YANG_VERSION, $2, NULL) == NULL) _YYERROR("yang_version_stmt");
467                             clicon_debug(3,"yang-version-stmt -> YANG-VERSION string"); }
468               ;
469 
470 /* import */
471 import_stmt   : K_IMPORT identifier_str
472                      { if (ysp_add_push(_yy, Y_IMPORT, $2, NULL) == NULL) _YYERROR("import_stmt"); }
473                 '{' import_substmts '}'
474                      { if (ystack_pop(_yy) < 0) _YYERROR("import_stmt");
475 		       clicon_debug(3,"import-stmt -> IMPORT id-arg-str { import-substmts }");}
476               ;
477 
478 import_substmts : import_substmts import_substmt
479                       { clicon_debug(3,"import-substmts -> import-substmts import-substm");}
480               | import_substmt
481                       { clicon_debug(3,"import-substmts ->");}
482               ;
483 
484 import_substmt : prefix_stmt {  clicon_debug(3,"import-stmt -> prefix-stmt"); }
485                | revision_date_stmt {  clicon_debug(3,"import-stmt -> revision-date-stmt"); }
486                | description_stmt   { clicon_debug(3,"import-stmt -> description-stmt"); }
487                | reference_stmt {  clicon_debug(3,"import-stmt -> reference-stmt"); }
488               ;
489 
490 include_stmt  : K_INCLUDE identifier_str ';'
491 		{ if (ysp_add(_yy, Y_INCLUDE, $2, NULL)== NULL) _YYERROR("include_stmt");
492                            clicon_debug(3,"include-stmt -> id-str"); }
493               | K_INCLUDE identifier_str
494 	      { if (ysp_add_push(_yy, Y_INCLUDE, $2, NULL) == NULL) _YYERROR("include_stmt"); }
495 	      '{' include_substmts '}'
496                 { if (ystack_pop(_yy) < 0) _YYERROR("include_stmt");
497                   clicon_debug(3,"include-stmt -> id-str { include-substmts }"); }
498               ;
499 
500 include_substmts : include_substmts include_substmt
501                       { clicon_debug(3,"include-substmts -> include-substmts include-substm");}
502               | include_substmt
503                       { clicon_debug(3,"include-substmts ->");}
504               ;
505 
506 include_substmt : revision_date_stmt {  clicon_debug(3,"include-stmt -> revision-date-stmt"); }
507                 | description_stmt   { clicon_debug(3,"include-stmt -> description-stmt"); }
508                 | reference_stmt {  clicon_debug(3,"include-stmt -> reference-stmt"); }
509                ;
510 
511 
512 /* namespace-stmt = namespace-keyword sep uri-str */
513 namespace_stmt : K_NAMESPACE string stmtend
514 		{ if (ysp_add(_yy, Y_NAMESPACE, $2, NULL)== NULL) _YYERROR("namespace_stmt");
515                             clicon_debug(3,"namespace-stmt -> NAMESPACE string"); }
516               ;
517 
518 prefix_stmt   : K_PREFIX identifier_str stmtend /* XXX prefix-arg-str */
519 		{ if (ysp_add(_yy, Y_PREFIX, $2, NULL)== NULL) _YYERROR("prefix_stmt");
520 			     clicon_debug(3,"prefix-stmt -> PREFIX string ;");}
521               ;
522 
523 belongs_to_stmt : K_BELONGS_TO identifier_str
524                     { if (ysp_add_push(_yy, Y_BELONGS_TO, $2, NULL) == NULL) _YYERROR("belongs_to_stmt"); }
525 
526                   '{' prefix_stmt '}'
527                     { if (ystack_pop(_yy) < 0) _YYERROR("belongs_to_stmt");
528 		      clicon_debug(3,"belongs-to-stmt -> BELONGS-TO id-arg-str { prefix-stmt } ");
529 			}
530                  ;
531 
532 organization_stmt: K_ORGANIZATION string stmtend
533 		{ if (ysp_add(_yy, Y_ORGANIZATION, $2, NULL)== NULL) _YYERROR("belongs_to_stmt");
534 			   clicon_debug(3,"organization-stmt -> ORGANIZATION string ;");}
535               ;
536 
537 contact_stmt  : K_CONTACT string stmtend
538 		{ if (ysp_add(_yy, Y_CONTACT, $2, NULL)== NULL) _YYERROR("contact_stmt");
539                             clicon_debug(3,"contact-stmt -> CONTACT string"); }
540               ;
541 
542 description_stmt : K_DESCRIPTION string stmtend
543 		{ if (ysp_add(_yy, Y_DESCRIPTION, $2, NULL)== NULL) _YYERROR("description_stmt");
544 			   clicon_debug(3,"description-stmt -> DESCRIPTION string ;");}
545               ;
546 
547 reference_stmt : K_REFERENCE string stmtend
548 		{ if (ysp_add(_yy, Y_REFERENCE, $2, NULL)== NULL) _YYERROR("reference_stmt");
549 			   clicon_debug(3,"reference-stmt -> REFERENCE string ;");}
550               ;
551 
552 units_stmt    : K_UNITS string ';'
553 		{ if (ysp_add(_yy, Y_UNITS, $2, NULL)== NULL) _YYERROR("units_stmt");
554                             clicon_debug(3,"units-stmt -> UNITS string"); }
555               ;
556 
557 revision_stmt : K_REVISION string ';'  /* XXX date-arg-str */
558 		{ if (ysp_add(_yy, Y_REVISION, $2, NULL) == NULL) _YYERROR("revision_stmt");
559 			 clicon_debug(3,"revision-stmt -> date-arg-str ;"); }
560               | K_REVISION string
561 	      { if (ysp_add_push(_yy, Y_REVISION, $2, NULL) == NULL) _YYERROR("revision_stmt"); }
562                 '{' revision_substmts '}'  /* XXX date-arg-str */
563                      { if (ystack_pop(_yy) < 0) _YYERROR("revision_stmt");
564 		       clicon_debug(3,"revision-stmt -> date-arg-str { revision-substmts  }"); }
565               ;
566 
567 revision_substmts : revision_substmts revision_substmt
568                      { clicon_debug(3,"revision-substmts -> revision-substmts revision-substmt }"); }
569               | revision_substmt
570                      { clicon_debug(3,"revision-substmts -> }"); }
571               ;
572 
573 revision_substmt : description_stmt { clicon_debug(3,"revision-substmt -> description-stmt"); }
574               | reference_stmt      { clicon_debug(3,"revision-substmt -> reference-stmt"); }
575               | unknown_stmt        { clicon_debug(3,"revision-substmt -> unknown-stmt");}
576               |                     { clicon_debug(3,"revision-substmt -> "); }
577               ;
578 
579 
580 /* revision */
581 revision_stmts : revision_stmts revision_stmt
582                        { clicon_debug(3,"revision-stmts -> revision-stmts revision-stmt"); }
583               | revision_stmt
584                        { clicon_debug(3,"revision-stmts -> "); }
585               ;
586 
587 revision_date_stmt : K_REVISION_DATE string stmtend  /* XXX date-arg-str */
588 		{ if (ysp_add(_yy, Y_REVISION_DATE, $2, NULL) == NULL) _YYERROR("revision_date_stmt");
589 			 clicon_debug(3,"revision-date-stmt -> date;"); }
590               ;
591 
592 extension_stmt : K_EXTENSION identifier_str ';'
593 	       { if (ysp_add(_yy, Y_EXTENSION, $2, NULL) == NULL) _YYERROR("extension_stmt");
594                     clicon_debug(3,"extenstion-stmt -> EXTENSION id-str ;"); }
595               | K_EXTENSION identifier_str
596  	        { if (ysp_add_push(_yy, Y_EXTENSION, $2, NULL) == NULL) _YYERROR("extension_stmt"); }
597 	       '{' extension_substmts '}'
598 	         { if (ystack_pop(_yy) < 0) _YYERROR("extension_stmt");
599                     clicon_debug(3,"extension-stmt -> EXTENSION id-str { extension-substmts }"); }
600 	      ;
601 
602 /* extension substmts */
603 extension_substmts : extension_substmts extension_substmt
604                   { clicon_debug(3,"extension-substmts -> extension-substmts extension-substmt"); }
605               | extension_substmt
606                   { clicon_debug(3,"extension-substmts -> extension-substmt"); }
607               ;
608 
609 extension_substmt : argument_stmt    { clicon_debug(3,"extension-substmt -> argument-stmt"); }
610               | status_stmt          { clicon_debug(3,"extension-substmt -> status-stmt"); }
611               | description_stmt     { clicon_debug(3,"extension-substmt -> description-stmt"); }
612               | reference_stmt       { clicon_debug(3,"extension-substmt -> reference-stmt"); }
613               | unknown_stmt         { clicon_debug(3,"extension-substmt -> unknown-stmt");}
614               |                      { clicon_debug(3,"extension-substmt -> "); }
615               ;
616 
617 argument_stmt  : K_ARGUMENT identifier_str ';'
618                { if (ysp_add(_yy, Y_ARGUMENT, $2, NULL) == NULL) _YYERROR("argument_stmt");
619 			 clicon_debug(3,"argument-stmt -> ARGUMENT identifier ;"); }
620                | K_ARGUMENT identifier_str
621 	       { if (ysp_add_push(_yy, Y_ARGUMENT, $2, NULL) == NULL) _YYERROR("argument_stmt"); }
622                 '{' argument_substmts '}'
623                        { if (ystack_pop(_yy) < 0) _YYERROR("argument_stmt");
624 	                 clicon_debug(3,"argument-stmt -> ARGUMENT { argument-substmts }"); }
625                ;
626 
627 /* argument substmts */
628 argument_substmts : argument_substmts argument_substmt
629                       { clicon_debug(3,"argument-substmts -> argument-substmts argument-substmt"); }
630                   | argument_substmt
631                       { clicon_debug(3,"argument-substmts -> argument-substmt"); }
632                   ;
633 
634 argument_substmt : yin_element_stmt1 { clicon_debug(3,"argument-substmt -> yin-element-stmt1");}
635                  | unknown_stmt   { clicon_debug(3,"argument-substmt -> unknown-stmt");}
636                  ;
637 
638 
639 /* Example of optional rule, eg [yin-element-stmt] */
640 yin_element_stmt1 : K_YIN_ELEMENT bool_str stmtend {free($2);}
641                ;
642 
643 /* Identity */
644 identity_stmt  : K_IDENTITY identifier_str ';'
645 	      { if (ysp_add(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("identity_stmt");
646 			   clicon_debug(3,"identity-stmt -> IDENTITY string ;"); }
647 
648               | K_IDENTITY identifier_str
649 	      { if (ysp_add_push(_yy, Y_IDENTITY, $2, NULL) == NULL) _YYERROR("identity_stmt"); }
650 	       '{' identity_substmts '}'
651                            { if (ystack_pop(_yy) < 0) _YYERROR("identity_stmt");
652 			     clicon_debug(3,"identity-stmt -> IDENTITY string { identity-substmts }"); }
653               ;
654 
655 identity_substmts : identity_substmts identity_substmt
656                       { clicon_debug(3,"identity-substmts -> identity-substmts identity-substmt"); }
657               | identity_substmt
658                       { clicon_debug(3,"identity-substmts -> identity-substmt"); }
659               ;
660 
661 identity_substmt : if_feature_stmt   { clicon_debug(3,"identity-substmt -> if-feature-stmt"); }
662               | base_stmt            { clicon_debug(3,"identity-substmt -> base-stmt"); }
663               | status_stmt          { clicon_debug(3,"identity-substmt -> status-stmt"); }
664               | description_stmt     { clicon_debug(3,"identity-substmt -> description-stmt"); }
665               | reference_stmt       { clicon_debug(3,"identity-substmt -> reference-stmt"); }
666               | unknown_stmt         { clicon_debug(3,"identity-substmt -> unknown-stmt");}
667               |                      { clicon_debug(3,"identity-substmt -> "); }
668               ;
669 
670 base_stmt     : K_BASE identifier_ref_str stmtend
671 		{ if (ysp_add(_yy, Y_BASE, $2, NULL)== NULL) _YYERROR("base_stmt");
672                             clicon_debug(3,"base-stmt -> BASE identifier-ref-arg-str"); }
673               ;
674 
675 /* Feature */
676 feature_stmt  : K_FEATURE identifier_str ';'
677 	       { if (ysp_add(_yy, Y_FEATURE, $2, NULL) == NULL) _YYERROR("feature_stmt");
678 		      clicon_debug(3,"feature-stmt -> FEATURE id-arg-str ;"); }
679               | K_FEATURE identifier_str
680 	      { if (ysp_add_push(_yy, Y_FEATURE, $2, NULL) == NULL) _YYERROR("feature_stmt"); }
681               '{' feature_substmts '}'
682                   { if (ystack_pop(_yy) < 0) _YYERROR("feature_stmt");
683                     clicon_debug(3,"feature-stmt -> FEATURE id-arg-str { feature-substmts }"); }
684               ;
685 
686 /* feature substmts */
687 feature_substmts : feature_substmts feature_substmt
688                       { clicon_debug(3,"feature-substmts -> feature-substmts feature-substmt"); }
689               | feature_substmt
690                       { clicon_debug(3,"feature-substmts -> feature-substmt"); }
691               ;
692 
693 feature_substmt : if_feature_stmt    { clicon_debug(3,"feature-substmt -> if-feature-stmt"); }
694               | status_stmt          { clicon_debug(3,"feature-substmt -> status-stmt"); }
695               | description_stmt     { clicon_debug(3,"feature-substmt -> description-stmt"); }
696               | reference_stmt       { clicon_debug(3,"feature-substmt -> reference-stmt"); }
697               | unknown_stmt         { clicon_debug(3,"feature-substmt -> unknown-stmt");}
698               |                      { clicon_debug(3,"feature-substmt -> "); }
699               ;
700 
701 /* if-feature-stmt = if-feature-keyword sep if-feature-expr-str */
702 if_feature_stmt : K_IF_FEATURE string stmtend
703 		{ if (ysp_add(_yy, Y_IF_FEATURE, $2, NULL) == NULL) _YYERROR("if_feature_stmt");
704                             clicon_debug(3,"if-feature-stmt -> IF-FEATURE identifier-ref-arg-str"); }
705               ;
706 
707 /* Typedef */
708 typedef_stmt  : K_TYPEDEF identifier_str
709                  { if (ysp_add_push(_yy, Y_TYPEDEF, $2, NULL) == NULL) _YYERROR("typedef_stmt"); }
710 	       '{' typedef_substmts '}'
711                  { if (ystack_pop(_yy) < 0) _YYERROR("typedef_stmt");
712 		   clicon_debug(3,"typedef-stmt -> TYPEDEF id-arg-str { typedef-substmts }"); }
713               ;
714 
715 typedef_substmts : typedef_substmts typedef_substmt
716                       { clicon_debug(3,"typedef-substmts -> typedef-substmts typedef-substmt"); }
717               | typedef_substmt
718                       { clicon_debug(3,"typedef-substmts -> typedef-substmt"); }
719               ;
720 
721 typedef_substmt : type_stmt          { clicon_debug(3,"typedef-substmt -> type-stmt"); }
722               | units_stmt           { clicon_debug(3,"typedef-substmt -> units-stmt"); }
723               | default_stmt         { clicon_debug(3,"typedef-substmt -> default-stmt"); }
724               | status_stmt          { clicon_debug(3,"typedef-substmt -> status-stmt"); }
725               | description_stmt     { clicon_debug(3,"typedef-substmt -> description-stmt"); }
726               | reference_stmt       { clicon_debug(3,"typedef-substmt -> reference-stmt"); }
727               | unknown_stmt         { clicon_debug(3,"typedef-substmt -> unknown-stmt");}
728               |                      { clicon_debug(3,"typedef-substmt -> "); }
729               ;
730 
731 /* Type */
732 type_stmt     : K_TYPE identifier_ref_str ';'
733 	       { if (ysp_add(_yy, Y_TYPE, $2, NULL) == NULL) _YYERROR("type_stmt");
734 			   clicon_debug(3,"type-stmt -> TYPE identifier-ref-arg-str ;");}
735               | K_TYPE identifier_ref_str
736 	      { if (ysp_add_push(_yy, Y_TYPE, $2, NULL) == NULL) _YYERROR("type_stmt");
737 			 }
738                 '{' type_body_stmts '}'
739                          { if (ystack_pop(_yy) < 0) _YYERROR("type_stmt");
740                            clicon_debug(3,"type-stmt -> TYPE identifier-ref-arg-str { type-body-stmts }");}
741               ;
742 
743 /* type-body-stmts is a little special since it is a choice of
744    sub-specifications that are all lists. One could model it as a list of
745    type-body-stmts and each individual specification as a simple.
746  */
747 type_body_stmts : type_body_stmts type_body_stmt
748                          { clicon_debug(3,"type-body-stmts -> type-body-stmts type-body-stmt"); }
749               |
750                          { clicon_debug(3,"type-body-stmts -> "); }
751               ;
752 
753 type_body_stmt/* numerical-restrictions */
754               : range_stmt             { clicon_debug(3,"type-body-stmt -> range-stmt"); }
755               /* decimal64-specification */
756               | fraction_digits_stmt   { clicon_debug(3,"type-body-stmt -> fraction-digits-stmt"); }
757               /* string-restrictions */
758               | length_stmt           { clicon_debug(3,"type-body-stmt -> length-stmt"); }
759               | pattern_stmt          { clicon_debug(3,"type-body-stmt -> pattern-stmt"); }
760               /* enum-specification */
761               | enum_stmt             { clicon_debug(3,"type-body-stmt -> enum-stmt"); }
762               /* leafref-specifications */
763               | path_stmt             { clicon_debug(3,"type-body-stmt -> path-stmt"); }
764               | require_instance_stmt { clicon_debug(3,"type-body-stmt -> require-instance-stmt"); }
765               /* identityref-specification */
766               | base_stmt             { clicon_debug(3,"type-body-stmt -> base-stmt"); }
767               /* instance-identifier-specification (see require-instance-stmt above */
768               /* bits-specification */
769               | bit_stmt               { clicon_debug(3,"type-body-stmt -> bit-stmt"); }
770               /* union-specification */
771               | type_stmt              { clicon_debug(3,"type-body-stmt -> type-stmt"); }
772 /* Cisco uses this (eg Cisco-IOS-XR-sysadmin-nto-misc-set-hostname.yang) but I dont see this is in the RFC */
773               | unknown_stmt           { clicon_debug(3,"type-body-stmt -> unknown-stmt");}
774               ;
775 
776 /* range-stmt */
777 range_stmt   : K_RANGE string ';' /* XXX range-arg-str */
778 	       { if (ysp_add(_yy, Y_RANGE, $2, NULL) == NULL) _YYERROR("range_stmt");
779 			   clicon_debug(3,"range-stmt -> RANGE string ;"); }
780 
781               | K_RANGE string
782 	      { if (ysp_add_push(_yy, Y_RANGE, $2, NULL) == NULL) _YYERROR("range_stmt"); }
783 	       '{' range_substmts '}'
784                           { if (ystack_pop(_yy) < 0) _YYERROR("range_stmt");
785 			     clicon_debug(3,"range-stmt -> RANGE string { range-substmts }"); }
786               ;
787 
788 range_substmts : range_substmts range_substmt
789                       { clicon_debug(3,"range-substmts -> range-substmts range-substmt"); }
790               | range_substmt
791                       { clicon_debug(3,"range-substmts -> range-substmt"); }
792               ;
793 
794 range_substmt : error_message_stmt   { clicon_debug(3,"range-substmt -> error-message-stmt");}
795               | description_stmt     { clicon_debug(3,"range-substmt -> description-stmt"); }
796               | reference_stmt       { clicon_debug(3,"range-substmt -> reference-stmt"); }
797               | unknown_stmt         { clicon_debug(3,"range-substmt -> unknown-stmt");}
798               |                      { clicon_debug(3,"range-substmt -> "); }
799               ;
800 
801 /* fraction-digits-stmt = fraction-digits-keyword fraction-digits-arg-str */
802 fraction_digits_stmt : K_FRACTION_DIGITS string stmtend
803 		{ if (ysp_add(_yy, Y_FRACTION_DIGITS, $2, NULL) == NULL) _YYERROR("fraction_digits_stmt");
804                             clicon_debug(3,"fraction-digits-stmt -> FRACTION-DIGITS string"); }
805               ;
806 
807 /* meta */
808 meta_stmts    : meta_stmts meta_stmt { clicon_debug(3,"meta-stmts -> meta-stmts meta-stmt"); }
809               | meta_stmt            { clicon_debug(3,"meta-stmts -> meta-stmt"); }
810               ;
811 
812 meta_stmt     : organization_stmt    { clicon_debug(3,"meta-stmt -> organization-stmt"); }
813               | contact_stmt         { clicon_debug(3,"meta-stmt -> contact-stmt"); }
814               | description_stmt     { clicon_debug(3,"meta-stmt -> description-stmt"); }
815               | reference_stmt       { clicon_debug(3,"meta-stmt -> reference-stmt"); }
816               ;
817 
818 
819 /* length-stmt */
820 length_stmt   : K_LENGTH string ';' /* XXX length-arg-str */
821 	       { if (ysp_add(_yy, Y_LENGTH, $2, NULL) == NULL) _YYERROR("length_stmt");
822 			   clicon_debug(3,"length-stmt -> LENGTH string ;"); }
823 
824               | K_LENGTH string
825 	      { if (ysp_add_push(_yy, Y_LENGTH, $2, NULL) == NULL) _YYERROR("length_stmt"); }
826 	       '{' length_substmts '}'
827                            { if (ystack_pop(_yy) < 0) _YYERROR("length_stmt");
828 			     clicon_debug(3,"length-stmt -> LENGTH string { length-substmts }"); }
829               ;
830 
831 length_substmts : length_substmts length_substmt
832                       { clicon_debug(3,"length-substmts -> length-substmts length-substmt"); }
833               | length_substmt
834                       { clicon_debug(3,"length-substmts -> length-substmt"); }
835               ;
836 
837 length_substmt : error_message_stmt  { clicon_debug(3,"length-substmt -> error-message-stmt");}
838               | description_stmt     { clicon_debug(3,"length-substmt -> description-stmt"); }
839               | reference_stmt       { clicon_debug(3,"length-substmt -> reference-stmt"); }
840               | unknown_stmt         { clicon_debug(3,"length-substmt -> unknown-stmt");}
841               |                      { clicon_debug(3,"length-substmt -> "); }
842               ;
843 
844 /* Pattern */
845 pattern_stmt  : K_PATTERN string ';'
846 	       { if (ysp_add(_yy, Y_PATTERN, $2, NULL) == NULL) _YYERROR("pattern_stmt");
847 			   clicon_debug(3,"pattern-stmt -> PATTERN string ;"); }
848 
849               | K_PATTERN string
850 	      { if (ysp_add_push(_yy, Y_PATTERN, $2, NULL) == NULL) _YYERROR("pattern_stmt"); }
851 	       '{' pattern_substmts '}'
852                            { if (ystack_pop(_yy) < 0) _YYERROR("pattern_stmt");
853 			     clicon_debug(3,"pattern-stmt -> PATTERN string { pattern-substmts }"); }
854               ;
855 
856 pattern_substmts : pattern_substmts pattern_substmt
857                       { clicon_debug(3,"pattern-substmts -> pattern-substmts pattern-substmt"); }
858               | pattern_substmt
859                       { clicon_debug(3,"pattern-substmts -> pattern-substmt"); }
860               ;
861 
862 pattern_substmt : modifier_stmt    { clicon_debug(3,"pattern-substmt -> modifier-stmt");}
863               | error_message_stmt { clicon_debug(3,"pattern-substmt -> error-message-stmt");}
864               | error_app_tag_stmt { clicon_debug(3,"pattern-substmt -> error-app-tag-stmt");}
865               | description_stmt   { clicon_debug(3,"pattern-substmt -> description-stmt");}
866               | reference_stmt     { clicon_debug(3,"pattern-substmt -> reference-stmt"); }
867               | unknown_stmt       { clicon_debug(3,"pattern-substmt -> unknown-stmt");}
868 
869               |                      { clicon_debug(3,"pattern-substmt -> "); }
870               ;
871 
872 modifier_stmt  : K_MODIFIER string stmtend
873 		{ if (ysp_add(_yy, Y_MODIFIER, $2, NULL)== NULL) _YYERROR("modifier_stmt");
874                             clicon_debug(3,"modifier-stmt -> MODIFIER string"); }
875               ;
876 
877 default_stmt  : K_DEFAULT string stmtend
878 		{ if (ysp_add(_yy, Y_DEFAULT, $2, NULL)== NULL) _YYERROR("default_stmt");
879                             clicon_debug(3,"default-stmt -> DEFAULT string"); }
880               ;
881 
882 /* enum-stmt */
883 enum_stmt     : K_ENUM string ';'
884 	       { if (ysp_add(_yy, Y_ENUM, $2, NULL) == NULL) _YYERROR("enum_stmt");
885 			   clicon_debug(3,"enum-stmt -> ENUM string ;"); }
886               | K_ENUM string
887 	      { if (ysp_add_push(_yy, Y_ENUM, $2, NULL) == NULL) _YYERROR("enum_stmt"); }
888 	       '{' enum_substmts '}'
889                          { if (ystack_pop(_yy) < 0) _YYERROR("enum_stmt");
890 			   clicon_debug(3,"enum-stmt -> ENUM string { enum-substmts }"); }
891               ;
892 
893 enum_substmts : enum_substmts enum_substmt
894                       { clicon_debug(3,"enum-substmts -> enum-substmts enum-substmt"); }
895               | enum_substmt
896                       { clicon_debug(3,"enum-substmts -> enum-substmt"); }
897               ;
898 
899 enum_substmt  : if_feature_stmt      { clicon_debug(3,"enum-substmt -> if-feature-stmt"); }
900               | value_stmt           { clicon_debug(3,"enum-substmt -> value-stmt"); }
901               | status_stmt          { clicon_debug(3,"enum-substmt -> status-stmt"); }
902               | description_stmt     { clicon_debug(3,"enum-substmt -> description-stmt"); }
903               | reference_stmt       { clicon_debug(3,"enum-substmt -> reference-stmt"); }
904               | unknown_stmt         { clicon_debug(3,"enum-substmt -> unknown-stmt");}
905               |                      { clicon_debug(3,"enum-substmt -> "); }
906               ;
907 
908 path_stmt     : K_PATH string stmtend /* XXX: path-arg-str */
909 		{ if (ysp_add(_yy, Y_PATH, $2, NULL)== NULL) _YYERROR("path_stmt");
910                             clicon_debug(3,"path-stmt -> PATH string"); }
911               ;
912 
913 require_instance_stmt : K_REQUIRE_INSTANCE bool_str stmtend
914 		{ if (ysp_add(_yy, Y_REQUIRE_INSTANCE, $2, NULL)== NULL) _YYERROR("require_instance_stmt");
915                             clicon_debug(3,"require-instance-stmt -> REQUIRE-INSTANCE string"); }
916               ;
917 
918 /* bit-stmt */
919 bit_stmt     : K_BIT identifier_str ';'
920 	       { if (ysp_add(_yy, Y_BIT, $2, NULL) == NULL) _YYERROR("bit_stmt");
921 			   clicon_debug(3,"bit-stmt -> BIT string ;"); }
922               | K_BIT identifier_str
923 	      { if (ysp_add_push(_yy, Y_BIT, $2, NULL) == NULL) _YYERROR("bit_stmt"); }
924 	       '{' bit_substmts '}'
925                          { if (ystack_pop(_yy) < 0) _YYERROR("bit_stmt");
926 			   clicon_debug(3,"bit-stmt -> BIT string { bit-substmts }"); }
927               ;
928 
929 bit_substmts : bit_substmts bit_substmt
930                       { clicon_debug(3,"bit-substmts -> bit-substmts bit-substmt"); }
931               | bit_substmt
932                       { clicon_debug(3,"bit-substmts -> bit-substmt"); }
933               ;
934 
935 bit_substmt   : if_feature_stmt      { clicon_debug(3,"bit-substmt -> if-feature-stmt"); }
936               | position_stmt        { clicon_debug(3,"bit-substmt -> positition-stmt"); }
937               | status_stmt          { clicon_debug(3,"bit-substmt -> status-stmt"); }
938               | description_stmt     { clicon_debug(3,"bit-substmt -> description-stmt"); }
939               | reference_stmt       { clicon_debug(3,"bit-substmt -> reference-stmt"); }
940               |                      { clicon_debug(3,"bit-substmt -> "); }
941               ;
942 
943 /* position-stmt = position-keyword position-value-arg-str */
944 position_stmt : K_POSITION integer_value_str stmtend
945 		{ if (ysp_add(_yy, Y_POSITION, $2, NULL) == NULL) _YYERROR("position_stmt");
946                             clicon_debug(3,"position-stmt -> POSITION integer-value"); }
947               ;
948 
949 /* status-stmt = status-keyword sep status-arg-str XXX: current-keyword*/
950 status_stmt   : K_STATUS string stmtend
951 		{ if (ysp_add(_yy, Y_STATUS, $2, NULL) == NULL) _YYERROR("status_stmt");
952                             clicon_debug(3,"status-stmt -> STATUS string"); }
953               ;
954 
955 config_stmt   : K_CONFIG bool_str stmtend
956 		{ if (ysp_add(_yy, Y_CONFIG, $2, NULL) == NULL) _YYERROR("config_stmt");
957                             clicon_debug(3,"config-stmt -> CONFIG config-arg-str"); }
958               ;
959 
960 /* mandatory-stmt = mandatory-keyword mandatory-arg-str */
961 mandatory_stmt : K_MANDATORY bool_str stmtend
962                          { yang_stmt *ys;
963 			     if ((ys = ysp_add(_yy, Y_MANDATORY, $2, NULL))== NULL) _YYERROR("mandatory_stmt");
964 			   clicon_debug(3,"mandatory-stmt -> MANDATORY mandatory-arg-str ;");}
965               ;
966 
967 presence_stmt : K_PRESENCE string stmtend
968                          { yang_stmt *ys;
969 			     if ((ys = ysp_add(_yy, Y_PRESENCE, $2, NULL))== NULL) _YYERROR("presence_stmt");
970 			   clicon_debug(3,"presence-stmt -> PRESENCE string ;");}
971               ;
972 
973 /* ordered-by-stmt = ordered-by-keyword sep ordered-by-arg-str */
974 ordered_by_stmt : K_ORDERED_BY string stmtend
975                          { yang_stmt *ys;
976 			     if ((ys = ysp_add(_yy, Y_ORDERED_BY, $2, NULL))== NULL) _YYERROR("ordered_by_stmt");
977 			   clicon_debug(3,"ordered-by-stmt -> ORDERED-BY ordered-by-arg ;");}
978               ;
979 
980 /* must-stmt */
981 must_stmt     : K_MUST string ';'
982 	       { if (ysp_add(_yy, Y_MUST, $2, NULL) == NULL) _YYERROR("must_stmt");
983 			   clicon_debug(3,"must-stmt -> MUST string ;"); }
984 
985               | K_MUST string
986 	      { if (ysp_add_push(_yy, Y_MUST, $2, NULL) == NULL) _YYERROR("must_stmt"); }
987 	       '{' must_substmts '}'
988                          { if (ystack_pop(_yy) < 0) _YYERROR("must_stmt");
989 			   clicon_debug(3,"must-stmt -> MUST string { must-substmts }"); }
990               ;
991 
992 must_substmts : must_substmts must_substmt
993                       { clicon_debug(3,"must-substmts -> must-substmts must-substmt"); }
994               | must_substmt
995                       { clicon_debug(3,"must-substmts -> must-substmt"); }
996               ;
997 
998 must_substmt  : error_message_stmt   { clicon_debug(3,"must-substmt -> error-message-stmt"); }
999               | error_app_tag_stmt   { clicon_debug(3,"must-substmt -> error-app-tag-stmt"); }
1000               | description_stmt     { clicon_debug(3,"must-substmt -> description-stmt"); }
1001               | reference_stmt       { clicon_debug(3,"must-substmt -> reference-stmt"); }
1002               |                      { clicon_debug(3,"must-substmt -> "); }
1003               ;
1004 
1005 /* error-message-stmt */
1006 error_message_stmt   : K_ERROR_MESSAGE string stmtend
1007 	       { if (ysp_add(_yy, Y_ERROR_MESSAGE, $2, NULL) == NULL) _YYERROR("error_message_stmt");
1008 	          clicon_debug(3,"error-message-stmt -> ERROR-MESSAGE string"); }
1009                ;
1010 
1011 error_app_tag_stmt : K_ERROR_APP_TAG string stmtend
1012 	       { if (ysp_add(_yy, Y_ERROR_MESSAGE, $2, NULL) == NULL) _YYERROR("error_message_stmt");
1013      	          clicon_debug(3,"error-app-tag-stmt -> ERROR-APP-TAG string"); }
1014                ;
1015 
1016 /* min-elements-stmt = min-elements-keyword min-value-arg-str */
1017 min_elements_stmt : K_MIN_ELEMENTS integer_value_str stmtend
1018 		{ if (ysp_add(_yy, Y_MIN_ELEMENTS, $2, NULL)== NULL) _YYERROR("min_elements_stmt");
1019 			   clicon_debug(3,"min-elements-stmt -> MIN-ELEMENTS integer ;");}
1020               ;
1021 
1022 /* max-elements-stmt   = max-elements-keyword ("unbounded"|integer-value)
1023  * XXX cannot use integer-value
1024  */
1025 max_elements_stmt : K_MAX_ELEMENTS string stmtend
1026 		{ if (ysp_add(_yy, Y_MAX_ELEMENTS, $2, NULL)== NULL) _YYERROR("max_elements_stmt");
1027 			   clicon_debug(3,"max-elements-stmt -> MIN-ELEMENTS integer ;");}
1028               ;
1029 
1030 value_stmt   : K_VALUE integer_value_str stmtend
1031 		{ if (ysp_add(_yy, Y_VALUE, $2, NULL) == NULL) _YYERROR("value_stmt");
1032                             clicon_debug(3,"value-stmt -> VALUE integer-value"); }
1033               ;
1034 
1035 /* Grouping */
1036 grouping_stmt  : K_GROUPING identifier_str
1037                     { if (ysp_add_push(_yy, Y_GROUPING, $2, NULL) == NULL) _YYERROR("grouping_stmt"); }
1038 	       '{' grouping_substmts '}'
1039                     { if (ystack_pop(_yy) < 0) _YYERROR("grouping_stmt");
1040 			     clicon_debug(3,"grouping-stmt -> GROUPING id-arg-str { grouping-substmts }"); }
1041               ;
1042 
1043 grouping_substmts : grouping_substmts grouping_substmt
1044                       { clicon_debug(3,"grouping-substmts -> grouping-substmts grouping-substmt"); }
1045               | grouping_substmt
1046                       { clicon_debug(3,"grouping-substmts -> grouping-substmt"); }
1047               ;
1048 
1049 grouping_substmt : status_stmt          { clicon_debug(3,"grouping-substmt -> status-stmt"); }
1050               | description_stmt     { clicon_debug(3,"grouping-substmt -> description-stmt"); }
1051               | reference_stmt       { clicon_debug(3,"grouping-substmt -> reference-stmt"); }
1052               | typedef_stmt         { clicon_debug(3,"grouping-substmt -> typedef-stmt"); }
1053               | grouping_stmt        { clicon_debug(3,"grouping-substmt -> grouping-stmt"); }
1054               | data_def_stmt        { clicon_debug(3,"grouping-substmt -> data-def-stmt"); }
1055               | action_stmt          { clicon_debug(3,"grouping-substmt -> action-stmt"); }
1056               | notification_stmt    { clicon_debug(3,"grouping-substmt -> notification-stmt"); }
1057               | unknown_stmt        { clicon_debug(3,"container-substmt -> unknown-stmt");}
1058               |                      { clicon_debug(3,"grouping-substmt -> "); }
1059               ;
1060 
1061 
1062 /* container */
1063 container_stmt : K_CONTAINER identifier_str ';'
1064 		{ if (ysp_add(_yy, Y_CONTAINER, $2, NULL) == NULL) _YYERROR("container_stmt");
1065                              clicon_debug(3,"container-stmt -> CONTAINER id-arg-str ;");}
1066               | K_CONTAINER identifier_str
1067 	      { if (ysp_add_push(_yy, Y_CONTAINER, $2, NULL) == NULL) _YYERROR("container_stmt"); }
1068                 '{' container_substmts '}'
1069                            { if (ystack_pop(_yy) < 0) _YYERROR("container_stmt");
1070                              clicon_debug(3,"container-stmt -> CONTAINER id-arg-str { container-substmts }");}
1071               ;
1072 
1073 container_substmts : container_substmts container_substmt
1074               | container_substmt
1075               ;
1076 
1077 container_substmt : when_stmt       { clicon_debug(3,"container-substmt -> when-stmt"); }
1078               | if_feature_stmt     { clicon_debug(3,"container-substmt -> if-feature-stmt"); }
1079               | must_stmt           { clicon_debug(3,"container-substmt -> must-stmt"); }
1080               | presence_stmt       { clicon_debug(3,"container-substmt -> presence-stmt"); }
1081               | config_stmt         { clicon_debug(3,"container-substmt -> config-stmt"); }
1082               | status_stmt         { clicon_debug(3,"container-substmt -> status-stmt"); }
1083               | description_stmt    { clicon_debug(3,"container-substmt -> description-stmt");}
1084               | reference_stmt      { clicon_debug(3,"container-substmt -> reference-stmt"); }
1085               | typedef_stmt        { clicon_debug(3,"container-substmt -> typedef-stmt"); }
1086               | grouping_stmt       { clicon_debug(3,"container-substmt -> grouping-stmt"); }
1087               | data_def_stmt       { clicon_debug(3,"container-substmt -> data-def-stmt");}
1088               | action_stmt         { clicon_debug(3,"container-substmt -> action-stmt");}
1089               | notification_stmt   { clicon_debug(3,"container-substmt -> notification-stmt");}
1090               | unknown_stmt        { clicon_debug(3,"container-substmt -> unknown-stmt");}
1091               |                     { clicon_debug(3,"container-substmt ->");}
1092               ;
1093 
1094 leaf_stmt     : K_LEAF identifier_str ';'
1095 		{ if (ysp_add(_yy, Y_LEAF, $2, NULL) == NULL) _YYERROR("leaf_stmt");
1096 			   clicon_debug(3,"leaf-stmt -> LEAF id-arg-str ;");}
1097               | K_LEAF identifier_str
1098 	      { if (ysp_add_push(_yy, Y_LEAF, $2, NULL) == NULL) _YYERROR("leaf_stmt"); }
1099                 '{' leaf_substmts '}'
1100                            { if (ystack_pop(_yy) < 0) _YYERROR("leaf_stmt");
1101                              clicon_debug(3,"leaf-stmt -> LEAF id-arg-str { lead-substmts }");}
1102               ;
1103 
1104 leaf_substmts : leaf_substmts leaf_substmt
1105               | leaf_substmt
1106               ;
1107 
1108 leaf_substmt  : when_stmt            { clicon_debug(3,"leaf-substmt -> when-stmt"); }
1109               | if_feature_stmt      { clicon_debug(3,"leaf-substmt -> if-feature-stmt"); }
1110               | type_stmt            { clicon_debug(3,"leaf-substmt -> type-stmt"); }
1111               | units_stmt           { clicon_debug(3,"leaf-substmt -> units-stmt"); }
1112               | must_stmt            { clicon_debug(3,"leaf-substmt -> must-stmt"); }
1113               | default_stmt         { clicon_debug(3,"leaf-substmt -> default-stmt"); }
1114               | config_stmt          { clicon_debug(3,"leaf-substmt -> config-stmt"); }
1115               | mandatory_stmt       { clicon_debug(3,"leaf-substmt -> mandatory-stmt"); }
1116               | status_stmt          { clicon_debug(3,"leaf-substmt -> status-stmt"); }
1117               | description_stmt     { clicon_debug(3,"leaf-substmt -> description-stmt"); }
1118               | reference_stmt       { clicon_debug(3,"leaf-substmt -> reference-stmt"); }
1119               | unknown_stmt         { clicon_debug(3,"leaf-substmt -> unknown-stmt");}
1120               |                      { clicon_debug(3,"leaf-substmt ->"); }
1121               ;
1122 
1123 /* leaf-list */
1124 leaf_list_stmt : K_LEAF_LIST identifier_str ';'
1125 		{ if (ysp_add(_yy, Y_LEAF_LIST, $2, NULL) == NULL) _YYERROR("leaf_list_stmt");
1126 			   clicon_debug(3,"leaf-list-stmt -> LEAF id-arg-str ;");}
1127               | K_LEAF_LIST identifier_str
1128 	      { if (ysp_add_push(_yy, Y_LEAF_LIST, $2, NULL) == NULL) _YYERROR("leaf_list_stmt"); }
1129                 '{' leaf_list_substmts '}'
1130                            { if (ystack_pop(_yy) < 0) _YYERROR("leaf_list_stmt");
1131                              clicon_debug(3,"leaf-list-stmt -> LEAF-LIST id-arg-str { lead-substmts }");}
1132               ;
1133 
1134 leaf_list_substmts : leaf_list_substmts leaf_list_substmt
1135               | leaf_list_substmt
1136               ;
1137 
1138 leaf_list_substmt : when_stmt        { clicon_debug(3,"leaf-list-substmt -> when-stmt"); }
1139               | if_feature_stmt      { clicon_debug(3,"leaf-list-substmt -> if-feature-stmt"); }
1140               | type_stmt            { clicon_debug(3,"leaf-list-substmt -> type-stmt"); }
1141               | units_stmt           { clicon_debug(3,"leaf-list-substmt -> units-stmt"); }
1142               | must_stmt            { clicon_debug(3,"leaf-list-substmt -> must-stmt"); }
1143               | default_stmt         { clicon_debug(3,"leaf-list-substmt -> default-stmt"); }
1144               | config_stmt          { clicon_debug(3,"leaf-list-substmt -> config-stmt"); }
1145               | min_elements_stmt    { clicon_debug(3,"leaf-list-substmt -> min-elements-stmt"); }
1146               | max_elements_stmt    { clicon_debug(3,"leaf-list-substmt -> max-elements-stmt"); }
1147               | ordered_by_stmt      { clicon_debug(3,"leaf-list-substmt -> ordered-by-stmt"); }
1148               | status_stmt          { clicon_debug(3,"leaf-list-substmt -> status-stmt"); }
1149               | description_stmt     { clicon_debug(3,"leaf-list-substmt -> description-stmt"); }
1150               | reference_stmt       { clicon_debug(3,"leaf-list-substmt -> reference-stmt"); }
1151               | unknown_stmt         { clicon_debug(3,"leaf-list-substmt -> unknown-stmt");}
1152               |                      { clicon_debug(3,"leaf-list-stmt ->"); }
1153               ;
1154 
1155 list_stmt     : K_LIST identifier_str ';'
1156 		{ if (ysp_add(_yy, Y_LIST, $2, NULL) == NULL) _YYERROR("list_stmt");
1157 			   clicon_debug(3,"list-stmt -> LIST id-arg-str ;"); }
1158               | K_LIST identifier_str
1159 	      { if (ysp_add_push(_yy, Y_LIST, $2, NULL) == NULL) _YYERROR("list_stmt"); }
1160 	       '{' list_substmts '}'
1161                            { if (ystack_pop(_yy) < 0) _YYERROR("list_stmt");
1162 			     clicon_debug(3,"list-stmt -> LIST id-arg-str { list-substmts }"); }
1163               ;
1164 
1165 list_substmts : list_substmts list_substmt
1166                       { clicon_debug(3,"list-substmts -> list-substmts list-substmt"); }
1167               | list_substmt
1168                       { clicon_debug(3,"list-substmts -> list-substmt"); }
1169               ;
1170 
1171 list_substmt  : when_stmt            { clicon_debug(3,"list-substmt -> when-stmt"); }
1172               | if_feature_stmt      { clicon_debug(3,"list-substmt -> if-feature-stmt"); }
1173               | must_stmt            { clicon_debug(3,"list-substmt -> must-stmt"); }
1174               | key_stmt             { clicon_debug(3,"list-substmt -> key-stmt"); }
1175               | unique_stmt          { clicon_debug(3,"list-substmt -> unique-stmt"); }
1176               | config_stmt          { clicon_debug(3,"list-substmt -> config-stmt"); }
1177               | min_elements_stmt    { clicon_debug(3,"list-substmt -> min-elements-stmt"); }
1178               | max_elements_stmt    { clicon_debug(3,"list-substmt -> max-elements-stmt"); }
1179               | ordered_by_stmt      { clicon_debug(3,"list-substmt -> ordered-by-stmt"); }
1180               | status_stmt          { clicon_debug(3,"list-substmt -> status-stmt"); }
1181               | description_stmt     { clicon_debug(3,"list-substmt -> description-stmt"); }
1182               | reference_stmt       { clicon_debug(3,"list-substmt -> reference-stmt"); }
1183               | typedef_stmt         { clicon_debug(3,"list-substmt -> typedef-stmt"); }
1184               | grouping_stmt        { clicon_debug(3,"list-substmt -> grouping-stmt"); }
1185               | data_def_stmt        { clicon_debug(3,"list-substmt -> data-def-stmt"); }
1186               | action_stmt          { clicon_debug(3,"list-substmt -> action-stmt"); }
1187               | notification_stmt    { clicon_debug(3,"list-substmt -> notification-stmt"); }
1188               | unknown_stmt         { clicon_debug(3,"list-substmt -> unknown-stmt");}
1189               |                      { clicon_debug(3,"list-substmt -> "); }
1190               ;
1191 
1192 /* key-stmt = key-keyword sep key-arg-str */
1193 key_stmt      : K_KEY string stmtend
1194 		{ if (ysp_add(_yy, Y_KEY, $2, NULL)== NULL) _YYERROR("key_stmt");
1195 			   clicon_debug(3,"key-stmt -> KEY id-arg-str ;");}
1196               ;
1197 
1198 /* unique-stmt = unique-keyword unique-arg-str */
1199 unique_stmt   : K_UNIQUE string stmtend
1200 		{ if (ysp_add(_yy, Y_UNIQUE, $2, NULL)== NULL) _YYERROR("unique_stmt");
1201 			   clicon_debug(3,"key-stmt -> KEY id-arg-str ;");}
1202               ;
1203 
1204 /* choice */
1205 choice_stmt   : K_CHOICE identifier_str ';'
1206 	       { if (ysp_add(_yy, Y_CHOICE, $2, NULL) == NULL) _YYERROR("choice_stmt");
1207 			   clicon_debug(3,"choice-stmt -> CHOICE id-arg-str ;"); }
1208               | K_CHOICE identifier_str
1209 	      { if (ysp_add_push(_yy, Y_CHOICE, $2, NULL) == NULL) _YYERROR("choice_stmt"); }
1210 	       '{' choice_substmts '}'
1211                            { if (ystack_pop(_yy) < 0) _YYERROR("choice_stmt");
1212 			     clicon_debug(3,"choice-stmt -> CHOICE id-arg-str { choice-substmts }"); }
1213               ;
1214 
1215 choice_substmts : choice_substmts choice_substmt
1216                       { clicon_debug(3,"choice-substmts -> choice-substmts choice-substmt"); }
1217               | choice_substmt
1218                       { clicon_debug(3,"choice-substmts -> choice-substmt"); }
1219               ;
1220 
1221 choice_substmt : when_stmt           { clicon_debug(3,"choice-substmt -> when-stmt"); }
1222               | if_feature_stmt      { clicon_debug(3,"choice-substmt -> if-feature-stmt"); }
1223               | default_stmt         { clicon_debug(3,"choice-substmt -> default-stmt"); }
1224               | config_stmt          { clicon_debug(3,"choice-substmt -> config-stmt"); }
1225               | mandatory_stmt       { clicon_debug(3,"choice-substmt -> mandatory-stmt"); }
1226               | status_stmt          { clicon_debug(3,"choice-substmt -> status-stmt"); }
1227               | description_stmt     { clicon_debug(3,"choice-substmt -> description-stmt"); }
1228               | reference_stmt       { clicon_debug(3,"choice-substmt -> reference-stmt"); }
1229               | short_case_stmt      { clicon_debug(3,"choice-substmt -> short-case-stmt");}
1230               | case_stmt            { clicon_debug(3,"choice-substmt -> case-stmt");}
1231               | unknown_stmt         { clicon_debug(3,"choice-substmt -> unknown-stmt");}
1232               |                      { clicon_debug(3,"choice-substmt -> "); }
1233               ;
1234 
1235 /* case */
1236 case_stmt   : K_CASE identifier_str ';'
1237 	       { if (ysp_add(_yy, Y_CASE, $2, NULL) == NULL) _YYERROR("case_stmt");
1238 			   clicon_debug(3,"case-stmt -> CASE id-arg-str ;"); }
1239               | K_CASE identifier_str
1240 	      { if (ysp_add_push(_yy, Y_CASE, $2, NULL) == NULL) _YYERROR("case_stmt"); }
1241 	       '{' case_substmts '}'
1242                            { if (ystack_pop(_yy) < 0) _YYERROR("case_stmt");
1243 			     clicon_debug(3,"case-stmt -> CASE id-arg-str { case-substmts }"); }
1244               ;
1245 
1246 case_substmts : case_substmts case_substmt
1247                       { clicon_debug(3,"case-substmts -> case-substmts case-substmt"); }
1248               | case_substmt
1249                       { clicon_debug(3,"case-substmts -> case-substmt"); }
1250               ;
1251 
1252 case_substmt  : when_stmt            { clicon_debug(3,"case-substmt -> when-stmt"); }
1253               | if_feature_stmt      { clicon_debug(3,"case-substmt -> if-feature-stmt"); }
1254               | status_stmt          { clicon_debug(3,"case-substmt -> status-stmt"); }
1255               | description_stmt     { clicon_debug(3,"case-substmt -> description-stmt"); }
1256               | reference_stmt       { clicon_debug(3,"case-substmt -> reference-stmt"); }
1257               | data_def_stmt        { clicon_debug(3,"case-substmt -> data-def-stmt");}
1258               | unknown_stmt         { clicon_debug(3,"case-substmt -> unknown-stmt");}
1259               |                      { clicon_debug(3,"case-substmt -> "); }
1260               ;
1261 
1262 anydata_stmt   : K_ANYDATA identifier_str ';'
1263 	       { if (ysp_add(_yy, Y_ANYDATA, $2, NULL) == NULL) _YYERROR("anydata_stmt");
1264 			   clicon_debug(3,"anydata-stmt -> ANYDATA id-arg-str ;"); }
1265               | K_ANYDATA identifier_str
1266 	      { if (ysp_add_push(_yy, Y_ANYDATA, $2, NULL) == NULL) _YYERROR("anydata_stmt"); }
1267 	       '{' anyxml_substmts '}'
1268                            { if (ystack_pop(_yy) < 0) _YYERROR("anydata_stmt");
1269 			     clicon_debug(3,"anydata-stmt -> ANYDATA id-arg-str { anyxml-substmts }"); }
1270               ;
1271 
1272 /* anyxml */
1273 anyxml_stmt   : K_ANYXML identifier_str ';'
1274 	       { if (ysp_add(_yy, Y_ANYXML, $2, NULL) == NULL) _YYERROR("anyxml_stmt");
1275 			   clicon_debug(3,"anyxml-stmt -> ANYXML id-arg-str ;"); }
1276               | K_ANYXML identifier_str
1277 	      { if (ysp_add_push(_yy, Y_ANYXML, $2, NULL) == NULL) _YYERROR("anyxml_stmt"); }
1278 	       '{' anyxml_substmts '}'
1279                            { if (ystack_pop(_yy) < 0) _YYERROR("anyxml_stmt");
1280 			     clicon_debug(3,"anyxml-stmt -> ANYXML id-arg-str { anyxml-substmts }"); }
1281               ;
1282 
1283 anyxml_substmts : anyxml_substmts anyxml_substmt
1284                       { clicon_debug(3,"anyxml-substmts -> anyxml-substmts anyxml-substmt"); }
1285               | anyxml_substmt
1286                       { clicon_debug(3,"anyxml-substmts -> anyxml-substmt"); }
1287               ;
1288 
1289 anyxml_substmt  : when_stmt          { clicon_debug(3,"anyxml-substmt -> when-stmt"); }
1290               | if_feature_stmt      { clicon_debug(3,"anyxml-substmt -> if-feature-stmt"); }
1291               | must_stmt            { clicon_debug(3,"anyxml-substmt -> must-stmt"); }
1292               | config_stmt          { clicon_debug(3,"anyxml-substmt -> config-stmt"); }
1293               | mandatory_stmt       { clicon_debug(3,"anyxml-substmt -> mandatory-stmt"); }
1294               | status_stmt          { clicon_debug(3,"anyxml-substmt -> status-stmt"); }
1295               | description_stmt     { clicon_debug(3,"anyxml-substmt -> description-stmt"); }
1296               | reference_stmt       { clicon_debug(3,"anyxml-substmt -> reference-stmt"); }
1297               | ustring ':' ustring ';' { free($1); free($3); clicon_debug(3,"anyxml-substmt -> anyxml extension"); }
1298               | unknown_stmt         { clicon_debug(3,"anyxml-substmt -> unknown-stmt");}
1299               ;
1300 
1301 /* uses-stmt = uses-keyword identifier-ref-arg-str */
1302 uses_stmt     : K_USES identifier_ref_str ';'
1303 	       { if (ysp_add(_yy, Y_USES, $2, NULL) == NULL) _YYERROR("uses_stmt");
1304 			   clicon_debug(3,"uses-stmt -> USES id-arg-str ;"); }
1305               | K_USES identifier_ref_str
1306 	      { if (ysp_add_push(_yy, Y_USES, $2, NULL) == NULL) _YYERROR("uses_stmt"); }
1307 	       '{' uses_substmts '}'
1308                            { if (ystack_pop(_yy) < 0) _YYERROR("uses_stmt");
1309 			     clicon_debug(3,"uses-stmt -> USES id-arg-str { uses-substmts }"); }
1310               ;
1311 
1312 uses_substmts : uses_substmts uses_substmt
1313                       { clicon_debug(3,"uses-substmts -> uses-substmts uses-substmt"); }
1314               | uses_substmt
1315                       { clicon_debug(3,"uses-substmts -> uses-substmt"); }
1316               ;
1317 
1318 uses_substmt  : when_stmt            { clicon_debug(3,"uses-substmt -> when-stmt"); }
1319               | if_feature_stmt      { clicon_debug(3,"uses-substmt -> if-feature-stmt"); }
1320               | status_stmt          { clicon_debug(3,"uses-substmt -> status-stmt"); }
1321               | description_stmt     { clicon_debug(3,"uses-substmt -> description-stmt"); }
1322               | reference_stmt       { clicon_debug(3,"uses-substmt -> reference-stmt"); }
1323               | refine_stmt          { clicon_debug(3,"uses-substmt -> refine-stmt"); }
1324               | uses_augment_stmt    { clicon_debug(3,"uses-substmt -> uses-augment-stmt"); }
1325               | unknown_stmt         { clicon_debug(3,"uses-substmt -> unknown-stmt");}
1326               |                      { clicon_debug(3,"uses-substmt -> "); }
1327               ;
1328 
1329 /* refine-stmt = refine-keyword sep refine-arg-str */
1330 refine_stmt   : K_REFINE desc_schema_nodeid_strs ';'
1331 	       { if (ysp_add(_yy, Y_REFINE, $2, NULL) == NULL) _YYERROR("refine_stmt");
1332 			   clicon_debug(3,"refine-stmt -> REFINE id-arg-str ;"); }
1333               | K_REFINE desc_schema_nodeid_strs
1334 	      { if (ysp_add_push(_yy, Y_REFINE, $2, NULL) == NULL) _YYERROR("refine_stmt"); }
1335 	       '{' refine_substmts '}'
1336                            { if (ystack_pop(_yy) < 0) _YYERROR("refine_stmt");
1337 			     clicon_debug(3,"refine-stmt -> REFINE id-arg-str { refine-substmts }"); }
1338               ;
1339 
1340 refine_substmts : refine_substmts refine_substmt
1341                       { clicon_debug(3,"refine-substmts -> refine-substmts refine-substmt"); }
1342               | refine_substmt
1343                       { clicon_debug(3,"refine-substmts -> refine-substmt"); }
1344               ;
1345 
1346 refine_substmt  : if_feature_stmt     { clicon_debug(3,"refine-substmt -> if-feature-stmt"); }
1347               | must_stmt     { clicon_debug(3,"refine-substmt -> must-stmt"); }
1348               | presence_stmt  { clicon_debug(3,"refine-substmt -> presence-stmt"); }
1349               | default_stmt    { clicon_debug(3,"refine-substmt -> default-stmt"); }
1350               | config_stmt    { clicon_debug(3,"refine-substmt -> config-stmt"); }
1351               | mandatory_stmt  { clicon_debug(3,"refine-substmt -> mandatory-stmt"); }
1352               | min_elements_stmt  { clicon_debug(3,"refine-substmt -> min-elements-stmt"); }
1353               | max_elements_stmt  { clicon_debug(3,"refine-substmt -> max-elements-stmt"); }
1354               | description_stmt  { clicon_debug(3,"refine-substmt -> description-stmt"); }
1355               | reference_stmt  { clicon_debug(3,"refine-substmt -> reference-stmt"); }
1356               | unknown_stmt    { clicon_debug(3,"refine-substmt -> unknown-stmt");}
1357               |                 { clicon_debug(3,"refine-substmt -> "); }
1358               ;
1359 
1360 /* uses-augment-stmt = augment-keyword augment-arg-str
1361 uses_augment_stmt : K_AUGMENT desc_schema_nodeid_strs
1362 */
1363 uses_augment_stmt : K_AUGMENT string
1364                       { if (ysp_add_push(_yy, Y_AUGMENT, $2, NULL) == NULL) _YYERROR("uses_augment_stmt"); }
1365                     '{' augment_substmts '}'
1366                       { if (ystack_pop(_yy) < 0) _YYERROR("uses_augment_stmt");
1367 			     clicon_debug(3,"uses-augment-stmt -> AUGMENT desc-schema-node-str { augment-substmts }"); }
1368 
1369 
1370 /* augment-stmt = augment-keyword sep augment-arg-str
1371  * XXX abs-schema-nodeid-str is too difficult, it needs the + semantics
1372 augment_stmt   : K_AUGMENT abs_schema_nodeid_strs
1373  */
1374 augment_stmt   : K_AUGMENT string
1375                    { if (ysp_add_push(_yy, Y_AUGMENT, $2, NULL) == NULL) _YYERROR("augment_stmt"); }
1376 	       '{' augment_substmts '}'
1377                    { if (ystack_pop(_yy) < 0) _YYERROR("augment_stmt");
1378 			     clicon_debug(3,"augment-stmt -> AUGMENT abs-schema-node-str { augment-substmts }"); }
1379               ;
1380 
1381 augment_substmts : augment_substmts augment_substmt
1382                       { clicon_debug(3,"augment-substmts -> augment-substmts augment-substmt"); }
1383               | augment_substmt
1384                       { clicon_debug(3,"augment-substmts -> augment-substmt"); }
1385               ;
1386 
1387 augment_substmt : when_stmt          { clicon_debug(3,"augment-substmt -> when-stmt"); }
1388               | if_feature_stmt      { clicon_debug(3,"augment-substmt -> if-feature-stmt"); }
1389               | status_stmt          { clicon_debug(3,"augment-substmt -> status-stmt"); }
1390               | description_stmt     { clicon_debug(3,"augment-substmt -> description-stmt"); }
1391               | reference_stmt       { clicon_debug(3,"augment-substmt -> reference-stmt"); }
1392               | data_def_stmt        { clicon_debug(3,"augment-substmt -> data-def-stmt"); }
1393               | case_stmt            { clicon_debug(3,"augment-substmt -> case-stmt");}
1394               | action_stmt          { clicon_debug(3,"augment-substmt -> action-stmt");}
1395               | notification_stmt    { clicon_debug(3,"augment-substmt -> notification-stmt");}
1396               |                      { clicon_debug(3,"augment-substmt -> "); }
1397               ;
1398 
1399 /* when */
1400 when_stmt   : K_WHEN string ';'
1401 	       { if (ysp_add(_yy, Y_WHEN, $2, NULL) == NULL) _YYERROR("when_stmt");
1402 			   clicon_debug(3,"when-stmt -> WHEN string ;"); }
1403             | K_WHEN string
1404 	    { if (ysp_add_push(_yy, Y_WHEN, $2, NULL) == NULL) _YYERROR("when_stmt"); }
1405 	       '{' when_substmts '}'
1406                            { if (ystack_pop(_yy) < 0) _YYERROR("when_stmt");
1407 			     clicon_debug(3,"when-stmt -> WHEN string { when-substmts }"); }
1408               ;
1409 
1410 when_substmts : when_substmts when_substmt
1411                       { clicon_debug(3,"when-substmts -> when-substmts when-substmt"); }
1412               | when_substmt
1413                       { clicon_debug(3,"when-substmts -> when-substmt"); }
1414               ;
1415 
1416 when_substmt  : description_stmt { clicon_debug(3,"when-substmt -> description-stmt"); }
1417               | reference_stmt   { clicon_debug(3,"when-substmt -> reference-stmt"); }
1418               |                  { clicon_debug(3,"when-substmt -> "); }
1419               ;
1420 
1421 /* rpc */
1422 rpc_stmt   : K_RPC identifier_str ';'
1423 	       { if (ysp_add(_yy, Y_RPC, $2, NULL) == NULL) _YYERROR("rpc_stmt");
1424 			   clicon_debug(3,"rpc-stmt -> RPC id-arg-str ;"); }
1425            | K_RPC identifier_str
1426 	   { if (ysp_add_push(_yy, Y_RPC, $2, NULL) == NULL) _YYERROR("rpc_stmt"); }
1427 	     '{' rpc_substmts '}'
1428                            { if (ystack_pop(_yy) < 0) _YYERROR("rpc_stmt");
1429 			     clicon_debug(3,"rpc-stmt -> RPC id-arg-str { rpc-substmts }"); }
1430               ;
1431 
1432 rpc_substmts : rpc_substmts rpc_substmt
1433                       { clicon_debug(3,"rpc-substmts -> rpc-substmts rpc-substmt"); }
1434               | rpc_substmt
1435                       { clicon_debug(3,"rpc-substmts -> rpc-substmt"); }
1436               ;
1437 
1438 rpc_substmt   : if_feature_stmt  { clicon_debug(3,"rpc-substmt -> if-feature-stmt"); }
1439               | status_stmt      { clicon_debug(3,"rpc-substmt -> status-stmt"); }
1440               | description_stmt { clicon_debug(3,"rpc-substmt -> description-stmt"); }
1441               | reference_stmt   { clicon_debug(3,"rpc-substmt -> reference-stmt"); }
1442               | typedef_stmt     { clicon_debug(3,"rpc-substmt -> typedef-stmt"); }
1443               | grouping_stmt    { clicon_debug(3,"rpc-substmt -> grouping-stmt"); }
1444               | input_stmt       { clicon_debug(3,"rpc-substmt -> input-stmt"); }
1445               | output_stmt      { clicon_debug(3,"rpc-substmt -> output-stmt"); }
1446               | unknown_stmt     { clicon_debug(3,"rpc-substmt -> unknown-stmt");}
1447               |                  { clicon_debug(3,"rpc-substmt -> "); }
1448               ;
1449 
1450 /* action */
1451 action_stmt   : K_ACTION identifier_str ';'
1452 	       { if (ysp_add(_yy, Y_ACTION, $2, NULL) == NULL) _YYERROR("action_stmt");
1453 			   clicon_debug(3,"action-stmt -> ACTION id-arg-str ;"); }
1454               | K_ACTION identifier_str
1455 	      { if (ysp_add_push(_yy, Y_ACTION, $2, NULL) == NULL) _YYERROR("action_stmt"); }
1456 	       '{' rpc_substmts '}'
1457                            { if (ystack_pop(_yy) < 0) _YYERROR("action_stmt");
1458 			     clicon_debug(3,"action-stmt -> ACTION id-arg-str { rpc-substmts }"); }
1459               ;
1460 
1461 /* notification */
1462 notification_stmt : K_NOTIFICATION identifier_str ';'
1463 	                { if (ysp_add(_yy, Y_NOTIFICATION, $2, NULL) == NULL) _YYERROR("notification_stmt");
1464 			   clicon_debug(3,"notification-stmt -> NOTIFICATION id-arg-str ;"); }
1465                   | K_NOTIFICATION identifier_str
1466 		  { if (ysp_add_push(_yy, Y_NOTIFICATION, $2, NULL) == NULL) _YYERROR("notification_stmt"); }
1467 	            '{' notification_substmts '}'
1468                         { if (ystack_pop(_yy) < 0) _YYERROR("notification_stmt");
1469 			     clicon_debug(3,"notification-stmt -> NOTIFICATION id-arg-str { notification-substmts }"); }
1470                   ;
1471 
1472 notification_substmts : notification_substmts notification_substmt
1473                          { clicon_debug(3,"notification-substmts -> notification-substmts notification-substmt"); }
1474                       | notification_substmt
1475                          { clicon_debug(3,"notification-substmts -> notification-substmt"); }
1476                       ;
1477 
1478 notification_substmt : if_feature_stmt  { clicon_debug(3,"notification-substmt -> if-feature-stmt"); }
1479                      | must_stmt        { clicon_debug(3,"notification-substmt -> must-stmt"); }
1480                      | status_stmt      { clicon_debug(3,"notification-substmt -> status-stmt"); }
1481                      | description_stmt { clicon_debug(3,"notification-substmt -> description-stmt"); }
1482                      | reference_stmt   { clicon_debug(3,"notification-substmt -> reference-stmt"); }
1483                      | typedef_stmt     { clicon_debug(3,"notification-substmt -> typedef-stmt"); }
1484                      | grouping_stmt    { clicon_debug(3,"notification-substmt -> grouping-stmt"); }
1485                      | data_def_stmt    { clicon_debug(3,"notification-substmt -> data-def-stmt"); }
1486                      | unknown_stmt     { clicon_debug(3,"notification-substmt -> unknown-stmt");}
1487                      |                  { clicon_debug(3,"notification-substmt -> "); }
1488                      ;
1489 
1490 /* deviation /oc-sys:system/oc-sys:config/oc-sys:hostname {
1491 	     deviate not-supported;
1492       }
1493  * XXX abs-schema-nodeid-str is too difficult, it needs the + semantics
1494 
1495 */
1496 deviation_stmt : K_DEVIATION string
1497                         { if (ysp_add_push(_yy, Y_DEVIATION, $2, NULL) == NULL) _YYERROR("deviation_stmt"); }
1498 	            '{' deviation_substmts '}'
1499                         { if (ystack_pop(_yy) < 0) _YYERROR("deviation_stmt");
1500 			     clicon_debug(3,"deviation-stmt -> DEVIATION id-arg-str { notification-substmts }"); }
1501                ;
1502 
1503 deviation_substmts : deviation_substmts deviation_substmt
1504                          { clicon_debug(3,"deviation-substmts -> deviation-substmts deviation-substmt"); }
1505                       | deviation_substmt
1506                          { clicon_debug(3,"deviation-substmts -> deviation-substmt"); }
1507                       ;
1508 
1509 deviation_substmt : description_stmt  { clicon_debug(3,"deviation-substmt -> description-stmt"); }
1510                   | reference_stmt  { clicon_debug(3,"deviation-substmt -> reference-stmt"); }
1511                   | deviate_stmt  { clicon_debug(3,"deviation-substmt -> deviate-stmt"); }
1512 		  ;
1513 
1514 /* RFC7950 differentiates between deviate-not-supported, deviate-add,
1515  * deviate-replave, and deviate-delete. Here all are bundled into a single
1516  * deviate rule. For now, until "deviate" gets supported.
1517  */
1518 deviate_stmt      : K_DEVIATE string ';'
1519 	                { if (ysp_add(_yy, Y_DEVIATE, $2, NULL) == NULL) _YYERROR("notification_stmt");
1520     			   clicon_debug(3,"deviate-not-supported-stmt -> DEVIATE string ;"); }
1521                   | K_DEVIATE string
1522 		  { if (ysp_add_push(_yy, Y_DEVIATE, $2, NULL) == NULL) _YYERROR("deviate_stmt"); }
1523 	            '{' deviate_substmts '}'
1524                         { if (ystack_pop(_yy) < 0) _YYERROR("deviate_stmt");
1525 			     clicon_debug(3,"deviate-stmt -> DEVIATE string { deviate-substmts }"); }
1526                    ;
1527 
1528 /* RFC7950 differentiates between deviate-not-supported, deviate-add,
1529  * deviate-replave, and deviate-delete. Here all are bundled into a single
1530  * deviate-substmt rule. For now, until "deviate" gets supported.
1531  */
1532 deviate_substmts     : deviate_substmts deviate_substmt
1533                          { clicon_debug(3,"deviate-substmts -> deviate-substmts deviate-substmt"); }
1534                      | deviate_substmt
1535                          { clicon_debug(3,"deviate-substmts -> deviate-substmt"); }
1536                      ;
1537 /* Bundled */
1538 deviate_substmt : type_stmt         { clicon_debug(3,"deviate-substmt -> type-stmt"); }
1539                 | units_stmt        { clicon_debug(3,"deviate-substmt -> units-stmt"); }
1540                 | must_stmt         { clicon_debug(3,"deviate-substmt -> must-stmt"); }
1541                 | unique_stmt       { clicon_debug(3,"deviate-substmt -> unique-stmt"); }
1542                 | default_stmt      { clicon_debug(3,"deviate-substmt -> default-stmt"); }
1543                 | config_stmt       { clicon_debug(3,"deviate-substmt -> config-stmt"); }
1544                 | mandatory_stmt    { clicon_debug(3,"deviate-substmt -> mandatory-stmt"); }
1545                 | min_elements_stmt { clicon_debug(3,"deviate-substmt -> min-elements-stmt"); }
1546                 | max_elements_stmt { clicon_debug(3,"deviate-substmt -> max-elements-stmt"); }
1547                 |                   { clicon_debug(3,"deviate-substmt -> "); }
1548                 ;
1549 
1550 
1551 /* Represents the usage of an extension
1552    unknown-statement   = prefix ":" identifier [sep string] optsep
1553                          (";" /
1554                           "{" optsep
1555                               *((yang-stmt / unknown-statement) optsep)
1556                            "}") stmt
1557  *
1558  */
1559 unknown_stmt  : ustring ':' ustring optsep ';'
1560                  { char *id; if ((id=string_del_join($1, ":", $3)) == NULL) _YYERROR("unknown_stmt");
1561 		   if (ysp_add(_yy, Y_UNKNOWN, id, NULL) == NULL) _YYERROR("unknown_stmt");
1562 		   clicon_debug(3,"unknown-stmt -> ustring : ustring");
1563 	       }
1564               | ustring ':' ustring SEP string optsep ';'
1565 	        { char *id; if ((id=string_del_join($1, ":", $3)) == NULL) _YYERROR("unknown_stmt");
1566 		   if (ysp_add(_yy, Y_UNKNOWN, id, $5) == NULL){ _YYERROR("unknwon_stmt"); }
1567 		   clicon_debug(3,"unknown-stmt -> ustring : ustring string");
1568 	       }
1569               | ustring ':' ustring optsep
1570                  { char *id; if ((id=string_del_join($1, ":", $3)) == NULL) _YYERROR("unknown_stmt");
1571 		     if (ysp_add_push(_yy, Y_UNKNOWN, id, NULL) == NULL) _YYERROR("unknown_stmt"); }
1572 	         '{' yang_stmts '}'
1573 	               { if (ystack_pop(_yy) < 0) _YYERROR("unknown_stmt");
1574 			 clicon_debug(3,"unknown-stmt -> ustring : ustring { yang-stmts }"); }
1575               | ustring ':' ustring SEP string optsep
1576  	         { char *id; if ((id=string_del_join($1, ":", $3)) == NULL) _YYERROR("unknown_stmt");
1577 		     if (ysp_add_push(_yy, Y_UNKNOWN, id, $5) == NULL) _YYERROR("unknown_stmt"); }
1578 	         '{' yang_stmts '}'
1579 	               { if (ystack_pop(_yy) < 0) _YYERROR("unknown_stmt");
1580 			 clicon_debug(3,"unknown-stmt -> ustring : ustring string { yang-stmts }"); }
1581 	      ;
1582 
1583 yang_stmts    : yang_stmts yang_stmt { clicon_debug(3,"yang-stmts -> yang-stmts yang-stmt"); }
1584               | yang_stmt            { clicon_debug(3,"yang-stmts -> yang-stmt");}
1585               ;
1586 
1587 yang_stmt     : action_stmt          { clicon_debug(3,"yang-stmt -> action-stmt");}
1588               | anydata_stmt         { clicon_debug(3,"yang-stmt -> anydata-stmt");}
1589               | anyxml_stmt          { clicon_debug(3,"yang-stmt -> anyxml-stmt");}
1590               | argument_stmt        { clicon_debug(3,"yang-stmt -> argument-stmt");}
1591               | augment_stmt         { clicon_debug(3,"yang-stmt -> augment-stmt");}
1592               | base_stmt            { clicon_debug(3,"yang-stmt -> base-stmt");}
1593               | bit_stmt             { clicon_debug(3,"yang-stmt -> bit-stmt");}
1594               | case_stmt            { clicon_debug(3,"yang-stmt -> case-stmt");}
1595               | choice_stmt          { clicon_debug(3,"yang-stmt -> choice-stmt");}
1596               | config_stmt          { clicon_debug(3,"yang-stmt -> config-stmt");}
1597               | contact_stmt         { clicon_debug(3,"yang-stmt -> contact-stmt");}
1598               | container_stmt       { clicon_debug(3,"yang-stmt -> container-stmt");}
1599               | default_stmt         { clicon_debug(3,"yang-stmt -> default-stmt");}
1600               | description_stmt     { clicon_debug(3,"yang-stmt -> description-stmt");}
1601               | deviate_stmt         { clicon_debug(3,"yang-stmt -> deviate-stmt");}
1602 /* deviate is not yet implemented, the above may be replaced by the following lines
1603               | deviate_add_stmt     { clicon_debug(3,"yang-stmt -> deviate-add-stmt");}
1604               | deviate_delete_stmt  { clicon_debug(3,"yang-stmt -> deviate-add-stmt");}
1605               | deviate_replace_stmt { clicon_debug(3,"yang-stmt -> deviate-add-stmt");}
1606 */
1607               | deviation_stmt       { clicon_debug(3,"yang-stmt -> deviation-stmt");}
1608               | enum_stmt            { clicon_debug(3,"yang-stmt -> enum-stmt");}
1609               | error_app_tag_stmt   { clicon_debug(3,"yang-stmt -> error-app-tag-stmt");}
1610               | error_message_stmt   { clicon_debug(3,"yang-stmt -> error-message-stmt");}
1611               | extension_stmt       { clicon_debug(3,"yang-stmt -> extension-stmt");}
1612               | feature_stmt         { clicon_debug(3,"yang-stmt -> feature-stmt");}
1613               | fraction_digits_stmt { clicon_debug(3,"yang-stmt -> fraction-digits-stmt");}
1614               | grouping_stmt        { clicon_debug(3,"yang-stmt -> grouping-stmt");}
1615               | identity_stmt        { clicon_debug(3,"yang-stmt -> identity-stmt");}
1616               | if_feature_stmt      { clicon_debug(3,"yang-stmt -> if-feature-stmt");}
1617               | import_stmt          { clicon_debug(3,"yang-stmt -> import-stmt");}
1618               | include_stmt         { clicon_debug(3,"yang-stmt -> include-stmt");}
1619               | input_stmt           { clicon_debug(3,"yang-stmt -> input-stmt");}
1620               | key_stmt             { clicon_debug(3,"yang-stmt -> key-stmt");}
1621               | leaf_list_stmt       { clicon_debug(3,"yang-stmt -> leaf-list-stmt");}
1622               | leaf_stmt            { clicon_debug(3,"yang-stmt -> leaf-stmt");}
1623               | length_stmt          { clicon_debug(3,"yang-stmt -> length-stmt");}
1624               | list_stmt            { clicon_debug(3,"yang-stmt -> list-stmt");}
1625               | mandatory_stmt       { clicon_debug(3,"yang-stmt -> list-stmt");}
1626               | max_elements_stmt    { clicon_debug(3,"yang-stmt -> list-stmt");}
1627               | min_elements_stmt    { clicon_debug(3,"yang-stmt -> list-stmt");}
1628               | modifier_stmt        { clicon_debug(3,"yang-stmt -> list-stmt");}
1629               | module_stmt          { clicon_debug(3,"yang-stmt -> list-stmt");}
1630               | must_stmt            { clicon_debug(3,"yang-stmt -> list-stmt");}
1631               | namespace_stmt       { clicon_debug(3,"yang-stmt -> list-stmt");}
1632               | notification_stmt    { clicon_debug(3,"yang-stmt -> notification-stmt");}
1633               | ordered_by_stmt      { clicon_debug(3,"yang-stmt -> list-stmt");}
1634               | organization_stmt    { clicon_debug(3,"yang-stmt -> list-stmt");}
1635               | output_stmt          { clicon_debug(3,"yang-stmt -> list-stmt");}
1636               | path_stmt            { clicon_debug(3,"yang-stmt -> list-stmt");}
1637               | pattern_stmt         { clicon_debug(3,"yang-stmt -> list-stmt");}
1638               | position_stmt        { clicon_debug(3,"yang-stmt -> list-stmt");}
1639               | prefix_stmt          { clicon_debug(3,"yang-stmt -> list-stmt");}
1640               | presence_stmt        { clicon_debug(3,"yang-stmt -> list-stmt");}
1641               | range_stmt           { clicon_debug(3,"yang-stmt -> list-stmt");}
1642               | reference_stmt       { clicon_debug(3,"yang-stmt -> list-stmt");}
1643               | refine_stmt          { clicon_debug(3,"yang-stmt -> list-stmt");}
1644               | require_instance_stmt { clicon_debug(3,"yang-stmt -> list-stmt");}
1645               | revision_date_stmt   { clicon_debug(3,"yang-stmt -> list-stmt");}
1646               | revision_stmt        { clicon_debug(3,"yang-stmt -> list-stmt");}
1647               | rpc_stmt             { clicon_debug(3,"yang-stmt -> rpc-stmt");}
1648               | status_stmt          { clicon_debug(3,"yang-stmt -> list-stmt");}
1649               | submodule_stmt       { clicon_debug(3,"yang-stmt -> list-stmt");}
1650               | typedef_stmt         { clicon_debug(3,"yang-stmt -> typedef-stmt");}
1651               | type_stmt            { clicon_debug(3,"yang-stmt -> list-stmt");}
1652               | unique_stmt          { clicon_debug(3,"yang-stmt -> list-stmt");}
1653               | units_stmt           { clicon_debug(3,"yang-stmt -> list-stmt");}
1654               | uses_augment_stmt    { clicon_debug(3,"yang-stmt -> list-stmt");}
1655               | uses_stmt            { clicon_debug(3,"yang-stmt -> list-stmt");}
1656               | value_stmt           { clicon_debug(3,"yang-stmt -> list-stmt");}
1657               | when_stmt            { clicon_debug(3,"yang-stmt -> list-stmt");}
1658               | yang_version_stmt    { clicon_debug(3,"yang-stmt -> list-stmt");}
1659 /*              | yin_element_stmt     { clicon_debug(3,"yang-stmt -> list-stmt");} */
1660               ;
1661 
1662 /* body */
1663 body_stmts    : body_stmts body_stmt { clicon_debug(3,"body-stmts -> body-stmts body-stmt"); }
1664               | body_stmt            { clicon_debug(3,"body-stmts -> body-stmt");}
1665               ;
1666 
1667 body_stmt     : extension_stmt       { clicon_debug(3,"body-stmt -> extension-stmt");}
1668               | feature_stmt         { clicon_debug(3,"body-stmt -> feature-stmt");}
1669               | identity_stmt        { clicon_debug(3,"body-stmt -> identity-stmt");}
1670               | typedef_stmt         { clicon_debug(3,"body-stmt -> typedef-stmt");}
1671               | grouping_stmt        { clicon_debug(3,"body-stmt -> grouping-stmt");}
1672               | data_def_stmt        { clicon_debug(3,"body-stmt -> data-def-stmt");}
1673               | augment_stmt         { clicon_debug(3,"body-stmt -> augment-stmt");}
1674               | rpc_stmt             { clicon_debug(3,"body-stmt -> rpc-stmt");}
1675               | notification_stmt    { clicon_debug(3,"body-stmt -> notification-stmt");}
1676               | deviation_stmt       { clicon_debug(3,"body-stmt -> deviation-stmt");}
1677               ;
1678 
1679 data_def_stmt : container_stmt       { clicon_debug(3,"data-def-stmt -> container-stmt");}
1680               | leaf_stmt            { clicon_debug(3,"data-def-stmt -> leaf-stmt");}
1681               | leaf_list_stmt       { clicon_debug(3,"data-def-stmt -> leaf-list-stmt");}
1682               | list_stmt            { clicon_debug(3,"data-def-stmt -> list-stmt");}
1683               | choice_stmt          { clicon_debug(3,"data-def-stmt -> choice-stmt");}
1684               | anydata_stmt         { clicon_debug(3,"data-def-stmt -> anydata-stmt");}
1685               | anyxml_stmt          { clicon_debug(3,"data-def-stmt -> anyxml-stmt");}
1686               | uses_stmt            { clicon_debug(3,"data-def-stmt -> uses-stmt");}
1687               ;
1688 
1689 /* short-case */
1690 short_case_stmt : container_stmt   { clicon_debug(3,"short-case-substmt -> container-stmt"); }
1691               | leaf_stmt          { clicon_debug(3,"short-case-substmt -> leaf-stmt"); }
1692               | leaf_list_stmt     { clicon_debug(3,"short-case-substmt -> leaf-list-stmt"); }
1693               | list_stmt          { clicon_debug(3,"short-case-substmt -> list-stmt"); }
1694               | anydata_stmt       { clicon_debug(3,"short-case-substmt -> anydata-stmt");}
1695               | anyxml_stmt        { clicon_debug(3,"short-case-substmt -> anyxml-stmt");}
1696               ;
1697 
1698 
1699 /* input */
1700 input_stmt  : K_INPUT
1701                   { if (ysp_add_push(_yy, Y_INPUT, NULL, NULL) == NULL) _YYERROR("input_stmt"); }
1702 	       '{' input_substmts '}'
1703                   { if (ystack_pop(_yy) < 0) _YYERROR("input_stmt");
1704 			     clicon_debug(3,"input-stmt -> INPUT { input-substmts }"); }
1705               ;
1706 
1707 input_substmts : input_substmts input_substmt
1708                       { clicon_debug(3,"input-substmts -> input-substmts input-substmt"); }
1709               | input_substmt
1710                       { clicon_debug(3,"input-substmts -> input-substmt"); }
1711               ;
1712 
1713 input_substmt : typedef_stmt         { clicon_debug(3,"input-substmt -> typedef-stmt"); }
1714               | grouping_stmt        { clicon_debug(3,"input-substmt -> grouping-stmt"); }
1715               | data_def_stmt        { clicon_debug(3,"input-substmt -> data-def-stmt"); }
1716               |                      { clicon_debug(3,"input-substmt -> "); }
1717               ;
1718 
1719 /* output */
1720 output_stmt  : K_OUTPUT  /* XXX reuse input-substatements since they are same */
1721                    { if (ysp_add_push(_yy, Y_OUTPUT, NULL, NULL) == NULL) _YYERROR("output_stmt"); }
1722 	       '{' input_substmts '}'
1723                    { if (ystack_pop(_yy) < 0) _YYERROR("output_stmt");
1724 			     clicon_debug(3,"output-stmt -> OUTPUT { input-substmts }"); }
1725               ;
1726 
1727 string        : qstrings { $$=$1; clicon_debug(3,"string -> qstrings (%s)", $1); }
1728               | ustring  { $$=$1; clicon_debug(3,"string -> ustring (%s)", $1); }
1729               ;
1730 
1731 /* quoted string */
1732 qstrings      : qstrings '+' qstring
1733                      {
1734 			 int len = strlen($1);
1735 			 $$ = realloc($1, len + strlen($3) + 1);
1736 			 sprintf($$+len, "%s", $3);
1737 			 free($3);
1738 			 clicon_debug(3,"qstrings-> qstrings + qstring");
1739 		     }
1740               | qstring
1741                      { $$=$1; clicon_debug(3,"qstrings-> qstring"); }
1742               ;
1743 
1744 qstring        : '"' ustring '"'  { $$=$2; clicon_debug(3,"string-> \" ustring \"");}
1745                | '"' '"'  { $$=strdup(""); clicon_debug(3,"string-> \"  \"");}
1746                | SQ ustring SQ  { $$=$2; clicon_debug(3,"string-> ' ustring '"); }
1747                | SQ SQ  { $$=strdup(""); clicon_debug(3,"string-> '  '");}
1748                ;
1749 
1750 /* unquoted string */
1751 ustring       : ustring CHARS
1752                      {
1753 			 int len = strlen($1);
1754 			 $$ = realloc($1, len+strlen($2) + 1);
1755 			 sprintf($$+len, "%s", $2);
1756 			 free($2);
1757  			 clicon_debug(3,"ustring-> string + CHARS");
1758 		     }
1759               | CHARS
1760 	             {$$=$1; }
1761               ;
1762 
1763 abs_schema_nodeid : abs_schema_nodeid '/' node_identifier
1764                  { if (($$=string_del_join($1, "/", $3)) == NULL) _YYERROR("abs_schema_nodeid");
1765 		   clicon_debug(3,"absolute-schema-nodeid -> absolute-schema-nodeid / node-identifier"); }
1766               | '/' node_identifier
1767                  {  if (($$=string_del_join(NULL, "/", $2)) == NULL) _YYERROR("abs_schema_nodeid");
1768 		     clicon_debug(3,"absolute-schema-nodeid -> / node-identifier"); }
1769               ;
1770 
1771 desc_schema_nodeid_strs : desc_schema_nodeid_strs '+' desc_schema_nodeid_str
1772                      {
1773 			 int len = strlen($1);
1774 			 $$ = realloc($1, len + strlen($3) + 1);
1775 			 sprintf($$+len, "%s", $3);
1776 			 free($3);
1777 			 clicon_debug(3,"desc-schema-nodeid-strs-> desc-schema-nodeid-strs + desc-schema-nodeid-str");
1778 		     }
1779                       | desc_schema_nodeid_str
1780                            { $$=$1; clicon_debug(3,"desc-schema-nodeid-strs-> desc-schema-nodeid-str"); }
1781                       ;
1782 
1783 desc_schema_nodeid_str : desc_schema_nodeid
1784                          { $$=$1; clicon_debug(3,"descendant-schema-nodeid-str -> descendant-schema-nodeid"); }
1785                      | '"' desc_schema_nodeid '"'
1786                          { $$=$2; clicon_debug(3,"descendant-schema-nodeid-str -> descendant-schema-nodeid"); }
1787                      ;
1788 
1789 /* descendant-schema-nodeid */
1790 desc_schema_nodeid : node_identifier
1791                      { $$= $1; clicon_debug(3,"descendant-schema-nodeid -> node_identifier"); }
1792                    | node_identifier abs_schema_nodeid
1793 		   { if (($$=string_del_join($1, " ", $2)) == NULL) _YYERROR("desc_schema_nodeid");clicon_debug(3,"descendant-schema-nodeid -> node_identifier abs_schema_nodeid"); }
1794                    ;
1795 
1796 identifier_str : '"' IDENTIFIER '"' { $$ = $2;
1797 		         clicon_debug(3,"identifier_str -> \" IDENTIFIER \" ");}
1798                | IDENTIFIER           { $$ = $1;
1799 		         clicon_debug(3,"identifier_str -> IDENTIFIER ");}
1800                ;
1801 
1802 identifier_ref_str : '"' identifier_ref '"' { $$ = $2;
1803 		         clicon_debug(3,"identifier_ref_str -> \" identifier_ref \" ");}
1804                | identifier_ref           { $$ = $1;
1805 		         clicon_debug(3,"identifier_ref_str -> identifier_ref ");}
1806                ;
1807 
1808 integer_value_str : '"' INT '"' { $$=$2; }
1809                   |     INT     { $$=$1; }
1810                   ;
1811 
1812 bool_str       : '"' BOOL '"' { $$ = $2;
1813 		         clicon_debug(3,"bool_str -> \" BOOL \" ");}
1814                |     BOOL     { $$ = $1;
1815 		         clicon_debug(3,"bool_str -> BOOL ");}
1816                ;
1817 
1818 
1819 /*   node-identifier     = [prefix ":"] identifier */
1820 node_identifier : IDENTIFIER
1821 		   { $$=$1; clicon_debug(3,"identifier-ref-arg-str -> string"); }
1822                 | IDENTIFIER ':' IDENTIFIER
1823 		{ if (($$=string_del_join($1, ":", $3)) == NULL) _YYERROR("node_identifier");
1824 			clicon_debug(3,"identifier-ref-arg-str -> prefix : string"); }
1825                 ;
1826 
1827 /* ;;; Basic Rules */
1828 
1829 /* identifier-ref = [prefix ":"] identifier */
1830 identifier_ref : node_identifier { $$=$1;}
1831                ;
1832 
1833 optsep :       SEP
1834                |
1835                ;
1836 
1837 
1838 stmtend        : ';'
1839                | '{' '}'
1840                | '{' unknown_stmt '}'
1841                ;
1842 
1843 %%
1844 
1845