private float EvaluateExpression(CompilerParser.ExpressionContext ctx) { float left, right; // Если выражение является обычным числом(left, right и sign будут null) - просто возвращаем его // В случае с одинокой переменной - читаем из ее значение памяти if (ctx.left == null) { return(ctx.Start.Type == CompilerParser.ID ? (float)CompilerParser.memory[ctx.Start.Text] : Convert.ToSingle(ctx.Start.Text)); } // Если левая часть выражения является переменной - вытаскиваем ее значение if (ctx.left.Start.Type == CompilerParser.ID) { left = Convert.ToSingle(CompilerParser.memory[ctx.left.Start.Text]); } // Если левая часть выражения тоже является выражением - рекурсивно вычисляем его значение else if (ctx.left.left != null) { left = EvaluateExpression(ctx.left); } // Если числом (у него левый узел всегда будет null), значит просто конвертируем его в float else { left = Convert.ToSingle(ctx.left.Start.Text); } // Тоже самое с правой частью, только смотрим на правый узел if (ctx.right.Start.Type == CompilerParser.ID) { right = Convert.ToSingle(CompilerParser.memory[ctx.right.Start.Text]); } else if (ctx.right.right != null) { right = EvaluateExpression(ctx.right); } else { right = Convert.ToSingle(ctx.right.Start.Text); } // Выполняем нужное арифметическое действие с операндами и возвращаем результат switch (ctx.sign.Text) { case "/": return(left / right); case "*": return(left * right); case "+": return(left + right); case "-": return(left - right); default: throw new Exception($"Incorrect sign '{ctx.sign.Text}'"); } }
/// <summary> /// Enter a parse tree produced by <see cref="CompilerParser.expression"/>. /// <para>The default implementation does nothing.</para> /// </summary> /// <param name="context">The parse tree.</param> public virtual void EnterExpression([NotNull] CompilerParser.ExpressionContext context) { }
/// <summary> /// Visit a parse tree produced by <see cref="CompilerParser.expression"/>. /// <para> /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/> /// on <paramref name="context"/>. /// </para> /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public virtual Result VisitExpression([NotNull] CompilerParser.ExpressionContext context) { return(VisitChildren(context)); }
public override CompilerParser VisitExpression([NotNull] CompilerParser.ExpressionContext context) { // Кидаем результат в специальное поле, чтобы потом получить к нему доступ из контекста context.val = EvaluateExpression(context); return(null); }