1 ######################################################################
2 # The remainder of this file is from parsedesc.{g,py}
9 def add_inline_token(tokens, str):
10 tokens.insert( 0, (str, eval(str, {}, {})) )
13 def cleanup_choice(lst):
14 if len(lst) == 0: return Sequence([])
15 if len(lst) == 1: return lst[0]
16 return apply(Choice, tuple(lst))
18 def cleanup_sequence(lst):
19 if len(lst) == 1: return lst[0]
20 return apply(Sequence, tuple(lst))
22 def cleanup_rep(node, rep):
23 if rep == 'star': return Star(node)
24 elif rep == 'plus': return Plus(node)
27 def resolve_name(tokens, id, args):
28 if id in map(lambda x: x[0], tokens):
31 print 'Warning: ignoring parameters on TOKEN %s<<%s>>' % (id, args)
34 # It's a name, so assume it's a nonterminal
35 return NonTerminal(id, args)
38 parser ParserDescription:
39 option: "context-insensitive-scanner"
46 token ID: '[a-zA-Z_][a-zA-Z_0-9]*'
47 token STR: '[rR]?\'([^\\n\'\\\\]|\\\\.)*\'|[rR]?"([^\\n"\\\\]|\\\\.)*"'
58 rule Parser: "parser" ID ":"
63 {{ return Generator(ID,Options,Tokens,Rules) }}
65 rule Options: {{ opt = {} }}
66 ( "option" ":" Str {{ opt[Str] = 1 }} )*
69 rule Tokens: {{ tok = [] }}
71 "token" ID ":" Str {{ tok.append( (ID,Str) ) }}
72 | "ignore" ":" Str {{ tok.append( ('#ignore',Str) ) }}
79 "rule" ID OptParam ":" ClauseA<<tokens>>
80 {{ rul.append( (ID,OptParam,ClauseA) ) }}
84 rule ClauseA<<tokens>>:
87 ( OR ClauseB<<tokens>> {{ v.append(ClauseB) }} )*
88 {{ return cleanup_choice(v) }}
90 rule ClauseB<<tokens>>:
92 ( ClauseC<<tokens>> {{ v.append(ClauseC) }} )*
93 {{ return cleanup_sequence(v) }}
95 rule ClauseC<<tokens>>:
97 ( PLUS {{ return Plus(ClauseD) }}
98 | STAR {{ return Star(ClauseD) }}
99 | {{ return ClauseD }} )
101 rule ClauseD<<tokens>>:
102 STR {{ t = (STR, eval(STR,{},{})) }}
103 {{ if t not in tokens: tokens.insert( 0, t ) }}
104 {{ return Terminal(STR) }}
105 | ID OptParam {{ return resolve_name(tokens, ID, OptParam) }}
106 | LP ClauseA<<tokens>> RP {{ return ClauseA }}
107 | LB ClauseA<<tokens>> RB {{ return Option(ClauseA) }}
108 | STMT {{ return Eval(STMT[2:-2]) }}
110 rule OptParam: [ ATTR {{ return ATTR[2:-2] }} ] {{ return '' }}
111 rule Str: STR {{ return eval(STR,{},{}) }}
114 # This replaces the default main routine
117 ('context-insensitive-scanner', 'context-insensitive-scanner',
118 'Scan all tokens (see docs)')
121 def generate(inputfilename, outputfilename='', dump=0, **flags):
122 """Generate a grammar, given an input filename (X.g)
123 and an output filename (defaulting to X.py)."""
125 if not outputfilename:
126 if inputfilename[-2:]=='.g': outputfilename = inputfilename[:-2]+'.py'
127 else: raise "Invalid Filename", outputfilename
129 print ' SCONFIG ', join(outputfilename.split('/')[-5:], '/')
131 DIVIDER = '\n%%\n' # This pattern separates the pre/post parsers
132 preparser, postparser = None, None # Code before and after the parser desc
134 # Read the entire file
135 s = open(inputfilename,'r').read()
137 # See if there's a separation between the pre-parser and parser
139 if f >= 0: preparser, s = s[:f]+'\n\n', s[f+len(DIVIDER):]
141 # See if there's a separation between the parser and post-parser
143 if f >= 0: s, postparser = s[:f], '\n\n'+s[f+len(DIVIDER):]
145 # Create the parser and scanner
146 p = ParserDescription(ParserDescriptionScanner(s))
150 t = wrap_error_reporter(p, 'Parser')
151 if not t: return # Error
152 if preparser is not None: t.preparser = preparser
153 if postparser is not None: t.postparser = postparser
156 for f in t.options.keys():
157 for opt,_,_ in yapps_options:
160 print 'Warning: unrecognized option', f
161 # Add command line options to the set
162 for f in flags.keys(): t.options[f] = flags[f]
164 # Generate the output
168 t.output = open(outputfilename, 'w')
171 if __name__=='__main__':
173 optlist, args = getopt.getopt(sys.argv[1:], 'f:', ['dump'])
174 if not args or len(args) > 2:
176 print ' python', sys.argv[0], '[flags] input.g [output.py]'
178 print (' --dump' + ' '*40)[:35] + 'Dump out grammar information'
179 for flag, _, doc in yapps_options:
180 print (' -f' + flag + ' '*40)[:35] + doc
182 # Read in the options and create a list of flags
185 for flag, name, _ in yapps_options:
186 if opt == ('-f', flag):
190 if opt == ('--dump', ''):
193 print 'Warning - unrecognized option: ', opt[0], opt[1]
195 apply(generate, tuple(args), flags)