From 14bf034f28223beee4aa0bbd2f331be0c96bd7e8 Mon Sep 17 00:00:00 2001 From: Brian Taylor Date: Sun, 10 Mar 2024 16:03:59 -0700 Subject: [PATCH] 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. --- src/frontend/logicexp.c | 43 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/frontend/logicexp.c b/src/frontend/logicexp.c index 614f4a57a..7ca949d82 100644 --- a/src/frontend/logicexp.c +++ b/src/frontend/logicexp.c @@ -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;