PageRenderTime 64ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/jay/net/xp_framework/tools/vm/emit/Emitter.class.php

https://github.com/thekid/xp-experiments
PHP | 200 lines | 138 code | 12 blank | 50 comment | 12 complexity | ba65e434dd141d1852e51b0027053e49 MD5 | raw file
  1. <?php
  2. /* This class is part of the XP framework's experiments
  3. *
  4. * $Id$
  5. */
  6. uses(
  7. 'net.xp_framework.tools.vm.CompileError',
  8. 'net.xp_framework.tools.vm.VNode',
  9. 'util.log.Traceable'
  10. );
  11. /**
  12. * Emitter
  13. *
  14. * @purpose Abstract base class
  15. */
  16. class Emitter extends Object implements Traceable {
  17. public
  18. $cat = NULL,
  19. $position = array(),
  20. $filename = '',
  21. $errors = array();
  22. /**
  23. * Emits an array of nodes
  24. *
  25. * @param net.xp_framework.tools.vm.VNode[] nodes
  26. */
  27. public function emitAll($nodes) {
  28. foreach ($nodes as $node) $this->emit($node);
  29. }
  30. /**
  31. * Set Filename
  32. *
  33. * @param string filename
  34. */
  35. public function setFilename($filename) {
  36. $this->filename= $filename;
  37. }
  38. /**
  39. * Get Filename
  40. *
  41. * @return string
  42. */
  43. public function getFilename() {
  44. return $this->filename;
  45. }
  46. /**
  47. * Adds an error
  48. *
  49. * @param net.xp_framework.tools.vm.CompileError error
  50. */
  51. public function addError($error) {
  52. $error->message.= ' at '.$this->filename.' line '.$this->position[0].' (offset '.$this->position[1].')';
  53. $this->errors[]= $error;
  54. }
  55. /**
  56. * Returns whether errors have occured
  57. *
  58. * @return bool
  59. */
  60. public function hasErrors() {
  61. return !empty($this->errors);
  62. }
  63. /**
  64. * Returns whether errors have occured
  65. *
  66. * @return net.xp_framework.tools.vm.CompileError[]
  67. */
  68. public function getErrors() {
  69. return $this->errors;
  70. }
  71. /**
  72. * Retrieves result
  73. *
  74. * @return string
  75. */
  76. public function getResult() { }
  77. /**
  78. * Emits a single node
  79. *
  80. * @param net.xp_framework.tools.vm.VNode node
  81. */
  82. public function emit($node) {
  83. if ($node instanceof VNode) {
  84. $this->position= $node->position;
  85. $func= 'emit'.ucfirst(substr(get_class($node), 0, -4));
  86. if (!method_exists($this, $func)) {
  87. $this->cat && $this->cat->error('No emitter for', $node);
  88. $this->addError(new CompileError(100, 'No emitter for '.$node->getClassName()));
  89. return;
  90. }
  91. $this->cat && $this->cat->debug($func, '(', $node->getClassName(), ')');
  92. $this->$func($node);
  93. return;
  94. } else if (is_array($node)) {
  95. $this->emitBlock($node);
  96. return;
  97. // -- FIXME: These should all be nodes! --------------------------------------------
  98. } else if ('"' == $node{0}) { // Double-quoted string
  99. $value= '';
  100. for ($i= 1, $s= strlen($node)- 1; $i < $s; $i++) {
  101. if ('\\' == $node{$i}) {
  102. switch ($node{$i+ 1}) {
  103. case 'r': $value.= "\r"; break;
  104. case 'n': $value.= "\n"; break;
  105. case 't': $value.= "\t"; break;
  106. case '"': $value.= '"'; break;
  107. case 'x': { // \x[0-9A-Fa-f]{1,2}, TBD: Checks needed? \xGG will break...
  108. $length= min(strspn($node, '0123456789abdefABCDEF', $i+ 2), 2);
  109. $value.= chr(hexdec(substr($node, $i+ 2, $length)));
  110. $i+= $length;
  111. break;
  112. }
  113. case '0': // \[0-7]{1,3}
  114. case '1':
  115. case '2':
  116. case '3':
  117. case '4':
  118. case '5':
  119. case '6':
  120. case '7': {
  121. $length= min(strspn($node, '01234567', $i+ 1), 3);
  122. $value.= chr(octdec(substr($node, $i+ 1, $length)));
  123. $i+= $length- 1;
  124. break;
  125. }
  126. }
  127. $i++;
  128. } else {
  129. $value.= $node{$i};
  130. }
  131. }
  132. $this->emitString($value);
  133. return;
  134. } else if ("'" == $node{0}) { // Single-quoted string
  135. $this->emitString(str_replace("\'", "'", substr($node, 1, -1)));
  136. return;
  137. } else if (is_int($node)) {
  138. $this->emitInteger($node);
  139. return;
  140. } else if (is_string($node)) {
  141. $this->emitConstant($node);
  142. return;
  143. }
  144. $this->cat && $this->cat->error('Cannot handle', $node);
  145. }
  146. /**
  147. * Emits a block
  148. *
  149. * @param net.xp_framework.tools.vm.VNode[] nodes
  150. */
  151. public function emitBlock($nodes) { }
  152. /**
  153. * Emits constants
  154. *
  155. * @param string name
  156. */
  157. public function emitConstant($name) { }
  158. /**
  159. * Emits constants
  160. *
  161. * @param string string
  162. */
  163. public function emitString($string) { }
  164. /**
  165. * Emits an integer
  166. *
  167. * @param int integer
  168. */
  169. public function emitInteger($integer) { }
  170. /**
  171. * Set a logger category for debugging
  172. *
  173. * @param util.log.LogCategory cat
  174. */
  175. public function setTrace($cat) {
  176. $this->cat= $cat;
  177. }
  178. }
  179. ?>