diff options
Diffstat (limited to 'grammar/grammar_test.go')
-rw-r--r-- | grammar/grammar_test.go | 683 |
1 files changed, 506 insertions, 177 deletions
diff --git a/grammar/grammar_test.go b/grammar/grammar_test.go index 46458b0..07d8b58 100644 --- a/grammar/grammar_test.go +++ b/grammar/grammar_test.go @@ -17,9 +17,10 @@ func TestGrammarBuilderOK(t *testing.T) { nameTests := []*okTest{ { - caption: "the `%name` can be the same identifier as a non-terminal symbol", + caption: "the `#name` can be the same identifier as a non-terminal symbol", specSrc: ` -%name s +#name s; + s : foo ; @@ -35,9 +36,10 @@ foo }, }, { - caption: "the `%name` can be the same identifier as a terminal symbol", + caption: "the `#name` can be the same identifier as a terminal symbol", specSrc: ` -%name foo +#name foo; + s : foo ; @@ -53,9 +55,10 @@ foo }, }, { - caption: "the `%name` can be the same identifier as the error symbol", + caption: "the `#name` can be the same identifier as the error symbol", specSrc: ` -%name error +#name error; + s : foo | error @@ -72,9 +75,10 @@ foo }, }, { - caption: "the `%name` can be the same identifier as a fragment", + caption: "the `#name` can be the same identifier as a fragment", specSrc: ` -%name f +#name f; + s : foo ; @@ -97,7 +101,8 @@ fragment f { caption: "a `#mode` can be the same identifier as a non-terminal symbol", specSrc: ` -%name test +#name test; + s : foo bar ; @@ -121,7 +126,8 @@ bar #mode s { caption: "a `#mode` can be the same identifier as a terminal symbol", specSrc: ` -%name test +#name test; + s : foo bar ; @@ -145,7 +151,8 @@ bar #mode bar { caption: "a `#mode` can be the same identifier as the error symbol", specSrc: ` -%name test +#name test; + s : foo bar | error @@ -170,7 +177,8 @@ bar #mode error { caption: "a `#mode` can be the same identifier as a fragment", specSrc: ` -%name test +#name test; + s : foo bar ; @@ -194,11 +202,28 @@ fragment f }, }, { + caption: "a `#prec` allows the empty directive group", + specSrc: ` +#name test; + +#prec (); + +s + : foo + ; + +foo + : 'foo'; +`, + }, + { caption: "a production has the same precedence and associativity as the right-most terminal symbol", specSrc: ` -%name test +#name test; -%left foo +#prec ( + #left foo +); s : foo bar // This alternative has the same precedence and associativity as the right-most terminal symbol 'bar', not 'foo'. @@ -236,10 +261,12 @@ bar { caption: "a production has the same precedence and associativity as the right-most terminal symbol", specSrc: ` -%name test +#name test; -%left foo -%right bar +#prec ( + #left foo + #right bar +); s : foo bar // This alternative has the same precedence and associativity as the right-most terminal symbol 'bar'. @@ -275,11 +302,13 @@ bar }, }, { - caption: "the `#prec` directive changes only precedence, not associativity", + caption: "the `#prec` directive applied to an alternative changes only precedence, not associativity", specSrc: ` -%name test +#name test; -%left foo +#prec ( + #left foo +); s : foo bar #prec foo @@ -315,12 +344,14 @@ bar }, }, { - caption: "the `#prec` directive changes only precedence, not associativity", + caption: "the `#prec` directive applied to an alternative changes only precedence, not associativity", specSrc: ` -%name test +#name test; -%left foo -%right bar +#prec ( + #left foo + #right bar +); s : foo bar #prec foo @@ -385,7 +416,9 @@ bar if err != nil { t.Fatalf("unexpected error: %v", err) } - test.validate(t, g) + if test.validate != nil { + test.validate(t, g) + } }) } } @@ -401,7 +434,7 @@ func TestGrammarBuilderSpecError(t *testing.T) { { caption: "a production `b` is unused", specSrc: ` -%name test +#name test; a : foo @@ -418,7 +451,7 @@ foo { caption: "a terminal symbol `bar` is unused", specSrc: ` -%name test +#name test; s : foo @@ -434,7 +467,7 @@ bar { caption: "a production `b` and terminal symbol `bar` is unused", specSrc: ` -%name test +#name test; a : foo @@ -456,7 +489,7 @@ bar { caption: "a production cannot have production directives", specSrc: ` -%name test +#name test; s #prec foo : foo @@ -470,7 +503,7 @@ foo { caption: "a lexical production cannot have alternative directives", specSrc: ` -%name test +#name test; s : foo @@ -484,7 +517,7 @@ foo { caption: "a production directive must not be duplicated", specSrc: ` -%name test +#name test; s : foo @@ -498,7 +531,7 @@ foo #skip #skip { caption: "an alternative directive must not be duplicated", specSrc: ` -%name test +#name test; s : foo bar #ast foo bar #ast foo bar @@ -514,7 +547,7 @@ bar { caption: "a production must not have a duplicate alternative (non-empty alternatives)", specSrc: ` -%name test +#name test; s : foo @@ -529,7 +562,7 @@ foo { caption: "a production must not have a duplicate alternative (non-empty and split alternatives)", specSrc: ` -%name test +#name test; s : foo @@ -552,7 +585,7 @@ bar { caption: "a production must not have a duplicate alternative (empty alternatives)", specSrc: ` -%name test +#name test; s : foo @@ -571,7 +604,7 @@ foo { caption: "a production must not have a duplicate alternative (empty and split alternatives)", specSrc: ` -%name test +#name test; s : foo @@ -593,7 +626,7 @@ foo { caption: "a terminal symbol and a non-terminal symbol (start symbol) are duplicates", specSrc: ` -%name test +#name test; s : foo @@ -609,7 +642,7 @@ s { caption: "a terminal symbol and a non-terminal symbol (not start symbol) are duplicates", specSrc: ` -%name test +#name test; s : foo @@ -629,11 +662,11 @@ a errs: []*SemanticError{semErrDuplicateName}, }, { - caption: "an invalid associativity type", + caption: "an invalid top-level directive", specSrc: ` -%name test +#name test; -%foo +#foo; s : a @@ -642,12 +675,12 @@ s a : 'a'; `, - errs: []*SemanticError{semErrMDInvalidName}, + errs: []*SemanticError{semErrDirInvalidName}, }, { caption: "a label must be unique in an alternative", specSrc: ` -%name test +#name test; s : foo@x bar@x @@ -663,7 +696,7 @@ bar { caption: "a label cannot be the same name as terminal symbols", specSrc: ` -%name test +#name test; s : foo bar@foo @@ -679,7 +712,7 @@ bar { caption: "a label cannot be the same name as non-terminal symbols", specSrc: ` -%name test +#name test; s : foo@a @@ -700,10 +733,85 @@ bar }, } - nameTests := []*specErrTest{ + nameDirTests := []*specErrTest{ + { + caption: "the `#name` directive is required", + specSrc: ` +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrNoGrammarName}, + }, + { + caption: "the `#name` directive needs an ID parameter", + specSrc: ` +#name; + +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { + caption: "the `#name` directive cannot take a pattern parameter", + specSrc: ` +#name "test"; + +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { + caption: "the `#name` directive cannot take a string parameter", + specSrc: ` +#name 'test'; + +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { + caption: "the `#name` directive takes just one parameter", + specSrc: ` +#name test1 test2; + +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + } + + precDirTests := []*specErrTest{ { - caption: "the `%name` is required", + caption: "the `#prec` directive needs a directive group parameter", specSrc: ` +#name test; + +#prec; + s : foo ; @@ -711,12 +819,14 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDMissingName}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%name` needs an ID parameter", + caption: "the `#prec` directive cannot take an ID parameter", specSrc: ` -%name +#name test; + +#prec foo; s : foo @@ -725,12 +835,14 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%name` takes just one parameter", + caption: "the `#prec` directive cannot take a pattern parameter", specSrc: ` -%name test1 test2 +#name test; + +#prec "foo"; s : foo @@ -739,17 +851,51 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { + caption: "the `#prec` directive cannot take a string parameter", + specSrc: ` +#name test; + +#prec 'foo'; + +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { + caption: "the `#prec` directive takes just one directive group parameter", + specSrc: ` +#name test; + +#prec () (); + +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, }, } - leftTests := []*specErrTest{ + leftDirTests := []*specErrTest{ { - caption: "the `%left` needs ID parameters", + caption: "the `#left` directive needs ID parameters", specSrc: ` -%name test +#name test; -%left +#prec ( + #left +); s : foo @@ -758,14 +904,16 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%left` cannot take an undefined symbol", + caption: "the `#left` directive cannot take an undefined symbol", specSrc: ` -%name test +#name test; -%left x +#prec ( + #left x +); s : foo @@ -774,14 +922,16 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%left` cannot take a non-terminal symbol", + caption: "the `#left` directive cannot take a non-terminal symbol", specSrc: ` -%name test +#name test; -%left s +#prec ( + #left s +); s : foo @@ -790,14 +940,16 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%left` cannot take a pattern parameter", + caption: "the `#left` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; -%left "foo" +#prec ( + #left "foo" +); s : foo @@ -806,14 +958,16 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%left` cannot take a string parameter", + caption: "the `#left` directive cannot take a string parameter", specSrc: ` -%name test +#name test; -%left 'foo' +#prec ( + #left 'foo' +); s : foo @@ -822,14 +976,34 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%left` cannot be specified multiple times for a symbol", + caption: "the `#left` directive cannot take a directive parameter", specSrc: ` -%name test +#name test; -%left foo foo +#prec ( + #left () +); + +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { + caption: "the `#left` dirctive cannot be specified multiple times for a symbol", + specSrc: ` +#name test; + +#prec ( + #left foo foo +); s : foo @@ -843,10 +1017,12 @@ foo { caption: "a symbol cannot have different precedence", specSrc: ` -%name test +#name test; -%left foo -%left foo +#prec ( + #left foo + #left foo +); s : foo @@ -860,10 +1036,12 @@ foo { caption: "a symbol cannot have different associativity", specSrc: ` -%name test +#name test; -%right foo -%left foo +#prec ( + #right foo + #left foo +); s : foo @@ -876,13 +1054,15 @@ foo }, } - rightTests := []*specErrTest{ + rightDirTests := []*specErrTest{ { - caption: "the `%right` needs ID parameters", + caption: "the `#right` directive needs ID parameters", specSrc: ` -%name test +#name test; -%right +#prec ( + #right +); s : foo @@ -891,14 +1071,16 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%right` cannot take an undefined symbol", + caption: "the `#right` directive cannot take an undefined symbol", specSrc: ` -%name test +#name test; -%right x +#prec ( + #right x +); s : foo @@ -907,14 +1089,16 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%right` cannot take a non-terminal symbol", + caption: "the `#right` directive cannot take a non-terminal symbol", specSrc: ` -%name test +#name test; -%right s +#prec ( + #right s +); s : foo @@ -923,14 +1107,16 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%right` cannot take a pattern parameter", + caption: "the `#right` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; -%right "foo" +#prec ( + #right "foo" +); s : foo @@ -939,14 +1125,16 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%right` cannot take a string parameter", + caption: "the `#right` directive cannot take a string parameter", specSrc: ` -%name test +#name test; -%right 'foo' +#prec ( + #right 'foo' +); s : foo @@ -955,14 +1143,34 @@ s foo : 'foo'; `, - errs: []*SemanticError{semErrMDInvalidParam}, + errs: []*SemanticError{semErrDirInvalidParam}, }, { - caption: "the `%right` cannot be specified multiple times for a symbol", + caption: "the `#right` directive cannot take a directive group parameter", specSrc: ` -%name test +#name test; -%right foo foo +#prec ( + #right () +); + +s + : foo + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { + caption: "the `#right` directive cannot be specified multiple times for a symbol", + specSrc: ` +#name test; + +#prec ( + #right foo foo +); s : foo @@ -976,10 +1184,12 @@ foo { caption: "a symbol cannot have different precedence", specSrc: ` -%name test +#name test; -%right foo -%right foo +#prec ( + #right foo + #right foo +); s : foo @@ -993,10 +1203,12 @@ foo { caption: "a symbol cannot have different associativity", specSrc: ` -%name test +#name test; -%left foo -%right foo +#prec ( + #left foo + #right foo +); s : foo @@ -1013,7 +1225,7 @@ foo { caption: "cannot use the error symbol as a non-terminal symbol", specSrc: ` -%name test +#name test; s : error @@ -1032,7 +1244,7 @@ foo: 'foo'; { caption: "cannot use the error symbol as a terminal symbol", specSrc: ` -%name test +#name test; s : error @@ -1045,7 +1257,7 @@ error: 'error'; { caption: "cannot use the error symbol as a terminal symbol, even if given the skip directive", specSrc: ` -%name test +#name test; s : foo @@ -1064,7 +1276,7 @@ error #skip { caption: "the `#ast` directive needs ID or label prameters", specSrc: ` -%name test +#name test; s : foo #ast @@ -1078,7 +1290,7 @@ foo { caption: "the `#ast` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; s : foo #ast "foo" @@ -1092,7 +1304,7 @@ foo { caption: "the `#ast` directive cannot take a string parameter", specSrc: ` -%name test +#name test; s : foo #ast 'foo' @@ -1104,9 +1316,23 @@ foo errs: []*SemanticError{semErrDirInvalidParam}, }, { + caption: "the `#ast` directive cannot take a directive group parameter", + specSrc: ` +#name test; + +s + : foo #ast () + ; + +foo + : "foo"; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { caption: "a parameter of the `#ast` directive must be either a symbol or a label in an alternative", specSrc: ` -%name test +#name test; s : foo bar #ast foo x @@ -1122,7 +1348,7 @@ bar { caption: "a symbol in a different alternative cannot be a parameter of the `#ast` directive", specSrc: ` -%name test +#name test; s : foo #ast bar @@ -1139,7 +1365,7 @@ bar { caption: "a label in a different alternative cannot be a parameter of the `#ast` directive", specSrc: ` -%name test +#name test; s : foo #ast b @@ -1156,7 +1382,7 @@ bar { caption: "a symbol can appear in the `#ast` directive only once", specSrc: ` -%name test +#name test; s : foo #ast foo foo @@ -1170,7 +1396,7 @@ foo { caption: "a label can appear in the `#ast` directive only once", specSrc: ` -%name test +#name test; s : foo@x #ast x x @@ -1184,7 +1410,7 @@ foo { caption: "a symbol can appear in the `#ast` directive only once, even if the symbol has a label", specSrc: ` -%name test +#name test; s : foo@x #ast foo x @@ -1198,7 +1424,7 @@ foo { caption: "symbol `foo` is ambiguous because it appears in an alternative twice", specSrc: ` -%name test +#name test; s : foo foo #ast foo @@ -1212,7 +1438,7 @@ foo { caption: "symbol `foo` is ambiguous because it appears in an alternative twice, even if one of them has a label", specSrc: ` -%name test +#name test; s : foo@x foo #ast foo @@ -1226,7 +1452,7 @@ foo { caption: "the expansion operator cannot be applied to a terminal symbol", specSrc: ` -%name test +#name test; s : foo #ast foo... @@ -1240,7 +1466,7 @@ foo { caption: "the expansion operator cannot be applied to a pattern", specSrc: ` -%name test +#name test; s : foo "bar"@b #ast foo b... @@ -1254,7 +1480,7 @@ foo { caption: "the expansion operator cannot be applied to a string", specSrc: ` -%name test +#name test; s : foo 'bar'@b #ast foo b... @@ -1267,11 +1493,11 @@ foo }, } - precDirTests := []*specErrTest{ + altPrecDirTests := []*specErrTest{ { caption: "the `#prec` directive needs an ID parameter", specSrc: ` -%name test +#name test; s : foo #prec @@ -1285,7 +1511,7 @@ foo { caption: "the `#prec` directive cannot take an undefined symbol", specSrc: ` -%name test +#name test; s : foo #prec x @@ -1299,7 +1525,7 @@ foo { caption: "the `#prec` directive cannot take a non-terminal symbol", specSrc: ` -%name test +#name test; s : a #prec b @@ -1322,7 +1548,7 @@ bar { caption: "the `#prec` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; s : foo #prec "foo" @@ -1336,7 +1562,7 @@ foo { caption: "the `#prec` directive cannot take a string parameter", specSrc: ` -%name test +#name test; s : foo #prec 'foo' @@ -1348,9 +1574,23 @@ foo errs: []*SemanticError{semErrDirInvalidParam}, }, { + caption: "the `#prec` directive cannot take a directive parameter", + specSrc: ` +#name test; + +s + : foo #prec () + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { caption: "a symbol the `#prec` directive takes must be given precedence explicitly", specSrc: ` -%name test +#name test; s : foo bar #prec foo @@ -1369,9 +1609,7 @@ bar { caption: "the `#recover` directive cannot take an ID parameter", specSrc: ` -%name test - -%name test +#name test; s : foo #recover foo @@ -1385,9 +1623,7 @@ foo { caption: "the `#recover` directive cannot take a pattern parameter", specSrc: ` -%name test - -%name test +#name test; s : foo #recover "foo" @@ -1401,9 +1637,7 @@ foo { caption: "the `#recover` directive cannot take a string parameter", specSrc: ` -%name test - -%name test +#name test; s : foo #recover 'foo' @@ -1414,13 +1648,27 @@ foo `, errs: []*SemanticError{semErrDirInvalidParam}, }, + { + caption: "the `#recover` directive cannot take a directive group parameter", + specSrc: ` +#name test; + +s + : foo #recover () + ; + +foo + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, } fragmentTests := []*specErrTest{ { caption: "a production cannot contain a fragment", specSrc: ` -%name test +#name test; s : f @@ -1434,7 +1682,7 @@ fragment f { caption: "fragments cannot be duplicated", specSrc: ` -%name test +#name test; s : foo @@ -1455,7 +1703,7 @@ fragment f { caption: "the `#alias` directive needs a string parameter", specSrc: ` -%name test +#name test; s : foo @@ -1469,7 +1717,7 @@ foo #alias { caption: "the `#alias` directive takes just one string parameter", specSrc: ` -%name test +#name test; s : foo @@ -1483,7 +1731,7 @@ foo #alias 'Foo' 'FOO' { caption: "the `#alias` directive cannot take an ID parameter", specSrc: ` -%name test +#name test; s : foo @@ -1497,7 +1745,7 @@ foo #alias Foo { caption: "the `#alias` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; s : foo @@ -1508,13 +1756,27 @@ foo #alias "Foo" `, errs: []*SemanticError{semErrDirInvalidParam}, }, + { + caption: "the `#alias` directive cannot take a directive group parameter", + specSrc: ` +#name test; + +s + : foo + ; + +foo #alias () + : 'foo'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, } - modeTests := []*specErrTest{ + modeDirTests := []*specErrTest{ { caption: "the `#mode` directive needs an ID parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1530,7 +1792,7 @@ bar #mode { caption: "the `#mode` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1546,7 +1808,7 @@ bar #mode "mode_1" { caption: "the `#mode` directive cannot take a string parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1559,13 +1821,29 @@ bar #mode 'mode_1' `, errs: []*SemanticError{semErrDirInvalidParam}, }, + { + caption: "the `#mode` directive cannot take a directive group parameter", + specSrc: ` +#name test; + +s + : foo bar + ; + +foo #push mode_1 + : 'foo'; +bar #mode () + : 'bar'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, } - pushTests := []*specErrTest{ + pushDirTests := []*specErrTest{ { caption: "the `#push` directive needs an ID parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1581,7 +1859,7 @@ bar #mode mode_1 { caption: "the `#push` directive takes just one ID parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1597,7 +1875,7 @@ bar #mode mode_1 { caption: "the `#push` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1613,7 +1891,7 @@ bar #mode mode_1 { caption: "the `#push` directive cannot take a string parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1626,13 +1904,29 @@ bar #mode mode_1 `, errs: []*SemanticError{semErrDirInvalidParam}, }, + { + caption: "the `#push` directive cannot take a directive group parameter", + specSrc: ` +#name test; + +s + : foo bar + ; + +foo #push () + : 'foo'; +bar #mode mode_1 + : 'bar'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, } - popTests := []*specErrTest{ + popDirTests := []*specErrTest{ { caption: "the `#pop` directive cannot take an ID parameter", specSrc: ` -%name test +#name test; s : foo bar baz @@ -1650,7 +1944,7 @@ baz #pop mode_1 { caption: "the `#pop` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; s : foo bar baz @@ -1668,7 +1962,7 @@ baz #pop "mode_1" { caption: "the `#pop` directive cannot take a string parameter", specSrc: ` -%name test +#name test; s : foo bar baz @@ -1683,13 +1977,31 @@ baz #pop 'mode_1' `, errs: []*SemanticError{semErrDirInvalidParam}, }, + { + caption: "the `#pop` directive cannot take a directive parameter", + specSrc: ` +#name test; + +s + : foo bar baz + ; + +foo #push mode_1 + : 'foo'; +bar #mode mode_1 + : 'bar'; +baz #pop () + : 'baz'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, } skipDirTests := []*specErrTest{ { caption: "the `#skip` directive cannot take an ID parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1705,7 +2017,7 @@ bar { caption: "the `#skip` directive cannot take a pattern parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1721,7 +2033,7 @@ bar { caption: "the `#skip` directive cannot take a string parameter", specSrc: ` -%name test +#name test; s : foo bar @@ -1735,9 +2047,25 @@ bar errs: []*SemanticError{semErrDirInvalidParam}, }, { + caption: "the `#skip` directive cannot take a directive group parameter", + specSrc: ` +#name test; + +s + : foo bar + ; + +foo #skip () + : 'foo'; +bar + : 'bar'; +`, + errs: []*SemanticError{semErrDirInvalidParam}, + }, + { caption: "a terminal symbol used in productions cannot have the skip directive", specSrc: ` -%name test +#name test; s : foo bar @@ -1754,18 +2082,19 @@ bar var tests []*specErrTest tests = append(tests, prodTests...) - tests = append(tests, nameTests...) - tests = append(tests, leftTests...) - tests = append(tests, rightTests...) + tests = append(tests, nameDirTests...) + tests = append(tests, precDirTests...) + tests = append(tests, leftDirTests...) + tests = append(tests, rightDirTests...) tests = append(tests, errorSymTests...) tests = append(tests, astDirTests...) - tests = append(tests, precDirTests...) + tests = append(tests, altPrecDirTests...) tests = append(tests, recoverDirTests...) tests = append(tests, fragmentTests...) tests = append(tests, aliasDirTests...) - tests = append(tests, modeTests...) - tests = append(tests, pushTests...) - tests = append(tests, popTests...) + tests = append(tests, modeDirTests...) + tests = append(tests, pushDirTests...) + tests = append(tests, popDirTests...) tests = append(tests, skipDirTests...) for _, test := range tests { t.Run(test.caption, func(t *testing.T) { |