1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-10 12:29:01 +00:00

The parsers no longer own a tape, merely taking one as an argument. So they can be an adjunct.

This commit is contained in:
Thomas Harte 2016-11-06 15:25:18 -05:00
parent bc83a8f2d0
commit 093eb55fc6
3 changed files with 111 additions and 115 deletions

View File

@ -24,30 +24,30 @@ enum class SymbolType {
class Acorn1200BaudTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolType> { class Acorn1200BaudTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolType> {
public: public:
Acorn1200BaudTapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) : Acorn1200BaudTapeParser() :
TapeParser(tape), TapeParser(),
_crc(0x1021, 0x0000) {} _crc(0x1021, 0x0000) {}
int get_next_bit() int get_next_bit(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
SymbolType symbol = get_next_symbol(); SymbolType symbol = get_next_symbol(tape);
return (symbol == SymbolType::One) ? 1 : 0; return (symbol == SymbolType::One) ? 1 : 0;
} }
int get_next_byte() int get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
int value = 0; int value = 0;
int c = 8; int c = 8;
if(get_next_bit()) if(get_next_bit(tape))
{ {
set_error_flag(); set_error_flag();
return -1; return -1;
} }
while(c--) while(c--)
{ {
value = (value >> 1) | (get_next_bit() << 7); value = (value >> 1) | (get_next_bit(tape) << 7);
} }
if(!get_next_bit()) if(!get_next_bit(tape))
{ {
set_error_flag(); set_error_flag();
return -1; return -1;
@ -56,17 +56,17 @@ class Acorn1200BaudTapeParser: public StaticAnalyer::TapeParser<WaveType, Symbol
return value; return value;
} }
int get_next_short() int get_next_short(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
int result = get_next_byte(); int result = get_next_byte(tape);
result |= get_next_byte() << 8; result |= get_next_byte(tape) << 8;
return result; return result;
} }
int get_next_word() int get_next_word(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
int result = get_next_short(); int result = get_next_short(tape);
result |= get_next_short() << 8; result |= get_next_short(tape) << 8;
return result; return result;
} }
@ -117,22 +117,22 @@ class Acorn1200BaudTapeParser: public StaticAnalyer::TapeParser<WaveType, Symbol
NumberTheory::CRC16 _crc; NumberTheory::CRC16 _crc;
}; };
static std::unique_ptr<File::Chunk> GetNextChunk(Acorn1200BaudTapeParser &parser) static std::unique_ptr<File::Chunk> GetNextChunk(const std::shared_ptr<Storage::Tape::Tape> &tape, Acorn1200BaudTapeParser &parser)
{ {
std::unique_ptr<File::Chunk> new_chunk(new File::Chunk); std::unique_ptr<File::Chunk> new_chunk(new File::Chunk);
int shift_register = 0; int shift_register = 0;
// TODO: move this into the parser // TODO: move this into the parser
#define shift() shift_register = (shift_register >> 1) | (parser.get_next_bit() << 9) #define shift() shift_register = (shift_register >> 1) | (parser.get_next_bit(tape) << 9)
// find next area of high tone // find next area of high tone
while(!parser.is_at_end() && (shift_register != 0x3ff)) while(!tape->is_at_end() && (shift_register != 0x3ff))
{ {
shift(); shift();
} }
// find next 0x2a (swallowing stop bit) // find next 0x2a (swallowing stop bit)
while(!parser.is_at_end() && (shift_register != 0x254)) while(!tape->is_at_end() && (shift_register != 0x254))
{ {
shift(); shift();
} }
@ -145,9 +145,9 @@ static std::unique_ptr<File::Chunk> GetNextChunk(Acorn1200BaudTapeParser &parser
// read out name // read out name
char name[11]; char name[11];
int name_ptr = 0; int name_ptr = 0;
while(!parser.is_at_end() && name_ptr < sizeof(name)) while(!tape->is_at_end() && name_ptr < sizeof(name))
{ {
name[name_ptr] = (char)parser.get_next_byte(); name[name_ptr] = (char)parser.get_next_byte(tape);
if(!name[name_ptr]) break; if(!name[name_ptr]) break;
name_ptr++; name_ptr++;
} }
@ -155,15 +155,15 @@ static std::unique_ptr<File::Chunk> GetNextChunk(Acorn1200BaudTapeParser &parser
new_chunk->name = name; new_chunk->name = name;
// addresses // addresses
new_chunk->load_address = (uint32_t)parser.get_next_word(); new_chunk->load_address = (uint32_t)parser.get_next_word(tape);
new_chunk->execution_address = (uint32_t)parser.get_next_word(); new_chunk->execution_address = (uint32_t)parser.get_next_word(tape);
new_chunk->block_number = (uint16_t)parser.get_next_short(); new_chunk->block_number = (uint16_t)parser.get_next_short(tape);
new_chunk->block_length = (uint16_t)parser.get_next_short(); new_chunk->block_length = (uint16_t)parser.get_next_short(tape);
new_chunk->block_flag = (uint8_t)parser.get_next_byte(); new_chunk->block_flag = (uint8_t)parser.get_next_byte(tape);
new_chunk->next_address = (uint32_t)parser.get_next_word(); new_chunk->next_address = (uint32_t)parser.get_next_word(tape);
uint16_t calculated_header_crc = parser.get_crc(); uint16_t calculated_header_crc = parser.get_crc();
uint16_t stored_header_crc = (uint16_t)parser.get_next_short(); uint16_t stored_header_crc = (uint16_t)parser.get_next_short(tape);
stored_header_crc = (uint16_t)((stored_header_crc >> 8) | (stored_header_crc << 8)); stored_header_crc = (uint16_t)((stored_header_crc >> 8) | (stored_header_crc << 8));
new_chunk->header_crc_matched = stored_header_crc == calculated_header_crc; new_chunk->header_crc_matched = stored_header_crc == calculated_header_crc;
@ -171,13 +171,13 @@ static std::unique_ptr<File::Chunk> GetNextChunk(Acorn1200BaudTapeParser &parser
new_chunk->data.reserve(new_chunk->block_length); new_chunk->data.reserve(new_chunk->block_length);
for(int c = 0; c < new_chunk->block_length; c++) for(int c = 0; c < new_chunk->block_length; c++)
{ {
new_chunk->data.push_back((uint8_t)parser.get_next_byte()); new_chunk->data.push_back((uint8_t)parser.get_next_byte(tape));
} }
if(new_chunk->block_length && !(new_chunk->block_flag&0x40)) if(new_chunk->block_length && !(new_chunk->block_flag&0x40))
{ {
uint16_t calculated_data_crc = parser.get_crc(); uint16_t calculated_data_crc = parser.get_crc();
uint16_t stored_data_crc = (uint16_t)parser.get_next_short(); uint16_t stored_data_crc = (uint16_t)parser.get_next_short(tape);
stored_data_crc = (uint16_t)((stored_data_crc >> 8) | (stored_data_crc << 8)); stored_data_crc = (uint16_t)((stored_data_crc >> 8) | (stored_data_crc << 8));
new_chunk->data_crc_matched = stored_data_crc == calculated_data_crc; new_chunk->data_crc_matched = stored_data_crc == calculated_data_crc;
} }
@ -233,13 +233,13 @@ std::unique_ptr<File> GetNextFile(std::deque<File::Chunk> &chunks)
std::list<File> StaticAnalyser::Acorn::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape) std::list<File> StaticAnalyser::Acorn::GetFiles(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
Acorn1200BaudTapeParser parser(tape); Acorn1200BaudTapeParser parser;
// populate chunk list // populate chunk list
std::deque<File::Chunk> chunk_list; std::deque<File::Chunk> chunk_list;
while(!parser.is_at_end()) while(!tape->is_at_end())
{ {
std::unique_ptr<File::Chunk> chunk = GetNextChunk(parser); std::unique_ptr<File::Chunk> chunk = GetNextChunk(tape, parser);
if(chunk) if(chunk)
{ {
chunk_list.push_back(*chunk); chunk_list.push_back(*chunk);

View File

@ -49,7 +49,7 @@ struct Data {
class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolType> { class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolType> {
public: public:
CommodoreROMTapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) : CommodoreROMTapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) :
TapeParser(tape), TapeParser(),
_wave_period(0.0f), _wave_period(0.0f),
_previous_was_high(false), _previous_was_high(false),
_parity_byte(0) {} _parity_byte(0) {}
@ -58,11 +58,11 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
Advances to the next block on the tape, treating it as a header, then consumes, parses, and returns it. Advances to the next block on the tape, treating it as a header, then consumes, parses, and returns it.
Returns @c nullptr if any wave-encoding level errors are encountered. Returns @c nullptr if any wave-encoding level errors are encountered.
*/ */
std::unique_ptr<Header> get_next_header() std::unique_ptr<Header> get_next_header(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
return duplicate_match<Header>( return duplicate_match<Header>(
get_next_header_body(true), get_next_header_body(tape, true),
get_next_header_body(false) get_next_header_body(tape, false)
); );
} }
@ -70,29 +70,29 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
Advances to the next block on the tape, treating it as data, then consumes, parses, and returns it. Advances to the next block on the tape, treating it as data, then consumes, parses, and returns it.
Returns @c nullptr if any wave-encoding level errors are encountered. Returns @c nullptr if any wave-encoding level errors are encountered.
*/ */
std::unique_ptr<Data> get_next_data() std::unique_ptr<Data> get_next_data(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
return duplicate_match<Data>( return duplicate_match<Data>(
get_next_data_body(true), get_next_data_body(tape, true),
get_next_data_body(false) get_next_data_body(tape, false)
); );
} }
void spin() // void spin()
{ // {
while(!is_at_end()) // while(!is_at_end())
{ // {
SymbolType symbol = get_next_symbol(); // SymbolType symbol = get_next_symbol();
switch(symbol) // switch(symbol)
{ // {
case SymbolType::One: printf("1"); break; // case SymbolType::One: printf("1"); break;
case SymbolType::Zero: printf("0"); break; // case SymbolType::Zero: printf("0"); break;
case SymbolType::Word: printf(" "); break; // case SymbolType::Word: printf(" "); break;
case SymbolType::EndOfBlock: printf("\n"); break; // case SymbolType::EndOfBlock: printf("\n"); break;
case SymbolType::LeadIn: printf("-"); break; // case SymbolType::LeadIn: printf("-"); break;
} // }
} // }
} // }
private: private:
/*! /*!
@ -122,20 +122,20 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
return std::move(*copy_to_return); return std::move(*copy_to_return);
} }
std::unique_ptr<Header> get_next_header_body(bool is_original) std::unique_ptr<Header> get_next_header_body(const std::shared_ptr<Storage::Tape::Tape> &tape, bool is_original)
{ {
std::unique_ptr<Header> header(new Header); std::unique_ptr<Header> header(new Header);
reset_error_flag(); reset_error_flag();
// find and proceed beyond lead-in tone // find and proceed beyond lead-in tone
proceed_to_symbol(SymbolType::LeadIn); proceed_to_symbol(tape, SymbolType::LeadIn);
// look for landing zone // look for landing zone
proceed_to_landing_zone(is_original); proceed_to_landing_zone(tape, is_original);
reset_parity_byte(); reset_parity_byte();
// get header type // get header type
uint8_t header_type = get_next_byte(); uint8_t header_type = get_next_byte(tape);
switch(header_type) switch(header_type)
{ {
default: header->type = Header::Unknown; break; default: header->type = Header::Unknown; break;
@ -150,11 +150,11 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
header->data.reserve(191); header->data.reserve(191);
for(size_t c = 0; c < 191; c++) for(size_t c = 0; c < 191; c++)
{ {
header->data.push_back(get_next_byte()); header->data.push_back(get_next_byte(tape));
} }
uint8_t parity_byte = get_parity_byte(); uint8_t parity_byte = get_parity_byte();
header->parity_was_valid = get_next_byte() == parity_byte; header->parity_was_valid = get_next_byte(tape) == parity_byte;
// parse if this is not pure data // parse if this is not pure data
if(header->type != Header::DataBlock) if(header->type != Header::DataBlock)
@ -174,22 +174,22 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
} }
std::unique_ptr<Data> get_next_data_body(bool is_original) std::unique_ptr<Data> get_next_data_body(const std::shared_ptr<Storage::Tape::Tape> &tape, bool is_original)
{ {
std::unique_ptr<Data> data(new Data); std::unique_ptr<Data> data(new Data);
reset_error_flag(); reset_error_flag();
// find and proceed beyond lead-in tone to the next landing zone // find and proceed beyond lead-in tone to the next landing zone
proceed_to_symbol(SymbolType::LeadIn); proceed_to_symbol(tape, SymbolType::LeadIn);
proceed_to_landing_zone(is_original); proceed_to_landing_zone(tape, is_original);
reset_parity_byte(); reset_parity_byte();
// accumulate until the next non-word marker is hit // accumulate until the next non-word marker is hit
while(!is_at_end()) while(!tape->is_at_end())
{ {
SymbolType start_symbol = get_next_symbol(); SymbolType start_symbol = get_next_symbol(tape);
if(start_symbol != SymbolType::Word) break; if(start_symbol != SymbolType::Word) break;
data->data.push_back(get_next_byte_contents()); data->data.push_back(get_next_byte_contents(tape));
} }
// the above has reead the parity byte to the end of the data; if it matched the calculated parity it'll now be zero // the above has reead the parity byte to the end of the data; if it matched the calculated parity it'll now be zero
@ -205,13 +205,13 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
/*! /*!
Finds and completes the next landing zone. Finds and completes the next landing zone.
*/ */
void proceed_to_landing_zone(bool is_original) void proceed_to_landing_zone(const std::shared_ptr<Storage::Tape::Tape> &tape, bool is_original)
{ {
uint8_t landing_zone[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t landing_zone[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
while(!is_at_end()) while(!tape->is_at_end())
{ {
memmove(landing_zone, &landing_zone[1], sizeof(uint8_t) * 8); memmove(landing_zone, &landing_zone[1], sizeof(uint8_t) * 8);
landing_zone[8] = get_next_byte(); landing_zone[8] = get_next_byte(tape);
bool is_landing_zone = true; bool is_landing_zone = true;
for(int c = 0; c < 9; c++) for(int c = 0; c < 9; c++)
@ -230,11 +230,11 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
Swallows symbols until it reaches the first instance of the required symbol, swallows that Swallows symbols until it reaches the first instance of the required symbol, swallows that
and returns. and returns.
*/ */
void proceed_to_symbol(SymbolType required_symbol) void proceed_to_symbol(const std::shared_ptr<Storage::Tape::Tape> &tape, SymbolType required_symbol)
{ {
while(!is_at_end()) while(!tape->is_at_end())
{ {
SymbolType symbol = get_next_symbol(); SymbolType symbol = get_next_symbol(tape);
if(symbol == required_symbol) return; if(symbol == required_symbol) return;
} }
} }
@ -242,9 +242,9 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
/*! /*!
Swallows the next byte; sets the error flag if it is not equal to @c value. Swallows the next byte; sets the error flag if it is not equal to @c value.
*/ */
void expect_byte(uint8_t value) void expect_byte(const std::shared_ptr<Storage::Tape::Tape> &tape, uint8_t value)
{ {
uint8_t next_byte = get_next_byte(); uint8_t next_byte = get_next_byte(tape);
if(next_byte != value) set_error_flag(); if(next_byte != value) set_error_flag();
} }
@ -256,10 +256,10 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
/*! /*!
Proceeds to the next word marker then returns the result of @c get_next_byte_contents. Proceeds to the next word marker then returns the result of @c get_next_byte_contents.
*/ */
uint8_t get_next_byte() uint8_t get_next_byte(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
proceed_to_symbol(SymbolType::Word); proceed_to_symbol(tape, SymbolType::Word);
return get_next_byte_contents(); return get_next_byte_contents(tape);
} }
/*! /*!
@ -267,13 +267,13 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
Returns a byte composed of the first eight of those as bits; sets the error flag if any symbol is not Returns a byte composed of the first eight of those as bits; sets the error flag if any symbol is not
::One and not ::Zero, or if the ninth bit is not equal to the odd parity of the other eight. ::One and not ::Zero, or if the ninth bit is not equal to the odd parity of the other eight.
*/ */
uint8_t get_next_byte_contents() uint8_t get_next_byte_contents(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
int byte_plus_parity = 0; int byte_plus_parity = 0;
int c = 9; int c = 9;
while(c--) while(c--)
{ {
SymbolType next_symbol = get_next_symbol(); SymbolType next_symbol = get_next_symbol(tape);
if((next_symbol != SymbolType::One) && (next_symbol != SymbolType::Zero)) set_error_flag(); if((next_symbol != SymbolType::One) && (next_symbol != SymbolType::Zero)) set_error_flag();
byte_plus_parity = (byte_plus_parity >> 1) | (((next_symbol == SymbolType::One) ? 1 : 0) << 8); byte_plus_parity = (byte_plus_parity >> 1) | (((next_symbol == SymbolType::One) ? 1 : 0) << 8);
} }
@ -292,10 +292,10 @@ class CommodoreROMTapeParser: public StaticAnalyer::TapeParser<WaveType, SymbolT
/*! /*!
Returns the result of two consecutive @c get_next_byte calls, arranged in little-endian format. Returns the result of two consecutive @c get_next_byte calls, arranged in little-endian format.
*/ */
uint16_t get_next_short() uint16_t get_next_short(const std::shared_ptr<Storage::Tape::Tape> &tape)
{ {
uint16_t value = get_next_byte(); uint16_t value = get_next_byte(tape);
value |= get_next_byte() << 8; value |= get_next_byte(tape) << 8;
return value; return value;
} }
@ -376,13 +376,13 @@ std::list<File> StaticAnalyser::Commodore::GetFiles(const std::shared_ptr<Storag
CommodoreROMTapeParser parser(tape); CommodoreROMTapeParser parser(tape);
std::list<File> file_list; std::list<File> file_list;
std::unique_ptr<Header> header = parser.get_next_header(); std::unique_ptr<Header> header = parser.get_next_header(tape);
while(!parser.is_at_end()) while(!tape->is_at_end())
{ {
if(!header) if(!header)
{ {
header = parser.get_next_header(); header = parser.get_next_header(tape);
continue; continue;
} }
@ -398,9 +398,9 @@ std::list<File> StaticAnalyser::Commodore::GetFiles(const std::shared_ptr<Storag
new_file.type = File::DataSequence; new_file.type = File::DataSequence;
new_file.data.swap(header->data); new_file.data.swap(header->data);
while(!parser.is_at_end()) while(!tape->is_at_end())
{ {
header = parser.get_next_header(); header = parser.get_next_header(tape);
if(!header) continue; if(!header) continue;
if(header->type != Header::DataBlock) break; if(header->type != Header::DataBlock) break;
std::copy(header->data.begin(), header->data.end(), std::back_inserter(new_file.data)); std::copy(header->data.begin(), header->data.end(), std::back_inserter(new_file.data));
@ -413,7 +413,7 @@ std::list<File> StaticAnalyser::Commodore::GetFiles(const std::shared_ptr<Storag
case Header::RelocatableProgram: case Header::RelocatableProgram:
case Header::NonRelocatableProgram: case Header::NonRelocatableProgram:
{ {
std::unique_ptr<Data> data = parser.get_next_data(); std::unique_ptr<Data> data = parser.get_next_data(tape);
if(data) if(data)
{ {
File new_file; File new_file;
@ -427,12 +427,12 @@ std::list<File> StaticAnalyser::Commodore::GetFiles(const std::shared_ptr<Storag
file_list.push_back(new_file); file_list.push_back(new_file);
} }
header = parser.get_next_header(); header = parser.get_next_header(tape);
} }
break; break;
default: default:
header = parser.get_next_header(); header = parser.get_next_header(tape);
break; break;
} }
} }

View File

@ -21,14 +21,32 @@ namespace StaticAnalyer {
template <typename WaveType, typename SymbolType> class TapeParser { template <typename WaveType, typename SymbolType> class TapeParser {
public: public:
/// Instantiates a new parser with the supplied @c tape. /// Instantiates a new parser with the supplied @c tape.
TapeParser(const std::shared_ptr<Storage::Tape::Tape> &tape) : _tape(tape), _has_next_symbol(false), _error_flag(false) {} TapeParser() : _has_next_symbol(false), _error_flag(false) {}
/// Resets the error flag. /// Resets the error flag.
void reset_error_flag() { _error_flag = false; } void reset_error_flag() { _error_flag = false; }
/// @returns @c true if an error has occurred since the error flag was last reset; @c false otherwise. /// @returns @c true if an error has occurred since the error flag was last reset; @c false otherwise.
bool get_error_flag() { return _error_flag; } bool get_error_flag() { return _error_flag; }
/// @returns @c true if the encapsulated tape has reached its end; @c false otherwise.
bool is_at_end() { return _tape->is_at_end(); } /*!
Asks the parser to continue taking pulses from the tape until either the subclass next declares a symbol
or the tape runs out, returning the most-recently declared symbol.
*/
SymbolType get_next_symbol(const std::shared_ptr<Storage::Tape::Tape> &tape)
{
while(!_has_next_symbol && !tape->is_at_end())
{
process_pulse(tape->get_next_pulse());
}
_has_next_symbol = false;
return _next_symbol;
}
/*!
Should be implemented by subclasses. Consumes @c pulse. Is likely either to call @c push_wave
or to take no action.
*/
virtual void process_pulse(Storage::Tape::Tape::Pulse pulse) = 0;
protected: protected:
@ -67,20 +85,6 @@ template <typename WaveType, typename SymbolType> class TapeParser {
remove_waves(number_of_waves); remove_waves(number_of_waves);
} }
/*!
Asks the parser to continue taking pulses from the tape until either the subclass next declares a symbol
or the tape runs out, returning the most-recently declared symbol.
*/
SymbolType get_next_symbol()
{
while(!_has_next_symbol && !is_at_end())
{
process_pulse(_tape->get_next_pulse());
}
_has_next_symbol = false;
return _next_symbol;
}
void set_error_flag() void set_error_flag()
{ {
_error_flag = true; _error_flag = true;
@ -89,12 +93,6 @@ template <typename WaveType, typename SymbolType> class TapeParser {
private: private:
bool _error_flag; bool _error_flag;
/*!
Should be implemented by subclasses. Consumes @c pulse. Is likely either to call @c push_wave
or to take no action.
*/
virtual void process_pulse(Storage::Tape::Tape::Pulse pulse) = 0;
/*! /*!
Should be implemented by subclasses. Inspects @c waves for a potential new symbol. If one is Should be implemented by subclasses. Inspects @c waves for a potential new symbol. If one is
found should call @c push_symbol. May wish alternatively to call @c remove_waves to have entries found should call @c push_symbol. May wish alternatively to call @c remove_waves to have entries
@ -106,8 +104,6 @@ template <typename WaveType, typename SymbolType> class TapeParser {
std::vector<WaveType> _wave_queue; std::vector<WaveType> _wave_queue;
SymbolType _next_symbol; SymbolType _next_symbol;
bool _has_next_symbol; bool _has_next_symbol;
std::shared_ptr<Storage::Tape::Tape> _tape;
}; };
} }