#! /usr/bin/env -S awk -f BEGIN { indentationSize = 0; indentType = ""; indent = 0; errors = errors ? errors : "/dev/null"; hasColon = 0; hasLeading = 0; indentString = ""; asserted = 0; } function assert(condition, string) { if (!condition) { printf("%s:%d: assertion failed: %s\n", FILENAME, FNR, string) asserted = 1 exit 1 } } function setIndentSpace(line, countString) { if (indentType == "") { indentType = " "; } assert(indentType == " ", "Indentation character changed to non-space"); countString = line; sub(/[^ ].*$/, "", countString); indentString = countString; size = length(countString); if (indentationSize == 0) { indentationSize = size; } if (size == indentationSize * indent) { # Ok } else if (size == indentationSize * (indent - 1)) { if (prevHasColon) { assert(0, "Current line must be indented because previous ends with colon"); } # Dedent: indent -= 1; } else if (size == indentationSize * (indent + 1)) { assert(0, "Indentation detected without previous line ending in a colon (:)"); } else { assert(0, "Indentation must be a multiple of the initial indentation count"); } hasLeading = 1; } function setIndentTab(line) { if (indentType == "") { indentType = "\t"; } assert(indentType == "\t", "Indentation character changed to non-tab"); countString = line; sub(/[^\t].*$/, "", countString); indentString = countString; size = length(countString); if (indentationSize == 0) { indentationSize = size; } if (size == indentationSize * indent) { # Ok } else if (size == indentationSize * (indent - 1)) { if (prevHasColon) { assert(0, "Current line must be indented because previous ends with colon"); } # Dedent: indent -= 1; } else if (size == indentationSize * (indent + 1)) { assert(0, "Indentation detected without previous line ending in a colon (:)"); } else { assert(0, "Indentation must be a multiple of the initial indentation count"); } hasLeading = 1; } function handleLine(line, idx) { for (idx = 0; idx < indent * indentationSize; idx += 1) { printf("%s", indentType); } if (hasLeading == 0) { for (idx = 0; idx < indent; idx += 1) { printf(")"); } if (indent > 0) printf("\n"); indent = 0; } sub(/^[\t ]*/, "", line); sub(/:$/, "", line); printf("(%s", line); if (hasColon == 0) { printf(")"); } printf("\n"); prepareForNextLine(); } function prepareForNextLine() { if (hasColon) { indent += 1; prevHasColon = 1; } else { prevHasColon = 0; } hasColon = 0; hasLeading = 0; } function handleEmptyLine() { for (idx = 0; idx < indent * indentationSize; idx += 1) { printf("%s", indentType); } for (idx = 0; idx < indent; idx += 1) { printf(")"); } printf("\n"); indent = 0; prepareForNextLine(); } # // { print("LINE:", $0, "INDENT:", indent); } /^(\t| )*;/ { prepareForNextLine(); print; next; } /^$/ { handleEmptyLine(); next; } /^(\t| )*\\ [^\\]/ { sub(/\\ /, "", $0); print; next; } /^(\t| )*\\\\/ { sub(/\\\\/, "\\", $0); } /:(\r)?$/ { hasColon = 1; } /^ +[^ ].*/ { setIndentSpace($0); } /^\t+[^\t].*/ { setIndentTab($0); } // { handleLine($0); } END { if (!asserted) { handleEmptyLine(); } }