Skip to content

HR271 is not determistic #173

@kputnam

Description

@kputnam

The HR271 standard contains one NM1 loop (Loop 2120) nested within another (Loop 2100). When the parser encounters an NM1 segment, it cannot decide whether to instantiate a new Loop 2120, or a whole new Loop 2100. The X279 and X279A1 implementations eliminate this ambiguity by using separate qualifiers, so the parser can figure out which loop is intended from the value in NM101.

Looking into this further, it seems X12 intends that the LS (loop start) and LE (loop end) segments alone would resolve the ambiguity. If the parser has read an NM1 segment after an LS but before an LE, then it must belong to Loop 2120. Otherwise, any NM1 encountered outside the LS and LE section would belong to Loop 2100.

d::LoopDef.build("2100", d::RepeatCount.unbounded,
  s::NM1.use( 300, r::Mandatory, d::RepeatCount.bounded(1)),
  ...

  d::LoopDef.build("2110", d::RepeatCount.unbounded,
    s:: EB.use(1300, r::Optional,  d::RepeatCount.bounded(1)),
    ...

    d::LoopDef.build("2115", d::RepeatCount.unbounded,
      s::III.use(2600, r::Optional,  d::RepeatCount.bounded(1)),
      ...

      d::LoopDef.build("2117", d::RepeatCount.unbounded,
        s:: LQ.use(3000, r::Optional,  d::RepeatCount.bounded(1)),
        ...

    d::LoopDef.build("2120 LS", d::RepeatCount.bounded(1),
      # @todo: NM1 3400 conflicts with NM1 at position 300, but
      # X279 states on page 328, regarding the LS segment:
      #
      #  1. Use this segment to identify the beginning of the
      #    Subscriber Benefit Related Entity Name loop. Because both
      #    the subscriber’s name loop and this loop begin with NM1
      #    segments, the LS and LE segments are used to
      #    differentiate these two loops.
      #
      # ParserError: too much non-determinism: SegmentUse(3400, NM1, O, 1), SegmentUse(300, NM1, M, 1)
      #
      s:: LS.use(3300, r::Optional,  d::RepeatCount.bounded(1)),

      d::LoopDef.build("2120", d::RepeatCount.unbounded,
        s::NM1.use(3400, r::Optional,  d::RepeatCount.bounded(1)),
        ...

      s:: LE.use(4000, r::Optional, d::RepeatCount.bounded(1))))))),

Currently the parser doesn't have special support of LS and LE segments. I don't think that is required here. Instead, the grammar could be changed so LE is required, and the parser would be changed to either not include the uncle loops in #successors, or to resolve the ambiguity by not choosing an uncle segment when a sibling is available. Recognizing the correct circumstances for this is important, and shouldn't be specific to LS and LE segments.

In the meantime, I will be disabling the HB271 standard, since there are automatically generated specs that will fail otherwise, and the grammar isn't usable in the real world anyway. The X279 implementation of HB271 won't be affected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions