Алгоритм генерации MathML для Javascript. Любые рекомендуемые ссылки

Я пытаюсь создать код, который может генерировать MathML для традиционного математического ввода. Я использую JavaScript для кодирования. Есть ли какие-либо ссылки или рекомендуемые материалы, которые я могу прочитать, чтобы понять требуемый алгоритм? Я читаю стандарты W3C для MathML, которые являются справочником по стандартам, но не по алгоритму.

Например, для примера ввода

sqrt 9 * 5 + 20

Я хочу сгенерировать выражение MathML, как показано ниже.

<math xmlns='w3.org/1998/Math/MathML'>; <mrow> <mrow> <mn>5</mn> <mo>&#8290;</mo> <mn>9</mn> <mo>&#8290;</mo> <mi>SQRT</mi> </mrow> <mo>+</mo> <mn>20</mn> </mrow> </math>

person JMD    schedule 08.02.2014    source источник
comment
Что вы подразумеваете под математическим уравнением? В каком формате ваш ввод? Как вы думаете, что должен делать алгоритм?   -  person Bergi    schedule 09.02.2014
comment
Вы не рассматривали матжакс?   -  person Bergi    schedule 09.02.2014
comment
Спасибо Берги. Я имел в виду математический анализатор, который может анализировать традиционную математику, такую ​​как SQRT 9 * 5 + 20, в выражение MathML, такое как ‹math xmlns='w3.org/1998/Math/MathML'› ‹mrow› ‹mrow› ‹mn›5‹/mn› ‹mo›⁢‹/mo› ‹mn›9‹/mn› ‹ мес›⁢‹/мес› ‹ми›SQRT‹/ми› ‹/мес› ‹мес›+‹/мес› ‹мин›20‹/мес› ‹/мес› ‹/математика›   -  person JMD    schedule 09.02.2014
comment
Пожалуйста, отредактируйте свой вопрос, включив в него такой существенный материал :-)   -  person Bergi    schedule 09.02.2014
comment
Было бы полезно предоставить справочную информацию о том, что вы имеете в виду под традиционным математическим вводом. Вы также можете посмотреть asciiMathML, www1.chapman.edu/~jipsen/mathml /asciimath.html.   -  person Peter Krautzberger    schedule 09.02.2014
comment
@PeterKrautzberger: Вы даже можете ответить по этой ссылке :-)   -  person Bergi    schedule 10.02.2014
comment
@bergi Сначала я подожду ответа от ОП.   -  person Peter Krautzberger    schedule 10.02.2014
comment
Это помогает мне. Я хотел бы отметить это как ответ, Питер.   -  person JMD    schedule 12.02.2014


Ответы (1)


Я нашел хороший учебник по MathML здесь: basic-алгебра.html и начал разрабатывать очень простой алгебраический синтаксический анализатор (например, 4*sqrt(x+6)=(5-z)*y/7) с грубым стеком для обработки круглых скобок и примером функции sqrt. Это то направление, которое вам нужно?

jsfiddle здесь: http://jsfiddle.net/alhambra1/bSJyE/

Код JavaScript:

<script>
document.write('<p><input id="input" size=50>')
document.write('<button onclick="convertToMathML()">Convert</button></p>')
document.write('<div id="output"></div>')

function lex(str,ptr){
    var ascii = str.charCodeAt(ptr),
        lexeme = {string: "", type: ""},
        operators = {"+": "+"
                    , "-": "-"
                    , "*": "&times;"
                    , "/": "&divide;"
                    , "=": "="},
        functions = {sqrt: "msqrt"}

    //identify type
    if (ascii == 41)
        lexeme.type = "closeBracket"
    else if (ascii == 40){
        lexeme.type = "func"
        lexeme.func = "mfenced"
    }
    else if (ascii > 45 && ascii < 58 && ascii != 47)
        lexeme.type = "mn"
    else if ((ascii > 64 && ascii < 91) || (ascii > 96 && ascii < 123)){
        for (i in functions){
            if (str.substr(ptr,i.length).toLowerCase() == i){
                lexeme.type = "func"
                lexeme.func = functions[i]
                ptr += i.length - 1
            } else
                lexeme.type = "mi"
        }
    } else if (!operators[str.charAt(ptr)])
        return {string: str.charAt(ptr), type: "error", pointer: ptr}
    else
        lexeme.type = "mo"

    switch (lexeme.type){
        case "mo":
            lexeme.string = operators[str.charAt(ptr++)]
            break
        default:
            lexeme.string = str.charAt(ptr++)
            break
    }

    ascii = str.charCodeAt(ptr)

    //identify numbers and functions 
    if (lexeme.type == "mn"){
        while (ptr < str.length && ascii > 45 && ascii < 58 && ascii != 47){
            lexeme.string += str.charAt(ptr)
            ascii = str.charCodeAt(++ptr)
        }
    } else if (lexeme.type == "func" && lexeme.func != "mfenced"){
        while (ptr < str.length && str.substr(ptr).match(/^\s/)){
            ascii = str.charCodeAt(++ptr)
        }
        if (str.charAt(ptr) != "(")
            return {string: str.charAt(ptr), type: "error", pointer: ptr}
        else
            ptr++
    }

    lexeme["pointer"] = ptr

    return lexeme
}

function markup(lexeme){
    return "<" + lexeme.type + ">\n"
           + lexeme.string + "\n"
           + "</" + lexeme.type + ">\n"
}

function convertToMathML(){
    var str = document.getElementById('input').value,
        expression = "",
        ptr = 0,
        stack = []

    while (ptr < str.length){
        var currLexeme = lex(str,ptr)

        if (currLexeme.type == "closeBracket"){
            if (stack.length == 0)
                expression = "Extra bracket at: " + (currLexeme.pointer - 1)
            else
                expression += "</" + stack.pop().func + ">\n"
                            + "</mrow>"          
            ptr = currLexeme.pointer
        } else if (currLexeme.type == "error"){
            expression = "Cannot parse \"" + currLexeme.string
                       + "\" at " + currLexeme.pointer
            break
        } else if (currLexeme.type == "func"){
            expression += "<" + currLexeme.func + ">\n"
                        + "<mrow>\n"
            stack.push(currLexeme)
            ptr = currLexeme.pointer
        } else {
            expression += markup (currLexeme)
            ptr = currLexeme.pointer
        }
    }

    if (ptr >= str.length && stack.length > 0)
        expression = "Missing " +  stack.length + " closing bracket/s."

    expression = "<math xmlns='http://www.w3.org/1998/Math/MathML'>"
               + expression + "</math>"

    document.getElementById('output').innerHTML = expression
}
</script>
person גלעד ברקן    schedule 09.02.2014
comment
У меня также есть еще один вопрос, знаете ли вы какую-либо веб-страницу, которая может вычислять математические выражения? Я разработал один, и до сих пор он работал хорошо, но я также хотел бы просмотреть любые хорошие алгоритмы, чтобы увидеть, есть ли возможности для улучшения того, что я сделал. - person JMD; 09.02.2014
comment
@groovy: № eval не предназначен для оценки математических выражений и не должен использоваться здесь. - person Bergi; 09.02.2014
comment
Спасибо. Я попробовал eval и получил ошибки JavaScript. Но информация, которую я получил от вас, оказалась полезной. - person JMD; 09.02.2014
comment
@user1998463 user1998463 ой, я ошибся... Shunting-yard используется для преобразования инфикса в RPN (en. wikipedia.org/wiki/Reverse_Polish_notation), что может быть легче оценить. Эта страница может помочь вам поэкспериментировать с eval, если вам интересно, w3schools.com/jsref /tryit.asp?filename=tryjsref_eval - person גלעד ברקן; 09.02.2014
comment
@ Берги, я не согласен. Вот более официальный пример: w3schools.com/jsref/jsref_eval.asp - person גלעד ברקן; 09.02.2014
comment
@groovy: школы никоим образом не являются официальными, и их примеры, как известно, не самые лучшие. Посетите w3fools.com. И если вы уже преобразовали уравнение в AST, вам ни в коем случае не следует использовать eval для его оценки, если вы можете сделать это правильно. - person Bergi; 09.02.2014
comment
@Bergi Берги, о, я не знал, что у w3schools плохая репутация; Я думаю, как любитель, вы учитесь везде, где можете. Имеет смысл, что выполнение собственного синтаксического анализа и оценки даст вам наибольший контроль. - person גלעד ברקן; 09.02.2014
comment
Эй, вы также знаете точный обратный процесс, то есть преобразование MathML в выражение. См. мою эту тему: stackoverflow.com/questions/26357109/ - person Saurabh Palatkar; 14.10.2014
comment
@SaurabhLprocks Я не знаком с приложением с открытым исходным кодом для обратного процесса. Кажется, что это может иметь что-то общее с синтаксическим анализом XML, но я не слишком большой эксперт в этом. - person גלעד ברקן; 15.10.2014