commit 0dd94adaa4436453e4ee032b68dbb15330fcc8cc Author: Jon Michael Aanes Date: Tue Nov 14 13:07:25 2017 +0100 Initial commit of tigersay diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..506d7db --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Ignore swapfiles. +.*.swp diff --git a/test_tig_1.tig b/test_tig_1.tig new file mode 100644 index 0000000..86af592 --- /dev/null +++ b/test_tig_1.tig @@ -0,0 +1,16 @@ +/* output: 1 */ +let + function indentstring (text : string, indent : string) : string = + let var out := indent + var newline_and_indent := concat("\n", indent) + var char := "" + in for i := 0 to size(text) - 1 do + ( char := substring (text, i, 1) + ; out := concat(out, if char <> "\n" + then char + else newline_and_indent)); + out + end +in + indentstring("Hello\nWorld", " ") = " Hello\n World" +end diff --git a/test_tig_2.tig b/test_tig_2.tig new file mode 100644 index 0000000..9e8db2d --- /dev/null +++ b/test_tig_2.tig @@ -0,0 +1,17 @@ +/* print: |00011110| */ +let + function is_whitespace (char:string) : int = + (char = "" | char = "\n" | char = " " | char = "\t") + + function testchar(char:string) = + if is_whitespace(char) then print("1") else print("0") +in + testchar("a"); + testchar("2"); + testchar("321"); + testchar(""); + testchar("\n"); + testchar(" "); + testchar("\t"); + testchar("Recursion") +end diff --git a/tigersay.tig b/tigersay.tig new file mode 100644 index 0000000..c7538b9 --- /dev/null +++ b/tigersay.tig @@ -0,0 +1,167 @@ + +let + /*************/ + /* Constants */ + + var false := 0 + var true := 1 + + var INDENT := " " + + + var TIGER := "\ +\\\ ^__^\n\ +\ \\ (oo)\\_______\n\ +\ (__)\\ )\\/\\\n\ +\ ||----w |\n\ +\ || ||" + + + /*************/ + /* Utilility */ + + function getinput () : string = + let var l := "" /* Full output */ + var c := "" /* Current char */ + in while true do + ( c := getchar() + ; if c = "" then break /* Hit EOF */ + ; l := concat(l, c) ) + ; l + end + + function concat3 (a:string, b:string, c:string) : string = + concat(a, concat(b, c)) + + function concat4 (a:string, b:string, c:string, d:string) : string = + concat(a, concat(b, concat(c, d))) + + function indentstring (text : string, before : string, after:string) : string = + let var out := before + var char := "" + in for i := 0 to size(text) - 1 do + ( char := substring (text, i, 1) + ; out := concat(out, if char <> "\n" + then char + else concat3(after, char, before))); + concat(out, after) + end + + + /* Linked Lists */ + + type stringll = { val: string, next: stringll } + + function ll_new () : stringll = + stringll { val = "", next = nil } + + function ll_append (ll:stringll, str:string) = + if ll.next = nil + then ll.next := stringll { val = str, next = nil } + else ll_append(ll.next, str) + + function ll_to_s (ll:stringll) : string = + if ll <> nil + then concat(ll.val, ll_to_s(ll.next)) + else "" + + var MAXWIDTH := 40 + + function is_whitespace (char:string) : int = + (char = "" | char = "\n" | char = " " | char = "\t") + + function substringabs (text:string, i1:int, i2:int) : string = + substring(text, i1, i2 - i1 + 1) + + function split_words (text:string) : stringll = + let var out := ll_new() + var prev_word_start_i := -1 + var char := "" + in for i := 0 to size(text) - 1 do + ( char := substring(text, i, 1) + ; if is_whitespace(char) & prev_word_start_i <> -1 + then ll_append(out, substringabs(text, prev_word_start_i, i - 1)) + else if not(is_whitespace(char)) & prev_word_start_i = -1 + then prev_word_start_i := i + ; if is_whitespace(char) then prev_word_start_i := -1 + ) + ; out + end + + function insert_whitespace_between_words (words : stringll, linewidth:int) : stringll = + let function help (words:stringll, width:int) : stringll = + if words = nil + then nil + else + if width + size(words.val) > linewidth + then stringll { val = "\n", next = stringll { val = words.val, next = help(words.next, size(words.val)) } } + else stringll { val = " ", next = stringll { val = words.val, next = help(words.next, size(words.val) + width ) } } + in help(words, 0) + end + + function wrapstring (text:string, linewidth: int) : string = + let var words := split_words(text) + var splitstr := insert_whitespace_between_words(words, linewidth) + in + ll_to_s(splitstr.next.next.next) + end + + function max (a:int, b:int) : int = + if a > b then a else b + + function longest_line_length (text:string) : int = + let var longest := 0 + var current := 0 + in for i := 0 to size(text) - 1 do + if substring(text, i, 1) = "\n" + then ( longest := max(longest, current) + ; current := 0) + else current := current + 1 + ; max(longest, current) + end + + function nr_char_in_str (text:string, char:string) : int = + let var count := 0 + var charwidth := size(char) + in for i := 0 to size(text) - 1 do + if substring(text, i, charwidth) = char then count := count + 1 + ; count + end + + function rep_string (str:string, rep:int) : string = + let var out := "" + in for i := 1 to rep do out := concat(out, str) + ; out + end + + function digit_to_s (n:int) :string = + if 0 <= n & n <= 9 + then chr(48 + n) + else "?" + + function int_to_s (n:int) : string = + concat(digit_to_s(n/10), digit_to_s(n - n/10*10)) + + /**************/ + /* Draw stuff */ + + function drawtextbubble (text:string) = + let var textwidth := longest_line_length(text) + var textheight := nr_char_in_str(text, "\n") + 1 + var bubblewidth := textwidth + 4 + var after_text := concat3("\013\027[",int_to_s(bubblewidth-1),"C|") + in print(concat(" ", concat(rep_string("_", bubblewidth - 2), " \n"))) + ; print(concat(indentstring(text, "| ", after_text), "\n")) + ; print(concat(" ", concat(rep_string("-", bubblewidth - 2), " \n"))) + end + + function drawtiger () = print(indentstring(TIGER, INDENT, "")) + + var text := getinput() +in + drawtextbubble(wrapstring(text, MAXWIDTH)); + drawtiger(); + print("\n") +end + +