本文介绍了“预期的EOF”自定义编译器中的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 所以我在C#中使用一个名为algebra的自定义语言编写自己的编译器。 我正在学习本教程http://msdn.microsoft.com/en-us/magazine/cc136756。 aspx 这是编译器的源代码。 我认为编译器代码有问题。 代码很大所以我把它作为下载链接附加,如果你不想下载它们,你可以查看教程代码,因为我的代码基本相同。 https://www.dropbox.com/s/6h5fu7f6in3mtfw/Ast.cs https ://www.dropbox.com/s/lt6x8zjltq68q50/Parser.cs https://www.dropbox.com/s/h84crc42472773s/Program.cs https ://www.dropbox.com/s/gkw2im5n1it28pb/Scanner.cs https://www.dropbox.com/s/0gnx65to6pfna0y/CodeGen.cs 这是创建消息的代码(Parser.cs): public Parser(Collections.IList< object>代币) { 此 .tokens = tokens; 此 .index = 0 ; this .result = this .ParseStmt(); if ( this .index!= this .tokens.Count) throw new System.Exception ( 期望的EOF); } 此代码扫描任何操作员标志(以'+'为例)(scanner.c) 顺便说一下,还有更多的代码。 case'+': input.Read(); this.result.Add(Scanner.Add); 休息; 这个位只是一个枚举(Ast.cs) // < bin_op> := + | - | * | / public enum BinOp { Add , Sub, Mul, Div } CodeGen.cs private void GenExpr(Expr expr,System.Type expectedType) { System.Type deliveredType; if (expr StringLiteral) { deliverType = typeof ( string ); this .il.Emit(Emit.OpCodes.Ldstr,((StringLiteral)expr).Value); } else if (expr 是 IntLiteral) { deliverType = typeof ( int ); this .il.Emit(Emit.OpCodes.Ldc_I4,((IntLiteral)expr).Value); } else if (expr 是变量) { string ident =((Variable)expr).Ident; deliveredType = this .TypeOfExpr(expr); if (!this.symbolTable.ContainsKey(ident)) { throw new System.Exception( 未声明的变量' + ident + '); } this .il.Emit(Emit.OpCodes.Ldloc, this .symbolTable [IDENT]); } else if (stmt 是打印) { 这些是'写'和'读''语句 // write语句是System.Console.WriteLine的别名。 // 它使用字符串大小写 this .GenExpr(((Print)stmt).Expr, typeof ( string )); this .il.Emit(Emit.OpCodes.Call, typeof (System.Console) .GetMethod( WriteLine, new System.Type [] { typeof ( string )})); } else if (stmt 是 ReadInt) { this .il.Emit(Emit.OpCodes.Call, typeof (System.Console).GetMethod( ReadLine,System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null , new 系统.Type [] {}, null )); this .il.Emit(Emit.OpCodes.Call, typeof ( int )。GetMethod( Parse,System.Reflection .BindingFlags.Public | System.Reflection.BindingFlags.Static, null , new System.Type [] { typeof ( string )}, null ) ); this .Store(((ReadInt)stmt).Ident, typeof ( INT )); } 此处更多代码定义变量,表达式等。 / * < expr> :=< string> * | < INT> * | < arith_expr> * | < IDENT> * / public abstract class Expr {} // < string> :=< string_elem> * public class StringLiteral:Expr { public string 值; } // < int> :=< digit> + public class IntLiteral:Expr { public int 值; } // < ident> :=< char> < ident_rest> * // < ident_rest> :=< char> | < digit> public class 变量:Expr { public string Ident; } // < bin_expr> :=< expr> < bin_op> < expr> public class BinExpr:Expr { public Expr Left; public Expr Right; public BinOp Op; } 关于运营商的更多信息(scanner.c)/ / b $ b #region ArithmiticConstants // 表示arithmitic标记的常量。这可以 // 或者写成枚举。 public static readonly object Add = new object (); public static readonly object Sub = new object (); public static readonly object Mul = new object (); public static readonly object Div = new object (); public static readonly object Semi = new object (); public static readonly object Equal = new object (); #endregion 问题看起来无法对数字或变量执行任何数学运算。 所以例如我写这样的代码并尝试编译它然而我得到一个错误(预期的EOF): 变量x = 9; 变量y = 10; 变量ans = x * y; 写ans; 这里输出应该是90但是编译器给出错误'EOF预期' 但是这样可行: 变量x = 9; 写x; 所以我可以确认语言有效 如果有人能帮助我,我将非常感激。 所以我很感激我得到的任何帮助。谢谢:)解决方案 so I am making my own compiler in C# for a custom Language called algebra.I am following this tutorial http://msdn.microsoft.com/en-us/magazine/cc136756.aspxHere is the source code of the compiler.I think there is something wrong with the compiler code.The code is quite big so I attach it as download links, if you don't want to download them you can look at the tutorial code as the code I have is basically the same. https://www.dropbox.com/s/6h5fu7f6in3mtfw/Ast.cs https://www.dropbox.com/s/lt6x8zjltq68q50/Parser.cs https://www.dropbox.com/s/h84crc42472773s/Program.cs https://www.dropbox.com/s/gkw2im5n1it28pb/Scanner.cs https://www.dropbox.com/s/0gnx65to6pfna0y/CodeGen.csHere is the code that creates the message(Parser.cs): public Parser(Collections.IList<object> tokens) { this.tokens = tokens; this.index = 0; this.result = this.ParseStmt(); if (this.index != this.tokens.Count) throw new System.Exception("expected EOF"); }This code scans for any operator signs(taking '+' as an example)(scanner.cs)there is more code to this by the way. case '+': input.Read(); this.result.Add(Scanner.Add); break;This bit is just an enumeration(Ast.cs)// <bin_op> := + | - | * | /public enum BinOp{Add,Sub,Mul,Div}CodeGen.cs private void GenExpr(Expr expr, System.Type expectedType) { System.Type deliveredType; if (expr is StringLiteral) { deliveredType = typeof(string); this.il.Emit(Emit.OpCodes.Ldstr, ((StringLiteral)expr).Value); } else if (expr is IntLiteral) { deliveredType = typeof(int); this.il.Emit(Emit.OpCodes.Ldc_I4, ((IntLiteral)expr).Value); } else if (expr is Variable) { string ident = ((Variable)expr).Ident; deliveredType = this.TypeOfExpr(expr); if (!this.symbolTable.ContainsKey(ident)) { throw new System.Exception("undeclared variable '" + ident + "'"); } this.il.Emit(Emit.OpCodes.Ldloc, this.symbolTable[ident]); } else if (stmt is Print) {These are the 'write' and 'read' statements // the "write" statement is an alias for System.Console.WriteLine. // it uses the string case this.GenExpr(((Print)stmt).Expr, typeof(string)); this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new System.Type[] { typeof(string) })); } else if (stmt is ReadInt) { this.il.Emit(Emit.OpCodes.Call, typeof(System.Console).GetMethod("ReadLine", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { }, null)); this.il.Emit(Emit.OpCodes.Call, typeof(int).GetMethod("Parse", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static, null, new System.Type[] { typeof(string) }, null)); this.Store(((ReadInt)stmt).Ident, typeof(int)); }more code here that defines variables ,expressions etc. /* <expr> := <string> * | <int> * | <arith_expr> * | <ident> */ public abstract class Expr { } // <string> := " <string_elem>* " public class StringLiteral : Expr { public string Value; } // <int> := <digit>+ public class IntLiteral : Expr { public int Value; } // <ident> := <char> <ident_rest>* // <ident_rest> := <char> | <digit> public class Variable : Expr { public string Ident; } // <bin_expr> := <expr> <bin_op> <expr> public class BinExpr : Expr { public Expr Left; public Expr Right; public BinOp Op; }More on the operators (scanner.cs)#region ArithmiticConstants// Constants to represent arithmitic tokens. This could// be alternatively written as an enum.public static readonly object Add = new object();public static readonly object Sub = new object();public static readonly object Mul = new object();public static readonly object Div = new object();public static readonly object Semi = new object();public static readonly object Equal = new object();#endregionthe problem looks like it's not possible to perform any mathematical operations on either a number or variable.so for example I write such code and try to compile it however I get an error(expected EOF): variable x = 9; variable y = 10; variable ans = x * y; write ans;here the output should be 90 however the compiler gives an error 'EOF expected'However this works: variable x = 9; write x;so I can confirm the language worksI would be very grateful if anyone could help me.So I appreciate any help that I get. Thanks :) 解决方案 这篇关于“预期的EOF”自定义编译器中的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-22 13:47