• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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