-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start working on a Skeleton compiler. #1028
- Loading branch information
Showing
14 changed files
with
851 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using TypeCobol.Compiler.Nodes; | ||
using TypeCobol.Compiler.Text; | ||
|
||
namespace TypeCobol.Codegen | ||
{ | ||
/// <summary> | ||
/// Callback interface used by an IGenerator instance. | ||
/// </summary> | ||
public interface IGeneratorEmitterCallback | ||
{ | ||
/// <summary> | ||
/// Callback before starting generating the given node. | ||
/// </summary> | ||
/// <param name="node">The node</param> | ||
/// <param name="generator">The generator</param> | ||
/// <returns>true if the generation process can continue on this node, othewise no generation action | ||
/// will be performed on this node, and this node and all its children will be marked as removed.</returns> | ||
bool BeforeNode(Node node, IGenerator generator); | ||
/// <summary> | ||
/// Callback to get the an Enumeration of all lines to be generated for the given node. | ||
/// </summary> | ||
/// <param name="node">The node</param> | ||
/// <param name="generator">The generator</param> | ||
/// <returns>The IEnumerable instance</returns> | ||
IEnumerable<ITextLine> Lines(Node Node, IGenerator generator); | ||
/// <summary> | ||
/// Callback after node generation. | ||
/// </summary> | ||
/// <param name="node">The node</param> | ||
/// <param name="generator">The generator</param> | ||
void AfterNode(Node node, IGenerator generator); | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<configuration> | ||
<startup> | ||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> | ||
</startup> | ||
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using System.IO; | ||
using System.Collections.Generic; | ||
using TypeCobol.TemplateCompiler.Skeletons; | ||
|
||
namespace TypeCobol.TemplateCompiler.Config { | ||
/// <summary><see cref="Skeleton"/> parser interface.</summary> | ||
public interface ConfigParser { | ||
List<Skeleton> Parse(string path); | ||
} | ||
|
||
public class Config { | ||
/// <summary> | ||
/// The Map the association a configuration file extension to its Class parser. | ||
/// </summary> | ||
private static readonly Dictionary<string,Type> _parsers = new Dictionary<string,Type> { | ||
{ ".xml", typeof(XmlParser) }, | ||
}; | ||
|
||
public static ConfigParser CreateParser(string extension) { | ||
Type type; | ||
try { type = _parsers[extension.ToLower()]; } | ||
catch(System.Exception) { type = _parsers[".xml"]; } | ||
return (ConfigParser)Activator.CreateInstance(type); | ||
} | ||
|
||
public static List<Skeleton> Parse(string path) { | ||
return CreateParser(Path.GetExtension(path)).Parse(path); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
using System.Xml; | ||
using System.Collections.Generic; | ||
using TypeCobol.TemplateCompiler.Skeletons; | ||
using System.IO; | ||
|
||
namespace TypeCobol.TemplateCompiler.Config { | ||
|
||
/// <summary>XML Skeleton file parser<see cref="Skeleton"/> parser.</summary> | ||
public class XmlParser: ConfigParser { | ||
internal static string TAG_SKELETON = "skeleton"; | ||
internal static string TAG_CONDITION_LIST = "conditions"; | ||
internal static string TAG_CONDITION = "condition"; | ||
internal static string ATTR_NODE = "node"; | ||
internal static string ATTR_CLAUSE = "clause"; | ||
internal static string TAG_PATTERN_LIST = "patterns"; | ||
internal static string TAG_PATTERN = "pattern"; | ||
internal static string ATTR_NAME = "name"; | ||
internal static string ATTR_GROUP = "group"; | ||
internal static string ATTR_LOCATION = "location"; | ||
internal static string ATTR_ACTION = "action"; | ||
internal static string ATTR_VARIABLES = "var"; | ||
internal static string ATTR_POSITION = "position"; | ||
internal static string ATTR_NEWLINE = "newline"; | ||
internal static string ATTR_BOOLEAN_PROPERTY = "boolean_property"; | ||
internal static string ATTR_DEPRECATED = "deprecated"; | ||
|
||
/// <summary>Parses an XML file.</summary> | ||
/// <param name="path">Path to an XML file</param> | ||
/// <returns>List of <see cref="Skeleton"/> defined in <paramref name="path"/></returns> | ||
public List<Skeleton> Parse(string path) | ||
{ | ||
string[] files = null; | ||
//If path contains "*" | ||
if (path.Contains("*")) | ||
{ | ||
string fileName = Path.GetFileName(path); | ||
path = string.Concat(Path.GetDirectoryName(path), Path.DirectorySeparatorChar); | ||
files = Directory.GetFiles(path, fileName); | ||
} | ||
//If path contains only directory. | ||
else if (Path.GetFileName(path).Equals(string.Empty)) | ||
{ | ||
files = Directory.GetFiles(path, "*.*"); | ||
} | ||
//If above conditions fail, it means the path has a specific file name. | ||
else | ||
{ | ||
files = new string[1]; | ||
files[0] = path; | ||
} | ||
|
||
var skeletons = new List<Skeleton>(); | ||
var factory = new SkeletonFactory(); | ||
foreach (var filePath in files) | ||
{ | ||
var xml = new XmlDocument(); | ||
xml.Load(filePath); | ||
|
||
foreach (var node in xml.ChildNodes) | ||
{ | ||
var e = node as XmlElement; | ||
if (e == null) continue; | ||
foreach (var child in e.ChildNodes) | ||
{ | ||
var ce = child as XmlElement; | ||
if (ce == null) continue; | ||
if (!ce.LocalName.ToLower().Equals(TAG_SKELETON)) continue; | ||
skeletons.Add(factory.Create(ce)); | ||
} | ||
} | ||
} | ||
return skeletons; | ||
} | ||
|
||
internal static string GetAttribute(XmlElement e, string name, string defaultvalue = null) { | ||
string a = e.GetAttribute(name); | ||
if (a == null || a.Length == 0) return defaultvalue; | ||
return a; | ||
} | ||
internal static Dictionary<string,string> GetAttributes(XmlElement e) { | ||
var attrs = new Dictionary<string,string>(); | ||
foreach(XmlAttribute attr in e.Attributes) { | ||
attrs[attr.LocalName.ToLower()] = attr.Value; | ||
} | ||
return attrs; | ||
} | ||
} | ||
|
||
|
||
|
||
interface Factory<T> { | ||
/// <summary>Creates an object from a given <see cref="System.Xml.XMLElement"/>.</summary> | ||
/// <typeparam name="T">Type of object created</param> | ||
/// <param name="e">XML element</param> | ||
/// <returns>Created object</returns> | ||
T Create(XmlElement e); | ||
} | ||
|
||
internal class SkeletonFactory: Factory<Skeleton> { | ||
private static ConditionListFactory CFactory = new ConditionListFactory(); | ||
private static PatternListFactory PFactory = new PatternListFactory(); | ||
public Skeleton Create(XmlElement e) { | ||
var skeleton = new Skeleton(); | ||
skeleton.Conditions = new List<Condition>(); | ||
skeleton.Patterns = new List<Pattern>(); | ||
foreach(var child in e.ChildNodes) { | ||
var ce = child as XmlElement; | ||
if (ce == null) continue; | ||
skeleton.Name = XmlParser.GetAttribute(e, XmlParser.ATTR_NAME); | ||
string name = ce.LocalName.ToLower(); | ||
if (name.Equals(XmlParser.TAG_CONDITION_LIST)) { | ||
skeleton.Conditions.AddRange(CFactory.Create(ce)); | ||
} else | ||
if (name.Equals(XmlParser.TAG_PATTERN_LIST)) { | ||
skeleton.Patterns.AddRange(PFactory.Create(ce)); | ||
} | ||
|
||
} | ||
|
||
skeleton.Properties = new List<string>(); | ||
string vars = e.GetAttribute(XmlParser.ATTR_VARIABLES); | ||
foreach(var var in vars.Split(',')) { | ||
string property = var.Trim(); | ||
if (property.Length > 0) skeleton.Properties.Add(property); | ||
} | ||
|
||
return skeleton; | ||
} | ||
} | ||
|
||
internal class ConditionListFactory: Factory<List<Condition>> { | ||
private static ConditionFactory Factory = new ConditionFactory(); | ||
public List<Condition> Create(XmlElement e) { | ||
var conditions = new List<Condition>(); | ||
foreach(var child in e.ChildNodes) { | ||
var ce = child as XmlElement; | ||
if (ce == null) continue; | ||
if (!ce.LocalName.ToLower().Equals(XmlParser.TAG_CONDITION)) continue; | ||
conditions.Add(Factory.Create(ce)); | ||
} | ||
return conditions; | ||
} | ||
} | ||
|
||
internal class ConditionFactory: Factory<Condition> { | ||
private Dictionary<string,List<string>> namespaces = new Dictionary<string,List<string>>(); | ||
|
||
public Condition Create(XmlElement e) { | ||
var condition = new ConditionOnNode(); | ||
condition.Attributes = XmlParser.GetAttributes(e); | ||
if (condition.Attributes.ContainsKey("node")) { | ||
condition.Node = condition.Attributes["node"]; | ||
condition.Attributes.Remove("node"); | ||
} | ||
return condition; | ||
} | ||
} | ||
|
||
internal class PatternListFactory: Factory<List<Pattern>> { | ||
private static PatternFactory Factory = new PatternFactory(); | ||
public List<Pattern> Create(XmlElement e) { | ||
var patterns = new List<Pattern>(); | ||
foreach(var child in e.ChildNodes) { | ||
var ce = child as XmlElement; | ||
if (ce == null) continue; | ||
if (!ce.LocalName.ToLower().Equals(XmlParser.TAG_PATTERN)) continue; | ||
patterns.Add(Factory.Create(ce)); | ||
} | ||
return patterns; | ||
} | ||
} | ||
|
||
internal class PatternFactory: Factory<Pattern> { | ||
public Pattern Create(XmlElement e) { | ||
var pattern = new Pattern(); | ||
pattern.Name = XmlParser.GetAttribute(e, XmlParser.ATTR_NAME); | ||
pattern.Group = XmlParser.GetAttribute(e, XmlParser.ATTR_GROUP); | ||
pattern.Location = XmlParser.GetAttribute(e, XmlParser.ATTR_LOCATION); | ||
pattern.Action = XmlParser.GetAttribute(e, XmlParser.ATTR_ACTION); | ||
string val = XmlParser.GetAttribute(e, XmlParser.ATTR_NEWLINE); | ||
pattern.NewLine = val != null ? val.Equals("true") : false; | ||
pattern.BooleanProperty = XmlParser.GetAttribute(e, XmlParser.ATTR_BOOLEAN_PROPERTY); | ||
pattern.Deprecated = XmlParser.GetAttribute(e, XmlParser.ATTR_DEPRECATED); | ||
pattern.Variables = new Dictionary<string,string>(); | ||
string vars = e.GetAttribute(XmlParser.ATTR_VARIABLES); | ||
foreach(var var in vars.Split(',')) { | ||
var kv = var.Split('='); | ||
if (kv.Length != 2) continue; | ||
string key = kv[0].Trim(); | ||
string value = kv[1].Trim().ToLower(); | ||
pattern.Variables.Add(key, value); | ||
} | ||
|
||
string pos = XmlParser.GetAttribute(e, XmlParser.ATTR_POSITION); | ||
if (pos != null) | ||
{ | ||
try | ||
{ | ||
pattern.Position = int.Parse(pos); | ||
} | ||
catch (System.FormatException) | ||
{ | ||
//do not set pattern.Position | ||
} | ||
} | ||
|
||
pattern.Template = e.InnerText; | ||
return pattern; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
using Mono.Options; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace TypeCobol.TemplateCompiler | ||
{ | ||
class Program | ||
{ | ||
/// <summary> | ||
/// Program name from Assembly name | ||
/// </summary> | ||
public static string ProgName => Assembly.GetExecutingAssembly().GetName().Name; | ||
|
||
/// <summary> | ||
/// Assembly version | ||
/// </summary> | ||
public static string Version => Assembly.GetExecutingAssembly().GetName().Version.ToString(); | ||
|
||
/// <summary> | ||
/// The Skeleton file in input. | ||
/// </summary> | ||
public static string SkeletonFile | ||
{ | ||
get; set; | ||
} | ||
|
||
/// <summary> | ||
/// The Output file. | ||
/// </summary> | ||
public static string OutputFile | ||
{ | ||
get; set; | ||
} | ||
|
||
/// <summary> | ||
/// Command Line Option Set | ||
/// </summary> | ||
public static OptionSet Options | ||
{ | ||
get; | ||
internal set; | ||
} | ||
|
||
static int Main(string[] args) | ||
{ | ||
bool help = false; | ||
bool version = false; | ||
|
||
var p = new OptionSet() | ||
{ | ||
"USAGE", | ||
" "+ProgName+" [OPTIONS]", | ||
"", | ||
"VERSION:", | ||
" "+Version, | ||
"", | ||
"DESCRIPTION:", | ||
" Run the TypeCobol Template Compiler.", | ||
{ "v|version","Show version", _ => version = true }, | ||
{ "h|help","Show help", _ => help = true }, | ||
{ "i|input=","{PATH} Template file path", (string v) => SkeletonFile = v }, | ||
{ "o|output=","{PATH} Generated output file path", (string v) => OutputFile = v } | ||
}; | ||
|
||
System.Collections.Generic.List<string> arguments; | ||
try { arguments = p.Parse(args); } | ||
catch (OptionException ex) { return Exit(1, ex.Message); } | ||
|
||
if (help) | ||
{ | ||
p.WriteOptionDescriptions(System.Console.Out); | ||
return 0; | ||
} | ||
if (version) | ||
{ | ||
System.Console.WriteLine(Version); | ||
return 0; | ||
} | ||
//Store the options. | ||
Options = p; | ||
|
||
|
||
return 0; | ||
} | ||
|
||
static int Exit(int code, string message) | ||
{ | ||
string errmsg = ProgName + ": " + message + "\n"; | ||
errmsg += "Try " + ProgName + " --help for usage information."; | ||
System.Console.WriteLine(errmsg); | ||
return code; | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.