Click here to Skip to main content
15,888,085 members
Please Sign up or sign in to vote.
1.00/5 (3 votes)
See more:
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.aspx

Here 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.cs


Here is the code that creates the message(Parser.cs):

C#
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)

C#
// <bin_op> := + | - | * | /
public enum BinOp
{
Add,
Sub,
Mul,
Div
}


CodeGen.cs

C#
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

C#
// 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.

C#
/* <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)
C#
#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();

#endregion


the 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 works



I would be very grateful if anyone could help me.
So I appreciate any help that I get. Thanks :)
Posted
Comments
[no name] 21-Jun-14 7:12am    
No one is going download all of this to debug it for you. Your problem most likely lies in if (this.index != this.tokens.Count) where you have set index = 0 and presumably the number of tokens is not 0 so you throw an exception.
Gabriel Denys 21-Jun-14 9:49am    
thanks, but I don't get an error when I don't use any mathematical symbols. I know there is way too much code for anyone to debug, do u have any tip on how to get help on this, I really need to fix this! Thanks :)
gggustafson 23-Jun-14 18:53pm    
Did you compile the compiler? Did you test the compiler with both of the samples provided? What did you find with the helloworld.gfn file? What was the code (.gfn file) you created and supplied to the compiler?
gggustafson 23-Jun-14 19:02pm    
Sorry just saw your code. Shouldn't "variable" be "var"?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900