From: <cw...@us...> - 2007-08-13 04:59:47
|
Revision: 495 http://rdfapi-php.svn.sourceforge.net/rdfapi-php/?rev=495&view=rev Author: cweiske Date: 2007-08-12 21:59:45 -0700 (Sun, 12 Aug 2007) Log Message: ----------- Add support for plain numbers and booleans in N3 files. This fixes bug #1545380: N3 parser doesn't understand numeric literals and allows me to go on integrating the new DAWG tests Modified Paths: -------------- trunk/rdfapi-php/api/syntax/N3Parser.php trunk/rdfapi-php/test/unit/Syntax/n3Parser_test.php Modified: trunk/rdfapi-php/api/syntax/N3Parser.php =================================================================== --- trunk/rdfapi-php/api/syntax/N3Parser.php 2007-08-12 18:10:08 UTC (rev 494) +++ trunk/rdfapi-php/api/syntax/N3Parser.php 2007-08-13 04:59:45 UTC (rev 495) @@ -77,7 +77,8 @@ $Univar = '\?'.$Name; $QName = '(?:[A-Za-z][A-Za-z0-9_@\.]*)?:'.$Name; $Literal = '"(\\\"|[^"])*"'; # '"(?:\\"|[^"])*"' - $Number = '[0-9]+(:?[\\.e][0-9]+)?'; + $Number = '[-+]?[0-9]+(\\.[0-9]+)?([eE][-+]?[0-9]+)?'; + $Boolean = '@(?:true|false)'; // $Literal = '"[^"\\\\]*(?:\\.\\[^"\\]*)*"'; # '"(?:\\"|[^"])*"' $LangTag = '@[A-Za-z\-]*[^ \^\.\;\,]'; $Datatype = '(\^\^)[^ ,\.;)]+'; @@ -85,17 +86,23 @@ // $LLiteral = '"""[^"\\\\]*(?:(?:.|"(?!""))[^"\\\\]*)*"""'; $LLiteral = '"""[^"\\\\]*(?:(?:\\\\.|"(?!""))[^"\\\\]*)*"""'; // '"""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""' - $Comment = '#.*$'; - $Prefix = '(?:[A-Za-z][A-Za-z0-9_]*)?:'; + $Comment = '#.*$'; + $Prefix = '(?:[A-Za-z][A-Za-z0-9_]*)?:'; $PrefixDecl = '@prefix'; - $WS = '[ \t]'; + $WS = '[ \t]'; $this->RDF_NS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; # for 'a' keyword $this->DAML_NS = 'http://www.daml.org/2001/03/daml+oil#'; # for '=' keyword $this->OWL_NS = 'http://www.w3.org/2002/07/owl#'; // $t = array( $LLiteral, $URI); //, $Literal, $PrefixDecl, $QName, $bNode, $Prefix, // $Univar, 'a', '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.', $WS, $Comment); - $t = array( $Datatype_URI,$Datatype,$LLiteral, $URI, $Literal, $PrefixDecl, $QName, $Number, $bNode, $Prefix, $Univar, 'a','=', '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.', $WS, $Comment,$LangTag); + $t = array( + $Datatype_URI, $Datatype, $LLiteral, $URI, $Literal, + $PrefixDecl, $QName, $Number, $Boolean, $bNode, + $Prefix, $Univar, 'a','=', + '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.', + $WS, $Comment,$LangTag + ); $this->Tokens = "/(".join($t,"|").")/m"; $this->bNode = 0; @@ -545,7 +552,8 @@ array_walk($list, array($this, 'replace_equal')); array_walk($list, array($this, 'replace_this')); - for ($i=0; $i<count($list); $i++) { + for ($i = 0; $i < count($list); $i++) { + if ($list[$i]=='<>') { if (!isset($path)) { if (!isset($_SERVER['SERVER_ADDR'])) { @@ -561,20 +569,28 @@ }; - if ((!strstr('<_"?.;,{}[]()@',$list[$i]{0})) - && (substr($list[$i],0,3)!='^^<') + if (preg_match('/^[-+]?[0-9]+$/', $list[$i])) { + //integer + $list[$i] = intval($list[$i]); + } else if (is_numeric($list[$i])) { + //float or decimal + // After conversion we cannot distinguish between both + $list[$i] = floatval($list[$i]); + } else if ((!strstr('<_"?.;,{}[]()@', $list[$i]{0})) + && (substr($list[$i],0,3) != '^^<') ) { - $_r = explode(":",$list[$i]); - $ns = $_r[0].':'; + //prefix or unknown + $_r = explode(':', $list[$i]); + $ns = $_r[0] . ':'; $name = $_r[1]; if (isset($prefixes[$ns])) { $list[$i] = '<'.$prefixes[$ns].$name.'>'; - } else if (isset($prefixes[substr($ns,2)])) { - $list[$i] = '^^'.$prefixes[substr($ns,2)].$name.''; + } else if (isset($prefixes[substr($ns, 2)])) { + $list[$i] = '^^' . $prefixes[substr($ns, 2)] . $name . ''; } else { - #die('Prefix not declared:'.$ns); - $this->parseError=true; + //die('Prefix not declared:'.$ns); + $this->parseError = true; trigger_error('Prefix not declared: '.$ns, E_USER_ERROR); break; } @@ -602,7 +618,9 @@ } if (substr($list[$i],0,2)=='^^') { - if ($list[$i][2]!='<'){$list[$i]='^^<'.substr($list[$i],2).'>';}; + if ($list[$i][2]!='<') { + $list[$i] = '^^<' . substr($list[$i], 2) . '>'; + } }; }//foreach list item @@ -999,67 +1017,94 @@ $t = $this->getStatements($t); # get all of the "statements" from the stream foreach ($t as $stat) { - $stats=$this->statementize($stat); + $stats = $this->statementize($stat); foreach ($stats as $y) { - $result[]=$y; + $result[]=$y; } } + // for x in [statementize(stat) for stat in t] { // for y in x: result.append(y) return $result; } - /** - * Constructs a RAP RDFNode from URI/Literal/Bnode - * @access private - * @param string $s - * @returns object RDFNode - **/ - function toRDFNode($s,$state) { - $ins=substr($s,1,-1); - if ($s{0}=="\"") { - $lang=NULL; + /** + * Constructs a RAP RDFNode from URI/Literal/Bnode + * @access private + * @param string $s + * @returns object RDFNode + **/ + function toRDFNode($s, $state) + { + $ins = substr($s, 1, -1); + if ($s{0} == '"') { + $lang = NULL; - if (count($state)>3) { + if (count($state)>3) { + for ($i = 3; $i < count($state); $i++) { + if ($state[$i][0]=='@') { + $lang = substr($state[3], 1); + } + if (substr($state[$i],0,2) == '^^') { + $dtype = substr($state[$i],2); + if ($dtype[0]=='<') { + $dtype = substr($dtype,1,-1); + } + } + } + } - for ($i = 3; $i < count($state); $i++){ - if ($state[$i][0]=='@')$lang=substr($state[3],1); - if (substr($state[$i],0,2)=='^^'){ + if (UNIC_RDF) { + $ins = $this->str2unicode_nfc($ins); + } + $new_Literal = new Literal($ins, $lang); + if (isset($dtype)) { + $new_Literal->setDatatype($dtype); + } + return $new_Literal; + } else if (is_int($s)) { + $value = new Literal($s); + $value->setDatatype(XML_SCHEMA . 'integer'); + return $value; + } else if (is_float($s)) { + $value = new Literal($s); + $value->setDatatype(XML_SCHEMA . 'double'); + return $value; + } else if ($s == '@true') { + $value = new Literal(true); + $value->setDatatype(XML_SCHEMA . 'boolean'); + return $value; + } else if ($s == '@false') { + $value = new Literal(false); + $value->setDatatype(XML_SCHEMA . 'boolean'); + return $value; + } - $dtype=substr($state[$i],2); - if ($dtype[0]=='<') $dtype= substr($dtype,1,-1); + if (strstr($s, '_' . BNODE_PREFIX)) { + if (($this->FixBnodes) || (!array_search($s,$this->bNodeMap))) { + return new BlankNode($ins); + } else { + return new BlankNode( + trim( + substr( + array_search($s, $this->bNodeMap), + 2 + ) + ) + ); + }; + } - }; + return new Resource($ins); + }//function toRDFNode($s, $state) - }; - }; - if(UNIC_RDF){ - $ins=$this->str2unicode_nfc($ins); - } - $new_Literal=new Literal($ins,$lang); - if (isset($dtype)) $new_Literal->setDatatype($dtype); - return $new_Literal; - }; - if (strstr($s,'_'.BNODE_PREFIX)) { - if (($this->FixBnodes) OR (!array_search($s,$this->bNodeMap))) { - return new BlankNode($ins); - } else {return new BlankNode(trim(substr(array_search($s,$this->bNodeMap),2))); - }; - } - - return new Resource($ins); - } - - - - } //end: N3Parser ?> Modified: trunk/rdfapi-php/test/unit/Syntax/n3Parser_test.php =================================================================== --- trunk/rdfapi-php/test/unit/Syntax/n3Parser_test.php 2007-08-12 18:10:08 UTC (rev 494) +++ trunk/rdfapi-php/test/unit/Syntax/n3Parser_test.php 2007-08-13 04:59:45 UTC (rev 495) @@ -1,4 +1,5 @@ <?php +require_once RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3; // ---------------------------------------------------------------------------------- // Class: testN3Parser @@ -8,103 +9,207 @@ * Tests the N3Parser * * @version $Id$ - * @author Tobias Gau� <tob...@we...> + * @author Tobias Gauss <tob...@we...> + * @author Christian Weiske <cw...@cw...? * * @package unittests * @access public */ - class testN3Parser extends UnitTestCase { - function testN3Parser() { - $this->UnitTestCase(); +class testN3Parser extends UnitTestCase +{ - $_SESSION['n3TestInput']=' - @prefix p: <http://www.example.org/personal_details#> . - @prefix m: <http://www.example.org/meeting_organization#> . + function testN3Parser() { + $this->UnitTestCase(); - <http://www.example.org/people#fred> - p:GivenName "Fred"; - p:hasEmail <mailto:fr...@ex...>; - m:attending <http://meetings.example.com/cal#m1> . + $_SESSION['n3TestInput']=' + @prefix p: <http://www.example.org/personal_details#> . + @prefix m: <http://www.example.org/meeting_organization#> . - <http://meetings.example.com/cal#m1> - m:homePage <http://meetings.example.com/m1/hp> . - '; + <http://www.example.org/people#fred> + p:GivenName "Fred"; + p:hasEmail <mailto:fr...@ex...>; + m:attending <http://meetings.example.com/cal#m1> . + <http://meetings.example.com/cal#m1> + m:homePage <http://meetings.example.com/m1/hp> . + '; - } - function testIsMemmodel() { - // Import Package - include_once(RDFAPI_INCLUDE_DIR.PACKAGE_SYNTAX_N3); - $n3pars= new N3Parser(); - $model=$n3pars->parse2model($_SESSION['n3TestInput'],false); - $this->assertIsA($model, 'memmodel'); - } + } + function testIsMemmodel() { - function testParsing() { + // Import Package + $n3pars= new N3Parser(); + $model=$n3pars->parse2model($_SESSION['n3TestInput'],false); + $this->assertIsA($model, 'memmodel'); + } - $n3pars= new N3Parser(); - $model=$n3pars->parse2model($_SESSION['n3TestInput'],false); + function testParsing() { + $n3pars= new N3Parser(); + $model=$n3pars->parse2model($_SESSION['n3TestInput'],false); - $model2 = new MemModel(); - // Ceate new statements and add them to the model - $statement1 = new Statement(new Resource("http://www.example.org/people#fred"), - new Resource("http://www.example.org/personal_details#hasEmail"), - new Resource("mailto:fr...@ex...")); - $statement2 = new Statement(new Resource("http://www.example.org/people#fred"), - new Resource("http://www.example.org/meeting_organization#attending"), - new Resource("http://meetings.example.com/cal#m1")); - $statement3 = new Statement(new Resource("http://www.example.org/people#fred"), - new Resource("http://www.example.org/personal_details#GivenName"), - new Literal("Fred")); - $statement4 = new Statement(new Resource("http://meetings.example.com/cal#m1"), - new Resource("http://www.example.org/meeting_organization#homePage"), - new Resource("http://meetings.example.com/m1/hp")); + $model2 = new MemModel(); + // Ceate new statements and add them to the model + $statement1 = new Statement(new Resource("http://www.example.org/people#fred"), + new Resource("http://www.example.org/personal_details#hasEmail"), + new Resource("mailto:fr...@ex...")); + $statement2 = new Statement(new Resource("http://www.example.org/people#fred"), + new Resource("http://www.example.org/meeting_organization#attending"), + new Resource("http://meetings.example.com/cal#m1")); + $statement3 = new Statement(new Resource("http://www.example.org/people#fred"), + new Resource("http://www.example.org/personal_details#GivenName"), + new Literal("Fred")); + $statement4 = new Statement(new Resource("http://meetings.example.com/cal#m1"), + new Resource("http://www.example.org/meeting_organization#homePage"), + new Resource("http://meetings.example.com/m1/hp")); - $model2->add($statement1); - $model2->add($statement2); - $model2->add($statement3); - $model2->add($statement4); + $model2->add($statement1); + $model2->add($statement2); + $model2->add($statement3); + $model2->add($statement4); - $this->assertTrue($model->containsAll($model2)); - } - function testPrefixNotDeclared() { - $rdfInput=' - @prefix m: <http://www.example.org/meeting_organization#>. + $this->assertTrue($model->containsAll($model2)); + } - <http://www.example.org/people#fred> - p:GivenName "Fred"; - p:hasEmail <mailto:fr...@ex...>; - m:attending <http://meetings.example.com/cal#m1> . - '; + function testPrefixNotDeclared() { + $rdfInput=' + @prefix m: <http://www.example.org/meeting_organization#>. - $n3pars= new N3Parser(); - $model=$n3pars->parse2model($rdfInput,false); - //var_dump($model); - $this->assertErrorPattern('[Prefix not declared: p:]'); - } + <http://www.example.org/people#fred> + p:GivenName "Fred"; + p:hasEmail <mailto:fr...@ex...>; + m:attending <http://meetings.example.com/cal#m1> . + '; - function testLoneSemicolon() { - $n3 = '<a> <b> <c> ; .'; - $parser = &new N3Parser(); - $model = &$parser->parse2model($n3, false); - $this->assertEqual(1, $model->size()); - $this->assertNoErrors(); - } + $n3pars= new N3Parser(); + $model=$n3pars->parse2model($rdfInput,false); + //var_dump($model); + $this->assertErrorPattern('[Prefix not declared: p:]'); + } - function testTightClosingList() { - $n3 = '@prefix : <http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql4/manifest#> . - @prefix mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#> . - <> mf:entries ( mf:syn-09) .'; - $parser = &new N3Parser(); - $model = &$parser->parse2model($n3, false); - //if bug occured, the parser would be in an endless loop - } + function testLoneSemicolon() { + $n3 = '<a> <b> <c> ; .'; + $parser = &new N3Parser(); + $model = &$parser->parse2model($n3, false); + $this->assertEqual(1, $model->size()); + $this->assertNoErrors(); } + + function testTightClosingList() { + $n3 = '@prefix : <http://www.w3.org/2001/sw/DataAccess/tests/data-r2/syntax-sparql4/manifest#> . + @prefix mf: <http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#> . + <> mf:entries ( mf:syn-09) .'; + $parser = &new N3Parser(); + $model = &$parser->parse2model($n3, false); + //if bug occured, the parser would be in an endless loop + } + + + + /** + * Check number parsing + * @see http://www.w3.org/2000/10/swap/grammar/n3-report.html#node + */ + function testNumbers() + { + $n3 = '@prefix : <http://example.org/#> . + :foo :bar 0.7 . + :foo :bar 42 . + :foo :bar 10e6 . + + :foo :bar -0.7 . + :foo :bar -42 . + :foo :bar -12E-6 . + '; + $parser = &new N3Parser(); + + $model = &$parser->parse2model($n3, false); + + $model2 = new MemModel(); + $model2->add( + new Statement( + new Resource("http://example.org/#foo"), + new Resource("http://example.org/#bar"), + new Literal(0.7, null, XML_SCHEMA . 'double') + ) + ); + $model2->add( + new Statement( + new Resource("http://example.org/#foo"), + new Resource("http://example.org/#bar"), + new Literal(42, null, XML_SCHEMA . 'integer') + ) + ); + $model2->add( + new Statement( + new Resource("http://example.org/#foo"), + new Resource("http://example.org/#bar"), + new Literal(10e6, null, XML_SCHEMA . 'double') + ) + ); + $model2->add( + new Statement( + new Resource("http://example.org/#foo"), + new Resource("http://example.org/#bar"), + new Literal(-0.7, null, XML_SCHEMA . 'double') + ) + ); + $model2->add( + new Statement( + new Resource("http://example.org/#foo"), + new Resource("http://example.org/#bar"), + new Literal(-42, null, XML_SCHEMA . 'integer') + ) + ); + $model2->add( + new Statement( + new Resource("http://example.org/#foo"), + new Resource("http://example.org/#bar"), + new Literal(-12E-6, null, XML_SCHEMA . 'double') + ) + ); + + $this->assertEqual(6, $model->size()); + $this->assertTrue($model->containsAll($model2)); + }//function testNumbers() + + + + function testBooleans() + { + $n3 = '@prefix : <http://example.org/#> . + :foo :bar @true . + :foo :bar @false . + '; + $parser = &new N3Parser(); + //$parser->debug = true; + $model = &$parser->parse2model($n3, false); + + $model2 = new MemModel(); + $model2->add( + new Statement( + new Resource("http://example.org/#foo"), + new Resource("http://example.org/#bar"), + new Literal(true, null, XML_SCHEMA . 'boolean') + ) + ); + $model2->add( + new Statement( + new Resource("http://example.org/#foo"), + new Resource("http://example.org/#bar"), + new Literal(false, null, XML_SCHEMA . 'boolean') + ) + ); + + //var_dump($model->triples); + $this->assertEqual(2, $model->size()); + $this->assertTrue($model->containsAll($model2)); + }//function testBooleans() +} ?> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |