You can have an anonymous sequence of symbols or set of alternatives, simply by enclosing them in parentheses. The implementation declares a dummy nonterminal for such groups, and replaces the group with the name of the dummy non-terminal.
You can also apply the postfix operators "*", "+" and "?" to any symbol or group. Curly brackets "{" .. "}" can also be used and are equivalent to ( .. ) *. Note you can't use [..] notation for optional constructions, since this conflicts with the use of [] for type subscripts.
Note: although it makes sense at present anonymous nonterminal specifications can't contain names or client code.
Note: restriction: at present each dummy is distinct, so any anonymous expression occuring more than once will lead to a reduce/reduce conflict.
Note: restriction: all the anonymous symbols must have attributes.
1: #line 3444 "./lpsrc/flx_tutorial.pak" 2: #import <flx.flxh> 3: 4: // the input string 5: data := "1+22+33$"; 6: 7: // a type for tokens 8: union token_t = 9: | TOK_EOF 10: | TOK_PLUS 11: | TOK_INT of int 12: ; 13: 14: // a token stream generator 15: var i = 0; 16: fun get_token():token_t = 17: { 18: ch := data.[i to i+1]; 19: ++i; 20: tok := 21: match ch with 22: | "$" => TOK_EOF 23: | "+" => TOK_PLUS 24: | "1" => TOK_INT 1 25: | "2" => TOK_INT 2 26: | "3" => TOK_INT 3 27: endmatch 28: ; 29: return tok; 30: } 31: 32: // a type for expression terms 33: union expr_t = 34: | Integer of int 35: ; 36: 37: // a grammar for expressions 38: nonterm eexpr : expr_t = 39: | xx:eexpr TOK_PLUS y:TOK_INT+ => 40: match xx with 41: | Integer ?i => let case 1 (?j,_) = y in Integer (i+j) 42: endmatch 43: 44: | y:TOK_INT => Integer y 45: ; 46: 47: // a parser for our example 48: var z : 1 + int = 49: parse (the get_token) with 50: | e: eexpr => match e with | Integer ?i => i endmatch 51: endmatch 52: ; 53: 54: // print the result 55: match z with 56: | case 0 => { print "Error"; } 57: | case 1 (?i) => { print i; } 58: endmatch; 59: endl; 60: