新增赋值操作

This commit is contained in:
2025-10-09 16:16:59 +08:00
parent de8b682330
commit c9e2493796
7 changed files with 158 additions and 6 deletions

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

View File

@@ -589,6 +589,38 @@ namespace Flee.Parsing
return node; 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) public override void Child(Production node, Node child)
{ {
base.Child(node, child); base.Child(node, child);

View File

@@ -1,9 +1,9 @@
%header% %header%
DESCRIPTION = "A general expression grammar" DESCRIPTION = "A general expression grammar with assignment support"
AUTHOR = "Eugene Ciloci" AUTHOR = "Eugene Ciloci (Modified By LiuBai)"
VERSION = "1.0" VERSION = "2.0"
DATE = "May 2007" DATE = "October 2025"
GRAMMARTYPE = "LL" GRAMMARTYPE = "LL"
CASESENSITIVE = "False" CASESENSITIVE = "False"
@@ -71,10 +71,13 @@ DATETIME = <<#[^#]+#>>
// Special Functions // Special Functions
IF = "if" IF = "if"
CAST = "cast" CAST = "cast"
ASSIGN = "="
%productions% %productions%
Expression = XorExpression; Expression = AssignmentExpression | XorExpression;
AssignmentExpression = IDENTIFIER "=" XorExpression;
XorExpression = OrExpression {XOR OrExpression}; XorExpression = OrExpression {XOR OrExpression};

View File

@@ -284,6 +284,10 @@
case (int)ExpressionConstants.EXPRESSION_GROUP: case (int)ExpressionConstants.EXPRESSION_GROUP:
EnterExpressionGroup((Production)node); EnterExpressionGroup((Production)node);
break;
case (int)ExpressionConstants.ASSIGNMENT_EXPRESSION:
EnterAssignmentExpression((Production)node);
break; break;
} }
} }
@@ -414,6 +418,9 @@
case (int)ExpressionConstants.CAST: case (int)ExpressionConstants.CAST:
return ExitCast((Token)node); return ExitCast((Token)node);
case (int)ExpressionConstants.ASSIGN:
return ExitAssign((Token)node);
case (int)ExpressionConstants.EXPRESSION: case (int)ExpressionConstants.EXPRESSION:
return ExitExpression((Production)node); return ExitExpression((Production)node);
@@ -501,6 +508,9 @@
case (int)ExpressionConstants.EXPRESSION_GROUP: case (int)ExpressionConstants.EXPRESSION_GROUP:
return ExitExpressionGroup((Production)node); return ExitExpressionGroup((Production)node);
case (int)ExpressionConstants.ASSIGNMENT_EXPRESSION:
return ExitAssignmentExpression((Production)node);
} }
return node; return node;
} }
@@ -629,6 +639,10 @@
case (int)ExpressionConstants.EXPRESSION_GROUP: case (int)ExpressionConstants.EXPRESSION_GROUP:
ChildExpressionGroup(node, child); ChildExpressionGroup(node, child);
break;
case (int)ExpressionConstants.ASSIGNMENT_EXPRESSION:
ChildAssignmentExpression(node, child);
break; break;
} }
} }
@@ -1391,5 +1405,24 @@
{ {
node.AddChild(child); 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);
}
} }
} }

View File

@@ -45,6 +45,7 @@
DATETIME = 1038, DATETIME = 1038,
IF = 1039, IF = 1039,
CAST = 1040, CAST = 1040,
ASSIGN = 1041,
EXPRESSION = 2001, EXPRESSION = 2001,
XOR_EXPRESSION = 2002, XOR_EXPRESSION = 2002,
OR_EXPRESSION = 2003, OR_EXPRESSION = 2003,
@@ -73,6 +74,7 @@
ARGUMENT_LIST = 2026, ARGUMENT_LIST = 2026,
LITERAL_EXPRESSION = 2027, LITERAL_EXPRESSION = 2027,
BOOLEAN_LITERAL_EXPRESSION = 2028, BOOLEAN_LITERAL_EXPRESSION = 2028,
EXPRESSION_GROUP = 2029 EXPRESSION_GROUP = 2029,
ASSIGNMENT_EXPRESSION = 2030
} }
} }

View File

@@ -51,6 +51,17 @@ namespace Flee.Parsing
pattern = new ProductionPattern(Convert.ToInt32(ExpressionConstants.EXPRESSION), "Expression"); pattern = new ProductionPattern(Convert.ToInt32(ExpressionConstants.EXPRESSION), "Expression");
alt = new ProductionPatternAlternative(); 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); alt.AddProduction(Convert.ToInt32(ExpressionConstants.XOR_EXPRESSION), 1, 1);
pattern.AddAlternative(alt); pattern.AddAlternative(alt);
AddPattern(pattern); AddPattern(pattern);

View File

@@ -150,6 +150,9 @@ namespace Flee.Parsing
pattern = new TokenPattern(Convert.ToInt32(ExpressionConstants.CAST), "CAST", TokenPattern.PatternType.STRING, "cast"); pattern = new TokenPattern(Convert.ToInt32(ExpressionConstants.CAST), "CAST", TokenPattern.PatternType.STRING, "cast");
AddPattern(pattern); AddPattern(pattern);
pattern = new TokenPattern(Convert.ToInt32(ExpressionConstants.ASSIGN), "ASSIGN", TokenPattern.PatternType.STRING, "=");
AddPattern(pattern);
} }
} }
} }