public void GenerateExistingResultForBranch(Generator generator, int branch) { MultipleValElement leftOperand = Child <MultipleValElement>(0); leftOperand.Child <GetVariableElement>(branch).ResultOfGeneration = GetVariableElement.GenerateOptions.Value; leftOperand.GenerateForBranch(generator, branch); }
/// <summary> /// Build expression value. It's called from ParseExpression /// </summary> /// <param name="lexemes">List of lexemes</param> /// <param name="pos">Position of current parsed lexeme</param> /// <param name="flags">Control flags. ExpressionFlags.None to ignore all flags</param> /// <param name="elem">Builded value element. null if it's not a value</param> /// <returns>Position of a next lexeme</returns> private int ParseExpressionValue(List <Lexeme> lexemes, int pos, ExpressionFlags flags, out ValueElement elem) { MultipleValElement multipleVals = new MultipleValElement(); if (lexemes[pos].Source == "(") { List <ValueElement> values; pos = ExtractSeparatedExpressions(lexemes, pos, flags | ExpressionFlags.ForbidMultiple, out values); if (pos >= (lexemes.Count - 1)) { Compilation.WriteError("Unexpected end of file. Did you forget ')' and ';' ?", -1); } foreach (var i in values) { multipleVals.AddValue(i); } } //"(" else if (lexemes[pos].Code == Lexeme.CodeType.Number) { var val = new ConstValElement { Type = m_symbols.GetTypeOfConstVal(lexemes[pos].Source), Value = lexemes[pos].Source }; ++pos; elem = val; return(pos); } else if (m_currentFunction.HasVariable(lexemes[pos].Source) && lexemes[pos + 1].Source != "(") { var val = new GetVariableElement() { VarName = lexemes[pos].Source, VarType = m_currentFunction.GetVariable(lexemes[pos].Source).VarType, ResultOfGeneration = GetVariableElement.GenerateOptions.Value }; ++pos; elem = val; return(pos); } else if (m_symbols.HasFunctionWithName(lexemes[pos].Source)) { FunctionCallElement callElement = new FunctionCallElement(); string funcName = lexemes[pos].Source; ++pos; List <ValueElement> values; if (lexemes[pos + 1].Source == ")") //fucntion without arguments { values = new List <ValueElement>(); pos += 2; //'(' ')' } else { pos = ExtractSeparatedExpressions(lexemes, pos, flags | ExpressionFlags.AllowAutoDefault, out values); } if (values.Count == 1 && values[0].NumberOfBranches > 1) { values = values[0].Children().Select(child => (ValueElement)child).ToList(); } callElement.FunctionInfo = m_symbols.GetFunction( funcName, values.Select(val => val?.ResultType.ResultTypes[0].Name).ToList()); for (int i = 0, end = values.Count; i < end; ++i) { if (values[i] == null) { values[i] = callElement.FunctionInfo.Arguments[i].DefaultVal; } } callElement.CallArguments = values; elem = callElement; return(pos); } else if (lexemes[pos].Source == "default") { ++pos; if (lexemes[pos].Source == "(") { Compilation.Assert(flags.HasFlag(ExpressionFlags.AllowDefaultValue), "Default type value keyword is used but it isn't allowed here.", lexemes[pos].Line); ++pos; //skip '(' string typeName = lexemes[pos].Source; //TODO: namespaces ConstValElement constVal = m_symbols.GetDefaultVal(typeName); elem = new ConstValElement { Type = constVal.Type, Value = constVal.Value }; ++pos; ++pos; //skip ')' } else { Compilation.Assert(flags.HasFlag(ExpressionFlags.AllowAutoDefault), "Auto default keyword is used but it isn't allowed here.", lexemes[pos].Line); elem = null; } return(pos); } else //Not a value { elem = null; return(pos); } elem = multipleVals; return(pos); }
/// <summary> /// Build expression element /// </summary> /// <param name="lexemes">List of lexemes</param> /// <param name="pos">Position of current parsed lexeme</param> /// <param name="endPos">Position at which function breaks. Pass -1 to parse until the end</param> /// <param name="flags">Control flags. ExpressionFlags.None to ignore all flags</param> /// <param name="elem"></param> /// <returns>Position of a next lexeme</returns> private int ParseExpression(List <Lexeme> lexemes, int pos, int endPos, ExpressionFlags flags, out ValueElement elem) { OperationElement lastOperation = null; OperationElement rootOperation = null; ValueElement lastValElement = null; bool breakCycle = false; if (endPos == -1) { endPos = lexemes.Count; } for (int end = endPos; !breakCycle && pos < end;) { var currentLexeme = lexemes[pos]; switch (currentLexeme.Source) { case ")": case ";": case "{": case "}": breakCycle = true; continue; case ",": Compilation.WriteError("Unexpected symbol: ','." + "Did you forget '(' ?\nExample: '( SYMBOLS, SYMBOLS )'.", lexemes[pos].Line); continue; case "+": case "-": case "*": case "/": case "^": case "=": { if (lastValElement == null && lastOperation == null) { if (lexemes[pos].Source == "-") { rootOperation = lastOperation = new UnaryMinusElement(); ++pos; continue; } else { Compilation.WriteError("Expected value or expression before '" + lexemes[pos].Source + "'", lexemes[pos].Line); } } OperationElement operation = null; switch (lexemes[pos].Source) { case "+": operation = new BinaryPlusElement(); break; case "-": operation = new BinaryMinusElement(); break; case "*": operation = new BinaryMultiplicationElement(); break; case "/": operation = new BinaryDivisionElement(); break; case "^": operation = new BinaryExponentiationElement(); break; case "=": { operation = new CopyElement(); if (lastValElement != null) { if (!(lastValElement is MultipleValElement)) { var multiple = new MultipleValElement(); multiple.AddValue(lastValElement); lastValElement = multiple; } } else { if (lastOperation != null) { var valElem = lastOperation.Child(1); if (!(valElem is MultipleValElement)) { var multiple = new MultipleValElement(); multiple.AddValue((ValueElement)valElem); lastOperation.SetChild(1, valElem); } } else { Compilation.WriteError("Expected value before '='", -1); } } } break; default: Compilation.WriteCritical("BUG: Unknown operator passed through the switch"); break; } if (lastOperation == null) { operation.SetChild(0, lastValElement); lastValElement = null; rootOperation = operation; } else { InsertOperationInTree(ref lastOperation, ref operation, ref rootOperation); } lastOperation = operation; } ++pos; break; default: pos = ParseExpressionValue(lexemes, pos, flags | ExpressionFlags.AllowDefaultValue & (~ExpressionFlags.OperationRequired), out lastValElement); if (lastValElement == null) { if (!flags.HasFlag(ExpressionFlags.AllowAutoDefault)) { Compilation.WriteError("Unknown symbol: '" + currentLexeme.Source + "'.", currentLexeme.Line); } else //used default keyword. Caller have to find result { elem = null; return(pos); } } else { if (lastOperation != null) { InsertValInTree(lastOperation, lastValElement); lastValElement = null; } } break; } } if (rootOperation == null) { if (flags.HasFlag(ExpressionFlags.OperationRequired) && !(lastValElement is FunctionCallElement)) { Compilation.WriteError("Expression must contain at least one operator", lexemes[pos].Line); } if (lastValElement == null) { Compilation.WriteError("No operation or value in expression", lexemes[pos].Line); } elem = lastValElement; } else { elem = rootOperation; } return(pos); }