(La) Tex math parsing для C/С++

Я хотел бы преобразовать выражения parse (la) tex math и преобразовать их в (любой вид!) выражения языка сценариев, поэтому я могу оценить выражения. Какие библиотеки вы рекомендуете?

Ответ 1

Возможно использование boost::spirit для того, чтобы токенизировать выражение. Вам нужно будет определить огромную грамматику!

Ответ 2

Может быть, это поможет - взгляните на TeXmacs, особенно на том, как он взаимодействует с системами компьютерной алгебры.

Ответ 3

Используйте генератор парсера для создания соответствующего синтаксического анализатора. Попробуйте ANTLR для этого, так как он включает в себя IDE для грамматики, что очень полезно. Используя правила перезаписи дерева, вы можете преобразовать дерево разбора в абстрактное синтаксическое дерево.

Запустите, возможно, с помощью анализатора выражений из учебника ANTLR. Я думаю, что это достаточно близко.

Ответ 4

Вот набор возможных вариантов из аналогичного вопроса. https://tex.stackexchange.com/info/4223/what-parsers-for-latex-mathematics-exist-outside-of-the-tex-engines

Я думаю, что Perl сделал бы прекрасный выбор для чего-то подобного, действуя на текст, является одной из его сторонних сторон.

Вот некоторая информация о том, как сделать эксклюзивный тест триггера (найти контекст между \begin {} и \end {} без сохранения этих строк), http://www.effectiveperlprogramming.com/2010/11/make-exclusive-flip-flop-operators/

EDIT: Итак, эта проблема начала меня. Вот первая попытка создать что-то здесь, это мой "math.pl", который принимает .tex файл в качестве аргумента (т.е. $./math.pl test.tex).

#!/usr/bin/env perl

use strict;
use warnings;

use Text::Balanced qw/extract_multiple extract_bracketed/;

my $re_num = qr/[+\-\dE\.]/;

my $file = shift;

open( my $fh, '<', $file);

#parsing this out for more than just the equation environment might be easier using Text::Balanced too.
my @equations;
my $current_equation = '';
while(<$fh>) {
  my $test;
  next unless ($test = /\\begin\{equation\}/ .. /\\end\{equation\}/);

  if ($test !~ /(^1|E0)$/ ) {
    chomp;
    $current_equation .= $_;
  } elsif ($test =~ /E0$/) {
    #print $current_equation . "\n";
    push @equations, {eq => $current_equation};
    $current_equation = '';
  }
}

foreach my $eq (@equations) {
  print "Full Equation: " . $eq->{'eq'} . "\n";
  solve($eq);
  print "Result: " . $eq->{'value'} . "\n\n";
}

sub solve {
  my $eq = shift;

  print $eq->{'eq'} . "\n";

  parse($eq);
  compute($eq);

  print "intermediate result: " . $eq->{'value'} . "\n";
}

sub parse {
  my $eq = shift;

  my ($command,@fields) = extract_multiple(
    $eq->{'eq'}, [ sub { extract_bracketed(shift,'{}') } ]
  );

  $command =~ s/^\\//;
  print "command: " . $command . "\n";

  @fields = map { s/^\{\ *//; s/\ *\}$//; print "arg: $_\n"; {value => $_}; } @fields;


  ($eq->{'command'}, @{ $eq->{'args'} }) = ($command, @fields);
}

sub compute {
  my ($eq) = @_;

  #check arguements ...
  foreach my $arg (@{$eq->{'args'}}) {
    #if arguement is a number, continue
    if ($arg->{'value'} =~ /^$re_num$/) {
      next;

    #if the arguement is a simple mathematical operation, do it and continue
    } elsif ($arg->{'value'} =~ /^($re_num)\ *(?:\ |\*|\\times)?\ *($re_num)$/) {
      $arg->{'value'} = $1 * $2;
    } elsif ($arg->{'value'} =~ /^($re_num)\ *(?:\+)?\ *($re_num)$/) {
      $arg->{'value'} = $1 + $2;
    } elsif ($arg->{'value'} =~ /^($re_num)\ *(?:\-)?\ *($re_num)$/) {
      $arg->{'value'} = $1 - $2;
    } elsif ($arg->{'value'} =~ /^($re_num)\ *(?:\/)?\ *($re_num)$/) {
      $arg->{'value'} = $1 / $2;
    } else {
      #parse it and calc it as if it were its own equation.
      $arg->{'eq'} = $arg->{'value'};
      solve($arg);
    }
  }

  my @args = @{$eq->{'args'}};

  ## add command processing here
  # frac
  if ($eq->{'command'} eq 'frac') {
    $eq->{'value'} = $args[0]->{'value'} / $args[1]->{'value'};
    return;
  }

}

и вот пример test.tex:

\documentclass{article}

\begin{document}

Hello World!

\begin{equation}
\frac{\frac{1}{3}}{2}
\end{equation}

\end{document}