如何调试 ANTLR4 目标语言为 Go 的监听器?

huangapple go评论82阅读模式
英文:

How to debug listeners for ANTLR4 target Go

问题

我正在尝试弄清楚为什么我的监听器对规则没有触发,尽管每个规则都被触发,但特定规则没有被触发。我在http://lab.antlr.org/上测试了我的语法。

谢谢。

这段代码会打印输出...

func (f *FSLListener) EnterEveryRule(ctx antlr.ParserRuleContext) {
	fmt.Printf("EnterEveryRule %v\n", ctx.GetText())
}

但这段代码不会打印输出

func (f *FSLListener) ExitVar_assignment(ctx *parser.Var_assignmentContext) error {
	fmt.Printf("Complete var assignment: %s\n", ctx.GetText())
    // ... 更新了这一行以反映我正在处理这个错误,这就是为什么我没有看到任何编译器错误
    return nil 
}

参考示例监听器https://github.com/antlr/antlr4/blob/master/doc/go-target.md

我的语法是

parser grammar fslParser;

options { tokenVocab=fslLexer; }


r: script* EOF;

script: var_assignment* init_function function_definition*;

var_assignment: VAR VALUE;
init_function: INIT cmd_list RBRACK;
function_definition: VALIDFUNCTIONID cmd_list RBRACK;

cmd_list: (cmd_expression)*;

cmd_expression:
  CMD FUNCTIONCALL
  | CMD FUNCTIONCALLWITHARGS param_list //function call
  | CMD VARREF COMMA param_list // variable reference
  | CMD builtin_functions param_list // user-defined function call
;

builtin_functions: (CREATE | DELETE | UPDATE | ADD | SUBTRACT | MULTIPLY | DIVIDE | PRINT);

param_list: ARG param (COMMA ARG param)*;
param:
  VARREF
  | VALUE
  | LETTERS VALUE
  | VARPARAM
  | VARPARAM VALUE
;

词法分析器

lexer grammar fslLexer;

INIT : 'init: [';
VALIDFUNCTIONID : [a-zA-Z]+ ': [';
VAR : 'var' [0-9]+':';
VALUE : [0-9]+ ('.' [0-9]+)?;
CMD : 'cmd:';
VARREF : '#var'[0-9]+ ;
FUNCTIONCALL : '#' [a-zA-Z]+ ;
FUNCTIONCALLWITHARGS : '#' [a-zA-Z]+',';
VARPARAM : '$' [a-zA-Z]+ ;

DIGITS: [0-9]+;
LETTERS: [a-zA-Z]+;

ARG: LETTERS DIGITS? COLON;

// Define function names as keywords
CREATE  : 'create,';
DELETE  : 'delete,';
UPDATE  : 'update,';
ADD     : 'add,';
SUBTRACT: 'subtract,';
MULTIPLY: 'multiply,';
DIVIDE  : 'divide,';
PRINT   : 'print,';

COLON : ':';
COMMA : ',';
RBRACK : ']';

SPACE : [ \t\r\n]+ -> skip ;

我试图匹配的示例输入:

var1: 1
var2: 2

init: [
    cmd: #setup
]

setup: [
    cmd: #sum, id: var1, value1: #var1, value2: #var2
    cmd: #printAll
]

sum: [
   cmd: add, id: $id, operand1: $value1, operand2: $value2
]

printAll: [
   cmd: print, value: #var1
   cmd: print, value: #var2
   cmd: print, value: #var3
]

英文:

I'm trying to figure out why my listeners aren't triggering for the rules when every rule is being triggered but not the specific rules. I tested my grammar works on http://lab.antlr.org/

Thank you.

this prints...

func (f *FSLListener) EnterEveryRule(ctx antlr.ParserRuleContext) {
	fmt.Printf("EnterEveryRule %v\n", ctx.GetText())
}

but this doesn't

func (f *FSLListener) ExitVar_assignment(ctx *parser.Var_assignmentContext) error {
	fmt.Printf("Complete var assignment: %s\n", ctx.GetText())
    // ... updated this line to reflect that I was handling this error which is why I didn't see any compiler errors
    return nil 
}

Following the example listener in https://github.com/antlr/antlr4/blob/master/doc/go-target.md

My Grammar is

parser grammar fslParser;

options { tokenVocab=fslLexer; }


r: script* EOF;

script: var_assignment* init_function function_definition*;

var_assignment: VAR VALUE;
init_function: INIT cmd_list RBRACK;
function_definition: VALIDFUNCTIONID cmd_list RBRACK;

cmd_list: (cmd_expression)*;

cmd_expression:
  CMD FUNCTIONCALL
  | CMD FUNCTIONCALLWITHARGS param_list //function call
  | CMD VARREF COMMA param_list // variable reference
  | CMD builtin_functions param_list // user-defined function call
;

builtin_functions: (CREATE | DELETE | UPDATE | ADD | SUBTRACT | MULTIPLY | DIVIDE | PRINT);

param_list: ARG param (COMMA ARG param)*;
param:
  VARREF
  | VALUE
  | LETTERS VALUE
  | VARPARAM
  | VARPARAM VALUE
;

Lexer

lexer grammar fslLexer;

INIT : 'init: [' ;
VALIDFUNCTIONID : [a-zA-Z]+ ': [';
VAR : 'var' [0-9]+':' ;
VALUE : [0-9]+ ('.' [0-9]+)? ;
CMD : 'cmd:' ;
VARREF : '#var'[0-9]+ ;
FUNCTIONCALL : '#' [a-zA-Z]+ ;
FUNCTIONCALLWITHARGS : '#' [a-zA-Z]+',' ;
VARPARAM : '$' [a-zA-Z]+ ;

DIGITS: [0-9]+;
LETTERS: [a-zA-Z]+;

ARG: LETTERS DIGITS? COLON;

// Define function names as keywords
CREATE  : 'create,' ;
DELETE  : 'delete,' ;
UPDATE  : 'update,' ;
ADD     : 'add,' ;
SUBTRACT: 'subtract,' ;
MULTIPLY: 'multiply,' ;
DIVIDE  : 'divide,' ;
PRINT   : 'print,' ;

COLON : ':';
COMMA : ',';
RBRACK : ']';

SPACE : [ \t\r\n]+ -> skip ;

Example input I'm trying to match:

var1: 1
var2: 2

init: [
    cmd: #setup
]

setup: [
    cmd: #sum, id: var1, value1: #var1, value2: #var2
    cmd: #printAll
]

sum: [
   cmd: add, id: $id, operand1: $value1, operand2: $value2
]

printAll: [
   cmd: print, value: #var1
   cmd: print, value: #var2
   cmd: print, value: #var3
]

答案1

得分: 2

func (f *FSLListener) ExitVar_assignment(ctx *parser.Var_assignmentContext) {
    fmt.Printf("完成变量赋值:%s\n", ctx.GetText())
}

应该是这样的:

func (f *FSLListener) ExitVar_assignment(ctx *parser.Var_assignmentContext) {
    fmt.Printf("完成变量赋值:%s\n", ctx.GetText())
}

这是Go代码中的一个简单语法错误。实现没有返回值。应用此更改后,我可以看到以下输出:

完成变量赋值:var1:1
完成变量赋值:var2:2

请注意,生成的fslParserListener接口是:

// fslParserListener是由fslParser生成的解析树的完整监听器。
type fslParserListener interface {
	// ExitVar_assignment在退出var_assignment产生式时调用。
	ExitVar_assignment(c *Var_assignmentContext)

	// 其他代码已省略
}

它没有返回值。

为了强制接口的一致性,您可以导出监听器接口,并将以下语句添加到您的代码中(假设接口导出为parser.FslParserListener):

var _ parser.FslParserListener = (*FSLListener)(nil)
英文:
func (f *FSLListener) ExitVar_assignment(ctx *parser.Var_assignmentContext) error {
    fmt.Printf("Complete var assignment: %s\n", ctx.GetText())
}

Should be:

func (f *FSLListener) ExitVar_assignment(ctx *parser.Var_assignmentContext) {
    fmt.Printf("Complete var assignment: %s\n", ctx.GetText())
}

This is a simple syntax error in the Go code. The implementation does not have a return value. After applying this change, I can see this output:

Complete var assignment: var1:1
Complete var assignment: var2:2

And please note that the generated fslParserListener interface is:

// fslParserListener is a complete listener for a parse tree produced by fslParser.
type fslParserListener interface {
	// ExitVar_assignment is called when exiting the var_assignment production.
	ExitVar_assignment(c *Var_assignmentContext)

	// Other codes truncated
}

It does not have a return value.

To force the interface compliance, you can export the listener interface and add this statement to your code (it assumes that the interface is exported as parser.FslParserListener):

var _ parser.FslParserListener = (*FSLListener)(nil)

huangapple
  • 本文由 发表于 2023年6月12日 03:16:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76452155.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定