Skip to content

Instantly share code, notes, and snippets.

@joeriks
Last active January 3, 2016 08:19
Show Gist options
  • Save joeriks/8434873 to your computer and use it in GitHub Desktop.
Save joeriks/8434873 to your computer and use it in GitHub Desktop.
A second version of grammar for a simple domain type DSL experiment (using PEGjs) see also http://joeriks.com/2014/01/14/a-simple-dsl-code-generation-using-node/
Foo.BarBas
Project
Foo:string
Id:key
Name
Write project name :label
You need to state the project name:err
Address
Person
Id:key
Name
SomeValue:number
Other.Namespace
Vehicle
Id:key
Name
Project
Id:key
Name
Write project name :label
You need to state the project name:err
Address
namespace Foo.BarBas {
public class Project {
public string Foo {get;set;}
public int Id {get;set;}
public string Name {get;set;}
public string Address {get;set;}
}
public class Person {
public int Id {get;set;}
public string Name {get;set;}
public number SomeValue {get;set;}
}
namespace Other.Namespace {
public class Vehicle {
public int Id {get;set;}
public string Name {get;set;}
}
public class Project {
public int Id {get;set;}
public string Name {get;set;}
public string Address {get;set;}
}
[
{
"name":"Foo.BarBas",
"types":[
{
"name":"Project",
"members":[
{
"name":"Foo",
"type":"string"
},
{
"name":"Id",
"type":"key"
},
{
"name":"Name",
"type":"string",
"details":[
{
"name":"Write project name ",
"type":"label"
},
{
"name":"You need to state the project name",
"type":"err"
}
]
},
{
"name":"Address",
"type":"string"
}
]
},
{
"name":"Person",
"members":[
{
"name":"Id",
"type":"key"
},
{
"name":"Name",
"type":"string"
},
{
"name":"SomeValue",
"type":"number"
}
]
}
]
},
{
"name":"Other.Namespace",
"types":[
{
"name":"Vehicle",
"members":[
{
"name":"Id",
"type":"key"
},
{
"name":"Name",
"type":"string"
}
]
},
{
"name":"Project",
"members":[
{
"name":"Id",
"type":"key"
},
{
"name":"Name",
"type":"string",
"details":[
{
"name":"Write project name ",
"type":"label"
},
{
"name":"You need to state the project name",
"type":"err"
}
]
},
{
"name":"Address",
"type":"string"
}
]
}
]
}
]
// do not use result cache, nor line and column tracking
/* sample:
Project
Id :key
Name
Write project name:label
You need to state the project name:err
Address
SomeValue :num
The idea is to create a json that is easy to use for code generation later.
*/
{ var indentStack = [], indent = ""; }
start
= (EOL* INDENT? nameSpace:NAMESPACE EOL* { return nameSpace; })+
NAMESPACEHEAD = c:[a-zA-Z.]+ " "* {return c.join("");}
NAMESPACE
= SAMEDENT type:(!EOL typeHead:NAMESPACEHEAD {return {"name":typeHead}}) EOL*
children:( INDENT c:TYPE* EOL* DEDENT { return c; })?
{
if (children) type["types"]=children;
return type; }
TYPEHEAD = c:[a-zA-Z]+ " "* {return c.join("");}
TYPE
= SAMEDENT type:(!EOL typeHead:TYPEHEAD {return {"name":typeHead}}) EOL*
children:( INDENT c:MEMBER* DEDENT { return c; })?
{
if (children) type["members"]=children;
return type; }
MEMBERHEAD = c:[a-zA-Z]+ " "* t:(":" t:MEMBERTYPE{return t})? {return {name:c.join(""),type:t==null?"string":t}}
MEMBERTYPE = type:('key'/'number'/'string') {return type;}
MEMBER
= SAMEDENT memberHead:(!EOL memberhead:MEMBERHEAD {return memberhead}) EOL*
children:( INDENT c:DETAIL* DEDENT { return c; })?
{
if (children) memberHead["details"] = children;
return memberHead }
DETAILHEAD = c:[a-zA-Z ]* t:(":" t:DETAILTYPE{return t})? {return {name:c.join(""),type:t}}
DETAILTYPE = type:('label'/'err') {return type;}
DETAIL
= SAMEDENT detailHead:(!EOL detailHead:DETAILHEAD {return detailHead}) EOL?
{return detailHead}
EOL
= ([ \t]*) ("\r\n" / "\n" / "\r")
SAMEDENT
= i:[ \t|" "]* &{ return i.join("") === indent; }
INDENT
= i:[ \t|" "]+ &{ return i.length > indent.length; }
{
indentStack.push(indent);
indent = i.join("");
peg$currPos = offset();
}
DEDENT
= { indent = indentStack.pop(); }
{% for namespace in model %}
namespace {{ namespace.name }} {
{% for ty in namespace.types %}
public class {{ty.name}} { {% for member in ty.members %}
public {% if (member.type=='key') %}int{% else %}{{member.type}}{%endif%} {{ member.name }} {get;set;}{% endfor %}
}
{% endfor %}
{% endfor %}
module.exports = function(grunt) {
grunt.initConfig({
watch: {
files: '*.txt',
tasks: ['dsl2']
},
peg: {
dsl2 : {
src: "dsl2.grammar",
dest: "dsl2.js"
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-peg');
grunt.registerTask('dsl2', function(){
var dsl2 = require("./dsl2");
console.log("dsl2" + dsl2);
var swig = require("swig");
var tpl = swig.compileFile("cs_template.swig");
console.log("tpl"+ tpl);
var parsed = dsl2.parse(grunt.file.read("typecode.txt"));
console.log(parsed);
grunt.file.write("parsedtoobject.json",JSON.stringify(parsed));
var result = tpl({model:parsed});
grunt.file.write("result.cs",result);
});
grunt.registerTask('default', ['dsl2','watch']);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment