| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 | 
							- <?php namespace Sieve;
 
- include_once 'SieveTree.php';
 
- include_once 'SieveScanner.php';
 
- include_once 'SieveSemantics.php';
 
- include_once 'SieveException.php';
 
- class SieveParser
 
- {
 
-     protected $scanner_;
 
-     protected $script_;
 
-     protected $tree_;
 
-     protected $status_;
 
-     public function __construct($script = null)
 
-     {
 
-         if (isset($script))
 
-             $this->parse($script);
 
-     }
 
-     public function GetParseTree()
 
-     {
 
-         return $this->tree_;
 
-     }
 
-     public function dumpParseTree()
 
-     {
 
-         return $this->tree_->dump();
 
-     }
 
-     public function getScriptText()
 
-     {
 
-         return $this->tree_->getText();
 
-     }
 
-     protected function getPrevToken_($parent_id)
 
-     {
 
-         $childs = $this->tree_->getChilds($parent_id);
 
-         for ($i = count($childs); $i > 0; --$i)
 
-         {
 
-             $prev = $this->tree_->getNode($childs[$i-1]);
 
-             if ($prev->is(SieveToken::Comment|SieveToken::Whitespace))
 
-                 continue;
 
-             // use command owning a block or list instead of previous
 
-             if ($prev->is(SieveToken::BlockStart|SieveToken::Comma|SieveToken::LeftParenthesis))
 
-                 $prev = $this->tree_->getNode($parent_id);
 
-             return $prev;
 
-         }
 
-         return $this->tree_->getNode($parent_id);
 
-     }
 
-     /*******************************************************************************
 
-      * methods for recursive descent start below
 
-      */
 
-     public function passthroughWhitespaceComment($token)
 
-     {
 
-         return 0;
 
-     }
 
-     public function passthroughFunction($token)
 
-     {
 
-         $this->tree_->addChild($token);
 
-     }
 
-     public function parse($script)
 
-     {
 
-         $this->script_ = $script;
 
-         $this->scanner_ = new SieveScanner($this->script_);
 
-         // Define what happens with passthrough tokens like whitespacs and comments
 
-         $this->scanner_->setPassthroughFunc(
 
-             array(
 
-                 $this, 'passthroughWhitespaceComment'
 
-             )
 
-         );
 
-         $this->tree_ = new SieveTree('tree');
 
-         $this->commands_($this->tree_->getRoot());
 
-         if (!$this->scanner_->nextTokenIs(SieveToken::ScriptEnd)) {
 
-             $token = $this->scanner_->nextToken();
 
-             throw new SieveException($token, SieveToken::ScriptEnd);
 
-         }
 
-     }
 
-     protected function commands_($parent_id)
 
-     {
 
-         while (true)
 
-         {
 
-             if (!$this->scanner_->nextTokenIs(SieveToken::Identifier))
 
-                 break;
 
-             // Get and check a command token
 
-             $token = $this->scanner_->nextToken();
 
-             $semantics = new SieveSemantics($token, $this->getPrevToken_($parent_id));
 
-             // Process eventual arguments
 
-             $this_node = $this->tree_->addChildTo($parent_id, $token);
 
-             $this->arguments_($this_node, $semantics);
 
-             $token = $this->scanner_->nextToken();
 
-             if (!$token->is(SieveToken::Semicolon))
 
-             {
 
-                 // TODO: check if/when semcheck is needed here
 
-                 $semantics->validateToken($token);
 
-                 if ($token->is(SieveToken::BlockStart))
 
-                 {
 
-                     $this->tree_->addChildTo($this_node, $token);
 
-                     $this->block_($this_node, $semantics);
 
-                     continue;
 
-                 }
 
-                 throw new SieveException($token, SieveToken::Semicolon);
 
-             }
 
-             $semantics->done($token);
 
-             $this->tree_->addChildTo($this_node, $token);
 
-         }
 
-     }
 
-     protected function arguments_($parent_id, &$semantics)
 
-     {
 
-         while (true)
 
-         {
 
-             if ($this->scanner_->nextTokenIs(SieveToken::Number|SieveToken::Tag))
 
-             {
 
-                 // Check if semantics allow a number or tag
 
-                 $token = $this->scanner_->nextToken();
 
-                 $semantics->validateToken($token);
 
-                 $this->tree_->addChildTo($parent_id, $token);
 
-             }
 
-             else if ($this->scanner_->nextTokenIs(SieveToken::StringList))
 
-             {
 
-                 $this->stringlist_($parent_id, $semantics);
 
-             }
 
-             else
 
-             {
 
-                 break;
 
-             }
 
-         }
 
-         if ($this->scanner_->nextTokenIs(SieveToken::TestList))
 
-         {
 
-             $this->testlist_($parent_id, $semantics);
 
-         }
 
-     }
 
-     protected function stringlist_($parent_id, &$semantics)
 
-     {
 
-         if (!$this->scanner_->nextTokenIs(SieveToken::LeftBracket))
 
-         {
 
-             $this->string_($parent_id, $semantics);
 
-             return;
 
-         }
 
-         $token = $this->scanner_->nextToken();
 
-         $semantics->startStringList($token);
 
-         $this->tree_->addChildTo($parent_id, $token);
 
-         
 
-         if($this->scanner_->nextTokenIs(SieveToken::RightBracket)) {
 
-             //allow empty lists
 
-             $token = $this->scanner_->nextToken();
 
-             $this->tree_->addChildTo($parent_id, $token);
 
-             $semantics->endStringList();
 
-             return;
 
-         }
 
-         do
 
-         {
 
-             $this->string_($parent_id, $semantics);
 
-             $token = $this->scanner_->nextToken();
 
-             if (!$token->is(SieveToken::Comma|SieveToken::RightBracket))
 
-                 throw new SieveException($token, array(SieveToken::Comma, SieveToken::RightBracket));
 
-             if ($token->is(SieveToken::Comma))
 
-                 $semantics->continueStringList();
 
-             $this->tree_->addChildTo($parent_id, $token);
 
-         }
 
-         while (!$token->is(SieveToken::RightBracket));
 
-         $semantics->endStringList();
 
-     }
 
-     protected function string_($parent_id, &$semantics)
 
-     {
 
-         $token = $this->scanner_->nextToken();
 
-         $semantics->validateToken($token);
 
-         $this->tree_->addChildTo($parent_id, $token);
 
-     }
 
-     protected function testlist_($parent_id, &$semantics)
 
-     {
 
-         if (!$this->scanner_->nextTokenIs(SieveToken::LeftParenthesis))
 
-         {
 
-             $this->test_($parent_id, $semantics);
 
-             return;
 
-         }
 
-         $token = $this->scanner_->nextToken();
 
-         $semantics->validateToken($token);
 
-         $this->tree_->addChildTo($parent_id, $token);
 
-         do
 
-         {
 
-             $this->test_($parent_id, $semantics);
 
-             $token = $this->scanner_->nextToken();
 
-             if (!$token->is(SieveToken::Comma|SieveToken::RightParenthesis))
 
-             {
 
-                 throw new SieveException($token, array(SieveToken::Comma, SieveToken::RightParenthesis));
 
-             }
 
-             $this->tree_->addChildTo($parent_id, $token);
 
-         }
 
-         while (!$token->is(SieveToken::RightParenthesis));
 
-     }
 
-     protected function test_($parent_id, &$semantics)
 
-     {
 
-         // Check if semantics allow an identifier
 
-         $token = $this->scanner_->nextToken();
 
-         $semantics->validateToken($token);
 
-         // Get semantics for this test command
 
-         $this_semantics = new SieveSemantics($token, $this->getPrevToken_($parent_id));
 
-         $this_node = $this->tree_->addChildTo($parent_id, $token);
 
-         // Consume eventual argument tokens
 
-         $this->arguments_($this_node, $this_semantics);
 
-         // Check that all required arguments were there
 
-         $token = $this->scanner_->peekNextToken();
 
-         $this_semantics->done($token);
 
-     }
 
-     protected function block_($parent_id, &$semantics)
 
-     {
 
-         $this->commands_($parent_id, $semantics);
 
-         $token = $this->scanner_->nextToken();
 
-         if (!$token->is(SieveToken::BlockEnd))
 
-         {
 
-             throw new SieveException($token, SieveToken::BlockEnd);
 
-         }
 
-         $this->tree_->addChildTo($parent_id, $token);
 
-     }
 
- }
 
 
  |