1
0
mirror of synced 2024-12-13 14:56:01 +03:00
doctrine2/lib/vendor/addendum/annotations/annotation_parser.php
2009-06-15 18:25:47 +00:00

353 lines
9.2 KiB
PHP
Executable File

<?php
/**
* Addendum PHP Reflection Annotations
* http://code.google.com/p/addendum/
*
* Copyright (C) 2006 Jan "johno Suchal <johno@jsmf.net>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**/
class CompositeMatcher {
protected $matchers = array();
private $wasConstructed = false;
public function add($matcher) {
$this->matchers[] = $matcher;
}
public function matches($string, &$value) {
if(!$this->wasConstructed) {
$this->build();
$this->wasConstructed = true;
}
return $this->match($string, $value);
}
protected function build() {}
}
class ParallelMatcher extends CompositeMatcher {
protected function match($string, &$value) {
$maxLength = false;
$result = null;
foreach($this->matchers as $matcher) {
$length = $matcher->matches($string, $subvalue);
if($maxLength === false || $length > $maxLength) {
$maxLength = $length;
$result = $subvalue;
}
}
$value = $this->process($result);
return $maxLength;
}
protected function process($value) {
return $value;
}
}
class SerialMatcher extends CompositeMatcher {
protected function match($string, &$value) {
$results = array();
$total_length = 0;
foreach($this->matchers as $matcher) {
if(($length = $matcher->matches($string, $result)) === false) return false;
$total_length += $length;
$results[] = $result;
$string = substr($string, $length);
}
$value = $this->process($results);
return $total_length;
}
protected function process($results) {
return implode('', $results);
}
}
class SimpleSerialMatcher extends SerialMatcher {
private $return_part_index;
public function __construct($return_part_index = 0) {
$this->return_part_index = $return_part_index;
}
public function process($parts) {
return $parts[$this->return_part_index];
}
}
class RegexMatcher {
private $regex;
public function __construct($regex) {
$this->regex = $regex;
}
public function matches($string, &$value) {
if(preg_match("/^{$this->regex}/", $string, $matches)) {
$value = $this->process($matches);
return strlen($matches[0]);
}
$value = false;
return false;
}
protected function process($matches) {
return $matches[0];
}
}
class AnnotationsMatcher {
public function matches($string, &$annotations) {
$annotations = array();
$annotation_matcher = new AnnotationMatcher;
while(true) {
if(preg_match('/\s(?=@)/', $string, $matches, PREG_OFFSET_CAPTURE)) {
$offset = $matches[0][1] + 1;
$string = substr($string, $offset);
} else {
return; // no more annotations
}
if(($length = $annotation_matcher->matches($string, $data)) !== false) {
$string = substr($string, $length);
list($name, $params) = $data;
$annotations[$name][] = $params;
}
}
}
}
class AnnotationMatcher extends SerialMatcher {
protected function build() {
$this->add(new RegexMatcher('@'));
$this->add(new RegexMatcher('[A-Z][a-zA-Z0-9_]+'));
$this->add(new AnnotationParametersMatcher);
}
protected function process($results) {
return array($results[1], $results[2]);
}
}
class ConstantMatcher extends RegexMatcher {
private $constant;
public function __construct($regex, $constant) {
parent::__construct($regex);
$this->constant = $constant;
}
protected function process($matches) {
return $this->constant;
}
}
class AnnotationParametersMatcher extends ParallelMatcher {
protected function build() {
$this->add(new ConstantMatcher('', array()));
$this->add(new ConstantMatcher('\(\)', array()));
$params_matcher = new SimpleSerialMatcher(1);
$params_matcher->add(new RegexMatcher('\(\s*'));
$params_matcher->add(new AnnotationValuesMatcher);
$params_matcher->add(new RegexMatcher('\s*\)'));
$this->add($params_matcher);
}
}
class AnnotationValuesMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationTopValueMatcher);
$this->add(new AnnotationHashMatcher);
}
}
class AnnotationTopValueMatcher extends AnnotationValueMatcher {
protected function process($value) {
return array('value' => $value);
}
}
class AnnotationValueMatcher extends ParallelMatcher {
protected function build() {
$this->add(new ConstantMatcher('true', true));
$this->add(new ConstantMatcher('false', false));
$this->add(new ConstantMatcher('TRUE', true));
$this->add(new ConstantMatcher('FALSE', false));
$this->add(new AnnotationStringMatcher);
$this->add(new AnnotationNumberMatcher);
$this->add(new AnnotationArrayMatcher);
$this->add(new AnnotationStaticConstantMatcher);
}
}
class AnnotationKeyMatcher extends ParallelMatcher {
protected function build() {
$this->add(new RegexMatcher('[a-zA-Z][a-zA-Z0-9_]*'));
$this->add(new AnnotationStringMatcher);
$this->add(new AnnotationIntegerMatcher);
}
}
class AnnotationPairMatcher extends SerialMatcher {
protected function build() {
$this->add(new AnnotationKeyMatcher);
$this->add(new RegexMatcher('\s*=\s*'));
$this->add(new AnnotationValueMatcher);
}
protected function process($parts) {
return array($parts[0] => $parts[2]);
}
}
class AnnotationHashMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationPairMatcher);
$this->add(new AnnotationMorePairsMatcher);
}
}
class AnnotationMorePairsMatcher extends SerialMatcher {
protected function build() {
$this->add(new AnnotationPairMatcher);
$this->add(new RegexMatcher('\s*,\s*'));
$this->add(new AnnotationHashMatcher);
}
protected function match($string, &$value) {
$result = parent::match($string, $value);
return $result;
}
public function process($parts) {
return array_merge($parts[0], $parts[2]);
}
}
class AnnotationArrayMatcher extends ParallelMatcher {
protected function build() {
$this->add(new ConstantMatcher('{}', array()));
$values_matcher = new SimpleSerialMatcher(1);
$values_matcher->add(new RegexMatcher('\s*{\s*'));
$values_matcher->add(new AnnotationArrayValuesMatcher);
$values_matcher->add(new RegexMatcher('\s*}\s*'));
$this->add($values_matcher);
}
}
class AnnotationArrayValuesMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationArrayValueMatcher);
$this->add(new AnnotationMoreValuesMatcher);
}
}
class AnnotationMoreValuesMatcher extends SimpleSerialMatcher {
protected function build() {
$this->add(new AnnotationArrayValueMatcher);
$this->add(new RegexMatcher('\s*,\s*'));
$this->add(new AnnotationArrayValuesMatcher);
}
protected function match($string, &$value) {
$result = parent::match($string, $value);
return $result;
}
public function process($parts) {
return array_merge($parts[0], $parts[2]);
}
}
class AnnotationArrayValueMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationValueInArrayMatcher);
$this->add(new AnnotationPairMatcher);
}
}
class AnnotationValueInArrayMatcher extends AnnotationValueMatcher {
public function process($value) {
return array($value);
}
}
class AnnotationStringMatcher extends ParallelMatcher {
protected function build() {
$this->add(new AnnotationSingleQuotedStringMatcher);
$this->add(new AnnotationDoubleQuotedStringMatcher);
}
}
class AnnotationNumberMatcher extends RegexMatcher {
public function __construct() {
parent::__construct("-?[0-9]*\.?[0-9]*");
}
protected function process($matches) {
$isFloat = strpos($matches[0], '.') !== false;
return $isFloat ? (float) $matches[0] : (int) $matches[0];
}
}
class AnnotationIntegerMatcher extends RegexMatcher {
public function __construct() {
parent::__construct("-?[0-9]*");
}
protected function process($matches) {
return (int) $matches[0];
}
}
class AnnotationSingleQuotedStringMatcher extends RegexMatcher {
public function __construct() {
parent::__construct("'([^']*)'");
}
protected function process($matches) {
return $matches[1];
}
}
class AnnotationDoubleQuotedStringMatcher extends RegexMatcher {
public function __construct() {
parent::__construct('"([^"]*)"');
}
protected function process($matches) {
return $matches[1];
}
}
class AnnotationStaticConstantMatcher extends RegexMatcher {
public function __construct() {
parent::__construct('(\w+::\w+)');
}
protected function process($matches) {
$name = $matches[1];
if(!defined($name)) {
trigger_error("Constant '$name' used in annotation was not defined.");
return false;
}
return constant($name);
}
}
?>