@@ -5,63 +5,69 @@ import ast::{ident, matcher_, matcher, match_tok,
5
5
import parse:: lexer:: { new_tt_reader, tt_reader_as_reader, reader} ;
6
6
import parse:: token:: { FAT_ARROW , SEMI , LBRACE , RBRACE , nt_matchers, nt_tt} ;
7
7
import parse:: parser:: { parser, SOURCE_FILE } ;
8
- import earley_parser :: { parse, success, failure, named_match,
8
+ import earley_parser :: { parse, parse_or_else , success, failure, named_match,
9
9
matched_seq, matched_nonterminal} ;
10
10
import std:: map:: hashmap;
11
11
12
-
13
-
14
12
fn add_new_extension ( cx : ext_ctxt , sp : span , name : ident ,
15
13
arg : ~[ ast:: token_tree ] ) -> base:: mac_result {
16
14
// these spans won't matter, anyways
17
15
fn ms ( m : matcher_ ) -> matcher {
18
16
{ node: m, span : { lo : 0 u, hi : 0 u, expn_info : none} }
19
17
}
20
18
19
+ // The grammar for macro_rules! is:
20
+ // $( $lhs:mtcs => $rhs:tt );+
21
+ // ...quasiquoting this would be nice.
21
22
let argument_gram = ~[
22
23
ms ( match_seq ( ~[
23
24
ms ( match_nonterminal ( @~"lhs", @~"matchers", 0 u) ) ,
24
25
ms ( match_tok ( FAT_ARROW ) ) ,
25
26
ms ( match_nonterminal ( @~"rhs", @~"tt", 1 u) ) ,
26
27
] , some ( SEMI ) , false , 0 u, 2 u) ) ] ;
27
28
29
+
30
+ // Parse the macro_rules! invocation (`none` is for no interpolations):
28
31
let arg_reader = new_tt_reader ( cx. parse_sess ( ) . span_diagnostic ,
29
32
cx. parse_sess ( ) . interner , none, arg) ;
30
- let arguments = alt parse ( cx. parse_sess ( ) , cx. cfg ( ) ,
31
- arg_reader as reader , argument_gram) {
32
- success ( m) { m }
33
- failure ( sp, msg) { cx. span_fatal ( sp, msg) ; }
34
- } ;
33
+ let argument_map = parse_or_else ( cx. parse_sess ( ) , cx. cfg ( ) ,
34
+ arg_reader as reader , argument_gram) ;
35
35
36
- let lhses = alt arguments. get ( @~"lhs") {
36
+ // Extract the arguments:
37
+ let lhses: ~[ @named_match ] = alt argument_map. get ( @~"lhs") {
37
38
@matched_seq ( s, sp) { s }
38
39
_ { cx. span_bug ( sp, ~"wrong-structured lhs") }
39
40
} ;
40
- let rhses = alt arguments . get ( @~"rhs") {
41
+ let rhses: ~ [ @ named_match ] = alt argument_map . get ( @~"rhs") {
41
42
@matched_seq ( s, sp) { s }
42
43
_ { cx. span_bug ( sp, ~"wrong-structured rhs") }
43
44
} ;
44
45
46
+ // Given `lhses` and `rhses`, this is the new macro we create
45
47
fn generic_extension ( cx : ext_ctxt , sp : span , arg : ~[ ast:: token_tree ] ,
46
48
lhses : ~[ @named_match ] , rhses : ~[ @named_match ] )
47
49
-> mac_result {
50
+ // Which arm's failure should we report? (the one furthest along)
48
51
let mut best_fail_spot = { lo: 0 u, hi: 0 u, expn_info: none} ;
49
52
let mut best_fail_msg = ~"internal error: ran no matchers";
50
53
51
54
let s_d = cx. parse_sess ( ) . span_diagnostic ;
52
55
let itr = cx. parse_sess ( ) . interner ;
53
56
54
- for lhses. eachi( ) |i, lhs| {
57
+ for lhses. eachi( ) |i, lhs| { // try each arm's matchers
55
58
alt lhs {
56
59
@matched_nonterminal( nt_matchers( mtcs) ) {
60
+ // `none` is because we're not interpolating
57
61
let arg_rdr = new_tt_reader( s_d, itr, none, arg) as reader;
58
62
alt parse( cx. parse_sess( ) , cx. cfg( ) , arg_rdr, mtcs) {
59
- success( m ) {
60
- let rhs = alt rhses[ i] {
63
+ success( named_matches ) {
64
+ let rhs = alt rhses[ i] { // okay, what's your transcriber?
61
65
@matched_nonterminal( nt_tt( @tt) ) { tt }
62
66
_ { cx. span_bug( sp, ~"bad thing in rhs") }
63
67
} ;
64
- let trncbr = new_tt_reader( s_d, itr, some( m) , ~[ rhs] ) ;
68
+ // rhs has holes ( `$id` and `$(...)` that need filled)
69
+ let trncbr = new_tt_reader ( s_d, itr, some ( named_matches) ,
70
+ ~[ rhs] ) ;
65
71
let p = parser ( cx. parse_sess ( ) , cx. cfg ( ) ,
66
72
trncbr as reader , SOURCE_FILE ) ;
67
73
ret mr_expr( p. parse_expr ( ) ) ;
0 commit comments