new config tool
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@878 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
196
util/newconfig/parsedesc.g
Normal file
196
util/newconfig/parsedesc.g
Normal file
@@ -0,0 +1,196 @@
|
||||
######################################################################
|
||||
# The remainder of this file is from parsedesc.{g,py}
|
||||
|
||||
def append(lst, x):
|
||||
"Imperative append"
|
||||
lst.append(x)
|
||||
return lst
|
||||
|
||||
def add_inline_token(tokens, str):
|
||||
tokens.insert( 0, (str, eval(str, {}, {})) )
|
||||
return Terminal(str)
|
||||
|
||||
def cleanup_choice(lst):
|
||||
if len(lst) == 0: return Sequence([])
|
||||
if len(lst) == 1: return lst[0]
|
||||
return apply(Choice, tuple(lst))
|
||||
|
||||
def cleanup_sequence(lst):
|
||||
if len(lst) == 1: return lst[0]
|
||||
return apply(Sequence, tuple(lst))
|
||||
|
||||
def cleanup_rep(node, rep):
|
||||
if rep == 'star': return Star(node)
|
||||
elif rep == 'plus': return Plus(node)
|
||||
else: return node
|
||||
|
||||
def resolve_name(tokens, id, args):
|
||||
if id in map(lambda x: x[0], tokens):
|
||||
# It's a token
|
||||
if args:
|
||||
print 'Warning: ignoring parameters on TOKEN %s<<%s>>' % (id, args)
|
||||
return Terminal(id)
|
||||
else:
|
||||
# It's a name, so assume it's a nonterminal
|
||||
return NonTerminal(id, args)
|
||||
|
||||
%%
|
||||
parser ParserDescription:
|
||||
option: "context-insensitive-scanner"
|
||||
|
||||
ignore: "[ \t\r\n]+"
|
||||
ignore: "#.*?\r?\n"
|
||||
token END: "$"
|
||||
token ATTR: "<<.+?>>"
|
||||
token STMT: "{{.+?}}"
|
||||
token ID: '[a-zA-Z_][a-zA-Z_0-9]*'
|
||||
token STR: '[rR]?\'([^\\n\'\\\\]|\\\\.)*\'|[rR]?"([^\\n"\\\\]|\\\\.)*"'
|
||||
token LP: '\\('
|
||||
token RP: '\\)'
|
||||
token LB: '\\['
|
||||
token RB: '\\]'
|
||||
token OR: '[|]'
|
||||
token STAR: '[*]'
|
||||
token PLUS: '[+]'
|
||||
token QUEST: '[?]'
|
||||
token COLON: ':'
|
||||
|
||||
rule Parser: "parser" ID ":"
|
||||
Options
|
||||
Tokens
|
||||
Rules<<Tokens>>
|
||||
END
|
||||
{{ return Generator(ID,Options,Tokens,Rules) }}
|
||||
|
||||
rule Options: {{ opt = {} }}
|
||||
( "option" ":" Str {{ opt[Str] = 1 }} )*
|
||||
{{ return opt }}
|
||||
|
||||
rule Tokens: {{ tok = [] }}
|
||||
(
|
||||
"token" ID ":" Str {{ tok.append( (ID,Str) ) }}
|
||||
| "ignore" ":" Str {{ tok.append( ('#ignore',Str) ) }}
|
||||
)*
|
||||
{{ return tok }}
|
||||
|
||||
rule Rules<<tokens>>:
|
||||
{{ rul = [] }}
|
||||
(
|
||||
"rule" ID OptParam ":" ClauseA<<tokens>>
|
||||
{{ rul.append( (ID,OptParam,ClauseA) ) }}
|
||||
)*
|
||||
{{ return rul }}
|
||||
|
||||
rule ClauseA<<tokens>>:
|
||||
ClauseB<<tokens>>
|
||||
{{ v = [ClauseB] }}
|
||||
( OR ClauseB<<tokens>> {{ v.append(ClauseB) }} )*
|
||||
{{ return cleanup_choice(v) }}
|
||||
|
||||
rule ClauseB<<tokens>>:
|
||||
{{ v = [] }}
|
||||
( ClauseC<<tokens>> {{ v.append(ClauseC) }} )*
|
||||
{{ return cleanup_sequence(v) }}
|
||||
|
||||
rule ClauseC<<tokens>>:
|
||||
ClauseD<<tokens>>
|
||||
( PLUS {{ return Plus(ClauseD) }}
|
||||
| STAR {{ return Star(ClauseD) }}
|
||||
| {{ return ClauseD }} )
|
||||
|
||||
rule ClauseD<<tokens>>:
|
||||
STR {{ t = (STR, eval(STR,{},{})) }}
|
||||
{{ if t not in tokens: tokens.insert( 0, t ) }}
|
||||
{{ return Terminal(STR) }}
|
||||
| ID OptParam {{ return resolve_name(tokens, ID, OptParam) }}
|
||||
| LP ClauseA<<tokens>> RP {{ return ClauseA }}
|
||||
| LB ClauseA<<tokens>> RB {{ return Option(ClauseA) }}
|
||||
| STMT {{ return Eval(STMT[2:-2]) }}
|
||||
|
||||
rule OptParam: [ ATTR {{ return ATTR[2:-2] }} ] {{ return '' }}
|
||||
rule Str: STR {{ return eval(STR,{},{}) }}
|
||||
%%
|
||||
|
||||
# This replaces the default main routine
|
||||
|
||||
yapps_options = [
|
||||
('context-insensitive-scanner', 'context-insensitive-scanner',
|
||||
'Scan all tokens (see docs)')
|
||||
]
|
||||
|
||||
def generate(inputfilename, outputfilename='', dump=0, **flags):
|
||||
"""Generate a grammar, given an input filename (X.g)
|
||||
and an output filename (defaulting to X.py)."""
|
||||
|
||||
if not outputfilename:
|
||||
if inputfilename[-2:]=='.g': outputfilename = inputfilename[:-2]+'.py'
|
||||
else: raise "Invalid Filename", outputfilename
|
||||
|
||||
print 'Input Grammar:', inputfilename
|
||||
print 'Output File:', outputfilename
|
||||
|
||||
DIVIDER = '\n%%\n' # This pattern separates the pre/post parsers
|
||||
preparser, postparser = None, None # Code before and after the parser desc
|
||||
|
||||
# Read the entire file
|
||||
s = open(inputfilename,'r').read()
|
||||
|
||||
# See if there's a separation between the pre-parser and parser
|
||||
f = find(s, DIVIDER)
|
||||
if f >= 0: preparser, s = s[:f]+'\n\n', s[f+len(DIVIDER):]
|
||||
|
||||
# See if there's a separation between the parser and post-parser
|
||||
f = find(s, DIVIDER)
|
||||
if f >= 0: s, postparser = s[:f], '\n\n'+s[f+len(DIVIDER):]
|
||||
|
||||
# Create the parser and scanner
|
||||
p = ParserDescription(ParserDescriptionScanner(s))
|
||||
if not p: return
|
||||
|
||||
# Now parse the file
|
||||
t = wrap_error_reporter(p, 'Parser')
|
||||
if not t: return # Error
|
||||
if preparser is not None: t.preparser = preparser
|
||||
if postparser is not None: t.postparser = postparser
|
||||
|
||||
# Check the options
|
||||
for f in t.options.keys():
|
||||
for opt,_,_ in yapps_options:
|
||||
if f == opt: break
|
||||
else:
|
||||
print 'Warning: unrecognized option', f
|
||||
# Add command line options to the set
|
||||
for f in flags.keys(): t.options[f] = flags[f]
|
||||
|
||||
# Generate the output
|
||||
if dump:
|
||||
t.dump_information()
|
||||
else:
|
||||
t.output = open(outputfilename, 'w')
|
||||
t.generate_output()
|
||||
|
||||
if __name__=='__main__':
|
||||
import sys, getopt
|
||||
optlist, args = getopt.getopt(sys.argv[1:], 'f:', ['dump'])
|
||||
if not args or len(args) > 2:
|
||||
print 'Usage:'
|
||||
print ' python', sys.argv[0], '[flags] input.g [output.py]'
|
||||
print 'Flags:'
|
||||
print (' --dump' + ' '*40)[:35] + 'Dump out grammar information'
|
||||
for flag, _, doc in yapps_options:
|
||||
print (' -f' + flag + ' '*40)[:35] + doc
|
||||
else:
|
||||
# Read in the options and create a list of flags
|
||||
flags = {}
|
||||
for opt in optlist:
|
||||
for flag, name, _ in yapps_options:
|
||||
if opt == ('-f', flag):
|
||||
flags[name] = 1
|
||||
break
|
||||
else:
|
||||
if opt == ('--dump', ''):
|
||||
flags['dump'] = 1
|
||||
else:
|
||||
print 'Warning - unrecognized option: ', opt[0], opt[1]
|
||||
|
||||
apply(generate, tuple(args), flags)
|
Reference in New Issue
Block a user