Last active
June 7, 2025 13:20
-
-
Save ne1uno/44b942855d36c5317a095c59ebd76681 to your computer and use it in GitHub Desktop.
parse/trace call back example gui demo in red-lang
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
get red-lang from red-lang.org | |
takeoff on a red-lang gitter post from 2018 about parse-?? custom tracing | |
un-comment at do-parse to see the demo parse-trace and parse/trace :callback | |
gui is from a simplified parse tab in my unpublished ne1 clean-script tool | |
cGPT suggested some utf color markers for succeed/fail that improve readability | |
difficult to imagine how to make trace debug parse rules without showing everything | |
;credits, | |
; 2018 post in gitter/red/parse @endo64, @gltewalt, @gltewalt & others for parse ideas | |
; splitters I think from live code enhanced on gist or @toomasv dx2 demo? | |
the examples are really to demo the custom trace and maybe not great parse examples | |
the sliders and area size calculations are a bit sloppy, please don't blame the sources | |
they need a limit so they can't be dropped in the wrong place | |
resizing doesn't account for scroll bars propeely so it's a bit of an adventure | |
Red [ | |
Title: "parse tracing" | |
File: %parse-??.red | |
Version: 0.1 | |
Needs: 'View | |
] | |
; system/view/debug?: on ; does step by step print of layout | |
line-end: "^/" ; crlf in area in windows seems to work better? otherwise ^M or ^/ | |
random/seed now/time/precise | |
;parse gui is setup to run a function live to demonstrate the parse trace | |
; a top row of buttons to clear areas, parse and quit | |
; p1..p4 area/text with 3 horizontal splitters between them | |
; there is no error reporting in the virtual function used in the demo | |
; they may just silently fail with typo or syntax errors, be warned. | |
P-def: random 4 | |
; select 1st 2nd 3rd nth example, drop-list to choose in ui however many | |
; each block of P-drop is 3 strings. | |
; [[{title}{function}{data}]...] , output of function will be to p3. trace to p4 | |
; <1> message for p3 <2> function spec & body for p1 <3> data to parse | |
; form gets rendered and errors on some char literal is why charset reduce works | |
; there few no error checks on the function syntax in this demo | |
; if you see nothing happening when you click parse that may be one reason why | |
; p1 area is not a full editor so has the normal area editing, it's a demo... | |
; p2 area data needs to be loadable as string or block | |
; the examples don't have to use parse, it is normal red language code | |
; it might've been simpler to read/write example scripts to/from disk | |
P-drop: [ | |
[{parse-block-demo} ;<P-d1> simpler test, | |
{["function spec & body body to parse data from P2 area" | |
data [series! block!] "from P2 area" | |
/local out spc rule et ;tag val not sure how parse words propagate | |
][ ;could be dangerous, don't do anything stupid | |
out: clear [] | |
print ['data mold data] | |
rule: [ | |
some [ | |
copy tag set-word! | |
copy val [integer! | string! | set-word! | word!] | |
(append/only out reduce [tag val]) | |
] | |
] | |
; et: parse-trace data rule ;default-trace prints to console | |
; et: parse data rule ;no-trace | |
et: parse-?? data rule 45 ;n=depth custom trace redirect enabled | |
reduce [et out] | |
]} | |
{[name: "Alice" age: 30 logged-in: true]} | |
] | |
; converts string like "2 +3 -4 'cmt" to [2 + 3 - 4] ignoring 'cmt not much error checking | |
[{parse-mlstring-code} ;<P-d2> | |
{["function spec & body body to parse data from P2 area" | |
data [series! block!] "from P2 area" | |
/local out rule spcs et lf digit sign ncmt v vars i x | |
][ ;could be dangerous, don't do anything stupid | |
out: clear [] | |
;data: "1 +3 'cmt" | |
print ['data mold data] | |
;crlf? area renders char literal | |
;note: ^^+- as tab, ^^+/ will embed a newline string or comment | |
spcs: charset reduce [space tab newline] | |
lf: charset reduce [newline] | |
digit: charset "0123456789." | |
sign: charset "+-" | |
ncmt: complement charset reduce ["'" newline] | |
rule: [ | |
some [ | |
some [spcs | end] | |
| [copy v [some [sign]] (append out v)] | |
| [copy v [some [digit]] (append out v)] | |
| ["'" any ncmt any [lf | end]] ; skip comment to end of line | |
] | |
] | |
; et: parse-trace data rule ;default-trace prints to console | |
; et: parse data rule ;no-trace | |
et: parse-?? data rule 45 ;n=depth custom trace redirect enabled | |
;rework the strings | |
print ["math ans=" attempt [math probe vars: collect [ | |
foreach [i x] probe out [ | |
keep reduce [to-float i] | |
keep either x [first to-block x][continue] | |
] | |
]]] | |
print reduce [";ans=" do vars] | |
append p3/text " p3/text output functest " ;don't try to embed ^-^/ | |
reduce [et out] | |
]} | |
{{5 +8 'cmt}} ;not a math replacement, only sums signed numbers as a demo | |
] | |
[{parse-string-char-counter} ;<P-d4> ; show skip if not a letter | |
{["function spec & body body to parse data from P2 area" | |
data [series!] "from P2 area" | |
/local out spc rule et letters counts ;ch cur | |
][ ;could be dangerous, don't do anything stupid | |
out: clear [] | |
print ['data mold trim data] | |
letters: charset "abcdefghijklmnopqrstuvwxyz" | |
counts: make map! [] | |
rule: [ | |
some [ | |
copy ch [letters | skip] | |
( | |
either all [ch curr: counts/:ch] [counts/:ch: curr + 1][counts/:ch: 1] | |
) | |
;end | |
] | |
] | |
et: parse-?? data rule 45 ;n=depth custom trace redirect enabled | |
probe append out counts | |
reduce [et out] | |
]} | |
{"all 5"} | |
] | |
[{parse-string-block-code} ;<P-d4> empty template | |
{["function spec & body body to parse data from P2 area" | |
data [string! block!] "from P2 area" | |
/local out spc rule et ;var | |
][ ;could be dangerous, don't do anything stupid | |
out: clear [] | |
print ['data mold trim data] | |
spc: charset reduce [space tab] | |
rule: [ | |
some [copy var [word! | string! | end] (append out var)] | |
] ; | |
et: parse-?? data rule 45 ;n=depth custom trace redirect enabled | |
reduce [et out] | |
]} | |
{[data block "data string"] | |
} | |
] | |
] | |
;for cli use bypass gui area/text | |
p4a: none | |
to-area: no | |
init-areas: func [ | |
P-def "integer block of P-drop to use" | |
][ | |
p1/text: P-drop/:P-def/2 | |
p2/text: P-drop/:P-def/3 | |
p3/text: rejoin ["parsed results ^M^/^-" | |
P-drop/:P-def/1 | |
] | |
p4/text: {parse trace ^M^/} | |
] | |
p-indent: make string! 30 | |
parse-skips: 0 ;0: all 1: fails 2: etc TBD | |
; can override while testing print also to console | |
;line endings tricky in windows area sometimes | |
print-et: function ["mimic print echo to etrace area, caller should reduce blk?" | |
blk [string! block!] ; | |
/local x | |
][ | |
; if block? blk [ | |
; repeat x length? blk [ | |
; blk/x: mold blk/x | |
; ] | |
; blk: join/with blk "^/" | |
; ] | |
print blk ;option to echo to console or not (only if don't redirect print) | |
;etrace/text: rejoin [etrace/text mold blk line-end] ;included brackets & quotes | |
if to-area [ ;area on windows needs crnl? | |
;p4a/text: rejoin [p4a/text replace/all blk "^/" "^M^/"] | |
;p4a/text: rejoin [p4a/text mold blk] | |
p4a/text: rejoin [p4a/text to-string blk newline] | |
] ;newline, trace adds newline between match & input | |
] | |
on-parse-compact: function [ | |
"Compact and clear parse/trace event printer" | |
event [word!] | |
match? [logic!] | |
rule [block!] | |
input [series!] | |
stack [block!] | |
][ | |
switch event [ | |
push [ | |
; print-et [p-indent] ;"-->" ;need no nl option print-et | |
append p-indent " " | |
] | |
pop [ | |
clear back back tail p-indent | |
; print-et [p-indent "<--"] ;is on line by itself, just adds noise really | |
] | |
fetch [ | |
print-et rejoin [ | |
p-indent "R: " mold/flat/part rule 40 line-end ; newline added by caller | |
p-indent "I: " either parse-skips = 0 [" At: " mold/flat/part input 30][""] | |
] | |
] | |
match [ | |
print-et rejoin [ | |
p-indent either match? ["✅"] ["❌"] ;green & red on console, newline added | |
;not sure why need to repeat rule, is 2 lines above | |
; either parse-skips = 0 [mold/flat/part rule 60][""] ; newline caller added, skip detail | |
] | |
] | |
end [ | |
print-et reduce ["Done: " mold match?] | |
] | |
] | |
true | |
] | |
;\gist\repos\repo-red\Oldes\Red-master\environment\functions.red | |
;the default callback in parse-trace I think | |
on-parse-event: func [ | |
event [word!] "Trace events: push, pop, fetch, match, iterate, paren, end" | |
match? [logic!] "Result of last matching operation" | |
rule [block!] "Current rule at current position" | |
input [series!] "Input series at next position to match" | |
stack [block!] "Internal parse rules stack" | |
return: [logic!] "TRUE: continue parsing, FALSE: stop and exit parsing" | |
][ | |
switch event [ | |
push [ | |
print [p-indent "-->"] | |
append p-indent " " | |
] | |
pop [ | |
clear back back tail p-indent | |
print [p-indent "<--"] | |
] | |
fetch [ | |
print [ | |
p-indent "match:" mold/flat/part rule 50 line-end | |
p-indent "input:" mold/flat/part input 50 p-indent | |
] | |
] | |
match [print [p-indent "==>" pick ["matched" "not matched"] match?]] | |
end [print ["return:" match?]] | |
] | |
true | |
] | |
parse-??: function [{Wrapper for parse/trace using ?? hook w/o the ?? hook} | |
input [series!] | |
rules [block!] | |
/case | |
/part | |
/skips sps | |
limit [integer!] | |
;return: [logic! block!] | |
][ | |
parse-skips: any [sps 1] ;0 all, 1 less detail, RSN | |
clear p-indent ;no longer works to indent red 22B | |
parse-event: :on-parse-compact ; :on-parse-event-mod ;on-parse-?? option TBD | |
either case [ | |
print ["parse/case/trace input rules :on-parse-??"] | |
parse/case/trace input rules :parse-event | |
][ | |
either part [ | |
print ["parse/part/trace input rules :on-parse-??"] | |
parse/part/trace input rules limit :parse-event | |
][ | |
print-et reduce ["parse/trace input rules :on-parse-??"] | |
parse/trace input rules :parse-event | |
] | |
] | |
] | |
;; June, 2018 https://rebol.tech/gitter.im/red/parse/2018/#msg5b164af7edd06f7d150e7faa | |
;; endo64> I saw "??" usage in Respectech's http://video.respectech.com:8080/tutorial/r3/index.r3 tutorial | |
;; We don't have ?? in Red/Parse, is it handy? | |
;; Should we consider to add it, or parse-trace is already do what ?? does? | |
;; gltewalt> Looks like [pindent] was a todo, to put in non-global? | |
;; greggirwin> Thanks @gltewalt | |
;; parse-?? "dog" [ ?? "d" ?? [ "i" | "o" ] ?? "g" ?? ] | |
;?? FIXME, I think the idea was ?? would be replaced in the rules or trigger more info? | |
; @gltewalt went on to work on parse caddy but it didn't show traces or have ?? | |
do-parse: does [ | |
rule: [["d" | "c"] [ "o" | "a" ] [ "g" | "t" ]] | |
parse-trace "dog" rule | |
parse-?? "cat" rule | |
] | |
; do-parse ; un-comment to show compact trace to console | |
; halt | |
; cfg stuff lifted from larger multi panel layout | |
; not all of it was needed for this parse trace demo | |
; not sure of the utility of this allocation, lifted from a red editor script | |
; I've also heard there's a 32k area/text limit, they seem to work ok for small demo's | |
p1script: make string! 30000 | |
p2script: make string! 60000 | |
p3script: make string! 40000 | |
p4script: make string! 90000 | |
out: copy "" ;replaced later but here incase of compiler confusion | |
f: func [][] ;replaced later | |
fs: func [][] ;replaced later | |
init-pos: 50x5 ;offset upper left of screen | |
window-size: 760x560 ;x650 was too close for some laptop x700 & taskbar | |
T-size: window-size - 5x30 ;room for status with n rows of buttons | |
H-size: as-pair (T-size/x - 12) (7) ;hoiz splitter init | |
;parse area inits. not sure how <>100% works | |
P1-size: as-pair (T-size/x - 12) to-integer (T-size/y * 30%) | |
P2-size: as-pair (T-size/x - 12) to-integer (T-size/y * 10%) | |
P3-size: as-pair (T-size/x - 12) to-integer (T-size/y * 25%) | |
P4-size: as-pair (T-size/x - 12) to-integer (T-size/y * 25%) | |
a_color: 240.240.240 | |
hvs_coloron: gray | |
hvs_coloroff: blue | |
afont: make font! [ ;ui area | |
name: "Consolas" ; | |
size: 11 | |
color: coal | |
] | |
ifont: make font! [ ;ui buttons | |
name: "Consolas" ; | |
size: 9 | |
color: coal | |
] | |
gview: layout [ | |
title "parse Text quad Pane" | |
size window-size | |
backdrop ivory | |
style btn: button 92x17 center font ifont pewter ;~9 char | |
style text: text font afont snow pewter | |
style drop-list: drop-list font afont snow pewter ;~9 char | |
style area: area a_color font afont | |
style splitter: base 5x5 hvs_coloron loose ;make I-beam cursor | |
across | |
pad -2x-4 | |
btn "cls P2-data" [ | |
clear p1/text | |
] | |
btn "cls P3-results" [ | |
clear p3/text | |
] | |
btn "cls P4-trace" [ | |
clear p4/text | |
] | |
pad 20x0 | |
text 90x16 "examples:" | |
drop-list 30x16 data [] [ | |
;print [face/selected] | |
] | |
on-created [ ;wonder can this fail if areas not created yet? | |
repeat ix length? P-drop [append face/data form ix] | |
face/selected: P-def | |
init-areas face/selected | |
] | |
on-change [ | |
init-areas face/selected | |
] | |
btn "Parse" [ ; p1 func rule p2 data p3 results p4 trace | |
;build dynamic function and run it | |
;need a way to trap error, | |
; just as likely to get syntax error that won't point to users function or data | |
; could check structure & open/close balance but way beyond trace demo already | |
either | |
;all [attempt [load to-string first blk] attempt [load to-string second blk]] | |
all [attempt [blk: to-block p1/text] attempt [first blk] attempt [second blk]] | |
[ | |
f: function first blk second blk | |
][ | |
print "p1 function has malformed blocks?" ;FIXME | |
blk: to-block p1/text | |
print [mold first blk newline mold second blk] | |
] | |
; probe spec-of :f | |
; probe reflect :f 'body | |
; ? f | |
; ?? f | |
; probe find spec-of :f 'local ; check all setwords if use function | |
;check debug cb or don't bother echo | |
if no [ | |
append p3/text rejoin [ newline "******" newline | |
'f-s mold spec-of :f newline 'f-b mold body-of :f newline | |
'data mold p2/text | |
newline newline | |
]] | |
px: copy ";in case attempt fails" | |
append p3/text rejoin [ | |
newline "------- mold" newline | |
;ok for string or block litteral in data | |
mold attempt [px: f attempt [load p2/text]] | |
newline "-------form " newline | |
form px | |
newline newline ;last line in area sometimes truncated | |
] | |
] | |
;add cd no-trace or spinbox verbose | |
;add cb string/block | |
pad 24x0 | |
btn "QuitAll" [quit] ;same compiled? | |
btn 38x15 "Exit" [print [";do system/options/script"] unview] ;prints to history | |
return | |
pad -2x-4 | |
below | |
p1: area P1-size p1script react [ | |
face/size/x: face/parent/size/x - 10 | |
] | |
splitter-hp1: splitter H-size react [ | |
face/size/x: face/parent/size/x - 10 | |
] | |
on-down [ofsx1: face/offset/x system/view/auto-sync?: off] | |
on-up [system/view/auto-sync?: on] | |
on-drag [ | |
face/offset/x: ofsx1 | |
p1/size/y: face/offset/y - 10 | |
p2/offset/y: face/offset/y + 10 | |
p2/size/y: face/parent/size/y - face/offset/y - 2 ;20 | |
show [p1 p2 face] | |
] on-over [face/color: either event/away? [hvs_coloron][hvs_coloroff]] | |
p2: area P2-size p2script react [ | |
face/size/x: face/parent/size/x | |
] | |
splitter-hp2: splitter H-size react [ | |
face/size/x: face/parent/size/x - 10 | |
] | |
on-down [ofsx2: face/offset/x system/view/auto-sync?: off] | |
on-up [system/view/auto-sync?: on] | |
on-drag [ | |
face/offset/x: ofsx2 | |
p2/size/y: face/offset/y - 10 | |
p3/offset/y: face/offset/y + 10 | |
p3/size/y: face/parent/size/y - face/offset/y - 2 ;20 | |
show [p2 p3 face] | |
] on-over [face/color: either event/away? [hvs_coloron][hvs_coloroff]] | |
p3: area P3-size p3script react [ | |
face/size/x: face/parent/size/x - 10 | |
] | |
splitter-hp3: splitter H-size react [ | |
face/size/x: face/parent/size/x | |
] | |
on-down [ofsx3: face/offset/x system/view/auto-sync?: off] | |
on-up [system/view/auto-sync?: on] | |
on-drag [ | |
face/offset/x: ofsx3 | |
p3/size/y: face/offset/y - 10 | |
p4/offset/y: face/offset/y + 10 | |
p4/size/y: face/parent/size/y - face/offset/y - 2 ;20 | |
show [p3 p4 face] | |
] on-over [face/color: either event/away? [hvs_coloron][hvs_coloroff]] | |
p4: area P4-size p4script react [ | |
face/size/x: face/parent/size/x - 10 | |
] | |
] | |
; copy to above print-et if compiling | |
p4a: p4 ;trace area object | |
to-area: on ; set toarea to do print-et redirect | |
;don't use /no-wait compiled or w/o opening console first | |
probe init-pos ;open console interpreted | |
view/no-wait/flags/options gview ['resize][offset: init-pos] | |
comment { don't debug the comments | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment