NAME

Music::NWC2MusicXML::Parser - NWCTXT text parser producing an internal score representation.

VERSION

0.001.0

SYNOPSIS

use Music::NWC2MusicXML::Parser;

my $parser = Music::NWC2MusicXML::Parser->new;
my $score  = $parser->parse($nwctxt);

DESCRIPTION

Music::NWC2MusicXML::Parser accepts the NWCTXT string produced by Music::NWC2MusicXML::NWC and returns a Music::NWC2MusicXML::Score object.

The internal representation is completely independent of MusicXML so that parsing and MusicXML generation can be tested separately.

NWCTXT record structure

Each record occupies one line and begins with |:

|RecordType|Field1:Value1|Field2:Value2|...

Fields are pipe-delimited. Values may be:

  • unquoted single tokens

  • double-quoted strings (which may contain | and :)

  • comma-separated lists

The parser does not use split(/[|]/) because quoted values and escape sequences require a proper tokeniser.

new

Construct a parser.

Arguments

Named parameters:

diagnostics -- a Music::NWC2MusicXML::Diagnostics instance (optional).

Returns

Blessed Music::NWC2MusicXML::Parser object.

API SPECIFICATION

Input

diagnostics : Music::NWC2MusicXML::Diagnostics  (optional)

Output

Music::NWC2MusicXML::Parser object

FORMAL SPECIFICATION

[ParserInit]
  diagnostics : Diagnostics

(placeholder -- populate with Z calculus as implementation matures)

parse

Parse a complete NWCTXT string and return the corresponding Music::NWC2MusicXML::Score.

Purpose

This is the primary entry point. It iterates over each line of the NWCTXT, dispatches to a type-specific handler, and accumulates the results into a Score object.

Arguments

$nwctxt -- scalar string containing the full NWCTXT representation (required).

Returns

A Music::NWC2MusicXML::Score object.

Side Effects

Croaks on fatal structural errors (e.g. missing header). Issues warnings via diagnostics for non-fatal issues (e.g. unknown records).

Usage Example

my $score = Music::NWC2MusicXML::Parser->new->parse($nwctxt);

API SPECIFICATION

Input

$nwctxt : SCALAR (UTF-8, required)
            -- Valid domain: non-empty string beginning with the line
            --   '!NoteWorthyComposer(<version>)' followed by pipe-delimited records
            -- Invalid partitions:
            --   undef or '' -> croaks error_empty_input
            --   non-empty but missing header -> croaks error_no_header
            -- Boundary: MAX_RECORDS = 1,000,000 pipe-delimited records
            --   At exactly 1,000,000 records: accepted
            --   At 1,000,001+ records: croaks error_too_many_records

Output

Music::NWC2MusicXML::Score

MESSAGES

| Code | Meaning | Resolution | |-----------------------|------------------------------------------|-------------------------------| | error_empty_input | Input is undef or zero-length | Check NWC decoder output | | error_no_header | Header line not found | Verify NWC binary decoder | | error_too_many_records| Record count exceeds MAX_RECORDS | Input may be malicious/corrupt| | error_bad_record | Record cannot be tokenised | File may be corrupt | | error_no_staff | Event seen before first AddStaff | NWCTXT may be truncated | | warn_unknown_record | Unknown record type stored as Unsupported| New NWC version may add types |

FORMAL SPECIFICATION

[Parse]
  nwctxt? : NWCTXT
  ----------
  score!  : Score

(placeholder)

DIAGNOSTICS

MESSAGES

| Code | Meaning | Resolution | |------------------------|------------------------------------------|-----------------------------------| | error_empty_input | NWCTXT string is empty or undef | Check NWC decoder | | error_no_header | Header line absent | Verify NWCTXT output from decoder | | error_too_many_records | Record count exceeds MAX_RECORDS (1M) | Probable corrupt input | | error_bad_record | Record fails tokenisation | File may be corrupt | | error_no_staff | Musical event before any AddStaff | NWCTXT may be truncated | | warn_unknown_record | Unknown record type | New NWC version; file as UnsupportedEvent | | warn_bad_value | Field value not in recognised set | NWC file may use newer syntax |

LIMITATIONS

  • Note and Rest pitch/duration sub-field parsing is stubbed (Phase 2).

  • Tuplet time-modification is not yet applied to affected events (Phase 4).

  • The parser does not yet validate measure duration totals (Phase 3 / --validate).

  • Multi-voice detection within a single staff is deferred to the MusicXML generator.

AUTHOR

Nigel Horne <njh@nigelhorne.com>

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.