Changeset 14826 for trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
- Timestamp:
- 04/04/17 17:52:44 (7 years ago)
- Location:
- trunk/sources
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources
- Property svn:mergeinfo changed
-
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
r14350 r14826 33 33 /// Parses mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3) 34 34 /// Identifier format (functions or variables): '_' | letter { '_' | letter | digit } 35 /// Variables names can be set under quotes "" or '' because variable names might contain spaces. 35 /// Variables names and variable values can be set under quotes "" or '' because variable names might contain spaces. 36 /// Variable = ident | " ident " | ' ident ' 36 37 /// It is also possible to use functions e.g. log("x1") or real-valued constants e.g. 3.1415 . 37 38 /// Variable names are case sensitive. Function names are not case sensitive. 39 /// 40 /// 41 /// S = Expr EOF 42 /// Expr = ['-' | '+'] Term { '+' Term | '-' Term } 43 /// Term = Fact { '*' Fact | '/' Fact } 44 /// Fact = '(' Expr ')' 45 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 46 /// | funcId '(' ArgList ')' 47 /// | VarExpr | number 48 /// ArgList = Expr { ',' Expr } 49 /// VarExpr = varId OptFactorPart 50 /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ] 51 /// varId = ident | ' ident ' | " ident " 52 /// varVal = ident | ' ident ' | " ident " 53 /// ident = '_' | letter { '_' | letter | digit } 38 54 /// </summary> 39 55 public sealed class InfixExpressionParser { 40 private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, Comma, End, NA };56 private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, LeftBracket, RightBracket, Comma, Eq, End, NA }; 41 57 private class Token { 42 58 internal double doubleVal; … … 65 81 private Constant constant = new Constant(); 66 82 private Variable variable = new Variable(); 83 private BinaryFactorVariable binaryFactorVar = new BinaryFactorVariable(); 84 private FactorVariable factorVar = new FactorVariable(); 67 85 68 86 private ProgramRootSymbol programRootSymbol = new ProgramRootSymbol(); … … 150 168 && str[pos] != '/' 151 169 && str[pos] != ')' 170 && str[pos] != ']' 152 171 && str[pos] != ',') { 153 172 sb.Append(str[pos]); … … 214 233 pos++; 215 234 yield return new Token { TokenType = TokenType.RightPar, strVal = ")" }; 235 } else if (str[pos] == '[') { 236 pos++; 237 yield return new Token { TokenType = TokenType.LeftBracket, strVal = "[" }; 238 } else if (str[pos] == ']') { 239 pos++; 240 yield return new Token { TokenType = TokenType.RightBracket, strVal = "]" }; 241 } else if (str[pos] == '=') { 242 pos++; 243 yield return new Token { TokenType = TokenType.Eq, strVal = "=" }; 216 244 } else if (str[pos] == ',') { 217 245 pos++; … … 222 250 } 223 251 } 224 225 // S = Expr EOF 226 // Expr = ['-' | '+'] Term { '+' Term | '-' Term } 227 // Term = Fact { '*' Fact | '/' Fact } 228 // Fact = '(' Expr ')' | funcId '(' ArgList ')' | varId | number 229 // ArgList = Expr { ',' Expr } 252 /// S = Expr EOF 230 253 private ISymbolicExpressionTreeNode ParseS(Queue<Token> tokens) { 231 254 var expr = ParseExpr(tokens); … … 237 260 return expr; 238 261 } 262 263 /// Expr = ['-' | '+'] Term { '+' Term | '-' Term } 239 264 private ISymbolicExpressionTreeNode ParseExpr(Queue<Token> tokens) { 240 265 var next = tokens.Peek(); … … 300 325 } 301 326 302 // Term= Fact { '*' Fact | '/' Fact }327 /// Term = Fact { '*' Fact | '/' Fact } 303 328 private ISymbolicExpressionTreeNode ParseTerm(Queue<Token> tokens) { 304 329 var factors = new List<ISymbolicExpressionTreeNode>(); … … 335 360 } 336 361 337 // Fact = '(' Expr ')' | 'LAG' '(' varId ',' ['+' | '-'] number ')' | funcId '(' ArgList ')' | varId | number 362 /// Fact = '(' Expr ')' 363 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 364 /// | funcId '(' ArgList ')' 365 /// | VarExpr | number 366 /// ArgList = Expr { ',' Expr } 367 /// VarExpr = varId OptFactorPart 368 /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ] 369 /// varId = ident | ' ident ' | " ident " 370 /// varVal = ident | ' ident ' | " ident " 371 /// ident = '_' | letter { '_' | letter | digit } 338 372 private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) { 339 373 var next = tokens.Peek(); … … 348 382 var idTok = tokens.Dequeue(); 349 383 if (tokens.Peek().TokenType == TokenType.LeftPar) { 350 // function identifier 384 // function identifier or LAG 351 385 var funcId = idTok.strVal.ToUpperInvariant(); 352 386 … … 394 428 } else { 395 429 // variable 396 var varNode = (VariableTreeNode)variable.CreateTreeNode(); 397 varNode.Weight = 1.0; 398 varNode.VariableName = idTok.strVal; 399 return varNode; 430 if (tokens.Peek().TokenType == TokenType.Eq) { 431 // binary factor 432 tokens.Dequeue(); // skip Eq 433 var valTok = tokens.Dequeue(); 434 if (valTok.TokenType != TokenType.Identifier) throw new ArgumentException("expected identifier"); 435 var binFactorNode = (BinaryFactorVariableTreeNode)binaryFactorVar.CreateTreeNode(); 436 binFactorNode.Weight = 1.0; 437 binFactorNode.VariableName = idTok.strVal; 438 binFactorNode.VariableValue = valTok.strVal; 439 return binFactorNode; 440 } else if (tokens.Peek().TokenType == TokenType.LeftBracket) { 441 // factor variable 442 var factorVariableNode = (FactorVariableTreeNode)factorVar.CreateTreeNode(); 443 factorVariableNode.VariableName = idTok.strVal; 444 445 tokens.Dequeue(); // skip [ 446 var weights = new List<double>(); 447 // at least one weight is necessary 448 var sign = 1.0; 449 if (tokens.Peek().TokenType == TokenType.Operator) { 450 var opToken = tokens.Dequeue(); 451 if (opToken.strVal == "+") sign = 1.0; 452 else if (opToken.strVal == "-") sign = -1.0; 453 else throw new ArgumentException(); 454 } 455 if (tokens.Peek().TokenType != TokenType.Number) throw new ArgumentException("number expected"); 456 var weightTok = tokens.Dequeue(); 457 weights.Add(sign * weightTok.doubleVal); 458 while (tokens.Peek().TokenType == TokenType.Comma) { 459 // skip comma 460 tokens.Dequeue(); 461 if (tokens.Peek().TokenType == TokenType.Operator) { 462 var opToken = tokens.Dequeue(); 463 if (opToken.strVal == "+") sign = 1.0; 464 else if (opToken.strVal == "-") sign = -1.0; 465 else throw new ArgumentException(); 466 } 467 weightTok = tokens.Dequeue(); 468 if (weightTok.TokenType != TokenType.Number) throw new ArgumentException("number expected"); 469 weights.Add(sign * weightTok.doubleVal); 470 } 471 var rightBracketToken = tokens.Dequeue(); 472 if (rightBracketToken.TokenType != TokenType.RightBracket) throw new ArgumentException("closing bracket ] expected"); 473 factorVariableNode.Weights = weights.ToArray(); 474 return factorVariableNode; 475 } else { 476 // variable 477 var varNode = (VariableTreeNode)variable.CreateTreeNode(); 478 varNode.Weight = 1.0; 479 varNode.VariableName = idTok.strVal; 480 return varNode; 481 } 400 482 } 401 483 } else if (next.TokenType == TokenType.Number) {
Note: See TracChangeset
for help on using the changeset viewer.