luser droog
2022-05-30 17:43:21 UTC
I just spent the evening and morning writing a parser for BNF syntax.
Pretty meager stuff, I know. But the debugging effort went rather
smoothly thanks to the introduction of error message support.
Even the bare-bones error messages told me which production was
failing.
(pc12.ps)run
/to-string{ dup type /stringtype ne {
dup length string exch 0 exch {3 copy putinterval length add} forall pop } if }
def
/space ( \n) anyof def
/space? //space many def
/alpha (a)(z) range (A)(Z) range alt def
/identifier (-) char //alpha alt some
{to-string} using
def
/terminal (") char (") noneof many
xthen (") char thenx def
/non-terminal (<) char //identifier
xthen (>) char thenx def
/Symbol //non-terminal def
/Expression //terminal //non-terminal alt //space? thenx some def
/BNF //space? //Symbol xthen //space? thenx
(::=) str then //space? thenx
//Expression then //space? thenx
def
/BNF-parse {
0 0 3 2 roll string-input BNF
dup first /OK eq { second first } if
} def
(
<postal-address> ::= <name-part> <street-address> <zip-part>
) BNF-parse
pq
[Terminal transcript. 'Norah' is my laptop's name.]
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Error: /undefined in alpha
Operand stack:
identifier
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1990 1 3 %oparray_pop 1989 1 3 %oparray_pop 1977 1 3 %oparray_pop 1833 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push
Dictionary stack:
--dict:737/1123(ro)(G)-- --dict:0/20(G)-- --dict:75/200(L)-- --dict:37/58(L)-- --dict:2/2(L)-- --dict:62/120(L)--
Current allocation mode is local
GPL Ghostscript 9.54.0: Unrecoverable error, exit code 1
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Error: /undefined in BNF
Operand stack:
BNF --nostringval-- --nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1990 1 3 %oparray_pop 1989 1 3 %oparray_pop 1977 1 3 %oparray_pop 1833 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval--
Dictionary stack:
--dict:737/1123(ro)(G)-- --dict:0/20(G)-- --dict:75/200(L)-- --dict:37/58(L)-- --dict:2/2(L)-- --dict:69/120(L)--
Current allocation mode is local
Current file position is 611
GPL Ghostscript 9.54.0: Unrecoverable error, exit code 1
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[{(<) eq} (not satisfied)] [[(\n) [0 0]] {0 0 ( <postal-address> ::= <name-part> <street-address> <zip-part>\n) string-input}]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[( after ) (\n)] [[{(<) eq} (not satisfied)] [[( ) [0 0]] {0 1 ( <postal-address> ::= <name-part> <street-address> <zip-part>\n) string-input}]]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[( after ) [(<) (p)]] [[{(>) eq} (not satisfied)] [[(o) [0 4]] {0 5 (stal-address> ::= <name-part> <street-address> <zip-part>\n) string-input}]]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[( after ) [(<) (p) (o) (s) (t) (a) (l) (-) (a) (d) (d) (r) (e) (s) (s) (>) (:) (:) (=)]] [[{(-) eq} (not satisfied)] [[(<) [0 23]] {0 24 (name-part> <street-address> <zip-part>\n) string-input}]]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[( after ) [(<) (p) (o) (s) (t) (a) (l) (-) (a) (d) (d) (r) (e) (s) (s) (>) (:) (:) (=)]] [[{dup (A) ge exch (Z) le and} (not satisfied)] [[(<) [0 23]] {0 24 (name-part> <street-address> <zip-part>\n) string-input}]]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
p
(o)
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
stack:
[(p) (o) (s) (t) (a) (l) (-) (a) (d) (d) (r) (e) (s) (s) (:) (:) (=) (n) (a) (m) (e) (-) (p) (a) (r) (t)]
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
stack:
[(p) (o) (s) (t) (a) (l) (-) (a) (d) (d) (r) (e) (s) (s) (:) (:) (=) (n) (a) (m) (e) (-) (p) (a) (r) (t) (s) (t) (r) (e) (e) (t) (-) (a) (d) (d) (r) (e) (s) (s) (z) (i) (p) (-) (p) (a) (r) (t)]
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Error: /undefined in to-string
Operand stack:
--nostringval-- (<) --nostringval-- --nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1990 1 3 %oparray_pop 1989 1 3 %oparray_pop 1977 1 3 %oparray_pop 1833 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval--
Dictionary stack:
--dict:737/1123(ro)(G)-- --dict:0/20(G)-- --dict:75/200(L)-- --dict:37/58(L)-- --dict:2/2(L)-- --dict:70/120(L)--
Current allocation mode is local
Current file position is 779
GPL Ghostscript 9.54.0: Unrecoverable error, exit code 1
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
stack:
[(postal-address) (:) (:) (=) (name-part) (street-address) (zip-part)]
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$
Pretty meager stuff, I know. But the debugging effort went rather
smoothly thanks to the introduction of error message support.
Even the bare-bones error messages told me which production was
failing.
(pc12.ps)run
/to-string{ dup type /stringtype ne {
dup length string exch 0 exch {3 copy putinterval length add} forall pop } if }
def
/space ( \n) anyof def
/space? //space many def
/alpha (a)(z) range (A)(Z) range alt def
/identifier (-) char //alpha alt some
{to-string} using
def
/terminal (") char (") noneof many
xthen (") char thenx def
/non-terminal (<) char //identifier
xthen (>) char thenx def
/Symbol //non-terminal def
/Expression //terminal //non-terminal alt //space? thenx some def
/BNF //space? //Symbol xthen //space? thenx
(::=) str then //space? thenx
//Expression then //space? thenx
def
/BNF-parse {
0 0 3 2 roll string-input BNF
dup first /OK eq { second first } if
} def
(
<postal-address> ::= <name-part> <street-address> <zip-part>
) BNF-parse
pq
[Terminal transcript. 'Norah' is my laptop's name.]
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Error: /undefined in alpha
Operand stack:
identifier
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1990 1 3 %oparray_pop 1989 1 3 %oparray_pop 1977 1 3 %oparray_pop 1833 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push
Dictionary stack:
--dict:737/1123(ro)(G)-- --dict:0/20(G)-- --dict:75/200(L)-- --dict:37/58(L)-- --dict:2/2(L)-- --dict:62/120(L)--
Current allocation mode is local
GPL Ghostscript 9.54.0: Unrecoverable error, exit code 1
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Error: /undefined in BNF
Operand stack:
BNF --nostringval-- --nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1990 1 3 %oparray_pop 1989 1 3 %oparray_pop 1977 1 3 %oparray_pop 1833 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval--
Dictionary stack:
--dict:737/1123(ro)(G)-- --dict:0/20(G)-- --dict:75/200(L)-- --dict:37/58(L)-- --dict:2/2(L)-- --dict:69/120(L)--
Current allocation mode is local
Current file position is 611
GPL Ghostscript 9.54.0: Unrecoverable error, exit code 1
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[{(<) eq} (not satisfied)] [[(\n) [0 0]] {0 0 ( <postal-address> ::= <name-part> <street-address> <zip-part>\n) string-input}]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[( after ) (\n)] [[{(<) eq} (not satisfied)] [[( ) [0 0]] {0 1 ( <postal-address> ::= <name-part> <street-address> <zip-part>\n) string-input}]]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[( after ) [(<) (p)]] [[{(>) eq} (not satisfied)] [[(o) [0 4]] {0 5 (stal-address> ::= <name-part> <street-address> <zip-part>\n) string-input}]]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[( after ) [(<) (p) (o) (s) (t) (a) (l) (-) (a) (d) (d) (r) (e) (s) (s) (>) (:) (:) (=)]] [[{(-) eq} (not satisfied)] [[(<) [0 23]] {0 24 (name-part> <street-address> <zip-part>\n) string-input}]]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Fail
[[( after ) [(<) (p) (o) (s) (t) (a) (l) (-) (a) (d) (d) (r) (e) (s) (s) (>) (:) (:) (=)]] [[{dup (A) ge exch (Z) le and} (not satisfied)] [[(<) [0 23]] {0 24 (name-part> <street-address> <zip-part>\n) string-input}]]]
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
p
(o)
GS>]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
stack:
[(p) (o) (s) (t) (a) (l) (-) (a) (d) (d) (r) (e) (s) (s) (:) (:) (=) (n) (a) (m) (e) (-) (p) (a) (r) (t)]
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
stack:
[(p) (o) (s) (t) (a) (l) (-) (a) (d) (d) (r) (e) (s) (s) (:) (:) (=) (n) (a) (m) (e) (-) (p) (a) (r) (t) (s) (t) (r) (e) (e) (t) (-) (a) (d) (d) (r) (e) (s) (s) (z) (i) (p) (-) (p) (a) (r) (t)]
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
Error: /undefined in to-string
Operand stack:
--nostringval-- (<) --nostringval-- --nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- false 1 %stopped_push 1990 1 3 %oparray_pop 1989 1 3 %oparray_pop 1977 1 3 %oparray_pop 1833 1 3 %oparray_pop --nostringval-- %errorexec_pop .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval-- --nostringval--
Dictionary stack:
--dict:737/1123(ro)(G)-- --dict:0/20(G)-- --dict:75/200(L)-- --dict:37/58(L)-- --dict:2/2(L)-- --dict:70/120(L)--
Current allocation mode is local
Current file position is 779
GPL Ghostscript 9.54.0: Unrecoverable error, exit code 1
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$ gsq pc12bnf.ps
stack:
[(postal-address) (:) (:) (=) (name-part) (street-address) (zip-part)]
]0;~/pcomb/ps
***@laptop ~/pcomb/ps
$