如何在我的 lexer/parser 中支持不同的语言版本
How to support different language versions in my lexer/parser
我想知道在我的语法中支持不同语言版本的最佳方式是什么。
我正在修改一种语言的现有语法,并且有一个新版本的语言,引入了新的关键字和我应该能够解析的附加语法。但是,用该语言编写的现有代码库已经可以使用这些新关键字作为标识符,因此我必须将此扩展设为可选。
所以我的问题是:基于布尔值编写条件词法分析器和解析器规则的首选方法是什么?我想到了语义谓词,但我对 antlr 比较陌生,我不确定将它们用于这样的目的是否是个好主意。
您可以采用两种方法:
- 如果附加语法对早期版本的语法无效并且之前有效表达式的解释没有改变 - 只有这样你才能考虑使用语义谓词之类的东西来衡量输入的哪一部分用新语法解析哪个用旧语法解析。
例如:扩展整数计算器以支持浮点数
1.0
对早期语法无效,新语法不会改变 1
(整数)计算的语义。
这个条件并不像看起来那么容易满足 - 可能会有非常微妙的条件,特别是如果语法或其新版本很复杂。
- 有两个版本的 lexer/parser 并按照@lex-li 的建议独立打开它们。这是一条安全的道路,它不必通过添加新语法语法来处理旧表达式的语义变化。
我在 MySQL grammar 中的语义谓词取得了很好的成功,以支持各种 MySQL 版本。这包括新功能、删除的功能和仅对特定 MySQL 版本范围有效的功能。此外,您可以使用语义谓词告诉用户特定语法在哪个版本中有效。但是你必须为此自己解析谓词。
例如,在this line中有条件地添加了一条新的导入语句:
simpleStatement:
// DDL
...
| {serverVersion >= 80000}? importStatement
我的 common recognizer class 中有一个字段 serverVersion
,生成的词法分析器和解析器 类 都从中派生。在触发解析过程之前,此字段设置了有效版本。
同样在词法分析器中,您可以使用这种方法保护关键字,如 MySQL 词法分析器中的 this and surrounding lines 所示:
MASTER_SYMBOL: M A S T E R;
MASTER_TLS_VERSION_SYMBOL: M A S T E R '_' T L S '_' V E R S I O N {serverVersion >= 50713}?;
MASTER_USER_SYMBOL: M A S T E R '_' U S E R;
MASTER_HEARTBEAT_PERIOD_SYMBOL: M A S T E R '_' H E A R T B E A T '_' P E R I O D?;
MATCH_SYMBOL: M A T C H; // SQL-2003-R
MAX_CONNECTIONS_PER_HOUR_SYMBOL: M A X '_' C O N N E C T I O N S '_' P E R '_' H O U R;
MAX_QUERIES_PER_HOUR_SYMBOL: M A X '_' Q U E R I E S '_' P E R '_' H O U R;
MAX_ROWS_SYMBOL: M A X '_' R O W S;
MAX_SIZE_SYMBOL: M A X '_' S I Z E;
MAX_STATEMENT_TIME_SYMBOL:
M A X '_' S T A T E M E N T '_' T I M E {50704 < serverVersion && serverVersion < 50708}?
;
MAX_SYMBOL: M A X { setType(determineFunction(MAX_SYMBOL)); }; // SQL-2003-N
MAX_UPDATES_PER_HOUR_SYMBOL: M A X '_' U P D A T E S '_' P E R '_' H O U R;
MAX_USER_CONNECTIONS_SYMBOL: M A X '_' U S E R '_' C O N N E C T I O N S;
我想知道在我的语法中支持不同语言版本的最佳方式是什么。
我正在修改一种语言的现有语法,并且有一个新版本的语言,引入了新的关键字和我应该能够解析的附加语法。但是,用该语言编写的现有代码库已经可以使用这些新关键字作为标识符,因此我必须将此扩展设为可选。
所以我的问题是:基于布尔值编写条件词法分析器和解析器规则的首选方法是什么?我想到了语义谓词,但我对 antlr 比较陌生,我不确定将它们用于这样的目的是否是个好主意。
您可以采用两种方法:
- 如果附加语法对早期版本的语法无效并且之前有效表达式的解释没有改变 - 只有这样你才能考虑使用语义谓词之类的东西来衡量输入的哪一部分用新语法解析哪个用旧语法解析。
例如:扩展整数计算器以支持浮点数
1.0
对早期语法无效,新语法不会改变 1
(整数)计算的语义。
这个条件并不像看起来那么容易满足 - 可能会有非常微妙的条件,特别是如果语法或其新版本很复杂。
- 有两个版本的 lexer/parser 并按照@lex-li 的建议独立打开它们。这是一条安全的道路,它不必通过添加新语法语法来处理旧表达式的语义变化。
我在 MySQL grammar 中的语义谓词取得了很好的成功,以支持各种 MySQL 版本。这包括新功能、删除的功能和仅对特定 MySQL 版本范围有效的功能。此外,您可以使用语义谓词告诉用户特定语法在哪个版本中有效。但是你必须为此自己解析谓词。
例如,在this line中有条件地添加了一条新的导入语句:
simpleStatement:
// DDL
...
| {serverVersion >= 80000}? importStatement
我的 common recognizer class 中有一个字段 serverVersion
,生成的词法分析器和解析器 类 都从中派生。在触发解析过程之前,此字段设置了有效版本。
同样在词法分析器中,您可以使用这种方法保护关键字,如 MySQL 词法分析器中的 this and surrounding lines 所示:
MASTER_SYMBOL: M A S T E R;
MASTER_TLS_VERSION_SYMBOL: M A S T E R '_' T L S '_' V E R S I O N {serverVersion >= 50713}?;
MASTER_USER_SYMBOL: M A S T E R '_' U S E R;
MASTER_HEARTBEAT_PERIOD_SYMBOL: M A S T E R '_' H E A R T B E A T '_' P E R I O D?;
MATCH_SYMBOL: M A T C H; // SQL-2003-R
MAX_CONNECTIONS_PER_HOUR_SYMBOL: M A X '_' C O N N E C T I O N S '_' P E R '_' H O U R;
MAX_QUERIES_PER_HOUR_SYMBOL: M A X '_' Q U E R I E S '_' P E R '_' H O U R;
MAX_ROWS_SYMBOL: M A X '_' R O W S;
MAX_SIZE_SYMBOL: M A X '_' S I Z E;
MAX_STATEMENT_TIME_SYMBOL:
M A X '_' S T A T E M E N T '_' T I M E {50704 < serverVersion && serverVersion < 50708}?
;
MAX_SYMBOL: M A X { setType(determineFunction(MAX_SYMBOL)); }; // SQL-2003-N
MAX_UPDATES_PER_HOUR_SYMBOL: M A X '_' U P D A T E S '_' P E R '_' H O U R;
MAX_USER_CONNECTIONS_SYMBOL: M A X '_' U S E R '_' C O N N E C T I O N S;