tgen.sh 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #!/bin/bash
  2. warn() {
  3. echo "$@" >&2
  4. }
  5. die() {
  6. echo "$@" >&2
  7. exit 3
  8. }
  9. content_desc() {
  10. local c=$1
  11. case $c in
  12. \ ) echo space ;;
  13. \!) echo exclamation mark ;;
  14. \$) echo dollar sign ;;
  15. \&) echo ampersand ;;
  16. \() echo opening bracket ;;
  17. \)) echo closing bracket ;;
  18. \*) echo asterisk ;;
  19. \;) echo semicolon ;;
  20. \?) echo question mark ;;
  21. \\) echo backslash ;;
  22. \`) echo tick mark;;
  23. \>) echo greater than ;;
  24. \<) echo less than ;;
  25. \{) echo opening curly brace ;;
  26. \|) echo pipe symbol ;;
  27. \}) echo closing curly brace ;;
  28. BS) echo backslash ;;
  29. SQ) echo single quote ;;
  30. DQ) echo double quote ;;
  31. TAB) echo tab ;;
  32. ES) echo empty string ;;
  33. NL) echo newline ;;
  34. A) echo letter A ;;
  35. esac
  36. }
  37. mode_name() {
  38. local mode=$1
  39. case $mode in
  40. bs) echo backslash escaping ;;
  41. sq) echo single quoting ;;
  42. dq) echo double quoting ;;
  43. esac
  44. }
  45. mktest() {
  46. local mode=$1; shift
  47. local mode_name
  48. local content_desc
  49. mode_name="$(mode_name "$mode")"
  50. local c
  51. local self=$0
  52. printf 'test "parse: %s (generated)" {\n' "$mode_name"
  53. printf ' // TEST GENERATED BY %s\n' "$self"
  54. #shellcheck disable=SC2016
  55. for c in "$@"; do
  56. content_desc="$(content_desc "$c")"
  57. # every backslash needs to be doubled because of printf.
  58. # some backslashes need to be doubled again becase of syntax (eg. `"\\\\" is 2 backslashes in Zig)
  59. case $mode:$c in
  60. bs:BS) printf ' try parse_t("\\\\\\\\", Result{ .tokens = &.{"\\\\"} }); // %s `\\` (%s)\n' "$mode_name" "$content_desc" ;;
  61. bs:DQ) printf ' try parse_t("\\\\\\"", Result{ .tokens = &.{"\\""} }); // %s `"` (%s)\n' "$mode_name" "$content_desc" ;;
  62. bs:ES) true ;; # impossible case
  63. bs:NL) printf ' try parse_t("\\\\\\n", Result{ .tokens = &.{"\\n"} }); // %s `\\n` (%s)\n' "$mode_name" "$content_desc" ;;
  64. bs:SQ) printf ' try parse_t("\\\\%s", Result{ .tokens = &.{"%s"} }); // %s `%s` (%s)\n' "'" "'" "$mode_name" "'" "$content_desc" ;;
  65. bs:TAB) printf ' try parse_t("\\\\\\t", Result{ .tokens = &.{"\\t"} }); // %s `\\t` (%s)\n' "$mode_name" "$content_desc" ;;
  66. bs:*) printf ' try parse_t("\\\\%s", Result{ .tokens = &.{"%s"} }); // %s `%s` (%s)\n' "$c" "$c" "$mode_name" "$c" "$content_desc" ;;
  67. sq:NL) printf ' try parse_t("%s\\n%s", Result{ .tokens = &.{"\\n"} }); // %s `\\n` (%s)\n' "'" "'" "$mode_name" "$content_desc" ;;
  68. sq:TAB) printf ' try parse_t("%s\\t%s", Result{ .tokens = &.{"\\t"} }); // %s `\\t` (%s)\n' "'" "'" "$mode_name" "$content_desc" ;;
  69. sq:DQ) printf ' try parse_t("%s\\"%s", Result{ .tokens = &.{"\\""} }); // %s `"` (%s)\n' "'" "'" "$mode_name" "$content_desc" ;;
  70. sq:ES) printf ' try parse_t("%s%s", Result{ .tokens = &.{""} }); // %s `\\` (%s)\n' "'" "'" "$mode_name" "$content_desc" ;;
  71. sq:BS) printf ' try parse_t("%s\\\\%s", Result{ .tokens = &.{"\\\\"} }); // %s `\\` (%s)\n' "'" "'" "$mode_name" "$content_desc" ;;
  72. sq:SQ) true ;; # impossible case
  73. sq:*) printf ' try parse_t("'"'"'%s'"'"'", Result{ .tokens = &.{"%s"} }); // %s `%s` (%s)\n' "$c" "$c" "$mode_name" "$c" "$content_desc" ;;
  74. dq:BS) printf ' try parse_t("\\"\\\\\\\\\\"", Result{ .tokens = &.{"\\\\"} }); // %s `\\` (%s)\n' "$mode_name" "$content_desc" ;;
  75. dq:DQ) printf ' try parse_t("\\"\\\\\\"\\"", Result{ .tokens = &.{"\\""} }); // %s `"` (%s)\n' "$mode_name" "$content_desc" ;;
  76. dq:ES) printf ' try parse_t("\\"\\"", Result{ .tokens = &.{""} }); // %s `\\` (%s)\n' "$mode_name" "$content_desc" ;;
  77. dq:NL) printf ' try parse_t("\\"\\n\\"", Result{ .tokens = &.{"\\n"} }); // %s `\\n` (%s)\n' "$mode_name" "$content_desc" ;;
  78. dq:SQ) printf ' try parse_t("\\"%s\\"", Result{ .tokens = &.{"%s"} }); // %s `%s` (%s)\n' "'" "'" "$mode_name" "'" "$content_desc" ;;
  79. dq:TAB) printf ' try parse_t("\\"\\t\\"", Result{ .tokens = &.{"\\t"} }); // %s `\\t` (tab)\n' "$mode_name" ;;
  80. dq:*) printf ' try parse_t("\\"%s\\"", Result{ .tokens = &.{"%s"} }); // %s `%s` (%s)\n' "$c" "$c" "$mode_name" "$c" "$content_desc" ;;
  81. *) die "unknown character or mode: c=$c mode=$mode" ;;
  82. esac
  83. done
  84. printf '}\n'
  85. echo
  86. }
  87. main() {
  88. local cases=(
  89. '!'
  90. '$'
  91. '&'
  92. '('
  93. ')'
  94. '*'
  95. ';'
  96. '?'
  97. '`'
  98. '{'
  99. '>'
  100. '<'
  101. '|'
  102. '}'
  103. ' '
  104. SQ
  105. DQ
  106. BS
  107. TAB
  108. NL
  109. ES
  110. A
  111. )
  112. mktest bs "${cases[@]}"
  113. mktest sq "${cases[@]}"
  114. mktest dq "${cases[@]}"
  115. }
  116. main "$@"