Bởi vì chúng ta đang nói về sự thụt dòng và khoảng trắng, chúng ta chỉ cần viết mã trong một chương trình một ngôn ngữ thực sự được thiết kế xung quanh khoảng trắng , vì điều đó phải dễ nhất, phải không?
Vì vậy, giải pháp là:
Đây là cơ sở64:
ICAgCQogICAgCgkJICAgIAkgCiAgICAKCQkgICAgCQkKICAgIAoJCSAgICAJICAKICAgIAoJCSAgICAJIAkKICAgIAoJCSAKIAogCQoKICAgCSAKICAgCQoJCQkgICAJCQkgCQkKCSAgCQoJICAJICAKICAgCQoJCQkgICAJIAkgCgkgIAkKCSAgCSAJCiAgIAkKCQkJICAgCSAgCQoJICAJCgkgIAkgCQogICAJCgkJCSAgIAkgICAgIAoJICAJCgkgIAkgCQogICAJCgkJCSAgIAkJCQkJIAkKCSAgCQoJICAJCSAKICAgCQoJCQkgICAJICAgCSAKCSAgCQoJICAJICAgIAogICAJCgkJCSAgIAkgCSAgIAoJICAJCgkgIAkgICAJCQogICAJCgkJCSAgIAkgCSAgCQoJICAJCgkgIAkgIAkgIAogICAJIAogICAJCgkJIAogCSAJCQkKICAgCQoJCQkJCiAgCgkKCiAgIAkgIAogICAJCgkJCQkKICAKCQoKICAgCSAJCgoJCgogICAJCSAKICAgCQkKICAgCQkKCQkJICAgCQoJICAJCQkgICAgCSAKICAgCQoJCSAKIAkgCQkJCiAgIAkKCQkJCQogIAoJCgogICAJICAgIAogICAJIAogICAJIAoJCSAKIAkgCQkJCiAgIAkKCQkJCQogIAoJCgogICAJICAgCQkKICAgCSAJCiAgIAkgCQoJCQkgICAJCgkgICAJCSAgICAJIAogICAJCgkJIAogCSAJCQkKICAgCQoJCQkJCiAgCgkKCiAgIAkgIAkgIAogICAJIAkKICAgCSAJCgkJCSAgIAkKCSAgCQkJICAgIAkgCiAgIAkKCQkgCiAJIAkJCQogICAJCgkJCQkKICAKCQoKICAgCQkKICAgCQoJCQkgICAJIAkgCgkgIAkKCSAgCQkgIAogICAJCgkJCSAgIAkJCQkgCQkKCSAgCQoJICAJCSAJCiAgIAkKCQkJICAgCQkJCQkgCQoJICAJCgkgIAkJCSAKICAgCQoJCQkgICAJCQkgCQkKCSAgCQoJICAJCQkJCiAgIAkKCQkJICAgCSAgIAkgCgkgIAkKCSAgCQkgCQkKICAgCQoJCQkgICAJIAkgCSAKCSAgCQoJICAJCQkgIAogICAJCgkJCSAgIAkgCQkJCQoJICAJCgkgIAkJCSAJCiAgIAkKCQkJICAgCSAJICAgCgkgIAkKCSAgCSAgCSAJCiAgIAkKCQkJICAgCSAJICAJCgkgIAkKCSAgCSAgCQkgCiAgIAkKCQkJCQogIAoJCgogICAJCSAgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkJIAkKICAgCQoJCQkJCiAgICAgCSAKICAgIAoJCSAgICAJCQogICAJCQoJCQkgICAJCgkgICAJCSAKCQoKICAgCQkJIAogICAJCQogICAJCQoJCQkgICAJCgkgIAkJCSAKIAkgCQkJCiAgIAkKCQkJCQogICAgIAkgCiAgICAKCQkgCgkKCiAgIAkJCQkKICAgCQoJCQkJCiAgICAgCSAJCgkJCQoJICAJIAkgCgoJCgogICAJICAJCQkKICAgCSAKICAgIAoJCSAKCQoKICAgCQkgCQkKICAgCQoJCQkJCiAgICAgCSAKICAgCSAKCQkgCgkKCiAgIAkJCSAgCiAgIAkgIAoJCQkgICAJIAkJCQkKCSAgCQoJICAJCQkJIAogICAJCgkJCQkKICAKCQoKICAgCQkJIAkKICAgCSAgCgkJCSAgIAkgCQkJCQoJICAJCgkgIAkJCQkJCiAgIAkKCQkJCQogIAoJCgogICAJCQkJIAogICAJCgkJCQkKICAgICAJIAogICAJCQoJCSAKCQoKICAgCQkJCQkKICAgCQoJCQkJCiAgICAgCSAKICAgCSAgCgkJIAoJCgogICAJICAJIAkKICAgCSAJCiAgIAkgCQoJCQkgICAJCgkgICAJCSAgICAJCgkJCQkKICAKCQoKICAgCSAgCQkgCiAgIAkgCQogICAJIAkKCQkJICAgCQoJICAJCQkgICAgCQoJCQkJCiAgCgkKCiAgIAkJCQogICAJIAkgCgkKICAgICAJCQoJCQkKICAgCSAgCQogCiAKCSAgCSAgIAogCiAKCQkgCSAgIAogICAJICAgICAKCQogICAgIAkgICAgIAoJCiAgICAgCQoJICAJCiAKIAkgIAkKCiAgIAkgICAKCgkKCiAgIAkgCSAJCiAgIAkKCQkJICAgCSAJIAoJICAJCgkgIAkJICAgCiAgIAkKCQkJICAgCSAgIAkgCgkgIAkKCSAgCQkgIAkKICAgCQoJCQkJCiAgCgkKCiAgIAkJICAgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkJICAJCiAgIAkgIAoJCQkgICAJIAkJCSAgCgkgIAkKCSAgCQkgCSAKICAgCSAKICAgCQoJCSAgICAJCgkJCQkKICAKCQoKICAgCQkgCSAKICAgCQoJCQkJCiAgCgkKCiAgIAkgCQkgCiAgIAkKCQkJICAgCSAJCQkJCgkgIAkKCSAgCSAgICAgCiAgIAkKCQkJCQogIAoJCgogICAJICAgICAKICAgCSAgCgkJCSAgIAkgCSAJIAoJICAJCgkgIAkgICAgCQogICAJCgkJCQkKICAKCQoKICAgCSAgICAJCiAgIAkKCQkJCQogICAgIAkgCiAgIAkKCQkgCgkKCiAgIAkgCQkJCiAgIAkKCQkJICAgCSAJIAoJICAJCgkgIAkgICAJIAogICAJCgkJCQkKICAKCQoKICAgCSAgIAkgCiAgIAkgCiAgICAKCQkgCgkKCiAgIAkKICAgCSAgCiAgIAkKCQkJCQkgICAgCQoJCgkgICAgCSAKCQkJCgkgIAkgCSAKICAgCSAKCQkJICAgCQoJICAJCgkgIAkgICAJCiAgIAkgCgkJCSAgIAkgCgkgIAkKCSAgCSAgCSAKICAgCSAKCQkJICAgCQkKCSAgCQoJICAJICAJCQogICAJIAoJCQkgICAJICAKCSAgCQoJICAJIAkgIAoKICAgCSAgIAkKCiAJIAkJCgogCiAJIAkJCgogICAJIAkgCgogCSAJIAoKIAogCSAJCQoKICAgCSAgCSAKCiAJIAkgCSAJCgogCiAJIAkJCgogICAJICAJCQoKIAkgCSAJCSAKCiAKIAkgCQkKCiAgIAkgCSAgCgogCSAJIAkJCQoKICAgCSAJCQoKIAogCQoKCgo=
Đối với những người có vấn đề in mã trên giấy ở đây là phiên bản có chú thích (bạn có thể tìm thấy trình biên dịch cho phần này ở cuối câu trả lời):
# heap structure:
# 1: read buffer
# 2: parser state
# 0: before indentation
# 1: after indentation
# 2: inside a string literal
# 3: inside a multiline comment
# 4: inside a single line comment
# 3: identation
# 4: old read buffer
# 5: parenthesis nesting amount
# -------------------
# initialize heap
# -------------------
SS 1 | SS 0 | TTS # [1] := 0
SS 2 | SS 0 | TTS # [2] := 0
SS 3 | SS 0 | TTS # [3] := 0
SS 4 | SS 0 | TTS # [4] := 0
SS 5 | SS 0 | TTS # [5] := 0
LSL 1 # goto L1
# -------------------
# sub: determine what to do in state 0
# -------------------
LSS 2 # LABEL L2
SS 1 | TTT | SS 59 | TSST | LTS 4 # if [1] == ; GOTO L4
SS 1 | TTT | SS 10 | TSST | LTS 5 # if [1] == \n GOTO L5
SS 1 | TTT | SS 9 | TSST | LTS 5 # if [1] == \t GOTO L5
SS 1 | TTT | SS 32 | TSST | LTS 5 # if [1] == ' ' GOTO L5
SS 1 | TTT | SS 125 | TSST | LTS 6 # if [1] == } GOTO L6
SS 1 | TTT | SS 34 | TSST | LTS 16 # if [1] == " GOTO L16
SS 1 | TTT | SS 40 | TSST | LTS 35 # if [1] == ( GOTO L35
SS 1 | TTT | SS 41 | TSST | LTS 36 # if [1] == ) GOTO L36
SS 2 | SS 1 | TTS # [2] := 1
LST 7 # call L7
SS 1 | TTT | TLSS # print [1]
LTL # return
LSS 4 # label L4 - ; handler
SS 1 | TTT | TLSS # print [1]
LTL # return
LSS 5 # label L5 - WS handler
LTL # return
LSS 6 # label L6 - } handler
# decrease identation by one
SS 3 | SS 3 | TTT | SS 1 | TSST | TTS # [3] := [3] - 1
SS 2 | SS 1 | TTS # [2] := 1
LST 7 # call L7
SS 1 | TTT | TLSS # print [1]
LTL # return
LSS 16 # label L16 - " handler
SS2 | SS 2 | TTS # [2] := 2
LST 7 # call L7
SS1 | TTT | TLSS # print [1]
LTL
LSS 35
SS 5 | SS 5 | TTT | SS 1 | TSSS | TTS # [5] := [5] + 1
SS 2 | SS 1 | TTS # [2] := 1
LST 7 # call L7
SS1 | TTT | TLSS # print [1]
LTL
LSS 36
SS 5 | SS 5 | TTT | SS 1 | TSST | TTS # [5] := [5] - 1
SS 2 | SS 1 | TTS # [2] := 1
LST 7 # call L7
SS1 | TTT | TLSS # print [1]
LTL
# -------------------
# sub: determine what to do in state 1
# -------------------
LSS 3 # LABEL L3
SS 1 | TTT | SS 10 | TSST | LTS 12 # if [1] == \n GOTO L12
SS 1 | TTT | SS 123 | TSST | LTS 13 # if [1] == { GOTO L13
SS 1 | TTT | SS 125 | TSST | LTS 14 # if [1] == } GOTO L14
SS 1 | TTT | SS 59 | TSST | LTS 15 # if [1] == ; GOTO L15
SS 1 | TTT | SS 34 | TSST | LTS 27 # if [1] == " GOTO L27
SS 1 | TTT | SS 42 | TSST | LTS 28 # if [1] == * GOTO L28
SS 1 | TTT | SS 47 | TSST | LTS 29 # if [1] == / GOTO L29
SS 1 | TTT | SS 40 | TSST | LTS 37 # if [1] == ( GOTO L37
SS 1 | TTT | SS 41 | TSST | LTS 38 # if [1] == ) GOTO L38
SS 1 | TTT | TLSS # print [1]
LTL # return
LSS 12 # LABEL L12 - \n handler
SS 2 | SS 0 | TTS # [2] := 0
LTL # return
LSS 13 # LABEL L13 - { handler
SS 1 | TTT | TLSS # print [1]
SS 2 | SS 0 | TTS # [2] := 0
SS 3 | SS 3 | TTT | SS 1 | TSSS | TTS # [3] := [3] + 1
LTL # return
LSS 14 # LABEL L14 - } handler
SS 3 | SS 3 | TTT | SS 1 | TSST | TTS # [3] := [3] - 1
LST 7 # call L7
SS 1 | TTT | TLSS # print [1]
SS 2 | SS 0 | TTS # [2] := 0
LTL # return
LSS 15 # LABEL L15 - ; handler
SS 1 | TTT | TLSS # print [1]
SS 5 | TTT | LTS 10 # if [5] == 0 GOTO L39
LTL
LSS 39
SS 2 | SS 0 | TTS # [2] := 0
LTL # return
LSS 27 # label L27 - " handler
SS1 | TTT | TLSS # print [1]
SS2 | SS 2 | TTS # [2] := 2
LTL
LSS 28 # label L28 - * handler - this might start a comment
SS 4 | TTT | SS 47 | TSST | LTS 30 # if [4] == / GOTO L30
SS1 | TTT | TLSS # print [1]
LTL
LSS 29 # label L29 - / handler - this might start a comment
SS 4 | TTT | SS 47 | TSST | LTS 31 # if [4] == / GOTO L31
SS1 | TTT | TLSS # print [1]
LTL
LSS 30 # label L30 - /* handler
SS1 | TTT | TLSS # print [1]
SS2 | SS 3 | TTS # [2] := 3
LTL
LSS 31 # label L31 - // handler
SS1 | TTT | TLSS # print [1]
SS2 | SS 4 | TTS # [2] := 4
LTL
LSS 37
SS 5 | SS 5 | TTT | SS 1 | TSSS | TTS # [5] := [5] + 1
SS1 | TTT | TLSS # print [1]
LTL
LSS 38
SS 5 | SS 5 | TTT | SS 1 | TSST | TTS # [5] := [5] - 1
SS1 | TTT | TLSS # print [1]
LTL
# -------------------
# sub: print identation
# -------------------
LSS 7 # label L7 - print identation
SS 10 | TLSS # print \n
SS 3 | TTT # push [3]
LSS 9 # label L9 - start loop
SLS | LTS 8 # if [3] == 0 GOTO L8
SLS | LTT 8 # if [3] < 0 GOTO L8 - for safety
SS 32 | TLSS # print ' '
SS 32 | TLSS # print ' '
SS 1 | TSST # i := i - 1
LSL 9 # GOTO L9
LSS 8 # label L8 - end loop
LTL #
# -------------------
# sub: L21 - string literal handler
# -------------------
LSS 21
SS 1 | TTT | SS 10 | TSST | LTS 24 # if [1] == \n GOTO L24
SS 1 | TTT | SS 34 | TSST | LTS 25 # if [1] == " GOTO L25
SS 1 | TTT | TLSS # print [1]
LTL
LSS 24 # \n handler - this should never happen, but let's be prepared and reset the parser
SS 2 | SS 0 | TTS # [2] := 0
LTL # return
LSS 25 # " handler - this might be escaped, so be prepared
SS 4 | TTT | SS 92 | TSST | LTS 26 # if [4] == \ GOTO L26
SS 2 | SS 1 | TTS # [2] := 1
SS 1 | TTT | TLSS # print [1]
LTL
LSS 26 # \\" handler - escaped quotes don't finish the literal
SS 1 | TTT | TLSS # print [1]
LTL
# -------------------
# sub: L22 - multiline comment handler
# -------------------
LSS 22
SS 1 | TTT | SS 47 | TSST | LTS 32 # if [1] == / GOTO L32
SS 1 | TTT | TLSS # print [1]
LTL
LSS 32
SS 4 | TTT | SS 42 | TSST | LTS 33 # if [4] == * GOTO L33
SS 1 | TTT | TLSS # print [1]
LTL
LSS 33
SS 1 | TTT | TLSS # print [1]
SS 2 | SS 1 | TTS # [2] := 1
LTL
# -------------------
# sub: L23 - singleline comment handler
# -------------------
LSS 23
SS 1 | TTT | SS 10 | TSST | LTS 34 # if [1] == \n GOTO L34
SS 1 | TTT | TLSS # print [1]
LTL
LSS 34
SS 2 | SS 0 | TTS # [2] := 0
LTL
# -------------------
# main loop
# -------------------
LSS 1 # LABEL L1
SS 4 | SS 1 | TTT | TTS # [4] := [1]
SS 1 | TLTS # [1] := read
SS 2 | TTT | LTS 10 # if [2] == 0 GOTO L10
SS 2 | TTT | SS 1 | TSST | LTS 17 # if [2] == 1 GOTO L17
SS 2 | TTT | SS 2 | TSST | LTS 18 # if [2] == 2 GOTO L18
SS 2 | TTT | SS 3 | TSST | LTS 19 # if [2] == 3 GOTO L19
SS 2 | TTT | SS 4 | TSST | LTS 20 # if [2] == 4 GOTO L20
LSS 17
LST 3 # call L3
LSL 11 # GOTO L11
LSS 10 # label L10
LST 2 # call L2
LSL 11
LSS 18
LST 21
LSL 11
LSS 19
LST 22
LSL 11
LSS 20
LST 23
LSS 11 # label L11
LSL 1 # goto L1
LLL # END
Điều này vẫn đang được tiến hành, mặc dù hy vọng nó sẽ vượt qua hầu hết các tiêu chí!
Các tính năng hiện được hỗ trợ:
- sửa lỗi nhận dạng dựa trên
{
và }
ký tự.
- thêm một dòng mới sau
;
- xử lý các ký tự thụt bên trong chuỗi ký tự (bao gồm cả thực tế là chuỗi ký tự không bị đóng khi gặp a
\"
)
- xử lý các ký tự thụt vào trong các bình luận đơn và đa dòng
- không thêm các ký tự dòng mới nếu bên trong dấu ngoặc đơn (như một
for
khối)
Ví dụ đầu vào (Tôi đã thêm một số trường hợp cạnh dựa trên nhận xét của Quincunx, để bạn có thể kiểm tra xem nó có hoạt động đúng không):
/* Hai Worldz. This code is to prevent formatting: if(this_code_is_touched){,then+your*program_"doesn't({work)}correctl"y.} */
#include<stdio.h>
#include<string.h>
int main() {
int i;
char s[99];
printf("----------------------\n;;What is your name?;;\n----------------------\n\""); //Semicolon added in the {;} string just to annoy you
/* Now we take the {;} input: */
scanf("%s",s);
for(i=0;i<strlen(s);i++){if(s[i]>='a'&&s[i]<='z'){
s[i]-=('a'-'A'); //this is same as s[i]=s[i]-'a'+'A'
}}printf("Your \"name\" in upper case is:\n%s\n",s);
return 0;}
Ví dụ đầu ra:
[~/projects/indent]$ cat example.c | ./wspace indent.ws 2>/dev/null
/* Hai Worldz. This code is to prevent formatting: if(this_code_is_touched){,then+your*program_"doesn't({work)}correctl"y.} */
#include<stdio.h>
#include<string.h>
int main() {
int i;;
char s[99];;
printf("----------------------\n;;What is your name?;;\n----------------------\n\"");; //Semicolon added in the {;} string just to annoy you
/* Now we take the {;} input: */
scanf("%s",s);;
for(i=0;i<strlen(s);i++){
if(s[i]>='a'&&s[i]<='z'){
s[i]-=('a'-'A');; //this is same as s[i]=s[i]-'a'+'A'
}
}
printf("Your \"name\" in upper case is:\n%s\n",s);;
return 0;;
}
Lưu ý rằng bởi vì khoảng trắng không hỗ trợ EOF kiểm tra intepreter ném ngoại lệ, mà chúng ta cần phải triệt tiêu. Vì không có cách nào trong khoảng trắng để kiểm tra EOF (theo như tôi biết vì đây là chương trình khoảng trắng đầu tiên của tôi) nên đây là điều không thể tránh khỏi, tôi hy vọng giải pháp vẫn được tính.
Đây là tập lệnh tôi đã sử dụng để biên dịch phiên bản chú thích thành khoảng trắng phù hợp:
#!/usr/bin/env ruby
ARGF.each_line do |line|
data = line.gsub(/'.'/) { |match| match[1].ord }
data = data.gsub(/[^-LST0-9#]/,'').split('#').first
if data
data.tr!('LST',"\n \t")
data.gsub!(/[-0-9]+/){|m| "#{m.to_i<0?"\t":" "}#{m.to_i.abs.to_s(2).tr('01'," \t")}\n" }
print data
end
end
Chạy:
./wscompiler.rb annotated.ws > indent.ws
Lưu ý rằng điều này, ngoài việc chuyển đổi S
, L
và T
nhân vật, cũng cho phép bình luận dòng duy nhất với #
, và có thể tự động chuyển đổi số và chữ nhân vật đơn giản thành đại diện khoảng trắng của họ. Hãy sử dụng nó cho các dự án khoảng trắng khác nếu bạn muốn