新增赋值操作
This commit is contained in:
68
ExpressionElements/Assignment.cs
Normal file
68
ExpressionElements/Assignment.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using Flee.ExpressionElements.Base;
|
||||
using Flee.ExpressionElements.MemberElements;
|
||||
using Flee.InternalTypes;
|
||||
using Flee.PublicTypes;
|
||||
|
||||
namespace Flee.ExpressionElements
|
||||
{
|
||||
internal class AssignmentElement : ExpressionElement
|
||||
{
|
||||
private readonly string _variableName;
|
||||
private readonly ExpressionElement _valueExpression;
|
||||
private readonly ExpressionContext _context;
|
||||
|
||||
public AssignmentElement(string variableName, ExpressionElement valueExpression, ExpressionContext context)
|
||||
{
|
||||
_variableName = variableName;
|
||||
_valueExpression = valueExpression;
|
||||
_context = context;
|
||||
|
||||
// 检查变量是否存在
|
||||
if (!_context.Variables.ContainsKey(_variableName))
|
||||
{
|
||||
this.ThrowCompileException("UndefinedVariable", CompileExceptionReason.UndefinedName, _variableName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Emit(FleeILGenerator ilg, IServiceProvider services)
|
||||
{
|
||||
// 首先计算右侧表达式的值
|
||||
_valueExpression.Emit(ilg, services);
|
||||
|
||||
// 获取一个临时本地变量来存储值
|
||||
var valueType = _valueExpression.ResultType;
|
||||
int tempIndex = ilg.GetTempLocalIndex(valueType);
|
||||
|
||||
// 存储值到临时变量
|
||||
Utility.EmitStoreLocal(ilg, tempIndex);
|
||||
|
||||
// 加载变量集合 (arg 2)
|
||||
ilg.Emit(System.Reflection.Emit.OpCodes.Ldarg_2); // 加载 VariableCollection
|
||||
|
||||
// 加载变量名
|
||||
ilg.Emit(System.Reflection.Emit.OpCodes.Ldstr, _variableName);
|
||||
|
||||
// 加载要设置的值
|
||||
Utility.EmitLoadLocal(ilg, tempIndex);
|
||||
|
||||
// 如果值类型是值类型,需要装箱
|
||||
if (valueType.IsValueType)
|
||||
{
|
||||
ilg.Emit(System.Reflection.Emit.OpCodes.Box, valueType);
|
||||
}
|
||||
|
||||
// 调用 Variables[string] 的 setter
|
||||
var indexerSetter = typeof(VariableCollection).GetProperty("Item", new Type[] { typeof(string) }).GetSetMethod();
|
||||
ilg.Emit(System.Reflection.Emit.OpCodes.Callvirt, indexerSetter);
|
||||
|
||||
// 加载返回值到栈上
|
||||
Utility.EmitLoadLocal(ilg, tempIndex);
|
||||
}
|
||||
|
||||
public override Type ResultType
|
||||
{
|
||||
get { return _valueExpression.ResultType; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -589,6 +589,38 @@ namespace Flee.Parsing
|
||||
return node;
|
||||
}
|
||||
|
||||
public override Node ExitAssign(Token node)
|
||||
{
|
||||
node.AddValue("=");
|
||||
return node;
|
||||
}
|
||||
|
||||
public override Node ExitAssignmentExpression(Production node)
|
||||
{
|
||||
// 获取子节点:标识符和表达式
|
||||
var children = this.GetChildValues(node);
|
||||
if (children.Count != 3) // IDENTIFIER, ASSIGN, Expression
|
||||
{
|
||||
throw new InvalidOperationException("Assignment expression must have exactly 3 children");
|
||||
}
|
||||
|
||||
string variableName = (string)children[0];
|
||||
ExpressionElement valueExpression = (ExpressionElement)children[2];
|
||||
|
||||
// 获取表达式上下文
|
||||
var context = _myServices.GetService(typeof(ExpressionContext)) as ExpressionContext;
|
||||
if (context == null)
|
||||
{
|
||||
throw new InvalidOperationException("ExpressionContext not found in services");
|
||||
}
|
||||
|
||||
// 创建赋值表达式元素
|
||||
var assignmentElement = new AssignmentElement(variableName, valueExpression, context);
|
||||
node.AddValue(assignmentElement);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
public override void Child(Production node, Node child)
|
||||
{
|
||||
base.Child(node, child);
|
||||
|
@@ -1,9 +1,9 @@
|
||||
%header%
|
||||
|
||||
DESCRIPTION = "A general expression grammar"
|
||||
AUTHOR = "Eugene Ciloci"
|
||||
VERSION = "1.0"
|
||||
DATE = "May 2007"
|
||||
DESCRIPTION = "A general expression grammar with assignment support"
|
||||
AUTHOR = "Eugene Ciloci (Modified By LiuBai)"
|
||||
VERSION = "2.0"
|
||||
DATE = "October 2025"
|
||||
|
||||
GRAMMARTYPE = "LL"
|
||||
CASESENSITIVE = "False"
|
||||
@@ -71,10 +71,13 @@ DATETIME = <<#[^#]+#>>
|
||||
// Special Functions
|
||||
IF = "if"
|
||||
CAST = "cast"
|
||||
ASSIGN = "="
|
||||
|
||||
%productions%
|
||||
|
||||
Expression = XorExpression;
|
||||
Expression = AssignmentExpression | XorExpression;
|
||||
|
||||
AssignmentExpression = IDENTIFIER "=" XorExpression;
|
||||
|
||||
XorExpression = OrExpression {XOR OrExpression};
|
||||
|
||||
|
@@ -284,6 +284,10 @@
|
||||
case (int)ExpressionConstants.EXPRESSION_GROUP:
|
||||
EnterExpressionGroup((Production)node);
|
||||
|
||||
break;
|
||||
case (int)ExpressionConstants.ASSIGNMENT_EXPRESSION:
|
||||
EnterAssignmentExpression((Production)node);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -414,6 +418,9 @@
|
||||
case (int)ExpressionConstants.CAST:
|
||||
|
||||
return ExitCast((Token)node);
|
||||
case (int)ExpressionConstants.ASSIGN:
|
||||
|
||||
return ExitAssign((Token)node);
|
||||
case (int)ExpressionConstants.EXPRESSION:
|
||||
|
||||
return ExitExpression((Production)node);
|
||||
@@ -501,6 +508,9 @@
|
||||
case (int)ExpressionConstants.EXPRESSION_GROUP:
|
||||
|
||||
return ExitExpressionGroup((Production)node);
|
||||
case (int)ExpressionConstants.ASSIGNMENT_EXPRESSION:
|
||||
|
||||
return ExitAssignmentExpression((Production)node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@@ -629,6 +639,10 @@
|
||||
case (int)ExpressionConstants.EXPRESSION_GROUP:
|
||||
ChildExpressionGroup(node, child);
|
||||
|
||||
break;
|
||||
case (int)ExpressionConstants.ASSIGNMENT_EXPRESSION:
|
||||
ChildAssignmentExpression(node, child);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1391,5 +1405,24 @@
|
||||
{
|
||||
node.AddChild(child);
|
||||
}
|
||||
|
||||
public virtual Node ExitAssign(Token node)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public virtual void EnterAssignmentExpression(Production node)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual Node ExitAssignmentExpression(Production node)
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
public virtual void ChildAssignmentExpression(Production node, Node child)
|
||||
{
|
||||
node.AddChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,7 @@
|
||||
DATETIME = 1038,
|
||||
IF = 1039,
|
||||
CAST = 1040,
|
||||
ASSIGN = 1041,
|
||||
EXPRESSION = 2001,
|
||||
XOR_EXPRESSION = 2002,
|
||||
OR_EXPRESSION = 2003,
|
||||
@@ -73,6 +74,7 @@
|
||||
ARGUMENT_LIST = 2026,
|
||||
LITERAL_EXPRESSION = 2027,
|
||||
BOOLEAN_LITERAL_EXPRESSION = 2028,
|
||||
EXPRESSION_GROUP = 2029
|
||||
EXPRESSION_GROUP = 2029,
|
||||
ASSIGNMENT_EXPRESSION = 2030
|
||||
}
|
||||
}
|
@@ -51,6 +51,17 @@ namespace Flee.Parsing
|
||||
|
||||
pattern = new ProductionPattern(Convert.ToInt32(ExpressionConstants.EXPRESSION), "Expression");
|
||||
alt = new ProductionPatternAlternative();
|
||||
alt.AddProduction(Convert.ToInt32(ExpressionConstants.ASSIGNMENT_EXPRESSION), 1, 1);
|
||||
pattern.AddAlternative(alt);
|
||||
alt = new ProductionPatternAlternative();
|
||||
alt.AddProduction(Convert.ToInt32(ExpressionConstants.XOR_EXPRESSION), 1, 1);
|
||||
pattern.AddAlternative(alt);
|
||||
AddPattern(pattern);
|
||||
|
||||
pattern = new ProductionPattern(Convert.ToInt32(ExpressionConstants.ASSIGNMENT_EXPRESSION), "AssignmentExpression");
|
||||
alt = new ProductionPatternAlternative();
|
||||
alt.AddToken(Convert.ToInt32(ExpressionConstants.IDENTIFIER), 1, 1);
|
||||
alt.AddToken(Convert.ToInt32(ExpressionConstants.ASSIGN), 1, 1);
|
||||
alt.AddProduction(Convert.ToInt32(ExpressionConstants.XOR_EXPRESSION), 1, 1);
|
||||
pattern.AddAlternative(alt);
|
||||
AddPattern(pattern);
|
||||
|
@@ -150,6 +150,9 @@ namespace Flee.Parsing
|
||||
|
||||
pattern = new TokenPattern(Convert.ToInt32(ExpressionConstants.CAST), "CAST", TokenPattern.PatternType.STRING, "cast");
|
||||
AddPattern(pattern);
|
||||
|
||||
pattern = new TokenPattern(Convert.ToInt32(ExpressionConstants.ASSIGN), "ASSIGN", TokenPattern.PatternType.STRING, "=");
|
||||
AddPattern(pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user