Towards a Better BBCode

SexpCode is a specialised mark-up language designed to replace BBCode and, to a lesser extent, user-generated HTML in general. It is not as yet intended as a general-purpose mark-up language, or to replace HTML for general web design.
SexpCode does away with the verbosity that has plagued HTML and XML since SGML, without sacrificing power and ease of use, and without succumbing to the various problems that plague other solutions, like Markdown.

This document provides an informal description of its syntax, pending the outcome of the ISO standardisation process.

Table of Contents

1. Simple functions

Most SexpCode functions are quite simple, and are applied like this:

{b This is bold text.}

This is bold text.

The first word in the S-expression is the function, everything else is the text it applies to. The S-expression is delimited by curly braces rather than the traditional parentheses, because they do not occur in natural language.

If you do need a literal curly brace in your text, you can escape it with a backslash.

{b These \}\} curly braces will not generate a syntax error, because they are ignored.}

These }} curly braces will not generate a syntax error, because they are ignored.

If you need a literal backslash, you can escape it with a backslash as well (though it will generally be ignored unless it precedes a curly brace).

S-expressions can be nested, of course:

{b This text is bold. {i This text is italic and bold.}}

This text is bold. This text is italic and bold.

Some functions can be iterated. sup is such a function:

{sup*2 This text is superscripted two levels.}

This text is superscripted two levels. 

You may also use an accent circonflexe instead, in keeping with traditional mathematical notation:

{sub^2 This text is subscripted two levels.}

This text is subscripted two levels. 

And finally, functions can be composed with a dot:

{b.i This text is both bold and italic.}

This text is both bold and italic.

Your expressions can get arbitrarily complicated:

{b.sup*2.i Way to be a dick, {sub*2.u.o dick}.}

Way to be a dick, dick. 

It should be noted the iteration operator has precedence over function composition.

Table 1 details the simple functions a SexpCode implementation can be expected to support.

Table 1: Simple functions
Function Description Example
b Bold text Text.
i Italic text Text.
u Underlined text Text.
o Overlined text Text.
s Strike-through Text.
m Monospaced text Text.
tt Teletype Text.
spoiler Obfuscated text Text.
sup Superscript Text.
sub Subscript Text.
quote Blockquote


† See appendix 1.
‡ May be iterated.

2. Higher-Arity Functions

Some functions can take arguments. url is an example of a function of arity 1:

{url Click here!}

Click here!

This syntax is equivalent to the following:

{{url} Click here!}

Click here!

This second syntax can be thought of as a partial application of the function, returning another function of lower arity. This is particularly useful if you want to compose a higher-arity function int a 0-arity function expression:

{{url}.b.i Bold italic link!}

Bold italic link!

If two higher-arity functions are composed, the arguments apply in the order of composition:

{url.code Python Contrived example.}

Contrived example.

If you need to pass an argument that has whitespace in it, use the following syntax:

{code '{Algorithmic Language Scheme} (fibs 10)}

(fibs 10)

The following is a list of higher-arity functions SexpCode can be expected to support:

Table 2: Higher-arity functions
Function Arguments Description
url target Hyperlinks
code lang Code
img source Images; see appendix 2

3. Verbatim

Should you wish to post some literal SexpCode, you could manually escape every curly brace as mentioned, or you could use the verbatim function:

{verbatim This {b text} will {i not} be translated.}

This {b text} will {i not} be translated.

The downside of this is that it still requires that the inside text be syntactically valid SexpCode. If you wish to post arbitrary text instead, there is an alternative syntax:

{- This }} text can {{{ have as many unbalanced braces as it likes. -}

This }} text can {{{ have as many unbalanced braces as it likes.

Here, the dash may be any expression (of arbitrary length) that starts with a non-alphanumeric character. The closing tag must be preceded by a space followed by the same expression.

4. Function Definition

It is possible to define your own functions:

{define em i}{em This text is highly semantic.}

This text is highly semantic.

Any function may be freely redefined, including built-in ones. Functions defined like this only have meaning to text after their initial definition.

{b This text is bold.} {define b i}{b This text is not.}

This text is bold. This text is not.

It goes without saying that the second argument of your function composition can be an arbitrarily complex function expression:

{define expert b.i.o.u.{code SexpCode}}{expert Like a boss}

Like a boss

Arity is passed transparently:

{define link url.i}{link Link!}


The only restriction is that defined functions cannot be iterated.

{define super sup*3}{super*3 Only three sups, or maybe an error.}

Only three sups, or maybe an error 

Function definition may be particularly useful to call a higher-arity function with the same set of arguments every time:

{define code verbatim.{code SexpCode}}
{code {b.i.o.u.s expart}}
Normal text.
{code {b more code}}

{b.i.o.u.s expart}
Normal text.
{b more code}

To undo function definitions, undefine works as you would expect.

{define a b}{undefine a}

Note that it is impossible to undefine built-in functions, and undefining a defined function with the name of a built-in function will revert that function to its original behavior:

{define b i}{b This text is in italics.} {undefine b}{b Now it's bold again.}

This text is in italics. Now it's bold again.

Appendix 1: Spoiler

The spoiler function is one of the few that doesn't have a direct HTML equivalent. It is unsurprising that many BBCode dialects don't bother with it.
The usual implementation is as black text on a black background. On mouse-over, the text turns white.

This is a typical spoiler.

An alternative could be the following, with or without automatic decoding:

Guvf vf n fcbvyre uvqqra ol EBG13.

These are merely suggestions, however, and the SexpCode standard has no specific requirements about how exactly the spoiler function is implemented. It only requires that it is implemented.

Appendix 2: Images

The img function is perhaps an odd one, in that you might not expect it to apply to text. However, not applying it to any text (outside of use in a composition of functions) is a syntax error.

When SexpCode is translated to HTML, the text the function is applied to is expected to be used for the alt attribute. XHTML has made this attribute compulsory, and even for older standards it is generally considered good form to use it.
Additionally, the same text may also be used for the title attribute, and perhaps to provide a caption.

{img This is a wug.}

This is a wug.

When SexpCode is translated to something other than HTML, the text may be used for a caption, for description of the image in some sort of image index, or it may be discarded altogether. This is up to the implementation.

When captions are not used, it may not make sense to allow the img function to be composable. Implementations may disallow composition in this case, or may opt to ignore the functions img is composed with.

Some webmasters may wish to use SexpCode for user comments, and may consider it inappropriate to allow users to post images. If they wish to disable img support entirely, this is allowed by the standard.

Appendix 3: Variants

We appreciate that SexpCode may be too powerful a language for a lot of applications, and that implementing it is more difficult than implementing BBCode. For this reason, the standard allows for reduced syntax implementations, collectively known as SexpCode.

There is no strict definition of SexpCode; it is a catch-all term referring to any SexpCode variant which does not implement all features detailed in this spec. To still be recognised as SexpCode, however, implementations must support at least the following items:

  1. Simple functions (all of them)
  2. Functions of arity 1, with the first argument syntax (url and code)
  3. Backslash escaping

Everything else (function composition, iteration, definition, &c.) is optional. Implementations that do implement all of these things may refer to themselves as SexpCode+, to make the distinction explicit.
The plain term SexpCode may refer to either SexpCode or SexpCode+. In this document, as in all documents of the SexpCode Working Group, it refers exclusively to SexpCode+. In case of ambiguity, we recommend being explicit.