# me_tcl.test: Tests for the ME virtual machine -*- tcl -*- # # This file contains a collection of tests for one or more of the # commands making up the ME virtual machine. Sourcing this file into # Tcl runs the tests and generates output for errors. No output means # no errors were found. # # Copyright (c) 2005 Andreas Kupries # All rights reserved. # # RCS: @(#) $Id: me_tcl.test,v 1.8 2007/08/01 22:49:26 andreas_kupries Exp $ # ------------------------------------------------------------------------- source [file join \ [file dirname [file dirname [file join [pwd] [info script]]]] \ devtools testutilities.tcl] testsNeedTcl 8.4 testsNeedTcltest 2.1 testing { useLocal me_tcl.tcl grammar::me::tcl } # ### ### ### ######### ######### ######### ## Pre-requisites. Helper commands to inspect the state of the ME ## virtual machine. proc ME_state {} { # This command retrieves all parts of the ME virtual machine state # for inspection by the testing commands. The result is a dictionary. set res {} lappend res [list tok__ [grammar::me::tcl ctok]] lappend res [list loc__ [grammar::me::tcl::icl_get]] lappend res [list ok___ $grammar::me::tcl::ok] lappend res [list error [grammar::me::tcl::ier_get]] lappend res [list sv___ [grammar::me::tcl sv]] lappend res [list ast__ [grammar::me::tcl astall]] set nt [grammar::me::tcl tokens] incr nt -1 lappend res [list input [grammar::me::tcl tok 0 $nt]] lappend res [list cache [dictsort [grammar::me::tcl nc]]] lappend res [list next_ [grammar::me::tcl next]] lappend res [list ord__ [dictsort [grammar::me::tcl ord]]] return $res } proc ME_stateText {} { join [ME_state] \n } proc next_badresult {} {return a} proc next_eof {} {return {}} proc next_char {x} {return [list $x 3 4 {}]} proc next_count {} { global count incr count return [list T$count 1 $count $count] } proc nc_init {} { global count set count 0 return } # ### ### ### ######### ######### ######### ## test mevmtcl-init-1.0 {Call without enough arguments} \ -returnCodes error \ -body { grammar::me::tcl::init } -result {wrong # args: should be "grammar::me::tcl::init nxcmd ?tokmap?"} test mevmtcl-init-1.1 {Call with too many arguments} \ -returnCodes error \ -body { grammar::me::tcl::init a b c } -result {wrong # args: should be "grammar::me::tcl::init nxcmd ?tokmap?"} test mevmtcl-init-1.2 {Call with bad token map} \ -returnCodes error \ -body { grammar::me::tcl::init a b } -result {Bad token order map, not a dictionary} test mevmtcl-init-2.0 {Basic initialization} \ -body { grammar::me::tcl::init fake ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-init-2.1 {Basic initialization, with map} \ -body { grammar::me::tcl::init fakeB {ident 0} ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fakeB ord__ {ident 0}} # ### ### ### ######### ######### ######### ## test mevmtcl-ict_advance-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_advance } -result {wrong # args: should be "grammar::me::tcl::ict_advance msg"} test mevmtcl-ict_advance-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_advance a b } -result {wrong # args: should be "grammar::me::tcl::ict_advance msg"} test mevmtcl-ict_advance-1.2 {Bad next callback} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_advance foo } -result {invalid command name "fake"} test mevmtcl-ict_advance-1.3 {Bad next callback, bad results} \ -returnCodes error \ -setup { grammar::me::tcl::init next_badresult } -body { grammar::me::tcl::ict_advance foo } -result {Bad callback result, expected 4 elements} test mevmtcl-ict_advance-2.0 {Behaviour at eof} \ -setup { grammar::me::tcl::init next_eof } -body { grammar::me::tcl::ict_advance "foo (got EOF)" ME_stateText } -result {tok__ {} loc__ 0 ok___ 0 error {0 {{foo (got EOF)}}} sv___ {} ast__ {} input {} cache {} next_ next_eof ord__ {}} test mevmtcl-ict_advance-2.1 {Behaviour for regular token} \ -setup { grammar::me::tcl::init next_count nc_init } -body { grammar::me::tcl::ict_advance foo ME_stateText } -result {tok__ T1 loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ict_advance-2.2 {Behaviour for backtracing in input} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::icl_rewind 0 } -body { grammar::me::tcl::ict_advance foo ME_stateText } -result {tok__ T2 loc__ 1 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3}} cache {} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-ict_match_token-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_match_token } -result {wrong # args: should be "grammar::me::tcl::ict_match_token tok msg"} test mevmtcl-ict_match_token-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_match_token a b c } -result {wrong # args: should be "grammar::me::tcl::ict_match_token tok msg"} test mevmtcl-ict_match_token-2.0 {Token is matching} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_token T1 "Expected foo" ME_stateText } -result {tok__ T1 loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ict_match_token-2.1 {Token is not matching} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_token BOGUS "Expected 'BOGUS'" ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {0 {{Expected 'BOGUS'}}} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-ict_match_tokrange-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_match_tokrange } -result {wrong # args: should be "grammar::me::tcl::ict_match_tokrange toks toke msg"} test mevmtcl-ict_match_tokrange-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_match_tokrange a b c d } -result {wrong # args: should be "grammar::me::tcl::ict_match_tokrange toks toke msg"} test mevmtcl-ict_match_tokrange-2.0 {Token range, lexicographic compare, outside low} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange T2 T4 "\[T2 .. T4\]" ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {0 {{[T2 .. T4]}}} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ict_match_tokrange-2.1 {Token range, lexicographic compare, outside up} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange A S "\[A .. S\]" ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {0 {{[A .. S]}}} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ict_match_tokrange-2.2 {Token range, lexicographic compare, in range} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange A T2 "\[A .. T2\]" ME_stateText } -result {tok__ T1 loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ict_match_tokrange-2.3 {Token range, lexicographic compare, in range, low edge} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange T1 T5 "\[T1 .. T5\]" ME_stateText } -result {tok__ T1 loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ict_match_tokrange-2.4 {Token range, lexicographic compare, in range, upper edge} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange A T1 "\[A .. T1\]" ME_stateText } -result {tok__ T1 loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ict_match_tokrange-3.0 {Token range, map order compare, outside low} \ -setup { grammar::me::tcl::init next_count {T1 0 A 1 B 2} nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange 1 2 "\[A .. B\]" ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {0 {{[A .. B]}}} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {A 1 B 2 T1 0}} test mevmtcl-ict_match_tokrange-3.1 {Token range, map order compare, outside up} \ -setup { grammar::me::tcl::init next_count {A 1 B 2 T1 3} nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange 1 2 "\[A .. B\]" ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {0 {{[A .. B]}}} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {A 1 B 2 T1 3}} test mevmtcl-ict_match_tokrange-3.2 {Token range, map order compare, in range} \ -setup { grammar::me::tcl::init next_count {A 1 T1 2 B 3} nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange 1 3 "\[A .. B\]" ME_stateText } -result {tok__ T1 loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {A 1 B 3 T1 2}} test mevmtcl-ict_match_tokrange-3.3 {Token range, map order compare, in range, low edge} \ -setup { grammar::me::tcl::init next_count {T1 0 A 1 B 2} nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange 0 1 "\[T1 .. A\]" ME_stateText } -result {tok__ T1 loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {A 1 B 2 T1 0}} test mevmtcl-ict_match_tokrange-3.4 {Token range, map order compare, in range, upper edge} \ -setup { grammar::me::tcl::init next_count {A 0 B 1 T1 2} nc_init grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokrange 0 2 "\[A .. T1\]" ME_stateText } -result {tok__ T1 loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {A 0 B 1 T1 2}} # ### ### ### ######### ######### ######### ## test mevmtcl-ict_match_tokclass-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_match_tokclass } -result {wrong # args: should be "grammar::me::tcl::ict_match_tokclass code msg"} test mevmtcl-ict_match_tokclass-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_match_tokclass a b c } -result {wrong # args: should be "grammar::me::tcl::ict_match_tokclass code msg"} test mevmtcl-ict_match_tokclass-1.2a {Call with bad code} \ -constraints tcl8.5plus \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_match_tokclass gargle foo } -result {bad class "gargle": must be alnum, alpha, ascii, control, boolean, digit, double, false, graph, integer, list, lower, print, punct, space, true, upper, wideinteger, wordchar, or xdigit} test mevmtcl-ict_match_tokclass-1.2b {Call with bad code} \ -constraints {!tcl8.5plus} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ict_match_tokclass gargle foo } -result {bad class "gargle": must be alnum, alpha, ascii, control, boolean, digit, double, false, graph, integer, lower, print, punct, space, true, upper, wordchar, or xdigit} test mevmtcl-ict_match_tokclass-2.0 {Token is matching} \ -setup { grammar::me::tcl::init {next_char X} grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokclass alpha "" ME_stateText } -result {tok__ X loc__ 0 ok___ 1 error {} sv___ {} ast__ {} input {{X 3 4 {}}} cache {} next_ {next_char X} ord__ {}} test mevmtcl-ict_match_tokclass-2.1 {Token is not matching} \ -setup { grammar::me::tcl::init {next_char 0} grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::ict_match_tokclass alpha "" ME_stateText } -result {tok__ 0 loc__ -1 ok___ 0 error {0 } sv___ {} ast__ {} input {{0 3 4 {}}} cache {} next_ {next_char 0} ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-inc_save-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::inc_save } -result {wrong # args: should be "grammar::me::tcl::inc_save symbol at"} test mevmtcl-inc_save-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::inc_save a b c } -result {wrong # args: should be "grammar::me::tcl::inc_save symbol at"} test mevmtcl-inc_save-2.0 {Basic save of nonterminal match data} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::inc_save A -1 ME_stateText } -result {tok__ T2 loc__ 1 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1} {T2 1 2 2}} cache {-1,A {1 1 {} {}}} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-inc_restore-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::inc_restore } -result {wrong # args: should be "grammar::me::tcl::inc_restore symbol"} test mevmtcl-inc_restore-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::inc_restore a b } -result {wrong # args: should be "grammar::me::tcl::inc_restore symbol"} test mevmtcl-inc_restore-2.0 {Restore match data, not present} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::icl_rewind -1 grammar::me::tcl::iok_fail } -body { list [grammar::me::tcl::inc_restore A] [ME_stateText] } -result {0 {tok__ T2 loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {{T1 1 1 1} {T2 1 2 2}} cache {} next_ next_count ord__ {}}} test mevmtcl-inc_restore-2.1 {Restore match data from cache} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::inc_save A -1 grammar::me::tcl::icl_rewind -1 grammar::me::tcl::iok_fail } -body { list [grammar::me::tcl::inc_restore A] [ME_stateText] } -result {1 {tok__ T2 loc__ 1 ok___ 1 error {} sv___ {} ast__ {} input {{T1 1 1 1} {T2 1 2 2}} cache {-1,A {1 1 {} {}}} next_ next_count ord__ {}}} # ### ### ### ######### ######### ######### ## test mevmtcl-iok_ok-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::iok_ok a } -result {wrong # args: should be "grammar::me::tcl::iok_ok"} test mevmtcl-iok_ok-2.0 {Regular behaviour} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::iok_ok ME_stateText } -result {tok__ {} loc__ -1 ok___ 1 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-iok_fail-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::iok_fail a } -result {wrong # args: should be "grammar::me::tcl::iok_fail"} test mevmtcl-iok_fail-2.0 {Regular behaviour} \ -setup { grammar::me::tcl::init fake grammar::me::tcl::iok_ok } -body { grammar::me::tcl::iok_fail ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-iok_negate-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::iok_negate a } -result {wrong # args: should be "grammar::me::tcl::iok_negate"} test mevmtcl-iok_negate-2.0 {Regular behaviour} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::iok_negate ME_stateText } -result {tok__ {} loc__ -1 ok___ 1 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-iok_negate-2.1 {Regular behaviour} \ -setup { grammar::me::tcl::init fake grammar::me::tcl::iok_ok } -body { grammar::me::tcl::iok_negate ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-icl_get-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::icl_get a } -result {wrong # args: should be "grammar::me::tcl::icl_get"} test mevmtcl-icl_get-2.0 {Get current location} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::icl_get } -result -1 test mevmtcl-icl_get-2.1 {Get current location after advancing} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::icl_get } -result 2 test mevmtcl-icl_get-2.2 {Get current location after advance & rewind} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::icl_rewind 1 } -body { grammar::me::tcl::icl_get } -result 1 # ### ### ### ######### ######### ######### ## test mevmtcl-icl_rewind-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::icl_rewind } -result {wrong # args: should be "grammar::me::tcl::icl_rewind oldloc"} test mevmtcl-icl_rewind-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::icl_rewind a b } -result {wrong # args: should be "grammar::me::tcl::icl_rewind oldloc"} test mevmtcl-icl_rewind-2.0 {Rewind travels back} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::icl_rewind 1 grammar::me::tcl::icl_get } -result 1 test mevmtcl-icl_rewind-2.1 {Rewind is not sanity checked} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::icl_rewind -4 grammar::me::tcl::icl_get } -result -4 test mevmtcl-icl_rewind-2.2 {Rewind is not sanity checked} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::icl_rewind 50 grammar::me::tcl::icl_get } -result 50 # ### ### ### ######### ######### ######### ## test mevmtcl-ier_get-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_get a } -result {wrong # args: should be "grammar::me::tcl::ier_get"} test mevmtcl-ier_get-2.0 {Get current error} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_get } -result {} test mevmtcl-ier_get-2.1 {Get current error} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_match_token BOGUS 'BOGUS' } -body { grammar::me::tcl::ier_get } -result {0 'BOGUS'} # ### ### ### ######### ######### ######### ## test mevmtcl-ier_clear-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_clear a } -result {wrong # args: should be "grammar::me::tcl::ier_clear"} test mevmtcl-ier_clear-2.0 {Clear error, no preceding error} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_clear ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-ier_clear-2.1 {Clear error} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_match_token BOGUS 'BOGUS' } -body { grammar::me::tcl::ier_clear ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-ier_nonterminal-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_nonterminal } -result {wrong # args: should be "grammar::me::tcl::ier_nonterminal msg pos"} test mevmtcl-ier_nonterminal-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_nonterminal a b c } -result {wrong # args: should be "grammar::me::tcl::ier_nonterminal msg pos"} test mevmtcl-ier_nonterminal-2.0 {No-op if there is no error} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_nonterminal A 4 ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-ier_nonterminal-2.1 {No-op for non-matching locations} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_match_token BOGUS 'BOGUS' } -body { grammar::me::tcl::ier_nonterminal A 4 ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {0 'BOGUS'} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ier_nonterminal-2.2 {Replace error for matching locations} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_match_token BOGUS 'BOGUS' } -body { grammar::me::tcl::ier_nonterminal A -1 ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {0 A} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-ier_merge-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_merge } -result {wrong # args: should be "grammar::me::tcl::ier_merge new"} test mevmtcl-ier_merge-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_merge a b } -result {wrong # args: should be "grammar::me::tcl::ier_merge new"} test mevmtcl-ier_merge-2.0 {Both errors empty} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_merge {} ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-ier_merge-2.1 {Stored error empty, argument not} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ier_merge {3 {A dot bar}} ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {3 {A dot bar}} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-ier_merge-2.2 {Stored error non-empty, argument is} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_match_token BOGUS 'BOGUS' } -body { grammar::me::tcl::ier_merge {} ME_stateText } -result {tok__ T1 loc__ -1 ok___ 0 error {0 'BOGUS'} sv___ {} ast__ {} input {{T1 1 1 1}} cache {} next_ next_count ord__ {}} test mevmtcl-ier_merge-2.3 {Both errors non-empty, stored further} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_match_token BOGUS 'BOGUS' } -body { grammar::me::tcl::ier_merge {0 {A C}} ME_stateText } -result {tok__ T3 loc__ 1 ok___ 0 error {2 'BOGUS'} sv___ {} ast__ {} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3}} cache {} next_ next_count ord__ {}} test mevmtcl-ier_merge-2.4 {Both errors non-empty, argument further} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_match_token BOGUS 'BOGUS' } -body { grammar::me::tcl::ier_merge {4 {A C}} ME_stateText } -result {tok__ T3 loc__ 1 ok___ 0 error {4 {A C}} sv___ {} ast__ {} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3}} cache {} next_ next_count ord__ {}} test mevmtcl-ier_merge-2.5 {Both errors non-empty, same location} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_match_token BOGUS 'BOGUS' } -body { grammar::me::tcl::ier_merge {2 {A C}} ME_stateText } -result {tok__ T3 loc__ 1 ok___ 0 error {2 {'BOGUS' A C}} sv___ {} ast__ {} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3}} cache {} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-isv_clear-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_clear a } -result {wrong # args: should be "grammar::me::tcl::isv_clear"} test mevmtcl-isv_clear-2.0 {Clear sv, was already clear} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_clear ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-isv_clear-2.1 {Clear sv, after creating something} \ -setup { grammar::me::tcl::init fake grammar::me::tcl::isv_terminal } -body { grammar::me::tcl::isv_clear ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {{{} -1 -1}} input {} cache {} next_ fake ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-isv_terminal-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_terminal a } -result {wrong # args: should be "grammar::me::tcl::isv_terminal"} test mevmtcl-isv_terminal-2.0 {Create terminal sv & push} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_terminal ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {{} -1 -1} ast__ {{{} -1 -1}} input {} cache {} next_ fake ord__ {}} test mevmtcl-isv_terminal-2.1 {Create terminal sv & push, after advancing} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo grammar::me::tcl::ict_advance foo } -body { grammar::me::tcl::isv_terminal ME_stateText } -result {tok__ T3 loc__ 2 ok___ 1 error {} sv___ {{} 2 2} ast__ {{{} 2 2}} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3}} cache {} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-isv_nonterminal_leaf-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_leaf } -result {wrong # args: should be "grammar::me::tcl::isv_nonterminal_leaf nt pos"} test mevmtcl-isv_nonterminal_leaf-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_leaf a b c } -result {wrong # args: should be "grammar::me::tcl::isv_nonterminal_leaf nt pos"} test mevmtcl-isv_nonterminal_leaf-2.0 {No-op if not ok} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_leaf A -3 ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-isv_nonterminal_leaf-2.1 {Generate sv} \ -setup { grammar::me::tcl::init fake grammar::me::tcl::iok_ok } -body { grammar::me::tcl::isv_nonterminal_leaf A -3 ME_stateText } -result {tok__ {} loc__ -1 ok___ 1 error {} sv___ {A -2 -1} ast__ {} input {} cache {} next_ fake ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-isv_nonterminal_range-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_range } -result {wrong # args: should be "grammar::me::tcl::isv_nonterminal_range nt pos"} test mevmtcl-isv_nonterminal_range-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_range a b c } -result {wrong # args: should be "grammar::me::tcl::isv_nonterminal_range nt pos"} test mevmtcl-isv_nonterminal_range-2.0 {No-op if not ok} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_range A -3 ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-isv_nonterminal_range-2.1 {Generate sv} \ -setup { grammar::me::tcl::init fake grammar::me::tcl::iok_ok } -body { grammar::me::tcl::isv_nonterminal_range A -3 ME_stateText } -result {tok__ {} loc__ -1 ok___ 1 error {} sv___ {A -2 -1 {{} -2 -1}} ast__ {} input {} cache {} next_ fake ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-isv_nonterminal_reduce-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_reduce } -result {wrong # args: should be "grammar::me::tcl::isv_nonterminal_reduce nt pos ?mrk?"} test mevmtcl-isv_nonterminal_reduce-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_reduce a b c d } -result {wrong # args: should be "grammar::me::tcl::isv_nonterminal_reduce nt pos ?mrk?"} test mevmtcl-isv_nonterminal_reduce-2.0 {No-op if not ok} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::isv_nonterminal_reduce A -3 ME_stateText } -result {tok__ {} loc__ -1 ok___ 0 error {} sv___ {} ast__ {} input {} cache {} next_ fake ord__ {}} test mevmtcl-isv_nonterminal_reduce-2.1 {Generate sv, reduce all} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal } -body { grammar::me::tcl::isv_nonterminal_reduce A -1 ME_stateText } -result {tok__ T3 loc__ 2 ok___ 1 error {} sv___ {A 0 2 {{} 0 0} {{} 1 1} {{} 2 2}} ast__ {{{} 0 0} {{} 1 1} {{} 2 2}} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3}} cache {} next_ next_count ord__ {}} test mevmtcl-isv_nonterminal_reduce-2.2 {Generate sv, reduce partial} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal } -body { grammar::me::tcl::isv_nonterminal_reduce A 0 1 ME_stateText } -result {tok__ T3 loc__ 2 ok___ 1 error {} sv___ {A 1 2 {{} 1 1} {{} 2 2}} ast__ {{{} 0 0} {{} 1 1} {{} 2 2}} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3}} cache {} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-ias_push-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ias_push a } -result {wrong # args: should be "grammar::me::tcl::ias_push"} test mevmtcl-ias_push-2.0 {Push sv to ast stack} \ -setup { grammar::me::tcl::init fake grammar::me::tcl::iok_ok grammar::me::tcl::isv_nonterminal_leaf A -3 } -body { grammar::me::tcl::ias_push ME_stateText } -result {tok__ {} loc__ -1 ok___ 1 error {} sv___ {A -2 -1} ast__ {{A -2 -1}} input {} cache {} next_ fake ord__ {}} # ### ### ### ######### ######### ######### ## test mevmtcl-ias_mark-1.0 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ias_mark a } -result {wrong # args: should be "grammar::me::tcl::ias_mark"} test mevmtcl-ias_mark-2.0 {Get ast stack size} \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ias_mark } -result 0 test mevmtcl-ias_mark-2.1 {Get ast stack size} \ -setup { grammar::me::tcl::init fake grammar::me::tcl::iok_ok grammar::me::tcl::isv_nonterminal_leaf A -3 grammar::me::tcl::ias_push } -body { grammar::me::tcl::ias_mark } -result 1 # ### ### ### ######### ######### ######### ## test mevmtcl-ias_pop2mark-1.0 {Call without enough arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ias_pop2mark } -result {wrong # args: should be "grammar::me::tcl::ias_pop2mark mark"} test mevmtcl-ias_pop2mark-1.1 {Call with too many arguments} \ -returnCodes error \ -setup { grammar::me::tcl::init fake } -body { grammar::me::tcl::ias_pop2mark a b } -result {wrong # args: should be "grammar::me::tcl::ias_pop2mark mark"} test mevmtcl-ias_pop2mark-2.0 {No-op if stack smaller than mark} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal } -body { grammar::me::tcl::ias_pop2mark 5 ME_stateText } -result {tok__ T3 loc__ 2 ok___ 1 error {} sv___ {{} 2 2} ast__ {{{} 0 0} {{} 1 1} {{} 2 2}} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3}} cache {} next_ next_count ord__ {}} test mevmtcl-ias_pop2mark-2.1 {Reduce to chosen size} \ -setup { grammar::me::tcl::init next_count nc_init grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal grammar::me::tcl::ict_advance foo grammar::me::tcl::isv_terminal } -body { grammar::me::tcl::ias_pop2mark 2 ME_stateText } -result {tok__ T4 loc__ 3 ok___ 1 error {} sv___ {{} 3 3} ast__ {{{} 0 0} {{} 1 1}} input {{T1 1 1 1} {T2 1 2 2} {T3 1 3 3} {T4 1 4 4}} cache {} next_ next_count ord__ {}} # ### ### ### ######### ######### ######### ## Cleanup and statistics. rename ME_state {} testsuiteCleanup