| 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))
|
|
|