1
0
Fork 0

Revert "apply a regex solution instead of tokenizer"

This reverts commit 33a7305e22c8d4e2ce38586855fd3d4b7b2af3dd.
pull/4208/head
Rob Bast 2015-07-03 11:58:42 +02:00
parent b5d286e27b
commit 4019f7bb44
2 changed files with 100 additions and 52 deletions

View File

@ -192,69 +192,115 @@ class SpdxLicense
* @param string $license * @param string $license
* *
* @return bool * @return bool
*
* @throws \RuntimeException * @throws \RuntimeException
*/ */
private function isValidLicenseString($license) private function isValidLicenseString($license)
{ {
$licenses = array_map('preg_quote', array_keys($this->licenses)); $tokens = array(
sort($licenses); 'po' => '\(',
$licenses = array_reverse($licenses); 'pc' => '\)',
$licenses = implode('|', $licenses); 'op' => '(?:or|OR|and|AND)',
'wi' => '(?:with|WITH)',
'lix' => '(?:NONE|NOASSERTION)',
'lir' => 'LicenseRef-\d+',
'lic' => '[-_.a-zA-Z0-9]{3,}\+?',
'ws' => '\s+',
'_' => '.',
);
$exceptions = array_map('preg_quote', array_keys($this->exceptions)); $next = function () use ($license, $tokens) {
sort($exceptions); static $offset = 0;
$exceptions = array_reverse($exceptions);
$exceptions = implode('|', $exceptions);
$regex = "{ if ($offset >= strlen($license)) {
(?(DEFINE) return null;
# idstring: 1*( ALPHA / DIGIT / - / . ) }
(?<idstring>[\pL\pN\-\.]{1,})
# license-id: taken from list foreach ($tokens as $name => $token) {
(?<licenseid>${licenses}) if (false === $r = preg_match('{' . $token . '}', $license, $matches, PREG_OFFSET_CAPTURE, $offset)) {
throw new \RuntimeException('Pattern for token %s failed (regex error).', $name);
}
if ($r === 0) {
continue;
}
if ($matches[0][1] !== $offset) {
continue;
}
$offset += strlen($matches[0][0]);
# license-exception-id: taken from list return array($name, $matches[0][0]);
(?<licenseexceptionid>${exceptions}) }
# license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring) throw new \RuntimeException(
(?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring)) 'At least the last pattern needs to match, but it did not (dot-match-all is missing?).'
);
};
# simple-expresssion: license-id / license-id+ / license-ref $open = 0;
(?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref)) $with = false;
$require = true;
$lastop = null;
# compound expression: 1*( while (list($token, $string) = $next()) {
# simple-expression / switch ($token) {
# simple-expression WITH license-exception-id / case 'po':
# compound-expression AND compound-expression / if ($open || !$require || $with) {
# compound-expression OR compound-expression
# ) / ( compound-expression ) )
(?<compound_head>
(?&simple_expression) ( \s+ (?:with|WITH) \s+ (?&licenseexceptionid))?
| \( \s* (?&compound_expression) \s*\)
)
(?<compound_expression>
(?&compound_head) (?: \s+ (?:and|AND|or|OR) \s+ (?&compound_expression))?
)
# license-expression: 1*1(simple-expression / compound-expression)
(?<license_expression>NONE | NOASSERTION | (?&compound_expression) | (?&simple_expression))
) # end of define
^(?&license_expression)$
}x";
$match = preg_match($regex, $license);
if (0 === $match) {
return false; return false;
} }
$open = 1;
if (false === $match) { break;
throw new \RuntimeException('Regex failed to compile/run.'); case 'pc':
if ($open !== 1 || $require || !$lastop || $with) {
return false;
}
$open = 2;
break;
case 'op':
if ($require || !$open || $with) {
return false;
}
$lastop || $lastop = $string;
if ($lastop !== $string) {
return false;
}
$require = true;
break;
case 'wi':
$with = true;
break;
case 'lix':
if ($open || $with) {
return false;
}
goto lir;
case 'lic':
if ($with && $this->isValidExceptionIdentifier($string)) {
$require = true;
$with = false;
goto lir;
}
if ($with) {
return false;
}
if (!$this->isValidLicenseIdentifier(rtrim($string, '+'))) {
return false;
}
// Fall-through intended
case 'lir':
lir:
if (!$require) {
return false;
}
$require = false;
break;
case 'ws':
break;
case '_':
return false;
default:
throw new \RuntimeException(sprintf('Unparsed token: %s.', print_r($token, true)));
}
} }
return true; return !($open % 2 || $require || $with);
} }
} }

View File

@ -39,7 +39,6 @@ class SpdxLicenseTest extends TestCase
"GPL-2.0 with Autoconf-exception-2.0", "GPL-2.0 with Autoconf-exception-2.0",
"GPL-2.0 WITH Autoconf-exception-2.0", "GPL-2.0 WITH Autoconf-exception-2.0",
"GPL-2.0+ WITH Autoconf-exception-2.0", "GPL-2.0+ WITH Autoconf-exception-2.0",
"(GPL-3.0 and GPL-2.0 or GPL-3.0+)",
), ),
$identifiers $identifiers
); );
@ -58,6 +57,7 @@ class SpdxLicenseTest extends TestCase
array(array()), array(array()),
array("The system pwns you"), array("The system pwns you"),
array("()"), array("()"),
array("(MIT)"),
array("(MIT"), array("(MIT"),
array("MIT)"), array("MIT)"),
array("MIT NONE"), array("MIT NONE"),
@ -66,6 +66,8 @@ class SpdxLicenseTest extends TestCase
array("(MIT and MIT) MIT"), array("(MIT and MIT) MIT"),
array(array("LGPL-2.0", "The system pwns you")), array(array("LGPL-2.0", "The system pwns you")),
array("and GPL-3.0+"), array("and GPL-3.0+"),
array("EUDatagrid and GPL-3.0+"),
array("(GPL-3.0 and GPL-2.0 or GPL-3.0+)"),
array("(EUDatagrid and GPL-3.0+ and )"), array("(EUDatagrid and GPL-3.0+ and )"),
array("(EUDatagrid xor GPL-3.0+)"), array("(EUDatagrid xor GPL-3.0+)"),
array("(MIT Or MIT)"), array("(MIT Or MIT)"),