Ignore:
Timestamp:
02/17/06 17:39:52 (8 years ago)
Author:
xi
Message:

Working on the scanner.

File:
1 edited

Legend:

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

    r46 r47  
    2424    # key: "valu\?e" 
    2525    #            ^ 
    26     pass 
     26    def __init__(self, context=None, context_marker=None, 
     27            problem=None, problem_marker=None, description=None): 
     28        self.context = context 
     29        self.context_marker = context_marker 
     30        self.problem = problem 
     31        self.problem_marker = problem_marker 
     32        self.description = description 
     33 
     34    def __str__(self): 
     35        lines = [] 
     36        for (place, marker) in [(self.context, self.context_marker), 
     37                                (self.problem, self.problem_marker)]: 
     38            if place is not None: 
     39                lines.append(place) 
     40                if marker is not None: 
     41                    lines.append(str(marker)) 
     42        if self.description is not None: 
     43            lines.append(self.description) 
     44        return '\n'.join(lines) 
    2745 
    2846class SimpleKey: 
     
    140158        # and decrease the current indentation level. 
    141159        self.unwind_indent(self.reader.column) 
    142  
    143         #print 
    144         #print self.reader.get_marker().get_snippet() 
    145160 
    146161        # Peek the next character. 
     
    257272                    or self.reader.index-key.index > 1024: 
    258273                if key.required: 
    259                     self.fail("simple key is required") 
     274                    raise ScannerError("while scanning a simple key", key.marker, 
     275                            "could not found expected ':'", self.reader.get_marker()) 
    260276                del self.possible_simple_keys[level] 
    261277 
     
    267283        # Check if a simple key is required at the current position. 
    268284        required = not self.flow_level and self.indent == self.reader.column 
     285 
     286        # A simple key is required only if it is the first token in the current 
     287        # line. Therefore it is always allowed. 
     288        assert self.allow_simple_key or not required 
    269289 
    270290        # The next token might be a simple key. Let's save it's number and 
     
    281301            self.possible_simple_keys[self.flow_level] = key 
    282302 
    283         # A simple key is required at the current position. 
    284         elif required: 
    285             self.fail("simple key is required") 
    286  
    287303    def remove_possible_simple_key(self): 
    288304        # Remove the saved possible key position at the current flow level. 
    289305        if self.flow_level in self.possible_simple_keys: 
    290306            key = self.possible_simple_keys[self.flow_level] 
    291             if key.required: 
    292                 self.fail("simple key is required") 
     307             
     308            # I don't think it's possible, but I could be wrong. 
     309            assert not key.required 
     310            #if key.required: 
     311            #    raise ScannerError("while scanning a simple key", key.marker, 
     312            #            "could not found expected ':'", self.reader.get_marker()) 
    293313 
    294314    # Indentation functions. 
     
    297317 
    298318        # In flow context, tokens should respect indentation. 
     319        # Actually the condition should be `self.indent >= column` according to 
     320        # the spec. But this condition will prohibit intuitively correct 
     321        # constructions such as 
     322        # key : { 
     323        # } 
    299324        if self.flow_level and self.indent > column: 
    300             self.fail("invalid intendation in the flow context") 
     325            raise ScannerError(None, None, 
     326                    "invalid intendation or unclosed '[' or '{'", 
     327                    self.reader.get_marker()) 
    301328 
    302329        # In block context, we may need to issue the BLOCK-END tokens. 
     
    329356         
    330357        # Add END. 
    331         self.tokens.append(EndToken(marker, marker)) 
     358        self.tokens.append(StreamEndToken(marker, marker)) 
    332359 
    333360        # The reader is ended. 
     
    344371 
    345372        # Scan and add DIRECTIVE. 
    346         self.scan_directive() 
     373        self.tokens.append(self.scan_directive()) 
    347374 
    348375    def fetch_document_start(self): 
     
    421448            # Are we allowed to start a new entry? 
    422449            if not self.allow_simple_key: 
    423                 self.fail("Cannot start a new entry here") 
     450                raise ScannerError(None, None, 
     451                        "sequence entries are not allowed here", 
     452                        self.reader.get_marker()) 
    424453 
    425454            # We may need to add BLOCK-SEQUENCE-START. 
     
    447476            # Are we allowed to start a key (not nessesary a simple)? 
    448477            if not self.allow_simple_key: 
    449                 self.fail("Cannot start a new key here") 
     478                raise ScannerError(None, None, 
     479                        "mapping keys are not allowed here", 
     480                        self.reader.get_marker()) 
    450481 
    451482            # We may need to add BLOCK-MAPPING-START. 
     
    490521        else: 
    491522             
     523            # Block context needs additional checks. 
     524            # (Do we really need them? They will be catched by the parser 
     525            # anyway.) 
     526            if not self.flow_level: 
     527 
     528                # We are allowed to start a complex value if and only if 
     529                # we can start a simple key. 
     530                if not self.allow_simple_key: 
     531                    raise ScannerError(None, None, 
     532                            "mapping values are not allowed here", 
     533                            self.reader.get_marker()) 
     534 
    492535            # Simple keys are allowed after ':' in the block context. 
    493536            self.allow_simple_key = not self.flow_level 
     
    511554 
    512555        # Scan and add ALIAS. 
    513         self.scan_anchor(AliasToken) 
     556        self.tokens.append(self.scan_anchor(AliasToken)) 
    514557 
    515558    def fetch_anchor(self): 
     
    522565 
    523566        # Scan and add ANCHOR. 
    524         self.scan_anchor(AnchorToken) 
     567        self.tokens.append(self.scan_anchor(AnchorToken)) 
    525568 
    526569    def fetch_tag(self): 
     
    533576 
    534577        # Scan and add TAG. 
    535         self.scan_tag() 
     578        self.tokens.append(self.scan_tag()) 
    536579 
    537580    def fetch_literal(self): 
     
    550593 
    551594        # Scan and add SCALAR. 
    552         self.scan_block_scalar(folded) 
     595        self.tokens.append(self.scan_block_scalar(folded)) 
    553596 
    554597    def fetch_single(self): 
     
    567610 
    568611        # Scan and add SCALAR. 
    569         self.scan_flow_scalar(double) 
     612        self.tokens.append(self.scan_flow_scalar(double)) 
    570613 
    571614    def fetch_plain(self): 
     
    580623 
    581624        # Scan and add SCALAR. May change `allow_simple_key`. 
    582         self.scan_plain() 
     625        self.tokens.append(self.scan_plain()) 
    583626 
    584627    # Checkers. 
     
    646689 
    647690    def scan_to_next_token(self): 
     691        # We ignore spaces, line breaks and comments. 
     692        # If we find a line break in the block context, we set the flag 
     693        # `allow_simple_key` on. 
    648694        found = False 
    649695        while not found: 
     
    651697                self.reader.forward() 
    652698            if self.reader.peek() == u'#': 
    653                 while self.reader.peek() not in u'\r\n': 
     699                while self.reader.peek() not in u'\0\r\n\x85\u2028\u2029': 
    654700                    self.reader.forward() 
    655             if self.reader.peek() in u'\r\n': 
    656                 self.reader.forward() 
     701            if self.scan_line_break(): 
    657702                if not self.flow_level: 
    658703                    self.allow_simple_key = True 
     
    663708        marker = self.reader.get_marker() 
    664709        if self.reader.peek(5) == u'%YAML ': 
    665             self.tokens.append(YAMLDirectiveToken(1, 1, marker, marker)) 
     710            token = YAMLDirectiveToken(1, 1, marker, marker) 
    666711        elif self.reader.peek(4) == u'%TAG ': 
    667             self.tokens.append(TagDirectiveToken(marker, marker)) 
     712            token = TagDirectiveToken(marker, marker) 
    668713        else: 
    669             self.tokens.append(ReservedDirectiveToken('', marker, marker)) 
     714            token = ReservedDirectiveToken('', marker, marker) 
    670715        while self.reader.peek() not in u'\0\r\n': 
    671716            self.reader.forward() 
    672717        self.reader.forward() 
     718        return token 
    673719 
    674720    def scan_anchor(self, TokenClass): 
     
    677723            self.reader.forward() 
    678724        end_marker = self.reader.get_marker() 
    679         self.tokens.append(TokenClass('', start_marker, end_marker)) 
     725        return TokenClass('', start_marker, end_marker) 
    680726 
    681727    def scan_tag(self): 
     
    684730            self.reader.forward() 
    685731        end_marker = self.reader.get_marker() 
    686         self.tokens.append(TagToken('', start_marker, end_marker)) 
     732        return TagToken('', start_marker, end_marker) 
    687733 
    688734    def scan_block_scalar(self, folded): 
     
    702748            if count < indent and self.reader.peek() not in u'#\r\n\x85\u2028\u2029': 
    703749                break 
    704         self.tokens.append(ScalarToken('', False, start_marker, start_marker)) 
     750        return ScalarToken('', False, start_marker, start_marker) 
    705751 
    706752    def scan_flow_scalar(self, double): 
     
    716762                self.reader.forward(1) 
    717763        self.reader.forward(1) 
    718         self.tokens.append(ScalarToken('', False, marker, marker)) 
     764        return ScalarToken('', False, marker, marker) 
    719765 
    720766    def scan_plain(self): 
     
    748794                break 
    749795            space = True 
    750         self.tokens.append(ScalarToken('', True, marker, marker)) 
     796        return ScalarToken('', True, marker, marker) 
     797 
     798    def scan_line_break(self): 
     799        # Transforms: 
     800        #   '\r\n'      :   '\n' 
     801        #   '\r'        :   '\n' 
     802        #   '\n'        :   '\n' 
     803        #   '\x85'      :   '\n' 
     804        #   '\u2028'    :   '\u2028' 
     805        #   '\u2029     :   '\u2029' 
     806        #   default     :   '' 
     807        ch = self.reader.peek() 
     808        if ch in u'\r\n\x85': 
     809            if self.reader.peek(2) == u'\r\n': 
     810                self.forward(2) 
     811            else: 
     812                self.reader.forward() 
     813            return u'\n' 
     814        elif ch in u'\u2028\u2029': 
     815            self.reader.forward() 
     816            return ch 
     817        return u'' 
    751818 
    752819    def invalid_token(self): 
    753820        self.fail("invalid token") 
    754  
    755     def fail(self, message): 
    756         raise ScannerError(message) 
    757821 
    758822#try: 
Note: See TracChangeset for help on using the changeset viewer.