]> git.lyx.org Git - features.git/blob - lib/lyx2lyx/lyx_2_4.py
Amend 3e92efd: Remove (Begin|End)Frontmatter in elsarticle
[features.git] / lib / lyx2lyx / lyx_2_4.py
1 # -*- coding: utf-8 -*-
2 # This file is part of lyx2lyx
3 # Copyright (C) 2018 The LyX team
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 """ Convert files to the file format generated by lyx 2.4"""
20
21 import re, string
22 import unicodedata
23 import sys, os
24
25 # Uncomment only what you need to import, please.
26
27 from parser_tools import (count_pars_in_inset, find_end_of_inset, find_end_of_layout,
28 find_token, get_bool_value, get_option_value, get_value, get_quoted_value) 
29 #    del_token, del_value, del_complete_lines,
30 #    find_complete_lines, find_end_of, 
31 #    find_re, find_substring, find_token_backwards,
32 #    get_containing_inset, get_containing_layout,
33 #    is_in_inset, set_bool_value
34 #    find_tokens, find_token_exact, check_token
35
36 from lyx2lyx_tools import (put_cmd_in_ert, add_to_preamble)
37 #  revert_font_attrs, insert_to_preamble, latex_length
38 #  get_ert, lyx2latex, lyx2verbatim, length_in_bp, convert_info_insets
39 #  revert_flex_inset, hex2ratio, str2bool
40
41 ####################################################################
42 # Private helper functions
43
44
45
46 ###############################################################################
47 ###
48 ### Conversion and reversion routines
49 ###
50 ###############################################################################
51
52 def removeFrontMatterStyles(document):
53     " Remove styles Begin/EndFromatter"
54
55     layouts = ['BeginFrontmatter', 'EndFrontmatter']
56     for layout in layouts:
57         i = 0
58         while True:
59             i = find_token(document.body, '\\begin_layout ' + layout, i)
60             if i == -1:
61                 break
62             j = find_end_of_layout(document.body, i)
63             if j == -1:
64                 document.warning("Malformed LyX document: Can't find end of layout at line %d" % i)
65                 i += 1
66                 continue
67             if document.body[j] == '':
68                 j = j + 1
69             del document.body[i:j+1]
70
71 def addFrontMatterStyles(document):
72     " Use styles Begin/EndFrontmatter for elsarticle"
73
74     def insertFrontmatter(prefix, line):
75         document.body[line:line] = ['\\begin_layout ' + prefix + 'Frontmatter',
76                                     '\\begin_inset Note Note',
77                                     'status open', '',
78                                     '\\begin_layout Plain Layout',
79                                     'Keep this empty!',
80                                     '\\end_layout', '',
81                                     '\\end_inset', '', '',
82                                     '\\end_layout']
83
84     if document.textclass == "elsarticle":
85         layouts = ['Title', 'Title footnote', 'Author', 'Author footnote',
86                    'Corresponding author', 'Address', 'Email', 'Abstract', 'Keywords']
87         first = -1
88         last = -1
89         for layout in layouts:
90             i = 0
91             while True:
92                 i = find_token(document.body, '\\begin_layout ' + layout, i)
93                 if i == -1:
94                     break
95                 k = find_end_of_layout(document.body, i)
96                 if k == -1:
97                     document.warning("Malformed LyX document: Can't find end of layout at line %d" % i)
98                     i += 1;
99                     continue
100                 if first == -1 or i < first:
101                     first = i
102                 if last == -1 or last <= k:
103                     last = k+1
104                 i = k
105         if first == -1:
106             return
107         if first > 0 and document.body[first-1] == '':
108             first -= 1
109         if document.body[last] == '':
110             last = last + 1
111         insertFrontmatter('End', last)
112         insertFrontmatter('Begin', first)
113
114 def convert_lst_literalparam(document):
115     " Add param literal to include inset "
116
117     i = 0
118     while True:
119         i = find_token(document.body, '\\begin_inset CommandInset include', i)
120         if i == -1:
121             break
122         j = find_end_of_inset(document.body, i)
123         if j == -1:
124             document.warning("Malformed LyX document: Can't find end of command inset at line %d" % i)
125             i += 1
126             continue
127         while i < j and document.body[i].strip() != '':
128             i += 1
129         document.body.insert(i, "literal \"true\"")
130
131
132 def revert_lst_literalparam(document):
133     " Remove param literal from include inset "
134
135     i = 0
136     while True:
137         i = find_token(document.body, '\\begin_inset CommandInset include', i)
138         if i == -1:
139             break
140         j = find_end_of_inset(document.body, i)
141         if j == -1:
142             document.warning("Malformed LyX document: Can't find end of include inset at line %d" % i)
143             i += 1
144             continue
145         k = find_token(document.body, 'literal', i, j)
146         if k == -1:
147             i += 1
148             continue
149         del document.body[k]
150
151
152 def revert_paratype(document):
153     " Revert ParaType font definitions to LaTeX "
154
155     if find_token(document.header, "\\use_non_tex_fonts false", 0) != -1:
156         preamble = ""
157         i1 = find_token(document.header, "\\font_roman \"PTSerif-TLF\"", 0)
158         i2 = find_token(document.header, "\\font_sans \"default\"", 0)
159         i3 = find_token(document.header, "\\font_typewriter \"default\"", 0)
160         j = find_token(document.header, "\\font_sans \"PTSans-TLF\"", 0)
161         sfval = get_value(document.header, "\\font_sf_scale", 0)
162         # cutoff " 100"
163         sfval = sfval[:-4]
164         sfoption = ""
165         if sfval != "100":
166             sfoption = "scaled=" + format(float(sfval) / 100, '.2f')
167         k = find_token(document.header, "\\font_typewriter \"PTMono-TLF\"", 0)
168         ttval = get_value(document.header, "\\font_tt_scale", 0)
169         # cutoff " 100"
170         ttval = ttval[:-4]
171         ttoption = ""
172         if ttval != "100":
173             ttoption = "scaled=" + format(float(ttval) / 100, '.2f')
174         if i1 != -1 and i2 != -1 and i3!= -1:
175             add_to_preamble(document, ["\\usepackage{paratype}"])
176         else:
177             if i1!= -1: 
178                 add_to_preamble(document, ["\\usepackage{PTSerif}"])
179                 document.header[i1] = document.header[i1].replace("PTSerif-TLF", "default")
180             if j!= -1: 
181                 if sfoption != "":
182                     add_to_preamble(document, ["\\usepackage[" + sfoption + "]{PTSans}"])
183                 else:
184                     add_to_preamble(document, ["\\usepackage{PTSans}"])
185                 document.header[j] = document.header[j].replace("PTSans-TLF", "default")
186             if k!= -1: 
187                 if ttoption != "":
188                     add_to_preamble(document, ["\\usepackage[" + ttoption + "]{PTMono}"])
189                 else:
190                     add_to_preamble(document, ["\\usepackage{PTMono}"])    
191                 document.header[k] = document.header[k].replace("PTMono-TLF", "default")
192
193
194 def revert_xcharter(document):
195     " Revert XCharter font definitions to LaTeX "
196
197     i = find_token(document.header, "\\font_roman \"xcharter\"", 0)
198     if i == -1:
199         return
200
201     # replace unsupported font setting
202     document.header[i] = document.header[i].replace("xcharter", "default")
203     # no need for preamble code with system fonts
204     if get_bool_value(document.header, "\\use_non_tex_fonts"):
205         return
206
207     # transfer old style figures setting to package options
208     j = find_token(document.header, "\\font_osf true")
209     if j != -1:
210         options = "[osf]"
211         document.header[j] = "\\font_osf false"
212     else:
213         options = ""
214     if i != -1:
215         add_to_preamble(document, ["\\usepackage%s{XCharter}"%options])
216
217
218 def revert_lscape(document):
219     " Reverts the landscape environment (Landscape module) to TeX-code "
220
221     if not "landscape" in document.get_module_list():
222         return
223
224     i = 0
225     while True:
226         i = find_token(document.body, "\\begin_inset Flex Landscape", i)
227         if i == -1:
228             return
229         j = find_end_of_inset(document.body, i)
230         if j == -1:
231             document.warning("Malformed LyX document: Can't find end of Landscape inset")
232             i += 1
233             continue
234
235         if document.body[i] == "\\begin_inset Flex Landscape (Floating)":
236             document.body[j - 2 : j + 1] = put_cmd_in_ert("\\end{landscape}}")
237             document.body[i : i + 4] = put_cmd_in_ert("\\afterpage{\\begin{landscape}")
238             add_to_preamble(document, ["\\usepackage{afterpage}"])
239         else:
240             document.body[j - 2 : j + 1] = put_cmd_in_ert("\\end{landscape}")
241             document.body[i : i + 4] = put_cmd_in_ert("\\begin{landscape}")
242
243         add_to_preamble(document, ["\\usepackage{pdflscape}"])
244         # no need to reset i
245
246
247 def convert_fontenc(document):
248     " Convert default fontenc setting "
249
250     i = find_token(document.header, "\\fontencoding global", 0)
251     if i == -1:
252         return
253
254     document.header[i] = document.header[i].replace("global", "auto")
255
256
257 def revert_fontenc(document):
258     " Revert default fontenc setting "
259
260     i = find_token(document.header, "\\fontencoding auto", 0)
261     if i == -1:
262         return
263
264     document.header[i] = document.header[i].replace("auto", "global")
265
266
267 def revert_nospellcheck(document):
268     " Remove nospellcheck font info param "
269
270     i = 0
271     while True:
272         i = find_token(document.body, '\\nospellcheck', i)
273         if i == -1:
274             return
275         del document.body[i]
276
277
278 def revert_floatpclass(document):
279     " Remove float placement params 'document' and 'class' "
280
281     i = 0
282     i = find_token(document.header, "\\float_placement class", 0)
283     if i != -1:
284         del document.header[i]
285
286     i = 0
287     while True:
288         i = find_token(document.body, '\\begin_inset Float', i)
289         if i == -1:
290             break
291         j = find_end_of_inset(document.body, i)
292         k = find_token(document.body, 'placement class', i, i + 2)
293         if k == -1:
294             k = find_token(document.body, 'placement document', i, i + 2)
295             if k != -1:
296                 del document.body[k]
297             i = j
298             continue
299         del document.body[k]
300
301
302 def revert_floatalignment(document):
303     " Remove float alignment params "
304
305     i = 0
306     i = find_token(document.header, "\\float_alignment", 0)
307     galignment = ""
308     if i != -1:
309         galignment = get_value(document.header, "\\float_alignment", i)
310         del document.header[i]
311
312     i = 0
313     while True:
314         i = find_token(document.body, '\\begin_inset Float', i)
315         if i == -1:
316             break
317         j = find_end_of_inset(document.body, i)
318         if j == -1:
319             document.warning("Malformed LyX document: Can't find end of inset at line " + str(i))
320             i += 1
321         k = find_token(document.body, 'alignment', i, i + 4)
322         if k == -1:
323             i = j
324             continue
325         alignment = get_value(document.body, "alignment", k)
326         if alignment == "document":
327             alignment = galignment
328         del document.body[k]
329         l = find_token(document.body, "\\begin_layout Plain Layout", i, j)
330         if l == -1:
331             document.warning("Can't find float layout!")
332             i = j
333             continue
334         alcmd = []
335         if alignment == "left":
336             alcmd = put_cmd_in_ert("\\raggedright{}")
337         elif alignment == "center":
338             alcmd = put_cmd_in_ert("\\centering{}")
339         elif alignment == "right":
340             alcmd = put_cmd_in_ert("\\raggedleft{}")
341         if len(alcmd) > 0:
342             document.body[l+1:l+1] = alcmd
343         i = j 
344
345
346 def revert_tuftecite(document):
347     " Revert \cite commands in tufte classes "
348
349     tufte = ["tufte-book", "tufte-handout"]
350     if document.textclass not in tufte:
351         return
352
353     i = 0
354     while (True):
355         i = find_token(document.body, "\\begin_inset CommandInset citation", i)
356         if i == -1:
357             break
358         j = find_end_of_inset(document.body, i)
359         if j == -1:
360             document.warning("Can't find end of citation inset at line %d!!" %(i))
361             i += 1
362             continue
363         k = find_token(document.body, "LatexCommand", i, j)
364         if k == -1:
365             document.warning("Can't find LatexCommand for citation inset at line %d!" %(i))
366             i = j + 1
367             continue
368         cmd = get_value(document.body, "LatexCommand", k)
369         if cmd != "cite":
370             i = j + 1
371             continue
372         pre = get_quoted_value(document.body, "before", i, j)
373         post = get_quoted_value(document.body, "after", i, j)
374         key = get_quoted_value(document.body, "key", i, j)
375         if not key:
376             document.warning("Citation inset at line %d does not have a key!" %(i))
377             key = "???"
378         # Replace command with ERT
379         res = "\\cite"
380         if pre:
381             res += "[" + pre + "]"
382         if post:
383             res += "[" + post + "]"
384         elif pre:
385             res += "[]"
386         res += "{" + key + "}"
387         document.body[i:j+1] = put_cmd_in_ert([res])
388         i = j + 1
389
390
391 def revert_stretchcolumn(document):
392     " We remove the column varwidth flags or everything else will become a mess. "
393     i = 0
394     while True:
395         i = find_token(document.body, "\\begin_inset Tabular", i)
396         if i == -1:
397             return
398         j = find_end_of_inset(document.body, i + 1)
399         if j == -1:
400             document.warning("Malformed LyX document: Could not find end of tabular.")
401             continue
402         for k in range(i, j):
403             if re.search('^<column.*varwidth="[^"]+".*>$', document.body[k]):
404                 document.warning("Converting 'tabularx'/'xltabular' table to normal table.")
405                 document.body[k] = document.body[k].replace(' varwidth="true"', '')
406         i = i + 1
407
408
409 def revert_vcolumns(document):
410     " Revert standard columns with line breaks etc. "
411     i = 0
412     needvarwidth = False
413     needarray = False
414     try:
415         while True:
416             i = find_token(document.body, "\\begin_inset Tabular", i)
417             if i == -1:
418                 return
419             j = find_end_of_inset(document.body, i)
420             if j == -1:
421                 document.warning("Malformed LyX document: Could not find end of tabular.")
422                 i += 1
423                 continue
424
425             # Collect necessary column information
426             m = i + 1
427             nrows = int(document.body[i+1].split('"')[3])
428             ncols = int(document.body[i+1].split('"')[5])
429             col_info = []
430             for k in range(ncols):
431                 m = find_token(document.body, "<column", m)
432                 width = get_option_value(document.body[m], 'width')
433                 varwidth = get_option_value(document.body[m], 'varwidth')
434                 alignment = get_option_value(document.body[m], 'alignment')
435                 special = get_option_value(document.body[m], 'special')
436                 col_info.append([width, varwidth, alignment, special, m])
437
438             # Now parse cells
439             m = i + 1
440             lines = []
441             for row in range(nrows):
442                 for col in range(ncols):
443                     m = find_token(document.body, "<cell", m)
444                     multicolumn = get_option_value(document.body[m], 'multicolumn')
445                     multirow = get_option_value(document.body[m], 'multirow')
446                     width = get_option_value(document.body[m], 'width')
447                     rotate = get_option_value(document.body[m], 'rotate')
448                     # Check for: linebreaks, multipars, non-standard environments
449                     begcell = m
450                     endcell = find_token(document.body, "</cell>", begcell)
451                     vcand = False
452                     if find_token(document.body, "\\begin_inset Newline", begcell, endcell) != -1:
453                         vcand = True
454                     elif count_pars_in_inset(document.body, begcell + 2) > 1:
455                         vcand = True
456                     elif get_value(document.body, "\\begin_layout", begcell) != "Plain Layout":
457                         vcand = True
458                     if vcand and rotate == "" and ((multicolumn == "" and multirow == "") or width == ""):
459                         if col_info[col][0] == "" and col_info[col][1] == "" and col_info[col][3] == "":
460                             needvarwidth = True
461                             alignment = col_info[col][2]
462                             col_line = col_info[col][4]
463                             vval = ""
464                             if alignment == "center":
465                                 vval = ">{\\centering}"
466                             elif  alignment == "left":
467                                 vval = ">{\\raggedright}"
468                             elif alignment == "right":
469                                 vval = ">{\\raggedleft}"
470                             if vval != "":
471                                 needarray = True
472                             vval += "V{\\linewidth}"
473                 
474                             document.body[col_line] = document.body[col_line][:-1] + " special=\"" + vval + "\">"
475                             # ERT newlines and linebreaks (since LyX < 2.4 automatically inserts parboxes
476                             # with newlines, and we do not want that)
477                             while True:
478                                 endcell = find_token(document.body, "</cell>", begcell)
479                                 linebreak = False
480                                 nl = find_token(document.body, "\\begin_inset Newline newline", begcell, endcell)
481                                 if nl == -1:
482                                     nl = find_token(document.body, "\\begin_inset Newline linebreak", begcell, endcell)
483                                     if nl == -1:
484                                          break
485                                     linebreak = True
486                                 nle = find_end_of_inset(document.body, nl)
487                                 del(document.body[nle:nle+1])
488                                 if linebreak:
489                                     document.body[nl:nl+1] = put_cmd_in_ert("\\linebreak{}")
490                                 else:
491                                     document.body[nl:nl+1] = put_cmd_in_ert("\\\\")
492                     m += 1
493
494             i = j + 1
495
496     finally:
497         if needarray == True:
498             add_to_preamble(document, ["\\usepackage{array}"])
499         if needvarwidth == True:
500             add_to_preamble(document, ["\\usepackage{varwidth}"])
501
502
503 def revert_bibencoding(document):
504     " Revert bibliography encoding "
505
506     # Get cite engine
507     engine = "basic"
508     i = find_token(document.header, "\\cite_engine", 0)
509     if i == -1:
510         document.warning("Malformed document! Missing \\cite_engine")
511     else:
512         engine = get_value(document.header, "\\cite_engine", i)
513
514     # Check if biblatex
515     biblatex = False
516     if engine in ["biblatex", "biblatex-natbib"]:
517         biblatex = True
518
519     # Map lyx to latex encoding names 
520     encodings = {
521         "utf8" : "utf8",
522         "utf8x" : "utf8x",
523         "armscii8" : "armscii8",
524         "iso8859-1" : "latin1",
525         "iso8859-2" : "latin2",
526         "iso8859-3" : "latin3",
527         "iso8859-4" : "latin4",
528         "iso8859-5" : "iso88595",
529         "iso8859-6" : "8859-6",
530         "iso8859-7" : "iso-8859-7",
531         "iso8859-8" : "8859-8",
532         "iso8859-9" : "latin5",
533         "iso8859-13" : "latin7",
534         "iso8859-15" : "latin9",
535         "iso8859-16" : "latin10",
536         "applemac" : "applemac",
537         "cp437" : "cp437",
538         "cp437de" : "cp437de",
539         "cp850" : "cp850",
540         "cp852" : "cp852",
541         "cp855" : "cp855",
542         "cp858" : "cp858",
543         "cp862" : "cp862",
544         "cp865" : "cp865",
545         "cp866" : "cp866",
546         "cp1250" : "cp1250",
547         "cp1251" : "cp1251",
548         "cp1252" : "cp1252",
549         "cp1255" : "cp1255",
550         "cp1256" : "cp1256",
551         "cp1257" : "cp1257",
552         "koi8-r" : "koi8-r",
553         "koi8-u" : "koi8-u",
554         "pt154" : "pt154",
555         "utf8-platex" : "utf8",
556         "ascii" : "ascii"
557     }
558
559     i = 0
560     bibresources = []
561     while (True):
562         i = find_token(document.body, "\\begin_inset CommandInset bibtex", i)
563         if i == -1:
564             break
565         j = find_end_of_inset(document.body, i)
566         if j == -1:
567             document.warning("Can't find end of bibtex inset at line %d!!" %(i))
568             i += 1
569             continue
570         encoding = get_quoted_value(document.body, "encoding", i, j)
571         if not encoding:
572             i += 1
573             continue
574         # remove encoding line
575         k = find_token(document.body, "encoding", i, j)
576         if k != -1:
577             del document.body[k]
578         # Re-find inset end line
579         j = find_end_of_inset(document.body, i)
580         if biblatex:
581             biblio_options = ""
582             h = find_token(document.header, "\\biblio_options", 0)
583             if h != -1:
584                 biblio_options = get_value(document.header, "\\biblio_options", h)
585                 if not "bibencoding" in biblio_options:
586                      document.header[h] += ",bibencoding=%s" % encodings[encoding]
587             else:
588                 bs = find_token(document.header, "\\biblatex_bibstyle", 0)
589                 if bs == -1:
590                     # this should not happen
591                     document.warning("Malformed LyX document! No \\biblatex_bibstyle header found!")
592                 else:
593                     document.header[bs-1 : bs-1] = ["\\biblio_options bibencoding=" + encodings[encoding]]
594         else:
595             document.body[j+1:j+1] = put_cmd_in_ert("\\egroup")
596             document.body[i:i] = put_cmd_in_ert("\\bgroup\\inputencoding{" + encodings[encoding] + "}")
597
598         i = j + 1
599
600
601
602 def convert_vcsinfo(document):
603     " Separate vcs Info inset from buffer Info inset. "
604
605     types = {
606         "vcs-revision" : "revision",
607         "vcs-tree-revision" : "tree-revision",
608         "vcs-author" : "author",
609         "vcs-time" : "time",
610         "vcs-date" : "date"
611     }
612     i = 0
613     while True:
614         i = find_token(document.body, "\\begin_inset Info", i)
615         if i == -1:
616             return
617         j = find_end_of_inset(document.body, i + 1)
618         if j == -1:
619             document.warning("Malformed LyX document: Could not find end of Info inset.")
620             i = i + 1
621             continue
622         tp = find_token(document.body, 'type', i, j)
623         tpv = get_quoted_value(document.body, "type", tp)
624         if tpv != "buffer":
625             i = i + 1
626             continue
627         arg = find_token(document.body, 'arg', i, j)
628         argv = get_quoted_value(document.body, "arg", arg)
629         if argv not in list(types.keys()):
630             i = i + 1
631             continue
632         document.body[tp] = "type \"vcs\""
633         document.body[arg] = "arg \"" + types[argv] + "\""
634         i = i + 1
635
636
637 def revert_vcsinfo(document):
638     " Merge vcs Info inset to buffer Info inset. "
639
640     args = ["revision", "tree-revision", "author", "time", "date" ]
641     i = 0
642     while True:
643         i = find_token(document.body, "\\begin_inset Info", i)
644         if i == -1:
645             return
646         j = find_end_of_inset(document.body, i + 1)
647         if j == -1:
648             document.warning("Malformed LyX document: Could not find end of Info inset.")
649             i = i + 1
650             continue
651         tp = find_token(document.body, 'type', i, j)
652         tpv = get_quoted_value(document.body, "type", tp)
653         if tpv != "vcs":
654             i = i + 1
655             continue
656         arg = find_token(document.body, 'arg', i, j)
657         argv = get_quoted_value(document.body, "arg", arg)
658         if argv not in args:
659             document.warning("Malformed Info inset. Invalid vcs arg.")
660             i = i + 1
661             continue
662         document.body[tp] = "type \"buffer\""
663         document.body[arg] = "arg \"vcs-" + argv + "\""
664         i = i + 1
665
666
667 ##
668 # Conversion hub
669 #
670
671 supported_versions = ["2.4.0", "2.4"]
672 convert = [
673            [545, [convert_lst_literalparam]],
674            [546, []],
675            [547, []],
676            [548, []],
677            [549, []],
678            [550, [convert_fontenc]],
679            [551, []],
680            [552, []],
681            [553, []],
682            [554, []],
683            [555, []],
684            [556, []],
685            [557, [convert_vcsinfo]],
686            [558, [removeFrontMatterStyles]]
687           ]
688
689 revert =  [
690            [557, [addFrontMatterStyles]],
691            [556, [revert_vcsinfo]],
692            [555, [revert_bibencoding]],
693            [554, [revert_vcolumns]],
694            [553, [revert_stretchcolumn]],
695            [552, [revert_tuftecite]],
696            [551, [revert_floatpclass, revert_floatalignment]],
697            [550, [revert_nospellcheck]],
698            [549, [revert_fontenc]],
699            [548, []],# dummy format change
700            [547, [revert_lscape]],
701            [546, [revert_xcharter]],
702            [545, [revert_paratype]],
703            [544, [revert_lst_literalparam]]
704           ]
705
706
707 if __name__ == "__main__":
708     pass