+determined by the immediately surrounding context -- usually some kind of
+bracket. The first such delimiter character which is not enclosed in
+brackets, braces or parentheses ends the fragment.
+
+%%%--------------------------------------------------------------------------
+\section{C types} \label{sec:syntax.type}
+
+Sod's syntax for C types closely mirrors the standard C syntax. A C type has
+two parts: a sequence of @<declaration-specifier>s and a @<declarator>. In
+Sod, a type must contain at least one @<declaration-specifier> (i.e.,
+`implicit @|int|' is forbidden), and storage-class specifiers are not
+recognized.
+
+
+\subsection{Declaration specifiers} \label{sec:syntax.type.declspec}
+
+\begin{grammar}
+<declaration-specifier> ::= <type-name>
+\alt "struct" <identifier> | "union" <identifier> | "enum" <identifier>
+\alt "void" | "char" | "int" | "float" | "double"
+\alt "short" | "long"
+\alt "signed" | "unsigned"
+\alt "bool" | "_Bool"
+\alt "imaginary" | "_Imaginary" | "complex" | "_Complex"
+\alt <qualifier>
+\alt <storage-specifier>
+\alt <atomic-type>
+\alt <other-declspec>
+
+<qualifier> ::= <atomic> | "const" | "volatile" | "restrict"
+
+<plain-type> ::= @<declaration-specifier>^+ <abstract-declarator>
+
+<atomic-type> ::= <atomic> "(" <plain-type> ")"
+
+<atomic> ::= "atomic" | "_Atomic"
+
+<storage-specifier> ::= <alignas> "(" <c-fragment> ")"
+
+<alignas> ::= "alignas" "_Alignas"
+
+<type-name> ::= <identifier>
+\end{grammar}
+
+Declaration specifiers may appear in any order. However, not all
+combinations are permitted. A declaration specifier must consist of zero or
+more @<qualifier>s, zero or more @<storage-specifier>s, and one of the
+following, up to reordering:
+\begin{itemize}
+\item @<type-name>;
+\item @<atomic-type>;
+\item @"struct" @<identifier>; @"union" @<identifier>; @"enum" @<identifier>;
+\item @"void";
+\item @"_Bool", @"bool";
+\item @"char"; @"unsigned char"; @"signed char";
+\item @"short", @"signed short", @"short int", @"signed short int";
+ @"unsigned short", @"unsigned short int";
+\item @"int", @"signed", @"signed int"; @"unsigned", @"unsigned int";
+\item @"long", @"signed long", @"long int", @"signed long int"; @"unsigned
+ long", @"unsigned long int";
+\item @"long long", @"signed long long", @"long long int", @"signed long long
+ int"; @"unsigned long long", @"unsigned long long int";
+\item @"float"; @"double"; @"long double";
+\item @"float _Imaginary", @"float imaginary"; @"double _Imaginary", @"double
+ imaginary"; @"long double _Imaginary", @"long double imaginary";
+\item @"float _Complex", @"float complex"; @"double _Complex", @"double
+ complex"; @"long double _Complex", @"long double complex".
+\end{itemize}
+All of these have their usual C meanings. Groups separated by commas mean
+the same thing, and Sod will not preserve the distinction.
+
+Almost all of these mean the same as they do in C. There are some minor
+differences:
+\begin{itemize}
+\item In C, the `tag' namespace is shared between @|struct|, @|union|, and
+ @|enum|; Sod has three distinct namespaces for tags. This may be fixed in
+ the future.
+\item The @<other-declspec> production is a syntactic extension point, where
+ extensions can introduce their own additions to the type system.
+\end{itemize}
+
+C standards from C99 onwards have tended to introduce new keywords beginning
+with an underscore followed by an uppercase letter, so as to avoid conflicts
+with existing code. More conventional spellings are then provided by macros
+in new header files. For example, C99 introduced @"_Bool", and a header file
+@|<stdbool.h>| which defines the macro @|bool|. Sod recognizes both the ugly
+underscore names and the more conventional macro names on input, but always
+emits the ugly names. This doesn't cause a compatibility problem in Sod,
+because Sod's parser recognizes keywords only in the appropriate context.
+For example, the (ill-advised) slot declaration
+\begin{prog}
+ bool bool;
+\end{prog}
+is completely acceptable, and will cause the C structure member
+\begin{prog}
+ \_Bool bool;
+\end{prog}
+to be emitted on output, which will be acceptable to C as long as
+@|<stdbool.h>| is not included.
+
+A @<type-name> is an identifier which has been declared as being a type name,
+using the @"typename" or @"class" definitions. The following type names are
+defined in the built-in module.
+\begin{itemize}
+\item @|va_list|
+\item @|size_t|
+\item @|ptrdiff_t|
+\item @|wchar_t|
+\end{itemize}
+
+
+\subsection{Declarators} \label{sec:syntax.type.declarator}
+
+\begin{grammar}
+<declarator>$[k, a]$ ::= @<pointer>^* <primary-declarator>$[k, a]$
+
+<primary-declarator>$[k, a]$ ::= $k$
+\alt "(" <primary-declarator>$[k, a]$ ")"
+\alt <primary-declarator>$[k, a]$ @<declarator-suffix>$[a]$
+
+<pointer> ::= "*" @<qualifier>^*
+
+<declarator-suffix>$[a]$ ::= "[" <c-fragment> "]"
+\alt "(" $a$ ")"
+
+<argument-list> ::= $\epsilon$ | "\dots"
+\alt <list>$[\mbox{@<argument>}]$ @["," "\dots"@]
+
+<argument> ::= @<declaration-specifier>^+ <argument-declarator>
+
+<abstract-declarator> ::= <declarator>$[\epsilon, \mbox{@<argument-list>}]$
+
+<argument-declarator> ::=
+ <declarator>$[\mbox{@<identifier> | $\epsilon$}, \mbox{@<argument-list>}]$
+
+<simple-declarator> ::=
+ <declarator>$[\mbox{@<identifier>}, \mbox{@<argument-list>}]$
+\end{grammar}
+
+The declarator syntax is taken from C, but with some differences.
+\begin{itemize}
+\item Array dimensions are uninterpreted @<c-fragments>, terminated by a
+ closing square bracket. This allows array dimensions to contain arbitrary
+ constant expressions.
+\item A declarator may have either a single @<identifier> at its centre or a
+ pair of @<identifier>s separated by a @`.'; this is used to refer to
+ slots or messages defined in superclasses.
+\end{itemize}
+The remaining differences are (I hope) a matter of presentation rather than
+substance.
+
+There is additional syntax to support messages and methods which accept
+keyword arguments.
+
+\begin{grammar}
+<keyword-argument> ::= <argument> @["=" <c-fragment>@]
+
+<keyword-argument-list> ::=
+ @[<list>$[\mbox{@<argument>}]$@]
+ "?" @[<list>$[\mbox{@<keyword-argument>}]$@]
+
+<method-argument-list> ::= <argument-list> | <keyword-argument-list>
+
+<dotted-name> ::= <identifier> "." <identifier>
+
+<keyword-declarator>$[k]$ ::=
+ <declarator>$[k, \mbox{@<method-argument-list>}]$
+\end{grammar}
+
+%%%--------------------------------------------------------------------------
+\section{Properties} \label{sec:syntax.prop}
+
+\begin{grammar}
+<properties> ::= "[" <list>$[\mbox{@<property>}]$ "]"
+
+<property> ::= <identifier> "=" <expression>
+
+<expression> ::= <logical-or>
+
+<logical-or> ::= <logical-and>
+ | <logical-or> "||" <logical-and>
+
+<logical-and> ::= <bitwise-or>
+ | <logical-and> "&&" <bitwise-or>
+
+<bitwise-or> ::= <bitwise-xor>
+ | <bitwise-or> "|" <bitwise-xor>
+
+<bitwise-xor> ::= <bitwise-and>
+ | <bitwise-xor> "^" <bitwise-and>
+
+<bitwise-and> ::= <equality>
+ | <bitwise-and> "&" <equality>
+
+<equality> ::= <ordering>
+ | <equality> "==" <ordering>
+ | <equality> "!=" <ordering>
+
+<ordering> ::= <shift>
+ | <ordering> "<" <shift>
+ | <ordering> "<=" <shift>
+ | <ordering> ">=" <shift>
+ | <ordering> ">" <shift>
+
+<shift> ::= <additive>
+ | <shift> "<<" <additive>
+ | <shift> ">>" <additive>
+
+<additive> ::= <term>
+ | <additive> "+" <term>
+ | <additive> "--" <term>
+
+<term> ::= <factor>
+ | <term> "*" <factor>
+ | <term> "/" <factor>
+
+<factor> ::= <primary>
+ | "!" <factor> | "~" factor
+ | "+" <factor> | "--" <factor>
+
+<primary> ::=
+ <integer-literal> | <string-literal> | <char-literal> | <identifier>
+\alt "<" <plain-type> ">" | "{" <c-fragment> "}" | "?" <s-expression>
+ | "(" <expression> ")"
+\end{grammar}
+
+\emph{Property sets} are a means for associating miscellaneous information
+with compile-time metaobjects such as modules, classes, messages, methods,
+slots, and initializers. By using property sets, additional information can
+be passed to extensions without the need to introduce idiosyncratic syntax.
+(That said, extensions can add additional first-class syntax, if necessary.)
+
+An error is reported if an unrecognized property is associated with an
+object.
+
+
+\subsection{Property values} \label{sec:syntax.prop.value}
+
+A property has a name, given as an @<identifier>, and a value computed by
+evaluating an @<expression>. The value can be one of a number of types.
+
+\begin{itemize}
+
+\item An @<integer-literal> denotes a value of type @|int|.
+
+\item Similarly @<string-literal> and @<char-literal> denote @|string| and
+ @|char| values respectively. Note that, as properties, characters are
+ quite distinct from integers, whereas in C, a character literal denotes a
+ value of type @|int|.