From b2b90974888603f7891cb5cd5fdbcbd6d94a09f5 Mon Sep 17 00:00:00 2001 From: steve Date: Thu, 6 May 1999 04:09:28 +0000 Subject: [PATCH] Parse more constant expressions. --- lexor.lex | 51 +++++++++++++++++++++++++++++++++++++++++---------- parse.y | 35 ++++++++++++++++++++++++++++++++++- pform.cc | 20 ++++++++++++++++++-- pform.h | 6 +++++- 4 files changed, 98 insertions(+), 14 deletions(-) diff --git a/lexor.lex b/lexor.lex index 90348b65c..768220233 100644 --- a/lexor.lex +++ b/lexor.lex @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: lexor.lex,v 1.11 1999/03/16 04:44:45 steve Exp $" +#ident "$Id: lexor.lex,v 1.12 1999/05/06 04:09:28 steve Exp $" #endif //# define YYSTYPE lexval @@ -44,6 +44,10 @@ static verinum*make_sized_binary(const char*txt); static verinum*make_sized_dec(const char*txt); static verinum*make_sized_octal(const char*txt); static verinum*make_sized_hex(const char*txt); +static verinum*make_unsized_binary(const char*txt); +static verinum*make_unsized_dec(const char*txt); +static verinum*make_unsized_octal(const char*txt); +static verinum*make_unsized_hex(const char*txt); %} @@ -73,7 +77,7 @@ static verinum*make_sized_hex(const char*txt); "||" { return K_LOR; } "&&" { return K_LAND; } -[;:\[\],()#=.@&!<|^~+*/-] { return yytext[0]; } +[}{;:\[\],()#=.@&!<|^~+*/-] { return yytext[0]; } \" { BEGIN(CSTRING); } \\\" { yymore(); } @@ -130,6 +134,11 @@ static verinum*make_sized_hex(const char*txt); [0-9][0-9_]*\'[hH][0-9a-fA-Fxz_]+ { yylval.number = make_sized_hex(yytext); return NUMBER; } +\'[bB][0-1xz_]+ { yylval.number = make_unsized_binary(yytext); return NUMBER; } +\'[oO][0-7xz_]+ { yylval.number = make_unsized_octal(yytext); return NUMBER; } +\'[hH][0-9a-fA-Fxz_]+ { yylval.number = make_unsized_hex(yytext); + return NUMBER; } + [0-9][0-9_]* { /* Handle the special case of the unsized decimal number. */ unsigned long value = 0; @@ -298,18 +307,13 @@ static int check_identifier(const char*name) return IDENTIFIER; } -static verinum*make_sized_binary(const char*txt) +static verinum*make_binary_with_size(unsigned size, const char*ptr) { - char*ptr; - unsigned size = strtoul(txt,&ptr,10); - assert(*ptr == '\''); - ptr += 1; assert(tolower(*ptr) == 'b'); - verinum::V*bits = new verinum::V[size]; unsigned idx = 0; - char*eptr = ptr + strlen(ptr) - 1; + const char*eptr = ptr + strlen(ptr) - 1; while ((eptr > ptr) && (idx < size)) { if (*eptr == '_') { @@ -336,7 +340,6 @@ static verinum*make_sized_binary(const char*txt) eptr -= 1; } - // Zero-extend binary number, except that z or x is extended // if it is the highest supplied digit. while (idx < size) { @@ -359,6 +362,24 @@ static verinum*make_sized_binary(const char*txt) return new verinum(bits, size); } +static verinum*make_sized_binary(const char*txt) +{ + char*ptr; + unsigned size = strtoul(txt,&ptr,10); + assert(*ptr == '\''); + ptr += 1; + assert(tolower(*ptr) == 'b'); + + return make_binary_with_size(size, ptr); +} + +static verinum*make_unsized_binary(const char*txt) +{ + assert(*txt == '\''); + txt += 1; + return make_binary_with_size(64, txt); +} + static verinum*make_sized_octal(const char*txt) { char*ptr; @@ -410,6 +431,11 @@ static verinum*make_sized_octal(const char*txt) return new verinum(bits, size); } +static verinum*make_unsized_octal(const char*txt) +{ + assert(0); +} + static verinum*make_sized_hex(const char*txt) { char*ptr; @@ -479,6 +505,11 @@ static verinum*make_sized_hex(const char*txt) return new verinum(bits, size); } +static verinum*make_unsized_hex(const char*txt) +{ + assert(0); +} + /* * Making a deciman number is much easier then the other base numbers * because there are no z or x values to worry about. diff --git a/parse.y b/parse.y index 5674dad85..270b3e4a1 100644 --- a/parse.y +++ b/parse.y @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: parse.y,v 1.20 1999/05/05 03:27:15 steve Exp $" +#ident "$Id: parse.y,v 1.21 1999/05/06 04:09:28 steve Exp $" #endif # include "parse_misc.h" @@ -170,6 +170,10 @@ case_items } ; + /* const_expressions are restricted expressions that have guaranteed + known values at compile time. I treat them differently at parse + time so that I can tack correctness checking onto the parse + process. */ const_expression : NUMBER { verinum*tmp = $1; @@ -184,6 +188,23 @@ const_expression { $$ = new PEString(*$1); delete $1; } + | IDENTIFIER + { if (!pform_is_parameter(*$1)) { + yyerror(@1, "Identifier in constant expression" + " must be a parameter name."); + delete $1; + $$ = 0; + } else { + PEIdent*tmp = new PEIdent(*$1); + tmp->set_file(@1.text); + tmp->set_lineno(@1.first_line); + $$ = tmp; + delete $1; + } + } + | const_expression '-' const_expression + { $$ = new PEBinary('-', $1, $3); + } ; delay @@ -277,6 +298,10 @@ expression { $$ = $1; } | '(' expression ')' { $$ = $2; } + | '{' expression_list '}' + { yyerror(@1, "Sorry, concatenation operator not supported."); + $$ = 0; + } | '~' expression %prec UNARY_PREC { $$ = new PEUnary('~', $2); } @@ -507,8 +532,16 @@ list_of_variables } ; + /* An lvalue is the expression that can go on the left side of an + assignment. This rule handles only procedural assignments. */ lvalue : identifier { $$ = $1; } + | identifier '[' expression ']' + { yyerror(@2, "Sorry, bit/memory selects " + "not supported in lvalue."); + $$ = $1; + delete $3; + } ; module diff --git a/pform.cc b/pform.cc index dde548542..286ce7d5f 100644 --- a/pform.cc +++ b/pform.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform.cc,v 1.12 1999/05/02 23:25:32 steve Exp $" +#ident "$Id: pform.cc,v 1.13 1999/05/06 04:09:28 steve Exp $" #endif # include "pform.h" @@ -426,8 +426,14 @@ static void pform_set_net_range(const string&name, list*range) PExpr*msb = *idx; idx ++; PExpr*lsb = *idx; - if (! (cur->msb->is_the_same(msb) && cur->lsb->is_the_same(lsb))) + if (msb == 0) { + VLerror(yylloc, "failed to parse msb of range."); + } else if (lsb == 0) { + VLerror(yylloc, "failed to parse lsb of range."); + } else if (! (cur->msb->is_the_same(msb) && + cur->lsb->is_the_same(lsb))) { VLerror(yylloc, "net ranges are not identical."); + } delete msb; delete lsb; } @@ -438,6 +444,13 @@ void pform_set_parameter(const string&name, PExpr*expr) cur_module->parameters[name] = expr; } +bool pform_is_parameter(const string&name) +{ + map::const_iterator cur = + cur_module->parameters.find(name); + return cur != cur_module->parameters.end(); +} + void pform_set_port_type(list*names, NetNet::PortType pt) { for (list::const_iterator cur = names->begin() @@ -535,6 +548,9 @@ int pform_parse(const char*path, map&modules, /* * $Log: pform.cc,v $ + * Revision 1.13 1999/05/06 04:09:28 steve + * Parse more constant expressions. + * * Revision 1.12 1999/05/02 23:25:32 steve * Enforce module instance names. * diff --git a/pform.h b/pform.h index 45f9d225f..e4470c828 100644 --- a/pform.h +++ b/pform.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: pform.h,v 1.9 1999/04/19 01:59:37 steve Exp $" +#ident "$Id: pform.h,v 1.10 1999/05/06 04:09:28 steve Exp $" #endif # include "netlist.h" @@ -107,6 +107,7 @@ extern void pform_set_attrib(const string&name, const string&key, extern void pform_set_type_attrib(const string&name, const string&key, const string&value); extern void pform_set_parameter(const string&name, PExpr*expr); +extern bool pform_is_parameter(const string&name); extern PProcess* pform_make_behavior(PProcess::Type, Statement*); extern Statement* pform_make_block(PBlock::BL_TYPE, list*); extern Statement* pform_make_assignment(string*t, PExpr*e); @@ -140,6 +141,9 @@ extern void pform_dump(ostream&out, Module*mod); /* * $Log: pform.h,v $ + * Revision 1.10 1999/05/06 04:09:28 steve + * Parse more constant expressions. + * * Revision 1.9 1999/04/19 01:59:37 steve * Add memories to the parse and elaboration phases. *