1<?php 2 3/** 4 * Hoa 5 * 6 * 7 * @license 8 * 9 * New BSD License 10 * 11 * Copyright © 2007-2017, Hoa community. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions are met: 15 * * Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * * Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * * Neither the name of the Hoa nor the names of its contributors may be 21 * used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37namespace Hoa\Compiler\Llk\Sampler; 38 39use Hoa\Compiler; 40use Hoa\Consistency; 41use Hoa\Visitor; 42 43/** 44 * Class \Hoa\Compiler\Llk\Sampler. 45 * 46 * Sampler parent. 47 * 48 * @copyright Copyright © 2007-2017 Hoa community 49 * @license New BSD License 50 */ 51abstract class Sampler 52{ 53 /** 54 * Compiler. 55 * 56 * @var \Hoa\Compiler\Llk\Parser 57 */ 58 protected $_compiler = null; 59 60 /** 61 * Tokens. 62 * 63 * @var array 64 */ 65 protected $_tokens = null; 66 67 /** 68 * All rules (from the compiler). 69 * 70 * @var array 71 */ 72 protected $_rules = null; 73 74 /** 75 * Token sampler. 76 * 77 * @var \Hoa\Visitor\Visit 78 */ 79 protected $_tokenSampler = null; 80 81 /** 82 * Root rule name. 83 * 84 * @var string 85 */ 86 protected $_rootRuleName = null; 87 88 /** 89 * Current token namespace. 90 * 91 * @var string 92 */ 93 protected $_currentNamespace = 'default'; 94 95 /** 96 * Skip tokens AST. 97 * 98 * @var array 99 */ 100 protected $_skipTokenAST = []; 101 102 103 /** 104 * Construct a generator. 105 * 106 * @param \Hoa\Compiler\Llk\Parser $compiler Compiler/parser. 107 * @param \Hoa\Visitor\Visit $tokenSampler Token sampler. 108 */ 109 public function __construct( 110 Compiler\Llk\Parser $compiler, 111 Visitor\Visit $tokenSampler 112 ) { 113 $this->_compiler = $compiler; 114 $this->_tokens = $compiler->getTokens(); 115 $this->_rules = $compiler->getRules(); 116 $this->_tokenSampler = $tokenSampler; 117 $this->_rootRuleName = $compiler->getRootRule(); 118 119 return; 120 } 121 122 /** 123 * Get compiler. 124 * 125 * @return \Hoa\Compiler\Llk\Parser 126 */ 127 public function getCompiler() 128 { 129 return $this->_compiler; 130 } 131 132 /** 133 * Get the AST of the current namespace skip token. 134 * 135 * @return \Hoa\Compiler\Llk\TreeNode 136 */ 137 protected function getSkipTokenAST() 138 { 139 if (!isset($this->_skipTokenAST[$this->_currentNamespace])) { 140 $token = new Compiler\Llk\Rule\Token( 141 -1, 142 'skip', 143 null, 144 -1 145 ); 146 147 $token->setRepresentation( 148 $this->_tokens[$this->_currentNamespace]['skip'] 149 ); 150 151 $this->_skipTokenAST[$this->_currentNamespace] = $token->getAST(); 152 } 153 154 return $this->_skipTokenAST[$this->_currentNamespace]; 155 } 156 157 /** 158 * Complete a token (namespace and representation). 159 * It returns the next namespace. 160 * 161 * @param \Hoa\Compiler\Llk\Rule\Token $token Token. 162 * @return string 163 */ 164 protected function completeToken(Compiler\Llk\Rule\Token $token) 165 { 166 if (null !== $token->getRepresentation()) { 167 return $this->_currentNamespace; 168 } 169 170 $name = $token->getTokenName(); 171 $token->setNamespace($this->_currentNamespace); 172 $toNamespace = $this->_currentNamespace; 173 174 if (isset($this->_tokens[$this->_currentNamespace][$name])) { 175 $token->setRepresentation( 176 $this->_tokens[$this->_currentNamespace][$name] 177 ); 178 } else { 179 foreach ($this->_tokens[$this->_currentNamespace] as $_name => $regex) { 180 if (false === strpos($_name, ':')) { 181 continue; 182 } 183 184 list($_name, $toNamespace) = explode(':', $_name, 2); 185 186 if ($_name === $name) { 187 break; 188 } 189 } 190 191 $token->setRepresentation($regex); 192 } 193 194 return $toNamespace; 195 } 196 197 /** 198 * Set current token namespace. 199 * 200 * @param string $namespace Token namespace. 201 * @return string 202 */ 203 protected function setCurrentNamespace($namespace) 204 { 205 $old = $this->_currentNamespace; 206 $this->_currentNamespace = $namespace; 207 208 return $old; 209 } 210 211 /** 212 * Generate a token value. 213 * Complete and set next token namespace. 214 * 215 * @param \Hoa\Compiler\Llk\Rule\Token $token Token. 216 * @return string 217 */ 218 protected function generateToken(Compiler\Llk\Rule\Token $token) 219 { 220 $toNamespace = $this->completeToken($token); 221 $this->setCurrentNamespace($toNamespace); 222 223 $out = $this->_tokenSampler->visit($token->getAST()); 224 225 if (isset($this->_tokens[$this->_currentNamespace]['skip'])) { 226 $out .= $this->_tokenSampler->visit($this->getSkipTokenAST()); 227 } 228 229 return $out; 230 } 231} 232 233/** 234 * Flex entity. 235 */ 236Consistency::flexEntity('Hoa\Compiler\Llk\Sampler\Sampler'); 237