parse dotted lists

This commit is contained in:
Kartik K. Agaram 2021-04-15 19:47:01 -07:00
parent 2e06991834
commit 613b1d5734
2 changed files with 191 additions and 0 deletions

View File

@ -57,6 +57,14 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace
close-paren?, dot? <- parse-sexpression tokens, right-ah, trace
return close-paren?, dot?
}
# dot -> return
var dot?/eax: boolean <- dot-token? curr-token
compare dot?, 0/false
{
break-if-=
trace-higher trace
return 0/false, 1/true
}
# not bracket -> parse atom
var bracket-token?/eax: boolean <- bracket-token? curr-token
compare bracket-token?, 0/false
@ -78,6 +86,12 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace
var close-paren?/eax: boolean <- copy 0/false
var dot?/ecx: boolean <- copy 0/false
close-paren?, dot? <- parse-sexpression tokens, left, trace
{
compare dot?, 0/false
break-if-=
error trace, "'.' cannot be at the start of a list"
return 1/true, dot?
}
compare close-paren?, 0/false
break-if-!=
var curr-addr/eax: (addr cell) <- lookup *curr
@ -88,6 +102,13 @@ fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace
var close-paren?/eax: boolean <- copy 0/false
var dot?/ecx: boolean <- copy 0/false
close-paren?, dot? <- parse-sexpression tokens, tmp, trace
# '.' -> clean up right here and return
compare dot?, 0/false
{
break-if-=
parse-dot-tail tokens, curr, trace
return 0/false, 0/false
}
allocate-pair curr
# ')' -> return
compare close-paren?, 0/false
@ -170,3 +191,38 @@ fn parse-atom _curr-token: (addr cell), _out: (addr handle cell), trace: (addr t
trace trace, "read", stream
}
}
fn parse-dot-tail tokens: (addr stream cell), _out: (addr handle cell), trace: (addr trace) {
var out/edi: (addr handle cell) <- copy _out
var close-paren?/eax: boolean <- copy 0/false
var dot?/ecx: boolean <- copy 0/false
close-paren?, dot? <- parse-sexpression tokens, out, trace
compare close-paren?, 0/false
{
break-if-=
error trace, "'. )' makes no sense"
return
}
compare dot?, 0/false
{
break-if-=
error trace, "'. .' makes no sense"
return
}
#
var dummy: (handle cell)
var dummy-ah/edi: (addr handle cell) <- address dummy
close-paren?, dot? <- parse-sexpression tokens, dummy-ah, trace
compare close-paren?, 0/false
{
break-if-!=
error trace, "cannot have multiple expressions between '.' and ')'"
return
}
compare dot?, 0/false
{
break-if-=
error trace, "cannot have two dots in a single list"
return
}
}

View File

@ -719,6 +719,141 @@ fn test-run-quote {
check-screen-row screen, 2/y, "=> a ", "F - test-run-quote/2"
}
fn test-run-dotted-list {
var sandbox-storage: sandbox
var sandbox/esi: (addr sandbox) <- address sandbox-storage
initialize-sandbox sandbox, 0/no-screen-or-keyboard
# type "'(a . b)"
edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# eval
edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x80/width, 0x10/height
#
render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals
check-screen-row screen, 0/y, "'(a . b) ", "F - test-run-dotted-list/0"
check-screen-row screen, 1/y, "... ", "F - test-run-dotted-list/1"
check-screen-row screen, 2/y, "=> (a . b) ", "F - test-run-dotted-list/2"
}
fn test-run-dot-and-list {
var sandbox-storage: sandbox
var sandbox/esi: (addr sandbox) <- address sandbox-storage
initialize-sandbox sandbox, 0/no-screen-or-keyboard
# type "'(a . (b))"
edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# eval
edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x80/width, 0x10/height
#
render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals
check-screen-row screen, 0/y, "'(a . (b)) ", "F - test-run-dot-and-list/0"
check-screen-row screen, 1/y, "... ", "F - test-run-dot-and-list/1"
check-screen-row screen, 2/y, "=> (a b) ", "F - test-run-dot-and-list/2"
}
fn test-run-final-dot {
var sandbox-storage: sandbox
var sandbox/esi: (addr sandbox) <- address sandbox-storage
initialize-sandbox sandbox, 0/no-screen-or-keyboard
# type "'(a .)"
edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# eval
edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x80/width, 0x10/height
#
render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals
check-screen-row screen, 0/y, "'(a .) ", "F - test-run-final-dot/0"
check-screen-row screen, 1/y, "... ", "F - test-run-final-dot/1"
check-screen-row screen, 2/y, "'. )' makes no sense ", "F - test-run-final-dot/2"
# further errors may occur
}
fn test-run-double-dot {
var sandbox-storage: sandbox
var sandbox/esi: (addr sandbox) <- address sandbox-storage
initialize-sandbox sandbox, 0/no-screen-or-keyboard
# type "'(a . .)"
edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# eval
edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x80/width, 0x10/height
#
render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals
check-screen-row screen, 0/y, "'(a . .) ", "F - test-run-double-dot/0"
check-screen-row screen, 1/y, "... ", "F - test-run-double-dot/1"
check-screen-row screen, 2/y, "'. .' makes no sense ", "F - test-run-double-dot/2"
# further errors may occur
}
fn test-run-multiple-expressions-after-dot {
var sandbox-storage: sandbox
var sandbox/esi: (addr sandbox) <- address sandbox-storage
initialize-sandbox sandbox, 0/no-screen-or-keyboard
# type "'(a . b c)"
edit-sandbox sandbox, 0x27/quote, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x28/open-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x61/a, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x2e/dot, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x62/b, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x20/space, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x63/c, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
edit-sandbox sandbox, 0x29/close-paren, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# eval
edit-sandbox sandbox, 0x13/ctrl-s, 0/no-globals, 0/no-screen, 0/no-keyboard, 0/no-disk
# setup: screen
var screen-on-stack: screen
var screen/edi: (addr screen) <- address screen-on-stack
initialize-screen screen, 0x80/width, 0x10/height
#
render-sandbox screen, sandbox, 0/x, 0/y, 0x80/width, 0x10/height, 0/no-globals
check-screen-row screen, 0/y, "'(a . b c) ", "F - test-run-multiple-expressions-after-dot/0"
check-screen-row screen, 1/y, "... ", "F - test-run-multiple-expressions-after-dot/1"
check-screen-row screen, 2/y, "cannot have multiple expressions between '.' and ')' ", "F - test-run-multiple-expressions-after-dot/2"
# further errors may occur
}
fn test-run-error-invalid-integer {
var sandbox-storage: sandbox
var sandbox/esi: (addr sandbox) <- address sandbox-storage