mirror of
https://github.com/holub/mame
synced 2025-04-23 08:49:55 +03:00
Minor bugfixes + parser is now based on tokens. Should ease reading other netlist formats significantly.
This commit is contained in:
parent
4737fe54cd
commit
e7ed74b009
@ -266,7 +266,6 @@ void netlist_factory_t::initialize()
|
||||
ENTRY(switch2, SWITCH2, "+i1,i2")
|
||||
ENTRY(nicRSFF, NETDEV_RSFF, "+S,R")
|
||||
ENTRY(7400, TTL_7400_NAND, "+A,B")
|
||||
ENTRY(7400_dip, TTL_7400_DIP, "-")
|
||||
ENTRY(7402, TTL_7402_NOR, "+A,B")
|
||||
ENTRY(7404, TTL_7404_INVERT, "+A")
|
||||
ENTRY(7410, TTL_7410_NAND, "+A,B,C")
|
||||
@ -278,18 +277,19 @@ void netlist_factory_t::initialize()
|
||||
ENTRY(7486, TTL_7486_XOR, "+A,B")
|
||||
ENTRY(nic7448, TTL_7448, "+A0,A1,A2,A3,LTQ,BIQ,RBIQ")
|
||||
ENTRY(7474, TTL_7474, "+CLK,D,CLRQ,PREQ")
|
||||
ENTRY(7474_dip, TTL_7474_DIP, "-")
|
||||
ENTRY(7483, TTL_7483, "+A1,A2,A3,A4,B1,B2,B3,B4,C0")
|
||||
ENTRY(7490, TTL_7490, "+CLK,R1,R2,R91,R92")
|
||||
ENTRY(7493, TTL_7493, "+CLKA,CLKB,R1,R2")
|
||||
ENTRY(7493_dip, TTL_7493_DIP, "-")
|
||||
ENTRY(74107, TTL_74107, "+CLK,J,K,CLRQ")
|
||||
ENTRY(74107_dip, TTL_74107_DIP, "-")
|
||||
ENTRY(74107A, TTL_74107A, "+CLK,J,K,CLRQ")
|
||||
ENTRY(74153, TTL_74153, "+C0,C1,C2,C3,A,B,G")
|
||||
ENTRY(9316, TTL_9316, "+CLK,ENP,ENT,CLRQ,LOADQ,A,B,C,D")
|
||||
ENTRY(9316_dip, TTL_9316_DIP, "-")
|
||||
ENTRY(NE555, NE555, "-")
|
||||
ENTRY(7400_dip, TTL_7400_DIP, "-")
|
||||
ENTRY(7474_dip, TTL_7474_DIP, "-")
|
||||
ENTRY(7493_dip, TTL_7493_DIP, "-")
|
||||
ENTRY(74107_dip, TTL_74107_DIP, "-")
|
||||
ENTRY(9316_dip, TTL_9316_DIP, "-")
|
||||
}
|
||||
|
||||
netlist_device_t *netlist_factory_t::new_device_by_classname(const pstring &classname, netlist_setup_t &setup) const
|
||||
|
@ -102,6 +102,16 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
ATTR_HOT inline int indexof(const _ListClass &elem) const
|
||||
{
|
||||
for (int i = 0; i < m_count; i++)
|
||||
{
|
||||
if (m_list[i] == elem)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
ATTR_HOT inline const _ListClass *first() const { return ((m_count > 0) ? &m_list[0] : NULL ); }
|
||||
ATTR_HOT inline const _ListClass *next(const _ListClass *lc) const { return ((lc < last()) ? lc + 1 : NULL ); }
|
||||
ATTR_HOT inline const _ListClass *last() const { return &m_list[m_count -1]; }
|
||||
|
@ -11,10 +11,232 @@
|
||||
//#define NL_VERBOSE_OUT(x) printf x
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// A netlist parser
|
||||
// A simple tokenizer
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_COLD void netlist_parser::error(const char *format, ...)
|
||||
pstring ptokenizer::currentline_str()
|
||||
{
|
||||
char buf[300];
|
||||
int bufp = 0;
|
||||
const char *p = m_line_ptr;
|
||||
while (*p && *p != 10)
|
||||
buf[bufp++] = *p++;
|
||||
buf[bufp] = 0;
|
||||
return pstring(buf);
|
||||
}
|
||||
|
||||
|
||||
void ptokenizer::skipeol()
|
||||
{
|
||||
char c = getc();
|
||||
while (c)
|
||||
{
|
||||
if (c == 10)
|
||||
{
|
||||
c = getc();
|
||||
if (c != 13)
|
||||
ungetc();
|
||||
return;
|
||||
}
|
||||
c = getc();
|
||||
}
|
||||
}
|
||||
|
||||
void ptokenizer::skipws()
|
||||
{
|
||||
while (unsigned char c = getc())
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ' ':
|
||||
case 9:
|
||||
case 10:
|
||||
case 13:
|
||||
break;
|
||||
case '#':
|
||||
skipeol(); // treat preprocessor defines as comments
|
||||
break;
|
||||
case '/':
|
||||
c = getc();
|
||||
if (c == '/')
|
||||
{
|
||||
skipeol();
|
||||
}
|
||||
else if (c == '*')
|
||||
{
|
||||
int f=0;
|
||||
while (!eof() )
|
||||
{
|
||||
c = getc();
|
||||
if (f == 0 && c == '*')
|
||||
f=1;
|
||||
else if (f == 1 && c== '/' )
|
||||
break;
|
||||
else
|
||||
f=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ungetc();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char ptokenizer::peekc()
|
||||
{
|
||||
unsigned char c = getc();
|
||||
ungetc();
|
||||
return c;
|
||||
}
|
||||
|
||||
unsigned char ptokenizer::getc()
|
||||
{
|
||||
if (*m_px == 10)
|
||||
{
|
||||
m_line++;
|
||||
m_line_ptr = m_px + 1;
|
||||
}
|
||||
if (*m_px)
|
||||
return *(m_px++);
|
||||
else
|
||||
return *m_px;
|
||||
}
|
||||
|
||||
void ptokenizer::ungetc()
|
||||
{
|
||||
m_px--;
|
||||
}
|
||||
|
||||
void ptokenizer::require_token(const token_id_t &token_num)
|
||||
{
|
||||
require_token(get_token(), token_num);
|
||||
}
|
||||
|
||||
void ptokenizer::require_token(const token_t tok, const token_id_t &token_num)
|
||||
{
|
||||
if (!tok.is(token_num))
|
||||
{
|
||||
error("Error: expected token <%s> got <%s>\n", m_tokens[token_num.id()].cstr(), tok.str().cstr());
|
||||
}
|
||||
}
|
||||
|
||||
pstring ptokenizer::get_string()
|
||||
{
|
||||
token_t tok = get_token();
|
||||
if (!tok.is_type(STRING))
|
||||
{
|
||||
error("Error: expected a string, got <%s>\n", tok.str().cstr());
|
||||
}
|
||||
return tok.str();
|
||||
}
|
||||
|
||||
pstring ptokenizer::get_identifier()
|
||||
{
|
||||
token_t tok = get_token();
|
||||
if (!tok.is_type(IDENTIFIER))
|
||||
{
|
||||
error("Error: expected an identifier, got <%s>\n", tok.str().cstr());
|
||||
}
|
||||
return tok.str();
|
||||
}
|
||||
|
||||
ptokenizer::token_t ptokenizer::get_token()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
token_t ret = get_token_internal();
|
||||
if (ret.is_type(ENDOFFILE))
|
||||
return ret;
|
||||
|
||||
if (ret.is(m_tok_comment_start))
|
||||
{
|
||||
do {
|
||||
ret = get_token_internal();
|
||||
} while (ret.is_not(m_tok_comment_end));
|
||||
}
|
||||
else if (ret.is(m_tok_line_comment))
|
||||
{
|
||||
skipeol();
|
||||
}
|
||||
else if (ret.str() == "#")
|
||||
{
|
||||
skipeol();
|
||||
}
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ptokenizer::token_t ptokenizer::get_token_internal()
|
||||
{
|
||||
/* skip ws */
|
||||
char c = getc();
|
||||
while (m_whitespace.find(c)>=0)
|
||||
{
|
||||
c = getc();
|
||||
if (eof())
|
||||
{
|
||||
return token_t(ENDOFFILE);
|
||||
}
|
||||
}
|
||||
if (m_identifier_chars.find(c)>=0)
|
||||
{
|
||||
/* read identifier till non identifier char */
|
||||
pstring tokstr = "";
|
||||
while (m_identifier_chars.find(c)>=0) {
|
||||
tokstr += c;
|
||||
c = getc();
|
||||
}
|
||||
ungetc();
|
||||
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
|
||||
if (id.id() >= 0)
|
||||
return token_t(id, tokstr);
|
||||
else
|
||||
{
|
||||
return token_t(IDENTIFIER, tokstr);
|
||||
}
|
||||
}
|
||||
else if (c == m_string)
|
||||
{
|
||||
pstring tokstr = "";
|
||||
c = getc();
|
||||
while (c != m_string)
|
||||
{
|
||||
tokstr += c;
|
||||
c = getc();
|
||||
}
|
||||
return token_t(STRING, tokstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* read identifier till first identifier char or ws */
|
||||
pstring tokstr = "";
|
||||
while ((m_identifier_chars.find(c)) < 0 && (m_whitespace.find(c) < 0)) {
|
||||
tokstr += c;
|
||||
/* expensive, check for single char tokens */
|
||||
if (tokstr.len() == 1)
|
||||
{
|
||||
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
|
||||
if (id.id() >= 0)
|
||||
return token_t(id, tokstr);
|
||||
}
|
||||
c = getc();
|
||||
}
|
||||
ungetc();
|
||||
token_id_t id = token_id_t(m_tokens.indexof(tokstr));
|
||||
if (id.id() >= 0)
|
||||
return token_t(id, tokstr);
|
||||
else
|
||||
{
|
||||
return token_t(UNKNOWN, tokstr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ATTR_COLD void ptokenizer::error(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
@ -22,14 +244,19 @@ ATTR_COLD void netlist_parser::error(const char *format, ...)
|
||||
pstring errmsg1 =pstring(format).vprintf(ap);
|
||||
va_end(ap);
|
||||
|
||||
char buf[300];
|
||||
int bufp = 0;
|
||||
const char *p = m_line_ptr;
|
||||
while (*p && *p != 10)
|
||||
buf[bufp++] = *p++;
|
||||
buf[bufp] = 0;
|
||||
verror(errmsg1, currentline_no(), currentline_str());
|
||||
|
||||
m_setup.netlist().error("line %d: error: %s\n\t\t%s\n", m_line, errmsg1.cstr(), buf);
|
||||
//throw error;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// A netlist parser
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
ATTR_COLD void netlist_parser::verror(pstring msg, int line_num, pstring line)
|
||||
{
|
||||
m_setup.netlist().error("line %d: error: %s\n\t\t%s\n", line_num,
|
||||
msg.cstr(), line.cstr());
|
||||
|
||||
//throw error;
|
||||
}
|
||||
@ -37,77 +264,100 @@ ATTR_COLD void netlist_parser::error(const char *format, ...)
|
||||
|
||||
void netlist_parser::parse(const char *buf)
|
||||
{
|
||||
m_px = buf;
|
||||
m_line_ptr = buf;
|
||||
m_line = 1;
|
||||
reset(buf);
|
||||
set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
|
||||
set_number_chars("01234567890eE-."); //FIXME: processing of numbers
|
||||
char ws[5];
|
||||
ws[0] = ' ';
|
||||
ws[1] = 9;
|
||||
ws[2] = 10;
|
||||
ws[3] = 13;
|
||||
ws[4] = 0;
|
||||
set_whitespace(ws);
|
||||
set_comment("/*", "*/", "//");
|
||||
m_tok_param_left = register_token("(");
|
||||
m_tok_param_right = register_token(")");
|
||||
m_tok_comma = register_token(",");
|
||||
|
||||
while (!eof())
|
||||
m_tok_ALIAS = register_token("ALIAS");
|
||||
m_tok_NET_C = register_token("NET_C");
|
||||
m_tok_PARAM = register_token("PARAM");
|
||||
m_tok_NET_MODEL = register_token("PARAM");
|
||||
m_tok_NETLIST_START = register_token("NETLIST_START");
|
||||
m_tok_NETLIST_END = register_token("NETLIST_END");
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
pstring n;
|
||||
skipws();
|
||||
if (eof()) break;
|
||||
n = getname('(');
|
||||
NL_VERBOSE_OUT(("Parser: Device: %s\n", n.cstr()));
|
||||
if (n == "ALIAS")
|
||||
net_alias();
|
||||
else if (n == "NET_C")
|
||||
net_c();
|
||||
else if (n == "PARAM")
|
||||
netdev_param();
|
||||
else if ((n == "NET_MODEL"))
|
||||
net_model();
|
||||
else if (n == "NETLIST_START")
|
||||
netdev_netlist_start();
|
||||
else if (n == "NETLIST_END")
|
||||
token_t token = get_token();
|
||||
|
||||
if (token.is_type(ENDOFFILE))
|
||||
return;
|
||||
|
||||
require_token(m_tok_param_left);
|
||||
NL_VERBOSE_OUT(("Parser: Device: %s\n", n.cstr()));
|
||||
|
||||
if (token.is(m_tok_ALIAS))
|
||||
net_alias();
|
||||
else if (token.is(m_tok_NET_C))
|
||||
net_c();
|
||||
else if (token.is(m_tok_PARAM))
|
||||
netdev_param();
|
||||
else if (token.is(m_tok_NET_MODEL))
|
||||
net_model();
|
||||
else if (token.is(m_tok_NETLIST_START))
|
||||
netdev_netlist_start();
|
||||
else if (token.is(m_tok_NETLIST_END))
|
||||
netdev_netlist_end();
|
||||
else
|
||||
device(n);
|
||||
else
|
||||
device(token.str());
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_parser::netdev_netlist_start()
|
||||
{
|
||||
// don't do much
|
||||
skipws();
|
||||
/*pstring dummyname = */ getname(')');
|
||||
//check_char(')');
|
||||
token_t name = get_token();
|
||||
require_token(m_tok_param_right);
|
||||
}
|
||||
|
||||
void netlist_parser::netdev_netlist_end()
|
||||
{
|
||||
// don't do much
|
||||
skipws();
|
||||
check_char(')');
|
||||
require_token(m_tok_param_right);
|
||||
}
|
||||
|
||||
void netlist_parser::net_model()
|
||||
{
|
||||
// don't do much
|
||||
pstring model = getstring();
|
||||
pstring model = get_string();
|
||||
m_setup.register_model(model);
|
||||
check_char(')');
|
||||
require_token(m_tok_param_right);
|
||||
}
|
||||
|
||||
void netlist_parser::net_alias()
|
||||
{
|
||||
pstring alias;
|
||||
pstring out;
|
||||
skipws();
|
||||
alias = getname(',');
|
||||
skipws();
|
||||
out = getname(')');
|
||||
pstring alias = get_identifier();
|
||||
|
||||
require_token(m_tok_comma);
|
||||
|
||||
pstring out = get_identifier();
|
||||
|
||||
require_token(m_tok_param_right);
|
||||
|
||||
NL_VERBOSE_OUT(("Parser: Alias: %s %s\n", alias.cstr(), out.cstr()));
|
||||
m_setup.register_alias(alias, out);
|
||||
}
|
||||
|
||||
void netlist_parser::net_c()
|
||||
{
|
||||
pstring t1;
|
||||
pstring t2;
|
||||
skipws();
|
||||
t1 = getname(',');
|
||||
skipws();
|
||||
t2 = getname(')');
|
||||
pstring t1 = get_identifier();
|
||||
|
||||
require_token(m_tok_comma);
|
||||
pstring t2 = get_identifier();
|
||||
|
||||
require_token(m_tok_param_right);
|
||||
|
||||
NL_VERBOSE_OUT(("Parser: Connect: %s %s\n", t1.cstr(), t2.cstr()));
|
||||
m_setup.register_link(t1 , t2);
|
||||
}
|
||||
@ -116,13 +366,12 @@ void netlist_parser::netdev_param()
|
||||
{
|
||||
pstring param;
|
||||
double val;
|
||||
skipws();
|
||||
param = getname(',');
|
||||
skipws();
|
||||
val = eval_param();
|
||||
param = get_identifier();
|
||||
require_token(m_tok_comma);
|
||||
val = eval_param(get_token());
|
||||
NL_VERBOSE_OUT(("Parser: Param: %s %f\n", param.cstr(), val));
|
||||
m_setup.register_param(param, val);
|
||||
check_char(')');
|
||||
require_token(m_tok_param_right);
|
||||
}
|
||||
|
||||
void netlist_parser::device(const pstring &dev_type)
|
||||
@ -132,11 +381,12 @@ void netlist_parser::device(const pstring &dev_type)
|
||||
netlist_device_t *dev;
|
||||
nl_util::pstring_list termlist = f->term_param_list();
|
||||
pstring def_param = f->def_param();
|
||||
token_t tok;
|
||||
|
||||
int cnt;
|
||||
|
||||
skipws();
|
||||
devname = getname2(',', ')');
|
||||
devname = get_identifier();
|
||||
|
||||
dev = f->Create();
|
||||
m_setup.register_dev(dev, devname);
|
||||
|
||||
@ -146,35 +396,34 @@ void netlist_parser::device(const pstring &dev_type)
|
||||
{
|
||||
pstring paramfq = devname + "." + def_param;
|
||||
NL_VERBOSE_OUT(("Defparam: %s\n", def_param.cstr()));
|
||||
check_char(',');
|
||||
skipws();
|
||||
if (peekc() == '"')
|
||||
require_token(m_tok_comma);
|
||||
|
||||
tok = get_token();
|
||||
if (tok.is_type(STRING))
|
||||
{
|
||||
pstring val = getstring();
|
||||
m_setup.register_param(paramfq, val);
|
||||
m_setup.register_param(paramfq, tok.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
double val = eval_param();
|
||||
double val = eval_param(tok);
|
||||
m_setup.register_param(paramfq, val);
|
||||
}
|
||||
if (termlist.count() > 0)
|
||||
check_char(',');
|
||||
}
|
||||
|
||||
tok = get_token();
|
||||
cnt = 0;
|
||||
while (getc() != ')' && cnt < termlist.count())
|
||||
while (tok.is(m_tok_comma) && cnt < termlist.count())
|
||||
{
|
||||
skipws();
|
||||
pstring output_name = getname2(',', ')');
|
||||
pstring output_name = get_identifier();
|
||||
|
||||
m_setup.register_link(devname + "." + termlist[cnt], output_name);
|
||||
|
||||
skipws();
|
||||
cnt++;
|
||||
tok = get_token();
|
||||
}
|
||||
if (cnt != termlist.count())
|
||||
fatalerror("netlist: input count mismatch for %s - expected %d found %d\n", devname.cstr(), termlist.count(), cnt);
|
||||
require_token(tok, m_tok_param_right);
|
||||
}
|
||||
|
||||
|
||||
@ -182,167 +431,35 @@ void netlist_parser::device(const pstring &dev_type)
|
||||
// private
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
void netlist_parser::skipeol()
|
||||
{
|
||||
char c = getc();
|
||||
while (c)
|
||||
{
|
||||
if (c == 10)
|
||||
{
|
||||
c = getc();
|
||||
if (c != 13)
|
||||
ungetc();
|
||||
return;
|
||||
}
|
||||
c = getc();
|
||||
}
|
||||
}
|
||||
|
||||
void netlist_parser::skipws()
|
||||
double netlist_parser::eval_param(const token_t tok)
|
||||
{
|
||||
while (unsigned char c = getc())
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case ' ':
|
||||
case 9:
|
||||
case 10:
|
||||
case 13:
|
||||
break;
|
||||
case '#':
|
||||
skipeol(); // treat preprocessor defines as comments
|
||||
break;
|
||||
case '/':
|
||||
c = getc();
|
||||
if (c == '/')
|
||||
{
|
||||
skipeol();
|
||||
}
|
||||
else if (c == '*')
|
||||
{
|
||||
int f=0;
|
||||
while (!eof() )
|
||||
{
|
||||
c = getc();
|
||||
if (f == 0 && c == '*')
|
||||
f=1;
|
||||
else if (f == 1 && c== '/' )
|
||||
break;
|
||||
else
|
||||
f=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ungetc();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pstring netlist_parser::getstring()
|
||||
{
|
||||
skipws();
|
||||
check_char('"');
|
||||
pstring ret = getname2_ext('"', 0, NULL);
|
||||
check_char('"');
|
||||
skipws();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
pstring netlist_parser::getname(char sep)
|
||||
{
|
||||
pstring ret = getname2(sep, 0);
|
||||
getc(); // undo the undo ...
|
||||
return ret;
|
||||
}
|
||||
|
||||
pstring netlist_parser::getname2(char sep1, char sep2)
|
||||
{
|
||||
static const char *allowed = "0123456789_.ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
return getname2_ext(sep1, sep2, allowed);
|
||||
}
|
||||
|
||||
pstring netlist_parser::getname2_ext(char sep1, char sep2, const char *allowed)
|
||||
{
|
||||
char buf[1024];
|
||||
char *p1 = buf;
|
||||
char c=getc();
|
||||
|
||||
while ((c != sep1) && (c != sep2))
|
||||
{
|
||||
char cU = toupper(c);
|
||||
if ((allowed == NULL) || strchr(allowed, cU) != NULL)
|
||||
*p1++ = c;
|
||||
else
|
||||
{
|
||||
*p1 = 0;
|
||||
error("illegal character <%c> in name ...\n", c);
|
||||
}
|
||||
c = getc();
|
||||
}
|
||||
*p1 = 0;
|
||||
ungetc();
|
||||
return pstring(buf);
|
||||
}
|
||||
void netlist_parser::check_char(char ctocheck)
|
||||
{
|
||||
skipws();
|
||||
char c = getc();
|
||||
if ( c == ctocheck)
|
||||
{
|
||||
return;
|
||||
}
|
||||
error("expected '%c' found '%c'\n", ctocheck, c);
|
||||
}
|
||||
|
||||
double netlist_parser::eval_param()
|
||||
{
|
||||
static const char *macs[6] = {"", "RES_K(", "RES_M(", "CAP_U(", "CAP_N(", "CAP_P("};
|
||||
static const char *allowed = "RESKMUNPAC_0123456789E(+-.";
|
||||
static const char *macs[6] = {"", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"};
|
||||
static double facs[6] = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
|
||||
int i;
|
||||
int f=0;
|
||||
bool e;
|
||||
double ret;
|
||||
pstring val;
|
||||
|
||||
pstring s = getname2_ext(')',',', allowed);
|
||||
|
||||
//printf("param %s\n", tok.m_token.cstr());
|
||||
for (i=1; i<6;i++)
|
||||
if (strncmp(s.cstr(), macs[i], strlen(macs[i])) == 0)
|
||||
if (tok.str().equals(macs[i]))
|
||||
f = i;
|
||||
if (f>0)
|
||||
check_char(')');
|
||||
s = s.substr(strlen(macs[f]));
|
||||
ret = s.as_double(&e);
|
||||
// if ((f>0) && e)
|
||||
if (e)
|
||||
{
|
||||
require_token(m_tok_param_left);
|
||||
val = get_identifier();
|
||||
}
|
||||
else
|
||||
val = tok.str();
|
||||
|
||||
ret = val.as_double(&e);
|
||||
|
||||
if (e)
|
||||
error("Error with parameter ...\n");
|
||||
if (f>0)
|
||||
require_token(m_tok_param_right);
|
||||
return ret * facs[f];
|
||||
}
|
||||
|
||||
unsigned char netlist_parser::peekc()
|
||||
{
|
||||
unsigned char c = getc();
|
||||
ungetc();
|
||||
return c;
|
||||
}
|
||||
|
||||
unsigned char netlist_parser::getc()
|
||||
{
|
||||
if (*m_px == 10)
|
||||
{
|
||||
m_line++;
|
||||
m_line_ptr = m_px + 1;
|
||||
}
|
||||
if (*m_px)
|
||||
return *(m_px++);
|
||||
else
|
||||
return *m_px;
|
||||
}
|
||||
|
||||
void netlist_parser::ungetc()
|
||||
{
|
||||
m_px--;
|
||||
}
|
||||
|
@ -10,12 +10,139 @@
|
||||
|
||||
#include "nl_setup.h"
|
||||
|
||||
class netlist_parser
|
||||
class ptokenizer
|
||||
{
|
||||
NETLIST_PREVENT_COPYING(ptokenizer)
|
||||
public:
|
||||
ptokenizer()
|
||||
: m_line(1), m_line_ptr(NULL), m_px(NULL)
|
||||
{}
|
||||
|
||||
enum token_type
|
||||
{
|
||||
IDENTIFIER,
|
||||
NUMBER,
|
||||
TOKEN,
|
||||
STRING,
|
||||
COMMENT,
|
||||
UNKNOWN,
|
||||
ENDOFFILE,
|
||||
};
|
||||
|
||||
struct token_id_t
|
||||
{
|
||||
public:
|
||||
token_id_t() : m_id(-2) {}
|
||||
token_id_t(const int id) : m_id(id) {}
|
||||
const int id() const { return m_id; }
|
||||
private:
|
||||
int m_id;
|
||||
};
|
||||
|
||||
struct token_t
|
||||
{
|
||||
token_t() {};
|
||||
token_t(token_type type)
|
||||
{
|
||||
m_type = type;
|
||||
m_id = token_id_t(-1);
|
||||
m_token ="";
|
||||
}
|
||||
token_t(token_type type, const pstring str)
|
||||
{
|
||||
m_type = type;
|
||||
m_id = token_id_t(-1);
|
||||
m_token = str;
|
||||
}
|
||||
token_t(const token_id_t id, const pstring str)
|
||||
{
|
||||
m_type = TOKEN;
|
||||
m_id = id;
|
||||
m_token = str;
|
||||
}
|
||||
|
||||
bool is(const token_id_t &tok_id) const { return m_id.id() == tok_id.id(); }
|
||||
bool is_not(const token_id_t &tok_id) const { return !is(tok_id); }
|
||||
|
||||
bool is_type(const token_type type) const { return m_type == type; }
|
||||
|
||||
pstring str() const { return m_token; }
|
||||
|
||||
private:
|
||||
token_type m_type;
|
||||
token_id_t m_id;
|
||||
pstring m_token;
|
||||
};
|
||||
|
||||
|
||||
int currentline_no() { return m_line; }
|
||||
pstring currentline_str();
|
||||
|
||||
/* tokenizer stuff follows ... */
|
||||
|
||||
token_t get_token();
|
||||
pstring get_string();
|
||||
pstring get_identifier();
|
||||
|
||||
void require_token(const token_id_t &token_num);
|
||||
void require_token(const token_t tok, const token_id_t &token_num);
|
||||
|
||||
token_id_t register_token(pstring token)
|
||||
{
|
||||
m_tokens.add(token);
|
||||
return token_id_t(m_tokens.count() - 1);
|
||||
}
|
||||
|
||||
void set_identifier_chars(pstring s) { m_identifier_chars = s; }
|
||||
void set_number_chars(pstring s) { m_number_chars = s; }
|
||||
void set_whitespace(pstring s) { m_whitespace = s; }
|
||||
void set_comment(pstring start, pstring end, pstring line)
|
||||
{
|
||||
m_tok_comment_start = register_token(start);
|
||||
m_tok_comment_end = register_token(end);
|
||||
m_tok_line_comment = register_token(line);
|
||||
m_string = '"';
|
||||
}
|
||||
|
||||
token_t get_token_internal();
|
||||
void error(const char *format, ...);
|
||||
|
||||
protected:
|
||||
void reset(const char *p) { m_px = p; m_line = 1; m_line_ptr = p; }
|
||||
virtual void verror(pstring msg, int line_num, pstring line) = 0;
|
||||
|
||||
private:
|
||||
void skipeol();
|
||||
void skipws();
|
||||
|
||||
unsigned char peekc();
|
||||
unsigned char getc();
|
||||
void ungetc();
|
||||
bool eof() { return *m_px == 0; }
|
||||
|
||||
int m_line;
|
||||
const char * m_line_ptr;
|
||||
const char * m_px;
|
||||
|
||||
/* tokenizer stuff follows ... */
|
||||
|
||||
pstring m_identifier_chars;
|
||||
pstring m_number_chars;
|
||||
netlist_list_t<pstring> m_tokens;
|
||||
pstring m_whitespace;
|
||||
char m_string;
|
||||
|
||||
token_id_t m_tok_comment_start;
|
||||
token_id_t m_tok_comment_end;
|
||||
token_id_t m_tok_line_comment;
|
||||
};
|
||||
|
||||
class netlist_parser : public ptokenizer
|
||||
{
|
||||
NETLIST_PREVENT_COPYING(netlist_parser)
|
||||
public:
|
||||
netlist_parser(netlist_setup_t &setup)
|
||||
: m_line(1), m_line_ptr(NULL), m_px(NULL), m_setup(setup) {}
|
||||
: ptokenizer(), m_setup(setup) {}
|
||||
|
||||
void parse(const char *buf);
|
||||
void net_alias();
|
||||
@ -26,27 +153,23 @@ public:
|
||||
void netdev_netlist_end();
|
||||
void net_model();
|
||||
|
||||
void error(const char *format, ...);
|
||||
protected:
|
||||
virtual void verror(pstring msg, int line_num, pstring line);
|
||||
private:
|
||||
|
||||
void skipeol();
|
||||
void skipws();
|
||||
pstring getname(char sep);
|
||||
pstring getname2(char sep1, char sep2);
|
||||
pstring getname2_ext(char sep1, char sep2, const char *allowed);
|
||||
void check_char(char ctocheck);
|
||||
double eval_param();
|
||||
pstring getstring();
|
||||
double eval_param(const token_t tok);
|
||||
|
||||
unsigned char peekc();
|
||||
unsigned char getc();
|
||||
void ungetc();
|
||||
bool eof() { return *m_px == 0; }
|
||||
token_id_t m_tok_param_left;
|
||||
token_id_t m_tok_param_right;
|
||||
token_id_t m_tok_comma;
|
||||
token_id_t m_tok_ALIAS;
|
||||
token_id_t m_tok_NET_C;
|
||||
token_id_t m_tok_PARAM;
|
||||
token_id_t m_tok_NET_MODEL;
|
||||
token_id_t m_tok_NETLIST_START;
|
||||
token_id_t m_tok_NETLIST_END;
|
||||
|
||||
int m_line;
|
||||
const char * m_line_ptr;
|
||||
const char * m_px;
|
||||
netlist_setup_t &m_setup;
|
||||
netlist_setup_t &m_setup;
|
||||
};
|
||||
|
||||
|
||||
|
@ -120,8 +120,8 @@ public:
|
||||
//
|
||||
inline int len() const { return m_ptr->len(); }
|
||||
|
||||
inline bool equals(const pstring &string) { return (pcmp(string.cstr(), m_ptr->str()) == 0); }
|
||||
inline bool iequals(const pstring &string) { return (pcmpi(string.cstr(), m_ptr->str()) == 0); }
|
||||
inline bool equals(const pstring &string) const { return (pcmp(string.cstr(), m_ptr->str()) == 0); }
|
||||
inline bool iequals(const pstring &string) const { return (pcmpi(string.cstr(), m_ptr->str()) == 0); }
|
||||
|
||||
inline int cmp(const pstring &string) const { return pcmp(string.cstr()); }
|
||||
inline int cmpi(const pstring &string) const { return pcmpi(cstr(), string.cstr()); }
|
||||
|
Loading…
Reference in New Issue
Block a user