#!xed !# Use it as 'ed wisp-file.w < /path/to/wisp.ed !# The wisp-file.w is overwritten with resulting Scheme forms !# You can change the "w" line in the bottom of the script with ",p" to !# print the new contents to stdout instead. !# Comments are stripped in the process, unfortunately H !# Remove trailing periods (REPL-friendly ones) g/ \.$/s/// !# Replace leading underscores with spaces g/^\(_*\)_____/s//\1 /g g/^\(_*\)____/s//\1 /g g/^\(_*\)___/s//\1 /g g/^\(_*\)__/s//\1 /g g/^_/s// /g !# Remove comments g/;/s/\([^;]*\);*.*/\1/ !# Remove trailing spaces (after comments) g/./s/[[:space:]]*$// !# Convert parens to double square brackets !# (for now, to not break the parsing rules) !# Useful for inline parenthesized forms: !# setf (slot-value stream 'buffer) nil g/(/s/(/[[/g g/)/s/)/]]/g !# Remove resulting empty lines g/^[ ]*$/d !# Join lines with semicolons (there are none left) !# Also add one semicolon to the front (useful in wrapping forms below) g/$/s//;/ ,j s/^/;/ !# Wrapping colons g/./s/\(;[ ]*\): \([^;]*\)\(\(\1[ ]\{1,\}[^;]*\)*\)/\1( \2\3)/g !# Un-join the lines s/;/\ /g !# Wrap every (non-parenthesized) line in parens v/(.*)/s/\([( ]*\)\(.*\)/\1(\2)/g !# Un-wrap wrapped (above) dots !# Otherwise we end up with !# (. 3) g/(\./s/(\(\..*\))/\1/ !# Join the lines back g/$/s//;/ ,j s/^/;/ !# Wrapping forms (repeated for 10x nesting (too little?)) g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g g/./s/\(;[ ]*\)(\([^;()]*\))\(\(\1[ ]\{1,\}[^;]*\)*\)/\1(\2\3)/g !# Curly-infix syntax (only the {a op b} form, no nesting) g/{ *\([^ ]*\) *\([^ ]*\) *\([^ ]*\) *}/s//(\2 \1 \3)/g !# Block-prefixing colon g/(:/s//(/g !# Inline colons (x5) g/./s/\([^\\]\): \([^;]*\);/\1(\2);/g g/./s/\([^\\]\): \([^;]*\);/\1(\2);/g g/./s/\([^\\]\): \([^;]*\);/\1(\2);/g g/./s/\([^\\]\): \([^;]*\);/\1(\2);/g g/./s/\([^\\]\): \([^;]*\);/\1(\2);/g !# Dot-prefixed pass-through forms g/./s/\(;[ ]*\)\. /\1/g !# Fix pass !# - Convert double square brackets to parens again g/./s/\[\[/(/g g/./s/\]\]/)/g !# - space-suffixed opening parens g/./s/( /(/g !# Reader macros g/[',`#]/s/(\('*`*\(,@*\)*\(#[',`@]*\)*\) \{1,\}/\1(/g !# Empty lists (due to introduced semicolons) g/./s/;();/;/g !# Split the lines back out g/./s/;/\ /g w Q