2015-09-16 3 views
2

Я ищу способ проверить, если строка является математическим выражением, как то естьуправления, если строка представляет собой математическое выражение

х + у -sin (1) * 99k

Я не хочу оценивать выражение, но понимаю, что строка написана правильно.

Есть ли какая-то библиотека Java для этого?

ОБНОВЛЕНИЕ: Извините, это не уравнение, а только выражение (ничего '='). меня думать о возможном решении:

  1. Укажите переменные, используемые
  2. заменить все переменные с «1»
  3. оценить новую строку с JEval
  4. если программа сгенерирует исключение, то неправильное выражение

Что вы думаете об этом?

Благодаря

+0

Должно ли это выражение быть правильным? Если нет, вы можете просто проверить, содержит ли он «=». – Oceans

+0

не уверен в библиотеке, но вы можете реализовать BNF для нее. но я уверен, так как вы действительно не хотите его оценивать, есть более простой способ. – nafas

+0

Дубликат этого http://stackoverflow.com/questions/2226863/whats-a-good-library-for-parsing-mathematics- выражения-в-java? – Michael

ответ

4

Попробуйте ANTLR. Вы можете написать грамматику, как:

grammar Expr;  

expr: FuncitonName '(' expr ')' 
    | '-' expr 
    | '(' expr ')' 
    | expr '*' expr 
    | expr '+' expr 
    | expr '-' expr 
    | expr '/' expr 
    | Const 
    | Variable 
    ; 

FuncitonName : [a-z] + ; 
Variable : [a-zA-Z] + ; 
Const : [0-9] +; 

WS : [ \t\r\n\u000C]+ -> skip; 

Вы должны определить грамматику более правильно в зависимости от того, какое выражение разрешены и какие нет. Сохраните его в файле Expr.g4 и выполните antlr4 Expr.g4, чтобы получить файлы ExprLexer.java и ExprParser.java. Тогда вы могли бы использовать их, чтобы проверить, если предложение является арифметическое выражение:

import org.antlr.v4.runtime.ANTLRInputStream; 
import org.antlr.v4.runtime.BailErrorStrategy; 
import org.antlr.v4.runtime.CommonTokenStream; 
import org.antlr.v4.runtime.misc.ParseCancellationException; 

public static boolean isExpr(String exp) { 

    ExprLexer lexer = new ExprLexer(new ANTLRInputStream(exp)); 
    CommonTokenStream tokens = new CommonTokenStream(lexer); 
    ExprParser parser = new ExprParser(tokens); 

    parser.removeErrorListeners(); 
    parser.setErrorHandler(new BailErrorStrategy()); 

    try { 
     parser.expr(); 
     return true; 
    } catch (ParseCancellationException e) { 
     return false; 
    } 

} 

и, наконец, тест:

System.out.println(isExpr("x + y -sin(1) * 99 * k")); //true 
System.out.println(isExpr("x + y +")); //false 

Вы можете обратиться к this вопросу.

+0

ANTLR путь хорош (я использую этот инструмент), но требую «немного» программирования и знаний (возможно, не включая «грех» в грамматике, а общий термин «функция»). мое доказательство концепции с оценкой ниже –

1

Мое специальное (и частично) решение. Все решения имеют большой вес, но Nashorn встроен. (Для ясности: я использую ANTLR тоже)

У меня проблема с sin() функции в исходном примере, броски javax.script.ScriptException: ReferenceError: "sin" is not defined in <eval>

ScriptEngineManager scm = new ScriptEngineManager(); 
    ScriptEngine eng = scm.getEngineByName("nashorn"); 

    Integer k = 1; 
    Integer x = 2; 
    Integer y = 3; 

    eng.put("k", k); 
    eng.put("x", k); 
    eng.put("y", k); 

    Object ret = null; 

    try { 
     ret = eng.eval("x + y * 99 * k"); 
    } catch (ScriptException e) { 
     e.printStackTrace(); 
    } 

Лично я использую Groovy. Сырой Groovy Eval имеет такое же проблему groovy.lang.MissingMethodException: No signature of method: sin() is applicable ...

, если я понял, что это лучше, я ловушка неизвестное свойство и неизвестный метод .... Я не знаю, как ловушка неизвестных элементов (но синтаксический правильно) в Насхорн или JEval

Смежные вопросы