/* Copyright (c) 2006 Ola Bini * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /** * $Id: ParserImpl.java,v 1.2 2006/09/24 16:32:34 olabini Exp $ */ package org.jvyaml; import java.io.Reader; import java.io.FileReader; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.jvyaml.events.*; import org.jvyaml.tokens.*; /** * @author <a href="mailto:ola.bini@ki.se">Ola Bini</a> * @version $Revision: 1.2 $ */ public class ParserImpl implements Parser { // Memnonics for the production table private final static int P_STREAM = 0; private final static int P_STREAM_START = 1; // TERMINAL private final static int P_STREAM_END = 2; // TERMINAL private final static int P_IMPLICIT_DOCUMENT = 3; private final static int P_EXPLICIT_DOCUMENT = 4; private final static int P_DOCUMENT_START = 5; private final static int P_DOCUMENT_START_IMPLICIT = 6; private final static int P_DOCUMENT_END = 7; private final static int P_BLOCK_NODE = 8; private final static int P_BLOCK_CONTENT = 9; private final static int P_PROPERTIES = 10; private final static int P_PROPERTIES_END = 11; private final static int P_FLOW_CONTENT = 12; private final static int P_BLOCK_SEQUENCE = 13; private final static int P_BLOCK_MAPPING = 14; private final static int P_FLOW_SEQUENCE = 15; private final static int P_FLOW_MAPPING = 16; private final static int P_SCALAR = 17; private final static int P_BLOCK_SEQUENCE_ENTRY = 18; private final static int P_BLOCK_MAPPING_ENTRY = 19; private final static int P_BLOCK_MAPPING_ENTRY_VALUE = 20; private final static int P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE = 21; private final static int P_BLOCK_SEQUENCE_START = 22; private final static int P_BLOCK_SEQUENCE_END = 23; private final static int P_BLOCK_MAPPING_START = 24; private final static int P_BLOCK_MAPPING_END = 25; private final static int P_INDENTLESS_BLOCK_SEQUENCE = 26; private final static int P_BLOCK_INDENTLESS_SEQUENCE_START = 27; private final static int P_INDENTLESS_BLOCK_SEQUENCE_ENTRY = 28; private final static int P_BLOCK_INDENTLESS_SEQUENCE_END = 29; private final static int P_FLOW_SEQUENCE_START = 30; private final static int P_FLOW_SEQUENCE_ENTRY = 31; private final static int P_FLOW_SEQUENCE_END = 32; private final static int P_FLOW_MAPPING_START = 33; private final static int P_FLOW_MAPPING_ENTRY = 34; private final static int P_FLOW_MAPPING_END = 35; private final static int P_FLOW_INTERNAL_MAPPING_START = 36; private final static int P_FLOW_INTERNAL_CONTENT = 37; private final static int P_FLOW_INTERNAL_VALUE = 38; private final static int P_FLOW_INTERNAL_MAPPING_END = 39; private final static int P_FLOW_ENTRY_MARKER = 40; private final static int P_FLOW_NODE = 41; private final static int P_FLOW_MAPPING_INTERNAL_CONTENT = 42; private final static int P_FLOW_MAPPING_INTERNAL_VALUE = 43; private final static int P_ALIAS = 44; private final static int P_EMPTY_SCALAR = 45; private final static Event DOCUMENT_END_TRUE = new DocumentEndEvent(true); private final static Event DOCUMENT_END_FALSE = new DocumentEndEvent(false); private final static Event MAPPING_END = new MappingEndEvent(); private final static Event SEQUENCE_END = new SequenceEndEvent(); private final static Event STREAM_END = new StreamEndEvent(); private final static Event STREAM_START = new StreamStartEvent(); private static class ProductionEnvironment { private List tags; private List anchors; private Map tagHandles; private int[] yamlVersion; private int[] defaultYamlVersion; public ProductionEnvironment(final YAMLConfig cfg) { this.tags = new LinkedList(); this.anchors = new LinkedList(); this.tagHandles = new HashMap(); this.yamlVersion = null; this.defaultYamlVersion = new int[2]; this.defaultYamlVersion[0] = Integer.parseInt(cfg.version().substring(0,cfg.version().indexOf('.'))); this.defaultYamlVersion[1] = Integer.parseInt(cfg.version().substring(cfg.version().indexOf('.')+1)); } public List getTags() { return this.tags; } public List getAnchors() { return this.anchors; } public Map getTagHandles() { return this.tagHandles; } public int[] getYamlVersion() { return this.yamlVersion; } public int[] getFinalYamlVersion() { if(null == this.yamlVersion) { return this.defaultYamlVersion; } return this.yamlVersion; } public void setYamlVersion(final int[] yamlVersion) { this.yamlVersion = yamlVersion; } } private static interface Production { Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner); } private final static Production[] P_TABLE = new Production[46]; private final static Map DEFAULT_TAGS_1_0 = new HashMap(); private final static Map DEFAULT_TAGS_1_1 = new HashMap(); static { DEFAULT_TAGS_1_0.put("!","tag:yaml.org,2002:"); DEFAULT_TAGS_1_1.put("!","!"); DEFAULT_TAGS_1_1.put("!!","tag:yaml.org,2002:"); } static { P_TABLE[P_STREAM] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { parseStack.add(0,P_TABLE[P_STREAM_END]); parseStack.add(0,P_TABLE[P_EXPLICIT_DOCUMENT]); parseStack.add(0,P_TABLE[P_IMPLICIT_DOCUMENT]); parseStack.add(0,P_TABLE[P_STREAM_START]); return null; } }; P_TABLE[P_STREAM_START] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { scanner.getToken(); return STREAM_START; } }; P_TABLE[P_STREAM_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { scanner.getToken(); return STREAM_END; } }; P_TABLE[P_IMPLICIT_DOCUMENT] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final Token curr = scanner.peekToken(); if(!(curr instanceof DirectiveToken || curr instanceof DocumentStartToken || curr instanceof StreamEndToken)) { parseStack.add(0,P_TABLE[P_DOCUMENT_END]); parseStack.add(0,P_TABLE[P_BLOCK_NODE]); parseStack.add(0,P_TABLE[P_DOCUMENT_START_IMPLICIT]); } return null; } }; P_TABLE[P_EXPLICIT_DOCUMENT] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(!(scanner.peekToken() instanceof StreamEndToken)) { parseStack.add(0,P_TABLE[P_EXPLICIT_DOCUMENT]); parseStack.add(0,P_TABLE[P_DOCUMENT_END]); parseStack.add(0,P_TABLE[P_BLOCK_NODE]); parseStack.add(0,P_TABLE[P_DOCUMENT_START]); } return null; } }; P_TABLE[P_DOCUMENT_START] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { Token tok = scanner.peekToken(); final Object[] directives = processDirectives(env,scanner); if(!(scanner.peekToken() instanceof DocumentStartToken)) { throw new ParserException(null,"expected '<document start>', but found " + tok.getClass().getName(),null); } scanner.getToken(); return new DocumentStartEvent(true,(int[])directives[0],(Map)directives[1]); } }; P_TABLE[P_DOCUMENT_START_IMPLICIT] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final Object[] directives = processDirectives(env,scanner); return new DocumentStartEvent(false,(int[])directives[0],(Map)directives[1]); } }; P_TABLE[P_DOCUMENT_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { Token tok = scanner.peekToken(); boolean explicit = false; while(scanner.peekToken() instanceof DocumentEndToken) { scanner.getToken(); explicit = true; } return explicit ? DOCUMENT_END_TRUE : DOCUMENT_END_FALSE; } }; P_TABLE[P_BLOCK_NODE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final Token curr = scanner.peekToken(); if(curr instanceof DirectiveToken || curr instanceof DocumentStartToken || curr instanceof DocumentEndToken || curr instanceof StreamEndToken) { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } else { if(curr instanceof AliasToken) { parseStack.add(0,P_TABLE[P_ALIAS]); } else { parseStack.add(0,P_TABLE[P_PROPERTIES_END]); parseStack.add(0,P_TABLE[P_BLOCK_CONTENT]); parseStack.add(0,P_TABLE[P_PROPERTIES]); } } return null; } }; P_TABLE[P_BLOCK_CONTENT] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final Token tok = scanner.peekToken(); if(tok instanceof BlockSequenceStartToken) { parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE]); } else if(tok instanceof BlockMappingStartToken) { parseStack.add(0,P_TABLE[P_BLOCK_MAPPING]); } else if(tok instanceof FlowSequenceStartToken) { parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE]); } else if(tok instanceof FlowMappingStartToken) { parseStack.add(0,P_TABLE[P_FLOW_MAPPING]); } else if(tok instanceof ScalarToken) { parseStack.add(0,P_TABLE[P_SCALAR]); } else { throw new ParserException("while scanning a node","expected the node content, but found " + tok.getClass().getName(),null); } return null; } }; P_TABLE[P_PROPERTIES] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { String anchor = null; Object tag = null; if(scanner.peekToken() instanceof AnchorToken) { anchor = ((AnchorToken)scanner.getToken()).getValue(); if(scanner.peekToken() instanceof TagToken) { scanner.getToken(); } } else if(scanner.peekToken() instanceof TagToken) { tag = ((TagToken)scanner.getToken()).getValue(); if(scanner.peekToken() instanceof AnchorToken) { anchor = ((AnchorToken)scanner.getToken()).getValue(); } } if(tag != null && !tag.equals("!")) { final String handle = ((String[])tag)[0]; final String suffix = ((String[])tag)[1]; if(handle != null) { if(!env.getTagHandles().containsKey(handle)) { throw new ParserException("while parsing a node","found undefined tag handle " + handle,null); } tag = ((String)env.getTagHandles().get(handle)) + suffix; } else { tag = suffix; } } env.getAnchors().add(0,anchor); env.getTags().add(0,tag); return null; } }; P_TABLE[P_PROPERTIES_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { env.getAnchors().remove(0); env.getTags().remove(0); return null; } }; P_TABLE[P_FLOW_CONTENT] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final Token tok = scanner.peekToken(); if(tok instanceof FlowSequenceStartToken) { parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE]); } else if(tok instanceof FlowMappingStartToken) { parseStack.add(0,P_TABLE[P_FLOW_MAPPING]); } else if(tok instanceof ScalarToken) { parseStack.add(0,P_TABLE[P_SCALAR]); } else { throw new ParserException("while scanning a flow node","expected the node content, but found " + tok.getClass().getName(),null); } return null; } }; P_TABLE[P_BLOCK_SEQUENCE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_END]); parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_START]); return null; } }; P_TABLE[P_BLOCK_MAPPING] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_END]); parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY]); parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_START]); return null; } }; P_TABLE[P_FLOW_SEQUENCE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_END]); parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_START]); return null; } }; P_TABLE[P_FLOW_MAPPING] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { parseStack.add(0,P_TABLE[P_FLOW_MAPPING_END]); parseStack.add(0,P_TABLE[P_FLOW_MAPPING_ENTRY]); parseStack.add(0,P_TABLE[P_FLOW_MAPPING_START]); return null; } }; P_TABLE[P_SCALAR] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final ScalarToken tok = (ScalarToken)scanner.getToken(); boolean[] implicit = null; if((tok.getPlain() && env.getTags().get(0) == null) || "!".equals(env.getTags().get(0))) { implicit = new boolean[]{true,false}; } else if(env.getTags().get(0) == null) { implicit = new boolean[]{false,true}; } else { implicit = new boolean[]{false,false}; } return new ScalarEvent((String)env.getAnchors().get(0),(String)env.getTags().get(0),implicit,tok.getValue(),tok.getStyle()); } }; P_TABLE[P_BLOCK_SEQUENCE_ENTRY] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof BlockEntryToken) { scanner.getToken(); if(!(scanner.peekToken() instanceof BlockEntryToken || scanner.peekToken() instanceof BlockEndToken)) { parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_BLOCK_NODE]); } else { parseStack.add(0,P_TABLE[P_BLOCK_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } } return null; } }; P_TABLE[P_BLOCK_MAPPING_ENTRY] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof KeyToken || scanner.peekToken() instanceof ValueToken) { if(scanner.peekToken() instanceof KeyToken) { scanner.getToken(); final Token curr = scanner.peekToken(); if(!(curr instanceof KeyToken || curr instanceof ValueToken || curr instanceof BlockEndToken)) { parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY]); parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY_VALUE]); parseStack.add(0,P_TABLE[P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE]); } else { parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY]); parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY_VALUE]); parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } } else { parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY]); parseStack.add(0,P_TABLE[P_BLOCK_MAPPING_ENTRY_VALUE]); parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } } return null; } }; P_TABLE[P_BLOCK_MAPPING_ENTRY_VALUE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof KeyToken || scanner.peekToken() instanceof ValueToken) { if(scanner.peekToken() instanceof ValueToken) { scanner.getToken(); final Token curr = scanner.peekToken(); if(!(curr instanceof KeyToken || curr instanceof ValueToken || curr instanceof BlockEndToken)) { parseStack.add(0,P_TABLE[P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE]); } else { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } } else { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } } return null; } }; P_TABLE[P_BLOCK_NODE_OR_INDENTLESS_SEQUENCE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof AliasToken) { parseStack.add(0,P_TABLE[P_ALIAS]); } else { if(scanner.peekToken() instanceof BlockEntryToken) { parseStack.add(0,P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE]); parseStack.add(0,P_TABLE[P_PROPERTIES]); } else { parseStack.add(0,P_TABLE[P_BLOCK_CONTENT]); parseStack.add(0,P_TABLE[P_PROPERTIES]); } } return null; } }; P_TABLE[P_BLOCK_SEQUENCE_START] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); scanner.getToken(); return new SequenceStartEvent((String)env.getAnchors().get(0), (String)env.getTags().get(0), implicit,false); } }; P_TABLE[P_BLOCK_SEQUENCE_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { Token tok = null; if(!(scanner.peekToken() instanceof BlockEndToken)) { tok = scanner.peekToken(); throw new ParserException("while scanning a block collection","expected <block end>, but found " + tok.getClass().getName(),null); } scanner.getToken(); return SEQUENCE_END; } }; P_TABLE[P_BLOCK_MAPPING_START] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); scanner.getToken(); return new MappingStartEvent((String)env.getAnchors().get(0), (String)env.getTags().get(0), implicit,false); } }; P_TABLE[P_BLOCK_MAPPING_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { Token tok = null; if(!(scanner.peekToken() instanceof BlockEndToken)) { tok = scanner.peekToken(); throw new ParserException("while scanning a block mapping","expected <block end>, but found " + tok.getClass().getName(),null); } scanner.getToken(); return MAPPING_END; } }; P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { parseStack.add(0,P_TABLE[P_BLOCK_INDENTLESS_SEQUENCE_END]); parseStack.add(0,P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_BLOCK_INDENTLESS_SEQUENCE_START]); return null; } }; P_TABLE[P_BLOCK_INDENTLESS_SEQUENCE_START] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); return new SequenceStartEvent((String)env.getAnchors().get(0), (String)env.getTags().get(0), implicit, false); } }; P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE_ENTRY] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof BlockEntryToken) { scanner.getToken(); final Token curr = scanner.peekToken(); if(!(curr instanceof BlockEntryToken || curr instanceof KeyToken || curr instanceof ValueToken || curr instanceof BlockEndToken)) { parseStack.add(0,P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_BLOCK_NODE]); } else { parseStack.add(0,P_TABLE[P_INDENTLESS_BLOCK_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } } return null; } }; P_TABLE[P_BLOCK_INDENTLESS_SEQUENCE_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { return SEQUENCE_END; } }; P_TABLE[P_FLOW_SEQUENCE_START] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); scanner.getToken(); return new SequenceStartEvent((String)env.getAnchors().get(0), (String)env.getTags().get(0), implicit,true); } }; P_TABLE[P_FLOW_SEQUENCE_ENTRY] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(!(scanner.peekToken() instanceof FlowSequenceEndToken)) { if(scanner.peekToken() instanceof KeyToken) { parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_FLOW_ENTRY_MARKER]); parseStack.add(0,P_TABLE[P_FLOW_INTERNAL_MAPPING_END]); parseStack.add(0,P_TABLE[P_FLOW_INTERNAL_VALUE]); parseStack.add(0,P_TABLE[P_FLOW_INTERNAL_CONTENT]); parseStack.add(0,P_TABLE[P_FLOW_INTERNAL_MAPPING_START]); } else { parseStack.add(0,P_TABLE[P_FLOW_SEQUENCE_ENTRY]); parseStack.add(0,P_TABLE[P_FLOW_NODE]); parseStack.add(0,P_TABLE[P_FLOW_ENTRY_MARKER]); } } return null; } }; P_TABLE[P_FLOW_SEQUENCE_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { scanner.getToken(); return SEQUENCE_END; } }; P_TABLE[P_FLOW_MAPPING_START] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final boolean implicit = env.getTags().get(0) == null || env.getTags().get(0).equals("!"); scanner.getToken(); return new MappingStartEvent((String)env.getAnchors().get(0), (String)env.getTags().get(0), implicit,true); } }; P_TABLE[P_FLOW_MAPPING_ENTRY] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(!(scanner.peekToken() instanceof FlowMappingEndToken)) { if(scanner.peekToken() instanceof KeyToken) { parseStack.add(0,P_TABLE[P_FLOW_MAPPING_ENTRY]); parseStack.add(0,P_TABLE[P_FLOW_ENTRY_MARKER]); parseStack.add(0,P_TABLE[P_FLOW_MAPPING_INTERNAL_VALUE]); parseStack.add(0,P_TABLE[P_FLOW_MAPPING_INTERNAL_CONTENT]); } else { parseStack.add(0,P_TABLE[P_FLOW_MAPPING_ENTRY]); parseStack.add(0,P_TABLE[P_FLOW_NODE]); parseStack.add(0,P_TABLE[P_FLOW_ENTRY_MARKER]); } } return null; } }; P_TABLE[P_FLOW_MAPPING_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { scanner.getToken(); return MAPPING_END; } }; P_TABLE[P_FLOW_INTERNAL_MAPPING_START] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { scanner.getToken(); return new MappingStartEvent(null,null,true,true); } }; P_TABLE[P_FLOW_INTERNAL_CONTENT] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final Token curr = scanner.peekToken(); if(!(curr instanceof ValueToken || curr instanceof FlowEntryToken || curr instanceof FlowSequenceEndToken)) { parseStack.add(0,P_TABLE[P_FLOW_NODE]); } else { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } return null; } }; P_TABLE[P_FLOW_INTERNAL_VALUE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof ValueToken) { scanner.getToken(); if(!((scanner.peekToken() instanceof FlowEntryToken) || (scanner.peekToken() instanceof FlowSequenceEndToken))) { parseStack.add(0,P_TABLE[P_FLOW_NODE]); } else { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } } else { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } return null; } }; P_TABLE[P_FLOW_INTERNAL_MAPPING_END] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { return MAPPING_END; } }; P_TABLE[P_FLOW_ENTRY_MARKER] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof FlowEntryToken) { scanner.getToken(); } return null; } }; P_TABLE[P_FLOW_NODE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof AliasToken) { parseStack.add(0,P_TABLE[P_ALIAS]); } else { parseStack.add(0,P_TABLE[P_PROPERTIES_END]); parseStack.add(0,P_TABLE[P_FLOW_CONTENT]); parseStack.add(0,P_TABLE[P_PROPERTIES]); } return null; } }; P_TABLE[P_FLOW_MAPPING_INTERNAL_CONTENT] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final Token curr = scanner.peekToken(); if(!(curr instanceof ValueToken || curr instanceof FlowEntryToken || curr instanceof FlowMappingEndToken)) { scanner.getToken(); parseStack.add(0,P_TABLE[P_FLOW_NODE]); } else { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } return null; } }; P_TABLE[P_FLOW_MAPPING_INTERNAL_VALUE] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { if(scanner.peekToken() instanceof ValueToken) { scanner.getToken(); if(!(scanner.peekToken() instanceof FlowEntryToken || scanner.peekToken() instanceof FlowMappingEndToken)) { parseStack.add(0,P_TABLE[P_FLOW_NODE]); } else { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } } else { parseStack.add(0,P_TABLE[P_EMPTY_SCALAR]); } return null; } }; P_TABLE[P_ALIAS] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { final AliasToken tok = (AliasToken)scanner.getToken(); return new AliasEvent(tok.getValue()); } }; P_TABLE[P_EMPTY_SCALAR] = new Production() { public Event produce(final List parseStack, final ProductionEnvironment env, final Scanner scanner) { return processEmptyScalar(); } }; } private static Event processEmptyScalar() { return new ScalarEvent(null,null,new boolean[]{true,false},"",(char)0); } private static Object[] processDirectives(final ProductionEnvironment env, final Scanner scanner) { while(scanner.peekToken() instanceof DirectiveToken) { final DirectiveToken tok = (DirectiveToken)scanner.getToken(); if(tok.getName().equals("YAML")) { if(env.getYamlVersion() != null) { throw new ParserException(null,"found duplicate YAML directive",null); } final int major = Integer.parseInt(tok.getValue()[0]); final int minor = Integer.parseInt(tok.getValue()[1]); if(major != 1) { throw new ParserException(null,"found incompatible YAML document (version 1.* is required)",null); } env.setYamlVersion(new int[]{major,minor}); } else if(tok.getName().equals("TAG")) { final String handle = tok.getValue()[0]; final String prefix = tok.getValue()[1]; if(env.getTagHandles().containsKey(handle)) { throw new ParserException(null,"duplicate tag handle " + handle,null); } env.getTagHandles().put(handle,prefix); } } Object[] value = new Object[2]; value[0] = env.getFinalYamlVersion(); if(!env.getTagHandles().isEmpty()) { value[1] = new HashMap(env.getTagHandles()); } final Map baseTags = ((int[])value[0])[1] == 0 ? DEFAULT_TAGS_1_0 : DEFAULT_TAGS_1_1; for(final Iterator iter = baseTags.keySet().iterator();iter.hasNext();) { final Object key = iter.next(); if(!env.getTagHandles().containsKey(key)) { env.getTagHandles().put(key,baseTags.get(key)); } } return value; } private Scanner scanner = null; private YAMLConfig cfg = null; public ParserImpl(final Scanner scanner) { this(scanner, YAML.config()); } public ParserImpl(final Scanner scanner, final YAMLConfig cfg) { this.scanner = scanner; this.cfg = cfg; } private Event currentEvent = null; public boolean checkEvent(final Class[] choices) { parseStream(); if(this.currentEvent == null) { this.currentEvent = parseStreamNext(); } if(this.currentEvent != null) { if(choices.length == 0) { return true; } for(int i=0,j=choices.length;i<j;i++) { if(choices[i].isInstance(this.currentEvent)) { return true; } } } return false; } public Event peekEvent() { parseStream(); if(this.currentEvent == null) { this.currentEvent = parseStreamNext(); } return this.currentEvent; } public Event getEvent() { parseStream(); if(this.currentEvent == null) { this.currentEvent = parseStreamNext(); } final Event value = this.currentEvent; this.currentEvent = null; return value; } private class EventIterator implements Iterator { public boolean hasNext() { return null != peekEvent(); } public Object next() { return getEvent(); } public void remove() { } } public Iterator eachEvent() { return new EventIterator(); } public Iterator iterator() { return eachEvent(); } private List parseStack = null; private ProductionEnvironment pEnv = null; public void parseStream() { if(null == parseStack) { this.parseStack = new LinkedList(); this.parseStack.add(0,P_TABLE[P_STREAM]); this.pEnv = new ProductionEnvironment(cfg); } } public Event parseStreamNext() { while(!parseStack.isEmpty()) { final Event value = ((Production)(this.parseStack.remove(0))).produce(this.parseStack,this.pEnv,this.scanner); if(null != value) { return value; } } this.pEnv = null; return null; } public static void tmain(final String[] args) throws Exception { final String filename = args[0]; System.out.println("Reading of file: \"" + filename + "\""); final StringBuffer input = new StringBuffer(); final Reader reader = new FileReader(filename); char[] buff = new char[1024]; int read = 0; while(true) { read = reader.read(buff); input.append(buff,0,read); if(read < 1024) { break; } } reader.close(); final String str = input.toString(); final long before = System.currentTimeMillis(); for(int i=0;i<1;i++) { final Parser pars = new ParserImpl(new ScannerImpl(str)); for(final Iterator iter = pars.eachEvent();iter.hasNext();iter.next()) { } } final long after = System.currentTimeMillis(); final long time = after-before; final double timeS = (after-before)/1000.0; System.out.println("Walking through the events for the file: " + filename + " took " + time + "ms, or " + timeS + " seconds"); } public static void main(final String[] args) throws Exception { final String filename = args[0]; final Parser pars = new ParserImpl(new ScannerImpl(new FileReader(filename))); for(final Iterator iter = pars.eachEvent();iter.hasNext();) { System.out.println(iter.next().getClass().getName()); } } }// ParserImpl