我目前正在做一个项目,我有一个任务是使用 ANTLR4 语法验证标识符。这部分项目如果前端使用Angular 6,语法也会编译到后端微服务。
验证包括验证以字母|数字字符开头的字符串,然后它可以具有字母|数字|下划线并以字母|数字字符结束。
我目前在语法实现方面遇到问题(因为我没有 Lex 经验(和处理错误。这是我的语法和错误的实现。
grammar test;
goal: identifier;
identifier: Alphanum+ Alphanumsymb* Alphanum+;
Alphanum: [a-zA-Z0-9];
Alphanumsymb: [a-zA-Z0-9_];
以及我的实现,用于根据语法检测字符串是否有效。
const teststring = "2019_Test_Identifier";
const inputStream = new ANTLRInputStream(teststring);
const lex = new lexer.TestGrammarLexer(inputStream);
const tokenStream = new CommonTokenStream(lex);
const pars = new parser.TestGrammarParser(tokenStream);
pars.goal();
console.log(pars.numberOfSyntaxErrors);
if ( pars.numberOfSyntaxErrors > 0 ) {
return false;
}
return true;
我的问题是,即使我的语法正确,我的错误处理实现也不正确,我还没有找到研究antlr4ts错误处理的材料。
所以,如果你能帮助我,我将不胜感激关于语法的反馈(它应该如何,或者它有 atm 的问题(,以及关于错误处理的实现(关于这个的一些信息,因为在测试时,我看到 ConsoleErrorListener 抛出语法错误到控制台,但我的函数显示 0 语法错误(。
感谢您的阅读,希望您能帮助我。
我认为使用ANTLR对于您的任务来说有点矫枉过正。ANTLR 或任何其他解析工具非常适合构造字符串的结构,但在这里,您只想知道字符串是否是标识符。如果您真的需要ANTLR,请详细说明原因,然后我可以帮助您处理错误。
对于此任务,我建议您只需使用如下所示的正则表达式来测试标识符:
const regex = /^[a-zA-Z0-9]+|[a-zA-Z0-9][a-zA-Z0-9_]*[a-zA-Z0-9]+$/
然后将其用作regex.text(str)
.
如果不接受字符串作为标识符,它将返回false
。
请注意,您对ANTLR语法中identifier
的定义不正确。由于两个+
量词,它至少需要两个字符,并且在长度为 1 的字符串(如a
(上失败。正则表达式版本也修复了这个问题。
预计此后端微服务将来将"做更多",当前的最低语法要求可以通过以下方式满足
ident : Alphanum (( Alphanum | Symb )* Alphanum )? ;
Alphanum : [a-zA-Z0-9] ;
Symb : '_' ;
现在,ident
规则允许使用单个字符标识符,这显然是原始规范所允许的。Symb
规则现在表示原始语法中唯一未被Alphanum
规则遮蔽的内容。
默认情况下,词法分析器和解析器包括控制台错误侦听器。
使用Recognizer#addErrorListener
添加ANTLRErrorListener
的自定义扩展,该扩展根据需要计数并报告任何错误ConsoleErrorListener
都是源示例。可以在词法分析器和解析器上设置相同的侦听器。
如果不需要控制台消息,请使用Recognizer#removeErrorListeners
首先删除控制台侦听器。
顺便说一句,所有 ANTLR 运行时在功能上都是相同的,并且在架构上非常相似。因此,{Java, Python, ...} 中的任何 ANTLR 代码示例在 TypeScript 中都将具有几乎等效的实现。