| Index: src/trusted/validator_mips/dgen/dgen_input.py | 
| diff --git a/src/trusted/validator_mips/dgen/dgen_input.py b/src/trusted/validator_mips/dgen/dgen_input.py | 
| new file mode 100755 | 
| index 0000000000000000000000000000000000000000..40788410b5f57240c1cdaa449d3afa7d231efe47 | 
| --- /dev/null | 
| +++ b/src/trusted/validator_mips/dgen/dgen_input.py | 
| @@ -0,0 +1,127 @@ | 
| +#!/usr/bin/python | 
| +# | 
| +# Copyright 2012 The Native Client Authors.  All rights reserved. | 
| +# Use of this source code is governed by a BSD-style license that can | 
| +# be found in the LICENSE file. | 
| +# Copyright 2012, Google Inc. | 
| +# | 
| + | 
| +""" | 
| +A simple recursive-descent parser for the table file format. | 
| + | 
| +The grammar implemented here is roughly (taking some liberties with whitespace | 
| +and comment parsing): | 
| + | 
| +table_file ::= ( BLANK_LINE | table_def ) end_of_file ; | 
| +table_def ::= "--" IDENT CITATION NL | 
| +    table_header | 
| +    ( table_row )+ ; | 
| +table_header ::= ( IDENT "(" BITRANGE ")" )+ ; | 
| +table_row ::= ( PATTERN )+ ACTION ; | 
| + | 
| +IDENT = /[a-z0-9_]+/ | 
| +CITATION = "(" /[^)]+/ ")" | 
| +BITRANGE = /[0-9]+/ (":" /[0-9]+/)? | 
| +PATTERN = /[10x_]+/ | 
| +ACTION = ( "=" IDENT | "->" IDENT ) ( "(" IDENT ")" )? | 
| +NL = a newline | 
| +BLANK_LINE = what you might expect it to be | 
| +""" | 
| + | 
| +import re | 
| +import dgen_core | 
| + | 
| +# These globals track the parser state. | 
| +_in = None | 
| +_line_no = None | 
| +_tables = None | 
| +_line = None | 
| +_last_row = None | 
| + | 
| + | 
| +def parse_tables(input): | 
| +    """Entry point for the parser.  Input should be a file or file-like.""" | 
| +    global _in, _line_no, _tables | 
| +    _in = input | 
| +    _line_no = 0 | 
| +    _tables = [] | 
| +    next_line() | 
| + | 
| +    while not end_of_file(): | 
| +        blank_line() or table_def() or unexpected() | 
| + | 
| +    return _tables | 
| + | 
| + | 
| +def blank_line(): | 
| +    if _line: | 
| +        return False | 
| + | 
| +    next_line(); | 
| +    return True | 
| + | 
| + | 
| +def table_def(): | 
| +    global _last_row | 
| + | 
| +    m = re.match(r'^-- ([^ ]+) \(([^)]+)\)', _line) | 
| +    if not m: return False | 
| + | 
| +    table = dgen_core.Table(m.group(1), m.group(2)) | 
| +    next_line() | 
| +    while blank_line(): pass | 
| + | 
| +    table_header(table) | 
| +    _last_row = None | 
| +    while not end_of_file() and not blank_line(): | 
| +        table_row(table) | 
| + | 
| +    _tables.append(table) | 
| +    return True | 
| + | 
| + | 
| +def table_header(table): | 
| +    for col in _line.split(): | 
| +        m = re.match(r'^([a-z0-9_]+)\(([0-9]+)(:([0-9]+))?\)$', col, re.I) | 
| +        if not m: raise Exception('Invalid column header: %s' % col) | 
| + | 
| +        hi_bit = int(m.group(2)) | 
| +        if m.group(4): | 
| +            lo_bit = int(m.group(4)) | 
| +        else: | 
| +            lo_bit = hi_bit | 
| +        table.add_column(m.group(1), hi_bit, lo_bit) | 
| +    next_line() | 
| + | 
| + | 
| +def table_row(table): | 
| +    global _last_row | 
| + | 
| +    row = _line.split() | 
| +    for i in range(0, len(row)): | 
| +        if row[i] == '"': row[i] = _last_row[i] | 
| +    _last_row = row | 
| + | 
| +    action = row[-1] | 
| +    patterns = row[:-1] | 
| +    table.add_row(patterns, action) | 
| +    next_line() | 
| + | 
| + | 
| +def end_of_file(): | 
| +    return _line is None | 
| + | 
| + | 
| +def next_line(): | 
| +    global _line_no, _line | 
| + | 
| +    _line_no += 1 | 
| +    _line = _in.readline() | 
| +    if _line: | 
| +        _line = re.sub(r'#.*', '', _line).strip() | 
| +    else: | 
| +        _line = None | 
| + | 
| + | 
| +def unexpected(): | 
| +    raise Exception('Line %d: Unexpected line in input: %s' % (_line_no, _line)) | 
|  |