Initial commit
This commit is contained in:
23
src/Program/Block.php
Normal file
23
src/Program/Block.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Program;
|
||||
|
||||
class Block
|
||||
{
|
||||
public string $N;
|
||||
/** @var Word[] */
|
||||
public array $words;
|
||||
|
||||
|
||||
public function __construct(string $N)
|
||||
{
|
||||
$this->N = $N;
|
||||
$this->words = [];
|
||||
}
|
||||
|
||||
|
||||
public function addWord(Word $word): void
|
||||
{
|
||||
$this->words[] = $word;
|
||||
}
|
||||
}
|
||||
38
src/Program/Program.php
Normal file
38
src/Program/Program.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Program;
|
||||
|
||||
use ArrayIterator;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
|
||||
class Program implements IteratorAggregate
|
||||
{
|
||||
public int $N;
|
||||
/** @var Block[] */
|
||||
private array $blocks;
|
||||
|
||||
|
||||
public function __construct(int $N)
|
||||
{
|
||||
$this->N = $N;
|
||||
$this->blocks = [];
|
||||
}
|
||||
|
||||
|
||||
public function addBlock(Block $block): self
|
||||
{
|
||||
$this->blocks[] = $block;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ArrayIterator|Traversable|Block[]
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->blocks);
|
||||
}
|
||||
}
|
||||
77
src/Program/ProgramParser.php
Normal file
77
src/Program/ProgramParser.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Program;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class ProgramParser
|
||||
{
|
||||
public function parseFile(string $filename): Program
|
||||
{
|
||||
$lines = explode(PHP_EOL, file_get_contents($filename));
|
||||
$lines = array_filter($lines);
|
||||
|
||||
return $this->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;
|
||||
}
|
||||
}
|
||||
28
src/Program/Word.php
Normal file
28
src/Program/Word.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Program;
|
||||
|
||||
class Word
|
||||
{
|
||||
public string $register;
|
||||
public int $value;
|
||||
|
||||
|
||||
public function __construct(string $register, int $value)
|
||||
{
|
||||
$this->register = $register;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
return "{$this->register}{$this->value}";
|
||||
}
|
||||
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user