Я хотел бы преобразовать выражения parse (la) tex math и преобразовать их в (любой вид!) выражения языка сценариев, поэтому я могу оценить выражения. Какие библиотеки вы рекомендуете?
(La) Tex math parsing для C/С++
Ответ 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}