aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2020-10-29 17:26:20 -0600
committerMelody Horn <melody@boringcactus.com>2020-10-29 17:26:20 -0600
commitc63fa2bbbdde21fb45ea98e3c69bbddbf25097a5 (patch)
treecb353675f554c67bacc8461f2dc0cb2ff9fac875
parent09d5c19296d6a1c7e58f995c5647500720b0a8e2 (diff)
downloadspec-c63fa2bbbdde21fb45ea98e3c69bbddbf25097a5.tar.gz
spec-c63fa2bbbdde21fb45ea98e3c69bbddbf25097a5.zip
start to elaborate on syntax
-rw-r--r--_ext/crowbar_domain.py110
-rw-r--r--conf.py4
-rw-r--r--index.rst3
-rw-r--r--language/flow-control.rst6
-rw-r--r--language/index.rst26
-rw-r--r--language/scanning.rst42
-rw-r--r--todo.rst4
7 files changed, 195 insertions, 0 deletions
diff --git a/_ext/crowbar_domain.py b/_ext/crowbar_domain.py
new file mode 100644
index 0000000..a5f2570
--- /dev/null
+++ b/_ext/crowbar_domain.py
@@ -0,0 +1,110 @@
+from collections import defaultdict
+
+from docutils.parsers.rst import directives
+
+from sphinx import addnodes
+from sphinx.directives import ObjectDescription
+from sphinx.domains import Domain
+from sphinx.domains import Index
+from sphinx.roles import XRefRole
+from sphinx.util.nodes import make_refnode
+
+
+class KeywordDirective(ObjectDescription):
+ has_content = True
+ required_arguments = 1
+
+ def handle_signature(self, sig, signode):
+ signode += addnodes.desc_name(text=sig)
+ return sig
+
+ def add_target_and_index(self, name_cls, sig, signode):
+ signode['ids'].append('keyword' + '-' + sig)
+ if 'noindex' not in self.options:
+ crowbar = self.env.get_domain('crowbar')
+ crowbar.add_keyword(sig)
+
+
+class KeywordIndex(Index):
+ name = 'keyword'
+ localname = 'Keyword Index'
+ shortname = 'Keyword'
+
+ def generate(self, docnames=None):
+ content = defaultdict(list)
+
+ # sort the list of recipes in alphabetical order
+ recipes = self.domain.get_objects()
+ recipes = sorted(recipes, key=lambda recipe: recipe[0])
+
+ # generate the expected output, shown below, from the above using the
+ # first letter of the recipe as a key to group thing
+ #
+ # name, subtype, docname, anchor, extra, qualifier, description
+ for name, dispname, typ, docname, anchor, _ in recipes:
+ content[dispname[0].lower()].append(
+ (dispname, 0, docname, anchor, docname, '', typ))
+
+ # convert the dict to the sorted list of tuples expected
+ content = sorted(content.items())
+
+ return content, True
+
+
+class CrowbarDomain(Domain):
+ name = 'crowbar'
+ label = 'Crowbar'
+ roles = {
+ 'ref': XRefRole()
+ }
+ directives = {
+ 'keyword': KeywordDirective,
+ }
+ indices = {
+ KeywordIndex,
+ }
+ initial_data = {
+ 'keywords': [],
+ }
+
+ def get_full_qualified_name(self, node):
+ return '{}.{}'.format('keyword', node.arguments[0])
+
+ def get_objects(self):
+ for obj in self.data['keywords']:
+ yield(obj)
+
+ def resolve_xref(self, env, fromdocname, builder, typ, target, node,
+ contnode):
+ match = [(docname, anchor)
+ for name, sig, typ, docname, anchor, prio
+ in self.get_objects() if sig == target]
+
+ if len(match) > 0:
+ todocname = match[0][0]
+ targ = match[0][1]
+
+ return make_refnode(builder, fromdocname, todocname, targ,
+ contnode, targ)
+ else:
+ print('Awww, found nothing')
+ return None
+
+ def add_keyword(self, signature):
+ """Add a new keyword to the domain."""
+ name = '{}.{}'.format('keyword', signature)
+ anchor = 'keyword-{}'.format(signature)
+
+ # name, dispname, type, docname, anchor, priority
+ self.data['keywords'].append(
+ (name, signature, 'Keyword', self.env.docname, anchor, 0))
+
+
+def setup(app):
+ app.add_domain(CrowbarDomain)
+
+ return {
+ 'version': '0.1',
+ 'parallel_read_safe': True,
+ 'parallel_write_safe': True,
+ }
diff --git a/conf.py b/conf.py
index 9aa2aa3..97209db 100644
--- a/conf.py
+++ b/conf.py
@@ -31,6 +31,8 @@ extensions = [
'recommonmark',
'crowbar_lexer',
'gemtext_builder',
+ 'crowbar_domain',
+ 'sphinx.ext.todo',
]
# Add any paths that contain templates here, relative to this directory.
@@ -43,6 +45,8 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
highlight_language = 'crowbar'
+todo_include_todos = True
+
# -- Options for HTML output -------------------------------------------------
diff --git a/index.rst b/index.rst
index 1b6f429..99f5d44 100644
--- a/index.rst
+++ b/index.rst
@@ -57,7 +57,9 @@ Chapters
safety
errors
syntax
+ language/index
LICENSE
+ todo
.. only:: html
@@ -65,4 +67,5 @@ Chapters
==================
* :ref:`genindex`
+ * :ref:`crowbar-keyword`
* :ref:`search`
diff --git a/language/flow-control.rst b/language/flow-control.rst
new file mode 100644
index 0000000..853b5bd
--- /dev/null
+++ b/language/flow-control.rst
@@ -0,0 +1,6 @@
+Flow Control
+============
+
+.. crowbar:keyword:: break
+
+ This keyword exits the containing loop.
diff --git a/language/index.rst b/language/index.rst
new file mode 100644
index 0000000..79702c5
--- /dev/null
+++ b/language/index.rst
@@ -0,0 +1,26 @@
+Language
+========
+
+The syntax of Crowbar is designed to be similar to the syntax of C.
+
+A Crowbar source file is UTF-8.
+Crowbar source files can come in two varieties:
+
+.. glossary::
+
+ header file
+ A Crowbar source file declaring types and functions.
+ Can be intended for internal use within a project, or to define the public API of a library.
+ Conventionally has the ``.hro`` file extension.
+
+ implementation file
+ A Crowbar source file providing function definitions, and sometimes its own type declarations.
+ Conventionally has the ``.cro`` file extension.
+
+A Crowbar source file is read into memory in two phases: *scanning* (which converts text into an unstructured sequence of tokens) and *parsing* (which converts an unstructured sequence of tokens into a parse tree).
+
+.. toctree::
+ :maxdepth: 1
+
+ scanning
+ flow-control
diff --git a/language/scanning.rst b/language/scanning.rst
new file mode 100644
index 0000000..7a7b7d3
--- /dev/null
+++ b/language/scanning.rst
@@ -0,0 +1,42 @@
+Scanning
+--------
+
+.. glossary::
+
+ keyword
+ One of the literal words ``bool``, :crowbar:ref:`break`, ``case``,
+ ``char``, ``const``, ``continue``, ``default``, ``do``, ``double``,
+ ``else``, ``enum``, ``extern``, ``float``, ``for``, ``fragile``,
+ ``function``, ``if``, ``include``, ``int``, ``long``, ``return``,
+ ``short``, ``signed``, ``sizeof``, ``struct``, ``switch``,
+ ``unsigned``, ``void``, or ``while``.
+
+ identifier
+ A nonempty sequence of characters blah blah blah
+
+ .. todo::
+
+ figure out https://www.unicode.org/reports/tr31/tr31-33.html
+
+ decimal constant
+ A sequence of characters matching the regular expression ``[0-9_]+``.
+ Denotes the numeric value of the given sequence of decimal digits.
+ Underscores are ignored by the compiler, but may be useful separators for other readers.
+
+ binary constant
+ A sequence of characters matching the regular expression ``0[bB][01_]+``.
+ Denotes the numeric value of the given sequence of binary digits (after the ``0[bB]`` prefix has been removed).
+ Underscores are ignored by the compiler, but may be useful separators for other readers.
+
+ octal constant
+ A sequence of characters matching the regular expression ``0o[0-7_]+``.
+ Denotes the numeric value of the given sequence of octal digits (after the ``0o`` prefix has been removed).
+ Underscores are ignored by the compiler, but may be useful separators for other readers.
+
+ token
+ A single atomic unit in a Crowbar source file.
+ Has one (and exactly one) of the following types.
+
+.. todo::
+
+ finish transcribing token definitions
diff --git a/todo.rst b/todo.rst
new file mode 100644
index 0000000..7f4d178
--- /dev/null
+++ b/todo.rst
@@ -0,0 +1,4 @@
+TODO
+====
+
+.. todolist::