Home | History | Annotate | Download | only in pyyaml
      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