2011-01-27 42 views
11

Tôi muốn chuyển đổi các biểu thức toán học parse (la), và chuyển đổi chúng thành biểu thức ngôn ngữ kịch bản (bất kỳ loại nào!), Vì vậy tôi có thể đánh giá các biểu thức. Bạn đề xuất thư viện nào?(La) Phân tích cú pháp toán học cho C/C++

+3

Đó là một ý tưởng khá kỳ lạ. Làm thế nào để bạn phân biệt $ a^n $ trong đó $ n $ là một chỉ số từ $ a^n $ là pow (a, n)? \ Cdot trong $ A \ cdot B $ là gì? Latex toán học là hoàn toàn trực quan, nó không có bất kỳ ngữ nghĩa. –

+2

@SKlogic: có thể điều này chỉ được sử dụng cho các cụm từ như '$ \ sqrt [4] {\ frac {a + b} {2}} $' – Benoit

+0

Trong trường hợp này, không rõ ràng tại sao sử dụng ký pháp latex - một ngôn ngữ thứ ba có thể được sử dụng, với dịch sang cả latex và bất cứ điều gì thuận tiện để đánh giá. –

Trả lời

1

Có thể sử dụng boost::spirit để mã hóa biểu thức. Bạn sẽ cần phải xác định một ngữ pháp rất lớn!

+4

... trong đó 'while (true) {huge * = huge; } 'được xác định và hành vi quan sát được. –

1

Có thể sẽ giúp ích - hãy xem TeXmacs, đặc biệt là theo cách tương tác với hệ thống đại số máy tính.

0

Sử dụng trình tạo trình phân tích cú pháp để tạo trình phân tích cú pháp thích hợp. Hãy thử ANTLR cho điều này, vì nó bao gồm một IDE cho ngữ pháp, rất hữu ích. Sử dụng quy tắc viết lại cây, bạn có thể chuyển đổi cây phân tích thành cây cú pháp trừu tượng.

Có thể bắt đầu với trình đánh giá biểu thức từ hướng dẫn ANTLR. Tôi nghĩ điều này là đủ gần.

0

Dưới đây là một tập hợp các tùy chọn có thể có từ một câu hỏi tương tự. https://tex.stackexchange.com/questions/4223/what-parsers-for-latex-mathematics-exist-outside-of-the-tex-engines

Tôi nghĩ rằng Perl sẽ thực hiện một lựa chọn tốt cho một cái gì đó như thế này, hành động trên văn bản là một trong những pháo đài của nó.

Dưới đây là một số thông tin về làm thế nào để thực hiện một thử nghiệm flip-flop độc quyền (để tìm bối cảnh giữa \ begin {} và \ end {} mà không giữ những dòng), http://www.effectiveperlprogramming.com/2010/11/make-exclusive-flip-flop-operators/

EDIT: Vì vậy, vấn đề này có bắt đầu tôi đi. Đây là một nỗ lực đầu tiên để tạo ra một cái gì đó ở đây là "math.pl" của tôi trong đó có một tập tin .tex như một sự tranh luận (tức là $./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; 
    } 

} 

và đây là một test.tex mẫu:

\documentclass{article} 

\begin{document} 

Hello World! 

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

\end{document} 
Các vấn đề liên quan