The lexer incorrectly treats a single '_' '-' '/' as an identifier. The counter used for tmp__ names should be incremented after use. The infix_to_postfix converter now has more checks for invalid infix expressions in LOGICEXP constructs. Without these checks the evaluation of the generated postfix could silently create bad gates which would load but simulate incorrectly. All MicroCap and PSpice libraries and QEI.cir pass their tests.

This commit is contained in:
Brian Taylor 2024-03-10 16:03:59 -07:00 committed by Holger Vogt
parent ae8e423d97
commit 14bf034f28
1 changed files with 40 additions and 3 deletions

View File

@ -353,10 +353,14 @@ static int lexer_scan(LEXER lx)
return c;
else if (lex_ident(c)) {
size_t i = 0;
BOOL need_gt1 = FALSE;
if (c == '+') { // an identifier does not begin with '+'
lx->lexer_buf[0] = (char) c;
lx->lexer_buf[1] = '\0';
return LEX_OTHER;
} else if (c == '_' || c == '/' || c == '-') {
// these need to be followed by at least one more ident
need_gt1 = TRUE;
}
while (lex_ident(c)) {
if (i >= lx->lexer_blen) {
@ -368,6 +372,10 @@ static int lexer_scan(LEXER lx)
i++;
c = lexer_getchar(lx);
}
if (i == 1 && need_gt1) {
lx->lexer_buf[1] = '\0';
return LEX_OTHER;
}
if (i >= lx->lexer_blen) {
lx->lexer_blen *= 2;
lx->lexer_buf =
@ -733,19 +741,37 @@ static int infix_to_postfix(char* infix, DSTRING * postfix_p)
LEXER lx;
NAME_ENTRY nlist = NULL, entry = NULL;
int status = 0;
int lparen_count = 0, rparen_count = 0;
lx = new_lexer(infix);
stack.top = -1;
nlist = add_name_entry("first", NULL);
ds_clear(postfix_p);
while ( ( ltok = lexer_scan(lx) ) != 0 ) { // start while ltok loop
if (ltok == '(') { lparen_count++; }
if (ltok == ')') { rparen_count++; }
if (ltok == LEX_ID && last_tok == LEX_ID) {
fprintf(stderr, "ERROR no gate operator between two identifiers\n");
fprintf(stderr, "ERROR (1) no gate operator between two identifiers\n");
status = 1;
goto err_return;
}
if (lex_gate_op(ltok) && lex_gate_op(last_tok)) {
fprintf(stderr, "ERROR two consecutive gate operators\n");
fprintf(stderr, "ERROR (2) two consecutive gate operators\n");
status = 1;
goto err_return;
}
if (last_tok == '~' && ltok != LEX_ID && ltok != '(') {
fprintf(stderr, "ERROR (3) \'~\' is not followed by an ID or lparen\n");
status = 1;
goto err_return;
}
if (ltok == '~' && (last_tok == LEX_ID || last_tok == ')')) {
fprintf(stderr, "ERROR (4) \'~\' follows an ID or rparen\n");
status = 1;
goto err_return;
}
if (ltok == ')' && (lex_gate_op(last_tok) || last_tok == '~')) {
fprintf(stderr, "ERROR (5) incomplete infix sub-expression\n");
status = 1;
goto err_return;
}
@ -775,6 +801,7 @@ static int infix_to_postfix(char* infix, DSTRING * postfix_p)
next_tok = lexer_scan(lx);
if (next_tok == LEX_ID) {
ds_cat_printf(postfix_p, " tilde_%s", lx->lexer_buf);
last_tok = next_tok;
continue; // while ltok loop
} else {
lexer_back_one(lx);
@ -787,12 +814,22 @@ static int infix_to_postfix(char* infix, DSTRING * postfix_p)
entry = add_name_entry(tokstr, nlist);
if (push(&stack, entry->name)) goto err_return;
} else {
fprintf(stderr, "ERROR unexpected infix token %d \'%s\'\n",
fprintf(stderr, "ERROR (6) unexpected infix token %d \'%s\'\n",
ltok, lx->lexer_buf);
status = 1;
goto err_return;
}
} // end while ltok loop
if (lex_gate_op(last_tok) || last_tok == '~') {
fprintf(stderr, "ERROR (7) incomplete infix expression\n");
status = 1;
goto err_return;
}
if (lparen_count != rparen_count) {
fprintf(stderr, "ERROR (8) mismatched parentheses\n");
status = 1;
goto err_return;
}
while (stack.top != -1) {
ds_cat_printf(postfix_p, " %s", pop(&stack, &status));
if (status) goto err_return;