qwertie / ecsharp

Home of LoycCore, the LES language of Loyc trees, the Enhanced C# parser, the LeMP macro preprocessor, and the LLLPG parser generator.
http://ecsharp.net
Other
172 stars 25 forks source link

How to make macros available for more purposes #68

Closed furesoft closed 4 years ago

furesoft commented 5 years ago

like define a new syntax element:

repository hellorep {

}

that will be replaced with:

public class hellorep : IRepository { ..other stuff... }

for example the Excess Project can do this but the Project is dead

qwertie commented 5 years ago

Luckily, the example you gave actually doesn't use any new syntax: Enhanced C# supports it already!

In fact, repository hellorep { ... } is simply a property declaration. And in Enhanced C#, you are allowed to put things inside a property declaration other than get and set accessors (such as variables and methods). Therefore, it is already possible to do what you are asking for.

You simply have to tell LeMP that you want to replace repository hellorep { ... } with public class hellorep : IRepository {...}. To do this, put the following code at the top of an ecstatic source file:

replace ({
   repository $Name {
     $(..stuff);
   }
} => {
   public class $Name : IRepository {
     $(..stuff);
   }
});

Then you can add code like this (which will change into a class):

repository hellorep { 
  public void Method () {}
  public int Field;
  public this() {}
}

You might encounter one small problem: constructors. repository is technically a property declaration, so the parser is not expecting to see a constructor inside it, and therefore hellorep() {} will be interpreted as an expression instead of a constructor. This problem is easy to solve, though: the word this is always interpreted as a constructor name, so you should write this () {} instead of ClassName() {}.

It is intentional that Enhanced C# does not support adding new syntax. One of the reasons is that often the syntax you want already exists. Another reason is that adding new syntax to C# creates ambiguity unless it is done very carefully. For example, you might think it is reasonable to add an <- operator, so you can write Mouth <- Cake. But this expression already has an interpretation in C#, Mouth < (-Cake). So if you were allowed to add a new <- operator, it would be ambiguous. Instead, I decided it would be better if Enhanced C# created a few extra syntax rules which you are allowed to use in your macros and replace commands.

furesoft commented 5 years ago

hmm, ive tried your example but it does not work. the generated file is only the same as the source file

qwertie commented 5 years ago

What version are you running? (version is written on the first line of output)

It should work in LeMP 2.6.2.0.

furesoft commented 5 years ago

i use the latest leMp version

furesoft commented 5 years ago

it works now, but i have another question.

i want to replace the name of the class by $name + "Repository"

ive tried with concatId but this is my result: public class concatId { ; }

;

` replace ({ repository $Name { $(..stuff); } } => { public class concatId($Name, "Repository") : IRepository { $(..stuff); } });

repository Date { public void Run() {} } `

and i have another question, how can i convert my replace macro call to make a new macro that i can use in different projects?

qwertie commented 5 years ago

class concatId($Name, "Repository") is a syntax error. Check your error list and make sure you can see the error.

In order to use an expression in a location where an expression is normally not allowed, you must use the $(out _) macro: in this case, class $(out concatId($Name, Repository))

qwertie commented 5 years ago

To share commands such as define and replace between different source files, you need to put the shared commands in a file and then use the includeFile("shared file name"); command at (or near) the top of other files that will use the shared commands.