UNPKG

3.76 kBMarkdownView Raw
1Dollphie
2========
3
4Dollphie is a structured document language inspired by
5[Scribble](http://docs.racket-lang.org/scribble/), and mainly designed for
6documenting source code. It's also a retake on my previous attempt at
7[a similar language for annotating source code](http://robotlolita.me/2013/02/23/unfancy-documentation.html),
8but this is more light-weight, more general, and more expressive.
9
10
11## 0. Overview
12
13Dollphie is a Lisp-like language with lightweight syntax for writing large
14amount of text, and some syntactical sugar for inline formatting. Unlike
15languages like LaTeX, Dollphie has a consistent grammar, and is not tied to a
16particular output format.
17
18A documentation for a module could be written in Dollphie as follows:
19
20 # module: Operators
21
22 Provides operators as first-class functions.
23
24 -- Core operators --------------------------------------------------
25
26 ### function: add
27
28 Returns the sum of two *numbers*.
29
30 @type{Number -> Number -> Number}
31 @code('js) ::
32 function add(a){ return function(b) {
33 return a + b
34 }}
35
36 -- Exports ---------------------------------------------------------
37
38 @code('js){{{
39 module.exports = add
40 }}}
41
42Once we desugar the document, we get the following Dollphie code:
43
44 @module("Operators" [
45 @text("Provides operators as first-class functions.")
46 @section("Core operators" [
47 @function("add" [
48 @text("Returns the sum of two " @bold("numbers."))
49 @type(block: "Number -> Number -> Number")
50 @code('js block: "function add(a){ return function(b) {
51 return a + b
52 }}")])])
53 @section("Exports" [
54 @code('js block: "module.exports = add")])])
55
56
57## 1. Formal syntax
58
59Dollphie is a fairly simple Lisp dialect:
60
61```hs
62eol = "\n" | "\r"
63space = EOL | " " | "\t"
64
65digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
66digits = digit+
67number = digits ("." digits)?
68
69escapedChar = "\\" char
70stringChar = escapedChar | not("\"")
71string = "\"" stringChar* "\""
72
73reserved = "define" | "let" | "if" | "fun" | "quote"
74special = "{" | "}" | "(" | ")" | "[" | "]" | ":" | "'" | "\"" | "@"
75nameStart = not(special | digit | space)
76nameRest = not(special | space)
77name = nameStart nameRest* [unless reserved]
78
79bool = "true" | "false"
80nil = "nil"
81vector = "[" value* "]"
82symbol = "'" name
83value = number | string | name | symbol | vector | nil
84
85call = "@" name callArgs? callBlock?
86callArgs = "(" callExpression* ")"
87callExpression = name [no space here] ":" expression
88 | expression
89callBlock = simpleBlock | rawBlock | indentBlock
90simpleBlock = "{" ["\\}" or anything but "}"] "}"
91rawBlock = "{{{" [anything but "}}}"] "}"
92indentBlock = "::" INDENT [anything] DEDENT
93
94def = "@define" "(" name args expression* ")"
95args = "[" name* "]"
96
97let = "@let" "(" letVector expression* ")"
98letVector = "[" (name [no space here] ":" value)+ "]"
99
100if = "@if" "(" expression "then:" expression "else:" expression ")"
101
102fun = "@fun" "(" args expression* ")"
103
104quote = "@raw" "(" expression ")"
105
106expression = let | if | fun | def | quote | call | value
107document = expression*
108```
109
110The sugared dialect has the following grammar:
111
112```hs
113heading = section | declaration
114block = paragraph | expression
115
116section = '-'+ title '-'*
117title = not('-')*
118declaration = '#'+ name [no space here] ':' qualifiedName '#'*
119
120qualifiedName = name ('.' name)*
121
122hardLine = '|' text+ EOL
123softLine = text+ EOL
124blankLine = ws EOL
125paragraph = (hardLine | softLine)+ blankLine
126
127strong = '\\*' | '*' text+ '*'
128italic = '\\/' | '/' text+ '/'
129formatting = strong | italic
130
131text = expression | formatting | word
132word = [anything but whitespace]
133```