识别彼此相邻的无限'{'expr'}'的语法
Grammar to recognize unlimited '{' expr '}' next to each-other
我正在使用 ANTLR4 to recognize the following TeX 风格编写 C# 应用程序:
{a}{x}+{b}{y}+{c}
我当前的语法总是采用 '{' expr '}' 的最后一个实例,然后忽略字符串的开头。以下是当前语法的一些输出结果(如下所述):
- 输入: {a} 输出: a [通过]
- 输入: {a}+{x} 输出: a + x [及格]
- 输入: {a}{x} 输出: x [失败]期望:斧头
- 输入: {a}{x}+{b} 输出: x + b [失败] 期望: ax + b
- 输入: {a}{x}+{b}{y} 输出: y [失败] 期望: ax + by
- 输入: {a}{x}+{b}{y}+{c} 输出: y + c [失败] 需要: ax + by + c
- 输入: {a}{x}+{b}{y}+{c}{d} 输出: d [失败] 期望: ax + by + cd
关于如何解决这个问题有什么想法吗?
语法 MyGra.g4 文件:
/*
* Parser Rules
*/
prog: expr+ ;
expr : '{' expr '}' # CB_Expr
| expr op=('+'|'-') expr # AddSub
| '{' ID '}' # CB_ID
| ID # ID
;
/*
* Lexer Rules
*/
ID: ('a' .. 'z' | 'A' .. 'Z')+;
ADD : '+';
SUB : '-';
WS: (' ' | '\r' | '\n') -> channel(HIDDEN);
MyGraVisitor.CS 文件:
public override string VisitID(MyGraParser.IDContext context)
{
return context.ID().GetText();
}
public override string VisitAddSub(MyGraParser.AddSubContext context)
{
if (context.op.Type == MyGraParser.ADD)
{
return Visit(context.expr(0)) + " + " + Visit(context.expr(1));
}
else
{
return Visit(context.expr(0)) + " - " + Visit(context.expr(1));
}
}
public override string VisitCB_Expr(MyGraParser.CB_ExprContext context)
{
return Visit(context.expr());
}
public override string VisitCB_ID(MyGraParser.CB_IDContext context)
{
return context.ID().GetText();
}
更新#1:
建议为
添加语法规则
'{' expr '}{' expr '}'
然而,如果我有 {a}{b}{c}{d}+{e}{f}{g},我认为语法应该通过解析树解释 "itself" 的递归版本...如果我有 1000 个 {expr} 彼此相邻怎么办?那我需要多少条规则?我认为这个建议是有效的,除了我不确定如何计算彼此相邻的无限量的 {expr}?
我的另一个问题是:如何重新使用规则 CB_Expr?
更新#2:
我添加了规则:
| expr CB_Expr # CB_Expr2
有访客:
public override string VisitCB_Expr2(MyGra.CB_Expr2Context context)
{
return Visit(context.expr()) + Visit(context.CB_Expr());
}
这没有用,我在所有情况下仍然得到相同的输出(如上所述)。
你的语法有歧义。例如:输入 {x} 可以有两个不同的解析树(如 Mephy 所说):
(CB_Expr { (expr (ID x)) })
和
(DB_ID {x})
删除 CB_ID 将解决此问题,而不会造成任何负面影响。
对于你的实际问题,这应该可以解决 expr:
expr : left=id_expr op=('+' |'-') right=expr #AddSub
| id_expr #ID_Expr
;
id_expr :
| '{' ID '}' id_expr #ID_Ex
| '{' ID '}' #ID
;
虽然我没有测试过这个,我也没有给你写过任何访问者,但是语法应该可以。
id_expr 规则以递归方式工作,因此您应该可以根据需要将尽可能多的 {ID} 放在彼此之后 - 至少一个,但现在的语法是这样。
我正在使用 ANTLR4 to recognize the following TeX 风格编写 C# 应用程序:
{a}{x}+{b}{y}+{c}
我当前的语法总是采用 '{' expr '}' 的最后一个实例,然后忽略字符串的开头。以下是当前语法的一些输出结果(如下所述):
- 输入: {a} 输出: a [通过]
- 输入: {a}+{x} 输出: a + x [及格]
- 输入: {a}{x} 输出: x [失败]期望:斧头
- 输入: {a}{x}+{b} 输出: x + b [失败] 期望: ax + b
- 输入: {a}{x}+{b}{y} 输出: y [失败] 期望: ax + by
- 输入: {a}{x}+{b}{y}+{c} 输出: y + c [失败] 需要: ax + by + c
- 输入: {a}{x}+{b}{y}+{c}{d} 输出: d [失败] 期望: ax + by + cd
关于如何解决这个问题有什么想法吗?
语法 MyGra.g4 文件:
/*
* Parser Rules
*/
prog: expr+ ;
expr : '{' expr '}' # CB_Expr
| expr op=('+'|'-') expr # AddSub
| '{' ID '}' # CB_ID
| ID # ID
;
/*
* Lexer Rules
*/
ID: ('a' .. 'z' | 'A' .. 'Z')+;
ADD : '+';
SUB : '-';
WS: (' ' | '\r' | '\n') -> channel(HIDDEN);
MyGraVisitor.CS 文件:
public override string VisitID(MyGraParser.IDContext context)
{
return context.ID().GetText();
}
public override string VisitAddSub(MyGraParser.AddSubContext context)
{
if (context.op.Type == MyGraParser.ADD)
{
return Visit(context.expr(0)) + " + " + Visit(context.expr(1));
}
else
{
return Visit(context.expr(0)) + " - " + Visit(context.expr(1));
}
}
public override string VisitCB_Expr(MyGraParser.CB_ExprContext context)
{
return Visit(context.expr());
}
public override string VisitCB_ID(MyGraParser.CB_IDContext context)
{
return context.ID().GetText();
}
更新#1:
建议为
添加语法规则'{' expr '}{' expr '}'
然而,如果我有 {a}{b}{c}{d}+{e}{f}{g},我认为语法应该通过解析树解释 "itself" 的递归版本...如果我有 1000 个 {expr} 彼此相邻怎么办?那我需要多少条规则?我认为这个建议是有效的,除了我不确定如何计算彼此相邻的无限量的 {expr}?
我的另一个问题是:如何重新使用规则 CB_Expr?
更新#2:
我添加了规则:
| expr CB_Expr # CB_Expr2
有访客:
public override string VisitCB_Expr2(MyGra.CB_Expr2Context context)
{
return Visit(context.expr()) + Visit(context.CB_Expr());
}
这没有用,我在所有情况下仍然得到相同的输出(如上所述)。
你的语法有歧义。例如:输入 {x} 可以有两个不同的解析树(如 Mephy 所说):
(CB_Expr { (expr (ID x)) })
和
(DB_ID {x})
删除 CB_ID 将解决此问题,而不会造成任何负面影响。
对于你的实际问题,这应该可以解决 expr:
expr : left=id_expr op=('+' |'-') right=expr #AddSub
| id_expr #ID_Expr
;
id_expr :
| '{' ID '}' id_expr #ID_Ex
| '{' ID '}' #ID
;
虽然我没有测试过这个,我也没有给你写过任何访问者,但是语法应该可以。
id_expr 规则以递归方式工作,因此您应该可以根据需要将尽可能多的 {ID} 放在彼此之后 - 至少一个,但现在的语法是这样。