Source for file SparqlParser.php

Documentation is available at SparqlParser.php

  1. <?php
  2. // ---------------------------------------------
  3. // Class: SparqlParser
  4. // ---------------------------------------------
  5.  
  6. /**
  7. * Parses a SPARQL Query string and returns a Query Object.
  8. *
  9. @author   Tobias Gauss <tobias.gauss@web.de>
  10. @version     $Id: fsource_sparql__sparqlSparqlParser.php.html,v 1.7 2006/06/26 12:34:18 tgauss Exp $
  11. *
  12. @package sparql
  13. */
  14. Class SparqlParser extends Object{
  15.  
  16.     /**
  17.     * @var Query The query Object
  18.     */
  19.     private $query;
  20.  
  21.     /**
  22.     * @var string The Querystring
  23.     */
  24.     private $querystring;
  25.  
  26.     /**
  27.     * @var array The tokenized Query
  28.     */
  29.     private $tokens array();
  30.  
  31.     /**
  32.     * @var int Last parsed graphPattern
  33.     */
  34.     private $tmp;
  35.  
  36.     /**
  37.     * @var array Operators introduced by sparql
  38.     */
  39.     private $sops array('regex','bound','isuri','isblank','isliteral','str','lang','datatype','langmatches');
  40.  
  41.  
  42.  
  43.     /**
  44.     * Constructor of SparqlParser
  45.     */
  46.     public function SparqlParser(){
  47.         $this->query          new Query();
  48.         $this->querystring    null;
  49.         // add the default prefixes defined in constants.php
  50.         global $default_prefixes;
  51.         $this->query->prefixes $default_prefixes;
  52.     }
  53.  
  54.     /**
  55.     * Main function of SparqlParser. Parses a query string.
  56.     *
  57.     * @param  String $queryString The SPARQL query
  58.     * @return Query  The query object
  59.     * @throws SparqlParserException
  60.     */
  61.     public function parse($queryString false){
  62.         try{
  63.             if($queryString){
  64.                 $uncommentedQuery $this->uncomment($queryString);
  65.                 $this->tokenize($uncommentedQuery);
  66.                 $this->querystring $uncommentedQuery;
  67.                 $this->parseQuery();
  68.             }else{
  69.                 throw new SparqlParserException("Querystring is empty.",null,key($this->tokens));
  70.                 $this->query->isEmpty true;
  71.             }
  72.             return $this->query;
  73.         }catch(SparqlParserException $e){
  74.             $this->error($e);
  75.             return false;
  76.         }
  77.     }
  78.  
  79.  
  80.     /**
  81.     * Tokenizes the querystring.
  82.     *
  83.     * @param  String $queryString 
  84.     * @return void 
  85.     */
  86.     protected function tokenize($queryString){
  87.         $queryString trim($queryString);
  88.         $specialChars array (" ""\t""\r""\n"",""("")","{","}",'"',"'",";","[","]");
  89.         $len strlen($queryString);
  90.         $this->tokens[0]='';
  91.         $n 0;
  92.         for ($i=0$i<$len++$i{
  93.             if (!in_array($queryString{$i}$specialChars))
  94.             $this->tokens[$n.= $queryString{$i};
  95.             else {
  96.                 if ($this->tokens[$n!= '')
  97.                 ++$n;
  98.                 $this->tokens[$n$queryString{$i};
  99.                 $this->tokens[++$n'';
  100.             }
  101.         }
  102.     }
  103.  
  104.  
  105.     /**
  106.     * Removes comments in the query string. Comments are
  107.     * indicated by '#'.
  108.     *
  109.     * @param  String $queryString 
  110.     * @return String The uncommented query string
  111.     */
  112.     protected function uncomment($queryString){
  113.         // php appears to escape quotes, so unescape them
  114.           $queryString str_replace('\"',"'",$queryString);
  115.           $queryString str_replace("\'",'"',$queryString);
  116.         
  117.         $regex ="/((\"[^\"]*\")|(\'[^\']*\')|(\<[^\>]*\>))|(#.*)/";
  118.         return preg_replace($regex,'\1',$queryString);
  119.     }
  120.  
  121.     /**
  122.     * Starts parsing the tokenized SPARQL Query.
  123.     *
  124.     * @return void 
  125.     */
  126.     protected function parseQuery({
  127.         do{
  128.             switch(strtolower(current($this->tokens))){
  129.                 case "base":
  130.                 $this->parseBase();
  131.                 break;
  132.                 case "prefix":
  133.                 $this->parsePrefix();
  134.                 break;
  135.                 case "select":
  136.                 $this->parseSelect();
  137.                 break;
  138.                 case "describe":
  139.                 $this->parseDescribe();
  140.                 break;
  141.                 case "ask":
  142.                 $this->parseAsk();
  143.                 break;
  144.                 case "from":
  145.                 $this->parseFrom();
  146.                 break;
  147.                 case "construct":
  148.                 $this->parseConstruct();
  149.                 break;
  150.                 case "where":
  151.                 $this->parseWhere();
  152.                 $this->parseModifier();
  153.                 break;
  154.                 case "{":
  155.                 prev($this->tokens);
  156.                 $this->parseWhere();
  157.                 $this->parseModifier();
  158.                 break;
  159.             }
  160.         }while(next($this->tokens));
  161.  
  162.     }
  163.  
  164.     /**
  165.     * Parses the BASE part of the query.
  166.     * 
  167.     * @return void 
  168.     * @throws SparqlParserException
  169.     */
  170.     protected function parseBase(){
  171.         $this->_fastForward();
  172.         if($this->iriCheck(current($this->tokens))){
  173.             $this->query->setBase(current($this->tokens));
  174.         }else{
  175.             $msg current($this->tokens);
  176.             $msg preg_replace('/</''&lt;'$msg);
  177.             throw new SparqlParserException("IRI expected ",null,key($this->tokens));
  178.         }
  179.     }
  180.  
  181.     /**
  182.     * Adds a new namespace prefix to the query object.
  183.     *
  184.     * @return void 
  185.     * @throws SparqlParserException
  186.     */
  187.     protected function parsePrefix(){
  188.         $this->_fastForward();
  189.         $prefix substr(current($this->tokens),0,-1);
  190.         $this->_fastForward();
  191.         if($this->iriCheck(current($this->tokens))){
  192.             $uri substr(current($this->tokens),1,-1);
  193.             $this->query->addPrefix($prefix,$uri);
  194.         }else{
  195.             $msg current($this->tokens);
  196.             $msg preg_replace('/</''&lt;'$msg);
  197.             throw new SparqlParserException("IRI expected ",null,key($this->tokens));
  198.         }
  199.  
  200.     }
  201.  
  202.     /**
  203.     * Parses the SELECT part of a query.
  204.     *
  205.     * @return void 
  206.     * @throws SparqlParserException
  207.     */
  208.     protected function parseSelect(){
  209.         while(strtolower(current($this->tokens))!='from'strtolower(current($this->tokens))!='where'strtolower(current($this->tokens))!="{"){
  210.             $this->_fastForward();
  211.             if($this->varCheck(current($this->tokens))|strtolower(current($this->tokens))=='*'){
  212.                 $this->query->addVariable(current($this->tokens));
  213.                 if(!$this->query->getResultForm())
  214.                 $this->query->setResultForm('select');
  215.             }else{
  216.                 if(strtolower(current($this->tokens))=='distinct'){
  217.                     $this->query->setResultForm('select distinct');
  218.                     $this->_fastForward();
  219.                     if($this->varCheck(current($this->tokens))|strtolower(current($this->tokens))=='*'){
  220.                         $this->query->addVariable(current($this->tokens));
  221.                     }else{
  222.                         throw new SparqlParserException ("Variable or '*' expected.",null,key($this->tokens));
  223.                     }
  224.                 }
  225.             }
  226.  
  227.             if(!current($this->tokens)){
  228.                 throw new SparqlParserException("Unexpected end of File. ",null,key($this->tokens));
  229.                 break;
  230.             }
  231.         }
  232.         prev($this->tokens);
  233.     }
  234.  
  235.  
  236.     /**
  237.     * Adds a new variable to the query and sets result form to 'DESCRIBE'.
  238.     *
  239.     * @return void 
  240.     */
  241.     protected function parseDescribe(){
  242.         while(strtolower(current($this->tokens))!='from'strtolower(current($this->tokens))!='where'){
  243.             $this->_fastForward();
  244.             if($this->varCheck(current($this->tokens))|$this->iriCheck(current($this->tokens))){
  245.                 $this->query->addVariable(current($this->tokens));
  246.                 if(!$this->query->getResultForm())
  247.                     $this->query->setResultForm('describe');
  248.             }
  249.             if(!current($this->tokens))
  250.             break;
  251.         }
  252.         prev($this->tokens);
  253.     }
  254.  
  255.     /**
  256.     * Sets result form to 'ASK'.
  257.     *
  258.     * @return void 
  259.     */
  260.     protected function parseAsk(){
  261.         $this->query->setResultForm('ask');
  262.         $this->_fastForward();
  263.         if(current($this->tokens)=="{")
  264.             $this->_rewind();
  265.         $this->parseWhere();
  266.         $this->parseModifier();
  267.     }
  268.  
  269.     /**
  270.     * Parses the FROM clause.
  271.     *
  272.     * @reutrn void
  273.     * @throws SparqlParserException
  274.     */
  275.     protected function parseFrom(){
  276.         $this->_fastForward();
  277.         if(strtolower(current($this->tokens))!='named'){
  278.             if($this->iriCheck(current($this->tokens))||$this->qnameCheck(current($this->tokens))){
  279.                 $this->query->addFrom(new Resource(substr(current($this->tokens),1,-1)));
  280.             }else if($this->varCheck(current($this->tokens))){
  281.                 $this->query->addFrom(current($this->tokens));
  282.             }else{
  283.                 throw new SparqlParserException("Variable, Iri or qname expected in FROM ",null,key($this->tokens));
  284.             }
  285.             $this->query->addFrom(current($this->tokens));
  286.         }else{
  287.             $this->_fastForward();
  288.             if($this->iriCheck(current($this->tokens))||$this->qnameCheck(current($this->tokens))){
  289.                 $this->query->addFromNamed(new Resource(substr(current($this->tokens),1,-1)));
  290.             }else if($this->varCheck(current($this->tokens))){
  291.                 $this->query->addFromNamed(current($this->tokens));
  292.             }else{
  293.                 throw new SparqlParserException("Variable, Iri or qname expected in FROM NAMED ",null,key($this->tokens));
  294.             }
  295.         }
  296.     }
  297.     
  298.     
  299.     /**
  300.     * Parses the CONSTRUCT clause.
  301.     *
  302.     * @return void 
  303.     * @throws SparqlParserException
  304.     */
  305.     protected function parseConstruct(){
  306.         $this->_fastForward();
  307.         $this->query->setResultForm('construct');
  308.         if(current($this->tokens)=="{"){
  309.             $this->parseGraphPattern(false,false,false,true);
  310.         }else{
  311.             throw new SparqlParserException("Unable to parse CONSTRUCT part. '{' expected. ",null,key($this->tokens));
  312.         }
  313.         $this->parseWhere();
  314.         $this->parseModifier();
  315.     }
  316.     
  317.  
  318.     /**
  319.     * Parses the WHERE clause.
  320.     *
  321.     * @return void 
  322.     * @throws SparqlParserException
  323.     */
  324.     protected function parseWhere(){
  325.         $this->_fastForward();
  326.         if(current($this->tokens)=="{"){
  327.             $this->parseGraphPattern();
  328.         }else{
  329.             throw new SparqlParserException("Unable to parse WHERE part. '{' expected in Query. ",null,key($this->tokens));
  330.         }
  331.     }
  332.  
  333.     
  334.  
  335.     /**
  336.     * Checks if $token is a variable.
  337.     *
  338.     * @param  String  $token The token
  339.     * @return boolean TRUE if the token is ja variable false if not
  340.     */
  341.     protected function varCheck($token){
  342.         if($token{0}=='$'|$token{0}=='?'){
  343.             $this->query->addVar($token);
  344.             return true;
  345.         }
  346.         return false;
  347.     }
  348.  
  349.     /**
  350.     * Checks if $token is an IRI.
  351.     *
  352.     * @param  String  $token The token
  353.     * @return boolean TRUE if the token is an IRI false if not
  354.     */
  355.     protected function iriCheck($token){
  356.         $pattern="/^<[^>]*>\.?$/";
  357.         if(preg_match($pattern,$token)>0)
  358.         return true;
  359.         return false;
  360.     }
  361.  
  362.  
  363.     /**
  364.     * Checks if $token is a Blanknode.
  365.     *
  366.     * @param  String  $token The token
  367.     * @return boolean TRUE if the token is BNode false if not
  368.     */
  369.     protected function bNodeCheck($token){
  370.         if($token{0== "_")
  371.         return true;
  372.         else
  373.         return false;
  374.     }
  375.  
  376.  
  377.     /**
  378.     * Checks if $token is a qname.
  379.     *
  380.     * @param  String  $token The token
  381.     * @return boolean TRUE if the token is a qname false if not
  382.     * @throws SparqlParserException
  383.     */
  384.     protected function qnameCheck($token){
  385.         $result false;
  386.         $pattern="/^([^:^\<]*):([^:]*)$/";
  387.         if(preg_match($pattern,$token,$hits)>0){
  388.             $prefs $this->query->getPrefixes();
  389.             if(isset($prefs{$hits{1}}))
  390.             return true;
  391.             if($hits{1}=="_")
  392.             return true;
  393.             throw new SparqlParserException("Unbound Prefix: <i>".$hits{1}."</i>",null,key($this->tokens));
  394.         }else{
  395.             $result false;
  396.         }
  397.         return $result;
  398.     }
  399.  
  400.  
  401.     /**
  402.     * Checks if $token is a Literal.
  403.     *
  404.     * @param  String  $token The token
  405.     * @return boolean TRUE if the token is a Literal false if not
  406.     */
  407.     protected function literalCheck($token){
  408.         $pattern="/^[\"\'].*$/";
  409.         if(preg_match($pattern,$token)>0)
  410.         return true;
  411.         return false;
  412.     }
  413.  
  414.     /**
  415.     * FastForward until next token which is not blank.
  416.     *
  417.     * @return void 
  418.     */
  419.     protected function _fastForward(){
  420.         next($this->tokens);
  421.         while(current($this->tokens)==" "|current($this->tokens)==chr(10)|current($this->tokens)==chr(13)|current($this->tokens)==chr(9)){
  422.             next($this->tokens);
  423.         }
  424.         return;
  425.     }
  426.  
  427.     /**
  428.     * Rewind until next token which is not blank.
  429.     *
  430.     * @return void 
  431.     */
  432.     protected function _rewind(){
  433.         prev($this->tokens);
  434.         while(current($this->tokens)==" "|current($this->tokens)==chr(10)|current($this->tokens)==chr(13)|current($this->tokens)==chr(9)){
  435.             prev($this->tokens);
  436.         }
  437.         return;
  438.     }
  439.  
  440.     /**
  441.     * Parses a graph pattern.
  442.     *
  443.     * @param  int     $optional Optional graph pattern
  444.     * @param  int     $union    Union graph pattern
  445.     * @param  string  $graph    Graphname
  446.     * @param  boolean $constr   TRUE if the pattern is a construct pattern
  447.     * @return void 
  448.     */
  449.     protected function parseGraphPattern($optional false$union false$graph false,$constr false$external false){
  450.         $pattern $this->query->getNewPattern($constr);
  451.         if(is_int($optional)){
  452.             $pattern->addOptional($optional);
  453.         }else{
  454.             $this->tmp $pattern->getId();
  455.         }
  456.         if(is_int($union)){
  457.             $pattern->addUnion($union);
  458.         }
  459.         if($graph != false){
  460.             $pattern->setGraphname($graph);
  461.         }
  462.  
  463.         $this->_fastForward();
  464.  
  465.         do{
  466.             switch(strtolower(current($this->tokens))){
  467.                 case "graph":
  468.                 $this->parseGraph();
  469.                 break;
  470.                 case "union":
  471.                 $this->_fastForward();
  472.                 $this->parseGraphPattern(false,$this->tmp);
  473.                 break;
  474.                 case "optional":
  475.                 $this->_fastForward();
  476.                 $this->parseGraphPattern($this->tmp,false);
  477.                 break;
  478.                 case "filter":
  479.                 $this->parseConstraint(&$pattern,true);
  480.                 $this->_fastForward();
  481.                 break;
  482.                 case ".":
  483.                 $this->_fastForward();
  484.                 break;
  485.                 case "{":
  486.                 $this->parseGraphPattern(false,false);
  487.                 break;
  488.                 case "}":
  489.                 $pattern->open false;
  490.                 break;
  491.                 default:
  492.                 $this->parseTriplePattern(&$pattern);
  493.                 break;
  494.             }
  495.         }while($pattern->open);
  496.         if($external)
  497.             return $pattern;
  498.         $this->_fastForward();
  499.     }
  500.     /**
  501.     * Parses a triple pattern.
  502.     *
  503.     * @param  GraphPattern $pattern 
  504.     * @return void 
  505.     */
  506.     protected function parseTriplePattern($pattern){
  507.         $trp      Array();
  508.         $prev     false;
  509.         $prevPred false;
  510.         $cont     true;
  511.         $sub      "";
  512.         $pre      "";
  513.         $tmp      "";
  514.         $tmpPred  "";
  515.         $obj      "";
  516.         do{
  517.             switch(strtolower(current($this->tokens))){
  518.                 case false:
  519.                 $cont          false;
  520.                 $pattern->open false;
  521.                 break;
  522.                 case "filter":
  523.                 $this->parseConstraint(&$pattern,false);
  524.                 $this->_fastForward();
  525.                 break;
  526.                 case "optional":
  527.                 $this->_fastForward();
  528.                 $this->parseGraphPattern($pattern->getId(),false);
  529.                 $cont false;
  530.                 break;
  531.                 case ";":
  532.                 $prev true;
  533.                 $this->_fastForward();
  534.                 break;
  535.                 case ".":
  536.                 $prev false;
  537.                 $this->_fastForward();
  538.                 break;
  539.                 case "graph":
  540.                 $this->parseGraph();
  541.                 break;
  542.                 case ",":
  543.                 $prev     true;
  544.                 $prevPred true;
  545.                 $this->_fastForward();
  546.                 break;
  547.                 case "}":
  548.                 $prev false;
  549.                 $pattern->open false;
  550.                 $cont false;
  551.                 break;
  552.                 case "[":
  553.                 $prev true;
  554.                 $tmp  $this->parseNode($this->query->getBlanknodeLabel());
  555.                 $this->_fastForward();
  556.                 break;
  557.                 case "]":
  558.                 $prev true;
  559.                 $this->_fastForward();
  560.                 break;
  561.                 case "(":
  562.                 $prev true;
  563.                 $tmp $this->parseCollection(&$trp);
  564.                 $this->_fastForward();
  565.                 break;
  566.                 case false:
  567.                 $cont false;
  568.                 $pattern->open false;
  569.                 break;
  570.                 default:
  571.                 if($prev){
  572.                     $sub $tmp;
  573.                 }else{
  574.                     $sub $this->parseNode();
  575.                     $this->_fastForward();
  576.                     $tmp     $sub;
  577.                 }
  578.                 if($prevPred){
  579.                     $pre $tmpPred;
  580.                 }else{
  581.                     $pre $this->parseNode();
  582.                     $this->_fastForward();
  583.                     $tmpPred $pre;
  584.                 }
  585.                 if(current($this->tokens)=="["){
  586.                     $tmp  $this->parseNode($this->query->getBlanknodeLabel());
  587.                     $prev true;
  588.                     $obj $tmp;
  589.                 }else if(current($this->tokens)=="("){
  590.                     $obj $this->parseCollection(&$trp);
  591.                     
  592.                 }else{
  593.                     $obj $this->parseNode();
  594.                 }
  595.                 $trp[new QueryTriple($sub,$pre,$obj);
  596.                 $this->_fastForward();
  597.                 break;
  598.  
  599.             }
  600.         }while($cont);
  601.         if(count($trp)>0){
  602.             $pattern->addTriplePattern($trp);
  603.         }
  604.     }
  605.     
  606.     
  607.     
  608.     
  609.     /**
  610.     * Parses a value constraint.
  611.     *
  612.     * @param  GraphPattern $pattern 
  613.     * @return void 
  614.     */
  615.     protected function parseConstraint($pattern,$outer){
  616.         $constraint new Constraint();
  617.         $constraint->setOuterFilter($outer);
  618.         $this->_fastForward();
  619.         if(current($this->tokens)=='('){
  620.             $this->parseBrackettedExpression(&$constraint);
  621.         }else{
  622.             $this->parseExpression(&$constraint);
  623.         }
  624.         $pattern->addConstraint(&$constraint);
  625.  
  626.     }
  627.     /**
  628.     * Parses a bracketted expression.
  629.     *
  630.     * @param  Constraint $constraint 
  631.     * @return void 
  632.     * @throws SparqlParserException
  633.     */
  634.     protected function parseBrackettedExpression($constraint){
  635.         $open 1;
  636.         $exp "";
  637.         $this->_fastForward();
  638.         while($open !=current($this->tokens)!= false){
  639.             switch(current($this->tokens)){
  640.                 case "(":
  641.                 $open++;
  642.                 $exp $exp.current($this->tokens);
  643.                 break;
  644.                 case ")":
  645.                 $open--;
  646.                 if($open != 0){
  647.                     $exp $exp.current($this->tokens);
  648.                 }
  649.                 break;
  650.                 case false:
  651.                 throw new SparqlParserException ("Unexpected end of query.",null,key($this->tokens));
  652.                 default:
  653.                 $exp $exp.current($this->tokens);
  654.                 break;
  655.             }
  656.             next($this->tokens);
  657.         }
  658.         $constraint->addExpression($exp);
  659.     }
  660.  
  661.  
  662.     /**
  663.     * Parses an expression.
  664.     *
  665.     * @param  Constraint  $constrain 
  666.     * @return void 
  667.     * @throws SparqlParserException
  668.     */
  669.     protected function parseExpression($constraint){
  670.         $exp "";
  671.         while(current($this->tokens)!= false && current($this->tokens)!= "}"){
  672.             switch(current($this->tokens)){
  673.                 case false:
  674.                 throw new SparqlParserException ("Unexpected end of query.",null,key($this->tokens));
  675.                 case ".":
  676.                 break;
  677.                 break;
  678.                 default:
  679.                 $exp $exp.current($this->tokens);
  680.                 break;
  681.             }
  682.             next($this->tokens);
  683.         }
  684.         $constraint->addExpression($exp);
  685.     }
  686.  
  687.     /**
  688.     * Parses a GRAPH clause.
  689.     *
  690.     * @param  GraphPattern $pattern 
  691.     * @return void 
  692.     * @throws SparqlParserException
  693.     */
  694.     protected function parseGraph(){
  695.         $this->_fastForward();
  696.         $name current($this->tokens);
  697.         if(!$this->varCheck($name)&!$this->iriCheck($name)&&!$this->qnameCheck($name)){
  698.             $msg $name;
  699.             $msg preg_replace('/</''&lt;'$msg);
  700.             throw new SparqlParserException(" IRI or Var expected. ",null,key($this->tokens));
  701.         }
  702.         $this->_fastForward();
  703.         
  704.         if($this->iriCheck($name)){
  705.             $name new Resource(substr($name,1,-1));
  706.         }else if($this->qnameCheck($name)){
  707.             $name new Resource($this->getFN($name));
  708.         }
  709.         $this->parseGraphPattern(false,false,$name);
  710.         if(current($this->tokens)=='.')
  711.         $this->_fastForward();
  712.     }
  713.  
  714.     /**
  715.     * Parses the solution modifiers of a query.
  716.     *
  717.     * @return void 
  718.     * @throws SparqlParserException
  719.     */
  720.     protected function parseModifier(){
  721.         do{
  722.             switch(strtolower(current($this->tokens))){
  723.                 case "order":
  724.                 $this->_fastForward();
  725.                 if(strtolower(current($this->tokens))=='by'){
  726.                     $this->_fastForward();
  727.                     $this->parseOrderCondition();
  728.                 }else{
  729.                     throw new SparqlParserException("'BY' expected.",null,key($this->tokens));
  730.                 }
  731.                 break;
  732.                 case "limit":
  733.                 $this->_fastForward();
  734.                 $val current($this->tokens);
  735.                 $this->query->setSolutionModifier('limit',$val);
  736.                 break;
  737.                 case "offset":
  738.                 $this->_fastForward();
  739.                 $val current($this->tokens);
  740.                 $this->query->setSolutionModifier('offset',$val);
  741.                 break;
  742.                 default:
  743.                 break;
  744.             }
  745.         }while(next($this->tokens));
  746.     }
  747.  
  748.     /**
  749.     * Parses order conditions of a query.
  750.     *
  751.     * @return void 
  752.     * @throws SparqlParserException
  753.     */
  754.     protected function parseOrderCondition(){
  755.         $valList array();
  756.         $val array();
  757.         while(strtolower(current($this->tokens))!='limit'
  758.         strtolower(current($this->tokens))!= false
  759.         strtolower(current($this->tokens))!= 'offset'){
  760.             switch (strtolower(current($this->tokens))){
  761.                 case "desc":
  762.                 $this->_fastForward();
  763.                 $this->_fastForward();
  764.                 if($this->varCheck(current($this->tokens))){
  765.                     $val['val'current($this->tokens);
  766.                 }else{
  767.                     throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
  768.                 }
  769.                 $this->_fastForward();
  770.                 if(current($this->tokens)!=')')
  771.                 throw new SparqlParserException("missing ')' in ORDER BY clause.",null,key($this->tokens));
  772.                 $val['type''desc';
  773.                 $this->_fastForward();
  774.                 break;
  775.                 case "asc" :
  776.                 $this->_fastForward();
  777.                 $this->_fastForward();
  778.                 if($this->varCheck(current($this->tokens))){
  779.                     $val['val'current($this->tokens);
  780.                 }else{
  781.                     throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
  782.                 }
  783.                 $this->_fastForward();
  784.                 if(current($this->tokens)!=')')
  785.                 throw new SparqlParserException("missing ')' in ORDER BY clause.",null,key($this->tokens));
  786.                 $val['type''asc';
  787.                 $this->_fastForward();
  788.                 break;
  789.                 default:
  790.                 if($this->varCheck(current($this->tokens))){
  791.                     $val['val'current($this->tokens);
  792.                     $val['type''asc';
  793.                 }else{
  794.                     throw new SparqlParserException("Variable expected in ORDER BY clause. ",null,key($this->tokens));
  795.                 }
  796.                 $this->_fastForward();
  797.                 break;
  798.             }
  799.             $valList[$val;
  800.         }
  801.         prev($this->tokens);
  802.         $this->query->setSolutionModifier('order by',$valList);
  803.     }
  804.  
  805.     /**
  806.     * Parses a String to an RDF node.
  807.     *
  808.     * @param  String $node 
  809.     * @return Node   The parsed RDF node
  810.     * @throws SparqlParserException
  811.     */
  812.     protected function parseNode($node false){
  813.         $eon false;
  814.         if($node){
  815.             $node $node;
  816.         }else{
  817.             $node current($this->tokens);
  818.         }
  819.         if($node{strlen($node)-1== '.')
  820.             $node substr($node,0,-1);
  821.         if($this->dtypeCheck(&$node))
  822.         return $node;
  823.         if($this->bNodeCheck(&$node)){
  824.             $node '?'.$node;
  825.             $this->query->addVar($node);
  826.             return $node;
  827.         }
  828.         if($node == '['){
  829.             $node '?'.substr($this->query->getBlanknodeLabel(),1);
  830.             $this->query->addVar($node);
  831.             $this->_fastForward();
  832.                 if(current($this->tokens)!=']')
  833.                     prev($this->tokens);
  834.             return $node;
  835.         }
  836.         if($this->iriCheck($node)){
  837.             $base $this->query->getBase();            
  838.             if($base!=null)
  839.                 $node new Resource(substr(substr($base,0,-1).substr($node,1),1,-1));
  840.             else
  841.                 $node new Resource(substr($node,1,-1));
  842.             return $node;
  843.         }elseif ($this->qnameCheck($node)){
  844.             $node $this->getFN($node);
  845.             $node new Resource($node);
  846.             return $node;
  847.         }elseif ($this->literalCheck($node)){
  848.             do{
  849.                 switch(substr($node,0,1)){
  850.                     case '"':
  851.                     $this->parseLiteral(&$node,'"');
  852.                     $eon true;
  853.                     break;
  854.                     case "'":
  855.                     $this->parseLiteral(&$node,"'");
  856.                     $eon true;
  857.                     break;
  858.                 }
  859.             }while(!$eon);
  860.  
  861.         }elseif ($this->varCheck($node)){
  862.             $pos strpos($node,'.');
  863.             if($pos)
  864.                 return substr($node,0,$pos);
  865.             else 
  866.                 return $node;
  867.         }else{
  868.             throw new SparqlParserException($node." is neither a valid rdf- node nor a variable.",null,key($this->tokens));
  869.         }
  870.         return $node;
  871.     }
  872.     
  873.     /**
  874.     * Checks if there is a datatype given and appends it to the node.
  875.     *
  876.     * @param  String $node 
  877.     * @return void 
  878.     */
  879.     protected function checkDtypeLang($node){
  880.         $this->_fastForward();
  881.         switch(substr(current($this->tokens),0,1)){
  882.             case '^':
  883.             if(substr(current($this->tokens),0,2)=='^^'){
  884.                 $node new Literal(substr($node,1,-1));            
  885.                 $node->setDatatype($this->getFN(substr(current($this->tokens),2)));
  886.             }
  887.             break;
  888.             case '@':
  889.             $node new Literal(substr($node,1,-1),substr(current($this->tokens),1));
  890.             break;
  891.             default:
  892.             prev($this->tokens);
  893.             $node new Literal(substr($node,1,-1));
  894.             break;
  895.  
  896.         }
  897.  
  898.     }
  899.  
  900.     /**
  901.     * Parses a literal.
  902.     *
  903.     * @param String $node 
  904.     * @param String $sep used separator " or '
  905.     * @return void 
  906.     */
  907.     protected function parseLiteral($node,$sep){
  908.         do{
  909.             next($this->tokens);
  910.             $node $node.current($this->tokens);
  911.         }while(current($this->tokens)!=$sep);
  912.         $this->checkDtypeLang(&$node);
  913.     }
  914.  
  915.     /**
  916.     * Checks if the Node is a typed Literal.
  917.     *
  918.     * @param String $node 
  919.     * @return boolean TRUE if typed FALSE if not
  920.     */
  921.     protected function dtypeCheck($node){
  922.         $patternInt "/^-?[0-9]+$/";
  923.         $match preg_match($patternInt,$node,$hits);
  924.         if($match>0){
  925.             $node new Literal($hits[0]);
  926.             $node->setDatatype(XML_SCHEMA.'integer');
  927.             return true;
  928.         }
  929.         $patternBool "/^(true|false)$/";
  930.         $match preg_match($patternBool,$node,$hits);
  931.         if($match>0){
  932.             $node new Literal($hits[0]);
  933.             $node->setDatatype(XML_SCHEMA.'boolean');
  934.             return true;
  935.         }
  936.         $patternType "/^a$/";
  937.         $match preg_match($patternType,$node,$hits);
  938.         if($match>0){
  939.             $node new Resource(RDF_NAMESPACE_URI.'type');
  940.             return true;
  941.         }
  942.         $patternDouble "/^-?[0-9]+.[0-9]+[e|E]?-?[0-9]*/";
  943.         $match preg_match($patternDouble,$node,$hits);
  944.         if($match>0){
  945.             $node new Literal($hits[0]);
  946.             $node->setDatatype(XML_SCHEMA.'double');
  947.             return true;
  948.         }
  949.         return false;
  950.     }
  951.     /**
  952.     * Parses an RDF collection.
  953.     *
  954.     * @param  TriplePattern $trp 
  955.     * @return Node          The first parsed label
  956.     */
  957.     protected function parseCollection($trp){
  958.         $tmpLabel $this->query->getBlanknodeLabel();
  959.         $firstLabel $this->parseNode($tmpLabel);
  960.         $this->_fastForward();
  961.         $i 0;
  962.         while(current($this->tokens)!=")"){
  963.             if($i>0)
  964.             $trp[new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"),$this->parseNode($tmpLabel $this->query->getBlanknodeLabel()));
  965.             $trp[new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#first"),$this->parseNode());
  966.             $this->_fastForward();
  967.             $i++;
  968.         }
  969.         $trp[new QueryTriple($this->parseNode($tmpLabel),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest"),new Resource("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"));
  970.         return $firstLabel;
  971.     }
  972.  
  973.     /**
  974.     * Error reporting.
  975.     *
  976.     * @param SparqlException $e 
  977.     * @return String 
  978.     */
  979.     protected function error($e){
  980.  
  981.         echo "<b>SPARQL PARSER ERROR: </b>".$e->getMessage()."<br>
  982.             In Query: <br><pre>";
  983.         if($e->getPointer())
  984.         $end $e->getPointer();
  985.         else
  986.         $end count($this->tokens)-1;
  987.  
  988.         for($i =0;$i<$end;$i++ ){
  989.             $token preg_replace('/&/''&amp;'$this->tokens[$i]);
  990.             $token preg_replace('/</''&lt;'$token);
  991.             echo $token;
  992.         }
  993.         $token preg_replace('/&/''&amp;'$this->tokens[$end]);
  994.         $token preg_replace('/</''&lt;'$token);
  995.         echo "-><b>".$token."</b><-";
  996.         "</pre><br>";
  997.     }
  998.  
  999.     /**
  1000.     * Gets the full URI of a qname token.
  1001.     *
  1002.     * @param  String $token 
  1003.     * @return String The complete URI of a given token
  1004.     */
  1005.     protected function getFN($token){
  1006.         $pattern="/^([^:]*):([^:]*)$/";
  1007.         if(preg_match($pattern,$token,$hits)>0){
  1008.             $prefs $this->query->getPrefixes();
  1009.             $base $this->query->getBase();
  1010.             
  1011.             if(isset($prefs{$hits{1}}))
  1012.             return substr($base,1,-1).$prefs{$hits{1}}.$hits{2};
  1013.             if($hits{1}=='_')
  1014.             return "_".$hits{2};
  1015.             $base $this->query->getBase();
  1016.             
  1017.                 
  1018.         }
  1019.         
  1020.         return false;
  1021.     }
  1022.     
  1023. }// end class: SparqlParser.php
  1024.  
  1025.  
  1026.  
  1027.  
  1028. ?>

Documentation generated on Mon, 26 Jun 2006 14:26:23 +0200 by phpDocumentor 1.3.0RC6