我有一些制作笔译和口译的知识和技能。但在每种情况下,我都使用了手写解析器。现在我有一个好主意,可以编写一个解释器,通过自己的 .NET 上的虚拟机工作,这样它就可以使用它的任何到达 API。也许IL的编译器也会出现。我决定使用 ANTLR 来提高开发速度,并主要关注语言和 VM 代码,而不是解析。ANTLR - 因为我在 Wikipedia 中发现它有一个 IDE,并且可以为 C# 生成解析器代码,我选择它来编写我的程序。
经过一些努力,我强制我的代码编译。这是 C# 代码:
using System;
using System.Resources;
using System.Reflection;
using System.Globalization;
using System.Configuration;
using System.IO;
using Antlr.Runtime;
class AgathaInterpretter
{
static ResourceManager rm;
static CultureInfo ci;
static string GetString(string key)
{
try
{
return rm.GetString(key, ci);
}
catch (Exception)
{
return "Resource string not found.";
}
}
public static void Main(string[] args)
{
ci = new CultureInfo(ConfigurationManager.AppSettings["locale"]);
rm = new ResourceManager("Agatha.Messages", Assembly.GetExecutingAssembly());
switch (args.Length)
{
case 0:
Console.WriteLine(GetString("ERROR_COMMAND_LINE_ARGS_ZERO"));
return;
case 1:
break;
default:
Console.WriteLine(GetString("ERROR_COMMAND_LINE_ARGS_GREATER"));
return;
}
StreamReader streamReader;
try
{
streamReader = new StreamReader(args[0]);
}
catch (Exception)
{
Console.WriteLine(GetString("ERROR_SCRIPT_FILE_INACCESSIBLE"));
return;
}
string str = "";
while (!streamReader.EndOfStream)
str += streamReader.ReadLine() + "\n";
Console.WriteLine(str);
ANTLRStringStream Input = new ANTLRStringStream(str);
AgathaLexer Lexer = new AgathaLexer(Input);
CommonTokenStream Tokens = new CommonTokenStream(Lexer);
AgathaParser Parser = new AgathaParser(Tokens);
Parser.prog();
}
}
这是我的语法:
grammar Agatha;
options
{
language=CSharp2;
}
tokens {
PLUS = '+' ;
MINUS = '-' ;
MULT = '*' ;
DIV = '/' ;
LP = '(' ;
RP = ')' ;
SEMICOLON = ';' ;
ASSIGN = '=';
}
public prog: statement+ ;
statement: assignmentExpression | SEMICOLON ;
assignmentExpression : ID ASSIGN additiveExpression SEMICOLON| additiveExpression SEMICOLON ;
additiveExpression: multiplicativeExpression ( ( PLUS | MINUS ) multiplicativeExpression )* ;
multiplicativeExpression: unaryExpression ( ( MULT | DIV ) unaryExpression )* ;
unaryExpression : LP assignmentExpression RP | NUMBER | ID;
NUMBER : (DIGIT)+ ;
WS : (' ' |'\t' |'\n' |'\r' )+ {skip();} ;
ID : ('a'..'z' |'A'..'Z' )+ ;
fragment DIGIT : '0'..'9' ;
似乎是有效的,生成了解析器。首先发布我的 C# 代码后,我尝试加载不同的文件并用我的 prog() 解析它们。但是,如果我也提供错误的源,没有例外,没有输出到控制台,什么都不会发生。我想先接受一些培训,但没有得到任何培训。我哪里错了?发生了什么?