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:
parent
3362fbc0db
commit
2e28782af3
|
|
@ -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_ << "'"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
236
vhdlpp/lexor.lex
236
vhdlpp/lexor.lex
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue