Docs: authors.itexi: Add contributor.
[lilypond/mpolesky.git] / scripts / build / yyout2grammar.py
blobd46f648cd5fef2a9e94a7c587fe7b198b8c181f3
1 #!@PYTHON@
3 # yyout2grammar.py
5 # This file is part of LilyPond, the GNU music typesetter.
7 # Copyright (C) 2005 by Carl D. Sorensen <c_sorensen@byu.edu>
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.
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.
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/>.
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
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
40 import sys
41 import re
43 atre = re.compile('(@\d+):')
45 intro_re = re.compile (r'(.*[:|])\s')
46 keyword_re = re.compile (r'(\S+)\s')
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
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
79 write_me = True
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]
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')
92 at_items=[]
93 inline = in_file.readline()
95 ## skip header material from file
96 while inline != '' and not(inline.startswith("Grammar")):
97 inline = in_file.readline()
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):]
121 if write_me:
122 write_line(inline, out_file)
123 inline = in_file.readline()
124 write_me = True
125 index_items = []
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)
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)