; CHECKPAR
;
; Program for Proteus
;
; (C) 1998-2004 Simone Zanella Productions
;
; Verify that the number of open parenthesis ('(', '[', '{') matches the number
; of closing parenthesis (')', ']', '}'); parenthesis inside strings are ignored.
; No output file is produced; messages are sent to console.
;!proteus -o
; Initialize
FUNCTION ONSTART()
IF STREQ(ARGV(3), "..")
CONSOLELN "Syntax: " ARGV(1) " " ARGV(2) " source"
CONSOLELN ""
CONSOLELN "Purpose: verify parenthesis match"
ABORT 0
FI
; Stack to keep parenthesis
_ParStack = STACKNEW()
RETURN
; First, remove '"' and '\"'
L = STRTRAN(L, "'\\\"'", "")
L = STRTRAN(L, "'\"'", "")
; Then, remove strings
X = STRSTR(L, "\"")
WHILE X
Prev = " "
FOR Y = INC(X) TO STRLEN(L)
Car = SUBSTR(L, Y, 1)
IF AND(STREQ(Car, "\""), \
NOT(STREQ(Prev, "\\")))
BREAK
FI
IF AND(STREQ(Car, "\\"), STREQ(Prev, "\\"))
Prev = " "
ELSE
Prev = Car
FI
NEXT
L = DELETE(L, X, INC(SUB(Y, X)))
X = STRSTR(L, "\"")
LOOP
; At last, remove single characters: '(', ')', '[', ']', '{', '}'
L = STRTRAN(L, "'('", "")
L = STRTRAN(L, "')'", "")
L = STRTRAN(L, "'['", "")
L = STRTRAN(L, "']'", "")
L = STRTRAN(L, "'{'", "")
L = STRTRAN(L, "'}'", "")
; Now find parenthesis
X = STRPBRK(L, "[]{}()")
WHILE X
; Found: isolate character
Car = SUBSTR(L, X, 1)
L = SUBSTR(L, INC(X), STRLEN(L))
; Open -> push
IF STRPBRK(Car, "[{(")
PUSH(ParStack, Car)
ELSE
; Closed -> pop
IF STACKHEIGHT(ParStack)
SCar = STACKTOP(ParStack, 0)
IF OR(OR(AND(STREQ(Car, ")"), STREQ(SCar, "(")), \
AND(STREQ(Car, "]"), STREQ(SCar, "["))), \
AND(STREQ(Car, "}"), STREQ(SCar, "{")))
POP(ParStack)
ELSE
CONSOLELN "Error (" ARGV(3) \
"): mismatch at line " \
N ", symbol \"" Car "\"."
ShowStack(ParStack)
ABORT 1
FI
ELSE
CONSOLELN "Error (" ARGV(3) \
"): line " N ", \'" Car \
"\' closed without opening."
ABORT 1
FI
FI
X = STRPBRK(L, "[]{}()")
LOOP
FUNCTION ONEND()
IF STACKHEIGHT(PUB(ParStack))
CONSOLELN "Error (" ARGV(3) \
"): end of file met with open parenthesis."
ShowStack(PUB(ParStack))
ABORT 1
FI
CONSOLELN "The program " ARGV(3) " is correct."
RETURN
FUNCTION ShowStack(parstack)
CONSOLELN "Parenthesis stack: "
FOR x = STACKHEIGHT(parstack) TO 0 STEP -1
CONSOLE POP(parstack)
NEXT
CONSOLELN ""
RETURN