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
c1b3846f
Commit
c1b3846f
authored
Jun 09, 2017
by
Eckhart Arnold
Browse files
- parser.py errors now also appear in the history logs
parent
f1605c5c
Changes
3
Hide whitespace changes
Inline
Side-by-side
DHParser/parsers.py
View file @
c1b3846f
...
...
@@ -123,13 +123,17 @@ class HistoryRecord:
self
.
node
=
node
self
.
remaining
=
remaining
def
err_msg
(
self
):
return
self
.
ERROR
+
": "
+
"; "
.
join
(
self
.
node
.
_errors
).
replace
(
'
\n
'
,
'
\\
'
)
@
property
def
stack
(
self
):
return
"->"
.
join
(
str
(
parser
)
for
parser
in
self
.
call_stack
)
@
property
def
status
(
self
):
return
self
.
FAIL
if
self
.
node
is
None
else
self
.
ERROR
if
self
.
node
.
_errors
else
self
.
MATCH
return
self
.
FAIL
if
self
.
node
is
None
else
\
self
.
err_msg
()
if
self
.
node
.
_errors
else
self
.
MATCH
@
property
def
extent
(
self
):
...
...
@@ -160,7 +164,7 @@ def add_parser_guard(parser_func):
node
,
rest
=
parser_func
(
parser
,
text
)
if
grammar
.
history_tracking
:
if
grammar
.
moving_forward
:
# and result[0] == None
if
grammar
.
moving_forward
or
(
node
and
node
.
_errors
)
:
# and result[0] == None
grammar
.
moving_forward
=
False
record
=
HistoryRecord
(
grammar
.
call_stack
.
copy
(),
node
,
len
(
rest
))
grammar
.
history
.
append
(
record
)
...
...
@@ -378,11 +382,17 @@ class Grammar:
else
:
stitches
.
append
(
result
)
error_msg
=
"Parser stopped before end"
+
\
(
"! trying to recover..."
((
"! trying to recover"
+
(
" but stopping history recording at this point."
if
self
.
history_tracking
else
"..."
))
if
len
(
stitches
)
<
MAX_DROPOUTS
else
" too often! Terminating parser."
)
stitches
.
append
(
Node
(
None
,
skip
))
stitches
[
-
1
].
add_error
(
error_msg
)
if
self
.
history_tracking
:
record
=
HistoryRecord
(
self
.
call_stack
.
copy
(),
stitches
[
-
1
],
len
(
rest
))
self
.
history
.
append
(
record
)
self
.
history_tracking
=
False
if
stitches
:
if
rest
:
stitches
.
append
(
Node
(
None
,
rest
))
...
...
examples/Tutorial/Lyrik.ebnf
View file @
c1b3846f
gedicht = bibliographisches {
LZ
}+ [serie] §titel §text
gedicht = bibliographisches {
LEERZEILE
}+ [serie] §titel §text
§ENDE
bibliographisches = autor §"," [Z
SP
] werk §"," [Z
SP
] ort §"," [Z
SP
] jahr §"."
bibliographisches = autor §"," [
N
Z] werk §"," [
N
Z] ort §"," [
N
Z] jahr §"."
autor = namenfolge [verknüpfung]
werk = wortfolge ["." §untertitel] [verknüpfung]
untertitel = wortfolge [verknüpfung]
ort = wortfolge [verknüpfung]
jahr = JAHRESZAHL
serie = !(titel vers Z
SP
vers) {
[ZSP]
zeile }+ {
LZ
}+
titel = zeile
zeile =
[LEER]
{ ZEICHENFOLGE }+
serie = !(titel vers
N
Z vers) {
NZ
zeile }+ {
LEERZEILE
}+
titel =
NZ
zeile
{ LEERZEILE }+
zeile = { ZEICHENFOLGE }+
text = { strophe }+
strophe = {
LZ+} { [ZSP]
vers }+
vers =
[LEER]
{ ZEICHENFOLGE }+
text = { strophe
{LEERZEILE}+
}+
strophe = {
NZ
vers }+
vers = { ZEICHENFOLGE }+
wortfolge = { WORT }+
namenfolge = { NAME }+
...
...
@@ -24,7 +24,7 @@ WORT = /\w+/~
NAME = /\w+\.?/~
ZEICHENFOLGE = /[^ \n<>]+/~
LEER = /[ \t]+/
ZSP
= /\n/~
L
Z
= /\n[ \t]*\n/~
NZ
= /\n/~
L
EERZEILE
= /\n[ \t]*
(?=
\n
)
/~
JAHRESZAHL = /\d\d\d\d/~
ENDE = !/./
examples/Tutorial/LyrikCompiler.py
0 → 100644
View file @
c1b3846f
#!/usr/bin/python
#######################################################################
#
# SYMBOLS SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
import
os
import
sys
from
functools
import
partial
try
:
import
regex
as
re
except
ImportError
:
import
re
from
DHParser.toolkit
import
logging
,
is_filename
from
DHParser.parsers
import
Grammar
,
CompilerBase
,
Required
,
Token
,
\
Optional
,
OneOrMore
,
Sequence
,
RE
,
NegativeLookahead
,
mixin_comment
,
compile_source
from
DHParser.syntaxtree
import
traverse
,
no_operation
#######################################################################
#
# SCANNER SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
def
LyrikScanner
(
text
):
return
text
def
get_scanner
():
return
LyrikScanner
#######################################################################
#
# PARSER SECTION - Don't edit! CHANGES WILL BE OVERWRITTEN!
#
#######################################################################
class
LyrikGrammar
(
Grammar
):
r
"""Parser for a Lyrik source file, with this grammar:
gedicht = bibliographisches { LEERZEILE }+ [serie] §titel §text
bibliographisches = autor §"," [NZ] werk §"," [NZ] ort §"," [NZ] jahr §"."
autor = namenfolge [verknüpfung]
werk = wortfolge ["." §untertitel] [verknüpfung]
untertitel = wortfolge [verknüpfung]
ort = wortfolge [verknüpfung]
jahr = JAHRESZAHL
serie = !(titel vers NZ vers) { NZ zeile }+ { LEERZEILE }+
titel = NZ zeile
zeile = { ZEICHENFOLGE }+
text = { strophe {LEERZEILE}+ }+
strophe = { NZ vers }+
vers = { ZEICHENFOLGE }+
wortfolge = { WORT }+
namenfolge = { NAME }+
verknüpfung = "<" ziel ">"
ziel = ZEICHENFOLGE
WORT = /\w+/~
NAME = /\w+\.?/~
ZEICHENFOLGE = /[^ \n<>]+/~
LEER = /[ \t]+/
NZ = /\n/~
LEERZEILE = /\n[ \t]*(?=\n)/~
JAHRESZAHL = /\d\d\d\d/~
ENDE = !/./
"""
source_hash__
=
"6718329094e23c5285d3bed5b2861c10"
parser_initialization__
=
"upon instatiation"
COMMENT__
=
r
''
WSP__
=
mixin_comment
(
whitespace
=
r
'[\t ]*'
,
comment
=
r
''
)
wspL__
=
''
wspR__
=
WSP__
ENDE
=
NegativeLookahead
(
RE
(
'.'
,
wR
=
''
))
JAHRESZAHL
=
RE
(
'
\\
d
\\
d
\\
d
\\
d'
)
LEERZEILE
=
RE
(
'
\\
n[
\\
t]*(?=
\\
n)'
)
NZ
=
RE
(
'
\\
n'
)
LEER
=
RE
(
'[
\\
t]+'
,
wR
=
''
)
ZEICHENFOLGE
=
RE
(
'[^
\\
n<>]+'
)
NAME
=
RE
(
'
\\
w+
\\
.?'
)
WORT
=
RE
(
'
\\
w+'
)
ziel
=
ZEICHENFOLGE
verknüpfung
=
Sequence
(
Token
(
"<"
),
ziel
,
Token
(
">"
))
namenfolge
=
OneOrMore
(
NAME
)
wortfolge
=
OneOrMore
(
WORT
)
vers
=
OneOrMore
(
ZEICHENFOLGE
)
strophe
=
OneOrMore
(
Sequence
(
NZ
,
vers
))
text
=
OneOrMore
(
Sequence
(
strophe
,
OneOrMore
(
LEERZEILE
)))
zeile
=
OneOrMore
(
ZEICHENFOLGE
)
titel
=
Sequence
(
NZ
,
zeile
)
serie
=
Sequence
(
NegativeLookahead
(
Sequence
(
titel
,
vers
,
NZ
,
vers
)),
OneOrMore
(
Sequence
(
NZ
,
zeile
)),
OneOrMore
(
LEERZEILE
))
jahr
=
JAHRESZAHL
ort
=
Sequence
(
wortfolge
,
Optional
(
verknüpfung
))
untertitel
=
Sequence
(
wortfolge
,
Optional
(
verknüpfung
))
werk
=
Sequence
(
wortfolge
,
Optional
(
Sequence
(
Token
(
"."
),
Required
(
untertitel
))),
Optional
(
verknüpfung
))
autor
=
Sequence
(
namenfolge
,
Optional
(
verknüpfung
))
bibliographisches
=
Sequence
(
autor
,
Required
(
Token
(
","
)),
Optional
(
NZ
),
werk
,
Required
(
Token
(
","
)),
Optional
(
NZ
),
ort
,
Required
(
Token
(
","
)),
Optional
(
NZ
),
jahr
,
Required
(
Token
(
"."
)))
gedicht
=
Sequence
(
bibliographisches
,
OneOrMore
(
LEERZEILE
),
Optional
(
serie
),
Required
(
titel
),
Required
(
text
))
root__
=
gedicht
def
get_grammar
():
global
thread_local_Lyrik_grammar_singleton
try
:
grammar
=
thread_local_Lyrik_grammar_singleton
return
grammar
except
NameError
:
thread_local_Lyrik_grammar_singleton
=
LyrikGrammar
()
return
thread_local_Lyrik_grammar_singleton
#######################################################################
#
# AST SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
Lyrik_AST_transformation_table
=
{
# AST Transformations for the Lyrik-grammar
"gedicht"
:
no_operation
,
"bibliographisches"
:
no_operation
,
"autor"
:
no_operation
,
"werk"
:
no_operation
,
"untertitel"
:
no_operation
,
"ort"
:
no_operation
,
"jahr"
:
no_operation
,
"serie"
:
no_operation
,
"titel"
:
no_operation
,
"zeile"
:
no_operation
,
"text"
:
no_operation
,
"strophe"
:
no_operation
,
"vers"
:
no_operation
,
"wortfolge"
:
no_operation
,
"namenfolge"
:
no_operation
,
"verknüpfung"
:
no_operation
,
"ziel"
:
no_operation
,
"WORT"
:
no_operation
,
"NAME"
:
no_operation
,
"ZEICHENFOLGE"
:
no_operation
,
"LEER"
:
no_operation
,
"NZ"
:
no_operation
,
"LEERZEILE"
:
no_operation
,
"JAHRESZAHL"
:
no_operation
,
"ENDE"
:
no_operation
,
"*"
:
no_operation
}
LyrikTransform
=
partial
(
traverse
,
processing_table
=
Lyrik_AST_transformation_table
)
def
get_transformer
():
return
LyrikTransform
#######################################################################
#
# COMPILER SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
class
LyrikCompiler
(
CompilerBase
):
"""Compiler for the abstract-syntax-tree of a Lyrik source file.
"""
def
__init__
(
self
,
grammar_name
=
"Lyrik"
,
grammar_source
=
""
):
super
(
LyrikCompiler
,
self
).
__init__
(
grammar_name
,
grammar_source
)
assert
re
.
match
(
'\w+\Z'
,
grammar_name
)
def
on_gedicht
(
self
,
node
):
return
node
def
on_bibliographisches
(
self
,
node
):
pass
def
on_autor
(
self
,
node
):
pass
def
on_werk
(
self
,
node
):
pass
def
on_untertitel
(
self
,
node
):
pass
def
on_ort
(
self
,
node
):
pass
def
on_jahr
(
self
,
node
):
pass
def
on_serie
(
self
,
node
):
pass
def
on_titel
(
self
,
node
):
pass
def
on_zeile
(
self
,
node
):
pass
def
on_text
(
self
,
node
):
pass
def
on_strophe
(
self
,
node
):
pass
def
on_vers
(
self
,
node
):
pass
def
on_wortfolge
(
self
,
node
):
pass
def
on_namenfolge
(
self
,
node
):
pass
def
on_verknüpfung
(
self
,
node
):
pass
def
on_ziel
(
self
,
node
):
pass
def
on_WORT
(
self
,
node
):
pass
def
on_NAME
(
self
,
node
):
pass
def
on_ZEICHENFOLGE
(
self
,
node
):
pass
def
on_LEER
(
self
,
node
):
pass
def
on_NZ
(
self
,
node
):
pass
def
on_LEERZEILE
(
self
,
node
):
pass
def
on_JAHRESZAHL
(
self
,
node
):
pass
def
on_ENDE
(
self
,
node
):
pass
def
get_compiler
(
grammar_name
=
"Lyrik"
,
grammar_source
=
""
):
global
thread_local_Lyrik_compiler_singleton
try
:
compiler
=
thread_local_Lyrik_compiler_singleton
compiler
.
set_grammar_name
(
grammar_name
,
grammar_source
)
return
compiler
except
NameError
:
thread_local_Lyrik_compiler_singleton
=
\
LyrikCompiler
(
grammar_name
,
grammar_source
)
return
thread_local_Lyrik_compiler_singleton
#######################################################################
#
# END OF DHPARSER-SECTIONS
#
#######################################################################
def
compile_src
(
source
):
"""Compiles ``source`` and returns (result, errors, ast).
"""
with
logging
(
"LOGS"
):
compiler
=
get_compiler
()
cname
=
compiler
.
__class__
.
__name__
log_file_name
=
os
.
path
.
basename
(
os
.
path
.
splitext
(
source
)[
0
])
\
if
is_filename
(
source
)
<
0
else
cname
[:
cname
.
find
(
'.'
)]
+
'_out'
result
=
compile_source
(
source
,
get_scanner
(),
get_grammar
(),
get_transformer
(),
compiler
)
return
result
if
__name__
==
"__main__"
:
if
len
(
sys
.
argv
)
==
1
:
sys
.
argv
.
append
(
"Lyrisches_Intermezzo_IV.txt"
)
if
len
(
sys
.
argv
)
>
1
:
result
,
errors
,
ast
=
compile_src
(
sys
.
argv
[
1
])
if
errors
:
for
error
in
errors
:
print
(
error
)
sys
.
exit
(
1
)
else
:
print
(
result
)
else
:
print
(
"Usage: LyrikCompiler.py [FILENAME]"
)
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