【问题标题】:Replace token's text in ANTLR在 ANTLR 中替换令牌的文本
【发布时间】:2012-04-25 10:48:55
【问题描述】:

我正在尝试将输入程序中的某些标记文本替换为特定格式的文本。我使用 C# 作为输出语言。

输入示例:

time#1m2s

我对该输入的 lex 语法:

fragment
DIGIT : '0'..'9'
      ;

CTE_DURATION 
    : ('T'|'t'|'TIME'|'time') '#' '-'? (DIGIT ('d'|'h'|'m'|'s'|'ms') '_'?)+
    ;

我想从输入示例中获取的输出令牌文本:

0.0:1:2.0

这意味着:0 天、0 小时、1 分钟、2 秒和 0 毫秒。

有什么建议吗?提前谢谢你。

【问题讨论】:

  • 我不明白你的问题,你能更具体一点吗?你的问题是你希望你的语法只接受这种格式的输入吗:0.0:1:2.0?
  • 我的 lex 语法接受“time#1m2s”并创建一个文本为“time#1m2s”的 CTE_DURATION 标记。我希望我的 lex 规则更改 CTE_DURATION 标记文本(在我的示例中,我想将标记文本更改为“0.0:1:2.0”)。

标签: c# antlr lexer


【解决方案1】:

这是一种方法(它在 Java 中,但应该不难移植到 C#):

grammar Test;

parse
 : CTE_DURATION EOF
 ;

CTE_DURATION 
 : ('T' 'IME'? | 't' 'ime'?) '#' minus='-'?
   (d=DIGITS 'd')? (h=DIGITS 'h')? (m=DIGITS 'm')? (s=DIGITS 's')? (ms=DIGITS 'ms')?
   {
     int days = $d == null ? 0 : Integer.valueOf($d.text);
     int hours = $h == null ? 0 : Integer.valueOf($h.text);
     int minutes = $m == null ? 0 : Integer.valueOf($m.text);
     int seconds = $s == null ? 0 : Integer.valueOf($s.text);
     int mseconds = $ms == null ? 0 : Integer.valueOf($ms.text);
     setText(($minus == null ? "" : "-") + days + "." + hours + ":" + minutes + ":" + seconds + "." + mseconds);
   }
 ;

fragment DIGITS : '0'..'9'+;

解析输入 time#1m2s 得到以下解析树:

请注意,语法现在也接受 time#(导致它产生 0.0:0:0.0),但您可以轻松地从词法分析器规则中产生异常,以防此类输入无效。

【讨论】:

  • 感谢您的回答。这解决了我的问题。我不得不在目标 C# 中使用“$text”而不是“setText()”。如何在输出中添加减号 ('-')(减号是可选的)?
  • 我在写评论之前尝试过这种方式。这总是会产生带有“-”的输出。编辑:我已经得到了可选减号的解决方案,添加了一个新的 lex 规则:“fragment MINUS:'-';”。我在 CTE_DURATION 规则中使用了 MINUS。谢谢。
猜你喜欢
  • 2012-04-10
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-10
  • 2023-04-11
相关资源
最近更新 更多