Skip to content

Instantly share code, notes, and snippets.

@toomasv
Last active March 16, 2019 22:25
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save toomasv/c78254ecdd970b623417e5b2146a0e0a to your computer and use it in GitHub Desktop.
Save toomasv/c78254ecdd970b623417e5b2146a0e0a to your computer and use it in GitHub Desktop.
Checking for matching/closing of nested thing and strings
Red []
ctx: context [
char: charset {([{}])"} ;"
opens: charset "[("
closes: charset "])"
line: 1
stack: make block! 1000
mark: comm: none
instr: false
inmulti: 0
str: copy ""
err: func [msg][cause-error 'user 'message reduce [rejoin msg]]
marks: "][)("
set 'check func [file [string!]][
line: 1
clear stack
mark: comm: none
instr: false
inmulti: 0
clear str
parse file [some [s:
#";" (unless any [instr inmulti > 0][comm: yes])
| [{#"} char #"^"" | #"^^" char]
| newline (line: line + 1 comm: none if instr [err ["Line-break inside simple string on line " line - 1]])
| [{^^"} | "^^{" | "^^}"] [if (any [instr inmulti > 0 comm]) | (err ["Lonely escaped string-char on line " line])]
| #"^"" (unless any [inmulti > 0 comm] [instr: pick [#[false] #[true]] instr]) ;"
| #"{" [if (not any [instr comm]) (inmulti: inmulti + 1 repend stack ['brace line]) |]
| #"}" [if (not any [instr comm]) (inmulti: inmulti - 1 if empty? mark: take/last/part stack 2 [
err ["Closing brace without opening one on line " line]
])[
if (mark/1 = 'brace)
| (err ["Wrong closing-brace on line " line " inside " mark/1 " from line " mark/2])
] |]
| opens [if (not any [instr inmulti > 0 comm]) (repend stack [s/1 line]) |]
| closes [if (not any [instr inmulti > 0 comm]) (if empty? mark: take/last/part stack 2 [
err ["Closing " pick ["bracket" "paren"] s/1 = #"]" " without opening one on line " line]
])[
if (mark/1 = select marks s/1)
| (err ["Wrong closing-" pick ["bracket" "paren"] s/1 = #"]"
" on line " line " inside " pick ["bracket" "paren"] mark/1 = #"[" " from line " mark/2])
] |]
| skip
]]
either empty? stack [true][
foreach [t l] stack [repend str: "" [pick ["bracket" "paren"] t = #"[" " line " l "; "]]
err [ "Stack not empty in the end of file. Open: " head str]
]
]
]
@toomasv
Copy link
Author

toomasv commented Jan 5, 2019

do %check.red
check read %<your-file-name>.red
or
check <string!>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment