<id-body-char> ::= <id-start-char> @! <digit-char>
-<alpha-char> ::= "A" | "B" | \dots\ | "Z"
-\alt "a" | "b" | \dots\ | "z"
-\alt <extended-alpha-char>
+<alpha-char> ::= "A" | "B" $| \cdots |$ "Z"
+ | "a" | "b" $| \cdots |$ "z"
+ | <extended-alpha-char>
<digit-char> ::= "0" | <nonzero-digit-char>
-<nonzero-digit-char> ::= "1" | "2" $| \ldots |$ "9"
+<nonzero-digit-char> ::= "1" | "2" $| \cdots |$ "9"
\end{grammar}
The precise definition of @<alpha-char> is left to the function
-\textsf{alpha-char-p} in the hosting Lisp system. For portability,
-programmers are encouraged to limit themselves to the standard ASCII letters.
+@|alpha-char-p| in the hosting Lisp system. For portability, programmers are
+encouraged to limit themselves to the standard ASCII letters.
There are no reserved words at the lexical level, but the higher-level syntax
recognizes certain identifiers as \emph{keywords} in some contexts. There is
<char-literal> ::= "'" <char-literal-char> "'"
-<string-literal-char> ::= any character other than "\\" or "\""
-\alt "\\" <char>
+<string-literal-char> :: "\\" <char>
+ | any character other than "\\" or "\""
-<char-literal-char> ::= any character other than "\\" or "'"
-\alt "\\" <char>
+<char-literal-char> :: "\\" <char>
+ | any character other than "\\" or "'"
<char> ::= any single character
\end{grammar}
\begin{grammar}
<integer-literal> ::= <decimal-integer>
-\alt <binary-integer>
-\alt <octal-integer>
-\alt <hex-integer>
+ | <binary-integer>
+ | <octal-integer>
+ | <hex-integer>
<decimal-integer> ::= "0" | <nonzero-digit-char> @<digit-char>^*
-<binary-integer> ::= "0" @("b"|"B"@) @<binary-digit-char>^+
+<binary-integer> ::= "0" @("b" @! "B"@) @<binary-digit-char>^+
<binary-digit-char> ::= "0" | "1"
-<octal-integer> ::= "0" @["o"|"O"@] @<octal-digit-char>^+
+<octal-integer> ::= "0" @["o" @! "O"@] @<octal-digit-char>^+
-<octal-digit-char> ::= "0" | "1" $| \ldots |$ "7"
+<octal-digit-char> ::= "0" | "1" $| \cdots |$ "7"
-<hex-integer> ::= "0" @("x"|"X"@) @<hex-digit-char>^+
+<hex-integer> ::= "0" @("x" @! "X"@) @<hex-digit-char>^+
<hex-digit-char> ::= <digit-char>
-\alt "A" | "B" | "C" | "D" | "E" | "F"
-\alt "a" | "b" | "c" | "d" | "e" | "f"
+ | "A" | "B" | "C" | "D" | "E" | "F"
+ | "a" | "b" | "c" | "d" | "e" | "f"
\end{grammar}
Sod understands only integers, not floating-point numbers; its integer syntax
\subsection{Punctuation} \label{sec:syntax.lex.punct}
\begin{grammar}
-<punctuation> ::= any nonalphanumeric character other than "_", "\"" or "'"
+<punctuation> ::= "\dots"
+\alt any nonalphanumeric character other than "_", "\"", or "'"
\end{grammar}
\subsection{Comments} \label{sec:syntax.lex.comment}
\begin{grammar}
-<comment> ::= <block-comment>
-\alt <line-comment>
+<comment> ::= <block-comment> | <line-comment>
<block-comment> ::=
"/*"
<property> ::= <identifier> "=" <expression>
-<expression> ::= <term> | <expression> "+" <term> | <expression> "--" <term>
+<expression> ::= <additive>
-<term> ::= <factor> | <term> "*" <factor> | <term> "/" <factor>
+<additive> ::= <term>
+ | <additive> "+" <term>
+ | <additive> "--" <term>
-<factor> ::= <primary> | "+" <factor> | "--" <factor>
+<term> ::= <factor>
+ | <term> "*" <factor>
+ | <term> "/" <factor>
+
+<factor> ::= <primary>
+ | "!" <factor> | "~" factor
+ | "+" <factor> | "--" <factor>
<primary> ::=
<integer-literal> | <string-literal> | <char-literal> | <identifier>
-\alt "<" <plain-type> ">"
-\alt "{" <c-fragment> "}"
-\alt "?" <s-expression>
-\alt "(" <expression> ")"
+\alt "<" <plain-type> ">" | "{" <c-fragment> "}" | "?" <s-expression>
+ | "(" <expression> ")"
\end{grammar}
\emph{Property sets} are a means for associating miscellaneous information
Finally, an S-expression preceded by @|?| causes the expression to be read in
the current package (which is always @|sod-user| at the start of a module)
and immediately evaluated (using @|eval|); the resulting value is converted
-into a property value using the \descref{decode-property}[generic
-function]{gf}.
+into a property value using the \descref{gf}{decode-property}[generic
+function].
\subsection{Property output types and coercions}
When a property value is inspected by the Sod translator, or an extension, it
is \emph{coerced} so as to conform to a requested output type. This coercion
-process is performed by the \descref{coerce-property-value}[generic
-function]{gf}, and additional output types and coercions can be defined by
+process is performed by the \descref{gf}{coerce-property-value}[generic
+function], and additional output types and coercions can be defined by
extensions. The built-in output types coercions, from the value types listed
above, are as follows.
\item The @|boolean| output type denotes a boolean value, which may be either
true or false. A value of type @|id| is considered true if it is @|true|,
- @|t|, @|yes|, @|on|, or @|verily|; or false if it is @|false|, @|nil|,
- @|no|, @|off|, or @|nowise|; it is erroneous to provide any other
- identifier where a boolean value is wanted. A value of type @|int| is
- considered true if it is nonzero, or false if it is zero.
+ @|t|, @|yes|, @|on|, @|yup|, or @|verily|; or false if it is @|false|,
+ @|nil|, @|no|, @|off|, @|nope|, or @|nowise|; it is erroneous to provide
+ any other identifier where a boolean value is wanted. A value of type
+ @|int| is considered true if it is nonzero, or false if it is zero.
\item The @|symbol| output type denotes a Lisp symbol.
upper; if the name contains letters of both cases, then it is not changed.
For example, @|foo45| becomes @|FOO45|, or \emph{vice-versa}; but @|Splat|
remains as it is. Second, the name is subjected to \emph{separator
- switching}: all underscores in the name are replaced with hyphens (and
+ switching}: all underscores in the name are replaced with hyphens (and
\emph{vice-versa}, though hyphens aren't permitted in identifiers in the
first place). Finally, the resulting name is interned in the current
package, which will usually be @|sod-user| unless changed explicitly by the
\begin{itemize}
\item The module name @<string> is converted into a filename by appending
@`.sod', if it has no extension already.\footnote{%
- Technically, what happens is \textsf{(merge-pathnames name (make-pathname
- :type "SOD" :case :common))}, so exactly what this means varies
- according to the host system.} %
+ Technically, what happens is @|(merge-pathnames name (make-pathname :type
+ "SOD" :case :common))|, so exactly what this means varies according to
+ the host system.} %
\item The file is looked for relative to the directory containing the
importing module.
\item If that fails, then the file is looked for in each directory on the
\end{itemize}
At this point, if the file has previously been imported, nothing further
happens.\footnote{%
- This check is done using \textsf{truename}, so it should see through simple
+ This check is done using @|truename|, so it should see through simple
tricks like symbolic links. However, it may be confused by fancy things
like bind mounts and so on.} %
\begin{itemize}
\item The name @<string> is converted into a filename by appending @`.lisp',
if it has no extension already.\footnote{%
- Technically, what happens is \textsf{(merge-pathnames name (make-pathname
- :type "LISP" :case :common))}, so exactly what this means varies
- according to the host system.} %
+ Technically, what happens is @|(merge-pathnames name (make-pathname :type
+ "LISP" :case :common))|, so exactly what this means varies according to
+ the host system.} %
\item A search is then made in the same manner as for module imports
(\xref{sec:syntax-module}).
\end{itemize}
-If the file is found, it is loaded using the host Lisp's \textsf{load}
-function.
+If the file is found, it is loaded using the host Lisp's @|load| function.
Note that Sod doesn't attempt to compile Lisp files, or even to look for
existing compiled files. The right way to package a substantial extension to
the Sod translator is to provide the extension as a standard ASDF system (or
similar) and leave a dropping @|foo-extension.lisp| in the module path saying
something like
-\begin{quote}
- \textsf{(asdf:load-system :foo-extension)}
-\end{quote}
+\begin{prog}
+ (asdf:load-system :foo-extension)
+\end{prog}
which will arrange for the extension to be compiled if necessary.
(This approach means that the language doesn't need to depend on any
class. It is an error if any of these @<identifier>s does not name a defined
class. The superclass list is required, and must not be empty; listing
@|SodObject| as your class's superclass is a good choice if nothing else
-seems suitable. It's not possible to define a \emph{root class} in the Sod
-language: you must use Lisp to do this, and it's quite involved.
+seems suitable. A class with no direct superclasses is called a \emph{root
+class}. It is not possible to define a root class in the Sod language: you
+must use Lisp to do this, and it's quite involved.
The @<properties> provide additional information. The standard class
properties are as follows.