fork download
  1. Лучше бы переделать чтобы хватало всем одного общего инстанса токенайзера. Ибо я не представляю зачем их плодить. Это нездоровая идея.
  2.  
  3. Соответственно в парсер передается не текст, а этот токенайзер и тем самым мы уменьшаем связность между ними.
  4.  
  5. То, что у тебя функция в одном аргументе принимает как набор токенов, так и текст тоже нехорошо — лучше принимать токенайзер.
  6.  
  7. И я тут подумал, удобно бы завести отдельный токен для закрывающего тега, [/ чтобы по одному токену было видно, открывающий у нас тег или закрывающий.
  8.  
  9. Функцию parse надо бы разбить на две: в одной цикл while, в другой switch. Вот так:
  10.  
  11. parseMixedContent() {
  12. ...
  13. while (не конец текста и не [/) {
  14. $nodes[] = $this->parseTagOrText();
  15. }
  16.  
  17. return $nodes;
  18. }
  19.  
  20. // парсит одну пару тегов либо кусок текста
  21. parseTagOrText() {
  22. if (текущий токен == [) {
  23. return parseTagPair();
  24. } иначе если текщий токен == [/) {
  25. ошибка;
  26. } else {
  27. return parsePlainText();
  28. }
  29. }
  30.  
  31. parseTagpair() {
  32. $node = parseOpeningTag();
  33. if (!$node->isTag()) {
  34. return $node; // дальше идти нет смысла
  35. }
  36.  
  37. do {
  38. $node->addChildren(parseMixedConent());
  39. $closingNode = parseClosingTag();
  40. if (тег не распарсился) {
  41. $content[] = $closingNode;
  42. } while (не нашли закрывающий тег);
  43.  
  44. $node->addChildren($content);
  45. return $node;
  46. }
  47.  
  48. switch кстати у тебя как-то странно оформлен, в плане отступов и переносов, первый раз такое вижу. У тебя вообще как-то код ужасно тесно оформлен, по несколько операторов на строчке, зачем так? И зачем все классы в один файл сваливать? Тяжело читать же.
  49.  
  50. if слишком глубоко вложены местами, надо разбивать на функции.
  51.  
  52. Не стоит писать вот так:
  53.  
  54. $x ? doSmth() : doElse()
  55.  
  56. Для этого есть if. Тернарный оператор используется в других случаях.
  57.  
Success #stdin #stdout 0.01s 20568KB
stdin
Standard input is empty
stdout
Лучше бы переделать чтобы хватало всем одного общего инстанса токенайзера. Ибо я не представляю зачем их плодить. Это нездоровая идея.

Соответственно в парсер передается не текст, а этот токенайзер и тем самым мы уменьшаем связность между ними. 

То, что у тебя функция в одном аргументе принимает как набор токенов, так и текст тоже нехорошо — лучше принимать токенайзер.

И я тут подумал, удобно бы завести отдельный токен для закрывающего тега, [/ чтобы по одному токену было видно, открывающий у нас тег или закрывающий.

Функцию parse надо бы разбить на две: в одной цикл while, в другой switch. Вот так: 

parseMixedContent() {
...
while (не конец текста и не [/) {
$nodes[] = $this->parseTagOrText();
}

return $nodes;
}

// парсит одну пару тегов либо кусок текста
parseTagOrText() {
if (текущий токен == [) {
return parseTagPair();
} иначе если текщий токен == [/) {
ошибка;
} else {
return parsePlainText();
}
}

parseTagpair() {
$node = parseOpeningTag();
if (!$node->isTag()) {
return $node; // дальше идти нет смысла
}

do {
$node->addChildren(parseMixedConent());
$closingNode = parseClosingTag();
if (тег не распарсился) {
$content[] = $closingNode;
} while (не нашли закрывающий тег);

$node->addChildren($content);
return $node;
}

switch кстати у тебя как-то странно оформлен,  в плане отступов и переносов, первый раз такое вижу. У тебя вообще как-то код ужасно тесно оформлен, по несколько операторов на строчке, зачем так? И зачем все классы в один файл сваливать? Тяжело читать же. 

if слишком глубоко вложены местами, надо разбивать на функции.

Не стоит писать вот так: 

$x ? doSmth() : doElse()

Для этого есть if. Тернарный оператор используется в других случаях.