1 /* 2 * gram.y 3 * 4 * $Author$ 5 * $Date$ 6 * 7 * Copyright (C) 2003 why the lucky stiff 8 */ 9 10 %start doc 11 %pure-parser 12 %parse-param {void* parser} 13 %lex-param {void* parser} 14 15 %{ 16 17 #define YYDEBUG 1 18 #define YYERROR_VERBOSE 1 19 #ifndef YYSTACK_USE_ALLOCA 20 #define YYSTACK_USE_ALLOCA 0 21 #endif 22 23 #include "syck.h" 24 #include "sycklex.h" 25 26 void apply_seq_in_map( SyckParser *parser, SyckNode *n ); 27 28 #define NULL_NODE(parser, node) \ 29 SyckNode *node = syck_new_str( "", scalar_plain ); \ 30 if ( ((SyckParser *)parser)->taguri_expansion == 1 ) \ 31 { \ 32 node->type_id = syck_taguri( YAML_DOMAIN, "null", 4 ); \ 33 } \ 34 else \ 35 { \ 36 node->type_id = syck_strndup( "null", 4 ); \ 37 } 38 %} 39 40 %union { 41 SYMID nodeId; 42 SyckNode *nodeData; 43 char *name; 44 }; 45 46 %token <name> YAML_ANCHOR YAML_ALIAS YAML_TRANSFER YAML_TAGURI YAML_ITRANSFER 47 %token <nodeData> YAML_WORD YAML_PLAIN YAML_BLOCK 48 %token YAML_DOCSEP YAML_IOPEN YAML_INDENT YAML_IEND 49 50 %type <nodeId> doc basic_seq 51 %type <nodeData> atom word_rep ind_rep struct_rep atom_or_empty empty 52 %type <nodeData> implicit_seq inline_seq implicit_map inline_map inline_seq_atom inline_map_atom 53 %type <nodeData> top_imp_seq in_implicit_seq in_inline_seq basic_mapping complex_key complex_value 54 %type <nodeData> top_imp_map in_implicit_map in_inline_map complex_mapping 55 56 %left '-' ':' 57 %left '[' ']' '{' '}' ',' '?' 58 59 %% 60 61 doc : atom 62 { 63 ((SyckParser *)parser)->root = syck_hdlr_add_node( (SyckParser *)parser, $1 ); 64 } 65 | YAML_DOCSEP atom_or_empty 66 { 67 ((SyckParser *)parser)->root = syck_hdlr_add_node( (SyckParser *)parser, $2 ); 68 } 69 | 70 { 71 ((SyckParser *)parser)->eof = 1; 72 } 73 ; 74 75 atom : word_rep 76 | ind_rep 77 ; 78 79 ind_rep : struct_rep 80 | YAML_TRANSFER ind_rep 81 { 82 syck_add_transfer( $1, $2, ((SyckParser *)parser)->taguri_expansion ); 83 $$ = $2; 84 } 85 | YAML_TAGURI ind_rep 86 { 87 syck_add_transfer( $1, $2, 0 ); 88 $$ = $2; 89 } 90 | YAML_ANCHOR ind_rep 91 { 92 /* 93 * _Anchors_: The language binding must keep a separate symbol table 94 * for anchors. The actual ID in the symbol table is returned to the 95 * higher nodes, though. 96 */ 97 $$ = syck_hdlr_add_anchor( (SyckParser *)parser, $1, $2 ); 98 } 99 | indent_open ind_rep indent_flex_end 100 { 101 $$ = $2; 102 } 103 ; 104 105 atom_or_empty : atom 106 | empty 107 ; 108 109 empty : indent_open empty indent_end 110 { 111 $$ = $2; 112 } 113 | 114 { 115 NULL_NODE( parser, n ); 116 $$ = n; 117 } 118 | YAML_ITRANSFER empty 119 { 120 if ( ((SyckParser *)parser)->implicit_typing == 1 ) 121 { 122 try_tag_implicit( $2, ((SyckParser *)parser)->taguri_expansion ); 123 } 124 $$ = $2; 125 } 126 | YAML_TRANSFER empty 127 { 128 syck_add_transfer( $1, $2, ((SyckParser *)parser)->taguri_expansion ); 129 $$ = $2; 130 } 131 | YAML_TAGURI empty 132 { 133 syck_add_transfer( $1, $2, 0 ); 134 $$ = $2; 135 } 136 | YAML_ANCHOR empty 137 { 138 /* 139 * _Anchors_: The language binding must keep a separate symbol table 140 * for anchors. The actual ID in the symbol table is returned to the 141 * higher nodes, though. 142 */ 143 $$ = syck_hdlr_add_anchor( (SyckParser *)parser, $1, $2 ); 144 } 145 ; 146 147 /* 148 * Indentation abstractions 149 */ 150 indent_open : YAML_IOPEN 151 | indent_open YAML_INDENT 152 ; 153 154 indent_end : YAML_IEND 155 ; 156 157 indent_sep : YAML_INDENT 158 ; 159 160 indent_flex_end : YAML_IEND 161 | indent_sep indent_flex_end 162 ; 163 164 /* 165 * Words are broken out to distinguish them 166 * as keys in implicit maps and valid elements 167 * for the inline structures 168 */ 169 word_rep : YAML_TRANSFER word_rep 170 { 171 syck_add_transfer( $1, $2, ((SyckParser *)parser)->taguri_expansion ); 172 $$ = $2; 173 } 174 | YAML_TAGURI word_rep 175 { 176 syck_add_transfer( $1, $2, 0 ); 177 $$ = $2; 178 } 179 | YAML_ITRANSFER word_rep 180 { 181 if ( ((SyckParser *)parser)->implicit_typing == 1 ) 182 { 183 try_tag_implicit( $2, ((SyckParser *)parser)->taguri_expansion ); 184 } 185 $$ = $2; 186 } 187 | YAML_ANCHOR word_rep 188 { 189 $$ = syck_hdlr_add_anchor( (SyckParser *)parser, $1, $2 ); 190 } 191 | YAML_ALIAS 192 { 193 /* 194 * _Aliases_: The anchor symbol table is scanned for the anchor name. 195 * The anchor's ID in the language's symbol table is returned. 196 */ 197 $$ = syck_hdlr_get_anchor( (SyckParser *)parser, $1 ); 198 } 199 | YAML_WORD 200 { 201 SyckNode *n = $1; 202 if ( ((SyckParser *)parser)->taguri_expansion == 1 ) 203 { 204 n->type_id = syck_taguri( YAML_DOMAIN, "str", 3 ); 205 } 206 else 207 { 208 n->type_id = syck_strndup( "str", 3 ); 209 } 210 $$ = n; 211 } 212 | YAML_PLAIN 213 | indent_open word_rep indent_flex_end 214 { 215 $$ = $2; 216 } 217 ; 218 219 /* 220 * Any of these structures can be used as 221 * complex keys 222 */ 223 struct_rep : YAML_BLOCK 224 | implicit_seq 225 | inline_seq 226 | implicit_map 227 | inline_map 228 ; 229 230 /* 231 * Implicit sequence 232 */ 233 implicit_seq : indent_open top_imp_seq indent_end 234 { 235 $$ = $2; 236 } 237 | indent_open in_implicit_seq indent_end 238 { 239 $$ = $2; 240 } 241 ; 242 243 basic_seq : '-' atom_or_empty 244 { 245 $$ = syck_hdlr_add_node( (SyckParser *)parser, $2 ); 246 } 247 ; 248 249 top_imp_seq : YAML_TRANSFER indent_sep in_implicit_seq 250 { 251 syck_add_transfer( $1, $3, ((SyckParser *)parser)->taguri_expansion ); 252 $$ = $3; 253 } 254 | YAML_TRANSFER top_imp_seq 255 { 256 syck_add_transfer( $1, $2, ((SyckParser *)parser)->taguri_expansion ); 257 $$ = $2; 258 } 259 | YAML_TAGURI indent_sep in_implicit_seq 260 { 261 syck_add_transfer( $1, $3, 0 ); 262 $$ = $3; 263 } 264 | YAML_TAGURI top_imp_seq 265 { 266 syck_add_transfer( $1, $2, 0 ); 267 $$ = $2; 268 } 269 | YAML_ANCHOR indent_sep in_implicit_seq 270 { 271 $$ = syck_hdlr_add_anchor( (SyckParser *)parser, $1, $3 ); 272 } 273 | YAML_ANCHOR top_imp_seq 274 { 275 $$ = syck_hdlr_add_anchor( (SyckParser *)parser, $1, $2 ); 276 } 277 ; 278 279 in_implicit_seq : basic_seq 280 { 281 $$ = syck_new_seq( $1 ); 282 } 283 | in_implicit_seq indent_sep basic_seq 284 { 285 syck_seq_add( $1, $3 ); 286 $$ = $1; 287 } 288 | in_implicit_seq indent_sep 289 { 290 $$ = $1; 291 } 292 ; 293 294 /* 295 * Inline sequences 296 */ 297 inline_seq : '[' in_inline_seq ']' 298 { 299 $$ = $2; 300 } 301 | '[' ']' 302 { 303 $$ = syck_alloc_seq(); 304 } 305 ; 306 307 in_inline_seq : inline_seq_atom 308 { 309 $$ = syck_new_seq( syck_hdlr_add_node( (SyckParser *)parser, $1 ) ); 310 } 311 | in_inline_seq ',' inline_seq_atom 312 { 313 syck_seq_add( $1, syck_hdlr_add_node( (SyckParser *)parser, $3 ) ); 314 $$ = $1; 315 } 316 ; 317 318 inline_seq_atom : atom 319 | basic_mapping 320 ; 321 322 /* 323 * Implicit maps 324 */ 325 implicit_map : indent_open top_imp_map indent_end 326 { 327 apply_seq_in_map( (SyckParser *)parser, $2 ); 328 $$ = $2; 329 } 330 | indent_open in_implicit_map indent_end 331 { 332 apply_seq_in_map( (SyckParser *)parser, $2 ); 333 $$ = $2; 334 } 335 ; 336 337 top_imp_map : YAML_TRANSFER indent_sep in_implicit_map 338 { 339 syck_add_transfer( $1, $3, ((SyckParser *)parser)->taguri_expansion ); 340 $$ = $3; 341 } 342 | YAML_TRANSFER top_imp_map 343 { 344 syck_add_transfer( $1, $2, ((SyckParser *)parser)->taguri_expansion ); 345 $$ = $2; 346 } 347 | YAML_TAGURI indent_sep in_implicit_map 348 { 349 syck_add_transfer( $1, $3, 0 ); 350 $$ = $3; 351 } 352 | YAML_TAGURI top_imp_map 353 { 354 syck_add_transfer( $1, $2, 0 ); 355 $$ = $2; 356 } 357 | YAML_ANCHOR indent_sep in_implicit_map 358 { 359 $$ = syck_hdlr_add_anchor( (SyckParser *)parser, $1, $3 ); 360 } 361 | YAML_ANCHOR top_imp_map 362 { 363 $$ = syck_hdlr_add_anchor( (SyckParser *)parser, $1, $2 ); 364 } 365 ; 366 367 complex_key : word_rep 368 | '?' atom indent_sep 369 { 370 $$ = $2; 371 } 372 ; 373 374 complex_value : atom_or_empty 375 ; 376 377 /* Default needs to be added to SyckSeq i think... 378 | '=' ':' atom 379 { 380 result = [ :DEFAULT, val[2] ] 381 } 382 */ 383 384 complex_mapping : complex_key ':' complex_value 385 { 386 $$ = syck_new_map( 387 syck_hdlr_add_node( (SyckParser *)parser, $1 ), 388 syck_hdlr_add_node( (SyckParser *)parser, $3 ) ); 389 } 390 /* 391 | '?' atom 392 { 393 NULL_NODE( parser, n ); 394 $$ = syck_new_map( 395 syck_hdlr_add_node( (SyckParser *)parser, $2 ), 396 syck_hdlr_add_node( (SyckParser *)parser, n ) ); 397 } 398 */ 399 ; 400 401 in_implicit_map : complex_mapping 402 | in_implicit_map indent_sep basic_seq 403 { 404 if ( $1->shortcut == NULL ) 405 { 406 $1->shortcut = syck_new_seq( $3 ); 407 } 408 else 409 { 410 syck_seq_add( $1->shortcut, $3 ); 411 } 412 $$ = $1; 413 } 414 | in_implicit_map indent_sep complex_mapping 415 { 416 apply_seq_in_map( (SyckParser *)parser, $1 ); 417 syck_map_update( $1, $3 ); 418 syck_free_node( $3 ); 419 $3 = NULL; 420 $$ = $1; 421 } 422 | in_implicit_map indent_sep 423 { 424 $$ = $1; 425 } 426 ; 427 428 /* 429 * Inline maps 430 */ 431 basic_mapping : atom ':' atom_or_empty 432 { 433 $$ = syck_new_map( 434 syck_hdlr_add_node( (SyckParser *)parser, $1 ), 435 syck_hdlr_add_node( (SyckParser *)parser, $3 ) ); 436 } 437 ; 438 439 inline_map : '{' in_inline_map '}' 440 { 441 $$ = $2; 442 } 443 | '{' '}' 444 { 445 $$ = syck_alloc_map(); 446 } 447 ; 448 449 in_inline_map : inline_map_atom 450 | in_inline_map ',' inline_map_atom 451 { 452 syck_map_update( $1, $3 ); 453 syck_free_node( $3 ); 454 $3 = NULL; 455 $$ = $1; 456 } 457 ; 458 459 inline_map_atom : atom 460 { 461 NULL_NODE( parser, n ); 462 $$ = syck_new_map( 463 syck_hdlr_add_node( (SyckParser *)parser, $1 ), 464 syck_hdlr_add_node( (SyckParser *)parser, n ) ); 465 } 466 | basic_mapping 467 ; 468 469 %% 470 471 void 472 apply_seq_in_map( SyckParser *parser, SyckNode *n ) 473 { 474 long map_len; 475 if ( n->shortcut == NULL ) 476 { 477 return; 478 } 479 480 map_len = syck_map_count( n ); 481 syck_map_assign( n, map_value, map_len - 1, 482 syck_hdlr_add_node( parser, n->shortcut ) ); 483 484 n->shortcut = NULL; 485 } 486 487