Development

Changeset 8111

You must first sign up to be able to contribute.

Changeset 8111

Show
Ignore:
Timestamp:
03/27/08 12:05:01 (1 year ago)
Author:
fabien
Message:

added alias and partial merge key support to YAML parser (closes #3214 - based on a patch from lsmith)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/1.1/lib/util/sfYamlParser.class.php

    r7923 r8111  
    2626    $lines         = array(), 
    2727    $currentLineNb = -1, 
    28     $currentLine   = ''; 
     28    $currentLine   = '', 
     29    $refs          = array(); 
    2930 
    3031  /** 
     
    6667      } 
    6768 
     69      $isRef = $isInPlace = false; 
    6870      if (preg_match('#^\-(\s+(?P<value>.+?))?\s*$#', $this->currentLine, $values)) 
    6971      { 
     72        if (isset($values['value']) && preg_match('#^&(?P<ref>\w+) *(?P<value>.*)#', $values['value'], $matches)) 
     73        { 
     74          $isRef = $matches['ref']; 
     75          $values['value'] = $matches['value']; 
     76        } 
     77 
    7078        // array 
    7179        if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) 
     
    7381          $c = $this->getRealCurrentLineNb() + 1; 
    7482          $parser = new sfYamlParser($c); 
     83          $parser->refs =& $this->refs; 
    7584          $data[] = $parser->parse($this->getNextEmbedBlock()); 
    7685        } 
     
    8392      { 
    8493        $key = sfYamlInline::parseScalar($values['key']); 
     94 
     95        if ('<<' === $key) 
     96        { 
     97          if (isset($values['value']) && '*' === substr($values['value'], 0, 1)) 
     98          { 
     99            $isInPlace = substr($values['value'], 1); 
     100            if (!array_key_exists($isInPlace, $this->refs)) 
     101            { 
     102              throw new InvalidArgumentException(sprintf('Reference "%s" does not exist on line %s.', $isInPlace, $this->currentLine)); 
     103            } 
     104          } 
     105          else 
     106          { 
     107            throw new InvalidArgumentException(sprintf('In place substitution must point to a reference on line %s.', $this->currentLine)); 
     108          } 
     109        } 
     110        else if (isset($values['value']) && preg_match('#^&(?P<ref>\w+) *(?P<value>.*)#', $values['value'], $matches)) 
     111        { 
     112          $isRef = $matches['ref']; 
     113          $values['value'] = $matches['value']; 
     114        } 
    85115 
    86116        // hash 
     
    96126            $c = $this->getRealCurrentLineNb() + 1; 
    97127            $parser = new sfYamlParser($c); 
     128            $parser->refs =& $this->refs; 
    98129            $data[$key] = $parser->parse($this->getNextEmbedBlock()); 
    99130          } 
     
    101132        else 
    102133        { 
    103           $data[$key] = $this->parseValue($values['value']); 
     134          if ($isInPlace) 
     135          { 
     136            $data = $this->refs[$isInPlace]; 
     137          } 
     138          else 
     139          { 
     140            $data[$key] = $this->parseValue($values['value']); 
     141          } 
    104142        } 
    105143      } 
     
    114152        throw new InvalidArgumentException(sprintf('Unable to parse line %d (%s).', $this->getRealCurrentLineNb(), $this->currentLine)); 
    115153      } 
     154 
     155      if ($isRef) 
     156      { 
     157        $this->refs[$isRef] = end($data); 
     158      } 
    116159    } 
    117160 
     
    227270  protected function parseValue($value) 
    228271  { 
     272    if ('*' === substr($value, 0, 1)) 
     273    { 
     274      if (false !== $pos = strpos($value, '#')) 
     275      { 
     276        $value = substr($value, 1, $pos - 2); 
     277      } 
     278      else 
     279      { 
     280        $value = substr($value, 1); 
     281      } 
     282 
     283      if (!array_key_exists($value, $this->refs)) 
     284      { 
     285        throw new InvalidArgumentException(sprintf('Reference "%s" does not exist (%s).', $value, $this->currentLine)); 
     286      } 
     287      return $this->refs[$value]; 
     288    } 
     289 
    229290    if (preg_match('/^(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?$/', $value, $matches)) 
    230291    { 
  • branches/1.1/test/unit/util/fixtures/yaml/YtsAnchorAlias.yml

    r7892 r8111  
    1 --- %YAML:1.0  
    2 test: Simple Alias Example  
    3 brief: >  
    4     If you need to refer to the same item of data twice,  
    5     you can give that item an alias.  The alias is a plain  
    6     string, starting with an ampersand.  The item may then  
    7     be referred to by the alias throughout your document  
    8     by using an asterisk before the name of the alias.  
    9     This is called an anchor.  
    10 yaml: |  
    11     - &showell Steve  
    12     - Clark  
    13     - Brian  
    14     - Oren  
    15     - *showell  
    16 python: |  
    17     [  
    18         [ 'Steve', 'Clark', 'Brian', 'Oren', 'Steve']  
    19     ]  
    20 ruby-setup: |  
    21     showell = 'Steve'  
    22 ruby: |  
    23     [ showell, 'Clark', 'Brian', 'Oren', showell ]  
    24   
    25 ---  
    26 test: Alias of a Mapping  
    27 brief: >  
    28     An alias can be used on any item of data, including  
    29     sequences, mappings, and other complex data types.  
    30 yaml: |  
    31     - &hello  
    32         Meat: pork  
    33         Starch: potato  
    34     - banana  
    35     - *hello  
    36 python: |  
    37     [  
    38         [   
    39             {'Meat': 'pork', 'Starch': 'potato'},   
    40             'banana',  
    41             {'Meat': 'pork', 'Starch': 'potato'},   
    42         ]  
    43     ]  
    44 ruby-setup: |  
    45     hello = { 'Meat' => 'pork', 'Starch' => 'potato' }  
    46 ruby: |  
    47     [   
    48       hello,   
    49       'banana',  
    50       hello  
    51     ]  
     1--- %YAML:1.0 
     2test: Simple Alias Example 
     3brief: > 
     4    If you need to refer to the same item of data twice, 
     5    you can give that item an alias.  The alias is a plain 
     6    string, starting with an ampersand.  The item may then 
     7    be referred to by the alias throughout your document 
     8    by using an asterisk before the name of the alias. 
     9    This is called an anchor. 
     10yaml: | 
     11    - &showell Steve 
     12    - Clark 
     13    - Brian 
     14    - Oren 
     15    - *showell 
     16php: | 
     17    array('Steve', 'Clark', 'Brian', 'Oren', 'Steve') 
     18 
     19--- 
     20test: Alias of a Mapping 
     21brief: > 
     22    An alias can be used on any item of data, including 
     23    sequences, mappings, and other complex data types. 
     24yaml: | 
     25    - &hello 
     26        Meat: pork 
     27        Starch: potato 
     28    - banana 
     29    - *hello 
     30php: | 
     31    array(array('Meat'=>'pork', 'Starch'=>'potato'), 'banana', array('Meat'=>'pork', 'Starch'=>'potato')) 
  • branches/1.1/test/unit/util/fixtures/yaml/YtsSpecificationExamples.yml

    r7923 r8111  
    215215---  
    216216test: Node for Sammy Sosa appears twice in this document  
    217 todo: true 
    218217spec: 2.10  
    219218yaml: |  
     
    226225      - *SS # Subsequent occurance  
    227226      - Ken Griffey  
    228 perl: |  
    229   {   
    230     'hr' => [ 'Mark McGwire', 'Sammy Sosa' ],  
    231     'rbi' => [ 'Sammy Sosa', 'Ken Griffey' ]   
    232   }  
    233 python: |  
    234    [{   
    235       'hr': [ 'Mark McGwire', 'Sammy Sosa' ],  
    236       'rbi': [ 'Sammy Sosa', 'Ken Griffey' ]  
    237    }]  
    238 ruby: |  
    239    {   
    240       'hr' =>  
    241          [ 'Mark McGwire', 'Sammy Sosa' ],  
    242       'rbi' =>  
    243          [ 'Sammy Sosa', 'Ken Griffey' ]  
    244    }  
    245 syck: | 
    246   struct test_node seq1[] = { 
    247       { T_STR, 0, "Mark McGwire" }, 
    248       { T_STR, 0, "Sammy Sosa" }, 
    249       end_node 
    250   }; 
    251   struct test_node seq2[] = { 
    252       { T_STR, 0, "Sammy Sosa" }, 
    253       { T_STR, 0, "Ken Griffey" }, 
    254       end_node 
    255   }; 
    256   struct test_node map[] = { 
    257       { T_STR, 0, "hr" }, 
    258           { T_SEQ, 0, 0, seq1 }, 
    259       { T_STR, 0, "rbi" }, 
    260           { T_SEQ, 0, 0, seq2 }, 
    261       end_node 
    262   }; 
    263   struct test_node stream[] = { 
    264       { T_MAP, 0, 0, map }, 
    265       end_node 
    266   }; 
    267   
     227php: |  
     228   array( 
     229      'hr' => 
     230         array('Mark McGwire', 'Sammy Sosa'), 
     231      'rbi' => 
     232         array('Sammy Sosa', 'Ken Griffey') 
     233   ) 
    268234---  
    269235test: Mapping between sequences  
     
    737703--- 
    738704test: Invoice 
    739 todo: true 
     705dump_skip: true 
    740706spec: 2.27 
    741707yaml: | 
     
    755721  ship-to: *id001 
    756722  product: 
    757       - sku         : BL394D 
     723      -  
     724        sku         : BL394D 
    758725        quantity    : 4 
    759726        description : Basketball 
    760727        price       : 450.00 
    761       - sku         : BL4438H 
     728      -  
     729        sku         : BL4438H 
    762730        quantity    : 1 
    763731        description : Super Hoop 
     
    769737    Backup contact is Nancy 
    770738    Billsmer @ 338-4338. 
    771 ruby-setup: | 
    772   YAML.add_domain_type( "clarkevans.com,2002", "invoice" ) { |type, val| val } 
    773   id001 = { 'given' => 'Chris', 'family' => 'Dumars', 'address' => 
    774   { 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 
    775     'state' => 'MI', 'postal' => 48046 } } 
    776 ruby: | 
    777   { 
    778      'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ), 
    779      'bill-to' => id001, 'ship-to' => id001, 'product' => 
    780        [ { 'sku' => 'BL394D', 'quantity' => 4, 
    781            'description' => 'Basketball', 'price' => 450.00 }, 
    782          { 'sku' => 'BL4438H', 'quantity' => 1, 
    783            'description' => 'Super Hoop', 'price' => 2392.00 } ], 
     739php: | 
     740  array( 
     741     'invoice' => 34843, 'date' => mktime(0, 0, 0, 1, 23, 2001), 
     742     'bill-to' =>  
     743      array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) ) 
     744     , 'ship-to' =>  
     745      array( 'given' => 'Chris', 'family' => 'Dumars', 'address' => array( 'lines' => "458 Walkman Dr.\nSuite #292\n", 'city' => 'Royal Oak', 'state' => 'MI', 'postal' => 48046 ) ) 
     746     , 'product' => 
     747       array( 
     748        array( 'sku' => 'BL394D', 'quantity' => 4, 'description' => 'Basketball', 'price' => 450.00 ), 
     749        array( 'sku' => 'BL4438H', 'quantity' => 1, 'description' => 'Super Hoop', 'price' => 2392.00 ) 
     750      ), 
    784751     'tax' => 251.42, 'total' => 4443.52, 
    785      'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" } 
     752     'comments' => "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n" 
     753  ) 
    786754--- 
    787755test: Log file 
     
    10471015---  
    10481016test: Overriding anchors  
    1049 todo: true 
    10501017yaml: |  
    10511018  anchor : &A001 This scalar has an anchor.  
     
    10541021   repeated use of this value. 
    10551022  alias : *A001 
    1056 ruby: |  
    1057   { 'anchor' => 'This scalar has an anchor.',   
    1058     'override' => "The alias node below is a repeated use of this value.\n",   
    1059     'alias' => "The alias node below is a repeated use of this value.\n" }  
    1060 syck: | 
    1061   struct test_node map[] = { 
    1062       { T_STR, 0, "anchor" }, 
    1063           { T_STR, 0, "This scalar has an anchor." }, 
    1064       { T_STR, 0, "override" }, 
    1065           { T_STR, 0, "The alias node below is a repeated use of this value.\n" }, 
    1066       { T_STR, 0, "alias" }, 
    1067           { T_STR, 0, "The alias node below is a repeated use of this value.\n" }, 
    1068       end_node 
    1069   }; 
    1070   struct test_node stream[] = { 
    1071       { T_MAP, 0, 0, map }, 
    1072       end_node 
    1073   }; 
    1074   
     1023php: |  
     1024  array( 'anchor' => 'This scalar has an anchor.', 
     1025    'override' => "The alias node below is a repeated use of this value.\n", 
     1026    'alias' => "The alias node below is a repeated use of this value.\n" ) 
    10751027---  
    10761028test: Flow and block formatting  
  • branches/1.1/test/unit/util/fixtures/yaml/index.yml

    r7981 r8111  
    22- sfTests 
    33- sfObjects 
    4 #- YtsAnchorAlias 
     4- sfMergeKey 
     5- YtsAnchorAlias 
    56- YtsBasicTests 
    67- YtsBlockMapping 
  • branches/1.1/test/unit/util/sfYamlDumperTest.php

    r7981 r8111  
    1313require_once(dirname(__FILE__).'/../../../lib/util/sfYamlDumper.class.php'); 
    1414 
    15 $t = new lime_test(136, new lime_output_color()); 
     15$t = new lime_test(138, new lime_output_color()); 
    1616 
    1717$parser = new sfYamlParser(); 
  • branches/1.1/test/unit/util/sfYamlParserTest.php

    r7981 r8111  
    44 * This file is part of the symfony package. 
    55 * (c) Fabien Potencier <fabien.potencier@symfony-project.com> 
    6  *  
     6 * 
    77 * For the full copyright and license information, please view the LICENSE 
    88 * file that was distributed with this source code. 
     
    1212require_once(dirname(__FILE__).'/../../../lib/util/sfYamlParser.class.php'); 
    1313 
    14 $t = new lime_test(135, new lime_output_color()); 
     14$t = new lime_test(138, new lime_output_color()); 
    1515 
    1616$parser = new sfYamlParser(); 

The Sensio Labs Network

Since 1998, Sensio Labs has been promoting the Open-Source software movement by providing quality web application development, training, consulting, and supporting several large Open-Source projects.