Java 用值替换表达式中的各种变量?
在StringJava 用值替换表达式中的各种变量?,java,Java,在Strings中,有变量和数组。例如,s可以是a-(b+a[b[2]])*d+3,这些变量的值存储在单独的文件中。这是我的代码段,我试图用另一个文件中相应的值替换当前字符串s中的任何变量 我只想替换标量变量,而不是数组,我有一个名为scalars的ArrayList,它存储了所有标量变量。因此,对于给定的示例,使用a=1,b=2,d=3,我希望将s变成1-(2+a[b[2]])*3+3标量也不包含重复变量,因此我的代码只适用于单个非重复变量,如a、b、c,而不适用于变量,如varx。如何改进代
s
中,有变量和数组。例如,s
可以是a-(b+a[b[2]])*d+3
,这些变量的值存储在单独的文件中。这是我的代码段,我试图用另一个文件中相应的值替换当前字符串s
中的任何变量
我只想替换标量变量,而不是数组,我有一个名为scalars
的ArrayList,它存储了所有标量变量。因此,对于给定的示例,使用a=1
,b=2
,d=3
,我希望将s
变成1-(2+a[b[2]])*3+3
<代码>标量也不包含重复变量,因此我的代码只适用于单个非重复变量,如a、b、c
,而不适用于变量,如varx
。如何改进代码以适应各种情况,或者有更好的方法吗
String s = expr;
if(scalars.size()>0){
int j = 0; //make so duplicates can be used , so var can be used, so it doesn't detect arrays
for(int k = 0; k<s.length(); k++){
if(Character.isLetter(s.charAt(k))){
s= s.substring(0,k) + this.scalars.get(j).value + s.substring(k+1,s.length());
j++;
}
}
}
String s=expr;
if(scalars.size()>0){
int j=0;//make以便可以使用重复项,因此可以使用var,因此它不会检测数组
对于(int k=0;k0){
int j=0;//make以便可以使用重复项,因此可以使用var,因此它不会检测数组
对于(int k=0;k0){
int i;
布尔值foundPlusMinus=false;
对于(i=s.length()-1;i>0;i--){
如果(s.charAt(i)='+'| | s.charAt(i)='-'){
系统输出打印LN(i);
foundPlusMinus=true;
break;//保留子字符串的i值
}
foundPlusMinus=假;
}
if(foundPlusMinus==false){//for循环已通过,但未找到+或-
对于(i=s.length()-1;i>0;i--){
如果(s.charAt(i)='*'| | s.charAt(i)=='/')){
系统输出打印LN(i);
break;//保留子字符串的i值
}
}
}
String sub1=s.substring(0,i);
系统输出打印项次(sub1);
String sub2=s.substring(i+1,s.length());
系统输出打印LN(sub2);
如果(s.charAt(i)='+'){
tempAns=evalNoPB(sub1)+evalNoPB(sub2);
}如果(s.charAt(i)='-'){
tempAns=evalNoPB(sub1)-evalNoPB(sub2);
}如果(s.charAt(i)='*'){
tempAns=evalNoPB(sub1)*evalNoPB(sub2);
}如果(s.charAt(i)='/'){
浮点除数检查=evalNoPB(sub2);
如果(除数检查!=0){
tempAns=evalNoPB(sub1)/evalNoPB(sub2);
}否则{//不能被0除
抛出新的IllegalArgumentException(“不能除以0”);
}
}
}
返回坦潘;
}
您需要的是一个编译器,一个相当复杂的程序,它用某种编程语言解析输入并将其转换为另一种编程语言
在这种情况下,输入语言将是带有数字、标量变量、数组变量、和、乘法和括号的表达式。输出语言应该是带有数字、数组变量、和、乘法和括号的表达式(注意它不包含标量变量) 有很多关于编译器的文献。这是一门跨越计算机科学大学学位课程的学科。
如果你定义了一种非常有限的语言,你可以不使用简单的替换,就像在OP中一样。但是一旦你开始处理更一般的语言,比如长度大于1的变量,你就开始需要整个体系结构来构建编译器 编译器有几个部分:
例如,考虑输入“3 +A”。 预期的令牌为:数字加标识符 我将用正则表达式定义标记:
- 加:[+]
- 减:-
- 乘法:[*]
- 划分:/
- 编号:[0-9]+
- 标识符:[a-zA-Z]+
- 开括号:[(]
- 右括号:[)]
- 开括号:\[
- 关闭\u括号:\]
- EOL:行尾没有正则表达式。输入用尽时,词法分析器将返回此标记
首先是一个令牌类,它包含一个令牌及其类型和从中生成令牌的输入的子字符串
public class Token
{
public static enum TokenType
{
PLUS,
MINUS,
MULTIPLY,
DIVIDE,
NUMBER,
IDENTIFIER,
OPEN_PARENTHESIS,
CLOSE_PARENTHESIS,
OPEN_BRACKET,
CLOSE_BRACKET,
EOL // End of line
}
public Token( TokenType type, String value)
{
this.type = type;
this.value = value;
}
private TokenType type;
public String value;
public TokenType getType()
{
return type;
}
@Override
public String toString()
{
return value;
}
}
接下来是词法分析器本身
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import expressionparser.Token.TokenType;
class Tokenizer
{
private final String input;
private Matcher matcher;
private Token lastToken;
public Tokenizer( String input )
{
this.input = input;
Pattern pattern =
Pattern.compile( "[+]|-|[*]|/|[0-9]+|[a-zA-Z]+|[(]|[)]|\\[|\\]|[ ]");
matcher = pattern.matcher( input );
lastToken = null;
}
public Token readAndComsumeToken( TokenType type ) throws ExpressionException
{
Token result = readToken();
if ( result.getType()!=type )
throw new ExpressionException("Erroneous exception" );
lastToken = null;
return result;
}
public Token readToken() throws ExpressionException
{
if (lastToken!=null)
return lastToken;
String value;
// Read till a non blank is received
do
{
if ( matcher==null )
{
lastToken = new Token(TokenType.EOL, "");
return lastToken;
}
if ( !matcher.find() )
throw new ExpressionException("Erroneous exception" );
value = matcher.group();
if ( matcher.end() >= input.length() )
{
// End of String
matcher = null;
}
if ( value.length()==0 )
throw new ExpressionException("Erroneous exception" );
} while ( value.equals( " " ) ||
value.equals("\t") || value.equals("\n") ||
value.equals("\f") || value.equals("\r") );
// Identify read token
TokenType type;
if ( value.equals("+") )
type = TokenType.PLUS;
else if ( value.equals("-") )
type = TokenType.MINUS;
else if ( value.equals("*") )
type = TokenType.MULTIPLY;
else if ( value.equals("/") )
type = TokenType.DIVIDE;
else if ( value.equals("(") )
type = TokenType.OPEN_PARENTHESIS;
else if ( value.equals(")") )
type = TokenType.CLOSE_PARENTHESIS;
else if ( value.equals("[") )
type = TokenType.OPEN_BRACKET;
else if ( value.equals("]") )
type = TokenType.CLOSE_BRACKET;
else
{
char firstChar = value.charAt(0);
if ( firstChar>='0' && firstChar<='9' )
type = TokenType.NUMBER;
else
type = TokenType.IDENTIFIER;
}
lastToken = new Token( type, value );
return lastToken;
}
public void consumeToken() throws IllegalStateException
{
if ( lastToken==null )
throw new IllegalStateException();
lastToken = null;
}
}
有几种方法可以实现这种语法,甚至有工具可以自动实现。我将为语法的每一个非终端使用Java方法来实现它。它在语义转换器中呈现,因为它与解析器交织在一起 语义翻译。
ExpressionParser
是语法分析器和语义转换器的组合。它使用Tokenizer
进行词法分析
import expressionparser.Token.TokenType;
import java.util.List;
public class ExpressionParser
{
private Tokenizer lex;
private List<Scalar> scalars;
public String compile( String expression, List<Scalar> scalars ) throws ExpressionException
{
lex = new Tokenizer(expression);
this.scalars = scalars;
return evalWholeExpression();
}
private String evalWholeExpression( ) throws ExpressionException
{
String result = evalExpression();
lex.readAndComsumeToken(Token.TokenType.EOL);
return result;
}
private String evalExpression() throws ExpressionException
{
String left = evalSummand();
return evalTailSum( left );
}
private String evalSummand( ) throws ExpressionException
{
String left = evalFactor();
return evalTailMultiplication( left );
}
private String evalFactor() throws ExpressionException
{
Token token = lex.readToken();
if ( token.getType() == TokenType.OPEN_PARENTHESIS )
{
lex.consumeToken();
String result = evalExpression();
lex.readAndComsumeToken(TokenType.CLOSE_PARENTHESIS);
return "(" + result + ")";
}
else if ( token.getType() == TokenType.NUMBER )
{
lex.consumeToken();
return token.toString();
}
else if ( token.getType()==TokenType.IDENTIFIER )
{
lex.consumeToken();
String tailArray = evalTailArray();
if ( "".equals(tailArray) )
{
String scalarValue = evaluateScalar( token.toString() );
return scalarValue;
}
else
{
verifyIsNotScalar( token.toString() );
return token + tailArray;
}
}
else
throw new ExpressionException( "Incorrect expression" );
}
private String evalTailSum( String left ) throws ExpressionException
{
Token token = lex.readToken();
if ( token.getType()==TokenType.PLUS )
{
lex.consumeToken();
String right = evalSummand();
return evalTailSum( left + "+" + right );
}
else if ( token.getType()==TokenType.MINUS )
{
lex.consumeToken();
String right = evalSummand();
return evalTailSum( left + "-" + right );
}
else
return left;
}
private String evalTailMultiplication( String left ) throws ExpressionException
{
Token token = lex.readToken();
if ( token.getType()==TokenType.MULTIPLY )
{
lex.consumeToken();
String right = evalFactor();
return evalTailSum( left + "*" + right );
}
else if ( token.getType()==TokenType.DIVIDE )
{
lex.consumeToken();
String right = evalFactor();
return evalTailSum( left + "/" + right );
}
else
return left;
}
private String evalTailArray() throws ExpressionException
{
Token token = lex.readToken();
if ( token.getType() == TokenType.OPEN_BRACKET )
{
lex.consumeToken();
String result = evalExpression();
lex.readAndComsumeToken(TokenType.CLOSE_BRACKET);
return "[" + result + "]" + evalTailArray();
}
else
return "";
}
private String evaluateScalar( String text ) throws ExpressionException
{
assert text!=null;
for ( Scalar s : scalars )
{
if ( text.equals( s.identifier ) )
return "" + s.value;
}
throw new ExpressionException( "Incorrect expression" );
}
private void verifyIsNotScalar( String text ) throws ExpressionException
{
assert text!=null;
for ( Scalar s : scalars )
{
if ( text.equals( s.identifier ) )
throw new ExpressionException( "Incorrect expression" );
}
}
}
由其自身和本规则使用:
<tailSum> ::= PLUS <summand> <tailSum> |
MINUS <summand> <tailSum> |
""
<expression> ::= <summand> <tailSum>
在标识符分支中,根据上下文无关语法中的规则,使用标识符并调用evalTailArray
。evalTailArray
如果没有数组订阅,则返回空字符串,因此标识符必须是标量变量。在这种情况下,它调用evaluateScalar
<tailSum> ::= PLUS <summand> <tailSum> |
MINUS <summand> <tailSum> |
""
<expression> ::= <summand> <tailSum>
public class Scalar
{
public Scalar( String identifier, int value )
{
this.identifier = identifier;
this.value = value;
}
public final String identifier;
public final int value;
}
import java.util.ArrayList;
import java.util.List;
public class Main
{
public static void main(String[] args)
{
try
{
final List<Scalar> scalars = new ArrayList<>();
scalars.add( new Scalar( "a", 1 ) );
scalars.add( new Scalar( "b", 2 ) );
scalars.add( new Scalar( "d", 3 ) );
scalars.add( new Scalar( "varx", 5 ) );
ExpressionParser parser = new ExpressionParser();
System.out.println( parser.compile("a - (b+A[B[2]])*d + 3", scalars));
System.out.println( parser.compile("5*(2+varx)+a", scalars));
System.out.println( parser.compile("B[a*384+(5+(5*(varx+3)))]+varx", scalars));
System.out.println( parser.compile("34+", scalars ) );
}
catch (ExpressionException ex)
{
System.out.println( ex.getMessage() );
}
}
}
1-(2+A[B[2]])*3+3
5*(2+5)+1
B[1*384+(5+(5*(5+3)))]+5
Incorrect expression