coreboot-v2/util/sconfig/parsedesc.g
<<
>>
Prefs
   1######################################################################
   2# The remainder of this file is from parsedesc.{g,py}
   3
   4def append(lst, x):
   5    "Imperative append"
   6    lst.append(x)
   7    return lst
   8
   9def add_inline_token(tokens, str):
  10    tokens.insert( 0, (str, eval(str, {}, {})) )
  11    return Terminal(str)
  12
  13def cleanup_choice(lst):
  14    if len(lst) == 0: return Sequence([])
  15    if len(lst) == 1: return lst[0]
  16    return apply(Choice, tuple(lst))
  17
  18def cleanup_sequence(lst):
  19    if len(lst) == 1: return lst[0]
  20    return apply(Sequence, tuple(lst))
  21
  22def cleanup_rep(node, rep):
  23    if rep == 'star':   return Star(node)
  24    elif rep == 'plus': return Plus(node)
  25    else:               return node
  26
  27def resolve_name(tokens, id, args):
  28    if id in map(lambda x: x[0], tokens):
  29        # It's a token
  30        if args: 
  31            print 'Warning: ignoring parameters on TOKEN %s<<%s>>' % (id, args)
  32        return Terminal(id)
  33    else:
  34        # It's a name, so assume it's a nonterminal
  35        return NonTerminal(id, args)
  36
  37%%
  38parser ParserDescription:
  39    option:      "context-insensitive-scanner"
  40
  41    ignore:      "[ \t\r\n]+"
  42    ignore:      "#.*?\r?\n"
  43    token END:   "$"
  44    token ATTR:  "<<.+?>>"
  45    token STMT:  "{{.+?}}"
  46    token ID:    '[a-zA-Z_][a-zA-Z_0-9]*'
  47    token STR:   '[rR]?\'([^\\n\'\\\\]|\\\\.)*\'|[rR]?"([^\\n"\\\\]|\\\\.)*"'
  48    token LP:    '\\('
  49    token RP:    '\\)'
  50    token LB:    '\\['
  51    token RB:    '\\]'
  52    token OR:    '[|]'
  53    token STAR:  '[*]'
  54    token PLUS:  '[+]'
  55    token QUEST: '[?]'
  56    token COLON: ':'
  57
  58    rule Parser: "parser" ID ":"
  59                   Options
  60                   Tokens
  61                   Rules<<Tokens>> 
  62                 END 
  63                 {{ return Generator(ID,Options,Tokens,Rules) }}
  64
  65    rule Options: {{ opt = {} }}
  66                  ( "option" ":" Str {{ opt[Str] = 1 }} )*
  67                  {{ return opt }}
  68
  69    rule Tokens:  {{ tok = [] }}
  70                  (
  71                    "token" ID ":" Str {{ tok.append( (ID,Str) ) }}
  72                  | "ignore"   ":" Str {{ tok.append( ('#ignore',Str) ) }}
  73                  )*
  74                  {{ return tok }}
  75
  76    rule Rules<<tokens>>:
  77                  {{ rul = [] }}
  78                  (
  79                    "rule" ID OptParam ":" ClauseA<<tokens>>
  80                    {{ rul.append( (ID,OptParam,ClauseA) ) }}
  81                  )*
  82                  {{ return rul }}
  83
  84    rule ClauseA<<tokens>>:
  85                  ClauseB<<tokens>>
  86                  {{ v = [ClauseB] }}
  87                  ( OR ClauseB<<tokens>> {{ v.append(ClauseB) }} )*
  88                  {{ return cleanup_choice(v) }}
  89
  90    rule ClauseB<<tokens>>:
  91                  {{ v = [] }}
  92                  ( ClauseC<<tokens>> {{ v.append(ClauseC) }} )*
  93                  {{ return cleanup_sequence(v) }}
  94
  95    rule ClauseC<<tokens>>:
  96                  ClauseD<<tokens>>
  97                  ( PLUS {{ return Plus(ClauseD) }}
  98                  | STAR {{ return Star(ClauseD) }}
  99                  |      {{ return ClauseD }} )
 100
 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]) }}
 109
 110    rule OptParam: [ ATTR {{ return ATTR[2:-2] }} ] {{ return '' }}
 111    rule Str:   STR {{ return eval(STR,{},{}) }}
 112%%
 113
 114# This replaces the default main routine
 115
 116yapps_options = [
 117    ('context-insensitive-scanner', 'context-insensitive-scanner',
 118     'Scan all tokens (see docs)')
 119    ]
 120
 121def 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)."""
 124
 125    if not outputfilename:
 126        if inputfilename[-2:]=='.g': outputfilename = inputfilename[:-2]+'.py'
 127        else: raise "Invalid Filename", outputfilename
 128        
 129    print '    SCONFIG   ', join(outputfilename.split('/')[-4:], '/')
 130    
 131    DIVIDER = '\n%%\n' # This pattern separates the pre/post parsers
 132    preparser, postparser = None, None # Code before and after the parser desc
 133
 134    # Read the entire file
 135    s = open(inputfilename,'r').read()
 136
 137    # See if there's a separation between the pre-parser and parser
 138    f = find(s, DIVIDER)
 139    if f >= 0: preparser, s = s[:f]+'\n\n', s[f+len(DIVIDER):]
 140
 141    # See if there's a separation between the parser and post-parser
 142    f = find(s, DIVIDER)
 143    if f >= 0: s, postparser = s[:f], '\n\n'+s[f+len(DIVIDER):]
 144
 145    # Create the parser and scanner
 146    p = ParserDescription(ParserDescriptionScanner(s))
 147    if not p: return
 148    
 149    # Now parse the file
 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
 154
 155    # Check the options
 156    for f in t.options.keys():
 157        for opt,_,_ in yapps_options:
 158            if f == opt: break
 159        else:
 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]
 163            
 164    # Generate the output
 165    if dump:
 166        t.dump_information()
 167    else:
 168        t.output = open(outputfilename, 'w')
 169        t.generate_output()
 170
 171if __name__=='__main__':
 172    import sys, getopt
 173    optlist, args = getopt.getopt(sys.argv[1:], 'f:', ['dump'])
 174    if not args or len(args) > 2:
 175        print 'Usage:'
 176        print '  python', sys.argv[0], '[flags] input.g [output.py]'
 177        print 'Flags:'
 178        print ('  --dump' + ' '*40)[:35] + 'Dump out grammar information'
 179        for flag, _, doc in yapps_options:
 180            print ('  -f' + flag + ' '*40)[:35] + doc
 181    else:
 182        # Read in the options and create a list of flags
 183        flags = {}
 184        for opt in optlist:
 185            for flag, name, _ in yapps_options:
 186                if opt == ('-f', flag):
 187                    flags[name] = 1
 188                    break
 189            else:
 190                if opt == ('--dump', ''):
 191                    flags['dump'] = 1
 192                else:
 193                    print 'Warning - unrecognized option:  ', opt[0], opt[1]
 194
 195        apply(generate, tuple(args), flags)
 196
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.