texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

branch master updated: * tp/Texinfo/ParserNonXS.pm (_split_def_args) (_n


From: Patrice Dumas
Subject: branch master updated: * tp/Texinfo/ParserNonXS.pm (_split_def_args) (_next_bracketed_or_word_agg, _parse_def): add _next_bracketed_or_word_agg and modify _parse_def to use the same code as the XS parser, which is much cleaner.
Date: Mon, 27 Mar 2023 08:33:02 -0400

This is an automated email from the git hooks/post-receive script.

pertusus pushed a commit to branch master
in repository texinfo.

The following commit(s) were added to refs/heads/master by this push:
     new 497b415675 * tp/Texinfo/ParserNonXS.pm (_split_def_args) 
(_next_bracketed_or_word_agg, _parse_def): add _next_bracketed_or_word_agg and 
modify _parse_def to use the same code as the XS parser, which is much cleaner.
497b415675 is described below

commit 497b415675b4152b94a3cfe17dedbd27b830e939
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Mon Mar 27 14:32:52 2023 +0200

    * tp/Texinfo/ParserNonXS.pm (_split_def_args)
    (_next_bracketed_or_word_agg, _parse_def): add
    _next_bracketed_or_word_agg and modify _parse_def to use the same code
    as the XS parser, which is much cleaner.
    
    * tp/Texinfo/ParserNonXS.pm (_parse_def, _end_line_def_line),
    tp/Texinfo/XS/parsetexi/def.c (parse_def, end_line_def_line): do not
    put spaces in the last linemacro defined command call argument.
---
 ChangeLog                          |  11 ++
 tp/Texinfo/ParserNonXS.pm          | 287 ++++++++++++++++---------------------
 tp/Texinfo/XS/parsetexi/def.c      |   4 +-
 tp/Texinfo/XS/parsetexi/end_line.c |  11 +-
 4 files changed, 142 insertions(+), 171 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 16f533479a..e2fbb2fa19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2023-03-27  Patrice Dumas  <pertusus@free.fr>
+
+       * tp/Texinfo/ParserNonXS.pm (_split_def_args)
+       (_next_bracketed_or_word_agg, _parse_def): add
+       _next_bracketed_or_word_agg and modify _parse_def to use the same code
+       as the XS parser, which is much cleaner.
+
+       * tp/Texinfo/ParserNonXS.pm (_parse_def, _end_line_def_line),
+       tp/Texinfo/XS/parsetexi/def.c (parse_def, end_line_def_line): do not
+       put spaces in the last linemacro defined command call argument.
+
 2023-03-26  Patrice Dumas  <pertusus@free.fr>
 
        linemacro implementation for the XS Parser
diff --git a/tp/Texinfo/ParserNonXS.pm b/tp/Texinfo/ParserNonXS.pm
index e8b401dfe1..222185a36d 100644
--- a/tp/Texinfo/ParserNonXS.pm
+++ b/tp/Texinfo/ParserNonXS.pm
@@ -2951,6 +2951,9 @@ sub _split_def_args
                                $current_position, length($t));
       if ($type) {
         $e->{'type'} = $type;
+        if ($type eq 'spaces') {
+          $e->{'extra'} = {'def_role' => 'spaces'};
+        }
         $type = undef;
       } else {
         $type = 'spaces';
@@ -2972,6 +2975,57 @@ sub _split_def_args
   return $root;
 }
 
+# the index is set past the gathered or aggregated
+# element.
+sub _next_bracketed_or_word_agg($$)
+{
+  my $current = shift;
+  my $index_ref = shift;
+
+  my $num = 0;
+  while (1) {
+    if (!$current->{'contents'}
+        or $$index_ref == scalar(@{$current->{'contents'}})) {
+      last;
+    }
+    my $element = $current->{'contents'}->[$$index_ref];
+    if ($element->{'type'} and ($element->{'type'} eq 'spaces'
+                                or $element->{'type'} eq 'spaces_inserted'
+                                or $element->{'type'} eq 'delimiter')) {
+      last if ($num > 0);
+
+      $$index_ref++;
+      next;
+    } elsif ($element->{'type'}
+             and ($element->{'type'} eq 'bracketed_arg'
+                  or $element->{'type'} eq 'bracketed_inserted')) {
+      last if ($num > 0);
+
+      $$index_ref++;
+      return $element;
+    }
+    # element is a text or command element
+    $$index_ref++;
+    $num++;
+  }
+
+  return undef if ($num == 0);
+
+  return $current->{'contents'}->[$$index_ref -1]
+    if ($num == 1);
+
+  my @gathered_contents
+    = splice(@{$current->{'contents'}}, $$index_ref - $num, $num);
+  my $new = {'type' => 'def_aggregate', 'parent' => $current,
+             'contents' => \@gathered_contents};
+  foreach my $content (@gathered_contents) {
+    $content->{'parent'} = $new;
+  }
+  splice (@{$current->{'contents'}}, $$index_ref - $num, 0, ($new));
+  $$index_ref = $$index_ref - $num + 1;
+  return $new;
+}
+
 # definition line parsing
 sub _parse_def($$$$)
 {
@@ -2985,7 +3039,7 @@ sub _parse_def($$$$)
 
   my @args;
   my $arg_type;
-  my $remaining_args_nr;
+  my $arg_types_nr;
 
   if ($self->{'macros'}->{$command}) {
     my $macro = $self->{'macros'}->{$command}->{'element'};
@@ -2999,10 +3053,10 @@ sub _parse_def($$$$)
         }
       }
     }
-    $remaining_args_nr = $args_total;
-    if ($remaining_args_nr > 0) {
+    $arg_types_nr = $args_total;
+    if ($arg_types_nr > 0) {
       # remove one for the rest of the line argument
-      $remaining_args_nr--;
+      $arg_types_nr--;
     }
   } else{
     # could have used def_aliases, but use code more similar with the XS parser
@@ -3023,6 +3077,7 @@ sub _parse_def($$$$)
       unshift @contents, $bracketed,
                          { 'text' => ' ', 'type' => 'spaces_inserted',
                            'parent' => $current,
+                           'extra' => {'def_role' => 'spaces'},
                          };
 
       $command = $def_aliases{$command};
@@ -3031,7 +3086,7 @@ sub _parse_def($$$$)
     $arg_type = pop @args if ($args[-1] eq 'arg' or $args[-1] eq 'argtype');
     # If $arg_type is not set (for @def* commands that are not documented
     # to take args), everything happens as if arg_type was set to 'arg'.
-    $remaining_args_nr = scalar(@args);
+    $arg_types_nr = scalar(@args);
   }
   @contents = map (_split_def_args($self, $_, $current, $source_info),
                    @contents );
@@ -3039,173 +3094,86 @@ sub _parse_def($$$$)
 
   $current->{'contents'} = \@new_contents;
 
-  my @result;
+  my %result;
 
   #  Fill in everything up to the args, collecting adjacent non-whitespace
   #  elements into a single element, e.g 'a@i{b}c'.
-  my $argument_content = [];
-  $remaining_args_nr--;
-
-  my $i = 0; # the offset in @new_contents of $token
-  if ($remaining_args_nr >= 0) {
-    while (@contents) {
-      my $token = $contents[0];
-      # finish previous item
-      if ( $token->{'type'}
-          and ($token->{'type'} eq 'spaces'
-                 or $token->{'type'} eq 'spaces_inserted'
-                 or $token->{'type'} eq 'bracketed_arg'
-                 or $token->{'type'} eq 'bracketed_inserted'
-                 or $token->{'type'} eq 'delimiter')) {
-        # we create a {'contents' =>} only if there is more than one
-        # content gathered.
-        if (scalar(@$argument_content)) {
-          if (scalar(@$argument_content) > 1) {
-            my $e = {'contents' => $argument_content,
-                     'type' => 'def_aggregate',
-                     'parent' => $current };
-            push @result, $e;
-            # Replace in the main tree.
-            splice @new_contents,
-                   $i - scalar(@$argument_content),
-                   scalar(@$argument_content),
-                   $e;
-            for my $e2 (@$argument_content) {
-              $e2->{'parent'} = $e;
-            }
-            $i -= scalar(@$argument_content) - 1;
-          } elsif (scalar(@$argument_content) == 1) {
-            push @result, $argument_content->[0];
-          }
-          $argument_content = [];
-          if ($token->{'type'} eq 'spaces'
-              or $token->{'type'} eq 'spaces_inserted') {
-            $remaining_args_nr--;
-          }
-        }
-      }
-
-      if ($token->{'type'} and ($token->{'type'} eq 'bracketed_arg'
-                                or $token->{'type'} eq 'bracketed_inserted')) {
-        push @result, $token;
-        shift @contents;
-        $remaining_args_nr--;
-      } elsif ($token->{'type'}
-          and ($token->{'type'} eq 'spaces'
-                 or $token->{'type'} eq 'spaces_inserted')) {
-        if ($token->{'text'}) {
-          $token->{'extra'} = {'def_role' => 'spaces'};
-          shift @contents;
-        } else {
-          $i++;
-          last;
-        }
-      } elsif ($token->{'type'} and $token->{'type'} eq 'delimiter') {
-        $token->{'extra'} = {'def_role' => 'delimiter'};
-      } else {
-        my $text_or_cmd = shift @contents;
-        push @$argument_content, $text_or_cmd;
-      }
+  my $i;
+  my $contents_idx = 0;
+  for ($i = 0; $i < $arg_types_nr; $i++) {
+    my $element = _next_bracketed_or_word_agg($current, \$contents_idx);
+    if ($element) {
+      $result{$args[$i]} = $element;
+    } else {
       $i++;
-      last if ($remaining_args_nr < 0);
-    }
-    # if the end was reached without args to trigger gathering the started
-    # argument content, it is gathered here.
-    if (scalar(@$argument_content) > 1) {
-      my $e = {'contents' => $argument_content,
-               'type' => 'def_aggregate',
-               'parent' => $current,
-               };
-      for my $e2 (@$argument_content) {
-        $e2->{'parent'} = $e;
+      last;
+    }
+  }
+  if ($self->{'macros'}->{$command}) {
+    while ($contents_idx < scalar(@{$current->{'contents'}})
+           and $current->{'contents'}->[$contents_idx]->{'type'}
+           and $current->{'contents'}->[$contents_idx]->{'type'} eq 'spaces') {
+      $contents_idx++;
+    }
+    if ($contents_idx < scalar(@{$current->{'contents'}})) {
+      my $contents_nr = scalar(@{$current->{'contents'}}) - $contents_idx;
+      if ($contents_nr == 1) {
+        $result{$args[$i]} = $current->{'contents'}->[$contents_idx];
+      } else {
+        my @gathered_contents
+          = splice(@{$current->{'contents'}}, $contents_idx,
+                   $contents_idx + $contents_nr);
+        my $new = {'type' => 'def_aggregate', 'parent' => $current,
+                   'contents' => \@gathered_contents};
+        foreach my $content (@gathered_contents) {
+          $content->{'parent'} = $new;
+        }
+        splice (@{$current->{'contents'}}, $contents_idx, 0, ($new));
+        $result{$args[$i]} = $new;
       }
-      push @result, $e;
-      # Replace in the main tree.
-      splice @new_contents, $i - scalar(@$argument_content),
-             scalar(@$argument_content), $e;
-    } elsif (scalar(@$argument_content) == 1) {
-      push @result, $argument_content->[0];
     }
+    return \%result;
   }
 
-  # at this point, @contents corresponds to the @def* args
-  if (scalar(@contents) > 0) {
-    splice @new_contents, -scalar(@contents);
+  foreach my $type (keys(%result)) {
+    my $element = $result{$type};
+    $element->{'extra'} = {} if (!$element->{'extra'});
+    $element->{'extra'}->{'def_role'} = $type;
   }
 
-  if ($self->{'macros'}->{$command}) {
-    if (scalar(@contents) > 1) {
-      my $e = {'contents' => \@contents,
-               'type' => 'def_aggregate',
-               'parent' => $current,
-              };
-      push @new_contents, $e;
-      # FIXME remove leading spaces?  Currently it is removed
-      # after converting to texinfo
-      push @result, $e;
-    } else {
-      push @new_contents, $contents[0];
-      push @result, $contents[0];
-    }
-  } else {
+  my @args_results = map (_split_delimiters($self, $_, $current, $source_info),
+                          splice(@{$current->{'contents'}}, $contents_idx,
+                                 scalar(@{$current->{'contents'}}) - 
$contents_idx));
+  push @{$current->{'contents'}}, @args_results;
 
-    @contents = map (_split_delimiters($self, $_, $current, $source_info),
-                     @contents );
-    my @args_results = @contents;
-    @new_contents = (@new_contents, @contents);
-
-    # Create the part of the parsed def line array for any arguments.
-    while (@contents) {
-      my $spaces;
-      my $next_token = shift @contents;
-      if ($next_token->{'type'} and $next_token->{'type'} eq 'spaces') {
-        $spaces = $next_token;
-        $next_token = shift @contents;
-      }
-      if (defined($spaces)) {
-        $spaces->{'extra'} = {'def_role' => 'spaces'};
-      }
-      last if (!defined($next_token));
-      if ($next_token->{'type'} and $next_token->{'type'} eq 'delimiter') {
-        $next_token->{'extra'} = {'def_role' => 'delimiter'};
+  # Create the part of the parsed def line array for any arguments.
+  foreach my $content (@args_results) {
+    if ($content->{'type'} and $content->{'type'} eq 'spaces') {
+      $content->{'extra'} = {'def_role' => 'spaces'};
+    } elsif ($content->{'type'} and $content->{'type'} eq 'delimiter') {
+      $content->{'extra'} = {'def_role' => 'delimiter'};
+    } else {
+      $content->{'extra'} = {} if (!$content->{'extra'});
+      $content->{'extra'}->{'def_role'} = 'arg';
+    }
+  }
+
+  # If a command like @deftypefn, mark the type arguments
+  if ($arg_type and $arg_type eq 'argtype') {
+    my $next_is_type = 1;
+    foreach my $arg(@args_results) {
+      if ($arg->{'extra'}->{'def_role'} eq 'spaces') {
+      } elsif ($arg->{'extra'}->{'def_role'} eq 'delimiter') {
+        $next_is_type = 1;
+      } elsif ($arg->{'cmdname'} and $arg->{'cmdname'} ne 'code') {
+        $next_is_type = 1;
+      } elsif ($next_is_type) {
+        $arg->{'extra'}->{'def_role'} = 'typearg';
+        $next_is_type = 0;
       } else {
-        $next_token->{'extra'} = {} if (!$next_token->{'extra'});
-        $next_token->{'extra'}->{'def_role'} = 'arg';
-      }
-    }
-
-    # If a command like @deftypefn, mark the type arguments
-    if ($arg_type and $arg_type eq 'argtype') {
-      my $next_is_type = 1;
-      foreach my $arg(@args_results) {
-        if ($arg->{'extra'}->{'def_role'} eq 'spaces') {
-        } elsif ($arg->{'extra'}->{'def_role'} eq 'delimiter') {
-          $next_is_type = 1;
-        } elsif ($arg->{'cmdname'} and $arg->{'cmdname'} ne 'code') {
-          $next_is_type = 1;
-        } elsif ($next_is_type) {
-          $arg->{'extra'}->{'def_role'} = 'typearg';
-          $next_is_type = 0;
-        } else {
-          $next_is_type = 1;
-        }
+        $next_is_type = 1;
       }
     }
-    for (my $i = 0; $i < scalar(@result)
-                    and $i < scalar(@args); $i++) {
-      my $element = $result[$i];
-      my $type = $args[$i];
-      $element->{'extra'} = {} if (!$element->{'extra'});
-      $element->{'extra'}->{'def_role'} = $type;
-    }
-  }
-
-  my %result;
-  for (my $i = 0; $i < scalar(@result)
-                  and $i < scalar(@args); $i++) {
-    my $element = $result[$i];
-    my $type = $args[$i];
-    $result{$type} = $element;
   }
 
   return \%result;
@@ -3748,10 +3716,7 @@ sub _end_line_def_line($$$)
               }
             } else {
               $argument_text = 
Texinfo::Convert::Texinfo::convert_to_texinfo($arg);
-              # should only be needed for the last argument
-              $argument_text =~ s/^\s*//;
             }
-            #print STDERR "AAAA '$argument_text' 
".Texinfo::Common::debug_print_element($arg)."\n";
             push @$macro_args, {'contents' => [{'text' => $argument_text}]};
           }
         }
diff --git a/tp/Texinfo/XS/parsetexi/def.c b/tp/Texinfo/XS/parsetexi/def.c
index 2085dca435..ed6753766b 100644
--- a/tp/Texinfo/XS/parsetexi/def.c
+++ b/tp/Texinfo/XS/parsetexi/def.c
@@ -454,7 +454,9 @@ parse_def (enum command_id command, ELEMENT *current)
   result[i] = 0;
   if (command_data(command).flags & CF_MACRO)
     {
-      /* FIXME do not add leading space to def_arg */
+      while (contents_idx < current->contents.number
+             && current->contents.list[contents_idx]->type == ET_spaces)
+        contents_idx++;
       /* note that element at contents_idx is not collected at that point */
       if (contents_idx < current->contents.number)
         {
diff --git a/tp/Texinfo/XS/parsetexi/end_line.c 
b/tp/Texinfo/XS/parsetexi/end_line.c
index 8106a0b014..deed106d50 100644
--- a/tp/Texinfo/XS/parsetexi/end_line.c
+++ b/tp/Texinfo/XS/parsetexi/end_line.c
@@ -708,7 +708,7 @@ end_line_def_line (ELEMENT *current)
                   ELEMENT *arg = def_info[def_info_index]->element;
                   if (arg->type == ET_bracketed_arg)
                     {
-                      /* we also duplicate leading and trailing spaces */
+                      /* duplicate leading and trailing spaces info */
                       KEY_PAIR *kspaces_before
                         = lookup_info (arg, "spaces_before_argument");
                       KEY_PAIR *kspaces_after
@@ -745,14 +745,7 @@ end_line_def_line (ELEMENT *current)
                         argument_text = strdup("");
                     }
                   else
-                    {
-                      /* FIXME remove leading spaces but they should probably
-                         not be in the input */
-                      char *converted_string = convert_to_texinfo (arg);
-                      argument_text = strdup(converted_string
-                       + strspn (converted_string, 
whitespace_chars_except_newline));
-                      free (converted_string);
-                    }
+                    argument_text = convert_to_texinfo (arg);
                 }
               else
                 argument_text = strdup("");



reply via email to

[Prev in Thread] Current Thread [Next in Thread]