Advertisement
funny_falcon

parser_combinator.c

Jul 8th, 2017
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.05 KB | None | 0 0
  1. // copy from: https://groups.google.com/forum/#!msg/comp.lang.c/BuwBXfpgN_M/4I4krY2PAgAJ
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4.  
  5. typedef struct parser *parser;
  6. typedef struct result *result;
  7. typedef result (*handler)( parser p, char *input );
  8.  
  9. struct parser {
  10.   handler test;
  11.   parser a, b;
  12.   int c;
  13. };
  14.  
  15. struct result {
  16.   result next;
  17.   int length_matched;
  18. };
  19.  
  20. #define new_function_for_(type) \
  21.   type new_##type ( struct type input ){ \
  22.     type local = calloc( sizeof *local, 1 ); \
  23.     return  local  ?  ( *local = input ), local  :  local; \
  24.   }
  25. new_function_for_(parser)
  26. new_function_for_(result)
  27.  
  28.  
  29. result parse( parser p, char *input ){  return  p->test( p, input );  }
  30. result parse_fail( parser p, char *input ){  return  NULL;  }
  31. result parse_succeed( parser p, char *input ){
  32.   return  new_result( (struct result){ .next = NULL, .length_matched = 0 } );
  33. }
  34. result parse_term( parser p, char *input ){
  35.   return  *input == p->c  ?
  36.     new_result( (struct result){ .next = NULL, .length_matched = 1 } ) :
  37.     NULL;
  38. }
  39.  
  40. result parse_alternate( parser p, char *input ){
  41.   result res = parse( p->a, input );
  42.   if(  res  ){
  43.     result r = res;
  44.     while(  r->next  ) r = r->next;
  45.     r->next = parse( p->b, input );
  46.     return  res;
  47.   } else  return  parse( p->b, input );
  48. }
  49.  
  50. void amend_lengths( result r, int length ){
  51.   if(  r  )  r->length_matched += length;
  52.   if(  r->next  )  amend_lengths( r->next, length );
  53. }
  54.  
  55. result parse_sequence_next( result r, parser p, char *input ){
  56.   if(  ! r  )  return  NULL;
  57.   result res = parse( p->b, input + r->length_matched );
  58.   if(  res  ){
  59.     amend_lengths( res, r->length_matched );
  60.     result tail = res;
  61.     while(  tail->next  )  tail = tail->next;
  62.     tail->next = parse_sequence_next( r->next, p, input );
  63.     return  res;
  64.   } else  return  parse_sequence_next( r->next, p, input );
  65. }
  66.  
  67. result parse_sequence( parser p, char *input ){
  68.   result res = parse( p->a, input );
  69.   return  parse_sequence_next( res, p, input );
  70. }
  71.  
  72.  
  73. parser fails(){  return  new_parser( (struct parser){ .test = parse_fail } ); }
  74. parser succeeds(){  return  new_parser( (struct parser){ .test = parse_succeed } ); }
  75.  
  76. parser term( int c ){
  77.   return  new_parser( (struct parser){ .test = parse_term, .c = c } );
  78. }
  79. parser alternate( parser a, parser b){
  80.   return  new_parser( (struct parser){ .test = parse_alternate, .a = a, .b = b } );
  81. }
  82. parser sequence( parser a, parser b){
  83.   return  new_parser( (struct parser){ .test = parse_sequence, .a = a, .b = b } );
  84. }
  85. parser many( parser a ){
  86.   parser q = new_parser( (struct parser){ .test = parse_sequence, .a = a } );
  87.   parser r = new_parser( (struct parser){ .test = parse_alternate, .a = q, .b = succeeds() } );
  88.   q->b = r;
  89.   return r;
  90. }
  91. parser some( parser a ){
  92.   parser q = new_parser( (struct parser){ .test = parse_sequence, .a = a } );
  93.   parser r = new_parser( (struct parser){ .test = parse_alternate, .a = q, .b = succeeds() } );
  94.   q->b = r;
  95.   return q;
  96. }
  97.  
  98. parser char_class( char *str ){
  99.   return  *str  ?  alternate( term( *str ), char_class( str + 1 ) )  :  fails();
  100. }
  101. parser string( char *str ){
  102.   return  *str  ?  sequence( term( *str ), string( str + 1 ) )  :  succeeds();
  103. }
  104.  
  105.  
  106. void print_results( result res ){
  107.   if(  res  )  printf( "%d ", res->length_matched ),
  108.                  print_results( res->next );
  109. }
  110.  
  111. void test( parser p, char *str ){
  112.   printf( "%s:", str );
  113.   fflush(0);
  114.   result r = parse( p, str );
  115.   print_results( r );
  116.   printf( "\n" );
  117. }
  118.  
  119. int main(){
  120.   parser p = string("hello");
  121.   test( p, "hello" );
  122.   test( p, "hell" );
  123.   test( p, "hello w" );
  124.   test( p, "xxxxx" );
  125.  
  126.   parser q = many( term( 'x' ) );
  127.   test( q, "xy" );
  128.   test( q, "xx" );
  129.   test( q, "xxxy" );
  130.   test( q, "xxxxy" );
  131.   test( q, "xxxxx" );
  132.  
  133.   parser r = sequence( many( term( 'x' ) ), string( "xy" ) );
  134.   test( r, "xy" );
  135.   test( r, "xx" );
  136.   test( r, "xxxy" );
  137.   test( r, "xxxxy" );
  138.   test( r, "xxxxx" );
  139.   return 0;
  140. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement