Create gh-pages branch via GitHub
Cat's Eye Technologies
10 years ago
43 | 43 | to be expressed <em>compactly</em>. Golf your grammar! (Or write it like a decent |
44 | 44 | human being, if you must.)</p> |
45 | 45 | |
46 | <p>The current released version of Tamsin is 0.1; the development version is | |
47 | 0.2-PRE. As indicated by the 0.x version number, it is a <strong>work in progress</strong>, | |
48 | with the usual caveat that things may change rapidly (and that version 0.2 might | |
49 | look completely different.)</p> | |
46 | <p>The current released version of Tamsin is 0.2; the development version is | |
47 | 0.3-PRE. As indicated by the 0.x version number, it is a <strong>work in progress</strong>, | |
48 | with the usual caveat that things may change rapidly (and that version 0.3 might | |
49 | look completely different.) See <a href="https://github.com/catseye/Tamsin/blob/master/HISTORY.markdown">HISTORY</a> | |
50 | for a list of major changes.</p> | |
50 | 51 | |
51 | 52 | <h2> |
52 | 53 | <a name="code-examples" class="anchor" href="#code-examples"><span class="octicon octicon-link"></span></a>Code Examples</h2> |
53 | 54 | |
54 | 55 | <p>Make a story more exciting in <strong>1 line of code</strong>:</p> |
55 | 56 | |
56 | <pre><code>main = S ← '' & {("." & '!' | "?" & '?!' | any) → C & S ← S + C} & S. | |
57 | </code></pre> | |
58 | ||
59 | <p>Parse an algebraic expression in <strong>4 lines of code</strong>:</p> | |
57 | <pre><code>main = ("." & '!' | "?" & '?!' | any)/''. | |
58 | </code></pre> | |
59 | ||
60 | <p>Parse an algebraic expression for syntactic correctness in <strong>4 lines of code</strong>:</p> | |
60 | 61 | |
61 | 62 | <pre><code>main = (expr0 & eof & 'ok'). |
62 | 63 | expr0 = expr1 & {"+" & expr1}. |
84 | 85 | line = field → F & {"," & field → G & F ← fields(G, F)} & F. |
85 | 86 | field = strings | bare. |
86 | 87 | strings = string → T & {string → S & T ← T + '"' + S} & T. |
87 | string = "\"" & T ← '' & {!"\"" & any → S & T ← T + S} & "\"" & T. | |
88 | bare = T ← '' & {!(","|"\n") & any → S & T ← T + S} & T. | |
89 | extract(lines(Lines, Line)) = extract(Lines) & extract_field(Line). | |
88 | string = "\"" & (!"\"" & any)/'' → T & "\"" & T. | |
89 | bare = (!(","|"\n") & any)/''. | |
90 | extract(lines(Ls, L)) = extract(Ls) & extract_field(L). | |
90 | 91 | extract(L) = L. |
91 | extract_field(fields(Last, fields(This, X))) = print This. | |
92 | extract_field(X) = return X. | |
92 | extract_field(fields(L, fields(T, X))) = print T. | |
93 | extract_field(X) = X. | |
93 | 94 | </code></pre> |
94 | 95 | |
95 | 96 | <p>Evaluate an (admittedly trivial) S-expression based language in |
96 | <strong>17 lines of code</strong>:</p> | |
97 | <strong>15 lines of code</strong>:</p> | |
97 | 98 | |
98 | 99 | <pre><code>main = sexp → S using scanner & reverse(S, nil) → SR & eval(SR). |
99 | scanner = scan using $.char. | |
100 | scan = {" "} & ("(" | ")" | (T ← '' & {$.alnum → S & T ← T + S} & return T)). | |
101 | sexp = $.alnum | list. | |
102 | list = "(" & listtail(nil). | |
103 | listtail(L) = sexp → S & listtail(pair(S, L)) | ")" & L. | |
104 | head(pair(A, B)) = return A. | |
105 | tail(pair(A, B)) = return B. | |
100 | scanner = ({" "} & ("(" | ")" | $:alnum/'')) using $:utf8. | |
101 | sexp = $:alnum | list. | |
102 | list = "(" & sexp/nil/pair → L & ")" & L. | |
103 | head(pair(A, B)) = A. | |
104 | tail(pair(A, B)) = B. | |
106 | 105 | cons(A, B) = return pair(A, B). |
107 | 106 | eval(pair(head, pair(X, nil))) = eval(X) → R & head(R). |
108 | 107 | eval(pair(tail, pair(X, nil))) = eval(X) → R & tail(R). |
113 | 112 | reverse(nil, A) = A. |
114 | 113 | reverse(X, A) = X. |
115 | 114 | </code></pre> |
115 | ||
116 | <p>Interpret a small subset of Tamsin in | |
117 | <strong><a href="https://github.com/catseye/Tamsin/blob/master/eg/tamsin-micro-interpreter.tamsin">less than 160 lines of code</a></strong>.</p> | |
116 | 118 | |
117 | 119 | <h2> |
118 | 120 | <a name="for-more-information" class="anchor" href="#for-more-information"><span class="octicon octicon-link"></span></a>For more information</h2> |
187 | 189 | <li> Keep the language simple (grammar should fit on a page.)</li> |
188 | 190 | <li> Recognize that the preceding two goals are in tension.</li> |
189 | 191 | <li> Have a relatively simple reference implementation (currently less than |
190 | 2500 lines of code, including everything — debugging and the C runtime | |
192 | 3000 lines of code, including everything — debugging and the C runtime | |
191 | 193 | used by the compiler.)</li> |
192 | 194 | </ul><h2> |
193 | 195 | <a name="license" class="anchor" href="#license"><span class="octicon octicon-link"></span></a>License</h2> |
0 | {"name":"Tamsin","tagline":"Look! Up on Github! Is it a parser generator? Is it a programming language? Is it a rubbish lister? No... it's Tamsin!","body":"Tamsin\r\n======\r\n\r\nTamsin is an oddball little language that can't decide if it's a\r\n[meta-language](https://github.com/catseye/Tamsin/blob/master/doc/Philosophy.markdown#meta-language), a\r\n[programming language](https://github.com/catseye/Tamsin/blob/master/doc/Philosophy.markdown#programming-language), or a\r\n[rubbish lister](https://github.com/catseye/Tamsin/blob/master/doc/Philosophy.markdown#rubbish-lister).\r\n\r\nIts primary goal is to allow the rapid development of **parsers**,\r\n**static analyzers**, **interpreters**, and **compilers**, and to allow them\r\nto be expressed *compactly*. Golf your grammar! (Or write it like a decent\r\nhuman being, if you must.)\r\n\r\nThe current released version of Tamsin is 0.1; the development version is\r\n0.2-PRE. As indicated by the 0.x version number, it is a **work in progress**,\r\nwith the usual caveat that things may change rapidly (and that version 0.2 might\r\nlook completely different.)\r\n\r\nCode Examples\r\n-------------\r\n\r\nMake a story more exciting in **1 line of code**:\r\n\r\n main = S ← '' & {(\".\" & '!' | \"?\" & '?!' | any) → C & S ← S + C} & S.\r\n\r\nParse an algebraic expression in **4 lines of code**:\r\n\r\n main = (expr0 & eof & 'ok').\r\n expr0 = expr1 & {\"+\" & expr1}.\r\n expr1 = term & {\"*\" & term}.\r\n term = \"x\" | \"y\" | \"z\" | \"(\" & expr0 & \")\".\r\n\r\nTranslate an algebraic expression to RPN (Reverse Polish Notation) in\r\n**7 lines of code**:\r\n\r\n main = expr0 → E & walk(E).\r\n expr0 = expr1 → E1 & {\"+\" & expr1 → E2 & E1 ← add(E1,E2)} & E1.\r\n expr1 = term → E1 & {\"*\" & term → E2 & E1 ← mul(E1,E2)} & E1.\r\n term = \"x\" | \"y\" | \"z\" | \"(\" & expr0 → E & \")\" & E.\r\n walk(add(L,R)) = walk(L) → LS & walk(R) → RS & return LS+RS+' +'.\r\n walk(mul(L,R)) = walk(L) → LS & walk(R) → RS & return LS+RS+' *'.\r\n walk(X) = return ' '+X.\r\n\r\nParse a CSV file (handling quoted commas and quotes correctly) and write\r\nout the 2nd-last field of each record — in **11 lines of code**:\r\n\r\n main = line → L & L ← lines(nil, L) &\r\n {\"\\n\" & line → M & L ← lines(L, M)} & extract(L) & ''.\r\n line = field → F & {\",\" & field → G & F ← fields(G, F)} & F.\r\n field = strings | bare.\r\n strings = string → T & {string → S & T ← T + '\"' + S} & T.\r\n string = \"\\\"\" & T ← '' & {!\"\\\"\" & any → S & T ← T + S} & \"\\\"\" & T.\r\n bare = T ← '' & {!(\",\"|\"\\n\") & any → S & T ← T + S} & T.\r\n extract(lines(Lines, Line)) = extract(Lines) & extract_field(Line).\r\n extract(L) = L.\r\n extract_field(fields(Last, fields(This, X))) = print This.\r\n extract_field(X) = return X.\r\n\r\nEvaluate an (admittedly trivial) S-expression based language in\r\n**17 lines of code**:\r\n\r\n main = sexp → S using scanner & reverse(S, nil) → SR & eval(SR).\r\n scanner = scan using $.char.\r\n scan = {\" \"} & (\"(\" | \")\" | (T ← '' & {$.alnum → S & T ← T + S} & return T)).\r\n sexp = $.alnum | list.\r\n list = \"(\" & listtail(nil).\r\n listtail(L) = sexp → S & listtail(pair(S, L)) | \")\" & L.\r\n head(pair(A, B)) = return A.\r\n tail(pair(A, B)) = return B.\r\n cons(A, B) = return pair(A, B).\r\n eval(pair(head, pair(X, nil))) = eval(X) → R & head(R).\r\n eval(pair(tail, pair(X, nil))) = eval(X) → R & tail(R).\r\n eval(pair(cons, pair(A, pair(B, nil)))) =\r\n eval(A) → AE & eval(B) → BE & return pair(AE, BE).\r\n eval(X) = X.\r\n reverse(pair(H, T), A) = reverse(H, nil) → HR & reverse(T, pair(HR, A)).\r\n reverse(nil, A) = A.\r\n reverse(X, A) = X.\r\n\r\nFor more information\r\n--------------------\r\n\r\nIf the above has piqued your curiosity, you may want to read the specification,\r\nwhich contains many more small examples written to demonstrate (and test) the\r\nsyntax and behavior of Tamsin:\r\n\r\n* [The Tamsin Language Specification](https://github.com/catseye/Tamsin/blob/master/doc/Tamsin.markdown)\r\n\r\nNote that this is the current development version of the specification, and\r\nit may differ from the examples in this document.\r\n\r\nQuick Start\r\n-----------\r\n\r\nThe Tamsin reference repository is [hosted on Github](https://github.com/catseye/Tamsin)\r\nwith a [Mercurial mirror on Bitbucket](https://bitbucket.org/catseye/tamsin).\r\n\r\nThis repository contains the reference implementation of Tamsin, called\r\n`tamsin`, written in Python 2.7. It can both interpret a Tamsin program and\r\ncompile a program written in Tamsin to C. The distribution also contains an\r\n[implementation of the Tamsin scanner and parser written in Tamsin itself](https://github.com/catseye/Tamsin/blob/master/eg/tamsin-parser.tamsin)\r\n(although we're still a ways from a fully bootrapped implementation.)\r\n\r\nWhile the interpreter is fine for prototyping, note that some informal\r\nbenchmarking revealed the compiled C programs to be about 30x faster. **Note**\r\nhowever that while the compiler passes all the tests, it currently fails to\r\ncorrectly compile the Tamsin parser written in Tamsin, so it should still be\r\nconsidered a **proof of concept**.\r\n\r\nTo start using `tamsin`,\r\n\r\n* Clone the repository — `git clone https://github.com/catseye/tamsin`\r\n* Either:\r\n * Put the repo's `bin` directory on your `$PATH`, or\r\n * Make a symbolic link to `bin/tamsin` somewhere already on your `$PATH`.\r\n* Errr... that's it.\r\n\r\n(Or, to make those steps trivial, you could use\r\n[toolshelf](https://github.com/catseye/toolshelf) and run\r\n`toolshelf dock gh:catseye/tamsin`)\r\n\r\nThen you can run `tamsin` like so:\r\n\r\n* `tamsin run eg/csv_parse.tamsin < eg/names.csv`\r\n\r\nYou can also compile to C and compile the C to an executable and run the\r\nexecutable all in one step, like so:\r\n\r\n* `tamsin loadngo eg/csv_extract.tamsin < eg/names.csv`\r\n\r\nDesign Goals\r\n------------\r\n\r\n* Allow parsers, static analyzers, interpreters, and compilers to be\r\n quickly prototyped. (And in the future, processor simulators and VM's\r\n and such things too.)\r\n* Allow writing these things very compactly.\r\n* Allow writing anything using only recursive-descent parsing techniques\r\n (insofar as this is possible.)\r\n* Provide means to solve practical problems.\r\n* Keep the language simple (grammar should fit on a page.)\r\n* Recognize that the preceding two goals are in tension.\r\n* Have a relatively simple reference implementation (currently less than\r\n 2500 lines of code, including everything — debugging and the C runtime\r\n used by the compiler.)\r\n\r\nLicense\r\n-------\r\n\r\nBSD-style license; see the file [LICENSE](https://github.com/catseye/Tamsin/blob/master/LICENSE).\r\n\r\nRelated work\r\n------------\r\n\r\n* [CoCo/R](http://www.scifac.ru.ac.za/coco/) (parser generation)\r\n* [Parsec](http://www.haskell.org/haskellwiki/Parsec) (parser combination)\r\n* [Perl](http://perl.com/) (rubbish listing)\r\n* [Erlang](http://erlang.org/) (pattern-matching)\r\n* [K](https://github.com/kevinlawler/kona) (similar feel; Tamsin\r\n is a _vertical language_)\r\n* [Cat's Eye Technologies](http://catseye.tc)' esoteric and experimental\r\n languages:\r\n * [Squishy2K](http://catseye.tc/node/Squishy2K)\r\n * [Arboretuum](http://catseye.tc/node/Arboretuum)\r\n * [Treacle](http://catseye.tc/node/Treacle)\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}⏎ | |
0 | {"name":"Tamsin","tagline":"Look! Up on Github! Is it a parser generator? Is it a programming language? Is it a rubbish lister? No... it's Tamsin!","body":"Tamsin\r\n======\r\n\r\nTamsin is an oddball little language that can't decide if it's a\r\n[meta-language](https://github.com/catseye/Tamsin/blob/master/doc/Philosophy.markdown#meta-language), a\r\n[programming language](https://github.com/catseye/Tamsin/blob/master/doc/Philosophy.markdown#programming-language), or a\r\n[rubbish lister](https://github.com/catseye/Tamsin/blob/master/doc/Philosophy.markdown#rubbish-lister).\r\n\r\nIts primary goal is to allow the rapid development of **parsers**,\r\n**static analyzers**, **interpreters**, and **compilers**, and to allow them\r\nto be expressed *compactly*. Golf your grammar! (Or write it like a decent\r\nhuman being, if you must.)\r\n\r\nThe current released version of Tamsin is 0.2; the development version is\r\n0.3-PRE. As indicated by the 0.x version number, it is a **work in progress**,\r\nwith the usual caveat that things may change rapidly (and that version 0.3 might\r\nlook completely different.) See [HISTORY](https://github.com/catseye/Tamsin/blob/master/HISTORY.markdown)\r\nfor a list of major changes.\r\n\r\nCode Examples\r\n-------------\r\n\r\nMake a story more exciting in **1 line of code**:\r\n\r\n main = (\".\" & '!' | \"?\" & '?!' | any)/''.\r\n\r\nParse an algebraic expression for syntactic correctness in **4 lines of code**:\r\n\r\n main = (expr0 & eof & 'ok').\r\n expr0 = expr1 & {\"+\" & expr1}.\r\n expr1 = term & {\"*\" & term}.\r\n term = \"x\" | \"y\" | \"z\" | \"(\" & expr0 & \")\".\r\n\r\nTranslate an algebraic expression to RPN (Reverse Polish Notation) in\r\n**7 lines of code**:\r\n\r\n main = expr0 → E & walk(E).\r\n expr0 = expr1 → E1 & {\"+\" & expr1 → E2 & E1 ← add(E1,E2)} & E1.\r\n expr1 = term → E1 & {\"*\" & term → E2 & E1 ← mul(E1,E2)} & E1.\r\n term = \"x\" | \"y\" | \"z\" | \"(\" & expr0 → E & \")\" & E.\r\n walk(add(L,R)) = walk(L) → LS & walk(R) → RS & return LS+RS+' +'.\r\n walk(mul(L,R)) = walk(L) → LS & walk(R) → RS & return LS+RS+' *'.\r\n walk(X) = return ' '+X.\r\n\r\nParse a CSV file (handling quoted commas and quotes correctly) and write\r\nout the 2nd-last field of each record — in **11 lines of code**:\r\n\r\n main = line → L & L ← lines(nil, L) &\r\n {\"\\n\" & line → M & L ← lines(L, M)} & extract(L) & ''.\r\n line = field → F & {\",\" & field → G & F ← fields(G, F)} & F.\r\n field = strings | bare.\r\n strings = string → T & {string → S & T ← T + '\"' + S} & T.\r\n string = \"\\\"\" & (!\"\\\"\" & any)/'' → T & \"\\\"\" & T.\r\n bare = (!(\",\"|\"\\n\") & any)/''.\r\n extract(lines(Ls, L)) = extract(Ls) & extract_field(L).\r\n extract(L) = L.\r\n extract_field(fields(L, fields(T, X))) = print T.\r\n extract_field(X) = X.\r\n\r\nEvaluate an (admittedly trivial) S-expression based language in\r\n**15 lines of code**:\r\n\r\n main = sexp → S using scanner & reverse(S, nil) → SR & eval(SR).\r\n scanner = ({\" \"} & (\"(\" | \")\" | $:alnum/'')) using $:utf8.\r\n sexp = $:alnum | list.\r\n list = \"(\" & sexp/nil/pair → L & \")\" & L.\r\n head(pair(A, B)) = A.\r\n tail(pair(A, B)) = B.\r\n cons(A, B) = return pair(A, B).\r\n eval(pair(head, pair(X, nil))) = eval(X) → R & head(R).\r\n eval(pair(tail, pair(X, nil))) = eval(X) → R & tail(R).\r\n eval(pair(cons, pair(A, pair(B, nil)))) =\r\n eval(A) → AE & eval(B) → BE & return pair(AE, BE).\r\n eval(X) = X.\r\n reverse(pair(H, T), A) = reverse(H, nil) → HR & reverse(T, pair(HR, A)).\r\n reverse(nil, A) = A.\r\n reverse(X, A) = X.\r\n\r\nInterpret a small subset of Tamsin in\r\n**[less than 160 lines of code](https://github.com/catseye/Tamsin/blob/master/eg/tamsin-micro-interpreter.tamsin)**.\r\n\r\nFor more information\r\n--------------------\r\n\r\nIf the above has piqued your curiosity, you may want to read the specification,\r\nwhich contains many more small examples written to demonstrate (and test) the\r\nsyntax and behavior of Tamsin:\r\n\r\n* [The Tamsin Language Specification](https://github.com/catseye/Tamsin/blob/master/doc/Tamsin.markdown)\r\n\r\nNote that this is the current development version of the specification, and\r\nit may differ from the examples in this document.\r\n\r\nQuick Start\r\n-----------\r\n\r\nThe Tamsin reference repository is [hosted on Github](https://github.com/catseye/Tamsin)\r\nwith a [Mercurial mirror on Bitbucket](https://bitbucket.org/catseye/tamsin).\r\n\r\nThis repository contains the reference implementation of Tamsin, called\r\n`tamsin`, written in Python 2.7. It can both interpret a Tamsin program and\r\ncompile a program written in Tamsin to C. The distribution also contains an\r\n[implementation of the Tamsin scanner and parser written in Tamsin itself](https://github.com/catseye/Tamsin/blob/master/eg/tamsin-parser.tamsin)\r\n(although we're still a ways from a fully bootrapped implementation.)\r\n\r\nWhile the interpreter is fine for prototyping, note that some informal\r\nbenchmarking revealed the compiled C programs to be about 30x faster. **Note**\r\nhowever that while the compiler passes all the tests, it currently fails to\r\ncorrectly compile the Tamsin parser written in Tamsin, so it should still be\r\nconsidered a **proof of concept**.\r\n\r\nTo start using `tamsin`,\r\n\r\n* Clone the repository — `git clone https://github.com/catseye/tamsin`\r\n* Either:\r\n * Put the repo's `bin` directory on your `$PATH`, or\r\n * Make a symbolic link to `bin/tamsin` somewhere already on your `$PATH`.\r\n* Errr... that's it.\r\n\r\n(Or, to make those steps trivial, you could use\r\n[toolshelf](https://github.com/catseye/toolshelf) and run\r\n`toolshelf dock gh:catseye/tamsin`)\r\n\r\nThen you can run `tamsin` like so:\r\n\r\n* `tamsin run eg/csv_parse.tamsin < eg/names.csv`\r\n\r\nYou can also compile to C and compile the C to an executable and run the\r\nexecutable all in one step, like so:\r\n\r\n* `tamsin loadngo eg/csv_extract.tamsin < eg/names.csv`\r\n\r\nDesign Goals\r\n------------\r\n\r\n* Allow parsers, static analyzers, interpreters, and compilers to be\r\n quickly prototyped. (And in the future, processor simulators and VM's\r\n and such things too.)\r\n* Allow writing these things very compactly.\r\n* Allow writing anything using only recursive-descent parsing techniques\r\n (insofar as this is possible.)\r\n* Provide means to solve practical problems.\r\n* Keep the language simple (grammar should fit on a page.)\r\n* Recognize that the preceding two goals are in tension.\r\n* Have a relatively simple reference implementation (currently less than\r\n 3000 lines of code, including everything — debugging and the C runtime\r\n used by the compiler.)\r\n\r\nLicense\r\n-------\r\n\r\nBSD-style license; see the file [LICENSE](https://github.com/catseye/Tamsin/blob/master/LICENSE).\r\n\r\nRelated work\r\n------------\r\n\r\n* [CoCo/R](http://www.scifac.ru.ac.za/coco/) (parser generation)\r\n* [Parsec](http://www.haskell.org/haskellwiki/Parsec) (parser combination)\r\n* [Perl](http://perl.com/) (rubbish listing)\r\n* [Erlang](http://erlang.org/) (pattern-matching)\r\n* [K](https://github.com/kevinlawler/kona) (similar feel; Tamsin\r\n is a _vertical language_)\r\n* [Cat's Eye Technologies](http://catseye.tc)' esoteric and experimental\r\n languages:\r\n * [Squishy2K](http://catseye.tc/node/Squishy2K)\r\n * [Arboretuum](http://catseye.tc/node/Arboretuum)\r\n * [Treacle](http://catseye.tc/node/Treacle)\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}⏎ |