/lib/Compiler.php

https://github.com/noyse1987/nephrite · PHP · 166 lines · 129 code · 30 blank · 7 comment · 17 complexity · 6f8f42e7dc786b5cf73cf8b9fa2eb9b5 MD5 · raw file

  1. <?php
  2. namespace lib;
  3. class Compiler {
  4. protected $_buffer;
  5. protected $_debug = false;
  6. protected $_doctype;
  7. protected $_doctypes = array(
  8. '5' => '<!DOCTYPE html>',
  9. 'html' => '<!DOCTYPE html>',
  10. 'xml' => '<?xml version="1.0" encoding="utf-8" ?>',
  11. 'default' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
  12. 'transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
  13. 'strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
  14. 'frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
  15. '1.1' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
  16. 'basic' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
  17. 'mobile' => '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
  18. );
  19. protected $_has_compiled_doctype = false;
  20. protected $_has_compiled_tag = false;
  21. protected $_indents = 0;
  22. protected $_inline_tags = array(
  23. 'a',
  24. 'abbr',
  25. 'acronym',
  26. 'b',
  27. 'br',
  28. 'code',
  29. 'em',
  30. 'font',
  31. 'i',
  32. 'img',
  33. 'ins',
  34. 'kbd',
  35. 'map',
  36. 'samp',
  37. 'small',
  38. 'span',
  39. 'strong',
  40. 'sub',
  41. 'sup'
  42. );
  43. protected $_node;
  44. protected $_options;
  45. protected $_pp = false;
  46. protected $_self_closing = array(
  47. 'meta',
  48. 'img',
  49. 'link',
  50. 'input',
  51. 'area',
  52. 'base',
  53. 'col',
  54. 'br',
  55. 'hr'
  56. );
  57. protected $_terse;
  58. protected $_xml;
  59. public function __construct($node, $options = array()) {
  60. $this->_options = $options;
  61. $this->_node = $node;
  62. $this->_pp = $options['pretty'] || false;
  63. $this->_debug = ( $options['compile_debug'] !== false );
  64. if ( $options['doctype'] ) {
  65. $this->_set_doctype($options['doctype']);
  66. }
  67. }
  68. protected function _buffer($str, $esc) {
  69. if ( $esc ) {
  70. $str = htmlentities($str, ENT_QUOTES);
  71. }
  72. $this->_buffer[$str];
  73. }
  74. /**
  75. * Returns the classname without the namespace.
  76. *
  77. * @param object|string $obj The object or class name from which to retrieve the classname.
  78. * @access public
  79. * @return string
  80. */
  81. protected function _classname_only($obj) {
  82. if ( !is_object($obj) && !is_string($obj) ) {
  83. return false;
  84. }
  85. $class = explode('\\', ( is_string($obj) ) ? $obj : get_class($obj));
  86. return array_pop($class);
  87. }
  88. public function compile() {
  89. $this->_buffer = array('var interp;');
  90. $this->_visit($this->_node);
  91. return implode("\n", $this->_buffer);
  92. }
  93. protected function _line($node) {
  94. if ( method_exists($node, 'get_instrument_line_number') ) {
  95. if ( $node->get_instrument_line_number() ) {
  96. return false;
  97. }
  98. }
  99. $this->_buffer[] = '__.lineno = ' . $node->get_line() . ';';
  100. }
  101. protected function _set_doctype($name = 'default') {
  102. $doctype = $this->_doctypes[strtolower($name)];
  103. if ( !$doctype ) {
  104. throw new \Exception('Unknown doctype "' . $name . '".');
  105. }
  106. $this->_doctype = $doctype;
  107. $this->_terse = ( $name == '5' || $name == 'html');
  108. $this->_xml = ( strpos($doctype, '<?xml') === 0 );
  109. }
  110. protected function _visit($node) {
  111. if ( $this->_debug ) {
  112. $this->_line($node);
  113. }
  114. return $this->_visit_node($node);
  115. }
  116. protected function _visit_block($block) {
  117. foreach ( $block->get_nodes() as $node ) {
  118. $this->_visit($node);
  119. }
  120. }
  121. protected function _visit_doctype($doctype) {
  122. if ( $doctype && ($doctype['val'] || !$this->_doctype) ) {
  123. $this->_set_doctype($doctype['val'] || 'default');
  124. }
  125. if ( $this->_doctype ) {
  126. $this->_buffer($this->_doctype);
  127. }
  128. $this->_has_compiled_doctype = true;
  129. }
  130. protected function _visit_node($node) {
  131. $name = strtolower($this->_classname_only($node));
  132. $method = '_visit_' . $name;
  133. return $this->$method($node);
  134. }
  135. }
  136. ?>