using Canon.Core.Abstractions; using Canon.Core.CodeGenerators; using Canon.Core.Enums; using Canon.Core.LexicalParser; using Canon.Core.SemanticParser; namespace Canon.Core.SyntaxNodes; public class OnNumberGeneratorEventArgs : EventArgs { public required NumberSemanticToken Token { get; init; } } public class OnVariableGeneratorEventArgs : EventArgs { public required Variable Variable { get; init; } } public class OnParethnesisGeneratorEventArgs : EventArgs { public required Expression Expression { get; init; } } public class OnProcedureCallGeneratorEventArgs : EventArgs { public required IdentifierSemanticToken ProcedureName { get; init; } public required ExpressionList Parameters { get; init; } } public class OnNotGeneratorEventArgs : EventArgs { public required Factor Factor { get; init; } } public class OnUminusGeneratorEventArgs : EventArgs { public required Factor Factor { get; init; } } public class Factor : NonTerminatedSyntaxNode { public override NonTerminatorType Type => NonTerminatorType.Factor; public override void PreVisit(SyntaxNodeVisitor visitor) { visitor.PreVisit(this); RaiseEvent(); } public override void PostVisit(SyntaxNodeVisitor visitor) { visitor.PostVisit(this); RaiseEvent(); } /// /// 使用数值产生式的事件 /// public event EventHandler? OnNumberGenerator; /// /// 使用括号产生式的事件 /// public event EventHandler? OnParethnesisGenerator; /// /// 使用变量产生式的事件 /// public event EventHandler? OnVariableGenerator; /// /// 使用过程调用产生式的事件 /// public event EventHandler? OnProcedureCallGenerator; /// /// 使用否定产生式的事件 /// public event EventHandler? OnNotGenerator; /// /// 使用负号产生式的事件 /// public event EventHandler? OnUminusGenerator; private PascalType? _factorType; public PascalType FactorType { get { if (_factorType is null) { throw new InvalidOperationException(); } return _factorType; } set { _factorType = value; } } public static Factor Create(List children) { return new Factor { Children = children }; } private void RaiseEvent() { if (Children.Count == 1) { //factor -> num if (Children[0].IsTerminated) { SemanticToken token = Children[0].Convert().Token; OnNumberGenerator?.Invoke(this, new OnNumberGeneratorEventArgs { Token = token.Convert() }); } // factor -> variable else { OnVariableGenerator?.Invoke(this, new OnVariableGeneratorEventArgs { Variable = Children[0].Convert() }); } } //factor -> ( expression ) else if (Children.Count == 3) { OnParethnesisGenerator?.Invoke(this, new OnParethnesisGeneratorEventArgs { Expression = Children[1].Convert() }); } //factor -> id ( expression ) else if (Children.Count == 4) { OnProcedureCallGenerator?.Invoke(this, new OnProcedureCallGeneratorEventArgs { ProcedureName = Children[0].Convert().Token.Convert(), Parameters = Children[2].Convert() }); } else { SemanticToken token = Children[0].Convert().Token; Factor factor = Children[1].Convert(); if (token.TokenType == SemanticTokenType.Keyword) { // factor -> not factor OnNotGenerator?.Invoke(this, new OnNotGeneratorEventArgs { Factor = factor }); } else { // factor -> uminus factor OnUminusGenerator?.Invoke(this, new OnUminusGeneratorEventArgs { Factor = factor }); } } OnNumberGenerator = null; OnVariableGenerator = null; OnParethnesisGenerator = null; OnProcedureCallGenerator = null; OnNotGenerator = null; OnUminusGenerator = null; } public override void GenerateCCode(CCodeBuilder builder) { if (Children.Count == 1) { //factor -> num if (Children[0].IsTerminated) { var token = Children[0].Convert().Token; if (token.TokenType == SemanticTokenType.Number) { builder.AddString(" " + token.LiteralValue); } } // factor -> variable else { Children[0].GenerateCCode(builder); } } //factor -> ( expression ) else if (Children.Count == 3) { builder.AddString(" ("); Children[1].GenerateCCode(builder); builder.AddString(")"); } //factor -> id ( expression ) else if (Children.Count == 4) { builder.AddString(" " + Children[0].Convert().Token.Convert() .IdentifierName); builder.AddString("("); Children[2].GenerateCCode(builder); builder.AddString(")"); } else { //factor -> not factor builder.AddString(" ("); if (Children[0].Convert().Token.TokenType == SemanticTokenType.Keyword) { builder.AddString("!"); } else { builder.AddString("-"); } Children[1].GenerateCCode(builder); builder.AddString(")"); } } }