fork download
  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "regexp"
  6. "strconv"
  7. "strings"
  8. )
  9.  
  10. func indentMixCo(s string) (string, error) {
  11. pairs := map[string]string{
  12. "FOR": "NEXT",
  13. "IF": "ENDIF",
  14. }
  15. level := 0
  16. lines := strings.Split(s, "\n")
  17. length, _ := strconv.Atoi(lines[0])
  18. spaces := strings.Trim(lines[1], "\n")
  19. lines = lines[2:]
  20. var stack []string
  21. var removed []string
  22. indented := false
  23. for i := 0; i < length; i++ {
  24. lines[i] = strings.TrimLeft(lines[i], "·»\t")
  25. for key, val := range pairs {
  26. rOpen, _ := regexp.Compile(fmt.Sprintf(`^%v($|\s)`, key))
  27. if rOpen.MatchString(lines[i]) {
  28. lines[i] = strings.Repeat(spaces, level) + lines[i]
  29. level++
  30. stack = append(stack, key)
  31. indented = true
  32. }
  33. rClose, _ := regexp.Compile(fmt.Sprintf(`^%v($|\s)`, val))
  34. if rClose.MatchString(lines[i]) {
  35. level--
  36. lines[i] = strings.Repeat(spaces, level) + lines[i]
  37. removed, stack = stack[len(stack)-1:], stack[:len(stack)-1]
  38. indented = true
  39. if removed[0] != key {
  40. return strings.Join(lines, "\n"), fmt.Errorf("error: %v found on line %v but was looking for %v", val, i+1, pairs[removed[0]])
  41. }
  42. }
  43. }
  44. if !indented {
  45. lines[i] = strings.Repeat(spaces, level) + lines[i]
  46. } else {
  47. indented = false
  48. }
  49. }
  50. return strings.Join(lines, "\n"), nil
  51. }
  52.  
  53. func main() {
  54. input := `12
  55. ····
  56. VAR I
  57. ·FOR I=1 TO 31
  58. »»»»IF !(I MOD 3) THEN
  59. ··PRINT "FIZZ"
  60. ··»»ENDIF
  61. »»»»····IF !(I MOD 5) THEN
  62. »»»»··PRINT "BUZZ"
  63. ··»»»»»»ENDIF
  64. »»»»IF (I MOD 3) && (I MOD 5) THEN
  65. ······PRINT "FIZZBUZZ"
  66. ··»»ENDIF
  67. »»»»·NEXT`
  68.  
  69. properFormat, err := indentMixCo(input)
  70. if err != nil {
  71. fmt.Println(err)
  72. fmt.Println(properFormat)
  73. } else {
  74. fmt.Println(properFormat)
  75. }
  76. }
  77.  
Success #stdin #stdout 0s 790016KB
stdin
Standard input is empty
stdout
VAR I
FOR I=1 TO 31
····IF !(I MOD 3) THEN
········PRINT "FIZZ"
····ENDIF
····IF !(I MOD 5) THEN
········PRINT "BUZZ"
····ENDIF
····IF (I MOD 3) && (I MOD 5) THEN
········PRINT "FIZZBUZZ"
····ENDIF
NEXT