1 28 package org.jvyamlb; 29 30 import java.io.InputStream ; 31 import java.io.FileInputStream ; 32 33 import java.util.HashMap ; 34 import java.util.Iterator ; 35 import java.util.LinkedList ; 36 import java.util.List ; 37 import java.util.Map ; 38 39 import org.jvyamlb.events.*; 40 import org.jvyamlb.tokens.*; 41 42 import org.jruby.util.ByteList; 43 44 47 public class ParserImpl implements Parser { 48 private final static int P_STREAM = 0; 50 private final static int P_STREAM_START = 1; private final static int P_STREAM_END = 2; private final static int P_IMPLICIT_DOCUMENT = 3; 53 private final static int P_EXPLICIT_DOCUMENT = 4; 54 private final static int P_DOCUMENT_START = 5; 55 private final static int P_DOCUMENT_START_IMPLICIT = 6; 56 private final static int P_DOCUMENT_END = 7; 57 private final static int P_BLOCK_NODE = 8; 58 private final static int P_BLOCK_CONTENT = 9; 59 private final static int P_PROPERTIES = 10; 60 private final static int P_PROPERTIES_END = 11; 61 private final static int P_FLOW_CONTENT = 12; 62 private final static int P_BLOCK_SEQUENCE = 13; 63 private final static int P_BLOCK_MAPPING = 14; 64 private final static int P_FLOW_SEQUENCE = 15; 65 private final static int P_FLOW_MAPPING = 16; 66 private final static int P_SCALAR = 17; 67 private final static int P_BLOCK_SEQUENCE_ENTRY = 18; 68 private final static int P_BLOCK_MAPPING_ENTRY = 19; 69 private final static int P_BLOCK_MAPPING_ENTRY_VALUE = 20; 70 private final static int P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE = 21; 71 private final static int P_BLOCK_SEQUENCE_START = 22; 72 private final static int P_BLOCK_SEQUENCE_END = 23; 73 private final static int P_BLOCK_MAPPING_START = 24; 74 private final static int P_BLOCK_MAPPING_END = 25; 75 private final static int P_INDENTLESS_BLOCK_SEQUENCE = 26; 76 private final static int P_BLOCK_INDENTLESS_SEQUENCE_START = 27; 77 private final static int P_INDENTLESS_BLOCK_SEQUENCE_ENTRY = 28; 78 private final static int P_BLOCK_INDENTLESS_SEQUENCE_END = 29; 79 private final static int P_FLOW_SEQUENCE_START = 30; 80 private final static int P_FLOW_SEQUENCE_ENTRY = 31; 81 private final static int P_FLOW_SEQUENCE_END = 32; 82 private final static int P_FLOW_MAPPING_START = 33; 83 private final static int P_FLOW_MAPPING_ENTRY = 34; 84 private final static int P_FLOW_MAPPING_END = 35; 85 private final static int P_FLOW_INTERNAL_MAPPING_START = 36; 86 private final static int P_FLOW_INTERNAL_CONTENT = 37; 87 private final static int P_FLOW_INTERNAL_VALUE = 38; 88 private final static int P_FLOW_INTERNAL_MAPPING_END = 39; 89 private final static int P_FLOW_ENTRY_MARKER = 40; 90 private final static int P_FLOW_NODE = 41; 91 private final static int P_FLOW_MAPPING_INTERNAL_CONTENT = 42; 92 private final static int P_FLOW_MAPPING_INTERNAL_VALUE = 43; 93 private final static int P_ALIAS = 44; 94 private final static int P_EMPTY_SCALAR = 45; 95 96 private final static Event DOCUMENT_END_TRUE = new DocumentEndEvent(true); 97 private final static Event DOCUMENT_END_FALSE = new DocumentEndEvent(false); 98 private final static Event MAPPING_END = new MappingEndEvent(); 99 private final static Event SEQUENCE_END = new SequenceEndEvent(); 100 private final static Event STREAM_END = new StreamEndEvent(); 101 private final static Event STREAM_START = new StreamStartEvent(); 102 103 private static class ProductionEnvironment { 104 private List tags; 105 private List anchors; 106 private Map tagHandles; 107 private int[] yamlVersion; 108 private int[] defaultYamlVersion; 109 110 public ProductionEnvironment(final YAMLConfig cfg) { 111 this.tags = new LinkedList (); 112 this.anchors = new LinkedList (); 113 this.tagHandles = new HashMap (); 114 this.yamlVersion = null; 115 this.defaultYamlVersion = new int[2]; 116 this.defaultYamlVersion[0] = Integer.parseInt(cfg.version().substring(0,cfg.version().indexOf('.'))); 117 this.defaultYamlVersion[1] = Integer.parseInt(cfg.version().substring(cfg.version().indexOf('.')+1)); 118 } 119 120 public List getTags() { 121 return this.tags; 122 } 123 124 public List getAnchors() { 125 return this.anchors; 126 } 127 128 public Map getTagHandles() { 129 return this.tagHandles; 130 } 131 132 public int[] getYamlVersion() { 133 return this.yamlVersion; 134 } 135 136 public int[] getFinalYamlVersion() { 137 if(null == this.yamlVersion) { 138 return this.defaultYamlVersion; 139 } 140 return this.yamlVersion; 141 } 142 143 public void setYamlVersion(final int[] yamlVersion) { 144 this.yamlVersion = yamlVersion; 145 } 146 } 147 148 private static interface Production { 149 Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner); 150 } 151 152 private final static Production[] P_TABLE = new Production[46]; 153 154 private final static Map DEFAULT_TAGS_1_0 = new HashMap (); 155 private final static Map DEFAULT_TAGS_1_1 = new HashMap (); 156 static { 157 DEFAULT_TAGS_1_0.put("!","tag:yaml.org,2002:"); 158 159 DEFAULT_TAGS_1_1.put("!","!"); 160 DEFAULT_TAGS_1_1.put("!!","tag:yaml.org,2002:"); 161 } 162 163 static { 164 P_TABLE[P_STREAM] = new Production() { 165 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 166 parseStack.add(0,P_TABLE[P_STREAM_END]); 167 parseStack.add(0,P_TABLE[P_EXPLICIT_DOCUMENT]); 168 parseStack.add(0,P_TABLE[P_IMPLICIT_DOCUMENT]); 169 parseStack.add(0,P_TABLE[P_STREAM_START]); 170 return null; 171 } 172 }; 173 P_TABLE[P_STREAM_START] = new Production() { 174 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 175 scanner.getToken(); 176 return STREAM_START; 177 } 178 }; 179 P_TABLE[P_STREAM_END] = new Production() { 180 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 181 scanner.getToken(); 182 return STREAM_END; 183 } 184 }; 185 P_TABLE[P_IMPLICIT_DOCUMENT] = new Production() { 186 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 187 final Token curr = scanner.peekToken(); 188 if(!(curr instanceof DirectiveToken || curr instanceof DocumentStartToken || curr instanceof StreamEndToken)) { 189 parseStack.add(0,P_TABLE[P_DOCUMENT_END]); 190 parseStack.add(0,P_TABLE[P_BLOCK_NODE]); 191 parseStack.add(0,P_TABLE[P_DOCUMENT_START_IMPLICIT]); 192 } 193 return null; 194 } 195 }; 196 P_TABLE[P_EXPLICIT_DOCUMENT] = new Production() { 197 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 198 if(!(scanner.peekToken() instanceof StreamEndToken)) { 199 parseStack.add(0,P_TABLE[P_EXPLICIT_DOCUMENT]); 200 parseStack.add(0,P_TABLE[P_DOCUMENT_END]); 201 parseStack.add(0,P_TABLE[P_BLOCK_NODE]); 202 parseStack.add(0,P_TABLE[P_DOCUMENT_START]); 203 } 204 return null; 205 } 206 }; 207 P_TABLE[P_DOCUMENT_START] = new Production() { 208 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 209 Token tok = scanner.peekToken(); 210 final Object [] directives = processDirectives(env,scanner); 211 if(!(scanner.peekToken() instanceof DocumentStartToken)) { 212 throw new ParserException(null,"expected '<document start>', but found " + tok.getClass().getName(),null); 213 } 214 scanner.getToken(); 215 return new DocumentStartEvent(true,(int[])directives[0],(Map )directives[1]); 216 } 217 }; 218 P_TABLE[P_DOCUMENT_START_IMPLICIT] = new Production() { 219 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 220 final Object [] directives = processDirectives(env,scanner); 221 return new DocumentStartEvent(false,(int[])directives[0],(Map )directives[1]); 222 } 223 }; 224 P_TABLE[P_DOCUMENT_END] = new Production() { 225 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 226 Token tok = scanner.peekToken(); 227 boolean explicit = false; 228 while(scanner.peekToken() instanceof DocumentEndToken) { 229 scanner.getToken(); 230 explicit = true; 231 } 232 return explicit ? DOCUMENT_END_TRUE : DOCUMENT_END_FALSE; 233 } 234 }; 235 P_TABLE[P_BLOCK_NODE] = new Production() { 236 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 237 final Token curr = scanner.peekToken(); 238 if(curr instanceof DirectiveToken || curr instanceof DocumentStartToken || curr instanceof DocumentEndToken || curr instanceof StreamEndToken) { 239 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 240 } else { 241 if(curr instanceof AliasToken) { 242 parseStack.add(0,P_TABLE[P_ALIAS]); 243 } else { 244 parseStack.add(0,P_TABLE[P_PROPERTIES_END]); 245 parseStack.add(0,P_TABLE[P_BLOCK_CONTENT]); 246 parseStack.add(0,P_TABLE[P_PROPERTIES]); 247 } 248 } 249 return null; 250 } 251 }; 252 P_TABLE[P_BLOCK_CONTENT] = new Production() { 253 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 254 final Token tok = scanner.peekToken(); 255 if(tok instanceof BlockSequenceStartToken) { 256 parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE]); 257 } else if(tok instanceof BlockMappingStartToken) { 258 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING]); 259 } else if(tok instanceof FlowSequenceStartToken) { 260 parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE]); 261 } else if(tok instanceof FlowMappingStartToken) { 262 parseStack.add(0,P_TABLE[P_FLOW_MAPPING]); 263 } else if(tok instanceof ScalarToken) { 264 parseStack.add(0,P_TABLE[P_SCALAR]); 265 } else { 266 throw new ParserException("while scanning a node","expected the node content, but found " + tok.getClass().getName(),null); 267 } 268 return null; 269 } 270 }; 271 P_TABLE[P_PROPERTIES] = new Production() { 272 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 273 String anchor = null; 274 Object tag = null; 275 if(scanner.peekToken() instanceof AnchorToken) { 276 anchor = ((AnchorToken)scanner.getToken()).getValue(); 277 if(scanner.peekToken() instanceof TagToken) { 278 scanner.getToken(); 279 } 280 } else if(scanner.peekToken() instanceof TagToken) { 281 tag = ((TagToken)scanner.getToken()).getValue(); 282 if(scanner.peekToken() instanceof AnchorToken) { 283 anchor = ((AnchorToken)scanner.getToken()).getValue(); 284 } 285 } 286 if(tag != null && !tag.equals("!")) { 287 final String handle = ScannerImpl.into(((ByteList[])tag)[0]); 288 final String suffix = ScannerImpl.into(((ByteList[])tag)[1]); 289 if(handle != null) { 290 if(!env.getTagHandles().containsKey(handle)) { 291 throw new ParserException("while parsing a node","found undefined tag handle " + handle,null); 292 } 293 tag = ((String )env.getTagHandles().get(handle)) + suffix; 294 } else { 295 tag = suffix; 296 } 297 } 298 env.getAnchors().add(0,anchor); 299 env.getTags().add(0,tag); 300 return null; 301 } 302 }; 303 P_TABLE[P_PROPERTIES_END] = new Production() { 304 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 305 env.getAnchors().remove(0); 306 env.getTags().remove(0); 307 return null; 308 } 309 }; 310 P_TABLE[P_FLOW_CONTENT] = new Production() { 311 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 312 final Token tok = scanner.peekToken(); 313 if(tok instanceof FlowSequenceStartToken) { 314 parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE]); 315 } else if(tok instanceof FlowMappingStartToken) { 316 parseStack.add(0,P_TABLE[P_FLOW_MAPPING]); 317 } else if(tok instanceof ScalarToken) { 318 parseStack.add(0,P_TABLE[P_SCALAR]); 319 } else { 320 throw new ParserException("while scanning a flow node","expected the node content, but found " + tok.getClass().getName(),null); 321 } 322 return null; 323 } 324 }; 325 P_TABLE[P_BLOCK_SEQUENCE] = new Production() { 326 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 327 parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_END]); 328 parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_ENTRY]); 329 parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_START]); 330 return null; 331 } 332 }; 333 P_TABLE[P_BLOCK_MAPPING] = new Production() { 334 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 335 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_END]); 336 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY]); 337 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_START]); 338 return null; 339 } 340 }; 341 P_TABLE[P_FLOW_SEQUENCE] = new Production() { 342 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 343 parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_END]); 344 parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_ENTRY]); 345 parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_START]); 346 return null; 347 } 348 }; 349 P_TABLE[P_FLOW_MAPPING] = new Production() { 350 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 351 parseStack.add(0,P_TABLE[P_FLOW_MAPPING_END]); 352 parseStack.add(0,P_TABLE[P_FLOW_MAPPING_ENTRY]); 353 parseStack.add(0,P_TABLE[P_FLOW_MAPPING_START]); 354 return null; 355 } 356 }; 357 P_TABLE[P_SCALAR] = new Production() { 358 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 359 final ScalarToken tok = (ScalarToken)scanner.getToken(); 360 boolean[] implicit = null; 361 if((tok.getPlain() && env.getTags().get(0) == null) || "!".equals(env.getTags().get(0))) { 362 implicit = new boolean[]{true,false}; 363 } else if(env.getTags().get(0) == null) { 364 implicit = new boolean[]{false,true}; 365 } else { 366 implicit = new boolean[]{false,false}; 367 } 368 return new ScalarEvent((String )env.getAnchors().get(0),(String )env.getTags().get(0),implicit,tok.getValue(),tok.getStyle()); 369 } 370 }; 371 P_TABLE[P_BLOCK_SEQUENCE_ENTRY] = new Production() { 372 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 373 if(scanner.peekToken() instanceof BlockEntryToken) { 374 scanner.getToken(); 375 if(!(scanner.peekToken() instanceof BlockEntryToken || scanner.peekToken() instanceof BlockEndToken)) { 376 parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_ENTRY]); 377 parseStack.add(0,P_TABLE[P_BLOCK_NODE]); 378 } else { 379 parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_ENTRY]); 380 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 381 } 382 } 383 return null; 384 } 385 }; 386 P_TABLE[P_BLOCK_MAPPING_ENTRY] = new Production() { 387 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 388 if(scanner.peekToken() instanceof KeyToken || scanner.peekToken() instanceof ValueToken) { 389 if(scanner.peekToken() instanceof KeyToken) { 390 scanner.getToken(); 391 final Token curr = scanner.peekToken(); 392 if(!(curr instanceof KeyToken || curr instanceof ValueToken || curr instanceof BlockEndToken)) { 393 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY]); 394 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY_VALUE]); 395 parseStack.add(0,P_TABLE[P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE]); 396 } else { 397 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY]); 398 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY_VALUE]); 399 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 400 } 401 } else { 402 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY]); 403 parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY_VALUE]); 404 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 405 } 406 } 407 return null; 408 } 409 }; 410 P_TABLE[P_BLOCK_MAPPING_ENTRY_VALUE] = new Production() { 411 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 412 if(scanner.peekToken() instanceof KeyToken || scanner.peekToken() instanceof ValueToken) { 413 if(scanner.peekToken() instanceof ValueToken) { 414 scanner.getToken(); 415 final Token curr = scanner.peekToken(); 416 if(!(curr instanceof KeyToken || curr instanceof ValueToken || curr instanceof BlockEndToken)) { 417 parseStack.add(0,P_TABLE[P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE]); 418 } else { 419 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 420 } 421 } else { 422 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 423 } 424 } 425 return null; 426 } 427 }; 428 P_TABLE[P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE] = new Production() { 429 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 430 if(scanner.peekToken() instanceof AliasToken) { 431 parseStack.add(0,P_TABLE[P_ALIAS]); 432 } else { 433 if(scanner.peekToken() instanceof BlockEntryToken) { 434 parseStack.add(0,P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE]); 435 parseStack.add(0,P_TABLE[P_PROPERTIES]); 436 } else { 437 parseStack.add(0,P_TABLE[P_BLOCK_CONTENT]); 438 parseStack.add(0,P_TABLE[P_PROPERTIES]); 439 } 440 } 441 return null; 442 } 443 }; 444 P_TABLE[P_BLOCK_SEQUENCE_START] = new Production() { 445 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 446 final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); 447 scanner.getToken(); 448 return new SequenceStartEvent((String )env.getAnchors().get(0), (String )env.getTags().get(0), implicit,false); 449 } 450 }; 451 P_TABLE[P_BLOCK_SEQUENCE_END] = new Production() { 452 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 453 Token tok = null; 454 if(!(scanner.peekToken() instanceof BlockEndToken)) { 455 tok = scanner.peekToken(); 456 throw new ParserException("while scanning a block collection","expected <block end>, but found " + tok.getClass().getName(),null); 457 } 458 scanner.getToken(); 459 return SEQUENCE_END; 460 } 461 }; 462 P_TABLE[P_BLOCK_MAPPING_START] = new Production() { 463 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 464 final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); 465 scanner.getToken(); 466 return new MappingStartEvent((String )env.getAnchors().get(0), (String )env.getTags().get(0), implicit,false); 467 } 468 }; 469 P_TABLE[P_BLOCK_MAPPING_END] = new Production() { 470 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 471 Token tok = null; 472 if(!(scanner.peekToken() instanceof BlockEndToken)) { 473 tok = scanner.peekToken(); 474 throw new ParserException("while scanning a block mapping","expected <block end>, but found " + tok.getClass().getName(),null); 475 } 476 scanner.getToken(); 477 return MAPPING_END; 478 } 479 }; 480 P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE] = new Production() { 481 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 482 parseStack.add(0,P_TABLE[P_BLOCK_INDENTLESS_SEQUENCE_END]); 483 parseStack.add(0,P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE_ENTRY]); 484 parseStack.add(0,P_TABLE[P_BLOCK_INDENTLESS_SEQUENCE_START]); 485 return null; 486 } 487 }; 488 P_TABLE[P_BLOCK_INDENTLESS_SEQUENCE_START] = new Production() { 489 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 490 final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); 491 return new SequenceStartEvent((String )env.getAnchors().get(0), (String )env.getTags().get(0), implicit, false); 492 } 493 }; 494 P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE_ENTRY] = new Production() { 495 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 496 if(scanner.peekToken() instanceof BlockEntryToken) { 497 scanner.getToken(); 498 final Token curr = scanner.peekToken(); 499 if(!(curr instanceof BlockEntryToken || curr instanceof KeyToken || curr instanceof ValueToken || curr instanceof BlockEndToken)) { 500 parseStack.add(0,P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE_ENTRY]); 501 parseStack.add(0,P_TABLE[P_BLOCK_NODE]); 502 } else { 503 parseStack.add(0,P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE_ENTRY]); 504 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 505 } 506 } 507 return null; 508 } 509 }; 510 P_TABLE[P_BLOCK_INDENTLESS_SEQUENCE_END] = new Production() { 511 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 512 return SEQUENCE_END; 513 } 514 }; 515 P_TABLE[P_FLOW_SEQUENCE_START] = new Production() { 516 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 517 final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); 518 scanner.getToken(); 519 return new SequenceStartEvent((String )env.getAnchors().get(0), (String )env.getTags().get(0), implicit,true); 520 } 521 }; 522 P_TABLE[P_FLOW_SEQUENCE_ENTRY] = new Production() { 523 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 524 if(!(scanner.peekToken() instanceof FlowSequenceEndToken)) { 525 if(scanner.peekToken() instanceof KeyToken) { 526 parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_ENTRY]); 527 parseStack.add(0,P_TABLE[P_FLOW_ENTRY_MARKER]); 528 parseStack.add(0,P_TABLE[P_FLOW_INTERNAL_MAPPING_END]); 529 parseStack.add(0,P_TABLE[P_FLOW_INTERNAL_VALUE]); 530 parseStack.add(0,P_TABLE[P_FLOW_INTERNAL_CONTENT]); 531 parseStack.add(0,P_TABLE[P_FLOW_INTERNAL_MAPPING_START]); 532 } else { 533 parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_ENTRY]); 534 parseStack.add(0,P_TABLE[P_FLOW_NODE]); 535 parseStack.add(0,P_TABLE[P_FLOW_ENTRY_MARKER]); 536 } 537 } 538 return null; 539 } 540 }; 541 P_TABLE[P_FLOW_SEQUENCE_END] = new Production() { 542 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 543 scanner.getToken(); 544 return SEQUENCE_END; 545 } 546 }; 547 P_TABLE[P_FLOW_MAPPING_START] = new Production() { 548 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 549 final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); 550 scanner.getToken(); 551 return new MappingStartEvent((String )env.getAnchors().get(0), (String )env.getTags().get(0), implicit,true); 552 } 553 }; 554 P_TABLE[P_FLOW_MAPPING_ENTRY] = new Production() { 555 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 556 if(!(scanner.peekToken() instanceof FlowMappingEndToken)) { 557 if(scanner.peekToken() instanceof KeyToken) { 558 parseStack.add(0,P_TABLE[P_FLOW_MAPPING_ENTRY]); 559 parseStack.add(0,P_TABLE[P_FLOW_ENTRY_MARKER]); 560 parseStack.add(0,P_TABLE[P_FLOW_MAPPING_INTERNAL_VALUE]); 561 parseStack.add(0,P_TABLE[P_FLOW_MAPPING_INTERNAL_CONTENT]); 562 } else { 563 parseStack.add(0,P_TABLE[P_FLOW_MAPPING_ENTRY]); 564 parseStack.add(0,P_TABLE[P_FLOW_NODE]); 565 parseStack.add(0,P_TABLE[P_FLOW_ENTRY_MARKER]); 566 } 567 } 568 return null; 569 } 570 }; 571 P_TABLE[P_FLOW_MAPPING_END] = new Production() { 572 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 573 scanner.getToken(); 574 return MAPPING_END; 575 } 576 }; 577 P_TABLE[P_FLOW_INTERNAL_MAPPING_START] = new Production() { 578 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 579 scanner.getToken(); 580 return new MappingStartEvent(null,null,true,true); 581 } 582 }; 583 P_TABLE[P_FLOW_INTERNAL_CONTENT] = new Production() { 584 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 585 final Token curr = scanner.peekToken(); 586 if(!(curr instanceof ValueToken || curr instanceof FlowEntryToken || curr instanceof FlowSequenceEndToken)) { 587 parseStack.add(0,P_TABLE[P_FLOW_NODE]); 588 } else { 589 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 590 } 591 return null; 592 } 593 }; 594 P_TABLE[P_FLOW_INTERNAL_VALUE] = new Production() { 595 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 596 if(scanner.peekToken() instanceof ValueToken) { 597 scanner.getToken(); 598 if(!((scanner.peekToken() instanceof FlowEntryToken) || (scanner.peekToken() instanceof FlowSequenceEndToken))) { 599 parseStack.add(0,P_TABLE[P_FLOW_NODE]); 600 } else { 601 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 602 } 603 } else { 604 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 605 } 606 return null; 607 } 608 }; 609 P_TABLE[P_FLOW_INTERNAL_MAPPING_END] = new Production() { 610 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 611 return MAPPING_END; 612 } 613 }; 614 P_TABLE[P_FLOW_ENTRY_MARKER] = new Production() { 615 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 616 if(scanner.peekToken() instanceof FlowEntryToken) { 617 scanner.getToken(); 618 } 619 return null; 620 } 621 }; 622 P_TABLE[P_FLOW_NODE] = new Production() { 623 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 624 if(scanner.peekToken() instanceof AliasToken) { 625 parseStack.add(0,P_TABLE[P_ALIAS]); 626 } else { 627 parseStack.add(0,P_TABLE[P_PROPERTIES_END]); 628 parseStack.add(0,P_TABLE[P_FLOW_CONTENT]); 629 parseStack.add(0,P_TABLE[P_PROPERTIES]); 630 } 631 return null; 632 } 633 }; 634 P_TABLE[P_FLOW_MAPPING_INTERNAL_CONTENT] = new Production() { 635 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 636 final Token curr = scanner.peekToken(); 637 if(!(curr instanceof ValueToken || curr instanceof FlowEntryToken || curr instanceof FlowMappingEndToken)) { 638 scanner.getToken(); 639 parseStack.add(0,P_TABLE[P_FLOW_NODE]); 640 } else { 641 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 642 } 643 return null; 644 } 645 }; 646 P_TABLE[P_FLOW_MAPPING_INTERNAL_VALUE] = new Production() { 647 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 648 if(scanner.peekToken() instanceof ValueToken) { 649 scanner.getToken(); 650 if(!(scanner.peekToken() instanceof FlowEntryToken || scanner.peekToken() instanceof FlowMappingEndToken)) { 651 parseStack.add(0,P_TABLE[P_FLOW_NODE]); 652 } else { 653 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 654 } 655 } else { 656 parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); 657 } 658 return null; 659 } 660 }; 661 P_TABLE[P_ALIAS] = new Production() { 662 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 663 final AliasToken tok = (AliasToken)scanner.getToken(); 664 return new AliasEvent(tok.getValue()); 665 } 666 }; 667 P_TABLE[P_EMPTY_SCALAR] = new Production() { 668 public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { 669 return processEmptyScalar(); 670 } 671 }; 672 } 673 674 private static Event processEmptyScalar() { 675 return new ScalarEvent(null,null,new boolean[]{true,false},new ByteList(ByteList.NULL_ARRAY),(char)0); 676 } 677 678 private static Object [] processDirectives(final ProductionEnvironment env, final Scanner scanner) { 679 while(scanner.peekToken() instanceof DirectiveToken) { 680 final DirectiveToken tok = (DirectiveToken)scanner.getToken(); 681 if(tok.getName().equals("YAML")) { 682 if(env.getYamlVersion() != null) { 683 throw new ParserException(null,"found duplicate YAML directive",null); 684 } 685 final int major = Integer.parseInt(tok.getValue()[0]); 686 final int minor = Integer.parseInt(tok.getValue()[1]); 687 if(major != 1) { 688 throw new ParserException(null,"found incompatible YAML document (version 1.* is required)",null); 689 } 690 env.setYamlVersion(new int[]{major,minor}); 691 } else if(tok.getName().equals("TAG")) { 692 final String handle = tok.getValue()[0]; 693 final String prefix = tok.getValue()[1]; 694 if(env.getTagHandles().containsKey(handle)) { 695 throw new ParserException(null,"duplicate tag handle " + handle,null); 696 } 697 env.getTagHandles().put(handle,prefix); 698 } 699 } 700 Object [] value = new Object [2]; 701 value[0] = env.getFinalYamlVersion(); 702 703 if(!env.getTagHandles().isEmpty()) { 704 value[1] = new HashMap (env.getTagHandles()); 705 } 706 707 final Map baseTags = ((int[])value[0])[1] == 0 ? DEFAULT_TAGS_1_0 : DEFAULT_TAGS_1_1; 708 for(final Iterator iter = baseTags.keySet().iterator();iter.hasNext();) { 709 final Object key = iter.next(); 710 if(!env.getTagHandles().containsKey(key)) { 711 env.getTagHandles().put(key,baseTags.get(key)); 712 } 713 } 714 return value; 715 } 716 717 private Scanner scanner = null; 718 private YAMLConfig cfg = null; 719 720 public ParserImpl(final Scanner scanner) { 721 this(scanner, YAML.config()); 722 } 723 724 public ParserImpl(final Scanner scanner, final YAMLConfig cfg) { 725 this.scanner = scanner; 726 this.cfg = cfg; 727 } 728 729 private Event currentEvent = null; 730 731 public boolean checkEvent(final Class [] choices) { 732 parseStream(); 733 if(this.currentEvent == null) { 734 this.currentEvent = parseStreamNext(); 735 } 736 if(this.currentEvent != null) { 737 if(choices.length == 0) { 738 return true; 739 } 740 for(int i=0,j=choices.length;i<j;i++) { 741 if(choices[i].isInstance(this.currentEvent)) { 742 return true; 743 } 744 } 745 } 746 return false; 747 } 748 749 public Event peekEvent() { 750 parseStream(); 751 if(this.currentEvent == null) { 752 this.currentEvent = parseStreamNext(); 753 } 754 return this.currentEvent; 755 } 756 757 public Event getEvent() { 758 parseStream(); 759 if(this.currentEvent == null) { 760 this.currentEvent = parseStreamNext(); 761 } 762 final Event value = this.currentEvent; 763 this.currentEvent = null; 764 return value; 765 } 766 767 private class EventIterator implements Iterator { 768 public boolean hasNext() { 769 return null != peekEvent(); 770 } 771 772 public Object next() { 773 return getEvent(); 774 } 775 776 public void remove() { 777 } 778 } 779 780 public Iterator eachEvent() { 781 return new EventIterator(); 782 } 783 784 public Iterator iterator() { 785 return eachEvent(); 786 } 787 788 private List parseStack = null; 789 private ProductionEnvironment pEnv = null; 790 791 public void parseStream() { 792 if(null == parseStack) { 793 this.parseStack = new LinkedList (); 794 this.parseStack.add(0,P_TABLE[P_STREAM]); 795 this.pEnv = new ProductionEnvironment(cfg); 796 } 797 } 798 799 public Event parseStreamNext() { 800 while(!parseStack.isEmpty()) { 801 final Event value = ((Production)(this.parseStack.remove(0))).produce(this.parseStack,this.pEnv,this.scanner); 802 if(null != value) { 803 return value; 804 } 805 } 806 this.pEnv = null; 807 return null; 808 } 809 810 public static void main(final String [] args) throws Exception { 811 final String filename = args[0]; 812 System.out.println("Reading of file: \"" + filename + "\""); 813 814 final ByteList input = new ByteList(1024); 815 final InputStream reader = new FileInputStream (filename); 816 byte[] buff = new byte[1024]; 817 int read = 0; 818 while(true) { 819 read = reader.read(buff); 820 input.append(buff,0,read); 821 if(read < 1024) { 822 break; 823 } 824 } 825 reader.close(); 826 final long before = System.currentTimeMillis(); 827 for(int i=0;i<1;i++) { 828 final Parser pars = new ParserImpl(new ScannerImpl(input)); 829 for(final Iterator iter = pars.eachEvent();iter.hasNext();iter.next()) { 830 } 831 } 832 final long after = System.currentTimeMillis(); 833 final long time = after-before; 834 final double timeS = (after-before)/1000.0; 835 System.out.println("Walking through the events for the file: " + filename + " took " + time + "ms, or " + timeS + " seconds"); 836 } 837 838 public static void tmain(final String [] args) throws Exception { 839 final String filename = args[0]; 840 System.out.println("Reading of file: \"" + filename + "\""); 841 842 final InputStream reader = new FileInputStream (filename); 843 final long before = System.currentTimeMillis(); 844 for(int i=0;i<1;i++) { 845 final Parser pars = new ParserImpl(new ScannerImpl(reader)); 846 for(final Iterator iter = pars.eachEvent();iter.hasNext();iter.next()) { 847 } 848 } 849 reader.close(); 850 final long after = System.currentTimeMillis(); 851 final long time = after-before; 852 final double timeS = (after-before)/1000.0; 853 System.out.println("Walking through the events for the file: " + filename + " took " + time + "ms, or " + timeS + " seconds"); 854 } 855 856 public static void tmain2(final String [] args) throws Exception { 857 final String filename = args[0]; 858 final Parser pars = new ParserImpl(new ScannerImpl(new FileInputStream (filename))); 859 for(final Iterator iter = pars.eachEvent();iter.hasNext();) { 860 System.out.println(iter.next().getClass().getName()); 861 } 862 } 863 } | Popular Tags |