| Index: src/trusted/validator_arm/dgen_input.py
|
| diff --git a/src/trusted/validator_arm/dgen_input.py b/src/trusted/validator_arm/dgen_input.py
|
| deleted file mode 100644
|
| index dad5a52c6324332e25a21055919411d3c0197bea..0000000000000000000000000000000000000000
|
| --- a/src/trusted/validator_arm/dgen_input.py
|
| +++ /dev/null
|
| @@ -1,316 +0,0 @@
|
| -#!/usr/bin/python
|
| -#
|
| -# Copyright (c) 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.
|
| -#
|
| -
|
| -"""
|
| -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 ::= table+ eof ;
|
| -
|
| -action ::= decoder_action arch | decoder_method | '"'
|
| -arch ::= '(' word+ ')'
|
| -citation ::= '(' word+ ')'
|
| -decoder_action ::= id (id (word (id)?)?)?
|
| -decoder_method ::= '->' id
|
| -footer ::= '+' '-' '-'
|
| -header ::= "|" (id '(' int (':' int)? ')')+
|
| -int ::= word (where word is a sequence of digits)
|
| -id ::= word (where word is sequence of letters, digits and _)
|
| -parenthesized_exp ::= '(' (word | punctuation)+ ')'
|
| -pattern ::= 'word' | '-' | '"'
|
| -row ::= '|' pattern+ action
|
| -table ::= table_desc header row+ footer
|
| -table_desc ::= '+' '-' '-' id citation?
|
| -
|
| -If a decoder_action has more than one element, the interpretation is as follows:
|
| - id[0] = action (plus optional architecture) to apply.
|
| - id[1] = Arm rule action corresponds to.
|
| - word = Bit pattern of rule.
|
| - id[3] = Name defining additional constraints for match.
|
| -"""
|
| -
|
| -import re
|
| -import dgen_core
|
| -
|
| -def parse_tables(input):
|
| - """Entry point for the parser. Input should be a file or file-like."""
|
| - parser = Parser()
|
| - return parser.parse(input)
|
| -
|
| -class Token(object):
|
| - """Holds a (characterized) unit of text for the parser."""
|
| -
|
| - def __init__(self, kind, value=None):
|
| - self.kind = kind
|
| - self.value = value if value else kind
|
| -
|
| -class Parser(object):
|
| - """Parses a set of tables from the input file."""
|
| -
|
| - def parse(self, input):
|
| - self.input = input # The remaining input to parse
|
| - decoder = dgen_core.Decoder() # The generated decoder of parse tables.
|
| - # Read tables while there.
|
| - while self._next_token().kind == '+':
|
| - self._table(decoder)
|
| -
|
| - if not self._next_token().kind == 'eof':
|
| - self._unexpected('unrecognized input found')
|
| - if not decoder.primary:
|
| - self._unexpected('No primary table defined')
|
| - if not decoder.tables():
|
| - self._unexpected('No tables defined')
|
| - return decoder
|
| -
|
| - def __init__(self):
|
| - self._words = [] # Words left on current line, not yet parsed.
|
| - self._line_no = 0 # The current line being parsed
|
| - self._token = None # The next token from the input.
|
| - self._reached_eof = False # True when end of file reached
|
| - # Punctuation allowed. Must be ordered such that if
|
| - # p1 != p2 are in the list, and p1.startswith(p2), then
|
| - # p1 must appear before p2.
|
| - self._punctuation = ['->', '-', '+', '(', ')', '=', ':', '"', '|']
|
| -
|
| - def _action(self, last_action, last_arch):
|
| - """ action ::= decoder_action arch | decoder_method | '"' """
|
| - if self._next_token().kind == '"':
|
| - self._read_token('"')
|
| - return (last_action, last_arch)
|
| - if self._next_token().kind == '=':
|
| - action = self._decoder_action()
|
| - arch = None
|
| - if self._next_token().kind == '(':
|
| - arch = self._arch()
|
| - return (action, arch)
|
| - elif self._next_token().kind == '->':
|
| - return (self._decoder_method(), None)
|
| - else:
|
| - self._unexpected("Row doesn't define an action")
|
| -
|
| - def _pattern(self, col_no, last_patterns, last_action, last_arch):
|
| - pass
|
| -
|
| - def _arch(self):
|
| - """ arch ::= '(' word+ ')' """
|
| - return ' '.join(self._parenthesized_exp())
|
| -
|
| - def _citation(self):
|
| - """ citation ::= '(' word+ ')' """
|
| - return ' '.join(self._parenthesized_exp())
|
| -
|
| - def _read_id_or_none(self, read_id):
|
| - if self._next_token().kind in ['|', '+', '(']:
|
| - return None
|
| - id = self._id() if read_id else self._read_token('word').value
|
| - return None if id and id == 'None' else id
|
| -
|
| - def _decoder_action(self):
|
| - """ decoder_action ::= id (id (word (id)?)?)? """
|
| - self._read_token('=')
|
| - name = self._read_id_or_none(True)
|
| - rule = self._read_id_or_none(True)
|
| - pattern = self._read_id_or_none(False)
|
| - constraints = self._read_id_or_none(True)
|
| - return dgen_core.DecoderAction(name, rule, pattern, constraints)
|
| -
|
| - def _decoder_method(self):
|
| - """ decoder_method ::= '->' id """
|
| - self._read_token('->')
|
| - name = self._id()
|
| - return dgen_core.DecoderMethod(name)
|
| -
|
| - def _footer(self):
|
| - """ footer ::= '+' '-' '-' """
|
| - self._read_token('+')
|
| - self._read_token('-')
|
| - self._read_token('-')
|
| -
|
| - def _header(self, table):
|
| - """ header ::= "|" (id '(' int (':' int)? ')')+ """
|
| - self._read_token('|')
|
| - while not self._next_token().kind == '|':
|
| - name = self._read_token('word').value
|
| - self._read_token('(')
|
| - hi_bit = self._int()
|
| - lo_bit = hi_bit
|
| - if self._next_token().kind == ':':
|
| - self._read_token(':')
|
| - lo_bit = self._int()
|
| - self._read_token(')')
|
| - table.add_column(name, hi_bit, lo_bit)
|
| -
|
| - def _int(self):
|
| - """ int ::= word
|
| -
|
| - Int is a sequence of digits. Returns the corresponding integer.
|
| - """
|
| - word = self._read_token('word').value
|
| - m = re.match(r'^([0-9]+)$', word)
|
| - if m:
|
| - return int(word)
|
| - else:
|
| - self._unexpected('integer expected but found "%s"' % word)
|
| -
|
| - def _id(self):
|
| - """ id ::= word
|
| -
|
| - Word starts with a letter, and followed by letters, digits,
|
| - and underscores. Returns the corresponding identifier.
|
| - """
|
| - ident = self._read_token('word').value
|
| - m = re.match(r'^[a-zA-z][a-zA-z0-9_]*$', ident)
|
| - if not m:
|
| - self._unexpected('"%s" is not a valid identifier' % ident)
|
| - return ident
|
| -
|
| - def _parenthesized_exp(self, minlength=1):
|
| - """ parenthesized_exp ::= '(' (word | punctuation)+ ')'
|
| -
|
| - The punctuation doesn't include ')'.
|
| - Returns the sequence of token values parsed.
|
| - """
|
| - self._read_token('(')
|
| - words = []
|
| - while not self._at_eof() and self._next_token().kind != ')':
|
| - words.append(self._read_token().value)
|
| - if len(words) < minlength:
|
| - self._unexpected("len(parenthesized expresssion) < %s" % minlength)
|
| - self._read_token(')')
|
| - return words
|
| -
|
| - def _pattern(self, last_pattern):
|
| - """ pattern ::= 'word' | '-' | '"'
|
| -
|
| - Arguments are:
|
| - col_no - The current column entry being read.
|
| - last_patterns - The list of patterns defined on the last row.
|
| - last_action - The action defined on the last row.
|
| - last_arch - The architecture defined on the last row..
|
| - """
|
| - if self._next_token().kind == '"':
|
| - self._read_token('"')
|
| - return last_pattern
|
| - if self._next_token().kind in ['-', 'word']:
|
| - return self._read_token().value
|
| - self._unexpected('Malformed pattern')
|
| -
|
| - def _row(self, table, last_patterns=None,
|
| - last_action=None, last_arch= None):
|
| - """ row ::= '|' pattern+ (decoder_action arch? | decoder_method)?
|
| -
|
| - Passed in sequence of patterns and action from last row,
|
| - and returns list of patterns and action from this row.
|
| - """
|
| - patterns = [] # Patterns as found on input.
|
| - expanded_patterns = [] # Patterns after being expanded.
|
| - self._read_token('|')
|
| - num_patterns = 0
|
| - num_patterns_last = len(last_patterns) if last_patterns else None
|
| - while self._next_token().kind not in ['=', '->', '|', '+']:
|
| - if not last_patterns or num_patterns < num_patterns_last:
|
| - last_pattern = last_patterns[num_patterns] if last_patterns else None
|
| - pattern = self._pattern(last_pattern)
|
| - patterns.append(pattern)
|
| - expanded_patterns.append(table.define_pattern(pattern, num_patterns))
|
| - num_patterns += 1
|
| - else:
|
| - # Processed patterns in this row, since width is now the
|
| - # same as last row.
|
| - break;
|
| -
|
| - (action, arch) = self._action(last_action, last_arch)
|
| - table.add_row(expanded_patterns, action, arch)
|
| - return (patterns, action, arch)
|
| -
|
| - def _table(self, decoder):
|
| - """ table ::= table_desc header row+ footer """
|
| - table = self._table_desc()
|
| - print 'Reading table %s...' % table.name
|
| - self._header(table)
|
| - (pattern, action, arch) = self._row(table)
|
| - while not self._next_token().kind == '+':
|
| - (pattern, action, arch) = self._row(table, pattern, action, arch)
|
| - if not decoder.add(table):
|
| - self._unexpected('Multiple tables with name %s' % table.name)
|
| - self._footer()
|
| -
|
| - def _table_desc(self):
|
| - """ table_desc ::= '+' '-' '-' id citation? """
|
| - self._read_token('+')
|
| - self._read_token('-')
|
| - self._read_token('-')
|
| - name = self._id()
|
| - citation = None
|
| - if self._next_token().kind == '(':
|
| - citation = self._citation()
|
| - return dgen_core.Table(name, citation)
|
| -
|
| - def _at_eof(self):
|
| - """Returns true if next token is the eof token."""
|
| - return self._next_token().kind == 'eof'
|
| -
|
| - def _read_token(self, kind=None):
|
| - """Reads and returns the next token from input."""
|
| - token = self._next_token()
|
| - self._token = None
|
| - if kind and kind != token.kind:
|
| - self._unexpected('Expected "%s" but found "%s"'
|
| - % (kind, token.kind))
|
| - return token
|
| -
|
| - def _next_token(self):
|
| - """Returns the next token from the input."""
|
| - # First seee if cached.
|
| - if self._token: return self._token
|
| -
|
| - # If no more tokens left on the current line. read
|
| - # input till more tokens are found
|
| - while not self._reached_eof and not self._words:
|
| - self._words = self._read_line().split()
|
| -
|
| - if self._words:
|
| - # More tokens found. Convert the first word to a token.
|
| - word = self._words.pop(0)
|
| - # First remove any applicable punctuation.
|
| - for p in self._punctuation:
|
| - index = word.find(p)
|
| - if index == 0:
|
| - # Found punctuation, return it.
|
| - self._pushback(word[len(p):])
|
| - self._token = Token(p)
|
| - return self._token
|
| - elif index > 0:
|
| - self._pushback(word[index:])
|
| - word = word[:index]
|
| - # if reached, word doesn't contain any punctuation, so return it.
|
| - self._token = Token('word', word)
|
| - else:
|
| - # No more tokens found, assume eof.
|
| - self._token = Token('eof')
|
| - return self._token
|
| -
|
| - def _pushback(self, word):
|
| - """Puts word back onto the list of words."""
|
| - if word:
|
| - self._words.insert(0, word)
|
| -
|
| - def _read_line(self):
|
| - """Reads the next line of input, and returns it. Otherwise None."""
|
| - self._line_no += 1
|
| - line = self.input.readline()
|
| - if line:
|
| - return re.sub(r'#.*', '', line).strip()
|
| - else:
|
| - self._reached_eof = True
|
| - return ''
|
| -
|
| - def _unexpected(self, context='Unexpected line in input'):
|
| - """"Reports that we didn't find the expected context. """
|
| - raise Exception('Line %d: %s' % (self._line_no, context))
|
|
|