Finite State Machines in jq - troyp/jq GitHub Wiki

Given these trivial wrappers around foreach:

def parse(stream; init; next; extract):
    foreach stream as $item (init; .item = $item | next; extract);

def parse(stream; init; next):
    parse(stream; init; next; select(.ready).result));

one can define a parser as just an init and next functions, with the next function being a switch statement matching on state:

def in_record_start: .state == "record_start";
def next_from_record_state: ...;
def csv_init: {.ready:false, .state:"record_start", .result:null};
def csv_next:
       (select(in_record_start) | next_from_record_start)
    // (select(in_double_quoted_field) | next_from_double_quoted_field)
    // ...;
def parse_csv(stream):
    parse(stream | explode[]; csv_init; csv_next);

Because jq has no "switch statement", we build one out of select(condition) | actions chained with the // operator.