Homework 4. C Type Equivalence

Motivation

In the C language, there are often several different ways to write the same type. For example, the following two types are equivalent:

  int const unsigned * const volatile
  const unsigned int * volatile const

Write a Prolog predicate same_c_type(A, B) that succeeds if A and B are Prolog lists of C keywords and tokens that represent the same C type. For example, the goal:

same_c_type([int, const, unsigned, *, const, volatile],
	      [const, unsigned, int, *, volatile, const])

should succeed. Use the Prolog atoms '(' and ')' to represent C parentheses.

You may assume that the first argument of same_c_type/2 is a ground term, i.e., that it does not contain any logical variables. However, the second argument can contain logical variables, and if it does then same_c_type/2 should backtrack through all solutions. For example, same_c_type([unsigned,const,*], T) should backtrack through all possible solutions for T. The behavior should be something like the following.

| ?- same_c_type([unsigned,const,*], T).
T = [const,int,unsigned,*] ? ;
T = [const,unsigned,*] ? ;
T = [const,unsigned,int,*] ? ;
T = [int,const,unsigned,*] ? ;
T = [int,unsigned,const,*] ? ;
T = [unsigned,const,*] ? ;
T = [unsigned,const,int,*] ? ;
T = [unsigned,int,const,*] ? ;
T = [const,int,unsigned,'(',*,')'] ? ;
T = [const,unsigned,'(',*,')'] ?
yes

Note that the user got tired of seeing more answers here; there are actually an infinite number of answers. The order that solutions are backtracked through is not important, so long as all the correct solutions are backtracked through, and so long as the same solution isn't generated more than once.

For the purpose of this assignment, limit yourself to the following subset of the full C grammar for type names:

type-name:
type-specifier-group abstract-declaratoropt
type-specifier-group:
specifier-qualifier-listopt type-specifier specifier-qualifier-listopt
specifier-qualifier-list:
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt
type-specifier:
void
char
short
int
long
float
double
signed
unsigned
bool
complex
imaginary
type-qualifier:
const
restrict
volatile
abstract-declarator:
pointer
pointeropt ( abstract-declarator )
pointer:
* type-qualifier-listopt pointeropt
type-qualifier-list:
type-qualifier
type-qualifier-list type-qualifier

In this grammar, nonterminals are in italics, whereas keywords and other symbols are in sample case. The "opt" subscript means the preceding nonterminal is optional. Alternatives are listed on separate lines.

Two pointer types are equivalent if they have the same qualifiers and both point to equivalent types. For example, int const * const volatile is equivalent to const int * volatile const.

Parenthesization of abstract declarators does not affect the resulting type. For example, int * (**) and int ** (*) are both equivalent to int ***.

The order that keywords appear within a type specifier group or type qualifier list does not affect the resulting type. For example, int const unsigned is equivalent to unsigned int const.

A type specifier group's type specifiers must be one of the following. The order of the type specifiers does not matter; for example, unsigned int is the same as int unsigned. Also, the type specifiers need not be adjacent and can be separated by type qualifiers; for example, int const unsigned is equivalent to unsigned int const. Also, types on the same line are equivalent; for example, short is equivalent to signed short. (C actually uses the keywords _Bool, _Complex, and _Imaginary, but for convenience we use bool, complex, and imaginary instead.)

  void
  char
  signed char
  unsigned char
  short  signed short  short int  signed short int
  unsigned short  unsigned short int
  int  signed  signed int
  unsigned  unsigned int
  long  signed long  long int  signed long int
  unsigned long  unsigned long int
  long long  signed long long  long long int  signed long long int
  unsigned long long  unsigned long long int
  float
  double
  long double
  bool
  float complex
  double complex
  long double complex
  float imaginary
  double imaginary
  long double imaginary

Note that char is equivalent to neither signed char nor unsigned char.

Unlike type specifiers, type qualifiers may occur at most once within a type specifier group or a type qualifier list. (C allows them to appear multiple times, but the duplicate occurrences are ignored, so we take the more restrictive approach here.)

To turn in your assignment, submit a file hw4.prolog containing your definition of same_c_type/2 along with any other auxiliary definitions.


© 2005, 2007 Paul Eggert. See copying rules.
$Id: hw4.html,v 1.33 2007/04/30 23:35:53 eggert Exp $