1 /** 2 * Copyright (c) 2008, http://www.snakeyaml.org 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package org.pyyaml; 17 18 import java.util.ArrayList; 19 20 import org.yaml.snakeyaml.DumperOptions.Version; 21 import org.yaml.snakeyaml.events.AliasEvent; 22 import org.yaml.snakeyaml.events.DocumentEndEvent; 23 import org.yaml.snakeyaml.events.DocumentStartEvent; 24 import org.yaml.snakeyaml.events.Event; 25 import org.yaml.snakeyaml.events.ImplicitTuple; 26 import org.yaml.snakeyaml.events.MappingEndEvent; 27 import org.yaml.snakeyaml.events.MappingStartEvent; 28 import org.yaml.snakeyaml.events.ScalarEvent; 29 import org.yaml.snakeyaml.events.SequenceEndEvent; 30 import org.yaml.snakeyaml.events.SequenceStartEvent; 31 import org.yaml.snakeyaml.events.StreamEndEvent; 32 import org.yaml.snakeyaml.events.StreamStartEvent; 33 import org.yaml.snakeyaml.parser.Parser; 34 import org.yaml.snakeyaml.tokens.AliasToken; 35 import org.yaml.snakeyaml.tokens.AnchorToken; 36 import org.yaml.snakeyaml.tokens.ScalarToken; 37 import org.yaml.snakeyaml.tokens.TagToken; 38 import org.yaml.snakeyaml.tokens.Token; 39 40 public class CanonicalParser implements Parser { 41 private ArrayList<Event> events; 42 private boolean parsed; 43 private CanonicalScanner scanner; 44 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 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 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) 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 96 .getValue(), null, null, null)); 97 } else if (scanner.checkToken(Token.ID.FlowSequenceStart)) { 98 events.add(new SequenceStartEvent(anchor, tag, false, null, null, null)); 99 parseSequence(); 100 } else if (scanner.checkToken(Token.ID.FlowMappingStart)) { 101 events.add(new MappingStartEvent(anchor, tag, false, null, null, null)); 102 parseMapping(); 103 } else { 104 throw new CanonicalException("SCALAR, '[', or '{' is expected, got " 105 + scanner.tokens.get(0)); 106 } 107 } 108 } 109 110 // sequence: SEQUENCE-START (node (ENTRY node)*)? ENTRY? SEQUENCE-END 111 private void parseSequence() { 112 scanner.getToken(Token.ID.FlowSequenceStart); 113 if (!scanner.checkToken(Token.ID.FlowSequenceEnd)) { 114 parseNode(); 115 while (!scanner.checkToken(Token.ID.FlowSequenceEnd)) { 116 scanner.getToken(Token.ID.FlowEntry); 117 if (!scanner.checkToken(Token.ID.FlowSequenceEnd)) { 118 parseNode(); 119 } 120 } 121 } 122 scanner.getToken(Token.ID.FlowSequenceEnd); 123 events.add(new SequenceEndEvent(null, null)); 124 } 125 126 // mapping: MAPPING-START (map_entry (ENTRY map_entry)*)? ENTRY? MAPPING-END 127 private void parseMapping() { 128 scanner.getToken(Token.ID.FlowMappingStart); 129 if (!scanner.checkToken(Token.ID.FlowMappingEnd)) { 130 parseMapEntry(); 131 while (!scanner.checkToken(Token.ID.FlowMappingEnd)) { 132 scanner.getToken(Token.ID.FlowEntry); 133 if (!scanner.checkToken(Token.ID.FlowMappingEnd)) { 134 parseMapEntry(); 135 } 136 } 137 } 138 scanner.getToken(Token.ID.FlowMappingEnd); 139 events.add(new MappingEndEvent(null, null)); 140 } 141 142 // map_entry: KEY node VALUE node 143 private void parseMapEntry() { 144 scanner.getToken(Token.ID.Key); 145 parseNode(); 146 scanner.getToken(Token.ID.Value); 147 parseNode(); 148 } 149 150 public void parse() { 151 parseStream(); 152 parsed = true; 153 } 154 155 public Event getEvent() { 156 if (!parsed) { 157 parse(); 158 } 159 return events.remove(0); 160 } 161 162 /** 163 * Check the type of the next event. 164 */ 165 public boolean checkEvent(Event.ID choice) { 166 if (!parsed) { 167 parse(); 168 } 169 if (!events.isEmpty()) { 170 if (events.get(0).is(choice)) { 171 return true; 172 } 173 } 174 return false; 175 } 176 177 /** 178 * Get the next event. 179 */ 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