algebra-latex icon indicating copy to clipboard operation
algebra-latex copied to clipboard

Parsing of function expressions

Open EricRabil opened this issue 6 years ago • 13 comments
trafficstars

Hello, I am attempting to parse f\left(x\right)=x^2 into a function definition, f(x)=x^2, which is an acceptable format in Algebrite. Instead, f*x=x^2 is produced.

If this is my mistake, how can I declare an algebraic function and have it translate to the desired output above?

If this is not my mistake, and algebra-latex does not support this, are there plans to implement this into the library?

EricRabil avatar Oct 09 '19 00:10 EricRabil

Hi, there is currently no way to declare a function like you are trying.

There is no way to know the difference between a function declaration f(x), and a variable f followed by another variable ´x´ inside parenthesis, which is also a totally valid math string.

I don't see an obvious way to tell algebra-latex to parse it as a function rather than the product of two variables. Maybe you have an idea?

viktorstrate avatar Oct 09 '19 18:10 viktorstrate

Perhaps it could be implemented as an option or a custom method?

Some ideas that come to mind:

  • Reserving a set of characters that, when used in that declaration, are interpreted as a function declaration instead of distribution.
  • Boolean option that determines whether an expression following the format f(x) immediately followed by an = is interpreted as a declaration or a distribution
  • Custom method option that allows library dependents to determine the logic

Sent with GitHawk

EricRabil avatar Oct 09 '19 20:10 EricRabil

  1. Reserving a set of characters. This is already done, for the builtin math functions like sin, cos, sqrt etc. see /src/models/functions.js

  2. Looking at the syntax eg. f(x) immediatley followed by =. This is a great idea, but this doesn't really solve the problem completely, because often you want to use the function after it has been declared, and this would not be possible.

  3. Custom options for external libraries. This might work, but other libraries would have to implement it.

A solution might be to add a configuration object where custom function names could be set. And the parser would know to parse it as a function whenever it sees these names.

Like so:

new AlgebraLatex({
  functions: ['f', 'g', 'func']
}).parseLatex(latexInput)

viktorstrate avatar Oct 10 '19 17:10 viktorstrate

I think that your solution is ideal, especially because you can customize the reservations on a per-parse basis. I can try to implement this, although my experience with this library is minuscule.

EricRabil avatar Oct 14 '19 19:10 EricRabil

Great 🎉 I will encourage you to try to implement it.

The important files are:

The /src/index.js file, where the object is created

The keyword method in Parser.js line 144, where it is decided if it should be interpreted as a function.

viktorstrate avatar Oct 14 '19 19:10 viktorstrate

So at Parser.js:144 I would just need to mixin the added keywords?

EricRabil avatar Oct 14 '19 19:10 EricRabil

Exactly, the variable functions is an array of all predefined functions. See /src/models/functions.js

viktorstrate avatar Oct 14 '19 19:10 viktorstrate

The deprecated latex parameter in the AlgebraLatex constructor is preventing me from adding an options object. Shall I add a typeof check and preserve original functionality if the first parameter is a string?

constructor(latex) {
  if (typeof latex === 'undefined') {
    return
  } else if (typeof latex === 'object') {
    this.parseOptions(latex)
    return
  }

  this.parseLatex(latex)
}

EricRabil avatar Oct 14 '19 19:10 EricRabil

Okay. Just remove the old parameter. Then we just have to push a major version (v2.0) for next update

viktorstrate avatar Oct 14 '19 19:10 viktorstrate

My fork is a working concept of this, however it does not allow me to define a function with multiple arguments.

For example: \\f\\left(x,y\\right) yields

\f\left(x.y\right)
       ^
Error at line: 1 col: 8
Unknown symbol: .

This seems to be a result of a regex that accommodates the European decimal. Perhaps I can replace this with another option?

EricRabil avatar Oct 14 '19 21:10 EricRabil

Your implementation is great, and I will happily merge it, if you send a pull request.

The problem with multi-variable functions is a new issue of its own. You are welcome to fix this issue too, but it is a little more complicated, as both the lexer, the parser and the formatter would have to be modified.

If you want to try to implement it, here are what needs to be done. If not, I can do it later when I have the time.

Lexer

The lexer should first determine if the comma is a part of a european number, otherwise it should return a new separator token object maybe { type: 'separator' }

Eg. 2,3 is a number. 2, 3 is a separator. a,b is a separator

Note that multi-variable functions also can be written as f(x; y) or f(2,5; 3,0). So semicolons should also be interpreted as a { type: 'separator' }

Parser

Parser.function() should be rewritten to understand the comma. The output for a multi-variable function should be somthing like the following. The change is that content is an array instead of a single object.

// f(x, y)
{
  type: 'function',
  value: 'f',
  content: [{
    type: 'variable', value: 'x',
  }, {
    type: 'variable', value: 'y',
  }
}

Formatters

The formatters should be updated to understand the new parsed formats

viktorstrate avatar Oct 16 '19 11:10 viktorstrate

Sorry to bump a dead thread. Working on multivariate arguments, and not sure how to handle the separators in Latex. Popular editors like MathQuill don't support spaces between the arguments, at least not by default. Even the demo page of MathQuill doesn't let you put spaces in the arguments :(

Perhaps an option is in order that can disable European decimal detection?

EricRabil avatar May 27 '21 21:05 EricRabil

No issue, i've reopened it.

Perhaps an option is in order that can disable European decimal detection?

I agree that it would probably be the best solution to add an option to chose comma separator format. This would also make the output formatting more precise as the user can decide.

Also I don't see any general solution that would cover all edge-cases.

viktorstrate avatar May 28 '21 09:05 viktorstrate