gpt4 book ai didi

c# - ANTLR Visitor 类使用 C# 从表达式树中获取表达式

转载 作者:行者123 更新时间:2023-11-30 21:41:04 25 4
gpt4 key购买 nike

在为我的 antlr 程序编写访问者时遇到问题,比如这样的表达式

multiplyingExpression ((PLUS | MINUS) multiplyingExpression)*

我想得到表达式的左边部分,得到运算符类型和表达式的右边部分,请帮忙。这是我目前所拥有的

private double WalkLeft(testGrammerParser.MultiplyingExpressionContext context)
{
return Visit(context.GetRuleContext<testGrammerParser.MultiplyingExpressionContext>(0));
}

private double WalkRight(testGrammerParser.MultiplyingExpressionContext context)
{
return Visit(context.GetRuleContext<testGrammerParser.MultiplyingExpressionContext>(1));
}

我得到的错误是未将对象引用设置为对象的实例

提前致谢。

编辑

我更喜欢这样的东西

public Integer visitMulDiv(LabeledExprParser.MulDivContext ctx) {
int left = visit(ctx.expr(0)); // get value of left subexpression
int right = visit(ctx.expr(1)); // get value of right subexpression
if ( ctx.op.getType() == LabeledExprParser.MUL ) return left * right; //check operation type
return left / right; // must be DIV
}

编辑 2(语法)

这是我正在使用的语法

grammar testGrammer;

/*
* Parser Rules
*/

compileUnit
: expression + EOF
;

expression
: multiplyingExpression ((PLUS | MINUS) multiplyingExpression)*
;

multiplyingExpression
: powExpression ((TIMES | DIV) powExpression)*
;

powExpression
: atom (POW atom)*
;

atom
: scientific
| variable
| LPAREN expression RPAREN
| func
;

scientific
: number (E number)?
;

func
: funcname LPAREN expression RPAREN
;

funcname
: COS
| TAN
| SIN
| ACOS
| ATAN
| ASIN
| LOG
| LN
;

number
: MINUS? DIGIT + (POINT DIGIT +)?
;

variable
: MINUS? LETTER (LETTER | DIGIT)*
;

COS
: 'cos'
;

SIN
: 'sin'
;

TAN
: 'tan'
;

ACOS
: 'acos'
;

ASIN
: 'asin'
;

ATAN
: 'atan'
;

LN
: 'ln'
;

LOG
: 'log'
;

LPAREN
: '('
;

RPAREN
: ')'
;

PLUS
: '+'
;

MINUS
: '-'
;

TIMES
: '*'
;

DIV
: '/'
;

POINT
: '.'
;

E
: 'e' | 'E'
;

POW
: '^'
;

LETTER
: ('a' .. 'z') | ('A' .. 'Z')
;

DIGIT
: ('0' .. '9')
;

/*
* Lexer Rules
*/

WS
:[ \r\n\t] + -> channel(HIDDEN)
;

最佳答案

我终于做到了,这是完整的访问者类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExpressionParser
{
class testVisitor: testGrammerBaseVisitor<double>
{
public override double VisitCompileUnit(testGrammerParser.CompileUnitContext context)
{
return Visit(context.expression(0));
}

public override double VisitExpression(testGrammerParser.ExpressionContext context)
{
var left = context.multiplyingExpression(0);
var right = context.multiplyingExpression(1);

if (right != null)
{
if (context.PLUS(0) == null)
{
return Visit(left) - Visit(right);
}

return Visit(left) + Visit(right);
}

return Visit(left);
}

public override double VisitMultiplyingExpression(testGrammerParser.MultiplyingExpressionContext context)
{
var left = context.powExpression(0);
var right = context.powExpression(1);

if (right != null)
{
if (context.DIV(0) == null)
{
return Visit(left) * Visit(right);
}

return Visit(left) / Visit(right);
}

return Visit(left);
}

public override double VisitPowExpression(testGrammerParser.PowExpressionContext context)
{
var left = context.atom(0);
var right = context.atom(1);

if (right != null)
{
return Math.Pow(Visit(left), Visit(right));
}

return Visit(left);
}

public override double VisitAtom(testGrammerParser.AtomContext context)
{
if (context.scientific() != null)
{
return Visit(context.scientific());
}

if (context.variable() != null)
{
return Visit(context.variable());
}

if (context.expression() != null) //need to check this out
{
return Visit(context.expression());
}

return Visit(context.func());
}

public override double VisitScientific(testGrammerParser.ScientificContext context)
{
var left = context.number(0);
var right = context.number(1);

if (right != null)
{
return Visit(left) * Math.E * Visit(right);
}

return Visit(left);
}

public override double VisitFunc(testGrammerParser.FuncContext context)
{
var type = context.funcname().GetText();

switch (type)
{
case "cos":
return Math.Cos(Visit(context.expression()));

case "sin":
return Math.Sin(Visit(context.expression()));

case "tan":
return Math.Tan(Visit(context.expression()));

case "acos":
return Math.Acos(Visit(context.expression()));

case "asin":
return Math.Asin(Visit(context.expression()));

case "atan":
return Math.Atan(Visit(context.expression()));

case "ln":
return Math.Log(Visit(context.expression()));

case "log":
return Math.Log(Visit(context.expression()));
}

return Visit(context.expression());
}

public override double VisitNumber(testGrammerParser.NumberContext context)
{
var left = context.DIGIT(0);
var right = context.DIGIT(1);
int minus = 1;

if (context.MINUS() != null)
{
minus = -1;
}

if (right != null)
{
return (minus * Visit(left)) + Visit(right);
}

return minus * Visit(left);
}

public override double VisitVariable(testGrammerParser.VariableContext context)
{
return base.VisitVariable(context); // yet to implement this
}

public override double VisitTerminal(Antlr4.Runtime.Tree.ITerminalNode node)
{
return double.Parse(node.GetText());
}

}
}

这是它的语法

grammar testGrammer;

/*
* Parser Rules
*/

compileUnit
: expression + EOF
;

expression
: multiplyingExpression ((PLUS | MINUS) multiplyingExpression)*
;

multiplyingExpression
: powExpression ((TIMES | DIV) powExpression)*
;

powExpression
: atom (POW atom)*
;

atom
: scientific
| variable
| LPAREN expression RPAREN
| func
;

scientific
: number (E number)?
;

func
: funcname LPAREN expression RPAREN
;

funcname
: COS
| TAN
| SIN
| ACOS
| ATAN
| ASIN
| LOG
| LN
;

number
: MINUS? DIGIT + (POINT DIGIT +)?
;

variable
: MINUS? LETTER (LETTER | DIGIT)*
;

COS
: 'cos'
;

SIN
: 'sin'
;

TAN
: 'tan'
;

ACOS
: 'acos'
;

ASIN
: 'asin'
;

ATAN
: 'atan'
;

LN
: 'ln'
;

LOG
: 'log'
;

LPAREN
: '('
;

RPAREN
: ')'
;

PLUS
: '+'
;

MINUS
: '-'
;

TIMES
: '*'
;

DIV
: '/'
;

POINT
: '.'
;

E
: 'e' | 'E'
;

POW
: '^'
;

LETTER
: ('a' .. 'z') | ('A' .. 'Z')
;

DIGIT
: ('0' .. '9')
;

/*
* Lexer Rules
*/

WS
:[ \r\n\t] + -> channel(HIDDEN)
;

我用来测试的主类是

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Antlr4.Runtime;
using Antlr4.Runtime.Tree;
using System.Windows.Forms;


namespace ExpressionParser
{
class Program
{
static void Main(string[] args)
{
String input = "cos(3*3+3)";

ITokenSource lexer = new testGrammerLexer(new AntlrInputStream(input));
ITokenStream tokens = new CommonTokenStream(lexer);
testGrammerParser parser = new testGrammerParser(tokens);
parser.AddErrorListener(new ThrowExceptionErrorListener());
parser.BuildParseTree = true;
IParseTree tree;

try
{
tree = parser.compileUnit();
var visitor = new testVisitor();
var results = visitor.Visit(tree);

MessageBox.Show(results + "");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}

#钉钉子

关于c# - ANTLR Visitor 类使用 C# 从表达式树中获取表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43874375/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com