parse($lines); } public function parse(array $lines): Program { // In the first parsing stage, all words are parsed from the file. /** @var Word[] $words */ $words = []; foreach ($lines as $line) { $characters = str_split(trim($line) . ' '); $state = 'NONE'; $wordBuffer = []; foreach ($characters as $character) { if ('READING' === $state) { if ('-' === $character || is_numeric($character)) { $wordBuffer['value'] .= $character; continue; } // Word is finished $words[] = new Word($wordBuffer['register'], $wordBuffer['value']); $wordBuffer = []; $state = 'NONE'; continue; } if ('NONE' === $state && ctype_alpha($character)) { $state = 'READING'; $wordBuffer = ['register' => $character, 'value' => '']; continue; } if (stripos($line, 'EOF') !== false) { break 2; // End of program reached } if (';' === $character) { break; // Rest of line is a comment } } } // In the second stage, the words are ordered by N numbers // and shaped into a program $firstWord = array_shift($words); if (!preg_match('/^N9\d\d\d$/i', $firstWord)) { throw new RuntimeException('Expected program number, got ' . $firstWord); } $program = new Program($firstWord->value); $lineBuffer = null; foreach ($words as $word) { if ($word->register === 'N') { if (!is_null($lineBuffer)) { $program->addBlock($lineBuffer); } $lineBuffer = new Block($word->value); continue; } $lineBuffer->addWord($word); } return $program; } }