View Javadoc

1   /**
2    * Copyright (c) 2008-2012, 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 }