Ignore:
Timestamp:
02/19/06 17:17:28 (8 years ago)
Author:
xi
Message:

Parser is done. Add iterator interfaces for Scanner and Parser.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/pyyaml3000/lib/yaml/scanner.py

    r48 r51  
    1515 
    1616class ScannerError(YAMLError): 
    17     # TODO: 
    1817    # ScannerError: while reading a quoted string 
    1918    #         in '...', line 5, column 10: 
     
    2423    # key: "valu\?e" 
    2524    #            ^ 
     25 
    2626    def __init__(self, context=None, context_marker=None, 
    2727            problem=None, problem_marker=None): 
     
    4242 
    4343class SimpleKey: 
     44    # See below simple keys treatment. 
     45 
    4446    def __init__(self, token_number, required, index, line, column, marker): 
    4547        self.token_number = token_number 
     
    115117        self.possible_simple_keys = {} 
    116118 
    117     # Two public methods. 
    118  
    119     def peek_token(self): 
    120         """Get the current token.""" 
     119    # Public methods. 
     120 
     121    def check(self, *choices): 
     122        # Check if the next token is one of the given types. 
     123        while self.need_more_tokens(): 
     124            self.fetch_more_tokens() 
     125        if self.tokens: 
     126            for choice in choices: 
     127                if isinstance(self.tokens[0], choice): 
     128                    return True 
     129        return False 
     130 
     131    def peek(self): 
     132        # Return the next token, but do not delete if from the queue. 
    121133        while self.need_more_tokens(): 
    122134            self.fetch_more_tokens() 
     
    124136            return self.tokens[0] 
    125137 
    126     def get_token(self): 
    127         "Get the current token and remove it from the list of pending tokens.""" 
     138    def get(self): 
     139        # Return the next token. 
    128140        while self.need_more_tokens(): 
    129141            self.fetch_more_tokens() 
     
    131143            self.tokens_taken += 1 
    132144            return self.tokens.pop(0) 
     145 
     146    def __iter__(self): 
     147        # Iterator protocol. 
     148        while self.need_more_tokens(): 
     149            self.fetch_more_tokens() 
     150        while self.tokens: 
     151            self.tokens_taken += 1 
     152            yield self.tokens.pop(0) 
     153            while self.need_more_tokens(): 
     154                self.fetch_more_tokens() 
    133155 
    134156    # Private methods. 
     
    164186            return self.fetch_stream_end() 
    165187 
    166         # Is it the byte order mark? 
    167         if ch == u'\uFEFF': 
    168             return self.fetch_bom() 
    169  
    170188        # Is it a directive? 
    171189        if ch == u'%' and self.check_directive(): 
     
    198216            return self.fetch_flow_mapping_end() 
    199217 
    200         # Is it the entry indicator? 
    201         if ch in u'-,' and self.check_entry(): 
    202             return self.fetch_entry() 
     218        # Is it the flow entry indicator? 
     219        if ch in u',': 
     220            return self.fetch_flow_entry() 
     221 
     222        # Is it the block entry indicator? 
     223        if ch in u'-' and self.check_block_entry(): 
     224            return self.fetch_block_entry() 
    203225 
    204226        # Is it the key indicator? 
     
    365387        self.done = True 
    366388 
    367     def fetch_bom(self): 
    368         # We consider the BOM marker as a DOCUMENT-END indicator unless it's 
    369         # the first character in the stream. It's a reasonable approximation 
    370         # of the specification requirements. We can follow the specification 
    371         # literally, but it will require a new token class. Probably later. 
    372  
    373         # We ignore BOM if it is the first character in the stream. 
    374         if self.reader.index == 0: 
    375             slef.reader.forward() 
    376  
    377         # Otherwise we issue DOCUMENT-END. 
    378         else: 
    379  
    380             # Set the current intendation to -1. 
    381             self.unwind_indent(-1) 
    382  
    383             # Reset simple keys. Note that there could not be a block 
    384             # collection after BOM. 
    385             self.remove_possible_simple_key() 
    386             self.allow_simple_key = False 
    387  
    388             # Add DOCUMENT-END. 
    389             start_marker = self.reader.get_marker() 
    390             self.reader.forward() 
    391             end_marker = self.reader.get_marker() 
    392             self.tokens.append(DocumentEndToken(start_marker, end_marker)) 
    393  
    394389    def fetch_directive(self): 
    395390         
     
    472467        self.tokens.append(TokenClass(start_marker, end_marker)) 
    473468 
    474     def fetch_entry(self): 
     469    def fetch_flow_entry(self): 
     470 
     471        # Simple keys are allowed after ','. 
     472        self.allow_simple_key = True 
     473 
     474        # Reset possible simple key on the current level. 
     475        self.remove_possible_simple_key() 
     476 
     477        # Add FLOW-ENTRY. 
     478        start_marker = self.reader.get_marker() 
     479        self.reader.forward() 
     480        end_marker = self.reader.get_marker() 
     481        self.tokens.append(FlowEntryToken(start_marker, end_marker)) 
     482 
     483    def fetch_block_entry(self): 
    475484 
    476485        # Block context needs additional checks. 
     
    488497                self.tokens.append(BlockSequenceStartToken(marker, marker)) 
    489498 
    490         # Simple keys are allowed after '-' and ','. 
     499        # It's an error for the block entry to occur in the flow context, 
     500        # but we let the parser detect this. 
     501        else: 
     502            pass 
     503 
     504        # Simple keys are allowed after '-'. 
    491505        self.allow_simple_key = True 
    492506 
     
    494508        self.remove_possible_simple_key() 
    495509 
    496         # Add ENTRY. 
     510        # Add BLOCK-ENTRY. 
    497511        start_marker = self.reader.get_marker() 
    498512        self.reader.forward() 
    499513        end_marker = self.reader.get_marker() 
    500         self.tokens.append(EntryToken(start_marker, end_marker)) 
     514        self.tokens.append(BlockEntryToken(start_marker, end_marker)) 
    501515 
    502516    def fetch_key(self): 
     
    682696                return True 
    683697 
    684     def check_entry(self): 
    685  
    686         # ENTRY(flow context):      ',' 
    687         if self.flow_level: 
    688             return self.reader.peek() == u',' 
    689  
    690         # ENTRY(block context):     '-' (' '|'\n') 
    691         else: 
    692             return self.reader.peek() == u'-'   \ 
    693                     and self.reader.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 
     698    def check_block_entry(self): 
     699 
     700        # BLOCK-ENTRY:      '-' (' '|'\n') 
     701        return self.reader.peek(1) in u'\0 \t\r\n\x85\u2028\u2029' 
    694702 
    695703    def check_key(self): 
     
    738746        # If we find a line break in the block context, we set the flag 
    739747        # `allow_simple_key` on. 
     748        # The byte order mark is stripped if it's the first character in the 
     749        # stream. We do not yet support BOM inside the stream as the 
     750        # specification requires. Any such mark will be considered as a part 
     751        # of the document. 
     752        if self.reader.index == 0 and self.reader.peek() == u'\uFEFF': 
     753            self.reader.forward() 
    740754        found = False 
    741755        while not found: 
     
    981995                # 
    982996                # This is the folding according to the specification: 
    983                 # 
    984                 #if folded and line_break == u'\n'   \ 
    985                 #        and leading_non_space and self.reader.peek() not in u' \t': 
    986                 #    if not breaks: 
    987                 #        chunks.append(u' ') 
    988                 #else: 
    989                 #    chunks.append(line_break) 
    990                 # 
     997                 
     998                if folded and line_break == u'\n'   \ 
     999                        and leading_non_space and self.reader.peek() not in u' \t': 
     1000                    if not breaks: 
     1001                        chunks.append(u' ') 
     1002                else: 
     1003                    chunks.append(line_break) 
     1004                 
    9911005                # This is Clark Evans's interpretation (also in the spec 
    9921006                # examples): 
    9931007                # 
    994                 if folded and line_break == u'\n': 
    995                     if not breaks: 
    996                         if self.reader.peek() not in ' \t': 
    997                             chunks.append(u' ') 
    998                         else: 
    999                             chunks.append(line_break) 
    1000                 else: 
    1001                     chunks.append(line_break) 
     1008                #if folded and line_break == u'\n': 
     1009                #    if not breaks: 
     1010                #        if self.reader.peek() not in ' \t': 
     1011                #            chunks.append(u' ') 
     1012                #        else: 
     1013                #            chunks.append(line_break) 
     1014                #else: 
     1015                #    chunks.append(line_break) 
    10021016            else: 
    10031017                break 
Note: See TracChangeset for help on using the changeset viewer.