203 lines
5.7 KiB
C#
203 lines
5.7 KiB
C#
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
using System.Windows.Forms;
|
|
|
|
namespace YLPublishTool
|
|
{
|
|
class Parser
|
|
{
|
|
int _nextPos;
|
|
int _lineNum;
|
|
int _lineStartPos;
|
|
int _lineEndPos;
|
|
string _source;
|
|
StringReader _sr;
|
|
|
|
bool _isGlobal;
|
|
TreeNode _actionNode;
|
|
List<TreeNode> _treeNodes;
|
|
NameValueCollection _globalProperties;
|
|
NameValueCollection _actionProperties;
|
|
|
|
public IEnumerable<TreeNode> InnerParse(string source, NameValueCollection predefines = null)
|
|
{
|
|
_sr = new StringReader(_source = source);
|
|
|
|
_nextPos = 0;
|
|
_lineNum = 1;
|
|
_lineStartPos = 0;
|
|
_lineEndPos = 0;
|
|
|
|
_isGlobal = false;
|
|
_actionNode = null;
|
|
_treeNodes = new List<TreeNode>();
|
|
_globalProperties = predefines ?? new NameValueCollection();
|
|
_actionProperties = new NameValueCollection();
|
|
|
|
while (ReadLine(out string line))
|
|
{
|
|
ParseLine(line.TrimStart());
|
|
}
|
|
|
|
return _treeNodes;
|
|
}
|
|
|
|
private bool ReadLine(out string line)
|
|
{
|
|
line = null;
|
|
_lineNum++;
|
|
_lineStartPos = _nextPos;
|
|
|
|
while (_sr.Peek() > 0)
|
|
{
|
|
_lineEndPos = _nextPos++;
|
|
var ch = _sr.Read();
|
|
var lineBreak = ch == '\r';
|
|
if (lineBreak)
|
|
{
|
|
if (_sr.Peek() == '\n')
|
|
{
|
|
_nextPos++;
|
|
_sr.Read();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lineBreak = ch == '\n';
|
|
}
|
|
|
|
if (lineBreak)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_lineEndPos >= _lineStartPos)
|
|
{
|
|
line = _source.Substring(_lineStartPos, _lineEndPos - _lineStartPos).TrimEnd();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void ParseLine(string line)
|
|
{
|
|
if (string.IsNullOrEmpty(line) || line[0] == '#')
|
|
{
|
|
return;
|
|
}
|
|
|
|
var tag = new ParseInfo {
|
|
LineNum = _lineNum,
|
|
OriginalText = line,
|
|
ConvertedText = line,
|
|
StartPos = _lineStartPos,
|
|
EndPos = _lineEndPos
|
|
};
|
|
|
|
if (line[0] == '[')
|
|
{
|
|
_actionNode = new TreeNode(line) { Tag = tag };
|
|
_treeNodes.Add(_actionNode);
|
|
line = line.Trim(new[] { '[', ']' });
|
|
_isGlobal = line == "全局变量";
|
|
if (!_isGlobal && !Helper.ExistsAction(line))
|
|
{
|
|
_actionNode.ForeColor = System.Drawing.Color.Red;
|
|
tag.ErrorInfo = "没有找到对应的指令处理器";
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (_actionNode == null)
|
|
{
|
|
tag.ErrorInfo = "此处发生错误,脚本不会继续执行";
|
|
_actionNode = new TreeNode("缺失[]指令") {
|
|
Tag = tag,
|
|
ForeColor = System.Drawing.Color.Red
|
|
};
|
|
_treeNodes.Add(_actionNode);
|
|
}
|
|
|
|
var tn = new TreeNode {
|
|
Tag = tag
|
|
};
|
|
_actionNode.Nodes.Add(tn);
|
|
|
|
var index = line.IndexOf('=');
|
|
if (index < 0)
|
|
{
|
|
tn.Text = "无效行,忽略";
|
|
tn.ForeColor = System.Drawing.Color.Red;
|
|
return;
|
|
}
|
|
|
|
var left = line.Substring(0, index).TrimEnd();
|
|
if (left.Length < 1)
|
|
{
|
|
tn.Text = "无效行,忽略";
|
|
tn.ForeColor = System.Drawing.Color.Red;
|
|
return;
|
|
}
|
|
|
|
index++;
|
|
var right = line.Substring(index).TrimStart();
|
|
|
|
if (right.StartsWith("#"))
|
|
{
|
|
tn.Text = "注释说明,忽略";
|
|
tn.ForeColor = System.Drawing.Color.Red;
|
|
return;
|
|
}
|
|
|
|
if (right.StartsWith("'''"))
|
|
{
|
|
var startPos = _lineStartPos + index;
|
|
while (ReadLine(out string line2))
|
|
{
|
|
if (line2.EndsWith("'''"))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
right = _source.Substring(startPos, _lineEndPos - startPos).Trim().Trim('\'');
|
|
}
|
|
tag.OriginalText = right;
|
|
right = ConvertTemplateString(right);
|
|
if (right.Length > 0)
|
|
{
|
|
(_isGlobal ? _globalProperties : _actionProperties)[left] = right;
|
|
}
|
|
tn.Text = left + " =";
|
|
tag.ConvertedText = right;
|
|
tag.EndPos = _lineEndPos;
|
|
}
|
|
|
|
private string ConvertTemplateString(string str)
|
|
{
|
|
if (string.IsNullOrEmpty(str) || str.IndexOf("${") < 0)
|
|
{
|
|
return str;
|
|
}
|
|
|
|
return Regex.Replace(str, @"\$\{(.+?)\}", m =>
|
|
{
|
|
var name = m.Groups[1].Value;
|
|
return _actionProperties[name] ?? _globalProperties[name];
|
|
});
|
|
}
|
|
}
|
|
|
|
class ParseInfo
|
|
{
|
|
public int LineNum;
|
|
public int StartPos;
|
|
public int EndPos;
|
|
public string OriginalText;
|
|
public string ConvertedText;
|
|
public string ErrorInfo;
|
|
}
|
|
}
|