mq-lang 0.5.13

Core language implementation for mq query language
Documentation
# JSON Implementation in mq

def _parse_json_value(input):
  let input = trim(input)

  |

  def handle_string_char(char, escaped, pos):
    if (char == "\"" && !escaped):
      [true, pos]
    elif (char == "\""):
      [false, !escaped]
    else:
      [false, false]
  end

  def _parse_string(input):
    let escaped = false
    | let pos = 1
    | let end_pos = None
    | let input_len = len(input)
    | let pos = while (is_none(end_pos) && pos < input_len):
          let char = input[pos]
          | let tokens = handle_string_char(char, escaped, pos)
          | let should_end = tokens[0]
          | let new_escaped = tokens[1]
          | let end_pos = if (should_end): pos else: None
          | let escaped = if (!should_end): new_escaped else: false
          | let pos = pos + 1
          | pos
        end
    | let str_content = input[1:pos - 1]
    | let remaining = input[pos:len(input)]
    | [str_content, remaining]
  end

  def _parse_number(input):
    let input = trim(input)
    | let number_pattern = "^(-?[0-9]+(?:\\.[0-9]+)?)"
    | let match_result = regex_match(input, number_pattern)
    | if (is_empty(match_result)):
        [None, input]
      else:
        do
          let number_str = first(match_result)
          | let remaining = input[len(number_str):len(input)]
          | [to_number(number_str), remaining]
        end
  end

  def _parse_boolean(input):
    let input = trim(input)
    | if (starts_with(input, "true")):
        [true, input[4:len(input)]]
      elif (starts_with(input, "false")):
        [false, input[5:len(input)]]
      else:
        [None, input]
  end

  def _parse_null(input):
    let input = trim(input)
    | if (starts_with(input, "null")):
        [None, input[4:len(input)]]
      else:
        [None, input]
  end

  def _parse_array_value(input):
    let input = input[1:len(input)]
    | let input = trim(input)
    | let elements = []
    | let finish = false
    | if (starts_with(input, "]")):
        [elements, input[1:len(input)]]
      else:
        while (!finish):
          let tokens = _parse_json_value(input)
          | let value = tokens[0]
          | let rest = tokens[1]
          | let elements = elements + [value]
          | let input = trim(rest)
          | if (is_none(value)): error("Invalid JSON array element")
          | let finish = starts_with(input, "]")
          | let input = if (starts_with(input, ",")):
                      trim(input[1:len(input)])
                    elif (starts_with(input, "]")):
                      trim(input[1:len(input)])
                    else:
                      error("Expected ',' or ']' in array")
          | [elements, input];
  end

  def _parse_array(input):
    let input = trim(input)
    | if (not(starts_with(input, "["))):
        [None, input]
      else:
        _parse_array_value(input)
  end

  def _parse_object_value(obj, key, input):
    let input = trim(input[1:len(input)])
    | let tokens = _parse_json_value(input)
    | let value = tokens[0]
    | let rest = tokens[1]
    | let obj = set(obj, key, value)
    | let input = trim(rest)
    | if (starts_with(input, ",")):
        [obj, trim(input[1:len(input)])]
      elif (starts_with(input, "}")):
        [obj, input]
      elif (is_empty(input)):
        [obj, trim(input)]
      else:
        error("Expected ',' or '}' in object")
  end

  def _parse_object(input):
    let input = input[1:len(input)]
    | let input = trim(input)
    | let obj = {}
    | let result = if (starts_with(input, "}")):
          [obj, input[1:len(input)]]
        else:
          while (!starts_with(input, "}") && !is_empty(input)):
            let tokens = _parse_string(input)
            | let key = tokens[0]
            | let input = trim(tokens[1])
            | if (is_none(key)): error("Invalid JSON object key")
            | if (!starts_with(input, ":")): error("Expected ':' after object key")
            | let result = _parse_object_value(obj, key, input)
            | let obj = result[0]
            | let input = trim(result[1])
            | let result = if (starts_with(input, ",")):
                          [obj, input[1:len(input)]]
                        else:
                          [obj, input]
            | let obj = result[0]
            | let input = trim(result[1])
            | [obj, input]
          end
    | let obj = result[0]
    | let input = result[1]
    | if (starts_with(input, "}")):
        [obj, trim(input[1:len(input)])]
      else:
        [obj, input]

  end

  def parse_object(input):
    let input = trim(input)
    | if (!starts_with(input, "{")):
        [None, input]
      else:
        _parse_object(input)
  end

  | if (starts_with(input, "{")):
      _parse_object(input)
    elif (starts_with(input, "[")):
      _parse_array(input)
    elif (starts_with(input, "\"")):
      _parse_string(input)
    elif (starts_with(input, "t") || starts_with(input, "f")):
      _parse_boolean(input)
    elif (starts_with(input, "n")):
      _parse_null(input)
    else:
      _parse_number(input)
end

# Parses a JSON string and returns the corresponding data structure.
def json_parse(input):
  let data = _parse_json_value(to_string(input))
  | data[0]
end

# Serializes a value to a JSON string.
def json_stringify(data):
  def _format_json_stringify(data):
    "\"" + data + "\""
  end

  def _json_array_stringify(data):
    "[" + join(map(data, json_stringify), ", ") + "]"
  end

  def _json_object_stringify(data):
    "{" + join(
      map(entries(data),
        fn(entry): "\"" + first(entry) + "\": " + json_stringify(last(entry));), ", ") + "}"
  end

  | if (is_string(data)):
      _format_json_stringify(data)
    elif (is_number(data)):
      to_string(data)
    elif (is_bool(data)):
      to_string(data)
    elif (is_none(data)):
      "null"
    elif (is_array(data)):
      _json_array_stringify(data)
    elif (is_dict(data)):
      _json_object_stringify(data)
    else:
      to_string(data)
end

# Converts a JSON data structure to a Markdown table.
def json_to_markdown_table(data):
  def _create_array_markdown_table(data):
    let headers = keys(first(data))
    | let header_row = "| " + join(headers, " | ") + " |"
    | let separator_row = "| " + join(map(headers, fn(_): "---";), " | ") + " |"
    | let data_rows = map(data, fn(row):
          "| " + join(map(headers, fn(header): if (is_none(row[header])): "" else: replace(to_string(row[header]), "\n", "\\n");), " | ") + " |"
        end)
    | [header_row, separator_row] + data_rows
    | join("\n")
  end

  def _create_dict_markdown_table(data):
    let headers = ["Key", "Value"]
    | let header_row = "| " + join(headers, " | ") + " |"
    | let separator_row = "| " + join(map(headers, fn(_): "---";), " | ") + " |"
    | let data_rows = map(keys(data), fn(key):
          "| " + key + " | " + (if (is_none(data[key])): "" else: replace(to_string(data[key]), "\n", "\\n")) + " |"
        end)
    | [header_row, separator_row] + data_rows
    | join("\n")
  end

  def _create_simple_markdown_table(data):
    "| Value |\n| --- |\n| " + to_string(data) + " |"
  end

  | if (is_array(data)):
      _create_array_markdown_table(data)
    elif (is_dict(data)):
      _create_dict_markdown_table(data)
    else:
      _create_simple_markdown_table(data)
end