File: semantics.rst

package info (click to toggle)
python-tatsu 5.17.1%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,516 kB
  • sloc: python: 13,185; makefile: 127
file content (79 lines) | stat: -rw-r--r-- 2,360 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
.. Copyright (c) 2017-2026 Juancarlo AƱez (apalala@gmail.com)
.. SPDX-License-Identifier: BSD-4-Clause

.. include:: links.rst

Semantic Actions
----------------

|TatSu| grammars lack notation for semantic actions. That is on purpose,
because semantic actions within a grammar obscure the declarative nature
of the context, and allow poor modularization from the parser-execution
perspective.

Semantic actions are defined in a class, and applied by passing an
object of the class to the ``parse()`` method of the parser as the
``semantics=`` parameter. |TatSu| will invoke the method that matches
the name of the grammar rule every time the rule parses. The argument to
the method will be the `AST`_ constructed from the right-hand-side of
the rule:

.. code:: python

    class MySemantics:
        def some_rule_name(self, ast):
            return ''.join(ast)

        def _default(self, ast):
            pass

If there's no method matching the rule's name, |TatSu| will try to
invoke a ``_default()`` method if it's defined:

.. code:: python

    def _default(self, ast):
        ...

Nothing will happen if neither the per-rule method nor ``_default()``
are defined.

The per-rule methods in classes implementing the semantics provide
enough opportunity to do rule post-processing operations, like
verifications (for inadequate use of keywords as identifiers), or `AST`_
transformation:

.. code:: python

    class MyLanguageSemantics:
        def identifier(self, ast):
            if my_lange_module.is_keyword(ast):
                raise FailedSemantics('"%s" is a keyword' % str(ast))
            return ast

For finer-grained control it's enough to declare more rules, as the
impact on the parsing times will be minimal.

If preprocessing is required at some point, it's enough to place
invocations of empty rules where appropriate:

.. code:: python

    myrule = first_part preproc {second_part} ;

    preproc = () ;

The abstract parser will honor as a semantic action a method declared
as:

.. code:: python

    def preproc(self, ast):
        ...


.. _Abstract Syntax Tree: http://en.wikipedia.org/wiki/Abstract_syntax_tree
.. _AST: http://en.wikipedia.org/wiki/Abstract_syntax_tree
.. _PEG: http://en.wikipedia.org/wiki/Parsing_expression_grammar
.. _Python: http://python.org
.. _keywords: https://en.wikipedia.org/wiki/Reserved_word