Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
9.2.2023: Due to updates GitLab will be unavailable for some minutes between 9:00 and 11:00.
Open sidebar
badw-it
DHParser
Commits
f414983c
Commit
f414983c
authored
Jan 23, 2019
by
di68kap
Browse files
- work in progress!
parent
ce75dc7b
Changes
8
Hide whitespace changes
Inline
Side-by-side
DHParser/log.py
View file @
f414983c
...
...
@@ -56,7 +56,8 @@ import threading
from
DHParser.error
import
line_col
from
DHParser.stringview
import
StringView
from
DHParser.syntaxtree
import
Node
,
ParserBase
from
DHParser.syntaxtree
import
Node
from
DHParser.parse
import
ParserBase
from
DHParser.toolkit
import
is_filename
,
escape_control_characters
,
GLOBALS
,
typing
from
typing
import
List
,
Tuple
,
Union
...
...
DHParser/parse.py
View file @
f414983c
...
...
@@ -37,8 +37,8 @@ from DHParser.error import Error, linebreaks
from
DHParser.log
import
is_logging
,
HistoryRecord
from
DHParser.preprocess
import
BEGIN_TOKEN
,
END_TOKEN
,
RX_TOKEN_NAME
from
DHParser.stringview
import
StringView
,
EMPTY_STRING_VIEW
from
DHParser.syntaxtree
import
Node
,
RootNode
,
ParserBase
,
WHITESPACE_PTYPE
,
\
TOKEN_PTYPE
,
ZOMBIE_PARSER
,
ZOMBIE
,
ResultType
from
DHParser.syntaxtree
import
Node
,
RootNode
,
WHITESPACE_PTYPE
,
\
TOKEN_PTYPE
,
ZOMBIE
,
ResultType
from
DHParser.toolkit
import
sane_parser_name
,
escape_control_characters
,
re
,
typing
from
typing
import
Callable
,
cast
,
List
,
Tuple
,
Set
,
Dict
,
DefaultDict
,
Union
,
Optional
,
Any
...
...
@@ -147,6 +147,50 @@ ApplyFunc = Callable[['Parser'], None]
FlagFunc
=
Callable
[[
ApplyFunc
,
Set
[
ApplyFunc
]],
bool
]
class
ParserBase
:
"""
ParserBase is the base class for all real and mock parser classes.
It is defined here, because Node objects require a parser object
for instantiation.
"""
__slots__
=
'name'
,
'ptype'
,
'tag_name'
def
__init__
(
self
,):
# , pbases=frozenset()):
self
.
name
=
''
# type: str
self
.
ptype
=
':'
+
self
.
__class__
.
__name__
# type: str
self
.
tag_name
=
self
.
ptype
# type: str
def
__repr__
(
self
):
return
self
.
name
+
self
.
ptype
def
__str__
(
self
):
return
self
.
name
+
(
' = '
if
self
.
name
else
''
)
+
repr
(
self
)
def
__call__
(
self
,
text
:
StringView
)
->
Tuple
[
Optional
[
'Node'
],
StringView
]:
return
None
,
text
@
property
def
repr
(
self
)
->
str
:
"""Returns the parser's name if it has a name and repr()"""
return
self
.
name
if
self
.
name
else
self
.
__repr__
()
def
reset
(
self
):
"""Resets any parser variables. (Should be overridden.)"""
pass
@
property
def
grammar
(
self
)
->
'Grammar'
:
"""Returns the Grammar object to which the parser belongs. If not
yet connected to any Grammar object, None is returned."""
raise
NotImplementedError
def
apply
(
self
,
func
:
Callable
):
"""Applies the function `func` recursively to the parser and all
descendant parsers, if any exist."""
pass
class
Parser
(
ParserBase
):
"""
(Abstract) Base class for Parser combinator parsers. Any parser
...
...
@@ -2103,3 +2147,59 @@ class Forward(Parser):
self
.
parser
.
_apply
(
func
,
flip
)
return
True
return
False
class
MockParser
(
ParserBase
):
"""
MockParser objects can be used to reconstruct syntax trees from a
serialized form like S-expressions or XML. Mock objects can mimic
different parser types by assigning them a `ptype` on initialization.
Mock objects should not be used for anything other than
syntax tree (re-)construction. In all other cases where a parser
object substitute is needed, chose the singleton ZOMBIE_PARSER.
"""
__slots__
=
()
def
__init__
(
self
,
name
=
''
,
ptype
=
''
):
# , pbases=frozenset()):
assert
not
ptype
or
ptype
[
0
]
==
':'
super
().
__init__
()
self
.
name
=
name
if
ptype
:
self
.
ptype
=
ptype
# or ':' + self.__class__.__name__
class
ZombieParser
(
MockParser
):
"""
Serves as a substitute for a Parser instance.
``ZombieParser`` is the class of the singelton object
``ZOMBIE_PARSER``. The ``ZOMBIE_PARSER`` has a name and can be
called, but it never matches. It serves as a substitute where only
these (or one of these properties) is needed, but no real Parser-
object is instantiated.
"""
alive
=
False
__slots__
=
()
def
__init__
(
self
):
super
(
ZombieParser
,
self
).
__init__
()
assert
not
self
.
__class__
.
alive
,
"There can be only one!"
assert
self
.
__class__
==
ZombieParser
,
"No derivatives, please!"
self
.
name
=
ZOMBIE
self
.
__class__
.
alive
=
True
def
__copy__
(
self
):
return
self
def
__deepcopy__
(
self
,
memo
):
return
self
def
__call__
(
self
,
text
):
"""Better call Saul ;-)"""
return
None
,
text
ZOMBIE_PARSER
=
ZombieParser
()
\ No newline at end of file
DHParser/syntaxtree.py
View file @
f414983c
...
...
@@ -23,24 +23,18 @@ here, because node-objects refer to parser-objects. All concrete
parser classes are defined in the ``parse`` module.
"""
import
collections.abc
from
collections
import
OrderedDict
import
copy
from
DHParser.error
import
Error
,
ErrorCode
,
linebreaks
,
line_col
from
DHParser.stringview
import
StringView
from
DHParser.toolkit
import
re
,
typing
from
typing
import
Callable
,
cast
,
Iterator
,
List
,
AbstractSet
,
Set
,
Dict
,
Union
,
Tuple
,
Optional
from
DHParser.toolkit
import
re
from
typing
import
Callable
,
cast
,
Iterator
,
List
,
AbstractSet
,
Set
,
Union
,
Tuple
,
Optional
__all__
=
(
'ParserBase'
,
'WHITESPACE_PTYPE'
,
__all__
=
(
'WHITESPACE_PTYPE'
,
'TOKEN_PTYPE'
,
'MockParser'
,
'ZombieParser'
,
'ZOMBIE'
,
'ZOMBIE_PARSER'
,
'ZOMBIE_NODE'
,
'ResultType'
,
'StrictResultType'
,
...
...
@@ -61,113 +55,11 @@ __all__ = ('ParserBase',
#######################################################################
class
ParserBase
:
"""
ParserBase is the base class for all real and mock parser classes.
It is defined here, because Node objects require a parser object
for instantiation.
"""
__slots__
=
'name'
,
'ptype'
,
'tag_name'
def
__init__
(
self
,):
# , pbases=frozenset()):
self
.
name
=
''
# type: str
self
.
ptype
=
':'
+
self
.
__class__
.
__name__
# type: str
self
.
tag_name
=
self
.
ptype
# type: str
def
__repr__
(
self
):
return
self
.
name
+
self
.
ptype
def
__str__
(
self
):
return
self
.
name
+
(
' = '
if
self
.
name
else
''
)
+
repr
(
self
)
def
__call__
(
self
,
text
:
StringView
)
->
Tuple
[
Optional
[
'Node'
],
StringView
]:
return
None
,
text
@
property
def
repr
(
self
)
->
str
:
"""Returns the parser's name if it has a name and repr()"""
return
self
.
name
if
self
.
name
else
self
.
__repr__
()
def
reset
(
self
):
"""Resets any parser variables. (Should be overridden.)"""
pass
@
property
def
grammar
(
self
)
->
'Grammar'
:
"""Returns the Grammar object to which the parser belongs. If not
yet connected to any Grammar object, None is returned."""
raise
NotImplementedError
def
apply
(
self
,
func
:
Callable
):
"""Applies the function `func` recursively to the parser and all
descendant parsers, if any exist."""
pass
WHITESPACE_PTYPE
=
':Whitespace'
TOKEN_PTYPE
=
':Token'
class
MockParser
(
ParserBase
):
"""
MockParser objects can be used to reconstruct syntax trees from a
serialized form like S-expressions or XML. Mock objects can mimic
different parser types by assigning them a `ptype` on initialization.
Mock objects should not be used for anything other than
syntax tree (re-)construction. In all other cases where a parser
object substitute is needed, chose the singleton ZOMBIE_PARSER.
"""
__slots__
=
()
def
__init__
(
self
,
name
=
''
,
ptype
=
''
):
# , pbases=frozenset()):
assert
not
ptype
or
ptype
[
0
]
==
':'
super
().
__init__
()
self
.
name
=
name
if
ptype
:
self
.
ptype
=
ptype
# or ':' + self.__class__.__name__
ZOMBIE
=
"__ZOMBIE__"
class
ZombieParser
(
MockParser
):
"""
Serves as a substitute for a Parser instance.
``ZombieParser`` is the class of the singelton object
``ZOMBIE_PARSER``. The ``ZOMBIE_PARSER`` has a name and can be
called, but it never matches. It serves as a substitute where only
these (or one of these properties) is needed, but no real Parser-
object is instantiated.
"""
alive
=
False
__slots__
=
()
def
__init__
(
self
):
super
(
ZombieParser
,
self
).
__init__
()
assert
not
self
.
__class__
.
alive
,
"There can be only one!"
assert
self
.
__class__
==
ZombieParser
,
"No derivatives, please!"
self
.
name
=
ZOMBIE
self
.
__class__
.
alive
=
True
def
__copy__
(
self
):
return
self
def
__deepcopy__
(
self
,
memo
):
return
self
def
__call__
(
self
,
text
):
"""Better call Saul ;-)"""
return
None
,
text
ZOMBIE_PARSER
=
ZombieParser
()
#######################################################################
#
# syntaxtree nodes
...
...
DHParser/transform.py
View file @
f414983c
...
...
@@ -32,8 +32,8 @@ import inspect
from
functools
import
partial
,
singledispatch
from
DHParser.error
import
Error
,
ErrorCode
from
DHParser.syntaxtree
import
Node
,
WHITESPACE_PTYPE
,
TOKEN_PTYPE
,
ParserBase
,
MockParser
,
\
ZOMBIE_NODE
,
RootNode
,
parse_sxpr
,
flatten_sxp
r
from
DHParser.syntaxtree
import
Node
,
WHITESPACE_PTYPE
,
TOKEN_PTYPE
,
ZOMBIE_NODE
,
RootNode
,
parse_sxpr
,
flatten_sxpr
from
DHParser.parse
import
ParserBase
,
MockParse
r
from
DHParser.toolkit
import
issubtype
,
isgenerictype
,
expand_table
,
smart_list
,
re
,
typing
from
typing
import
AbstractSet
,
Any
,
ByteString
,
Callable
,
cast
,
Container
,
Dict
,
\
Tuple
,
List
,
Sequence
,
Union
,
Text
,
Generic
...
...
examples/XML/XMLCompiler.py
View file @
f414983c
...
...
@@ -32,8 +32,8 @@ from DHParser import logging, is_filename, load_if_file, \
is_empty
,
is_expendable
,
collapse
,
replace_content
,
WHITESPACE_PTYPE
,
TOKEN_PTYPE
,
\
remove_nodes
,
remove_content
,
remove_brackets
,
replace_parser
,
remove_anonymous_tokens
,
\
keep_children
,
is_one_of
,
has_content
,
apply_if
,
remove_first
,
remove_last
,
\
remove_anonymous_empty
,
keep_nodes
,
traverse_locally
,
strip
,
lstrip
,
rstrip
,
MockParser
,
\
ZOMBIE_NODE
remove_anonymous_empty
,
keep_nodes
,
traverse_locally
,
strip
,
lstrip
,
rstrip
,
ZOMBIE_NODE
from
DHParser.parse
import
MockParser
#######################################################################
...
...
@@ -574,7 +574,7 @@ class XMLCompiler(Compiler):
if
attributes
:
node
.
attr
.
update
(
attributes
)
preserve_whitespace
|=
attributes
.
get
(
'xml:space'
,
''
)
==
'preserve'
node
.
parser
=
self
.
get_parser
(
tag_name
)
node
.
tag_name
=
tag_name
content
=
self
.
compile_children
(
node
.
get
(
'content'
,
ZOMBIE_NODE
))
if
len
(
content
)
==
1
:
if
content
[
0
].
tag_name
==
"CharData"
:
...
...
examples/XMLSnippet/XMLSnippetCompiler.py
View file @
f414983c
...
...
@@ -18,8 +18,7 @@ try:
import
regex
as
re
except
ImportError
:
import
re
from
DHParser
import
logging
,
is_filename
,
load_if_file
,
MockParser
,
\
Grammar
,
Compiler
,
nil_preprocessor
,
PreprocessorToken
,
Whitespace
,
\
from
DHParser
import
logging
,
is_filename
,
load_if_file
,
Grammar
,
Compiler
,
nil_preprocessor
,
PreprocessorToken
,
Whitespace
,
\
Lookbehind
,
Lookahead
,
Alternative
,
Pop
,
Token
,
Synonym
,
AllOf
,
SomeOf
,
Unordered
,
\
Option
,
NegativeLookbehind
,
OneOrMore
,
RegExp
,
Retrieve
,
Series
,
Capture
,
\
ZeroOrMore
,
Forward
,
NegativeLookahead
,
Required
,
mixin_comment
,
compile_source
,
\
...
...
@@ -34,6 +33,7 @@ from DHParser import logging, is_filename, load_if_file, MockParser, \
remove_anonymous_empty
,
keep_nodes
,
traverse_locally
,
strip
,
lstrip
,
rstrip
,
\
replace_content
,
replace_content_by
,
forbid
,
assert_content
,
remove_infix_operator
,
\
error_on
,
recompile_grammar
,
GLOBALS
from
DHParser.parse
import
MockParser
#######################################################################
...
...
test/test_syntaxtree.py
View file @
f414983c
...
...
@@ -23,8 +23,8 @@ import copy
import
sys
sys
.
path
.
extend
([
'../'
,
'./'
])
from
DHParser.syntaxtree
import
Node
,
RootNode
,
parse_sxpr
,
parse_xml
,
flatten_sxpr
,
flatten_xml
,
\
MockParser
from
DHParser.syntaxtree
import
Node
,
RootNode
,
parse_sxpr
,
parse_xml
,
flatten_sxpr
,
flatten_xml
from
DHParser.parse
import
MockParser
from
DHParser.transform
import
traverse
,
reduce_single_child
,
\
replace_by_single_child
,
flatten
,
remove_expendables
from
DHParser.ebnf
import
get_ebnf_grammar
,
get_ebnf_transformer
,
get_ebnf_compiler
...
...
test/test_transform.py
View file @
f414983c
...
...
@@ -25,7 +25,8 @@ import sys
sys
.
path
.
extend
([
'../'
,
'./'
])
from
DHParser.syntaxtree
import
Node
,
parse_sxpr
,
flatten_sxpr
,
parse_xml
,
ZOMBIE_NODE
,
\
MockParser
,
TOKEN_PTYPE
TOKEN_PTYPE
from
DHParser.parse
import
MockParser
from
DHParser.transform
import
traverse
,
reduce_single_child
,
remove_whitespace
,
\
traverse_locally
,
collapse
,
collapse_if
,
lstrip
,
rstrip
,
remove_content
,
remove_tokens
,
\
transformation_factory
,
has_parent
...
...
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