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

Documentation generated on Fri, 13 Jan 2006 07:49:47 +0100 by phpDocumentor 1.3.0RC4