Commit e2467af3 authored by eckhart's avatar eckhart
Browse files

TODO.md extended and renamed it to CONTRIBUTING.md

parent 40fd996b
Contributing
============
DHParser while already fairly mature in terms of implemented features is still
in an experimental state, where the API is changed and smaller features will
be added or dropped from version to version.
The best (and easiest) way to contribute at this stage is to try to implement
a small DSL with DHParser and report bugs and problems and make suggestions
for further development. Have a look at the README.md-file to get started.
Please the code from the git repository. Because code still changes quickly,
any prepackaged builds may be outdated. The repository is here:
https://gitlab.lrz.de/badw-it/DHParser
Also helpful, would be examples for Editor and IDE-Support for DSLs built
with DHParser. See https://gitlab.lrz.de/badw-it/MLW-DSL/tree/master/VSCode
for one such example.
In case you are interested in getting deeper into DHParser, there are some
bigger projects, below:
Ideas for further development
=============================
Better error reporting
----------------------
A problem with error reporting consists in the fact that at best only the very
first parsing error is reported accurately and then triggers a number of pure
follow up errors. Stopping after the first error would mean that in order for
the user to detect all (true) errors in his or her file, the parser would have
to be run just as many times.
A possible solution could be to define reentry points that can be caught by
a regular expression and where the parsing process restarts in a defined way.
A reentry point could be defined as a pair (regular expression, parser) or
a triple (regular expression, parent parser, parser), where "parent parser"
would be the parser in the call stack to which the parsing process retreats,
before restarting.
A challenge could be to manage a clean retreat (captured variables,
left recursion stack, etc. without making the parser guard (see
`parse.add_parser_guard`) more complex than it already is.
Also, a good variety of test cases would be desirable.
Optimizations
-------------
......@@ -66,4 +114,60 @@ debugger, i.e. a debugger that allows to trace particular parsers:
* advantages: less clutter in the EBNF-code and easier to switch between
debugging and production code by simply commenting out the
trace-statements at the beginning.
\ No newline at end of file
Semantic Actions
----------------
A alternative way (instead of using Capture-Pop/Retrieve with retrieve filters)
to implement semantic actions would be by using derived classes
in place of of the stock parser classes in the Grammar object.
The derived classes can easily implement semantic actions.
In order to integrate derived classes into the ebnf-based parser generation,
a directive could be implemented that either allows binding derived classes
to certain symbols or defining substitutes for stock parser classes or both.
The difference between the two cases (let's call them "binding" and
"substitution" to make the distinction) is that the former only
substitutes a particular parser (`term` in the example below) while the
latter substitutes all parsers of a kind (Alternative in the examples below).
In any case ebnf.EBNFCompiler should be extended to generate stubs for the
respective derived classes. The base class would either be the root parser
class for the symbol or the substituted class referred to in the directive.
Furthermore, ebnf.EBNFCompiler must, of course use the substituting parsers
in the generated Grammar class.
Syntax proposal and example (EBNF directive)
@semantic_action = term, SemanticAlternative:Alternative
expression = term { ("+" | "-") term}
term = factor { ("*"|"/") factor }
...
The generated code might look like:
class TermSeries(Series):
"""A derived class of parser Series with semantic actions"""
def __call__(self, text: StringView) -> Tuple[Optional[Node], StringView]:
result = super().__call__(text)
# please implement your semantic action here
class SemanticAlternative(Alternative):
"""A derived class of parser Series with semantic actions"""
def __call__(self, text: StringView) -> Tuple[Optional[Node], StringView]:
result = super().__call__(text)
# please implement your semantic action here
class ArithmeticGrammar(Gramma):
...
expression = Forward()
term = TermSeries(factor, ZeroOrMore(Series(SemanticAlternative(Token("*"), Token("/")), factor)))
expression.set(Series(term, ZeroOrMore(Series(SemanticAlternative(Token("+"), Token("-")), term))))
root__ = expression
......@@ -234,7 +234,7 @@ class Parser(ParserBase):
def __init__(self, name: str = '') -> None:
# assert isinstance(name, str), str(name)
super(Parser, self).__init__(name)
super().__init__(name)
self._grammar = None # type: 'Grammar'
self.reset()
......
expression = term { ("+" | "-") term} ;
term = factor { ("*"|"/") factor} ;
factor = constant | variable | "(" expression ")" ;
variable = "x" | "y" | "z" ;
constant = digit {digit} ;
digit = "0" | "1" | "..." | "9" ;
test = digit constant variable ;
expression = term { ("+" | "-") term}
term = factor { ("*"|"/") factor}
factor = constant | variable | "(" expression ")"
variable = "x" | "y" | "z"
constant = digit {digit}
digit = "0" | "1" | "..." | "9"
test = digit constant variable
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment