Skip to content

atg/self-ml

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

86 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

# self-ml
# s-expression like format... markup language

# self-ml is a structural data language, akin to XML and JSON.
# Unlike XML and JSON, it is designed explicitly to be written by humans and read by computers.
# self-ml is inspired by Lisp's s-expressions.

# For a detailed description, see http://chocolatapp.com/blog/self-ml


### SYNTAX ###
# This is a comment, obviously

{# This is a block comment
   it can do this! #}

# Nodes start with a "head" and can have zero or more children
(fruit Apple Banana Orange)

# You can nest nodes, and yes you can have more than one top-level node
# Despite the formatting, whitespace and newlines are completely ignored, except as a separator
(food
    (fruit Apple Banana Orange)
    (veggies Potato Carrot Onion))

# There's one catch, strings can only be one word.
# Kidding! Use [ ] to introduce a string literal. You can put anything in there, *except* unbalanced square brackets
(cakes
    [Chocolate Cake]
    [Carrot Cake]
    [Christmas Cake])

# The other style of string literal uses backticks. If you need to insert a literal backtick into a backtick-delimited string, double it up
(regexen
    `[a-z\[0-9]+`
    `[a-z``0-9]`)

# You can have a node with no children
(booleans
    (true)
    (false))

# Nodes with no children are NOT EQUIVALENT to literal strings. For example, this is considered different
(booleans
    true
    false)

# As a general rule, heads should be part of a finite set of expected types, whereas strings may contain any valid data
# If you have something like this, you're probably doing something wrong
(parent (child1 foo bar) (child2 foo bar) (child3 foo bar))

# Of course, all rules have exceptions. You might want to use heads to represent arbitrary keys in a dictionary
(urls
    ([^polls/$]                          mysite.polls.views.index)
    ([^polls/(?P<poll_id>\d+)/$]         mysite.polls.views.detail)
    ([^polls/(?P<poll_id>\d+)/results/$] mysite.polls.views.results)
    ([^polls/(?P<poll_id>\d+)/vote/$]    mysite.polls.views.vote)
)