Skip to content

Commit

Permalink
Add grammar description
Browse files Browse the repository at this point in the history
  • Loading branch information
IwoHerka committed Jun 17, 2018
1 parent da1380a commit d8b7acd
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/source/_templates/sidebarintro.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ <h3>Useful Links</h3>
<li><a href="https://pypi.org/project/sexpr/">PyPI</a></li>
<li><a href="http://github.com/IwoHerka/sexpr">GitHub</a></li>
<li><a href="http://github.com/IwoHerka/sexpr/issues">Issue Tracker</a></li>
<li><a href="paypal.me/IwoHerka">Buy me a beer</a></li>
<li><a href="https://paypal.me/IwoHerka">Buy me a beer</a></li>
</ul>
79 changes: 79 additions & 0 deletions docs/source/defining_grammar.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,81 @@
Defining Grammar
================

Grammar in **sexpr** is defined in YAML, data serialisation language.
If you're looking for a quick primer, check out: `Learn YAML in Y minutes
<https://learnxinyminutes.com/docs/yaml/>`_.
Don't worry though, you don't need to know it to you define a grammar.
Syntax is very simple. Before we dive into concretes,
however, we must agree on some basic lingo.

Basic notions
-------------

Notation used in **sexpr** it very similar to `ENBF
<https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form>`_.
Simiarly, grammar is defined in terms or *rules*. Rules can be
*terminal* or *non-terminal*. Simply put, non-terminal rules
are all rules that correspond to concrete nodes in the end s-expression,
whereas terminal rules always define substitution.

Therefore, in an expression `(add 1 2)` of the grammar::

rules:
op:
- add
add:
- [ val ]
val:
[ 1, 2 ]

`add` is a non-terminal and `val` is a terminal rule. Please note that, by that
definition, root rule `op` is also a terminal rule. Moreover, as a consequence
of this definition, names of terminal rules defined in YAML are the only
ones to appear in the end s-expression.

Finally, in the above example, literals *1* and *2* are called *terminal symbols*.
They are the bottom of the hierarchy and cannot be substitued for anything
else.

Grammar in YAML
---------------

With that out of the way, writing actual grammar is pretty straightforward.
Each grammar must start with a **root rule**. Root rule is a top-level rule
definining what *every* valid s-expression in the grammar must be.
For example, in the grammar of predicates, root rule would simply be "predicate"::

rules:
predicate:
- tautology
- contradiction
- bool_or
- bool_and
- bool_not

Typically, like in this example, root rule is an alternative
(:class:`~sexpr.types.Alternative`). It says
that every predicate is a tautology or a contradiction or an alternation or
a conjunction or a negative.

Next in line are non-terminal rules. In YAML, they always have the form::

<name>:
- [ <expr><modifier>?[, <expr><modifier>?]* ]

For example::

one_or_more:
- [ expr+ ] # e.g. ['tag', 1, 2, 3]
zero_or_more:
- [ expr* ] # e.g. ['tag'] or ['tag', 1, 2, 3, 4]
exactly_two:
- [ expr, expr ] # e.g. ['tag', 1, 2]
exactly_one:
- [ expr ] # e.g. ['tag', 1]
optional:
- [ 'expr?' ] # e.g. ['tag'] or ['tag', 1]

In the example above, '?', '+' and '*' are so-called repetition modifiers.
Because of restrictions of YAML syntax, optional terms must be wrapped
in quotation marks.

0 comments on commit d8b7acd

Please sign in to comment.