]> git.donarmstrong.com Git - lilypond.git/blob - scripts/build/yyout2grammar.py
Merge remote-tracking branch 'origin/stable/2.16' into translation
[lilypond.git] / scripts / build / yyout2grammar.py
1 #!@PYTHON@
2 #
3 #  yyout2grammar.py
4
5 # This file is part of LilyPond, the GNU music typesetter.
6 #
7 # Copyright (C) 2005 by Carl D. Sorensen <c_sorensen@byu.edu>
8 #
9 # LilyPond is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # LilyPond is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
21
22
23 #  Convert from bison output file parser.output to
24 #  Grammar and index.
25 #  Drops all of the state information.
26 #  Converts \\ to \
27 #  Eliminates the @ variables created when {} is placed
28 #        in the middle of a rule
29 #  Eliminates all of the c-code stuff
30 #  Wraps lines that are longer than 78 characters for improved
31 #        formatting
32 #
33 # to create input file, run
34 #   bison -v parser.yy
35 # this will create a file parser.output
36 # then run
37 #   yyout2grammar.py parser.output your_output_file
38 #
39
40 import sys
41 import re
42
43 atre = re.compile('(@\d+):')
44
45 intro_re = re.compile (r'(.*[:|])\s')
46 keyword_re = re.compile (r'(\S+)\s')
47
48 # strip extra backslashes that are inserted by the python
49 # string handling routines
50 def strip_backslash(input_string):
51     i=input_string.find(r'"\\')
52     while i > -1 :
53         input_string = input_string[:i+1]+input_string[i+2:]
54         i = input_string.find(r'"\\')
55     return  input_string
56
57 #  write an output line, adjusting to make sure that max_line_length
58 #  is not exceeded
59 def write_line (output_line, output_file):
60     max_line_length = 78
61     indent_value = 3
62     if len(output_line) > max_line_length:
63         intro = intro_re.match(output_line)
64         if intro:
65             output_file.write(intro.group(1)+" ")
66             indent_column = len(intro.group(1))
67             output_line = output_line[indent_column:]
68             keyword = keyword_re.search(output_line)
69             while keyword:
70                 output_file.write(strip_backslash(keyword.group(1))+" \n")
71                 output_line = output_line[keyword.end(1):]
72                 keyword = keyword_re.search(output_line)
73                 if keyword:
74                     output_file.write("".rjust(indent_column + indent_value))
75     else:
76         output_file.write(strip_backslash(output_line))
77     return
78
79 write_me = True
80
81 if len(sys.argv)!=3:
82     print "Usage: yyout2grammar.py parser_output_file grammar_file."
83 else:
84     in_name = sys.argv[1]
85     out_name = sys.argv[2]
86
87     print "input file name",in_name
88     print "output file name",out_name
89     in_file = open(in_name,'r')
90     out_file= open(out_name, 'w')
91
92     at_items=[]
93     inline = in_file.readline()
94
95     ## skip header material from file
96     while inline != '' and not(inline.startswith("Grammar")):
97         inline = in_file.readline()
98
99     ## process the Grammar lines
100     if inline != '':
101         write_line(inline, out_file)
102         inline = in_file.readline()
103         while inline != '' and not(inline.startswith("Terminals")):
104             i = inline.find("$accept:")
105             if i>-1:
106                 write_me = False
107                 inline = in_file.readline()
108             atfound = re.findall(atre,inline)
109             if len(atfound) > 0:
110                 at_items.extend(atfound)
111                 #  print at_items
112                 write_me = False
113                 inline=in_file.readline()
114             else:
115                 for at_item in at_items:
116                     i=inline.find(at_item)
117                     ## remove @ item
118                     if i >= 0:
119                         inline=inline[:i] + inline[i+len(at_item):]
120
121             if write_me:
122                 write_line(inline, out_file)
123             inline = in_file.readline()
124             write_me = True
125     index_items = []
126
127     #  Write the Terminals header line and the following blank line
128     write_line(inline, out_file)
129     inline = in_file.readline()
130     write_line(inline, out_file)
131     inline = in_file.readline()
132     while inline != '' and not(inline.startswith("Nonterminals")):
133         i=inline.find('"\\\\')
134         while i > -1 :
135             inline = inline[:i+1]+inline[i+2:]
136             i = inline.find('"\\\\')
137         index_items.append(inline)
138         inline = in_file.readline()
139     index_items.sort(lambda x,y:cmp(x.lower(),y.lower()))
140     for index_item in index_items:
141         write_line (index_item, out_file)
142     write_line ('\n', out_file)
143
144     # Write the Nonterminals header and the blank line
145     write_line(inline, out_file)
146     inline = in_file.readline()
147     write_line(inline, out_file)
148     index_items = []
149     index_item=in_file.readline()
150     inline=in_file.readline()
151     while inline != '' and not(inline.startswith("state")):
152         while inline.startswith("    "):
153             index_item = index_item + inline
154             inline = in_file.readline()
155         if not(index_item.startswith("@")) and \
156                not(index_item.startswith("$accept")):
157             index_items.append(index_item)
158         index_item = inline
159         inline=in_file.readline()
160     index_items.sort(lambda x,y:cmp(x.lower(),y.lower()))
161     for index_item in index_items:
162         write_line (index_item, out_file)