Skip to content

Instantly share code, notes, and snippets.

@core-code
Created October 28, 2015 15:18
Show Gist options
  • Save core-code/8a82a51b29035fa031a5 to your computer and use it in GitHub Desktop.
Save core-code/8a82a51b29035fa031a5 to your computer and use it in GitHub Desktop.
using System;
using Irony.Parsing;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Linq;
namespace XLParser
{
public class JSONExport
{
public JSONExport ()
{
}
public string ParseToJSON (string formula)
{
ParseTreeNode root;
try {
root = XLParser.ExcelFormulaParser.Parse (formula);
} catch (ArgumentException) {
Type grammar = typeof(ExcelFormulaGrammar);
var r = new Parser ((Grammar)Activator.CreateInstance (grammar)).Parse (formula);
return (JsonConvert.SerializeObject (new
{
error = "Parse error",
formula = formula,
message = r.ParserMessages.Select (m => new
{
level = m.Level.ToString (),
line = m.Location.Line + 1,
column = m.Location.Column + 1,
msg = m.Message
//String.Format("{0} at {1}: {2}", m.Level, m.Location, m.Message)
}).FirstOrDefault ()
}));
}
return (JsonConvert.SerializeObject (
ToJSON (root),
Formatting.Indented,
new JsonSerializerSettings {
NullValueHandling = NullValueHandling.Ignore,
}
));
}
private JSONNode ToJSON (ParseTreeNode node)
{
return new JSONNode {
name = NodeText (node),
children = node.ChildNodes.Count == 0 ? null : node.ChildNodes.Select (ToJSON)
};
}
private class JSONNode
{
public string name;
public IEnumerable<JSONNode> children;
}
private string NodeText (ParseTreeNode node)
{
if (node.Term is NonTerminal)
return node.Term.Name;
// These are simple terminals like + or =, just print them
// For other terminals, print the terminal name + contents
return node.Term.Name.Length <= 2 ? ExcelFormulaParser.Print(node) : $"{node.Term.Name}[\"{ExcelFormulaParser.Print(node)}\"]";
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment