Permalink
Browse files

Parse bit string literals

  • Loading branch information...
1 parent 6fe156b commit 90c11e99ede436b8bf9a5a10a578f45e55c20628 @nickg committed Mar 29, 2012
Showing with 124 additions and 5 deletions.
  1. +2 −0 src/lexer.l
  2. +56 −5 src/parse.y
  3. +8 −0 test/parse/bitstring.vhd
  4. +58 −0 test/test_parse.c
View
@@ -52,6 +52,7 @@ lvals_t lvals;
ID [a-zA-Z][a-zA-Z_0-9]*
EXID \\.*\\
STRING \"([^\"]|\"\")*\"
+BIT_STRING [BOX]\"[0-9a-fA-f_]+\"
CHAR '.'
COMMENT --.*\n
INT [0-9]+
@@ -260,6 +261,7 @@ REJECT {R}{E}{J}{E}{C}{T}
"]" { TOKEN(tRSQUARE); }
{INT} { lvals.ival = atoll(yytext); TOKEN(tINT); }
{BASED_INT} { return parse_based_int(yytext); }
+{BIT_STRING} { lvals.sval = strdup(yytext); TOKEN(tBITSTRING); }
{STRING} { lvals.sval = strdup(yytext); TOKEN(tSTRING); }
{TICK} { TOKEN(tTICK); }
{CHAR} { if (resolve_ir1045()) {
View
@@ -129,6 +129,7 @@
static tree_t build_expr2(const char *fn, tree_t left, tree_t right,
const struct YYLTYPE *loc);
static tree_t str_to_agg(const char *start, const char *end);
+ static tree_t bit_str_to_agg(const char *str, const loc_t *loc);
static bool to_range_expr(tree_t t, range_t *r);
static ident_t loc_to_ident(const loc_t *loc);
static void parse_error(const loc_t *loc, const char *fmt, ...);
@@ -159,7 +160,7 @@
%type <t> package_decl name aggregate string_literal report
%type <t> waveform_element seq_stmt_without_label conc_assign_stmt
%type <t> comp_instance_stmt conc_stmt_without_label elsif_list
-%type <t> delay_mechanism
+%type <t> delay_mechanism bit_string_literal
%type <i> id opt_id selected_id func_name
%type <l> interface_object_decl interface_list
%type <l> port_clause generic_clause interface_decl signal_decl
@@ -196,7 +197,7 @@
%token tOTHERS tASSERT tSEVERITY tON tMAP tTHEN tELSE tELSIF tBODY
%token tWHILE tLOOP tAFTER tALIAS tATTRIBUTE tPROCEDURE tEXIT
%token tWHEN tCASE tBAR tLSQUARE tRSQUARE tINERTIAL tTRANSPORT
-%token tREJECT
+%token tREJECT tBITSTRING
%left tAND tOR tNAND tNOR tXOR tXNOR
%left tEQ tNEQ tLT tLE tGT tGE
@@ -1716,9 +1717,9 @@ element_assoc
literal
: numeric_literal
| string_literal
-/* | bit_string_literal
- | null
-*/
+| bit_string_literal
+/* | null
+ */
;
string_literal
@@ -1732,6 +1733,13 @@ string_literal
}
;
+bit_string_literal
+: tBITSTRING
+ {
+ $$ = bit_str_to_agg(lvals.sval, &@$);
+ free(lvals.sval);
+ }
+
numeric_literal : abstract_literal | physical_literal ;
abstract_literal
@@ -1990,6 +1998,49 @@ static tree_t str_to_agg(const char *start, const char *end)
return t;
}
+static tree_t bit_str_to_agg(const char *str, const loc_t *loc)
+{
+ tree_t t = tree_new(T_AGGREGATE);
+ tree_set_loc(t, loc);
+
+ char base_ch = str[0];
+ int base;
+ switch (base_ch) {
+ case 'X': base = 16; break;
+ case 'O': base = 8; break;
+ case 'B': base = 2; break;
+ default:
+ parse_error(loc, "invalid base '%c' for bit string", base_ch);
+ return t;
+ }
+
+ tree_t one = tree_new(T_REF);
+ tree_set_ident(one, ident_new("1"));
+
+ tree_t zero = tree_new(T_REF);
+ tree_set_ident(zero, ident_new("0"));
+
+ for (const char *p = str + 2; *p != '\"'; p++) {
+ int n = (isdigit((int)*p) ? (*p - '0')
+ : 10 + (isupper((int)*p) ? (*p - 'A') : (*p - 'a')));
+
+ if (n >= base) {
+ parse_error(loc, "invalid digit '%c' in bit string", *p);
+ return t;
+ }
+
+ for (int d = (base >> 1); d > 0; n = n % d, d >>= 1) {
+ assoc_t a;
+ a.kind = A_POS;
+ a.value = (n / d) ? one : zero;
+
+ tree_add_assoc(t, a);
+ }
+ }
+
+ return t;
+}
+
static bool to_range_expr(tree_t t, range_t *r)
{
if (tree_kind(t) == T_ATTR_REF && tree_ident2(t) == ident_new("range")) {
View
@@ -0,0 +1,8 @@
+package bitstring is
+
+ constant x : t := X"1234";
+ constant y : t := O"1234";
+ constant z : t := X"ab";
+ constant b : t := B"101";
+
+end package;
View
@@ -1311,6 +1311,63 @@ START_TEST(test_based)
}
END_TEST
+START_TEST(test_bitstring)
+{
+ tree_t p, a;
+
+ fail_unless(input_from_file(TESTDIR "/parse/bitstring.vhd"));
+
+ p = parse();
+ fail_unless(tree_kind(p) == T_PACKAGE);
+
+ ident_t one = ident_new("1");
+ ident_t zero = ident_new("0");
+
+ a = tree_value(tree_decl(p, 0));
+ fail_unless(tree_assocs(a) == 16);
+ fail_unless(tree_ident(tree_assoc(a, 0).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 1).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 2).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 3).value) == one);
+ fail_unless(tree_ident(tree_assoc(a, 4).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 5).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 6).value) == one);
+ fail_unless(tree_ident(tree_assoc(a, 7).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 8).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 9).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 10).value) == one);
+ fail_unless(tree_ident(tree_assoc(a, 11).value) == one);
+ fail_unless(tree_ident(tree_assoc(a, 12).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 13).value) == one);
+ fail_unless(tree_ident(tree_assoc(a, 14).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 15).value) == zero);
+
+ a = tree_value(tree_decl(p, 1));
+ fail_unless(tree_assocs(a) == 12);
+ fail_unless(tree_ident(tree_assoc(a, 0).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 1).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 2).value) == one);
+
+ a = tree_value(tree_decl(p, 2));
+ fail_unless(tree_assocs(a) == 8);
+ fail_unless(tree_ident(tree_assoc(a, 0).value) == one);
+ fail_unless(tree_ident(tree_assoc(a, 1).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 2).value) == one);
+ fail_unless(tree_ident(tree_assoc(a, 3).value) == zero);
+
+ a = tree_value(tree_decl(p, 3));
+ fail_unless(tree_assocs(a) == 3);
+ fail_unless(tree_ident(tree_assoc(a, 0).value) == one);
+ fail_unless(tree_ident(tree_assoc(a, 1).value) == zero);
+ fail_unless(tree_ident(tree_assoc(a, 2).value) == one);
+
+ p = parse();
+ fail_unless(p == NULL);
+
+ fail_unless(parse_errors() == 0);
+}
+END_TEST
+
int main(void)
{
register_trace_signal_handlers();
@@ -1338,6 +1395,7 @@ int main(void)
tcase_add_test(tc_core, test_ir1045);
tcase_add_test(tc_core, test_concat);
tcase_add_test(tc_core, test_based);
+ tcase_add_test(tc_core, test_bitstring);
suite_add_tcase(s, tc_core);
SRunner *sr = srunner_create(s);

0 comments on commit 90c11e9

Please sign in to comment.