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
25 # Drops all of the state information.
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
33 # to create input file, run
35 # this will create a file parser.output
37 # yyout2grammar.py parser.output your_output_file
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
'"\\')
53 input_string
= input_string
[:i
+1]+input_string
[i
+2:]
54 i
= input_string
.find(r
'"\\')
57 # write an output line, adjusting to make sure that max_line_length
59 def write_line (output_line
, output_file
):
62 if len(output_line
) > max_line_length
:
63 intro
= intro_re
.match(output_line
)
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
)
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
)
74 output_file
.write("".rjust(indent_column
+ indent_value
))
76 output_file
.write(strip_backslash(output_line
))
82 print "Usage: yyout2grammar.py parser_output_file grammar_file."
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')
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
101 write_line(inline
, out_file
)
102 inline
= in_file
.readline()
103 while inline
!= '' and not(inline
.startswith("Terminals")):
104 i
= inline
.find("$accept:")
107 inline
= in_file
.readline()
108 atfound
= re
.findall(atre
,inline
)
110 at_items
.extend(atfound
)
113 inline
=in_file
.readline()
115 for at_item
in at_items
:
116 i
=inline
.find(at_item
)
119 inline
=inline
[:i
] + inline
[i
+len(at_item
):]
122 write_line(inline
, out_file
)
123 inline
= in_file
.readline()
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('"\\\\')
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
)
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
)
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
)