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
5b6deeea
Commit
5b6deeea
authored
Jan 19, 2019
by
eckhart
Browse files
- ebnf.py: Ambigous error messages now cause a compiler error
parent
220512ba
Changes
3
Hide whitespace changes
Inline
Side-by-side
DHParser/ebnf.py
View file @
5b6deeea
...
...
@@ -432,8 +432,19 @@ class EBNFCompiler(Compiler):
root_symbol: The name of the root symbol.
directives: A dictionary of all directives and their default
values.
directives: A record of all directives and their default values.
defined_directives: A set of all directives that have already been
defined. With the exception of those directives contained
in EBNFCompiler.REPEATABLE_DIRECTIVES, directives must only
be defined once.
consumed_custom_errors: A set of symbols for which a custom error
has been defined and(!) consumed during compilation. This
allows to add a compiler error in those cases where (i) an
error message has been defined but will never used or (ii)
an error message is accidently used twice. For examples, see
`test_ebnf.TestErrorCustomization`
re_flags: A set of regular expression flags to be added to all
regular expressions found in the current parsing process
...
...
@@ -481,8 +492,9 @@ class EBNFCompiler(Compiler):
self
.
definitions
=
{}
# type: Dict[str, str]
self
.
deferred_tasks
=
[]
# type: List[Callable]
self
.
root_symbol
=
""
# type: str
self
.
directives
=
EBNFDirectives
()
# type: EBNFDirectives
self
.
defined_directives
=
set
()
# type: Set[str]
self
.
directives
=
EBNFDirectives
()
# type: EBNFDirectives
self
.
defined_directives
=
set
()
# type: Set[str]
self
.
consumed_custom_errors
=
set
()
# type: Set[str]
self
.
grammar_id
+=
1
...
...
@@ -989,8 +1001,15 @@ class EBNFCompiler(Compiler):
if
custom_args
:
current_symbol
=
next
(
reversed
(
self
.
rules
.
keys
()))
if
current_symbol
in
self
.
directives
.
error
:
# use class field instead or direct representation of error messages!
custom_args
.
append
(
'err_msgs='
+
current_symbol
+
self
.
ERR_MSG_SUFFIX
)
if
current_symbol
in
self
.
consumed_custom_errors
:
self
.
tree
.
new_error
(
node
,
"Cannot apply customized error messages unambigiously, because "
"symbol {} contains more than one series with a mandatory marker '§' "
"in its definiens."
.
format
(
current_symbol
),
Error
.
AMBIGUOUS_ERROR_MSG
)
else
:
# use class field instead or direct representation of error messages!
custom_args
.
append
(
'err_msgs='
+
current_symbol
+
self
.
ERR_MSG_SUFFIX
)
self
.
consumed_custom_errors
.
add
(
current_symbol
)
compiled
=
self
.
non_terminal
(
node
,
'Series'
,
custom_args
)
# TODO: Maybe add a warning about ambiguous error messages in case there are several
# Series with mandatory items within the definiens of the same symbol?
...
...
DHParser/error.py
View file @
5b6deeea
...
...
@@ -85,6 +85,8 @@ class Error:
PARSER_STOPPED_BEFORE_END
=
ErrorCode
(
1040
)
CAPTURE_STACK_NOT_EMPTY
=
ErrorCode
(
1050
)
MALFORMED_ERROR_STRING
=
ErrorCode
(
1060
)
AMBIGUOUS_ERROR_MSG
=
ErrorCode
(
1070
)
UNUSED_ERROR_MSG
=
ErrorCode
(
1080
)
def
__init__
(
self
,
message
:
str
,
pos
,
code
:
ErrorCode
=
ERROR
,
orig_pos
:
int
=
-
1
,
line
:
int
=
-
1
,
column
:
int
=
-
1
)
->
None
:
...
...
test/test_ebnf.py
View file @
5b6deeea
...
...
@@ -448,12 +448,12 @@ class TestAllSome:
assert
grammar
(
'B'
).
content
==
'B'
class
Test
CuratedErrors
:
class
Test
ErrorCustomization
:
"""
Cu
ret
ed Errors replace existing errors with alternative
Cu
stomiz
ed Errors replace existing errors with alternative
error codes and messages that are more helptful to the user.
"""
def
test_cu
rat
ed_mandatory_continuation
(
self
):
def
test_cu
stomiz
ed_mandatory_continuation
(
self
):
lang
=
"""
document = series | /.*/
@series_error = "a user defined error message"
...
...
@@ -472,7 +472,7 @@ class TestCuratedErrors:
assert
st
.
collect_errors
()[
0
].
code
==
Error
.
MANDATORY_CONTINUATION
assert
st
.
collect_errors
()[
0
].
message
==
"a user defined error message"
def
test_cu
rat
ed_error_case_sensitive
(
self
):
def
test_cu
stomiz
ed_error_case_sensitive
(
self
):
lang
=
"""
document = Series | /.*/
@Series_error = "a user defined error message"
...
...
@@ -484,14 +484,27 @@ class TestCuratedErrors:
assert
st
.
collect_errors
()[
0
].
code
==
Error
.
MANDATORY_CONTINUATION
assert
st
.
collect_errors
()[
0
].
message
==
"a user defined error message"
def
test_error_cusomization_mistakes
(
self
):
def
test_ambiguous_error_customization
(
self
):
lang
=
"""
document = series
@series_error = "ambiguous error message: does it apply to 'one' or 'two'?"
series = "A" § "B" "C" | "X" § "Y" "Z"
"""
try
:
parser
=
grammar_provider
(
lang
)()
assert
False
,
"CompilationError because of ambiguous error message exptected!"
except
CompilationError
as
compilation_error
:
err
=
next
(
compilation_error
.
errors
)
assert
err
.
code
==
Error
.
AMBIGUOUS_ERROR_MSG
,
str
(
compilation_error
)
def
test_unsed_error_customization
(
self
):
lang
=
"""
document = series | other
@other_error = "a user defined error message"
series = "A" § "B" "C"
other = "X" | "Y" | "Z"
"""
parser
=
grammar_provider
(
lang
)()
parser
=
grammar_provider
(
lang
)()
# TODO: Here an error should occur!
st
=
parser
(
"ABC"
)
assert
not
st
.
error_flag
st
=
parser
(
"Y"
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment