Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ANTLR中的一些语法问题_C#_Antlr - Fatal编程技术网

C# ANTLR中的一些语法问题

C# ANTLR中的一些语法问题,c#,antlr,C#,Antlr,我一直在做一个练习,内容是从文本文件中读取,然后: 仅用一个空格替换连续的空格/制表符 仅用一个替换连续的换行符 使所有文本大写 当我执行它时,它不会向output.txt文件写入任何内容 我试图找出这个问题已有一段时间了,但没有成功。这是我的密码: grammar Ejerc1; options { language = CSharp3; } @header { using System.IO; using System; } fragment Spaces : ('

我一直在做一个练习,内容是从文本文件中读取,然后:

  • 仅用一个空格替换连续的空格/制表符
  • 仅用一个替换连续的换行符
  • 使所有文本大写
当我执行它时,它不会向
output.txt
文件写入任何内容

我试图找出这个问题已有一段时间了,但没有成功。这是我的密码:

grammar Ejerc1;
options
{
    language = CSharp3;
}
@header
{
using System.IO;
using System;
}
fragment Spaces     :   (' '|'\t')+ { $text = " "; };
fragment Any        :   (~(' '|'\t'|'\n'|'\r'))+ { $text = $text.ToUpper(); };
fragment NewLines   :   ('\r'|'\n')+ { $text = "\r\n"; };

/* Parser */
public file[string filePath]
@init {
if (File.Exists($filePath)) { 
    File.Delete($filePath); 
}
StreamWriter w = new StreamWriter($filePath);
}
@after {
w.Close();
}
:
(
 Spaces { w.Write($Spaces.text); }
|NewLines { w.Write($NewLines.text); }
|Any { w.Write($Any.text); }
)*
EOF;
下面是
Main
方法中的代码:

string inputPath = "text.txt";
string outputPath = "output.txt";
var input = new ANTLRFileStream(inputPath);
var lexer = new Ejerc1Lexer(input);

var tokens = new CommonTokenStream(lexer);
var parser = new Ejerc1Parser(tokens);
parser.file(outputPath);

片段规则只能从其他lexer规则中使用,不能从解析器规则中使用,正如您正在尝试的那样。只需从3个lexer规则中删除
片段
关键字即可

此外,代码段:

$text = " ";
转换为以下内容(伪代码):

这是无效的(至少在使用Java目标时是无效的)。您可能要尝试:

Spaces     :   (' '|'\t')+ { SetText(" "); };

相反。但是CSharp3目标可能会接受它。

没有在v3上玩太多,但我在一个教程中发现了这样的评论:“lexer规则可以引用其他lexer规则。它们通常引用‘fragment’lexer规则。这些规则不会导致创建标记,并且只用于简化其他lexer规则的定义。”也许从定义中删除“片段”会有所帮助?另外,不要使用
Spaces{w.Write($Spaces.text);}
,而是尝试
sp=Spaces{w.Write($sp.text);}
@OwenS。谢谢这就是问题所在。另外,你能解释一下为什么你建议做
sp=Spaces…
而不是直接做吗?在
Spaces{w.Write($Spaces.text);}
sp=Spaces{w.Write($sp.text);}
之间没有区别。后者在使用两个相同的令牌或产品时使用:
foo:Token-Token。若要引用其中一个,则会为它们分配一个“标签”:
foo:a=Token b=Token{…$a.text…$b.text…}@BartKiers明白了。再次感谢:)成功了:)关于做
SetText(…)
,谢谢你的建议。很高兴知道,尽管在CSharp3中它似乎是有效的;)在了解片段规则的含义后,这完全有道理;)如果片段规则不会成为令牌,那么解析器应该如何使用它呢?:)@奥斯卡,很高兴知道CSharp3接受了。Java目标确实接受
$type=SOME_type
,所以我总是觉得奇怪为什么
$text=“SOME text”
不起作用。当然不客气!
Spaces     :   (' '|'\t')+ { SetText(" "); };