@@ -27,8 +27,9 @@ use cpclib_tokens::macro_segment::tokenize_macro_body;
2727use cpclib_tokens:: { Expr , ExprFormat , FormattedExpr } ;
2828
2929use super :: common:: {
30- inner_code, inner_code_with_state, my_line_ending, my_many0_nocollect, my_space0, my_space1,
31- parse_argname_and_value, parse_comma, parse_comment, parse_convertible_word,
30+ inner_code, inner_code_with_state, my_line_ending, my_many0_nocollect, my_space0,
31+ my_space0_with_newlines, my_space1, parse_argname_and_value, parse_comma,
32+ parse_comma_multiline, parse_comment, parse_convertible_word,
3233 parse_optional_argname_and_value, parse_word
3334} ;
3435use super :: context;
@@ -2926,63 +2927,112 @@ pub fn parse_macro_or_struct_call_inner(
29262927
29272928 let has_parenthesis = opt ( (
29282929 '(' ,
2929- my_space0 ,
2930- not ( alt ( ( ( "void" , my_space0 ) . value ( ( ) ) , ')' . value ( ( ) ) ) ) )
2930+ my_space0_with_newlines ,
2931+ not ( alt ( ( ( "void" , my_space0_with_newlines ) . value ( ( ) ) , ')' . value ( ( ) ) ) ) )
29312932 ) )
29322933 . parse_next ( input) ?
29332934 . is_some ( ) ;
2934- let args: Vec < ( LocatedMacroParam , & [ u8 ] ) > = if peek ( alt ( (
2935- eof. value ( ( ) ) ,
2936- parse_comment. value ( ( ) ) ,
2937- line_ending. value ( ( ) ) ,
2938- ':' . value ( ( ) )
2939- ) ) )
2940- . parse_next ( input)
2941- . is_ok ( )
2935+ let args: Vec < ( LocatedMacroParam , & [ u8 ] ) > = if !has_parenthesis
2936+ && peek ( alt ( (
2937+ eof. value ( ( ) ) ,
2938+ parse_comment. value ( ( ) ) ,
2939+ line_ending. value ( ( ) ) ,
2940+ ':' . value ( ( ) )
2941+ ) ) )
2942+ . parse_next ( input)
2943+ . is_ok ( )
2944+ || ( has_parenthesis
2945+ && peek ( alt ( ( eof. value ( ( ) ) , parse_comment. value ( ( ) ) , ':' . value ( ( ) ) ) ) )
2946+ . parse_next ( input)
2947+ . is_ok ( ) )
29422948 {
29432949 vec ! [ ]
29442950 }
29452951 else {
2946- cut_err (
2947- alt ( (
2948- delimited (
2949- my_space0,
2952+ if has_parenthesis {
2953+ cut_err (
2954+ alt ( (
2955+ delimited (
2956+ my_space0,
2957+ alt ( (
2958+ "()" . value ( ( ) ) ,
2959+ Caseless ( "(void)" ) . value ( ( ) ) ,
2960+ parse_comment. value ( ( ) )
2961+ ) ) ,
2962+ my_space0
2963+ )
2964+ . value ( Default :: default ( ) ) ,
29502965 alt ( (
2951- "()" . value ( ( ) ) ,
2952- Caseless ( "(void)" ) . value ( ( ) ) ,
2953- parse_comment. value ( ( ) )
2954- ) ) ,
2955- my_space0
2956- )
2957- . value ( Default :: default ( ) ) ,
2966+ alt ( ( Caseless ( "(void)" ) , "()" ) ) . value ( Vec :: new ( ) ) ,
2967+ delimited (
2968+ my_space0_with_newlines,
2969+ separated (
2970+ 1 ..,
2971+ alt ( (
2972+ parse_macro_arg. with_taken ( ) ,
2973+ my_space1
2974+ . map ( |space : InnerZ80Span | {
2975+ LocatedMacroParam :: RawArgument ( space. into ( ) )
2976+ } )
2977+ . with_taken ( )
2978+ ) ) ,
2979+ parse_comma_multiline
2980+ ) ,
2981+ my_space0_with_newlines
2982+ )
2983+ ) )
2984+ ) )
2985+ . context ( if for_struct {
2986+ "STRUCT: error in arguments list"
2987+ }
2988+ else {
2989+ "MACRO or STRUCT: forbidden name"
2990+ } )
2991+ )
2992+ . parse_next ( input) ?
2993+ }
2994+ else {
2995+ cut_err (
29582996 alt ( (
2959- alt ( ( Caseless ( "(void)" ) , "()" ) ) . value ( Vec :: new ( ) ) ,
2960- separated (
2961- 1 ..,
2997+ delimited (
2998+ my_space0,
29622999 alt ( (
2963- parse_macro_arg. with_taken ( ) ,
2964- my_space1
2965- . map ( |space : InnerZ80Span | {
2966- LocatedMacroParam :: RawArgument ( space. into ( ) )
2967- } )
2968- . with_taken ( )
3000+ "()" . value ( ( ) ) ,
3001+ Caseless ( "(void)" ) . value ( ( ) ) ,
3002+ parse_comment. value ( ( ) )
29693003 ) ) ,
2970- parse_comma
3004+ my_space0
29713005 )
3006+ . value ( Default :: default ( ) ) ,
3007+ alt ( (
3008+ alt ( ( Caseless ( "(void)" ) , "()" ) ) . value ( Vec :: new ( ) ) ,
3009+ separated (
3010+ 1 ..,
3011+ alt ( (
3012+ parse_macro_arg. with_taken ( ) ,
3013+ my_space1
3014+ . map ( |space : InnerZ80Span | {
3015+ LocatedMacroParam :: RawArgument ( space. into ( ) )
3016+ } )
3017+ . with_taken ( )
3018+ ) ) ,
3019+ parse_comma
3020+ )
3021+ ) )
29723022 ) )
2973- ) )
2974- . context ( if for_struct {
2975- "STRUCT: error in arguments list"
2976- }
2977- else {
2978- "MACRO or STRUCT: forbidden name"
2979- } )
2980- )
2981- . parse_next ( input ) ?
3023+ . context ( if for_struct {
3024+ "STRUCT: error in arguments list"
3025+ }
3026+ else {
3027+ "MACRO or STRUCT: forbidden name"
3028+ } )
3029+ )
3030+ . parse_next ( input ) ?
3031+ }
29823032 } ;
29833033
29843034 if has_parenthesis {
2985- ( my_space0 , ')' , my_space0) . parse_next ( input) ?;
3035+ ( my_space0_with_newlines , ')' , my_space0) . parse_next ( input) ?;
29863036 }
29873037
29883038 if args. len ( ) == 1 && args. first ( ) . unwrap ( ) . 0 . is_empty ( ) {
@@ -3251,4 +3301,39 @@ mod tests {
32513301 assert ! ( res. res. is_ok( ) , "Should parse successfully: {}" , input) ;
32523302 }
32533303 }
3304+
3305+
3306+ #[ test]
3307+ fn test_parse_macro_call ( ) {
3308+ let cases = [
3309+ ( "MACRO1" , "MACRO1()" , 0 ) ,
3310+ ( "MACRO2" , "MACRO2(void)" , 0 ) ,
3311+ ( "MACRO3" , "MACRO3(42)" , 1 ) ,
3312+ ( "MACRO4" , "MACRO4(arg1, arg2, arg3)" , 3 ) ,
3313+ ( "MACRO5" , "MACRO5([nested, list], {eval} evaluated_arg, raw_arg)" , 3 ) ,
3314+ ( "SWITCH_VALUES" , "SWITCH_VALUES(scroller_configuration_table.current_generating_code_table,scroller_configuration_table.next_generating_code_table)" , 2 ) ,
3315+ ( "SWITCH_VALUES" , "SWITCH_VALUES(\n scroller_configuration_table.current_generating_code_table,\n scroller_configuration_table.next_generating_code_table\n )" , 2 ) ,
3316+ ( "add_to_a" , "add_to_a(10)" , 1 )
3317+ ] ;
3318+
3319+ for ( name, call, expected_args) in cases {
3320+ let res = dbg ! ( parse_test( parse_macro_or_struct_call( false , false ) , call) ) ;
3321+ assert ! (
3322+ res. res. is_ok( ) ,
3323+ "Should parse successfully: {} (error: {:?})" ,
3324+ call,
3325+ res. res. err( )
3326+ ) ;
3327+
3328+ let token = dbg ! ( res. res. unwrap( ) . inner. left( ) . unwrap( ) ) ;
3329+ if let LocatedTokenInner :: MacroCall ( call_name, args) = token {
3330+ assert_eq ! ( call_name. as_bstr( ) , name. as_bytes( ) , "Macro name should match" ) ;
3331+ assert_eq ! ( args. len( ) , expected_args, "Expected {} arguments, got {}" , expected_args, args. len( ) ) ;
3332+ println ! ( "Parsed macro call: {} with args: {:?}" , call_name, args) ;
3333+ }
3334+ else {
3335+ panic ! ( "Expected a MacroCall token" ) ;
3336+ }
3337+ }
3338+ }
32543339}
0 commit comments