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
2f87d91a
Commit
2f87d91a
authored
Apr 17, 2018
by
di68kap
Browse files
- syntaxtree.py: error propagation added
parent
90bb9074
Changes
2
Hide whitespace changes
Inline
Side-by-side
DHParser/parse.py
View file @
2f87d91a
...
...
@@ -782,10 +782,16 @@ class Grammar:
self
.
tree__
.
swallow
(
result
)
return
self
.
tree__
def
add_error
(
self
,
text
,
error_msg
,
code
=
Error
.
ERROR
):
"""Adds an error at the location of `text` whithin the whole document that is
def
location
(
self
,
remaining
:
str
)
->
int
:
"""Returns the location of the `remaining` text within the currently
parsed document.
"""
self
.
document_length__
-
len
(
remaining
)
def
add_error
(
self
,
location
,
error_msg
,
code
=
Error
.
ERROR
):
"""Adds an error at the location of `text` within the whole document that is
currently being parsed."""
self
.
tree__
.
add_errr
(
self
.
document_length__
-
len
(
text
)
,
error_msg
,
code
)
self
.
tree__
.
add_err
o
r
(
location
,
error_msg
,
code
)
def
push_rollback__
(
self
,
location
,
func
):
"""
...
...
@@ -863,18 +869,18 @@ class PreprocessorToken(Parser):
if
text
[
0
:
1
]
==
BEGIN_TOKEN
:
end
=
text
.
find
(
END_TOKEN
,
1
)
if
end
<
0
:
self
.
grammar
.
add_error
(
text
,
self
.
grammar
.
add_error
(
self
.
grammar
.
location
(
text
)
,
'END_TOKEN delimiter missing from preprocessor token. '
'(Most likely due to a preprocessor bug!)'
)
# type: Node
return
Node
(
self
,
''
),
text
[
1
:]
elif
end
==
0
:
self
.
grammar
.
add_error
(
text
,
self
.
grammar
.
add_error
(
self
.
grammar
.
location
(
text
)
,
'Preprocessor-token cannot have zero length. '
'(Most likely due to a preprocessor bug!)'
)
return
Node
(
self
,
''
),
text
[
2
:]
elif
text
.
find
(
BEGIN_TOKEN
,
1
,
end
)
>=
0
:
node
=
Node
(
self
,
text
[
len
(
self
.
name
)
+
1
:
end
])
self
.
grammar
.
add_error
(
text
,
self
.
grammar
.
add_error
(
self
.
grammar
.
location
(
text
)
,
'Preprocessor-tokens must not be nested or contain '
'BEGIN_TOKEN delimiter as part of their argument. '
'(Most likely due to a preprocessor bug!)'
)
...
...
@@ -1256,7 +1262,8 @@ class ZeroOrMore(Option):
if
not
node
:
break
if
len
(
text
)
==
n
:
self
.
grammar
.
add_error
(
text
,
dsl_error_msg
(
self
,
'Infinite Loop detected.'
))
self
.
grammar
.
add_error
(
self
.
grammar
.
location
(
text
),
dsl_error_msg
(
self
,
'Infinite Loop detected.'
))
results
+=
(
node
,)
return
Node
(
self
,
results
),
text
...
...
@@ -1300,7 +1307,8 @@ class OneOrMore(UnaryOperator):
if
not
node
:
break
if
len
(
text_
)
==
n
:
self
.
grammar
.
add_error
(
text
,
dsl_error_msg
(
self
,
'Infinite Loop detected.'
))
self
.
grammar
.
add_error
(
self
.
grammar
.
location
(
text
),
dsl_error_msg
(
self
,
'Infinite Loop detected.'
))
results
+=
(
node
,)
if
results
==
():
return
None
,
text
...
...
@@ -1360,7 +1368,7 @@ class Series(NaryOperator):
i
=
max
(
1
,
text
.
index
(
match
.
regs
[
1
][
0
]))
if
match
else
1
node
=
Node
(
self
,
text_
[:
i
]).
init_pos
(
self
.
grammar
.
document_length__
-
len
(
text_
))
self
.
grammar
.
add_error
(
text
,
'%s expected; "%s" found!'
self
.
grammar
.
add_error
(
self
.
grammar
.
location
(
text
)
,
'%s expected; "%s" found!'
%
(
parser
.
repr
,
text_
[:
10
].
replace
(
'
\n
'
,
'
\\
n '
)),
code
=
Error
.
MANDATORY_CONTINUATION
)
text_
=
text_
[
i
:]
...
...
@@ -1629,7 +1637,8 @@ def Required(parser: Parser) -> Parser:
# i = max(1, text.index(m.regs[1][0])) if m else 1
# node = Node(self, text[:i])
# text_ = text[i:]
# self.grammar.add_error(text, '%s expected; "%s" found!' % (str(self.parser),
# self.grammar.add_error(self.grammar.location(text),
# '%s expected; "%s" found!' % (str(self.parser),
# text[:10]), code=Error.MANDATORY_CONTINUATION)
# return node, text_
#
...
...
@@ -1803,7 +1812,7 @@ class Retrieve(Parser):
stack
=
self
.
grammar
.
variables__
[
self
.
symbol
.
name
]
value
=
self
.
filter
(
stack
)
except
(
KeyError
,
IndexError
):
self
.
grammar
.
add_error
(
text
,
self
.
grammar
.
add_error
(
self
.
grammar
.
location
(
text
)
,
dsl_error_msg
(
self
,
"'%s' undefined or exhausted."
%
self
.
symbol
.
name
))
return
Node
(
self
,
''
),
text
if
text
.
startswith
(
value
):
...
...
DHParser/syntaxtree.py
View file @
2f87d91a
...
...
@@ -228,22 +228,22 @@ class Node(collections.abc.Sized):
At any rate, it should only be reassigned during the parsing
stage and never during or after the AST-transformation.
errors (list): A list of all errors that occured on this node.
attributes (dict): An optional dictionary of XML-attributes. This
dictionary is created lazily upon first usage. The attributes
will only be shown in the XML-Representation, not in the
S-Expression-output.
_parent (Node): SLOT RESERVED FOR FUTURE USE!
"""
__slots__
=
[
'_result'
,
'children'
,
'_len'
,
'_pos'
,
'parser'
,
'_xml_attr'
,
'_content'
]
__slots__
=
[
'_result'
,
'children'
,
'_len'
,
'_pos'
,
'parser'
,
'errors'
'_xml_attr'
,
'_content'
]
def
__init__
(
self
,
parser
,
result
:
ResultType
,
leafhint
:
bool
=
False
)
->
None
:
"""
Initializes the ``Node``-object with the ``Parser``-Instance
that generated the node and the parser's result.
"""
self
.
errors
=
[]
# type: List[Error]
self
.
_pos
=
-
1
# type: int
# Assignment to self.result initializes the attributes _result, children and _len
# The following if-clause is merely an optimization, i.e. a fast-path for leaf-Nodes
...
...
@@ -259,9 +259,9 @@ class Node(collections.abc.Sized):
def
__str__
(
self
):
s
=
""
.
join
(
str
(
child
)
for
child
in
self
.
children
)
if
self
.
children
else
self
.
content
if
self
.
_
errors
:
if
self
.
errors
:
return
' <<< Error on "%s" | %s >>> '
%
\
(
s
,
'; '
.
join
(
e
.
message
for
e
in
self
.
_
errors
))
(
s
,
'; '
.
join
(
e
.
message
for
e
in
self
.
errors
))
return
s
...
...
@@ -391,14 +391,10 @@ class Node(collections.abc.Sized):
if
isinstance
(
result
,
Node
):
self
.
children
=
(
result
,)
self
.
_result
=
self
.
children
self
.
error_flag
=
result
.
error_flag
else
:
if
isinstance
(
result
,
tuple
):
self
.
children
=
result
self
.
_result
=
result
or
''
if
result
:
if
self
.
error_flag
==
0
:
self
.
error_flag
=
max
(
child
.
error_flag
for
child
in
self
.
children
)
else
:
self
.
children
=
NoChildren
self
.
_result
=
result
...
...
@@ -448,7 +444,7 @@ class Node(collections.abc.Sized):
"""
if
overwrite
or
self
.
_pos
<
0
:
self
.
_pos
=
pos
for
err
in
self
.
_
errors
:
for
err
in
self
.
errors
:
err
.
pos
=
pos
else
:
assert
self
.
_pos
==
pos
,
str
(
"%i != %i"
%
(
self
.
_pos
,
pos
))
...
...
@@ -466,7 +462,7 @@ class Node(collections.abc.Sized):
# Returns the errors that occurred at this Node,
# not including any errors from child nodes.
# """
# return self.
_
errors.copy()
# return self.errors.copy()
@
property
def
attributes
(
self
):
...
...
@@ -681,26 +677,50 @@ class Node(collections.abc.Sized):
class
RootNode
(
Node
):
"""
errors (list): A list of parser- or compiler-errors:
tuple(position, string) attached to this node
errors (list): A list of all errors that have occured so far during
processing (i.e. parsing, AST-transformation, compiling)
of this tree.
error_flag (int): 0 if no error occurred in either the node
itself or any of its descendants. Otherwise contains the
highest warning or error level or all errors that occurred.
error_flag (int): the highest warning or error level of all errors
that occurred.
"""
def
__init__
(
self
):
super
().
__init__
(
ZOMBIE_PARSER
,
''
)
self
.
errors
=
[]
self
.
error_flag
=
0
def
_propagate_errors
(
self
):
assert
self
.
children
if
not
self
.
errors
:
return
self
.
errors
.
sort
(
key
=
lambda
e
:
e
.
pos
)
errlist
=
copy
.
copy
(
self
.
errors
)
for
leaf
in
self
.
select
(
lambda
nd
:
not
nd
.
children
,
False
):
leaf
.
errors
=
[]
while
errlist
and
leaf
.
pos
<=
errlist
[
0
].
pos
<
leaf
.
pos
+
leaf
.
len
:
leaf
.
errors
.
append
(
errlist
[
0
])
del
errlist
[
0
]
if
not
errlist
:
break
def
_propagate_new_error
(
self
,
error
):
for
leaf
in
self
.
select
(
lambda
nd
:
not
nd
.
children
,
False
):
if
leaf
.
pos
<=
error
.
pos
<
leaf
.
pos
+
leaf
.
len
:
leaf
.
errord
.
append
(
error
)
break
else
:
assert
False
,
"Error %s at pos %i out of bounds"
%
(
str
(
error
),
error
.
pos
)
def
swallow
(
self
,
node
):
self
.
_result
=
node
.
_result
self
.
children
=
node
.
children
self
.
_len
=
node
.
_len
self
.
_pos
=
node
.
_pos
self
.
parser
=
node
.
parser
self
.
_xml_attr
=
node
.
_xml_attr
if
hasattr
(
node
,
'_xml_attr'
):
self
.
_xml_attr
=
node
.
_xml_attr
self
.
_content
=
node
.
_content
self
.
_propagate_errors
()
def
add_error
(
self
,
pos
:
int
,
...
...
@@ -713,8 +733,11 @@ class RootNode(Node):
message(str): A string with the error message.abs
code(int): An error code to identify the kind of error
"""
self
.
errors
.
append
(
Error
(
message
,
code
,
pos
))
error
=
Error
(
message
,
code
,
pos
)
self
.
errors
.
append
(
error
)
self
.
error_flag
=
max
(
self
.
error_flag
,
code
)
if
self
.
children
:
self
.
_propagate_new_error
(
error
)
return
self
def
collect_errors
(
self
,
clear_errors
=
False
)
->
List
[
Error
]:
...
...
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