Changeset 55


Ignore:
Timestamp:
02/22/06 19:18:34 (8 years ago)
Author:
xi
Message:

Working on Constructor.

Location:
branches/pyyaml3000
Files:
19 added
8 edited

Legend:

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

    r53 r55  
    66from composer import Composer 
    77from resolver import Resolver 
     8from constructor import Constructor 
    89 
    910from tokens import * 
    1011from events import * 
    11  
    12 def scan(data, Reader=Reader, Scanner=Scanner): 
    13     reader = Reader(data) 
    14     scanner = Scanner(reader) 
    15     return iter(scanner) 
     12from nodes import * 
    1613 
    1714def parse(data, Reader=Reader, Scanner=Scanner, Parser=Parser): 
     
    1916    scanner = Scanner(reader) 
    2017    parser = Parser(scanner) 
    21     return iter(parser) 
     18    return parser 
    2219 
    23 def compose(data, Reader=Reader, Scanner=Scanner, Parser=Parser, 
    24         Composer=Composer): 
    25     reader = Reader(data) 
    26     scanner = Scanner(reader) 
    27     parser = Parser(scanner) 
    28     composer = Composer(parser) 
    29     return iter(composer) 
    30  
    31 def compose_document(*args, **kwds): 
    32     try: 
    33         return compose(*args, **kwds).next() 
    34     except StopIteration: 
    35         return None 
    36  
    37 def resolve(data, Reader=Reader, Scanner=Scanner, Parser=Parser, 
    38         Composer=Composer, Resolver=Resolver): 
     20def load(data, Reader=Reader, Scanner=Scanner, Parser=Parser, 
     21        Composer=Composer, Resolver=Resolver, Constructor=Constructor): 
    3922    reader = Reader(data) 
    4023    scanner = Scanner(reader) 
     
    4225    composer = Composer(parser) 
    4326    resolver = Resolver(composer) 
    44     return iter(resolver) 
     27    constructor = Constructor(resolver) 
     28    return constructor 
    4529 
    46 def resolve_document(*args, **kwds): 
    47     try: 
    48         return resolve(*args, **kwds).next() 
    49     except StopIteration: 
    50         return None 
     30def load_document(*args, **kwds): 
     31    for document in load(*args, **kwds): 
     32        return document 
    5133 
  • branches/pyyaml3000/lib/yaml/composer.py

    r53 r55  
    8282    def compose_mapping_node(self): 
    8383        start_event = self.parser.get() 
    84         value = [] 
     84        value = {} 
    8585        while not self.parser.check(CollectionEndEvent): 
     86            key_event = self.parser.peek() 
    8687            item_key = self.compose_node() 
    8788            item_value = self.compose_node() 
    88             value.append((item_key, item_value)) 
     89            if item_key in value: 
     90                raise ComposerError("while composing a mapping", start_event.start_marker, 
     91                        "found duplicate key", key_event.start_marker) 
     92            value[item_key] = item_value 
    8993        end_event = self.parser.get() 
    9094        return MappingNode(start_event.tag, value, 
  • branches/pyyaml3000/lib/yaml/nodes.py

    r53 r55  
    2323 
    2424class ScalarNode(Node): 
    25     pass 
     25    id = 'scalar' 
    2626 
    2727class CollectionNode(Node): 
     
    2929 
    3030class SequenceNode(CollectionNode): 
    31     pass 
     31    id = 'sequence' 
    3232 
    3333class MappingNode(CollectionNode): 
    34     pass 
     34    id = 'mapping' 
    3535 
  • branches/pyyaml3000/lib/yaml/parser.py

    r53 r55  
    7272    # Since writing an LL(1) parser is a straightforward task, we do not give 
    7373    # many comments here. 
    74     # Note that we use Python generators. If you rewrite the parser to another 
     74    # Note that we use Python generators. If you rewrite the parser in another 
    7575    # language, you may replace all 'yield'-s with event handler calls. 
    7676 
  • branches/pyyaml3000/lib/yaml/resolver.py

    r54 r55  
    11 
    22from nodes import * 
     3 
     4import re 
    35 
    46class BaseResolver: 
     
    4042            self.resolve_sequence(path, node) 
    4143            for index in range(len(node.value)): 
    42                 self.resolve_node(path+[node, index], node.value[index]) 
     44                self.resolve_node(path+[(node, index)], node.value[index]) 
    4345        elif isinstance(node, MappingNode): 
    4446            self.resolve_mapping(path, node) 
    45             for key, value in node.value: 
     47            for key in node.value: 
    4648                self.resolve_node(path+[node, None], key) 
    47                 self.resolve_node(path+[node, key], value) 
     49                self.resolve_node(path+[node, key], node.value[key]) 
    4850 
    4951    def resolve_scalar(self, path, node): 
     
    6264 
    6365    def detect_scalar(self, value): 
    64         return None 
     66        if value == u'': 
     67            detectors = self.yaml_detectors.get(u'', []) 
     68        else: 
     69            detectors = self.yaml_detectors.get(value[0], []) 
     70        detectors += self.yaml_detectors.get(None, []) 
     71        for tag, regexp in detectors: 
     72            if regexp.match(value): 
     73                return tag 
     74 
     75    def add_detector(cls, tag, regexp, first): 
     76        if not 'yaml_detectors' in cls.__dict__: 
     77            cls.yaml_detectors = cls.yaml_detectors.copy() 
     78        for ch in first: 
     79            cls.yaml_detectors.setdefault(ch, []).append((tag, regexp)) 
     80    add_detector = classmethod(add_detector) 
     81 
     82    yaml_detectors = {} 
    6583 
    6684class Resolver(BaseResolver): 
    6785    pass 
    6886 
     87Resolver.add_detector( 
     88        u'tag:yaml.org,2002:bool', 
     89        re.compile(ur'''^(?:y|Y|yes|Yes|YES|n|N|no|No|NO 
     90                    |true|True|TRUE|false|False|FALSE 
     91                    |on|On|ON|off|Off|OFF)$''', re.X), 
     92        list(u'yYnNtTfFoO')) 
     93 
     94Resolver.add_detector( 
     95        u'tag:yaml.org,2002:float', 
     96        re.compile(ur'''^(?:[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*(?:[eE][-+][0-9]+)? 
     97                    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]* 
     98                    |[-+]?\.(?:inf|Inf|INF) 
     99                    |\.(?:nan|NaN|NAN))$''', re.X), 
     100        list(u'-+0123456789.')) 
     101 
     102Resolver.add_detector( 
     103        u'tag:yaml.org,2002:int', 
     104        re.compile(ur'''^(?:[-+]?0b[0-1_]+ 
     105                    |[-+]?0[0-7_]+ 
     106                    |[-+]?(?:0|[1-9][0-9_]*) 
     107                    |[-+]?0x[0-9a-fA-F_]+ 
     108                    |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$''', re.X), 
     109        list(u'-+0123456789')) 
     110 
     111Resolver.add_detector( 
     112        u'tag:yaml.org,2002:merge', 
     113        re.compile(ur'^(?:<<)$'), 
     114        ['<']) 
     115 
     116Resolver.add_detector( 
     117        u'tag:yaml.org,2002:null', 
     118        re.compile(ur'''^(?: ~ 
     119                    |null|Null|NULL 
     120                    | )$''', re.X), 
     121        [u'~', u'n', u'N', u'']) 
     122 
     123Resolver.add_detector( 
     124        u'tag:yaml.org,2002:timestamp', 
     125        re.compile(ur'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] 
     126                    |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]? 
     127                     (?:[Tt]|[ \t]+)[0-9][0-9]? 
     128                     :[0-9][0-9] :[0-9][0-9] (?:\.[0-9]*)? 
     129                     (?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$''', re.X), 
     130        list(u'0123456789')) 
     131 
     132Resolver.add_detector( 
     133        u'tag:yaml.org,2002:value', 
     134        re.compile(ur'^(?:=)$'), 
     135        ['=']) 
     136 
  • branches/pyyaml3000/lib/yaml/scanner.py

    r52 r55  
    11 
    2 # Tokens: 
    3 # YAML-DIRECTIVE(major_version, minor_version), TAG-DIRECTIVE(handle, prefix) 
    4 # RESERVED-DIRECTIVE(name) 
    5 # DOCUMENT-START, DOCUMENT-END 
    6 # BLOCK-SEQUENCE-START, BLOCK-MAPPING-START, BLOCK-END 
    7 # FLOW-SEQUENCE-START, FLOW-MAPPING-START, FLOW-SEQUENCE-END, FLOW-MAPPING-END 
    8 # ENTRY, KEY, VALUE 
    9 # ALIAS(name), ANCHOR(name), TAG(value), SCALAR(value, plain) 
     2# Scanner produces tokens of the following types: 
     3# DIRECTIVE(name, value) 
     4# DOCUMENT-START 
     5# DOCUMENT-END 
     6# STREAM-END 
     7# BLOCK-SEQUENCE-START 
     8# BLOCK-MAPPING-START 
     9# BLOCK-END 
     10# FLOW-SEQUENCE-START 
     11# FLOW-MAPPING-START 
     12# FLOW-SEQUENCE-END 
     13# FLOW-MAPPING-END 
     14# BLOCK-ENTRY 
     15# FLOW-ENTRY 
     16# KEY 
     17# VALUE 
     18# ALIAS(value) 
     19# ANCHOR(value) 
     20# TAG(value) 
     21# SCALAR(value, plain) 
    1022 
    1123__all__ = ['Scanner', 'ScannerError'] 
  • branches/pyyaml3000/tests/test_structure.py

    r54 r55  
    77from yaml.composer import * 
    88from yaml.resolver import * 
     9from yaml.constructor import * 
    910from yaml.nodes import * 
    1011 
     
    138139        elif isinstance(node1, MappingNode): 
    139140            self.failUnlessEqual(len(node1.value), len(node2.value)) 
    140             for (key1, value1), (key2, value2) in zip(node1.value, node2.value): 
     141            items1 = node1.value.items() 
     142            items1.sort(lambda (k1,v1), (k2,v2): cmp((k1.tag,k1.value,v1.tag,v1.value), 
     143                                                    (k2.tag,k2.value,v2.tag,v2.value))) 
     144            items2 = node2.value.items() 
     145            items2.sort(lambda (k1,v1), (k2,v2): cmp((k1.tag,k1.value,v1.tag,v1.value), 
     146                                                    (k2.tag,k2.value,v2.tag,v2.value))) 
     147            for (key1, value1), (key2, value2) in zip(items1, items2): 
    141148                self._compare(key1, key2) 
    142149                self._compare(value1, value2) 
    143150 
    144151TestResolver.add_tests('testResolver', '.data', '.canonical') 
     152 
     153class MyConstructor(Constructor): 
     154 
     155    def construct_sequence(self, node): 
     156        return tuple(Constructor.construct_sequence(self, node)) 
     157 
     158    def construct_mapping(self, node): 
     159        pairs = self.construct_pairs(node) 
     160        pairs.sort() 
     161        return pairs 
     162 
     163class TestConstructor(test_appliance.TestAppliance): 
     164 
     165    def _testConstructor(self, test_name, data_filename, canonical_filename): 
     166        natives1 = None 
     167        natives2 = None 
     168        try: 
     169            constructor1 = MyConstructor(Resolver(Composer(Parser(Scanner(Reader(file(data_filename, 'rb'))))))) 
     170            natives1 = list(iter(constructor1)) 
     171            canonical = test_appliance.CanonicalParser(file(canonical_filename, 'rb').read()) 
     172            canonical.parse() 
     173            constructor2 = MyConstructor(Resolver(Composer(canonical))) 
     174            natives2 = list(iter(constructor2)) 
     175            self.failUnlessEqual(natives1, natives2) 
     176        except: 
     177            print 
     178            print "DATA1:" 
     179            print file(data_filename, 'rb').read() 
     180            print "DATA2:" 
     181            print file(canonical_filename, 'rb').read() 
     182            print "NATIVES1:", natives1 
     183            print "NATIVES2:", natives2 
     184            raise 
     185 
     186TestConstructor.add_tests('testConstructor', '.data', '.canonical') 
    145187 
    146188class TestParserOnCanonical(test_appliance.TestAppliance): 
  • branches/pyyaml3000/tests/test_yaml.py

    r52 r55  
    88from test_structure import * 
    99from test_errors import * 
     10from test_detector import * 
    1011from test_syck import * 
    1112 
Note: See TracChangeset for help on using the changeset viewer.