Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
badw-it
DHParser
Commits
f277041a
Commit
f277041a
authored
Jul 10, 2017
by
di68kap
Browse files
- Test Case for Bug: Problem with greedy regex in ebnf.EBNFGrammar
parent
77bad89f
Changes
11
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
f277041a
...
@@ -21,3 +21,4 @@ test/tmp*
...
@@ -21,3 +21,4 @@ test/tmp*
build/
build/
dist/
dist/
MANIFEST
MANIFEST
playground/*
DHParser/dsl.py
View file @
f277041a
...
@@ -119,7 +119,8 @@ if __name__ == "__main__":
...
@@ -119,7 +119,8 @@ if __name__ == "__main__":
class
GrammarError
(
Exception
):
class
GrammarError
(
Exception
):
"""Raised when (already) the grammar of a domain specific language (DSL)
"""
Raised when (already) the grammar of a domain specific language (DSL)
contains errors.
contains errors.
"""
"""
...
@@ -129,7 +130,8 @@ class GrammarError(Exception):
...
@@ -129,7 +130,8 @@ class GrammarError(Exception):
class
CompilationError
(
Exception
):
class
CompilationError
(
Exception
):
"""Raised when a string or file in a domain specific language (DSL)
"""
Raised when a string or file in a domain specific language (DSL)
contains errors.
contains errors.
"""
"""
def
__init__
(
self
,
error_messages
,
dsl_text
,
dsl_grammar
,
AST
,
result
):
def
__init__
(
self
,
error_messages
,
dsl_text
,
dsl_grammar
,
AST
,
result
):
...
@@ -144,7 +146,8 @@ class CompilationError(Exception):
...
@@ -144,7 +146,8 @@ class CompilationError(Exception):
def
grammar_instance
(
grammar_representation
)
->
Tuple
[
Grammar
,
str
]:
def
grammar_instance
(
grammar_representation
)
->
Tuple
[
Grammar
,
str
]:
"""Returns a grammar object and the source code of the grammar, from
"""
Returns a grammar object and the source code of the grammar, from
the given `grammar`-data which can be either a file name, ebnf-code,
the given `grammar`-data which can be either a file name, ebnf-code,
python-code, a Grammar-derived grammar class or an instance of
python-code, a Grammar-derived grammar class or an instance of
such a class (i.e. a grammar object already).
such a class (i.e. a grammar object already).
...
@@ -177,7 +180,8 @@ def compileDSL(text_or_file: str,
...
@@ -177,7 +180,8 @@ def compileDSL(text_or_file: str,
dsl_grammar
:
Union
[
str
,
Grammar
],
dsl_grammar
:
Union
[
str
,
Grammar
],
ast_transformation
:
TransformationFunc
,
ast_transformation
:
TransformationFunc
,
compiler
:
Compiler
)
->
Any
:
compiler
:
Compiler
)
->
Any
:
"""Compiles a text in a domain specific language (DSL) with an
"""
Compiles a text in a domain specific language (DSL) with an
EBNF-specified grammar. Returns the compiled text or raises a
EBNF-specified grammar. Returns the compiled text or raises a
compilation error.
compilation error.
...
@@ -197,7 +201,8 @@ def compileDSL(text_or_file: str,
...
@@ -197,7 +201,8 @@ def compileDSL(text_or_file: str,
def
raw_compileEBNF
(
ebnf_src
:
str
,
branding
=
"DSL"
)
->
EBNFCompiler
:
def
raw_compileEBNF
(
ebnf_src
:
str
,
branding
=
"DSL"
)
->
EBNFCompiler
:
"""Compiles an EBNF grammar file and returns the compiler object
"""
Compiles an EBNF grammar file and returns the compiler object
that was used and which can now be queried for the result as well
that was used and which can now be queried for the result as well
as skeleton code for scanner, transformer and compiler objects.
as skeleton code for scanner, transformer and compiler objects.
...
@@ -218,7 +223,8 @@ def raw_compileEBNF(ebnf_src: str, branding="DSL") -> EBNFCompiler:
...
@@ -218,7 +223,8 @@ def raw_compileEBNF(ebnf_src: str, branding="DSL") -> EBNFCompiler:
def
compileEBNF
(
ebnf_src
:
str
,
branding
=
"DSL"
)
->
str
:
def
compileEBNF
(
ebnf_src
:
str
,
branding
=
"DSL"
)
->
str
:
"""Compiles an EBNF source file and returns the source code of a
"""
Compiles an EBNF source file and returns the source code of a
compiler suite with skeletons for scanner, transformer and
compiler suite with skeletons for scanner, transformer and
compiler.
compiler.
...
@@ -244,7 +250,8 @@ def compileEBNF(ebnf_src: str, branding="DSL") -> str:
...
@@ -244,7 +250,8 @@ def compileEBNF(ebnf_src: str, branding="DSL") -> str:
def
parser_factory
(
ebnf_src
:
str
,
branding
=
"DSL"
)
->
Grammar
:
def
parser_factory
(
ebnf_src
:
str
,
branding
=
"DSL"
)
->
Grammar
:
"""Compiles an EBNF grammar and returns a grammar-parser factory
"""
Compiles an EBNF grammar and returns a grammar-parser factory
function for that grammar.
function for that grammar.
Args:
Args:
...
@@ -264,7 +271,8 @@ def parser_factory(ebnf_src: str, branding="DSL") -> Grammar:
...
@@ -264,7 +271,8 @@ def parser_factory(ebnf_src: str, branding="DSL") -> Grammar:
def
load_compiler_suite
(
compiler_suite
:
str
)
->
\
def
load_compiler_suite
(
compiler_suite
:
str
)
->
\
Tuple
[
ScannerFactoryFunc
,
ParserFactoryFunc
,
TransformerFactoryFunc
,
CompilerFactoryFunc
]:
Tuple
[
ScannerFactoryFunc
,
ParserFactoryFunc
,
TransformerFactoryFunc
,
CompilerFactoryFunc
]:
"""Extracts a compiler suite from file or string ``compiler suite``
"""
Extracts a compiler suite from file or string ``compiler suite``
and returns it as a tuple (scanner, parser, ast, compiler).
and returns it as a tuple (scanner, parser, ast, compiler).
Returns:
Returns:
...
@@ -300,7 +308,8 @@ def load_compiler_suite(compiler_suite: str) -> \
...
@@ -300,7 +308,8 @@ def load_compiler_suite(compiler_suite: str) -> \
def
is_outdated
(
compiler_suite
:
str
,
grammar_source
:
str
)
->
bool
:
def
is_outdated
(
compiler_suite
:
str
,
grammar_source
:
str
)
->
bool
:
"""Returns ``True`` if the ``compile_suite`` needs to be updated.
"""
Returns ``True`` if the ``compile_suite`` needs to be updated.
An update is needed, if either the grammar in the compieler suite
An update is needed, if either the grammar in the compieler suite
does not reflect the latest changes of ``grammar_source`` or if
does not reflect the latest changes of ``grammar_source`` or if
...
@@ -348,7 +357,8 @@ def run_compiler(text_or_file: str, compiler_suite: str) -> Any:
...
@@ -348,7 +357,8 @@ def run_compiler(text_or_file: str, compiler_suite: str) -> Any:
def
compile_on_disk
(
source_file
:
str
,
compiler_suite
=
""
,
extension
=
".xml"
):
def
compile_on_disk
(
source_file
:
str
,
compiler_suite
=
""
,
extension
=
".xml"
):
"""Compiles the a source file with a given compiler and writes the
"""
Compiles the a source file with a given compiler and writes the
result to a file.
result to a file.
If no ``compiler_suite`` is given it is assumed that the source
If no ``compiler_suite`` is given it is assumed that the source
...
...
DHParser/parsers.py
View file @
f277041a
...
@@ -73,6 +73,7 @@ from DHParser.syntaxtree import WHITESPACE_PTYPE, TOKEN_PTYPE, ZOMBIE_PARSER, Pa
...
@@ -73,6 +73,7 @@ from DHParser.syntaxtree import WHITESPACE_PTYPE, TOKEN_PTYPE, ZOMBIE_PARSER, Pa
Node
,
TransformationFunc
Node
,
TransformationFunc
from
DHParser.toolkit
import
load_if_file
,
error_messages
from
DHParser.toolkit
import
load_if_file
,
error_messages
__all__
=
[
'ScannerFunc'
,
__all__
=
[
'ScannerFunc'
,
'HistoryRecord'
,
'HistoryRecord'
,
'Parser'
,
'Parser'
,
...
@@ -112,6 +113,7 @@ __all__ = ['ScannerFunc',
...
@@ -112,6 +113,7 @@ __all__ = ['ScannerFunc',
'compile_source'
]
'compile_source'
]
########################################################################
########################################################################
#
#
# Grammar and parsing infrastructure
# Grammar and parsing infrastructure
...
@@ -128,6 +130,7 @@ LEFT_RECURSION_DEPTH = 20 if platform.python_implementation() == "PyPy" \
...
@@ -128,6 +130,7 @@ LEFT_RECURSION_DEPTH = 20 if platform.python_implementation() == "PyPy" \
MAX_DROPOUTS
=
25
# type: int
MAX_DROPOUTS
=
25
# type: int
# stop trying to recover parsing after so many errors
# stop trying to recover parsing after so many errors
class
HistoryRecord
:
class
HistoryRecord
:
"""
"""
Stores debugging information about one completed step in the
Stores debugging information about one completed step in the
...
@@ -292,7 +295,8 @@ class Parser(ParserBase, metaclass=ParserMetaClass):
...
@@ -292,7 +295,8 @@ class Parser(ParserBase, metaclass=ParserMetaClass):
pass
pass
def
apply
(
self
,
func
:
ApplyFunc
):
def
apply
(
self
,
func
:
ApplyFunc
):
"""Applies function `func(parser)` recursively to this parser and all
"""
Applies function `func(parser)` recursively to this parser and all
descendants of the tree of parsers. The same function can never
descendants of the tree of parsers. The same function can never
be applied twice between calls of the ``reset()``-method!
be applied twice between calls of the ``reset()``-method!
"""
"""
...
@@ -305,7 +309,8 @@ class Parser(ParserBase, metaclass=ParserMetaClass):
...
@@ -305,7 +309,8 @@ class Parser(ParserBase, metaclass=ParserMetaClass):
def
mixin_comment
(
whitespace
:
str
,
comment
:
str
)
->
str
:
def
mixin_comment
(
whitespace
:
str
,
comment
:
str
)
->
str
:
"""Returns a regular expression that merges comment and whitespace
"""
Returns a regular expression that merges comment and whitespace
regexps. Thus comments cann occur whereever whitespace is allowed
regexps. Thus comments cann occur whereever whitespace is allowed
and will be skipped just as implicit whitespace.
and will be skipped just as implicit whitespace.
...
@@ -327,9 +332,11 @@ class Grammar:
...
@@ -327,9 +332,11 @@ class Grammar:
wspL__
=
''
wspL__
=
''
wspR__
=
WSP__
wspR__
=
WSP__
@
classmethod
@
classmethod
def
_assign_parser_names
(
cls
):
def
_assign_parser_names
(
cls
):
"""Initializes the `parser.name` fields of those
"""
Initializes the `parser.name` fields of those
Parser objects that are directly assigned to a class field with
Parser objects that are directly assigned to a class field with
the field's name, e.g.
the field's name, e.g.
class Grammar(Grammar):
class Grammar(Grammar):
...
@@ -361,6 +368,7 @@ class Grammar:
...
@@ -361,6 +368,7 @@ class Grammar:
parser
.
parser
.
name
=
entry
parser
.
parser
.
name
=
entry
cls
.
parser_initialization__
=
"done"
cls
.
parser_initialization__
=
"done"
def
__init__
(
self
,
root
:
Parser
=
None
)
->
None
:
def
__init__
(
self
,
root
:
Parser
=
None
)
->
None
:
# if not hasattr(self.__class__, 'parser_initialization__'):
# if not hasattr(self.__class__, 'parser_initialization__'):
# self.__class__.parser_initialization__ = "pending"
# self.__class__.parser_initialization__ = "pending"
...
@@ -372,13 +380,16 @@ class Grammar:
...
@@ -372,13 +380,16 @@ class Grammar:
self
.
dirty_flag__
=
False
self
.
dirty_flag__
=
False
self
.
history_tracking__
=
False
self
.
history_tracking__
=
False
self
.
_reset__
()
self
.
_reset__
()
# prepare parsers in the class, first
# prepare parsers in the class, first
self
.
_assign_parser_names
()
self
.
_assign_parser_names
()
# then deep-copy the parser tree from class to instance;
# then deep-copy the parser tree from class to instance;
# parsers not connected to the root object will be copied later
# parsers not connected to the root object will be copied later
# on demand (see Grammar.__getitem__()). Usually, the need to
# on demand (see Grammar.__getitem__()). Usually, the need to
# do so only arises during testing.
# do so only arises during testing.
self
.
root__
=
root
if
root
else
copy
.
deepcopy
(
self
.
__class__
.
root__
)
self
.
root__
=
root
if
root
else
copy
.
deepcopy
(
self
.
__class__
.
root__
)
if
self
.
wspL__
:
if
self
.
wspL__
:
self
.
wsp_left_parser__
=
Whitespace
(
self
.
wspL__
)
# type: ParserBase
self
.
wsp_left_parser__
=
Whitespace
(
self
.
wspL__
)
# type: ParserBase
self
.
wsp_left_parser__
.
grammar
=
self
self
.
wsp_left_parser__
.
grammar
=
self
...
@@ -393,6 +404,7 @@ class Grammar:
...
@@ -393,6 +404,7 @@ class Grammar:
self
.
wsp_right_parser__
=
ZOMBIE_PARSER
self
.
wsp_right_parser__
=
ZOMBIE_PARSER
self
.
root__
.
apply
(
self
.
_add_parser__
)
self
.
root__
.
apply
(
self
.
_add_parser__
)
def
__getitem__
(
self
,
key
):
def
__getitem__
(
self
,
key
):
try
:
try
:
return
self
.
__dict__
[
key
]
return
self
.
__dict__
[
key
]
...
@@ -406,6 +418,7 @@ class Grammar:
...
@@ -406,6 +418,7 @@ class Grammar:
return
self
[
key
]
return
self
[
key
]
raise
KeyError
(
'Unknown parser "%s" !'
%
key
)
raise
KeyError
(
'Unknown parser "%s" !'
%
key
)
def
_reset__
(
self
):
def
_reset__
(
self
):
self
.
document__
=
""
# type: str
self
.
document__
=
""
# type: str
# variables stored and recalled by Capture and Retrieve parsers
# variables stored and recalled by Capture and Retrieve parsers
...
@@ -422,8 +435,10 @@ class Grammar:
...
@@ -422,8 +435,10 @@ class Grammar:
self
.
moving_forward__
=
True
# type: bool
self
.
moving_forward__
=
True
# type: bool
self
.
left_recursion_encountered__
=
False
# type: bool
self
.
left_recursion_encountered__
=
False
# type: bool
def
_add_parser__
(
self
,
parser
:
Parser
)
->
None
:
def
_add_parser__
(
self
,
parser
:
Parser
)
->
None
:
"""Adds the particular copy of the parser object to this
"""
Adds the particular copy of the parser object to this
particular instance of Grammar.
particular instance of Grammar.
"""
"""
if
parser
.
name
:
if
parser
.
name
:
...
@@ -436,8 +451,10 @@ class Grammar:
...
@@ -436,8 +451,10 @@ class Grammar:
self
.
all_parsers__
.
add
(
parser
)
self
.
all_parsers__
.
add
(
parser
)
parser
.
grammar
=
self
parser
.
grammar
=
self
def
__call__
(
self
,
document
:
str
,
start_parser
=
"root__"
)
->
Node
:
def
__call__
(
self
,
document
:
str
,
start_parser
=
"root__"
)
->
Node
:
"""Parses a document with with parser-combinators.
"""
Parses a document with with parser-combinators.
Args:
Args:
document (str): The source text to be parsed.
document (str): The source text to be parsed.
...
@@ -504,8 +521,10 @@ class Grammar:
...
@@ -504,8 +521,10 @@ class Grammar:
result
.
pos
=
0
# calculate all positions
result
.
pos
=
0
# calculate all positions
return
result
return
result
def
push_rollback__
(
self
,
location
,
func
):
def
push_rollback__
(
self
,
location
,
func
):
"""Adds a rollback function that either removes or re-adds
"""
Adds a rollback function that either removes or re-adds
values on the variable stack (`self.variables`) that have been
values on the variable stack (`self.variables`) that have been
added (or removed) by Capture or Pop Parsers, the results of
added (or removed) by Capture or Pop Parsers, the results of
which have been dismissed.
which have been dismissed.
...
@@ -513,8 +532,10 @@ class Grammar:
...
@@ -513,8 +532,10 @@ class Grammar:
self
.
rollback__
.
append
((
location
,
func
))
self
.
rollback__
.
append
((
location
,
func
))
self
.
last_rb__loc__
=
location
self
.
last_rb__loc__
=
location
def
rollback_to__
(
self
,
location
):
def
rollback_to__
(
self
,
location
):
"""Rolls back the variable stacks (`self.variables`) to its
"""
Rolls back the variable stacks (`self.variables`) to its
state at an earlier location in the parsed document.
state at an earlier location in the parsed document.
"""
"""
while
self
.
rollback__
and
self
.
rollback__
[
-
1
][
0
]
<=
location
:
while
self
.
rollback__
and
self
.
rollback__
[
-
1
][
0
]
<=
location
:
...
@@ -524,8 +545,10 @@ class Grammar:
...
@@ -524,8 +545,10 @@ class Grammar:
self
.
last_rb__loc__
==
self
.
rollback__
[
-
1
][
0
]
if
self
.
rollback__
\
self
.
last_rb__loc__
==
self
.
rollback__
[
-
1
][
0
]
if
self
.
rollback__
\
else
(
len
(
self
.
document__
)
+
1
)
else
(
len
(
self
.
document__
)
+
1
)
def
log_parsing_history__
(
self
,
log_file_name
:
str
=
''
)
->
None
:
def
log_parsing_history__
(
self
,
log_file_name
:
str
=
''
)
->
None
:
"""Writes a log of the parsing history of the most recently parsed
"""
Writes a log of the parsing history of the most recently parsed
document.
document.
"""
"""
def
prepare_line
(
record
):
def
prepare_line
(
record
):
...
@@ -558,7 +581,8 @@ class Grammar:
...
@@ -558,7 +581,8 @@ class Grammar:
def
dsl_error_msg
(
parser
:
Parser
,
error_str
:
str
)
->
str
:
def
dsl_error_msg
(
parser
:
Parser
,
error_str
:
str
)
->
str
:
"""Returns an error message for errors in the parser configuration,
"""
Returns an error message for errors in the parser configuration,
e.g. errors that result in infinite loops.
e.g. errors that result in infinite loops.
Args:
Args:
...
@@ -578,6 +602,7 @@ def dsl_error_msg(parser: Parser, error_str: str) -> str:
...
@@ -578,6 +602,7 @@ def dsl_error_msg(parser: Parser, error_str: str) -> str:
return
" "
.
join
(
msg
)
return
" "
.
join
(
msg
)
########################################################################
########################################################################
#
#
# Token and Regular Expression parser classes (i.e. leaf classes)
# Token and Regular Expression parser classes (i.e. leaf classes)
...
@@ -591,7 +616,8 @@ END_SCANNER_TOKEN = '\x1c'
...
@@ -591,7 +616,8 @@ END_SCANNER_TOKEN = '\x1c'
def
make_token
(
token
:
str
,
argument
:
str
=
''
)
->
str
:
def
make_token
(
token
:
str
,
argument
:
str
=
''
)
->
str
:
"""Turns the ``token`` and ``argument`` into a special token that
"""
Turns the ``token`` and ``argument`` into a special token that
will be caught by the `ScannerToken`-parser.
will be caught by the `ScannerToken`-parser.
This function is a support function that should be used by scanners
This function is a support function that should be used by scanners
...
@@ -766,7 +792,8 @@ class RE(Parser):
...
@@ -766,7 +792,8 @@ class RE(Parser):
class
Token
(
RE
):
class
Token
(
RE
):
"""Class Token parses simple strings. Any regular regular
"""
Class Token parses simple strings. Any regular regular
expression commands will be interpreted as simple sequence of
expression commands will be interpreted as simple sequence of
characters.
characters.
...
@@ -827,7 +854,8 @@ class NaryOperator(Parser):
...
@@ -827,7 +854,8 @@ class NaryOperator(Parser):
class
Synonym
(
UnaryOperator
):
class
Synonym
(
UnaryOperator
):
"""Simply calls another parser and encapsulates the result in
"""
Simply calls another parser and encapsulates the result in
another node if that parser matches.
another node if that parser matches.
This parser is needed to support synonyms in EBNF, e.g.
This parser is needed to support synonyms in EBNF, e.g.
...
@@ -954,7 +982,8 @@ class Series(NaryOperator):
...
@@ -954,7 +982,8 @@ class Series(NaryOperator):
class
Alternative
(
NaryOperator
):
class
Alternative
(
NaryOperator
):
"""Matches if at least one of several alternatives matches. Returns
"""
Matches if at least one of several alternatives matches. Returns
the first match.
the first match.
This parser represents the EBNF-operator "|" with the qualification
This parser represents the EBNF-operator "|" with the qualification
...
@@ -1010,6 +1039,7 @@ class Alternative(NaryOperator):
...
@@ -1010,6 +1039,7 @@ class Alternative(NaryOperator):
return
self
return
self
########################################################################
########################################################################
#
#
# Flow control operators
# Flow control operators
...
@@ -1259,6 +1289,7 @@ class Forward(Parser):
...
@@ -1259,6 +1289,7 @@ class Forward(Parser):
class
Compiler
:
class
Compiler
:
def
__init__
(
self
,
grammar_name
=
""
,
grammar_source
=
""
):
def
__init__
(
self
,
grammar_name
=
""
,
grammar_source
=
""
):
self
.
dirty_flag
=
False
self
.
dirty_flag
=
False
self
.
set_grammar_name
(
grammar_name
,
grammar_source
)
self
.
set_grammar_name
(
grammar_name
,
grammar_source
)
...
...
DHParser/testing.py
View file @
f277041a
...
@@ -34,7 +34,8 @@ from DHParser.dsl import compile_on_disk
...
@@ -34,7 +34,8 @@ from DHParser.dsl import compile_on_disk
def
mock_syntax_tree
(
sexpr
):
def
mock_syntax_tree
(
sexpr
):
"""Generates a tree of nodes from an S-expression.
"""
Generates a tree of nodes from an S-expression.
Example:
Example:
>>> mock_syntax_tree("(a (b c))").as_sxpr()
>>> mock_syntax_tree("(a (b c))").as_sxpr()
...
@@ -84,7 +85,8 @@ def mock_syntax_tree(sexpr):
...
@@ -84,7 +85,8 @@ def mock_syntax_tree(sexpr):
def
recompile_grammar
(
ebnf_filename
,
force
=
False
)
->
bool
:
def
recompile_grammar
(
ebnf_filename
,
force
=
False
)
->
bool
:
"""Recompiles an ebnf-grammar if necessary, that is if either no
"""
Recompiles an ebnf-grammar if necessary, that is if either no
corresponding 'XXXXCompiler.py'-file exists or if that file is
corresponding 'XXXXCompiler.py'-file exists or if that file is
outdated.
outdated.
...
@@ -128,7 +130,8 @@ UNIT_STAGES = {'match', 'fail', 'ast', 'cst', '__ast__', '__cst__'}
...
@@ -128,7 +130,8 @@ UNIT_STAGES = {'match', 'fail', 'ast', 'cst', '__ast__', '__cst__'}
def
unit_from_configfile
(
config_filename
):
def
unit_from_configfile
(
config_filename
):
"""Reads a grammar unit test from a config file.
"""
Reads a grammar unit test from a config file.
"""
"""
cfg
=
configparser
.
ConfigParser
(
interpolation
=
None
)
cfg
=
configparser
.
ConfigParser
(
interpolation
=
None
)
cfg
.
read
(
config_filename
)
cfg
.
read
(
config_filename
)
...
@@ -152,7 +155,8 @@ def unit_from_configfile(config_filename):
...
@@ -152,7 +155,8 @@ def unit_from_configfile(config_filename):
def
unit_from_json
(
json_filename
):
def
unit_from_json
(
json_filename
):
"""Reads a grammar unit test from a json file.
"""
Reads a grammar unit test from a json file.
"""
"""
with
open
(
json_filename
,
'r'
)
as
f
:
with
open
(
json_filename
,
'r'
)
as
f
:
unit
=
json
.
load
(
f
)
unit
=
json
.
load
(
f
)
...
@@ -166,7 +170,8 @@ def unit_from_json(json_filename):
...
@@ -166,7 +170,8 @@ def unit_from_json(json_filename):
def
unit_from_file
(
filename
):
def
unit_from_file
(
filename
):
"""Reads a grammar unit test from a file. The format of the file is
"""
Reads a grammar unit test from a file. The format of the file is
determined by the ending of its name.
determined by the ending of its name.
"""
"""
if
filename
.
endswith
(
".json"
):
if
filename
.
endswith
(
".json"
):
...
@@ -178,7 +183,8 @@ def unit_from_file(filename):
...
@@ -178,7 +183,8 @@ def unit_from_file(filename):
def
get_report
(
test_unit
):
def
get_report
(
test_unit
):
"""Returns a text-report of the results of a grammar unit test.
"""
Returns a text-report of the results of a grammar unit test.
"""
"""
report
=
[]
report
=
[]
for
parser_name
,
tests
in
test_unit
.
items
():
for
parser_name
,
tests
in
test_unit
.
items
():
...
@@ -205,7 +211,8 @@ def get_report(test_unit):
...
@@ -205,7 +211,8 @@ def get_report(test_unit):
def
grammar_unit
(
test_unit
,
parser_factory
,
transformer_factory
,
report
=
True
,
verbose
=
False
):
def
grammar_unit
(
test_unit
,
parser_factory
,
transformer_factory
,
report
=
True
,
verbose
=
False
):
"""Unit tests for a grammar-parser and ast transformations.
"""
Unit tests for a grammar-parser and ast transformations.
"""
"""
if
isinstance
(
test_unit
,
str
):
if
isinstance
(
test_unit
,
str
):
unit_dir
,
unit_name
=
os
.
path
.
split
(
os
.
path
.
splitext
(
test_unit
)[
0
])
unit_dir
,
unit_name
=
os
.
path
.
split
(
os
.
path
.
splitext
(
test_unit
)[
0
])
...
@@ -288,7 +295,8 @@ def grammar_unit(test_unit, parser_factory, transformer_factory, report=True, ve
...
@@ -288,7 +295,8 @@ def grammar_unit(test_unit, parser_factory, transformer_factory, report=True, ve
def
grammar_suite
(
directory
,
parser_factory
,
transformer_factory
,
ignore_unknown_filetypes
=
False
,
def
grammar_suite
(
directory
,
parser_factory
,
transformer_factory
,
ignore_unknown_filetypes
=
False
,
report
=
True
,
verbose
=
False
):
report
=
True
,
verbose
=
False
):
"""Runs all grammar unit tests in a directory. A file is considered a test
"""
Runs all grammar unit tests in a directory. A file is considered a test
unit, if it has the word "test" in its name.
unit, if it has the word "test" in its name.
"""
"""
all_errors
=
collections
.
OrderedDict
()
all_errors
=
collections
.
OrderedDict
()
...
@@ -318,7 +326,8 @@ def grammar_suite(directory, parser_factory, transformer_factory, ignore_unknown
...
@@ -318,7 +326,8 @@ def grammar_suite(directory, parser_factory, transformer_factory, ignore_unknown
def
runner
(
tests
,
namespace
):
def
runner
(
tests
,
namespace
):
""" Runs all or some selected Python unit tests found in the
"""
Runs all or some selected Python unit tests found in the
namespace. To run all tests in a module, call
namespace. To run all tests in a module, call
``runner("", globals())`` from within that module.
``runner("", globals())`` from within that module.
...
...
examples/LaTeX/LaTeX.ebnf
View file @
f277041a
...
@@ -113,7 +113,7 @@ text = { cfgtext | (BRACKETS //~) }+
...
@@ -113,7 +113,7 @@ text = { cfgtext | (BRACKETS //~) }+
cfgtext = { word_sequence | (ESCAPED //~) }+
cfgtext = { word_sequence | (ESCAPED //~) }+
word_sequence = { TEXTCHUNK //~ }+
word_sequence = { TEXTCHUNK //~ }+
blockcmd =
"\"
("begin{" ("enumerate" | "itemize" | "figure" | "quote"
blockcmd =
/\/
("begin{" ("enumerate" | "itemize" | "figure" | "quote"
| "quotation" | "tabular") "}"
| "quotation" | "tabular") "}"
| "subsection" | "section" | "chapter" | "subsubsection"
| "subsection" | "section" | "chapter" | "subsubsection"
| "paragraph" | "subparagraph" | "item")
| "paragraph" | "subparagraph" | "item")
...
...
examples/LaTeX/LaTeXCompiler.py
View file @
f277041a
...
@@ -163,7 +163,7 @@ class LaTeXGrammar(Grammar):
...
@@ -163,7 +163,7 @@ class LaTeXGrammar(Grammar):
cfgtext = { word_sequence | (ESCAPED //~) }+
cfgtext = { word_sequence | (ESCAPED //~) }+
word_sequence = { TEXTCHUNK //~ }+
word_sequence = { TEXTCHUNK //~ }+