-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Ref] C block declare and typedef parsing
In order to insert DECLARE variables into the component-type parameters struct, we need to be able to identify their type information. These types _could_ be user-defined `typedef` aliases, provided in, e.g., the SHARE section of the current or any-other component (probably preceding only, but possibly trailing definitions, since SHARE goes before all initialization). Previously parsing for both variable declaration and typedefs was performed in one pass, but this led to a confusing Listener class which mistakenly identified typenames for `typedef` `struct`s incorrectly, sometimes. E.g., ``` typdef struct the_struct_label { double a_double; int an_int; } the_struct_alias; ``` would have been misidentified as the equivalent of `typedef struct the_struct_label an_int;` By splitting `typedef` and declaration parsing into two passes, there are now two slightly-simpler Listener classes that handle the above case plus all others implemented in a new test file. This double-pass invariably means slower parsing, but this seems a worthwhile trade-off at the moment.
- Loading branch information
Showing
3 changed files
with
187 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
from mccode_antlr.translators.c_listener import ( | ||
extract_c_declared_variables_and_defined_types as extract | ||
) | ||
from textwrap import dedent | ||
|
||
def test_alias_types(): | ||
block = dedent("""\ | ||
typedef unsigned int age_t; | ||
""") | ||
variables, types = extract(block) | ||
assert len(variables) == 0 | ||
assert len(types) == 1 | ||
assert types[0] == 'age_t' | ||
|
||
|
||
def test_stackoverflow_struct_type(): | ||
block = dedent("""\ | ||
typedef struct nodeT { | ||
void *content; | ||
struct nodeT *next; | ||
} Node; | ||
""") | ||
variables, types = extract(block) | ||
assert len(variables) == 0 | ||
assert len(types) == 1 | ||
assert 'Node' == types[0] | ||
|
||
def test_stackoverflow_enum_type(): | ||
block = dedent("""\ | ||
typedef enum season_t { SPRING, SUMMER, FALL, WINTER } Season; | ||
""") | ||
variables, types = extract(block) | ||
assert len(variables) == 0 | ||
assert len(types) == 1 | ||
assert 'Season' == types[0] | ||
|
||
def test_repeated_struct_name(): | ||
block = dedent("""\ | ||
typedef struct PolyhedronIndexValuePair { | ||
int index; | ||
double value; | ||
} PolyhedronIndexValuePair; | ||
""") | ||
variables, types = extract(block) | ||
|
||
assert len(variables) == 0 | ||
assert len(types) == 1 | ||
assert types[0] == 'PolyhedronIndexValuePair' | ||
|
||
|
||
def test_mccode_style_typedef(): | ||
block = dedent("""\ | ||
struct _struct_Progress_bar { | ||
char _name[256]; /* e.g. instance of Progress_bar name */ | ||
char _type[13]; /* Progress_bar */ | ||
long _index; /* index in TRACE list */ | ||
Coords _position_absolute; | ||
Coords _position_relative; /* wrt PREVIOUS */ | ||
Rotation _rotation_absolute; | ||
Rotation _rotation_relative; /* wrt PREVIOUS */ | ||
int _rotation_is_identity; | ||
int _position_relative_is_zero; | ||
_class_Progress_bar_parameters _parameters; | ||
}; | ||
typedef struct _struct_Progress_bar _class_Progress_bar; | ||
""") | ||
variables, types = extract(block) | ||
assert len(variables) == 0 | ||
assert len(types) == 1 | ||
assert types[0] == "_class_Progress_bar" | ||
|
||
|
||
def test_assignments(): | ||
block = dedent("""\ | ||
int blah=1; | ||
double yarg; | ||
// yarg = 2.0; // this parser only handles _declarations_ no out-of-declaration assignments allowed. | ||
char mmmm[11] = "0123456789"; | ||
""") | ||
variables, types = extract(block) | ||
assert len(variables) == 3 | ||
assert len(types) == 0 | ||
assert 'blah' in variables | ||
assert variables['blah'] == ('int', '1') | ||
assert 'yarg' in variables | ||
assert variables['yarg'] == ('double', None) | ||
assert 'mmmm[11]' in variables | ||
assert variables['mmmm[11]'] == ('char', '"0123456789"') | ||
|
||
def test_struct_declaration(): | ||
block = dedent("""\ | ||
struct my_struct_type the_struct; | ||
struct another_struct a_struct_with_values={0, 1.0, "two"}; | ||
struct the_third_s * ptr_to_third_struct; | ||
""") | ||
variables, types = extract(block) | ||
assert len(variables) == 3 | ||
assert len(types) == 0 | ||
expected = { | ||
'the_struct': ('struct my_struct_type', None), | ||
'a_struct_with_values': ('struct another_struct', '{0, 1.0, "two"}'), | ||
'* ptr_to_third_struct': ('struct the_third_s', None), | ||
} | ||
assert all(x in variables for x in expected) | ||
for name, (dtype, value) in expected.items(): | ||
assert(variables[name] == (dtype, value)) | ||
|
||
|
||
def test_typedef_declaration(): | ||
block = dedent("""\ | ||
typedef double blah; | ||
blah really_a_double=1.0f; | ||
blah * double_ptr=NULL; | ||
blah double_array[10]; | ||
""") | ||
variables, types = extract(block) | ||
assert len(variables) == 3 | ||
assert len(types) == 1 | ||
assert types[0] == "blah" | ||
expected = { | ||
'really_a_double': ('blah', '1.0f'), | ||
'* double_ptr': ('blah', 'NULL'), | ||
'double_array[10]': ('blah', None), | ||
} | ||
assert all(x in variables for x in expected) | ||
for name, (dtype, value) in expected.items(): | ||
assert(variables[name] == (dtype, value)) |