1 /** 2 * Copyright (c) 2008, SnakeYAML 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 package org.pyyaml; 15 16 import java.util.ArrayList; 17 import org.yaml.snakeyaml.DumperOptions; 18 import org.yaml.snakeyaml.DumperOptions.Version; 19 import org.yaml.snakeyaml.events.AliasEvent; 20 import org.yaml.snakeyaml.events.DocumentEndEvent; 21 import org.yaml.snakeyaml.events.DocumentStartEvent; 22 import org.yaml.snakeyaml.events.Event; 23 import org.yaml.snakeyaml.events.ImplicitTuple; 24 import org.yaml.snakeyaml.events.MappingEndEvent; 25 import org.yaml.snakeyaml.events.MappingStartEvent; 26 import org.yaml.snakeyaml.events.ScalarEvent; 27 import org.yaml.snakeyaml.events.SequenceEndEvent; 28 import org.yaml.snakeyaml.events.SequenceStartEvent; 29 import org.yaml.snakeyaml.events.StreamEndEvent; 30 import org.yaml.snakeyaml.events.StreamStartEvent; 31 import org.yaml.snakeyaml.nodes.Tag; 32 import org.yaml.snakeyaml.parser.Parser; 33 import org.yaml.snakeyaml.tokens.AliasToken; 34 import org.yaml.snakeyaml.tokens.AnchorToken; 35 import org.yaml.snakeyaml.tokens.ScalarToken; 36 import org.yaml.snakeyaml.tokens.TagToken; 37 import org.yaml.snakeyaml.tokens.Token; 38 39 public class CanonicalParser implements Parser { 40 41 private final ArrayList<Event> events; 42 private boolean parsed; 43 private final CanonicalScanner scanner; 44 CanonicalParser(String data)45 public CanonicalParser(String data) { 46 events = new ArrayList<Event>(); 47 parsed = false; 48 scanner = new CanonicalScanner(data); 49 } 50 51 // stream: STREAM-START document* STREAM-END parseStream()52 private void parseStream() { 53 scanner.getToken(Token.ID.StreamStart); 54 events.add(new StreamStartEvent(null, null)); 55 while (!scanner.checkToken(Token.ID.StreamEnd)) { 56 if (scanner.checkToken(Token.ID.Directive, Token.ID.DocumentStart)) { 57 parseDocument(); 58 } else { 59 throw new CanonicalException("document is expected, got " + scanner.tokens.get(0)); 60 } 61 } 62 scanner.getToken(Token.ID.StreamEnd); 63 events.add(new StreamEndEvent(null, null)); 64 } 65 66 // document: DIRECTIVE? DOCUMENT-START node parseDocument()67 private void parseDocument() { 68 if (scanner.checkToken(Token.ID.Directive)) { 69 scanner.getToken(Token.ID.Directive); 70 } 71 scanner.getToken(Token.ID.DocumentStart); 72 events.add(new DocumentStartEvent(null, null, true, Version.V1_1, null)); 73 parseNode(); 74 events.add(new DocumentEndEvent(null, null, true)); 75 } 76 77 // node: ALIAS | ANCHOR? TAG? (SCALAR|sequence|mapping) parseNode()78 private void parseNode() { 79 if (scanner.checkToken(Token.ID.Alias)) { 80 AliasToken token = (AliasToken) scanner.getToken(); 81 events.add(new AliasEvent(token.getValue(), null, null)); 82 } else { 83 String anchor = null; 84 if (scanner.checkToken(Token.ID.Anchor)) { 85 AnchorToken token = (AnchorToken) scanner.getToken(); 86 anchor = token.getValue(); 87 } 88 String tag = null; 89 if (scanner.checkToken(Token.ID.Tag)) { 90 TagToken token = (TagToken) scanner.getToken(); 91 tag = token.getValue().getHandle() + token.getValue().getSuffix(); 92 } 93 if (scanner.checkToken(Token.ID.Scalar)) { 94 ScalarToken token = (ScalarToken) scanner.getToken(); 95 events.add(new ScalarEvent(anchor, tag, new ImplicitTuple(false, false), token.getValue(), 96 null, null, DumperOptions.ScalarStyle.PLAIN)); 97 } else if (scanner.checkToken(Token.ID.FlowSequenceStart)) { 98 events.add(new SequenceStartEvent(anchor, Tag.SEQ.getValue(), false, null, null, 99 DumperOptions.FlowStyle.AUTO)); 100 parseSequence(); 101 } else if (scanner.checkToken(Token.ID.FlowMappingStart)) { 102 events.add(new MappingStartEvent(anchor, Tag.MAP.getValue(), false, null, null, 103 DumperOptions.FlowStyle.AUTO)); 104 parseMapping(); 105 } else { 106 throw new CanonicalException( 107 "SCALAR, '[', or '{' is expected, got " + scanner.tokens.get(0)); 108 } 109 } 110 } 111 112 // sequence: SEQUENCE-START (node (ENTRY node)*)? ENTRY? SEQUENCE-END parseSequence()113 private void parseSequence() { 114 scanner.getToken(Token.ID.FlowSequenceStart); 115 if (!scanner.checkToken(Token.ID.FlowSequenceEnd)) { 116 parseNode(); 117 while (!scanner.checkToken(Token.ID.FlowSequenceEnd)) { 118 scanner.getToken(Token.ID.FlowEntry); 119 if (!scanner.checkToken(Token.ID.FlowSequenceEnd)) { 120 parseNode(); 121 } 122 } 123 } 124 scanner.getToken(Token.ID.FlowSequenceEnd); 125 events.add(new SequenceEndEvent(null, null)); 126 } 127 128 // mapping: MAPPING-START (map_entry (ENTRY map_entry)*)? ENTRY? MAPPING-END parseMapping()129 private void parseMapping() { 130 scanner.getToken(Token.ID.FlowMappingStart); 131 if (!scanner.checkToken(Token.ID.FlowMappingEnd)) { 132 parseMapEntry(); 133 while (!scanner.checkToken(Token.ID.FlowMappingEnd)) { 134 scanner.getToken(Token.ID.FlowEntry); 135 if (!scanner.checkToken(Token.ID.FlowMappingEnd)) { 136 parseMapEntry(); 137 } 138 } 139 } 140 scanner.getToken(Token.ID.FlowMappingEnd); 141 events.add(new MappingEndEvent(null, null)); 142 } 143 144 // map_entry: KEY node VALUE node parseMapEntry()145 private void parseMapEntry() { 146 scanner.getToken(Token.ID.Key); 147 parseNode(); 148 scanner.getToken(Token.ID.Value); 149 parseNode(); 150 } 151 parse()152 public void parse() { 153 parseStream(); 154 parsed = true; 155 } 156 getEvent()157 public Event getEvent() { 158 if (!parsed) { 159 parse(); 160 } 161 return events.remove(0); 162 } 163 164 /** 165 * Check the type of the next event. 166 */ checkEvent(Event.ID choice)167 public boolean checkEvent(Event.ID choice) { 168 if (!parsed) { 169 parse(); 170 } 171 if (!events.isEmpty()) { 172 return events.get(0).is(choice); 173 } 174 return false; 175 } 176 177 /** 178 * Get the next event. 179 */ peekEvent()180 public Event peekEvent() { 181 if (!parsed) { 182 parse(); 183 } 184 if (events.isEmpty()) { 185 return null; 186 } else { 187 return events.get(0); 188 } 189 } 190 } 191