Files
zszq-trs/Tools/YLPublishTool/Parser.cs
T
2024-05-09 14:06:26 +08:00

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;
}
}