Add parser support for concatenations/conditional assignment/elsif

Some of these should be easy to translate, but get the parsing out
of the way first.
This commit is contained in:
Stephen Williams 2011-06-05 13:58:54 -07:00
parent 3362fbc0db
commit 2e28782af3
6 changed files with 358 additions and 9 deletions

View File

@ -163,6 +163,9 @@ void ExpArithmetic::dump(ostream&out, int indent) const
case POW:
fun_name = "**";
break;
case CONCAT:
fun_name = "&";
break;
}
out << setw(indent) << "" << "Arithmetic " << fun_name
@ -183,6 +186,16 @@ void ExpBinary::dump_operands(ostream&out, int indent) const
operand2_->dump(out, indent);
}
void ExpBitstring::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Bit string " << value_.size()
<< "b\"";
for (size_t idx = value_.size() ; idx > 0 ; idx -= 1) {
out << value_[idx-1];
}
out << "\"";
}
void ExpCharacter::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "Character '" << value_ << "'"

View File

@ -21,6 +21,7 @@
# include "scope.h"
# include <iostream>
# include <typeinfo>
# include <cstring>
# include <cassert>
using namespace std;
@ -161,11 +162,27 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
return false;
case POW:
return false;
case CONCAT:
return false;
}
return true;
}
/*
* Store bitstrings in little-endian order.
*/
ExpBitstring::ExpBitstring(const char*val)
: value_(strlen(val))
{
for (size_t idx = value_.size() ; idx > 0 ; idx -= 1)
value_[idx-1] = *val++;
}
ExpBitstring::~ExpBitstring()
{
}
ExpCharacter::ExpCharacter(char val)
: value_(val)
{

View File

@ -22,6 +22,7 @@
# include "StringHeap.h"
# include "LineInfo.h"
# include <inttypes.h>
# include <vector>
class Entity;
class Architecture;
@ -146,7 +147,7 @@ class ExpBinary : public Expression {
class ExpArithmetic : public ExpBinary {
public:
enum fun_t { PLUS, MINUS, MULT, DIV, MOD, REM, POW };
enum fun_t { PLUS, MINUS, MULT, DIV, MOD, REM, POW, CONCAT };
public:
ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2);
@ -177,6 +178,19 @@ class ExpAttribute : public Expression {
perm_string name_;
};
class ExpBitstring : public Expression {
public:
explicit ExpBitstring(const char*);
~ExpBitstring();
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent = 0) const;
private:
std::vector<char>value_;
};
class ExpCharacter : public Expression {
public:

View File

@ -101,6 +101,9 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
case REM:
out << " /* ?remainder? */ ";
break;
case CONCAT:
out << " /* ?concat? */ ";
break;
}
errors += emit_operand2(out, ent, arc);
@ -108,6 +111,13 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
return errors;
}
int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
{
int errors = 0;
errors += 1;
return errors;
}
int ExpCharacter::emit(ostream&out, Entity*, Architecture*)
{
const VType*etype = peek_type();

View File

@ -54,6 +54,7 @@ static char* escape_apostrophe_and_dup(char* text);
static double make_double_from_based(char* text);
static int64_t make_long_from_based(char* text);
static char* make_bitstring_literal(const char*text);
static int64_t lpow(int64_t left, int64_t right);
static unsigned short short_from_hex_char(char ch);
@ -175,6 +176,10 @@ based_integer [0-9a-fA-F](_?[0-9a-fA-F])*
}
}
{integer}?[sSuU]?[xXbBoOdD]\"[^\"]+\" {
yylval.text = make_bitstring_literal(yytext);
return BITSTRING_LITERAL;
}
/* Compound symbols */
"<=" { return LEQ; }
@ -381,6 +386,237 @@ static char* escape_apostrophe_and_dup(char* text)
return newstr;
}
static char*make_bitstring_bin(int width_prefix, bool sflag, bool,
const char*src)
{
int src_len = strlen(src);
if (width_prefix < 0)
width_prefix = src_len;
char*res = new char[width_prefix+1];
char*rp = res;
if (width_prefix > src_len) {
size_t pad = width_prefix - src_len;
for (size_t idx = 0 ; idx < pad ; idx += 1)
*rp++ = sflag? src[0] : '0';
} else if (src_len > width_prefix) {
src += src_len - width_prefix;
}
while (*src) {
*rp++ = *src++;
}
return res;
}
static char*make_bitstring_oct(int width_prefix, bool sflag, bool,
const char*src)
{
int src_len = strlen(src);
if (width_prefix < 0)
width_prefix = 3*src_len;
char*res = new char[width_prefix+1];
char*rp = res + width_prefix;
*rp = 0;
rp -= 1;
for (const char*sp = src + src_len - 1; sp >= src ; sp -= 1) {
int val;
switch (*sp) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
val = *sp - '0';
*rp-- = (val&1)? '1' : '0';
if (rp >= res) *rp-- = (val&2)? '1' : '0';
if (rp >= res) *rp-- = (val&4)? '1' : '0';
break;
default:
*rp-- = *sp;
if (rp >= res) *rp-- = *sp;
if (rp >= res) *rp-- = *sp;
break;
}
if (rp < res)
break;
}
if (rp >= res) {
char pad = sflag? src[0] : '0';
while (rp >= res)
*rp-- = pad;
}
return res;
}
static char*make_bitstring_hex(int width_prefix, bool sflag, bool,
const char*src)
{
int src_len = strlen(src);
if (width_prefix <= 0)
width_prefix = 4*src_len;
char*res = new char[width_prefix+1];
char*rp = res + width_prefix;
*rp = 0;
rp -= 1;
for (const char*sp = src + src_len - 1; sp >= src ; sp -= 1) {
int val;
switch (*sp) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
val = *sp - '0';
*rp-- = (val&1)? '1' : '0';
if (rp >= res) *rp-- = (val&2)? '1' : '0';
if (rp >= res) *rp-- = (val&4)? '1' : '0';
if (rp >= res) *rp-- = (val&8)? '1' : '0';
break;
case 'a': case 'A':
case 'b': case 'B':
case 'c': case 'C':
case 'd': case 'D':
case 'e': case 'E':
case 'f': case 'F':
val = 10 + toupper(*sp) - 'A';
*rp-- = (val&1)? '1' : '0';
if (rp >= res) *rp-- = (val&2)? '1' : '0';
if (rp >= res) *rp-- = (val&4)? '1' : '0';
if (rp >= res) *rp-- = (val&8)? '1' : '0';
break;
default:
*rp-- = *sp;
if (rp >= res) *rp-- = *sp;
if (rp >= res) *rp-- = *sp;
break;
}
if (rp < res)
break;
}
if (rp >= res) {
char pad = sflag? src[0] : '0';
while (rp >= res)
*rp-- = pad;
}
return res;
}
static char*make_bitstring_dec(int, bool, bool, const char*)
{
assert(0);
return 0;
}
static char* make_bitstring_literal(const char*text)
{
int width_prefix = -1;
const char*cp = text;
bool signed_flag = false;
bool unsigned_flag = false;
unsigned base = 0;
// Parse out the explicit width, if present.
if (size_t len = strspn(cp, "0123456789")) {
width_prefix = 0;
while (len > 0) {
width_prefix *= 10;
width_prefix += *cp - '0';
cp += 1;
}
} else {
width_prefix = -1;
}
// Detect and s/u flags.
if (*cp == 's' || *cp == 'S') {
signed_flag = true;
cp += 1;
} else if (*cp == 'u' || *cp == 'U') {
unsigned_flag = true;
cp += 1;
}
// Now get the base marker.
switch (*cp) {
case 'b':
case 'B':
base = 2;
break;
case 'o':
case 'O':
base = 8;
break;
case 'x':
case 'X':
base = 16;
break;
case 'd':
case 'D':
base = 10;
break;
default:
assert(0);
}
cp += 1;
char*simplified = new char [strlen(cp) + 1];
char*dp = simplified;
assert(*cp == '"');
cp += 1;
while (*cp && *cp != '"') {
if (*cp == '_') {
cp += 1;
continue;
}
*dp++ = *cp++;
}
*dp = 0;
char*res;
switch (base) {
case 2:
res = make_bitstring_bin(width_prefix, signed_flag, unsigned_flag, simplified);
break;
case 8:
res = make_bitstring_oct(width_prefix, signed_flag, unsigned_flag, simplified);
break;
case 10:
res = make_bitstring_dec(width_prefix, signed_flag, unsigned_flag, simplified);
break;
case 16:
res = make_bitstring_hex(width_prefix, signed_flag, unsigned_flag, simplified);
break;
default:
assert(0);
res = 0;
}
delete[]simplified;
return res;
}
/**
* This function takes a floating point based number
* in form of a C-strings and converts it to a double.

View File

@ -169,7 +169,7 @@ const VType*parse_type_by_name(perm_string name)
%token <text> IDENTIFIER
%token <uni_integer> INT_LITERAL
%token <uni_real> REAL_LITERAL
%token <text> STRING_LITERAL CHARACTER_LITERAL
%token <text> STRING_LITERAL CHARACTER_LITERAL BITSTRING_LITERAL
/* compound symbols */
%token LEQ GEQ VASSIGN NE BOX EXP ARROW DLT DGT
@ -275,10 +275,19 @@ architecture_statement_part
;
association_element
: IDENTIFIER ARROW name
: IDENTIFIER ARROW expression
{ named_expr_t*tmp = new named_expr_t(lex_strings.make($1), $3);
delete[]$1;
$$ = tmp;
}
| IDENTIFIER ARROW K_open
{ sorrymsg(@3, "Port map \"open\" not supported.\n");
$$ = 0;
}
| IDENTIFIER ARROW error
{ errormsg(@3, "Invalid target for port map association.\n");
yyerrok;
$$ = 0;
}
;
@ -443,6 +452,16 @@ concurrent_signal_assignment_statement
$$ = tmp;
delete $3;
}
| name LEQ waveform K_when expression K_else waveform ';'
{ ExpName*name = dynamic_cast<ExpName*> ($1);
assert(name);
SignalAssignment*tmp = new SignalAssignment(name, *$3);
FILE_NAME(tmp, @1);
$$ = tmp;
delete $3;
sorrymsg(@4, "Conditional signal assignment not supported here.\n");
}
| name LEQ error ';'
{ errormsg(@2, "Syntax error in signal assignment waveform.\n");
delete $1;
@ -755,15 +774,15 @@ identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ;
if_statement
: K_if expression K_then sequence_of_statements
if_statement_else
if_statement_elsif_list_opt if_statement_else
K_end K_if ';'
{ IfSequential*tmp = new IfSequential($2, $4, $5);
{ IfSequential*tmp = new IfSequential($2, $4, $6);
FILE_NAME(tmp, @1);
$$ = tmp;
}
| K_if error K_then sequence_of_statements
if_statement_else
if_statement_elsif_list_opt if_statement_else
K_end K_if ';'
{ errormsg(@2, "Error in if_statement condition expression.\n");
yyerrok;
@ -772,7 +791,7 @@ if_statement
}
| K_if expression K_then error K_end K_if ';'
{ errormsg(@2, "Too many errors in sequence within if_statement.\n");
{ errormsg(@4, "Too many errors in sequence within if_statement.\n");
yyerrok;
$$ = 0;
}
@ -784,9 +803,33 @@ if_statement
}
;
if_statement_elsif_list_opt
: if_statement_elsif_list
|
;
if_statement_elsif_list
: if_statement_elsif_list if_statement_elsif
| if_statement_elsif
;
if_statement_elsif
: K_elsif expression K_then sequence_of_statements
{ sorrymsg(@1, "elsif sub-statements are not supported.\n"); }
| K_elsif expression K_then error
{ errormsg(@4, "Too many errors in elsif sub-statements.\n");
yyerrok;
}
;
if_statement_else
: K_else sequence_of_statements
{ $$ = $2; }
| K_else error
{ errormsg(@2, "Too many errors in else sub-statements.\n");
yyerrok;
$$ = 0;
}
|
{ $$ = 0; }
;
@ -1004,8 +1047,7 @@ port_map_aspect
: K_port K_map '(' association_list ')'
{ $$ = $4; }
| K_port K_map '(' error ')'
{
errormsg(@1, "Syntax error in port map aspect.\n");
{ errormsg(@1, "Syntax error in port map aspect.\n");
}
;
@ -1053,6 +1095,12 @@ primary
FILE_NAME(tmp, @1);
$$ = tmp;
}
| BITSTRING_LITERAL
{ ExpBitstring*tmp = new ExpBitstring($1);
FILE_NAME(tmp, @1);
delete[]$1;
$$ = tmp;
}
| '(' expression ')'
{ $$ = $2; }
;
@ -1248,6 +1296,11 @@ simple_expression
FILE_NAME(tmp, @2);
$$ = tmp;
}
| term '&' term
{ ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::CONCAT, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
;
signal_assignment_statement
@ -1257,6 +1310,12 @@ signal_assignment_statement
delete $3;
$$ = tmp;
}
| name LEQ waveform K_when expression K_else waveform ';'
{ SignalSeqAssignment*tmp = new SignalSeqAssignment($1, $3);
FILE_NAME(tmp, @1);
sorrymsg(@4, "Conditional signal assignment not supported.\n");
$$ = tmp;
}
;
subtype_declaration