MLW_compiler.py 14.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


#######################################################################
#
# SYMBOLS SECTION - Can be edited. Changes will be preserved.
#
#######################################################################


from PyDSL import Pop, NegativeLookbehind, Capture, no_transformation, \
    Token, Alternative, mixin_comment, RE, \
    Sequence, remove_comments, Retrieve, is_scanner_token, \
    Lookbehind, replace_by_single_child, remove_scanner_tokens, remove_whitespace, \
    is_whitespace, ZeroOrMore, remove_enclosing_delimiters, CompilerBase, \
    RegExp, NegativeLookahead, WHITESPACE_KEYWORD, GrammarBase, \
    reduce_single_child, Optional, remove_children_if, remove_expendables, \
    remove_tokens, is_comment, partial, OneOrMore, \
    Forward, TOKEN_KEYWORD, Required, flatten, \
    is_expendable, Lookahead



#######################################################################
#
# SCANNER SECTION - Can be edited. Changes will be preserved.
#
#######################################################################

29
30
31
32
def MLWScanner(text):
    return text


33
34
35
36
37
#######################################################################
#
# PARSER SECTION - Don't edit! CHANGES WILL BE OVERWRITTEN!
#
#######################################################################
38

39
class MLWGrammar(GrammarBase):
40
41
42
43
44
    r"""Parser for a MLW source file, with this grammar:
    
    # EBNF-Syntax für MLW-Artikel
    
    @ comment       =  /#.*(?:\n|$)/    # Kommentare beginnen mit '#' und reichen bis zum Zeilenende
di68kap's avatar
di68kap committed
45
    @ whitespace    =  /[\t\r\ ]*/      # Auch Zeilensprünge zählen als Leerraum
46
47
48
49
50
51
52
53
54
55
56
57
    @ literalws     =  both             # Leerraum vor und nach Literalen wird automatisch entfernt
    
    
    Artikel         = [LEER]
                      §LemmaPosition  [ArtikelKopf]  §BedeutungsPosition  §Autorinfo
                      [LEER]  DATEI_ENDE
    
    
    #### LEMMA-POSITION ##########################################################
    
    LemmaPosition   = "LEMMA"  §Lemma  [LemmaVarianten]  §GrammatikPosition
    
di68kap's avatar
di68kap committed
58
    Lemma           = [_tll]  WORT_KLEIN [LEER]
59
60
    _tll            = "*"
    
di68kap's avatar
di68kap committed
61
    LemmaVarianten  = "VARIANTEN" [LEER] §LVariante  { TRENNER LVariante }
62
                      [TRENNER LVZusatz] [TRENNER]
di68kap's avatar
di68kap committed
63
64
    LVariante       = ~/(?:[a-z]|-)+/~      # Buchstabenfolge mit Trennzeichen "-"
    LVZusatz        = "ZUSATZ" "sim."
65
66
67
68
69
    
    
    
    #### GRAMMATIK-POSITION ######################################################
    
70
71
    GrammatikPosition = "GRAMMATIK" [LEER] §_wortart §TRENNER §Flexionen [_genus]
                        {GrammatikVarianten} [TRENNER]
72
73
74
75
76
77
78
    
    _wortart        = "nomen"  | "n." |
                      "verb"   | "v." |
                      "adverb" | "adv." |
                      "adjektiv" | "adj."
    
    
79
    GrammatikVarianten = TRENNER GVariante
80
81
82
83
84
85
86
87
88
89
90
91
92
93
    GVariante       = Flexionen  [_genus]  ":"  Beleg
    
    Flexionen       = Flexion { "," §Flexion }
    Flexion         = /-?[a-z]+/~
    
    _genus          = "maskulinum" | "m." |
                      "femininum" | "f." |
                      "neutrum" | "n."
    
    
    
    #### ARTIKEL-KOPF ############################################################
    
    ArtikelKopf     = SchreibweisenPosition
94
95
    SchreibweisenPosition =  "SCHREIBWEISE" [LEER] §SWTyp ":" [LEER]
                             §SWVariante { TRENNER SWVariante} [LEER]
96
97
98
99
100
    SWTyp           = "script." | "script. fat-"
    SWVariante      = Schreibweise ":" Beleg
    Schreibweise    = "vizreg-" | "festregel(a)" | "fezdregl(a)" | "fat-"
    
    Beleg           = Verweis
101
    Verweis         = ~/\w+/~
102
103
104
105
106
    VerweisZiel     = ~/<\w+>/~
    
    
    #### BEDEUTUNGS-POSITION #####################################################
    
di68kap's avatar
di68kap committed
107
    BedeutungsPosition = { "BEDEUTUNG" [LEER] §Bedeutung }+
108
    
109
    Bedeutung       = (Interpretamente | Bedeutungskategorie) [Belege]
110
111
    Bedeutungskategorie = /(?:(?![A-ZÄÖÜ][A-ZÄÖÜ]).)+/~ [LEER]
    Interpretamente = LateinischeBedeutung [LEER] §DeutscheBedeutung [LEER]
112
113
    LateinischeBedeutung = "LAT" /(?:(?![A-ZÄÖÜ][A-ZÄÖÜ]).)+/~
    DeutscheBedeutung = "DEU" /(?:(?![A-ZÄÖÜ][A-ZÄÖÜ]).)+/~
114
115
    Belege          = "BELEGE" [LEER] { "*" EinBeleg }
    EinBeleg        = { !(/\s*/ ("*" | "BEDEUTUNG" | "AUTOR" | "NAME" | "ZUSATZ")) /\s*.*\s*/ }+
di68kap's avatar
di68kap committed
116
                      [Zusatz]
117
    Zusatz          = "ZUSATZ" /\s*.*/
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    
    
    #### AUTOR/AUTORIN ###########################################################
    
    Autorinfo       = ("AUTORIN" | "AUTOR") Name
    Name            = WORT { WORT | /[A-ZÄÖÜÁÀ]\./ }
    
    
    #### MISZELLANEEN ############################################################
    
    WORT            = /[A-ZÄÖÜ]?[a-zäöüß]+/~
    WORT_GROSS      = /[A-ZÄÖÜ][a-zäöüß]+/~
    WORT_KLEIN      = /[a-zäöüß]+/~
    LAT_WORT        = /[a-z]+/~
    GROSSSCHRIFT    = /[A-ZÄÖÜ]+/~
    
di68kap's avatar
di68kap committed
134
135
136
137
    TRENNER         = /\s*;\s*/ | { ZSPRUNG }+
    ZSPRUNG         = /\n/~
    
    LEER            = /\s+/                     # horizontaler und(!) vertikaler Leerraum
138
139
140
    DATEI_ENDE      = !/./
    NIEMALS         = /(?!.)/
    """
di68kap's avatar
di68kap committed
141
    source_hash__ = "cf1ef8acfc5e15dffc53b1b48eda89b0"
142
    parser_initialization__ = "upon instatiation"
di68kap's avatar
di68kap committed
143
    wsp__ = mixin_comment(whitespace=r'[\t\r\ ]*', comment=r'#.*(?:\n|$)')
144
145
    wspL__ = wsp__
    wspR__ = wsp__
146
147
    NIEMALS = RE('(?!.)', wR='', wL='')
    DATEI_ENDE = NegativeLookahead(RE('.', wR='', wL=''))
di68kap's avatar
di68kap committed
148
149
150
    LEER = RE('\\s+', wR='', wL='')
    ZSPRUNG = RE('\\n', wL='')
    TRENNER = Alternative(RE('\\s*;\\s*', wR='', wL=''), OneOrMore(ZSPRUNG))
151
152
153
154
155
156
    GROSSSCHRIFT = RE('[A-ZÄÖÜ]+', wL='')
    LAT_WORT = RE('[a-z]+', wL='')
    WORT_KLEIN = RE('[a-zäöüß]+', wL='')
    WORT_GROSS = RE('[A-ZÄÖÜ][a-zäöüß]+', wL='')
    WORT = RE('[A-ZÄÖÜ]?[a-zäöüß]+', wL='')
    Name = Sequence(WORT, ZeroOrMore(Alternative(WORT, RE('[A-ZÄÖÜÁÀ]\\.', wR='', wL=''))))
157
    Autorinfo = Sequence(Alternative(Token("AUTORIN"), Token("AUTOR")), Name)
158
    Zusatz = Sequence(Token("ZUSATZ"), RE('\\s*.*', wR='', wL=''))
di68kap's avatar
di68kap committed
159
    EinBeleg = Sequence(OneOrMore(Sequence(NegativeLookahead(Sequence(RE('\\s*', wR='', wL=''), Alternative(Token("*"), Token("BEDEUTUNG"), Token("AUTOR"), Token("NAME"), Token("ZUSATZ")))), RE('\\s*.*\\s*', wR='', wL=''))), Optional(Zusatz))
160
    Belege = Sequence(Token("BELEGE"), Optional(LEER), ZeroOrMore(Sequence(Token("*"), EinBeleg)))
161
162
    DeutscheBedeutung = Sequence(Token("DEU"), RE('(?:(?![A-ZÄÖÜ][A-ZÄÖÜ]).)+', wL=''))
    LateinischeBedeutung = Sequence(Token("LAT"), RE('(?:(?![A-ZÄÖÜ][A-ZÄÖÜ]).)+', wL=''))
163
164
    Interpretamente = Sequence(LateinischeBedeutung, Optional(LEER), Required(DeutscheBedeutung), Optional(LEER))
    Bedeutungskategorie = Sequence(RE('(?:(?![A-ZÄÖÜ][A-ZÄÖÜ]).)+', wL=''), Optional(LEER))
165
    Bedeutung = Sequence(Alternative(Interpretamente, Bedeutungskategorie), Optional(Belege))
di68kap's avatar
di68kap committed
166
    BedeutungsPosition = OneOrMore(Sequence(Token("BEDEUTUNG"), Optional(LEER), Required(Bedeutung)))
167
    VerweisZiel = RE('<\\w+>')
168
    Verweis = RE('\\w+')
169
    Beleg = Verweis
170
171
172
    Schreibweise = Alternative(Token("vizreg-"), Token("festregel(a)"), Token("fezdregl(a)"), Token("fat-"))
    SWVariante = Sequence(Schreibweise, Token(":"), Beleg)
    SWTyp = Alternative(Token("script."), Token("script. fat-"))
173
    SchreibweisenPosition = Sequence(Token("SCHREIBWEISE"), Optional(LEER), Required(SWTyp), Token(":"), Optional(LEER), Required(SWVariante), ZeroOrMore(Sequence(TRENNER, SWVariante)), Optional(LEER))
174
    ArtikelKopf = SchreibweisenPosition
175
    _genus = Alternative(Token("maskulinum"), Token("m."), Token("femininum"), Token("f."), Token("neutrum"), Token("n."))
176
    Flexion = RE('-?[a-z]+', wL='')
177
178
    Flexionen = Sequence(Flexion, ZeroOrMore(Sequence(Token(","), Required(Flexion))))
    GVariante = Sequence(Flexionen, Optional(_genus), Token(":"), Beleg)
179
    GrammatikVarianten = Sequence(TRENNER, GVariante)
180
    _wortart = Alternative(Token("nomen"), Token("n."), Token("verb"), Token("v."), Token("adverb"), Token("adv."), Token("adjektiv"), Token("adj."))
181
    GrammatikPosition = Sequence(Token("GRAMMATIK"), Optional(LEER), Required(_wortart), Required(TRENNER), Required(Flexionen), Optional(_genus), ZeroOrMore(GrammatikVarianten), Optional(TRENNER))
di68kap's avatar
di68kap committed
182
    LVZusatz = Sequence(Token("ZUSATZ"), Token("sim."))
183
    LVariante = RE('(?:[a-z]|-)+')
184
    LemmaVarianten = Sequence(Token("VARIANTEN"), Optional(LEER), Required(LVariante), ZeroOrMore(Sequence(TRENNER, LVariante)), Optional(Sequence(TRENNER, LVZusatz)), Optional(TRENNER))
185
    _tll = Token("*")
di68kap's avatar
di68kap committed
186
    Lemma = Sequence(Optional(_tll), WORT_KLEIN, Optional(LEER))
187
    LemmaPosition = Sequence(Token("LEMMA"), Required(Lemma), Optional(LemmaVarianten), Required(GrammatikPosition))
188
189
190
191
    Artikel = Sequence(Optional(LEER), Required(LemmaPosition), Optional(ArtikelKopf), Required(BedeutungsPosition), Required(Autorinfo), Optional(LEER), DATEI_ENDE)
    root__ = Artikel
    

192
193
194
195
196
#######################################################################
#
# AST SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
197

198
199
# def test(node):
#     print(node.as_sexpr())
Eckhart Arnold's avatar
Eckhart Arnold committed
200
201
202
203
204
205
206
207
208
209
210
211
212


def join_strings(node, delimiter='\n'):
    new_result = []
    n = 0
    while n < len(node.result):
        nd = node.result[n]
        if not nd.children:
            a = n
            n += 1
            while n < len(node.result) and not node.result[n].children:
                n += 1
            nd.result = delimiter.join((r.result for r in node.result[a:n]))
213
214
        else:
            raise AssertionError(node.as_sexpr())
Eckhart Arnold's avatar
Eckhart Arnold committed
215
216
217
        new_result.append(nd)
    node.result = tuple(new_result)

218

219
220
221
MLWTransTable = {
    # AST Transformations for the MLW-grammar
    "Artikel": no_transformation,
222
223
224
225
    "LemmaPosition":
        [partial(remove_tokens, tokens={'LEMMA'})],
    "Lemma": no_transformation,
    "_tll, _wortart, _genus":
226
227
228
229
        [remove_expendables, reduce_single_child],
    "LemmaVarianten":
        [partial(remove_tokens, tokens={'VARIANTEN'}), flatten,
         partial(remove_tokens, tokens={',', ';'})],
Eckhart Arnold's avatar
Eckhart Arnold committed
230
    "LVariante, LVZusatz, Schreibweise, Name":
231
        [remove_expendables, reduce_single_child],
232
233
    "SWVariante":
        [remove_expendables, partial(remove_tokens, tokens={':'})],
234
235
236
237
238
239
240
241
242
243
    "GrammatikPosition":
        [partial(remove_tokens, tokens={'GRAMMATIK', ';'}), flatten],
    "GrammatikVarianten":
        [partial(remove_tokens, tokens={';'}), replace_by_single_child],
    "GVariante":
        [partial(remove_tokens, tokens={':'})],
    "Flexionen":
        [flatten, partial(remove_tokens, tokens={',', ';'})],
    "Flexion, Verweis":
        [remove_expendables, reduce_single_child],
244
245
    "Zusatz":
        [remove_expendables, remove_tokens, reduce_single_child],
246
    "ArtikelKopf": no_transformation,
247
248
249
    "SchreibweisenPosition":
        [partial(remove_tokens, tokens={'SCHREIBWEISE', ':'}),
         flatten, partial(remove_tokens, tokens={','})],
250
    "SWTyp": no_transformation,
251
252
    "BedeutungsPosition":
        [flatten, partial(remove_tokens, tokens={'BEDEUTUNG'})],
253
254
255
    "Bedeutung": no_transformation,
    "Bedeutungskategorie": no_transformation,
    "Interpretamente": no_transformation,
Eckhart Arnold's avatar
Eckhart Arnold committed
256
257
258
259
260
    "LateinischeBedeutung, DeutscheBedeutung":
        [remove_expendables, remove_tokens, reduce_single_child],
    "Belege":
        [flatten, remove_tokens],
    "EinBeleg":
261
        [flatten, remove_expendables, join_strings, reduce_single_child],
262
263
    "Beleg": no_transformation,
    "VerweisZiel": no_transformation,
264
265
    "Autorinfo":
        [partial(remove_tokens, tokens={'AUTORIN', 'AUTOR'})],
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
    "WORT, WORT_KLEIN, WORT_GROSS, GROSSSCHRIFT":
        # test,
        [remove_expendables, reduce_single_child],
    "LEER": no_transformation,
    "DATEI_ENDE": no_transformation,
    "NIEMALS": no_transformation,
    (TOKEN_KEYWORD, WHITESPACE_KEYWORD):
        [remove_expendables, reduce_single_child],
    "*":
        remove_expendables,
    "~":
        partial(remove_tokens, tokens={',', ';'}),
    "":
        [remove_expendables, replace_by_single_child]
}


283
284
285
286
287
#######################################################################
#
# COMPILER SECTION - Can be edited. Changes will be preserved.
#
#######################################################################
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353

class MLWCompiler(CompilerBase):
    """Compiler for the abstract-syntax-tree of a MLW source file.
    """

    def __init__(self, grammar_name="MLW"):
        super(MLWCompiler, self).__init__()
        assert re.match('\w+\Z', grammar_name)

    def Artikel(self, node):
        return node

    def LemmaPosition(self, node):
        pass

    def Lemma(self, node):
        pass

    def _tll(self, node):
        pass

    def LemmaVarianten(self, node):
        pass

    def LVariante(self, node):
        pass

    def LVZusatz(self, node):
        pass

    def GrammatikPosition(self, node):
        pass

    def _wortart(self, node):
        pass

    def GrammatikVarianten(self, node):
        pass

    def GVariante(self, node):
        pass

    def Flexionen(self, node):
        pass

    def Flexion(self, node):
        pass

    def _genus(self, node):
        pass

    def ArtikelKopf(self, node):
        pass

    def SchreibweisenPosition(self, node):
        pass

    def SWTyp(self, node):
        pass

    def SWVariante(self, node):
        pass

    def Schreibweise(self, node):
        pass

354
355
356
357
358
359
360
361
362
    def Beleg(self, node):
        pass

    def Verweis(self, node):
        pass

    def VerweisZiel(self, node):
        pass

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    def BedeutungsPosition(self, node):
        pass

    def Bedeutung(self, node):
        pass

    def Bedeutungskategorie(self, node):
        pass

    def Interpretamente(self, node):
        pass

    def LateinischeBedeutung(self, node):
        pass

    def DeutscheBedeutung(self, node):
        pass

    def Belege(self, node):
        pass

    def EinBeleg(self, node):
        pass

387
    def Zusatz(self, node):
388
389
        pass

390
    def Autorinfo(self, node):
391
392
        pass

393
    def Name(self, node):
394
395
396
397
398
        pass

    def WORT(self, node):
        pass

399
400
401
    def WORT_GROSS(self, node):
        pass

402
403
404
    def WORT_KLEIN(self, node):
        pass

405
406
407
    def LAT_WORT(self, node):
        pass

408
409
410
411
412
413
414
415
416
417
418
419
    def GROSSSCHRIFT(self, node):
        pass

    def LEER(self, node):
        pass

    def DATEI_ENDE(self, node):
        pass

    def NIEMALS(self, node):
        pass

420
421
422
423
424
425
426
427


#######################################################################
#
# END OF PYDSL-SECTIONS
#
#######################################################################