Source for file N3Parser.php

Documentation is available at N3Parser.php

  1. <?php
  2. require_once RDFAPI_INCLUDE_DIR 'util/Object.php';
  3. require_once RDFAPI_INCLUDE_DIR 'model/Resource.php';
  4. require_once RDFAPI_INCLUDE_DIR 'model/Literal.php';
  5. require_once RDFAPI_INCLUDE_DIR 'model/Statement.php';
  6.  
  7. // ----------------------------------------------------------------------------------
  8. // Class: N3Parser
  9. // ----------------------------------------------------------------------------------
  10.  
  11.  
  12. /**
  13.  * PHP Notation3 Parser
  14.  *
  15.  * This parser can parse a subset of n3, reporting triples to a callback function
  16.  * or constructing a RAP Model ( http://www.wiwiss.fu-berlin.de/suhl/bizer/rdfapi )
  17.  *
  18.  * Supported N3 features:
  19.  * <ul>
  20.  *   <li>Standard things, repeated triples ( ; and , ), blank nodes using [ ], self-reference ('<>')</li>
  21.  *   <li>@prefix mappings</li>
  22.  *   <li>= maps to owl#sameAs</li>
  23.  *   <li>a maps to rdf-syntax-ns#type</li>
  24.  *   <li>Literal datytype- and xmlLanguageTag support
  25.  * </ul>
  26.  * Un-supported N3 Features include:
  27.  * <ul>
  28.  *   <li>Reification using { }</li>
  29.  *   <li>. and ^ operators for tree traversal</li>
  30.  *   <li>Any log operators, like log:forAll etc.</li>
  31.  * </ul>
  32.  *
  33.  * This parser is based on n3.py from Epp released 2nd March, 2002.
  34.  * by Sean B. Palmer
  35.  * ( http://infomesh.net/2002/eep/20020302-013802/n3.py )
  36.  *
  37.  * This parser is released under the GNU GPL license.
  38.  * ( http://www.gnu.org/licenses/gpl.txt )
  39.  *
  40.  *
  41.  *
  42.  * @author Sean B. Palmer <sean@mysterylights.com>, Gunnar AA. Grimnes <ggrimnes@csd.abdn.ac.uk>, Daniel Westphal <mail@d-westphal.de>
  43.  * @version $Id: fsource_syntax__syntaxN3Parser.php.html 443 2007-06-01 16:25:38Z cax $
  44.  * @package syntax
  45.  * @access public
  46.  ***/
  47.  
  48. class N3Parser extends Object {
  49.  
  50.  
  51.   /* ==================== Variables ==================== */
  52.  
  53.   var $Tokens;
  54.   var $bNode;
  55.   var $RDF_NS$DAML_NS$OWL_NS;
  56.   var $debug;
  57.   var $parseError;
  58.   var $parsedNamespaces = array();
  59.  
  60.   /* ==================== Public Methods ==================== */
  61.  
  62.   /**
  63.    * Constructor
  64.    * @access public
  65.    ***/
  66.   function N3Parser({
  67.     //Regular expressions:
  68.      $Name '[A-Za-z0-9_@\.]+[^\.,;\[\]\s ]*';
  69.      $URI '<[^> ]*>';
  70.      $bNode '_:'.$Name;
  71.      $Univar '\?'.$Name;
  72.      $QName '(?:[A-Za-z][A-Za-z0-9_@\.]*)?:'.$Name;
  73.      $Literal '"(\\\"|[^"])*"'# '"(?:\\"|[^"])*"'
  74. //   $Literal = '"[^"\\\\]*(?:\\.\\[^"\\]*)*"'; # '"(?:\\"|[^"])*"'
  75.      $LangTag '@[A-Za-z\-]*[^ \^\.\;\,]';
  76.      $Datatype '(\^\^)[^ ,\.;)]+';
  77.      $Datatype_URI '(\^\^)'.$URI;
  78.      //     $LLiteral = '"""[^"\\\\]*(?:(?:.|"(?!""))[^"\\\\]*)*"""';
  79.      $LLiteral '"""[^"\\\\]*(?:(?:\\\\.|"(?!""))[^"\\\\]*)*"""';
  80.      //          '"""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
  81.      $Comment '#.*$';
  82.      $Prefix '(?:[A-Za-z][A-Za-z0-9_]*)?:';
  83.      $PrefixDecl '@prefix';
  84.      $WS '[ \t]';
  85.      $this->RDF_NS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'# for 'a' keyword
  86.      $this->DAML_NS = 'http://www.daml.org/2001/03/daml+oil#'# for '=' keyword
  87.      $this->OWL_NS = 'http://www.w3.org/2002/07/owl#';
  88.  
  89.      //     $t = array( $LLiteral, $URI); //, $Literal, $PrefixDecl, $QName, $bNode, $Prefix,
  90.      //        $Univar, 'a', '{', '}', '\(', '\)', '\[', '\]', ',', ';', '\.', $WS, $Comment);
  91.      $t array$Datatype_URI,$Datatype,$LLiteral$URI$Literal$PrefixDecl$QName$bNode$Prefix$Univar'a','=''{''}''\(''\)''\[''\]'','';''\.'$WS$Comment,$LangTag);
  92.      $this->Tokens="/(".join($t,"|").")/m";
  93.  
  94.      $this->bNode=0;
  95.      $this->debug=0;
  96.      $this->bNodeMap array();
  97.      $this->FixBnodes FIX_BLANKNODES;
  98.      $this->parseError=false;
  99.   }
  100.  
  101.  
  102.   /**
  103.    * Sets, if BlankNode labels should be replaced by the generic label from the constants.php file
  104.    * default is "false" -> the used label in n3 is parsed to the model
  105.    * @param boolean 
  106.    * @access public
  107.    ***/
  108.   function setFixBnodes($set{
  109.  
  110.       if (($set===trueOR ($set===false)) $this->FixBnodes $set;
  111.   }
  112.  
  113.  
  114.   /**
  115.    * This parses a N3 string and prints out the triples
  116.    * @param string $s 
  117.    * @access public
  118.    ***/
  119.   function parse($s{
  120.     //   """Get a string, tokenize, create list, convert to Eep store."""
  121.     $stat=$this->n3tolist($s);
  122.     foreach $stat as $t{
  123.  
  124.       if (count($t)>3{
  125.         $object=$t[2];
  126.  
  127.         for ($i 3$i 5$i++){
  128.           if ($t[$i][0]=='@')$object.=$t[$i];
  129.           if (substr($t[$i],0,2)=='^^')$object.=$t[$i];
  130.         };
  131.       else {$object=$t[2];};
  132.  
  133.       print '('.$t[0].', '.$t[1].', '.$object.")\n";
  134.  
  135.     }
  136.     //   return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
  137.     //              for t in n3tolist(s)]
  138.   }
  139.  
  140.  
  141.   /**
  142.    * This parses a N3 string and calls func($subject, $predicate, $object) with each trioke
  143.    * @param string $s 
  144.    * @param string $func 
  145.    * @access public
  146.    ***/
  147.   function uparse($s,$func{
  148.     //   """Get a string, tokenize, create list, convert to Eep store."""
  149.     $stat=$this->n3tolist($s);
  150.     foreach $stat as $t{
  151.  
  152.         if (count($t)>3{
  153.         $object=$t[2];
  154.  
  155.         for ($i 3$i 5$i++){
  156.           if ($t[$i][0]=='@')$object.=$t[$i];
  157.           if (substr($t[$i],0,2)=='^^')$object.=$t[$i];
  158.         };
  159.       else {$object=$t[2];};
  160.         //    print "(".$t[0].", ".$t[1].", ".$t[2].")";
  161.  
  162.       $func($t[0],$t[1],$object);
  163.     }
  164.     //   return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
  165.     //              for t in n3tolist(s)]
  166.   }
  167.  
  168.  
  169.   /**
  170.    * This parses a N3 string and returns a memmodel
  171.    * @param string $s 
  172.    * @access public
  173.    * @return object Model 
  174.    ***/
  175.  
  176.   function parse2model($s,$model false{
  177.     if($model == false){
  178.         $m=new MemModel();
  179.     }else{
  180.         $m=$model;
  181.     }
  182.     //   """Get a string, tokenize, create list, convert to Eep store."""
  183.     $stat=$this->n3tolist($s);
  184.  
  185.     foreach $stat as $t{
  186.       $s=$this->toRDFNode($t[0],$t);
  187.       $p=$this->toRDFNode($t[1],$t);
  188.       $o=$this->toRDFNode($t[2],$t);
  189.  
  190.        $new_statementnew Statement($s,$p,$o);
  191.  
  192.       $m->add($new_statement);
  193.       //    print "(".$t[0].", ".$t[1].", ".$t[2].")";
  194.     }
  195.     //   return [[eep.Article(t[0]), eep.Article(t[1]), eep.Article(t[2])]
  196.     //              for t in n3tolist(s)]
  197.     $m->addParsedNamespaces($this->parsedNamespaces);
  198.     return $m;
  199.   }
  200.  
  201. /**
  202.  * Generate a new MemModel from an URI or file.
  203.  *
  204.  * @access    public
  205.  * @param $path 
  206.  * @throws PhpError
  207.  * @return object MemModel 
  208.  */
  209.   function generateModel($path,$dummy=false,$model=false{
  210.  
  211.     $handle fopen($path,'r'or die("N3 ParserCould not open File: '$path' - Stopped parsing.");
  212.     $done=false;
  213.     $input="";
  214.     while(!$done)
  215.     {
  216.       $input .= fread$handle512 );
  217.       $done feof($handle);
  218.  
  219.     };
  220.  
  221.  
  222.     fclose($handle);
  223.  
  224.     $m $this->parse2model($input,$model);
  225.     return $m;
  226.   }
  227.  
  228.  
  229.   /* ==================== Private Methods from here ==================== */
  230.  
  231.   //  General list processing functions
  232.  
  233. /**
  234.  * Returns FALSE if argument is a whitespace character
  235.  * @access private
  236.  * @param string $s 
  237.  ***/
  238.   function isWS($s{
  239.     return !preg_match('/^(#.*|\s*)$/'$s);
  240.   }
  241.  
  242.  
  243.  
  244.   /**
  245.    * Returns true if the string is not a comment
  246.    * @access private
  247.    * @param string $s 
  248.    * @returns boolean
  249.    ***/
  250.   function notComment($s{
  251.     if ($s==""return false;
  252.     $N3Comment '^[ \t]*\#';
  253.  
  254.     if (ereg($N3Comment,$s)) return false;
  255.     else return true;
  256.   }
  257.  
  258.   /**
  259.    * Removes all whitespace tokens from list
  260.    * @access private
  261.    * @param array $list 
  262.    ***/
  263.   function filterWs($list{
  264.     //    var_dump($list);
  265.     //  """Filter whitespace from a list."""
  266.  
  267.     return array_filter($listarray($this,"isWS"));
  268.   }
  269.  
  270. /**
  271. * converts a string to its unicode NFC form (e.g. \uHHHH or \UHHHHHHHH).
  272. *
  273. @param String $str 
  274. @return String 
  275. @access private
  276. *
  277. */
  278. function str2unicode_nfc($str=""){
  279.     $result="";
  280.     /* try to detect encoding */
  281.     $tmp=str_replace("?"""$str);
  282.     if(strpos(utf8_decode($tmp)"?")===false){
  283.         $str=utf8_decode($str);
  284.     }
  285.     for($i=0,$i_max=strlen($str);$i<$i_max;$i++){
  286.         $nr=0;/* unicode dec nr */
  287.         /* char */
  288.         $char=$str[$i];
  289.         /* utf8 binary */
  290.         $utf8_char=utf8_encode($char);
  291.         $bytes=strlen($utf8_char);
  292.         if($bytes==1){
  293.             /* 0####### (0-127) */
  294.             $nr=ord($utf8_char);
  295.         }
  296.         elseif($bytes==2){
  297.             /* 110##### 10###### = 192+x 128+x */
  298.             $nr=((ord($utf8_char[0])-192)*64(ord($utf8_char[1])-128);
  299.         }
  300.         elseif($bytes==3){
  301.             /* 1110#### 10###### 10###### = 224+x 128+x 128+x */
  302.             $nr=((ord($utf8_char[0])-224)*4096((ord($utf8_char[1])-128)*64(ord($utf8_char[2])-128);
  303.         }
  304.         elseif($bytes==4){
  305.             /* 1111#### 10###### 10###### 10###### = 240+x 128+x 128+x 128+x */
  306.             $nr=((ord($utf8_char[0])-240)*262144((ord($utf8_char[1])-128)*4096((ord($utf8_char[2])-128)*64(ord($utf8_char[3])-128);
  307.         }
  308.         /* result (see http://www.w3.org/TR/rdf-testcases/#ntrip_strings) */
  309.         if($nr<9){/* #x0-#x8 (0-8) */
  310.             $result.="\\u".sprintf("%04X",$nr);
  311.         }
  312.         elseif($nr==9){/* #x9 (9) */
  313.             $result.='\t';
  314.         }
  315.         elseif($nr==10){/* #xA (10) */
  316.             $result.='\n';
  317.         }
  318.         elseif($nr<13){/* #xB-#xC (11-12) */
  319.             $result.="\\u".sprintf("%04X",$nr);
  320.         }
  321.         elseif($nr==13){/* #xD (13) */
  322.             $result.='\t';
  323.         }
  324.         elseif($nr<32){/* #xE-#x1F (14-31) */
  325.             $result.="\\u".sprintf("%04X",$nr);
  326.         }
  327.         elseif($nr<34){/* #x20-#x21 (32-33) */
  328.             $result.=$char;
  329.         }
  330.         elseif($nr==34){/* #x22 (34) */
  331.             $result.='\"';
  332.         }
  333.         elseif($nr<92){/* #x23-#x5B (35-91) */
  334.             $result.=$char;
  335.         }
  336.         elseif($nr==92){/* #x5C (92) */
  337.             $result.='\\';
  338.         }
  339.         elseif($nr<127){/* #x5D-#x7E (93-126) */
  340.             $result.=$char;
  341.         }
  342.         elseif($nr<65536){/* #x7F-#xFFFF (128-65535) */
  343.             $result.="\\u".sprintf("%04X",$nr);
  344.         }
  345.         elseif($nr<1114112){/* #x10000-#x10FFFF (65536-1114111) */
  346.             $result.="\\U".sprintf("%08X",$nr);
  347.         }
  348.         else{
  349.             /* other chars are not defined => ignore */
  350.         }
  351.     }
  352.     return $result;
  353. }
  354.  
  355.  
  356.  
  357.   /**
  358.    * Gets a slice of an array.
  359.    * Returns the wanted slice, as well as the remainder of the array.
  360.    * e.g. getSpan(['p', 'q', 'r'], 1, 2) gives (['q'], ['p', 'r'])
  361.    * @return array 
  362.    * @access private
  363.    * @param array $list 
  364.    * @param integer $start 
  365.    * @param integer $end 
  366.    ***/
  367.   function getSpan($list$start$end{
  368.  
  369.     $pre=array_slice($list0$start);
  370.     $post=array_slice($list$end);
  371.  
  372.     return array(array_slice($list$start,$end-$start),$this->array_concat($pre,$post));
  373.   }
  374.  
  375.  
  376.   /**
  377.    * Concatenates two arrays
  378.    * @param array $a 
  379.    * @param array $b 
  380.    * @returns array
  381.    * @access private
  382.    ***/
  383.   function array_concat($a$b{
  384.     array_splice($a,count($a),0,$b);
  385.     return $a;
  386.   }
  387.  
  388.   /**
  389.    * Returns an array with all indexes where item appears in list
  390.    * @param array $list 
  391.    * @param string $item 
  392.    * @returns array
  393.    * @access private
  394.    ***/
  395.   function posns($list$item{
  396.     $res=array();
  397.     $i=0;
  398.     foreach $list as $k=>$v{
  399.       if ($v === $item $res[]=$i;
  400.       $i++;
  401.     }
  402.     $res[]=$i;
  403.     return $res;
  404.   }
  405.  
  406.  
  407.   /* More N3 specific functions */
  408.  
  409.   /**
  410.    * Returns a list of tokens
  411.    * @param string $s 
  412.    * @returns array
  413.    * @access private
  414.    ***/
  415.   function toke($s{
  416.  
  417.     //    print "$s\n";
  418.     //   """Notation3 tokenizer. Takes in a string, returns a raw token list."""
  419.     if (strlen($s== 0die('Document has no content!');
  420.  
  421.     $s=str_replace("\r\n","\n",$s);
  422.     $s=str_replace("\r","\n",$s);
  423.  
  424.  
  425.     //$lines=explode("\n",$s);
  426.  
  427.     //$reallines=array_filter($lines, array($this, "notComment"));
  428.     //    print "LINES: ".join($reallines, " ")." :LINES\n";
  429.     //array_walk($reallines, array($this, "trimLine"));
  430.     //$res=array();
  431.  
  432.     //    foreach ($reallines as $l) {
  433.     //preg_match_all($this->Tokens, $l, $newres);
  434.     //$res=$this->array_concat($res,$newres[0]);
  435.     //}
  436.  
  437.     $res=array();
  438.     preg_match_all($this->Tokens$s$newres);
  439.  
  440.     $res=$this->array_concat($resarray_map('trim'$newres[0]));
  441.  
  442.     return $res;
  443.   }
  444.  
  445.   /**
  446.    * Returns a list with the elements between start and end as one quoted string
  447.    * e.g. listify(["a","b","c","d"],1,2) => ["a","b c", "d"]
  448.    * @param array $list 
  449.    * @param integer $start 
  450.    * @param integer $end 
  451.    * @returns array
  452.    * @access private
  453.    ***/
  454.   function listify($list$start$end{
  455.  
  456.     //Re-form a list, merge elements start->end into one quoted element
  457.     //Start and end are offsets...
  458.  
  459.     $l=$end-$start;
  460.  
  461.     $s=array_slice($list0$start);
  462.     $m=array_slice($list$start,$l);
  463.     $e=array_slice($list$end);
  464.  
  465.     //  array_push($s,"\"".join($m," ")."\"");
  466.     array_push($s,$m);
  467.  
  468.     return $this->array_concat($s,$e);
  469.   }
  470.  
  471.   /**
  472.    * Returns an array with prefixes=>namespace mappings
  473.    * @param array $list 
  474.    * @access private
  475.    * @returns array
  476.    ***/
  477.   function getPrefixes($list{
  478.  
  479.     $prefixes=array();
  480.     $ns=1;
  481.     $name=2;
  482.     foreach ($list as $l{
  483.       if ($l=='@prefix'{
  484.     //   while '@prefix' in list {
  485.  
  486.     $pos=current($list);
  487.     //pos = list.index('@prefix')
  488.     $r $this->getSpan($list$pos($pos+4))# processes the prefix tokens
  489.     $binding=$r[0];
  490.     $list=$r[1];
  491.     $prefixes[$binding[$ns]] substr($binding[$name],1,-1);
  492.     $this->parsedNamespaces[substr($binding[$name],1,-1)substr($binding[$ns],0,-1);
  493.       }
  494.     }
  495.  
  496.     if (count($prefixes)<1$listarray_slice($list,0);
  497.  
  498.     return array($prefixes$list);
  499.   }
  500.  
  501.   /**
  502.    * Callback function for replacing "a" elements with the right RDF uri.
  503.    * @param string $l 
  504.    * @access private
  505.    ***/
  506.   function replace_a_type(&$l,$p{
  507.     if ($l=='a'$l='<'.$this->RDF_NS.'type>';
  508.   }
  509.  
  510.   /**
  511.    * Callback function for replacing "=" elements with the right DAML+OIL uri.
  512.    * @param string $l 
  513.    * @access private
  514.    ***/
  515.   function replace_equal(&$l,$p{
  516.     if ($l=='='$l='<'.$this->OWL_NS.'sameAs>';
  517.   }
  518.  
  519.   /**
  520.    * Callback function for replacing "this" elements with the right RDF uri.
  521.    * @param string $l 
  522.    * @access private
  523.    ***/
  524.   function replace_this($l,$p{
  525.     if ($l=='this'$l='<urn:urn-n:this>';
  526.   }
  527.  
  528.   /**
  529.    * Applies stuff :)
  530.    * Expands namespace prefixes etc.
  531.    * @param array $prefixes 
  532.    * @param array $list 
  533.    * @returns $list
  534.    * @access private
  535.    ***/
  536.   function applyStuff($prefixes$list{
  537.  
  538.     array_walk($listarray($this'replace_a_type'));
  539.     array_walk($listarray($this'replace_equal'));
  540.     array_walk($listarray($this'replace_this'));
  541.  
  542.     for ($i=0;$i<count($list);$i++{
  543.       //   for i in range(len(list)) {
  544. //      if (!strstr('<_"?.;,{}[]()',$list[$i]{0})) {
  545.  
  546.  
  547. // if a <> resource occours, change it to the parsed filename or local URI + timestamp
  548.  
  549.         if ($list[$i]=='<>'{
  550.             if (!isset($path)) {
  551.                 if (!isset($_SERVER['SERVER_ADDR'])) $_SERVER['SERVER_ADDR']='localhost';
  552.                 if (!isset($_SERVER['REQUEST_URI'])) $_SERVER['REQUEST_URI']='/rdfapi-php';
  553.                 $list[$i]='<http://'.$_SERVER['SERVER_ADDR'].$_SERVER['REQUEST_URI'].'#generate_timestamp_'.time().'>';
  554.  
  555.           }else {$list[$i]='<'.$path.'>';};
  556.         };
  557.  
  558.  
  559.         if ((!strstr('<_"?.;,{}[]()@',$list[$i]{0}))AND (substr($list[$i],0,3)!='^^<')) {
  560.       $_rexplode(":",$list[$i]);
  561.  
  562.  
  563.  
  564.  
  565.  
  566.     $ns=$_r[0].':';
  567.     $name=$_r[1];
  568.  
  569.     if (isset($prefixes[$ns])) $list[$i'<'.$prefixes[$ns].$name.'>';
  570.     else if (isset($prefixes[substr($ns,2)])) $list[$i'^^'.$prefixes[substr($ns,2)].$name.'';
  571.   else {
  572.   #die('Prefix not declared:'.$ns);
  573.       $this->parseError=true;
  574.     trigger_error('Prefix not declared: '.$nsE_USER_ERROR);
  575.     break;
  576.  
  577.  
  578.   }
  579.  
  580.       else {
  581.     if ($list[$i]{0== '"'{  // Congratulations - it's a literal!
  582.       if (substr($list[$i],0,3== '"""'{
  583.         if (substr($list[$i],-3,3== '"""'// A big literal...
  584.           $lit substr($list[$i],3,-3);
  585.           //          print "++$lit++";
  586.           $lit=str_replace('\n''\\n',$lit);
  587.  
  588.           $lit=ereg_replace("[^\\]\"""\\\""$lit);
  589.  
  590.           $list[$i'"'.$lit.'"';
  591.         }
  592.         else die ('Incorrect string formatting: '.substr($list[$i],-3,3))}
  593.       else {
  594.         if (strstr($list[$i],"\n")) die('Newline in literal: '+$list[$i]);
  595.       }
  596.     }
  597.       }
  598.  
  599.       if (substr($list[$i],0,2)=='^^'{
  600.         if ($list[$i][2]!='<'){$list[$i]='^^<'.substr($list[$i],2).'>';};
  601.       };
  602.  
  603.  
  604.     }
  605.  
  606.  
  607.     return $list;
  608.   }
  609.  
  610.   /**
  611.    * Returns an array of triples extracted from the list of n3 tokens
  612.    * @param array $list 
  613.    * @returns array
  614.    * @access private
  615.    ***/
  616.   function getStatements($list{
  617.  
  618.  
  619.     $statements array();
  620.  
  621.     while (in_array('.'$list)) {
  622.       //  for($i=0;$i<count($list); $i++) {
  623.       //    if ($list[$i]==".") {
  624.       //   while '.' in list {
  625.       $pos=array_search('.',$list);
  626.  
  627.       $r=$this->getSpan($list0$pos+1);
  628.  
  629.       $statement=$r[0];
  630.       $list $r[1];
  631.  
  632.       array_pop($statement);
  633.       $statements[]=$statement;
  634.     }
  635.  
  636.     return $statements;
  637.   }
  638.  
  639.   /**
  640.    * Gets a list of triples with same subject
  641.    * e.g. :Gunnar :firstname "Gunnar" ; :lastname "Grimnes.
  642.    * @param array $list 
  643.    * @returns array
  644.    * @acces private
  645.    ***/
  646.   function getPovs($list{
  647.     $povs array();
  648.     while (in_array(';'$list)) {
  649.       $r=$this->posns($list,';');
  650.       $pos=array_slice($r,0,2);
  651.       $r $this->getSpan($list$pos[0]$pos[1]);
  652.       $pov=$r[0];
  653.       $list=$r[1];
  654.  
  655.       // skip lone semicolons, e.g. "<a> <b> <c> ; ."
  656.       if (count($pov== 1continue;
  657.  
  658.       $povs[]=array_slice($pov,1);
  659.     }
  660.  
  661.     return array($list$povs);
  662.   }
  663.  
  664.   /**
  665.    * Gets a list of triples with same predicate
  666.    * e.g. :Gunnar :likes "Cheese", "Wine".
  667.    * @access private
  668.    * @param array $list 
  669.    * @returns array
  670.    ***/
  671.   function getObjs($list{
  672.  
  673.  
  674.     $objs array();
  675.     while (in_array(",",$list)) {
  676.       $pos=array_search(",",$list);
  677.       //  for($i=0;$i<count($list); $i++) {
  678.       //    if ($list[$i]==",") {
  679.       //   while ',' in list {
  680.  
  681.  
  682.       $get_array_fields=2;
  683.       if (isset ($list[$pos+2])) {
  684.           if (@$list[$pos+2][0]=='@'$get_array_fields++;
  685.         if (@$list[$pos+2][0]=='^'$get_array_fields++;
  686.       };
  687.       if (isset ($list[$pos+3])) if (@$list[$pos+3][0]=='^'$get_array_fields++;};
  688.  
  689.  
  690.       $r=$this->getSpan($list$pos($pos+$get_array_fields));
  691.  
  692.       $obj=$r[0];
  693.       if (!isset($obj[2])) $obj[2]=' ';
  694.       if (!isset($obj[3])) $obj[3]=' ';
  695.  
  696.       $list=$r[1];
  697.  
  698.  
  699.       $objs[]=$obj;
  700.  
  701.  
  702.     }
  703.  
  704.     return array($list$objs);
  705.   }
  706.  
  707.   /**
  708.    * Does the real work, returns a list of subject, predicate, object triples.
  709.    * @param array $list 
  710.    * @returns array
  711.    * @access private
  712.    ***/
  713.   function statementize($list{
  714.  
  715.     if (count($list== && preg_match("/_".BNODE_PREFIX."[0-9]+_/",$list[0])) {
  716.     if ($this->debugprint "Ignored bNode exists statement$list\n";
  717.     return array();
  718.     }
  719.  
  720.  
  721.  
  722.     if (count($list== 3return array($list);
  723.     if (count($list3die("Error: statement too short!");
  724.  
  725.     //Get all ;
  726.     $r=$this->getPovs($list);
  727.     $spo=$r[0];
  728.     $po=$r[1];
  729.     $all=array();
  730.  
  731.  
  732.  
  733.     //      (spo, po), all = getPovs(list), []
  734.     $subject $spo[0];
  735.     foreach ($po as $pop{
  736.       //  for pop in po {
  737.       $r=$this->getObjs($pop);
  738.  
  739.       $myPo=$r[0];
  740.       $obj=$r[1];
  741.       //myPo, obj = getObjs(pop)
  742.  
  743.       if (!isset($myPo[2])) $myPo[2]=' ';
  744.       if (!isset($myPo[3])) $myPo[3]=' ';
  745.  
  746.  
  747.       $predicate $myPo[0];
  748.       $all[]=array($subject,$predicate,$myPo[1],$myPo[2],$myPo[3]);
  749.       //    all.append([subject, predicate, myPo[1]])
  750.  
  751.  
  752.  
  753.       foreach ($obj as $o$all[]=array($subject,$predicate$o[1],$o[2],$o[3]);
  754.       //         for x in obj: all.append([subject, predicate, x])
  755.  
  756.     }
  757.  
  758.  
  759.  
  760.     $r $this->getObjs($spo);
  761.     $spo=$r[0];
  762.  
  763.     $objs=$r[1];
  764.  
  765.     //spo, objs = getObjs(spo)
  766.     $subject=$spo[0];
  767.     $predicate=$spo[1];
  768.  
  769.  
  770.     if(!isset($spo[3])) $spo[3]=' ';
  771.     if(!isset($spo[4])) $spo[4]=' ';
  772.  
  773.     $all[]=array($subject$predicate$spo[2],$spo[3],$spo[4]);
  774.  
  775.     foreach ($objs as $obj$all[]=array($subject$predicate$obj[1],$obj[2],$obj[3]);
  776.  
  777.     return $all;
  778.   }
  779.  
  780.   /**
  781.    * Makes lists of elements in list into a seperate array element.
  782.    * e.g. doLists(["a","b","[","c","]","d"], "[","]")=> ["a","b", ["c"], "d"]
  783.    * @param array $list 
  784.    * @param string $schar 
  785.    * @param string $echar 
  786.    * @returns array
  787.    * @access private
  788.    ***/
  789.   function doLists($list$schar$echar{
  790.  
  791.     while (in_array($schar$list)) {
  792.       //   while schar in list {
  793.       $ndict=array();
  794.       $nestingLevel=0;
  795.       $biggest=0;
  796.       for ($i=0;$i<count($list);$i++{
  797.     if ($list[$i== $schar{
  798.       $nestingLevel += 1;
  799.       if (!in_array($nestingLevelarray_keys($ndict))) {
  800.         $ndict[$nestingLevelarray(array($i));
  801.       else {
  802.         $ndict[$nestingLevel][]=array($i);
  803.       }
  804.     }
  805.     if ($list[$i== $echar{
  806.       if (!in_array($nestingLevelarray_keys($ndict))) {
  807.         $ndict[$nestingLevel]=array(array($i));
  808.       else {
  809.             $ndict[$nestingLevel][count($ndict[$nestingLevel])-1][]=$i;
  810.             $nestingLevel-= 1;
  811. # elif type(list[i]) == type([]) {
  812. #    list[i] = doLists(list[i], schar, echar)
  813.       }
  814.     }
  815.       }
  816.       foreach (array_keys($ndictas $key)
  817.     if ($key $biggest)  $biggest $key;
  818.  
  819.       $tol $ndict[$biggest][0];
  820.       $list $this->listify($list$tol[0]($tol[1]+1));
  821.     }
  822.     return $list;
  823.   }
  824.  
  825.   /**
  826.    * Apply doLists for all different types of list.
  827.    * @param array 
  828.    * @returns array
  829.    * @access private
  830.    ***/
  831.   function listStuff($list{
  832. # y, z = zip(['[', ']'], ['{', '}'], ['(', ')'])
  833. # return map(doLists, [list, list, list], y, z).pop()
  834.     $list $this->doLists($list'['']');
  835.     $list $this->doLists($list'{''}');
  836.     return $this->doLists($list'('')');
  837.   }
  838.  
  839.   /**
  840.    * Generates a new node id.
  841.    * @access private
  842.    * @returns string
  843.    ***/
  844.   function bnodeID({
  845.  
  846.     $this->bNode++;
  847.     return "_".BNODE_PREFIX.$this->bNode."_";
  848.   }
  849.  
  850.   /**
  851.    * This makes bNodes out of variables like _:a etc.
  852.    * @access private
  853.    * @param array $list 
  854.    * @returns array
  855.    ***/
  856.   function fixAnon($list{
  857. //    $map=array();
  858.     for($i=0;$i<count($list);$i++{
  859.       $l=$list[$i];
  860.       if (substr($l,0,2)=="_:"{
  861.       if (!isset($this->bNodeMap[$l])) {
  862.       $a=$this->bnodeID();
  863.       $this->bNodeMap[$l]=$a;
  864.     else $a=$this->bNodeMap[$l];
  865.     $list[$i]=$a;
  866.       }
  867.     }
  868.     return $list;
  869.   }
  870.  
  871.   /**
  872.    * This makes [ ] lists into bnodes.
  873.    * @access private
  874.    * @param array $list 
  875.    * @return array 
  876.    ***/
  877.   function expandLists($list{
  878.  
  879.     for($i=0;$i<count($list);$i++{
  880.       if (is_array($list[$i])) {
  881.     if $list[$i][0]=='[' {
  882.       $bnode=$this->bnodeID();
  883.       $prop=$list[$i];
  884.       $list[$i]=$bnode;
  885.       $list[]=$bnode;
  886.       $list=$this->array_concat($listarray_slice($prop,1,-1));
  887.       $list[]='.';
  888.     }elseif($list[$i][0]=='('{
  889.  
  890.         $rdfNil '<'RDF_NAMESPACE_URI RDF_NIL .'>';
  891.         $rdfFirst '<'RDF_NAMESPACE_URI RDF_FIRST .'>';
  892.         $rdfRest '<'RDF_NAMESPACE_URI RDF_REST .'>';
  893.  
  894.         // local copy of list without "(" and ")"
  895.         $t_list array_slice($list[$i]1-1);
  896.  
  897.         //prepare bnodes
  898.         $fromBnode $this->bnodeID();
  899.         $toBnode $this->bnodeID();
  900.  
  901.         //link first bnode into graph
  902.         $list[$i$fromBnode;
  903.  
  904.         $count count($t_list);
  905.  
  906.         //loop through list, convert to RDF linked list
  907.         for ($idx 0$idx $count$idx++){
  908.  
  909.             // set rdf:first
  910.             $list[$fromBnode;
  911.             $list[$rdfFirst;
  912.             $list[$t_list[$idx];
  913.             $list['.';
  914.  
  915.             // set rdf:rest (nil or next bnode)
  916.             if ($idx == $count 1{
  917.                 $list[$fromBnode;
  918.                 $list[$rdfRest;
  919.                 $list[$rdfNil;
  920.                 $list['.';
  921.             }
  922.             else {
  923.                 $list[$fromBnode;
  924.                 $list[$rdfRest;
  925.                 $list[$toBnode;
  926.                 $list['.';
  927.  
  928.                 $fromBnode $toBnode;
  929.                 $toBnode $this->bnodeID();
  930.             }
  931.         }
  932.     }
  933.     else {
  934.         die('Only [ ] and () lists are supported!');
  935.     }
  936.     }
  937.  
  938.  
  939.     }
  940.     return $list;
  941.   }
  942.  
  943.   /**
  944.    * Main work-horse function. This converts a N3 string to a list of statements
  945.    * @param string $s 
  946.    * @returns array
  947.    * @access private
  948.    ***/
  949.   function n3tolist($s{
  950.  
  951.     //   """Convert an N3 string into a list of triples as strings."""
  952.     $result array();
  953.  
  954.    $t $this->filterWs($this->toke($s))# tokenize the stream, and filter whitespace tokens
  955.  
  956.     if ($this->debug{
  957.       print "Filter WS:\n";
  958.       var_dump($t);
  959.     }
  960.     $r=$this->getPrefixes($t)# get the prefix directives, and add to a dict
  961.     $prefixes=$r[0];
  962.     $t=$r[1];
  963.     if ($this->debug{
  964.       print "Prefixes:\n";
  965.       var_dump($prefixes);
  966.       print "***\n";
  967.       var_dump($t);
  968.     }
  969.     $t=$this->applyStuff($prefixes$t);#apply prefixes, keywords, and string formatting
  970.     if ($this->debug{
  971.       print "Stuff applied:\n";
  972.       var_dump($t);
  973.     }
  974.  
  975.     $t=$this->fixAnon($t)# fix _:a anons
  976.     if ($this->debug{
  977.       print "Fix anon:\n";
  978.       var_dump($t);
  979.     }
  980.  
  981.     $t $this->listStuff($t)# apply list stuff: todo
  982.     if ($this->debug{
  983.       print "Lists done:\n";
  984.       var_dump($t);
  985.     }
  986.     $t=$this->expandLists($t);
  987.     if ($this->debug{
  988.       print "Lists applied:\n";
  989.       var_dump($t);
  990.     }
  991.     $t $this->getStatements($t)# get all of the "statements" from the stream
  992.  
  993.     foreach ($t as $stat{
  994.       $stats=$this->statementize($stat);
  995.  
  996.       foreach ($stats as $y{
  997.     $result[]=$y;
  998.       }
  999.     }
  1000.     //   for x in [statementize(stat) for stat in t] {
  1001.     //      for y in x: result.append(y)
  1002.     return $result;
  1003.   }
  1004.  
  1005.   /**
  1006.    * Constructs a RAP RDFNode from URI/Literal/Bnode
  1007.    * @access private
  1008.    * @param string $s 
  1009.    * @returns object RDFNode
  1010.    ***/
  1011.   function toRDFNode($s,$state{
  1012.     $ins=substr($s,1,-1);
  1013.     if ($s{0}=="\""{
  1014.       $lang=NULL;
  1015.  
  1016.  
  1017.  
  1018.       if (count($state)>3{
  1019.  
  1020.  
  1021.         for ($i 3$i count($state)$i++){
  1022.           if ($state[$i][0]=='@')$lang=substr($state[3],1);
  1023.           if (substr($state[$i],0,2)=='^^'){
  1024.  
  1025.             $dtype=substr($state[$i],2);
  1026.             if ($dtype[0]=='<'$dtypesubstr($dtype,1,-1);
  1027.  
  1028.           };
  1029.  
  1030.         };
  1031.       };
  1032.  
  1033.  
  1034.      if(UNIC_RDF){
  1035.           $ins=$this->str2unicode_nfc($ins);
  1036.       }
  1037.       $new_Literal=new Literal($ins,$lang);
  1038.       if (isset($dtype)) $new_Literal->setDatatype($dtype);
  1039.       return  $new_Literal;
  1040.     };
  1041.  
  1042.     if (strstr($s,'_'.BNODE_PREFIX)) {
  1043.         if (($this->FixBnodesOR (!array_search($s,$this->bNodeMap))) {
  1044.             return new BlankNode($ins);
  1045.         else {return new BlankNode(trim(substr(array_search($s,$this->bNodeMap),2)));
  1046.         };
  1047.     }
  1048.  
  1049.     return new Resource($ins);
  1050.   }
  1051.  
  1052.  
  1053.  
  1054.  
  1055. //end: N3Parser
  1056.  
  1057. ?>

Documentation generated on Fri, 1 Jun 2007 16:49:59 +0200 by phpDocumentor 1.3.2