Удален _ParsePABC1

This commit is contained in:
Mikhalkovich Stanislav 2026-01-02 12:16:36 +03:00
parent eaebd483b8
commit 7fc176f854
29 changed files with 0 additions and 1279 deletions

View file

@ -1,40 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxVisitors", "ParsePABC1\SyntaxVisitors.csproj", "{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTree", "..\SyntaxTree\SyntaxTree.csproj", "{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YieldDesugarTest", "YieldDesugarTest\YieldDesugarTest.csproj", "{9EBC62C6-3092-4E9D-940E-476D332E0951}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTreeChanger", "..\SyntaxTreeChanger\SyntaxTreeChanger.csproj", "{F10A5330-DCF4-4533-877C-7B1B1BE23884}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}.Release|Any CPU.Build.0 = Release|Any CPU
{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}.Release|Any CPU.Build.0 = Release|Any CPU
{9EBC62C6-3092-4E9D-940E-476D332E0951}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9EBC62C6-3092-4E9D-940E-476D332E0951}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9EBC62C6-3092-4E9D-940E-476D332E0951}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9EBC62C6-3092-4E9D-940E-476D332E0951}.Release|Any CPU.Build.0 = Release|Any CPU
{F10A5330-DCF4-4533-877C-7B1B1BE23884}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F10A5330-DCF4-4533-877C-7B1B1BE23884}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F10A5330-DCF4-4533-877C-7B1B1BE23884}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F10A5330-DCF4-4533-877C-7B1B1BE23884}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

View file

@ -1,78 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class BaseChangeVisitor : CollectUpperNodesVisitor
{
public override void DefaultVisit(syntax_tree_node n)
{
// Элементы списков - с конца в начало чтобы можно было эти элементы изменять по ходу (удалять/вставлять/заменять один несколькими)
var Сount = n.subnodes_count;
var СountWithoutListElements = n.subnodes_without_list_elements_count;
for (var i = 0; i < СountWithoutListElements; i++)
ProcessNode(n[i]);
for (var i = Сount - 1; i >= СountWithoutListElements; i--) // в обратном порядке
ProcessNode(n[i]);
}
public void Replace(syntax_tree_node from, syntax_tree_node to)
{
var upper = UpperNode();
if (upper == null)
throw new Exception("У корневого элемента нельзя получить UpperNode");
upper.Replace(from, to);
}
public T UpperNodeAs<T>(int up = 1) where T : syntax_tree_node
{
var stl = UpperNode(up) as T;
if (stl == null)
throw new Exception("Элемент вложен не в " + typeof(T));
return stl;
}
public bool DeleteInIdentList(ident id)
{
var idl = UpperNodeAs<ident_list>();
return idl.Remove(id);
}
public bool DeleteInStatementList(statement st)
{
var stl = UpperNodeAs<statement_list>();
return stl.Remove(st);
}
public static IEnumerable<statement> SeqStatements(params statement[] seq)
{
var l = new List<statement>();
foreach (var st in seq)
if (st is statement_list)
l.AddRange((st as statement_list).list);
else l.Add(st);
return l;
}
public void ReplaceStatement(statement from, statement to)
{
var stl = UpperNodeAs<statement_list>();
stl.Replace(from, to);
}
public void ReplaceStatement(statement from, IEnumerable<statement> to)
{
var stl = UpperNodeAs<statement_list>();
stl.Replace(from, to);
}
}
}

View file

@ -1,27 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class BaseEnterExitVisitor : WalkingVisitorNew
{
public BaseEnterExitVisitor()
{
OnEnter = Enter;
OnLeave = Exit;
}
public virtual void Enter(syntax_tree_node st)
{
}
public virtual void Exit(syntax_tree_node st)
{
}
}
}

View file

@ -1,61 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class CollectUpperNamespacesVisitor : CollectUpperNodesVisitor
{
protected List<declaration> list = new List<declaration>();
public bool PrintInfo = true;
public override void Enter(syntax_tree_node st)
{
base.Enter(st);
if (st is procedure_definition || st is class_definition)
{
list.Add(st as declaration);
if (PrintInfo)
Console.Write("+: "+st.GetType().Name);
}
}
public override void Exit(syntax_tree_node st)
{
if (st is procedure_definition || st is class_definition)
{
if (PrintInfo)
Console.WriteLine("-: " + st.GetType().Name);
list.RemoveAt(list.Count - 1);
}
base.Exit(st);
}
public override void visit(procedure_definition p)
{
if (PrintInfo)
Console.WriteLine(" " + p.proc_header.name.meth_name);
var ld = new FindLocalDefsVisitor();
p.visit(ld);
base.visit(p);
}
public override void visit(class_definition cl)
{
type_declarations tds = UpperNode(2) as type_declarations;
if (PrintInfo)
{
var f = tds.types_decl.Find(td => td.type_def == cl);
Console.WriteLine(" " + f.type_name);
}
base.visit(cl);
}
}
}

View file

@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class CollectUpperNodesVisitor : BaseEnterExitVisitor
{
protected List<syntax_tree_node> listNodes = new List<syntax_tree_node>();
public syntax_tree_node CurrentNode
{
get
{
return listNodes[listNodes.Count - 1];
}
}
public syntax_tree_node UpperNode(int up = 1)
{
return listNodes[listNodes.Count - 1 - up];
}
public override void Enter(syntax_tree_node st)
{
listNodes.Add(st);
}
public override void Exit(syntax_tree_node st)
{
listNodes.RemoveAt(listNodes.Count - 1);
}
}
}

View file

@ -1,62 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler.Errors;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
class Program
{
static syntax_tree_node ParseFile(string fname)
{
Compiler c = new Compiler();
var err = new List<Error>();
var txt = System.IO.File.ReadAllText(fname);
var cu = c.ParsersController.Compile(fname, txt, err, PascalABCCompiler.Parsers.ParseMode.ForFormatter);
if (cu == null)
{
Console.WriteLine("Не распарсилось");
}
return cu;
}
static void Main(string[] args)
{
var cu = ParseFile(@"d:\w5\e.pas");
if (cu == null)
return;
//CodeFormatters.CodeFormatter cf = new CodeFormatters.CodeFormatter(0);
//txt = cf.FormatTree(txt, cu as compilation_unit, 0, 0);
cu.visit(new ChangeWhileVisitor());
cu.visit(new DeleteRedundantBeginEnds());
/*cu.visit(new CollectUpperNamespacesVisitor());
var allv = new AllVarsInProcYields();
cu.visit(allv);
allv.PrintDict();*/
/*var cnt = new CountNodesVisitor();
cu.visit(cnt);
cnt.PrintSortedByValue();*/
var ld = new List<string>();
ld.Add("p1");
var dld = new DeleteLocalDefs(ld);
cu.visit(dld);
cu.visit(new SimplePrettyPrinterVisitor());
}
}
}

View file

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Управление общими сведениями о сборке осуществляется с помощью
// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
// связанные со сборкой.
[assembly: AssemblyTitle("ParsePABC1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ParsePABC1")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми
// для COM-компонентов. Если требуется обратиться к типу в этой сборке через
// COM, задайте атрибуту ComVisible значение TRUE для этого типа.
[assembly: ComVisible(false)]
// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
[assembly: Guid("fa30eefc-3fcc-45a3-8b6f-465b1a5c17ba")]
// Сведения о версии сборки состоят из следующих четырех значений:
//
// Основной номер версии
// Дополнительный номер версии
// Номер сборки
// Редакция
//
// Можно задать все значения или принять номера сборки и редакции по умолчанию
// используя "*", как показано ниже:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -1,44 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class CountNodesVisitor : BaseEnterExitVisitor
{
public Dictionary<System.Type, int> d = new Dictionary<System.Type, int>();
public int exprcount,statcount;
public override void Enter(syntax_tree_node st)
{
if (d.ContainsKey(st.GetType()))
d[st.GetType()] += 1;
else d[st.GetType()] = 1;
if (st is expression)
exprcount++;
if (st is statement)
statcount++;
}
public void PrintSortedByValue()
{
var q = d.Select(x => new { x.Key, x.Value }).OrderByDescending(y => y.Value);
foreach (var a in q)
Console.WriteLine("{0}: {1} ", a.Key.Name, a.Value);
Console.WriteLine();
Console.WriteLine("Expressions Count: {0}", exprcount);
Console.WriteLine("Statements Count: {0}", statcount);
}
public void Print()
{
foreach (var a in d)
Console.WriteLine("{0}: {1} ", a.Key.Name, a.Value);
}
}
}

View file

@ -1,36 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler.Errors;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class DeleteRedundantBeginEnds : BaseChangeVisitor
{
public override void Exit(syntax_tree_node st)
{
var stl = st as statement_list;
if (stl != null && UpperNode() is statement_list)
ReplaceStatement(stl, stl.subnodes);
var lst = st as labeled_statement;
if (lst != null)
{
var sttl = lst.to_statement as statement_list;
if (sttl != null)
{
sttl.subnodes[0] = new labeled_statement(lst.label_name, sttl.subnodes[0]); // а если [0] элемента вообще нет?
ReplaceStatement(lst,sttl.subnodes);
}
}
base.Exit(st);
}
}
}

View file

@ -1,209 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler.Errors;
using PascalABCCompiler.PCU;
using PascalABCCompiler.SemanticTreeConverters;
using System.CodeDom.Compiler;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class SimplePrettyPrinterVisitor : WalkingVisitorNew
{
int off = 0;
bool printNodeType = false;
public static SimplePrettyPrinterVisitor New
{
get { return new SimplePrettyPrinterVisitor(); }
}
public SimplePrettyPrinterVisitor()
{
OnEnter = Enter;
OnLeave = Exit;
}
public void Println(string s)
{
Console.Write(new string(' ', off));
Console.WriteLine(s);
}
public void Print(string s)
{
Console.Write(new string(' ', off));
Console.Write(s);
}
public void PrintNoOffset(string s)
{
Console.Write(s);
}
public void PrintlnNoOffset(string s)
{
Console.WriteLine(s);
}
public void PrintlnNode(syntax_tree_node st)
{
if (printNodeType)
Console.Write(st.GetType().Name + ": ");
Console.WriteLine(new string(' ', off)+st);
}
public virtual void Enter(syntax_tree_node st)
{
if (st is statement_list)
{
Println("begin");
off += 2;
}
else if (st is type_declarations) // надо в visit и самому всё обрабатывать
{
var tds = st is type_declarations;
Println("type ");
off += 2;
}
else if (st is case_variant)
{
var td = st as case_variant;
Println(td.conditions.ToString()+": ");
off += 2;
//ProcessNode(td.type_def);
//visitNode = false;
}
else if (st is type_declaration)
{
var td = st as type_declaration;
Print(td.type_name + " = ");
ProcessNode(td.type_def);
visitNode = false;
}
else if (st is class_definition)
{
var cd = st as class_definition;
PrintNoOffset("class");
if (cd.class_parents != null && cd.class_parents.types.Count > 0)
{
PrintlnNoOffset("(" + cd.class_parents.ToString() + ")");
}
else
PrintlnNoOffset("");
off += 2;
ProcessNode(cd.body);
visitNode = false;
}
else if (st is access_modifer_node)
{
var am = st as access_modifer_node;
Println(am.access_level.ToString());
}
else if (st is variable_definitions)
{
var vds = st as variable_definitions;
Println("var");
off += 2;
}
else if (st is var_def_statement)
{
var vds = st as var_def_statement;
Println(vds.ToString());
}
else if (st is empty_statement || st is declarations || st is block || st is class_body || st is class_members || st is case_variants || st is program_module)
{
}
else if (st is if_node)
{
var ifn = st as if_node;
Println("if " + ifn.condition.ToString() + " then");
off += 2;
ProcessNode(ifn.then_body);
if (ifn.else_body == null)
{
visitNode = false;
return;
}
off -= 2;
Println("else ");
off += 2;
ProcessNode(ifn.else_body);
visitNode = false;
}
else if (st is while_node)
{
var wn = st as while_node;
Println("while " + wn.expr.ToString() + " do");
off += 2;
}
else if (st is case_node)
{
var cn = st as case_node;
Println("case " + cn.param.ToString() + " of");
off += 2;
}
else if (st is labeled_statement)
{
var lst = st as labeled_statement;
Println(lst.label_name.name + ": ");
ProcessNode(lst.to_statement);
visitNode = false;
}
else if (st is var_statement || st is procedure_header)
{
Println(st.ToString());
visitNode = false;
}
else if (st is procedure_definition)
{
Println("");
}
else if (st is statement || st is variable_definitions || st is label_definitions)
{
PrintlnNode(st);
if (st is labeled_statement)
visitNode = false;
}
else if (st is token_info)
{
var s = st.ToString();
if (s == "begin" || s == "end")
return;
PrintlnNode(st);
}
else
{
var q = st.GetType().GetMethod("ToString", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
if (q == null)
Println(st.GetType().Name);
}
}
public virtual void Exit(syntax_tree_node st)
{
if (st is statement_list)
{
off -= 2;
Println("end");
}
else if (st is while_node || st is if_node || st is type_declarations || st is variable_definitions || st is case_variant)
{
off -= 2;
}
else if (st is class_definition || st is case_node)
{
off -= 2;
Println("end;");
}
}
}
}

View file

@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class DeleteAllLocalDefs : BaseChangeVisitor
{
public List<var_def_statement> LocalDeletedDefs = new List<var_def_statement>(); // все локальные описания
public HashSet<string> LocalDeletedDefsNames = new HashSet<string>(); // их имена - для быстрого поиска
public DeleteAllLocalDefs() // надо запускать этот визитор начиная с корня подпрограммы
{
}
public override void visit(var_statement vs) // локальные описания внутри процедуры
{
LocalDeletedDefs.Add(vs.var_def);
DeleteInStatementList(vs);
LocalDeletedDefsNames.UnionWith(vs.var_def.vars.idents.Select(id => id.name));
}
public override void visit(variable_definitions vd)
{
foreach (var v in vd.list)
{
LocalDeletedDefs.Add(v);
LocalDeletedDefsNames.UnionWith(v.vars.idents.Select(id => id.name));
}
var d = UpperNodeAs<declarations>();
d.defs.Remove(vd); // может ли остаться список declarations пустым?
}
// еще - не заходить в лямбды
}
}

View file

@ -1,72 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class DeleteLocalDefs : BaseChangeVisitor
{
public List<var_def_statement> LocalDeletedIds = new List<var_def_statement>();
public List<var_def_statement> BlockDeletedIds = new List<var_def_statement>();
public HashSet<string> idsToDelete;
public HashSet<string> deletedIdsToDeleteInLocalScope = new HashSet<string>(); // одно множество и на Local и на Block
public DeleteLocalDefs(HashSet<string> ids) // надо запускать этот визитор начиная с корня подпрограммы
{
idsToDelete = ids;
}
public override void visit(var_statement vs)
{
var idents = vs.var_def.vars.idents;
var IdentsToDeleteInVarDef = idents.FindAll(id => idsToDelete.Contains(id.name)); // найти в операторе все идентификаторы для удаления
if (IdentsToDeleteInVarDef.Count != 0)
{
deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id => id.name)); // добавить те идентификаторы, которые мы удаляем из данного описания
LocalDeletedIds.Add(new var_def_statement(new ident_list(IdentsToDeleteInVarDef), vs.var_def.vars_type, vs.var_def.inital_value)); // добавить описание из удаленных в данном разделе описаний идентификаторов
idents.RemoveAll(id => idsToDelete.Contains(id.name)); // удалить в операторе все идентификаторы для удаления
idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope);
if (idents.Count == 0) // то и весь var_statement надо убить
this.DeleteInStatementList(vs);
}
// Здесь мы не обрабатываем вложенный var_def_statement, поэтому когда мы будем обрабатывать его в другом visit, то это будут переменные до beginа подпрограммы или основной программы
}
public override void visit(var_def_statement vd)
{
var idents = vd.vars.idents;
var IdentsToDeleteInVarDef = idents.FindAll(id => idsToDelete.Contains(id.name)); // найти в операторе все идентификаторы для удаления
if (IdentsToDeleteInVarDef.Count != 0)
{
deletedIdsToDeleteInLocalScope.UnionWith(IdentsToDeleteInVarDef.Select(id => id.name)); // добавить те идентификаторы, которые мы удаляем из данного описания
BlockDeletedIds.Add(new var_def_statement(new ident_list(IdentsToDeleteInVarDef), vd.vars_type, vd.inital_value)); // добавить описание из удаленных в данном разделе описаний идентификаторов
idents.RemoveAll(id => idsToDelete.Contains(id.name)); // удалить в операторе все идентификаторы для удаления
if (idents.Count == 0)
{
// Выше - variable_definitions, еще выше - declarations
var uvdsl = UpperNodeAs<variable_definitions>();
uvdsl.var_definitions.Remove(vd);
if (uvdsl.var_definitions.Count == 0)
{
var d = UpperNodeAs<declarations>(2);
d.defs.Remove(uvdsl);
}
}
}
}
public void AfterProcTraverse()
{
idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope); // исключаем из множества удаляемых идентификаторов те, которые мы нашли и удалили в секции var_statement. Это надо делать не для каждого описания, а в конце подпрограммы после удаления из всех секций var_statement
}
}
}

View file

@ -1,93 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler.Errors;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors
{
public class LoweringVisitor : BaseChangeVisitor
{
public static LoweringVisitor New
{
get { return new LoweringVisitor(); }
}
int varnum = 0;
public string newVarName()
{
varnum++;
return "<>varLV" + varnum.ToString();
}
public static void Accept(procedure_definition pd)
{
New.ProcessNode(pd);
}
public override void Enter(syntax_tree_node st)
{
base.Enter(st);
if (!(st is procedure_definition || st is block || st is statement_list || st is case_node || st is for_node || st is foreach_stmt || st is if_node || st is repeat_node || st is while_node || st is with_statement || st is try_stmt || st is lock_stmt))
{
visitNode = false;
}
}
public override void visit(while_node wn)
{
ProcessNode(wn.statements);
var b = HasStatementVisitor<yield_node>.Has(wn);
if (!b)
return;
var gt1 = goto_statement.New;
var gt2 = goto_statement.New;
var if0 = new if_node(un_expr.Not(wn.expr), gt1);
var lb2 = new labeled_statement(gt2.label, if0);
var lb1 = new labeled_statement(gt1.label);
ReplaceStatement(wn, SeqStatements(lb2, wn.statements, gt2, lb1));
// в declarations ближайшего блока добавить описание labels
block bl = listNodes.FindLast(x => x is block) as block;
bl.defs.Add(new label_definitions(gt1.label, gt2.label));
}
public override void visit(for_node fn)
{
ProcessNode(fn.statements);
var b = HasStatementVisitor<yield_node>.Has(fn);
if (!b)
return;
var gt1 = goto_statement.New;
var gt2 = goto_statement.New;
var endtemp = new ident(newVarName());
var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value);
var ass2 = new var_statement(endtemp, fn.type_name, fn.finish_value);
var if0 = new if_node(bin_expr.Greater(fn.loop_variable, fn.finish_value), gt1);
var lb2 = new labeled_statement(gt2.label, if0);
var lb1 = new labeled_statement(gt1.label);
var Inc = new procedure_call(new method_call(new ident("Inc"),new expression_list(fn.loop_variable)));
ReplaceStatement(fn, SeqStatements(ass1,ass2,lb2, fn.statements, Inc, gt2, lb1));
// в declarations ближайшего блока добавить описание labels
block bl = listNodes.FindLast(x => x is block) as block;
bl.defs.Add(new label_definitions(gt1.label, gt2.label));
}
}
}

View file

@ -1,250 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
using PascalABCCompiler.ParserTools;
using PascalABCCompiler.Errors;
namespace SyntaxVisitors
{
public static class Consts
{
public static string Current = "<>current";
public static string State = "<>state";
}
public class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor
{
int clnum = 0;
public string newClassName()
{
clnum++;
return "clyield#" + clnum.ToString();
}
public FindMainIdentsVisitor mids; // захваченные переменные процедуры по всем её yield
public int countNodesVisited;
public bool hasYields = false;
public static ProcessYieldCapturedVarsVisitor New
{
get { return new ProcessYieldCapturedVarsVisitor(); }
}
public ProcessYieldCapturedVarsVisitor()
{
//PrintInfo = false;
}
public override void Enter(syntax_tree_node st)
{
base.Enter(st);
countNodesVisited++;
// сокращение обходимых узлов. Как сделать фильтр по тем узлам, которые необходимо обходить? Например, все операторы (без выражений и описаний), все описания (без операторов)
if (st is assign || st is var_def_statement || st is procedure_call || st is procedure_header || st is expression)
{
visitNode = false; // фильтр - куда не заходить
}
}
type_declarations GenClassesForYield(procedure_definition pd, IEnumerable<var_def_statement> fields)
{
var fh = (pd.proc_header as function_header);
if (fh == null)
throw new SyntaxError("Only functions can contain yields", "", pd.proc_header.source_context, pd.proc_header);
var seqt = fh.return_type as sequence_type;
if (seqt == null)
throw new SyntaxError("Functions with yields must return sequences", "", fh.return_type.source_context, fh.return_type);
// Теперь на месте функции генерируем класс
// Захваченные переменные
var cm = class_members.Public;
foreach (var m in fields)
cm.Add(m);
// Параметры функции
List<ident> lid = new List<ident>();
var pars = fh.parameters;
if (pars != null)
foreach (var ps in pars.params_list)
{
if (ps.param_kind != parametr_kind.none)
throw new SyntaxError("Parameters of functions with yields must not have 'var', 'const' or 'params' modifier", "", pars.source_context, pars);
if (ps.inital_value != null)
throw new SyntaxError("Parameters of functions with yields must not have initial values", "", pars.source_context, pars);
var_def_statement vds = new var_def_statement(ps.idents, ps.vars_type);
cm.Add(vds); // все параметры функции делаем полями класса
lid.AddRange(vds.vars.idents);
}
var stels = seqt.elements_type;
// Системные поля и методы для реализации интерфейса IEnumerable
cm.Add(new var_def_statement(Consts.State, "integer"),
new var_def_statement(Consts.Current, stels),
procedure_definition.EmptyDefaultConstructor,
new procedure_definition("Reset"),
new procedure_definition("MoveNext", "boolean", pd.proc_body),
new procedure_definition("get_Current", "object", new assign("Result", Consts.Current)),
new procedure_definition("GetEnumerator", "System.Collections.IEnumerator", new assign("Result", "Self"))
);
var className = newClassName();
var classNameHelper = className + "Helper";
var interfaces = new named_type_reference_list("System.Collections.IEnumerator", "System.Collections.IEnumerable");
var td = new type_declaration(classNameHelper, SyntaxTreeBuilder.BuildClassDefinition(interfaces, cm));
// Изменение тела процедуры
var stl = new statement_list(new var_statement("res", new new_expr(className)));
stl.AddMany(lid.Select(id => new assign(new dot_node("res", id), id)));
stl.Add(new assign("Result", "res"));
pd.proc_body = new block(stl);
// Второй класс
var tpl = new template_param_list(stels);
var IEnumeratorT = new template_type_reference("System.Collections.Generic.IEnumerator", tpl);
var cm1 = class_members.Public.Add(
procedure_definition.EmptyDefaultConstructor,
new procedure_definition(new function_header("get_Current", stels), new assign("Result", Consts.Current)),
new procedure_definition(new function_header("GetEnumerator", IEnumeratorT), new assign("Result", "Self")),
new procedure_definition("Dispose")
);
var interfaces1 = new named_type_reference_list(classNameHelper);
var IEnumerableT = new template_type_reference("System.Collections.Generic.IEnumerable", tpl);
interfaces1.Add(IEnumerableT).Add(IEnumeratorT);
var td1 = new type_declaration(className, SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1));
var cct = new type_declarations(td);
cct.Add(td1);
return cct;
}
public override void visit(procedure_definition pd)
{
hasYields = false;
if (pd.proc_header is function_header)
mids = new FindMainIdentsVisitor();
base.visit(pd);
if (!hasYields) // т.е. мы разобрали функцию и уже выходим. Это значит, что пока yield будет обрабатываться только в функциях. Так это и надо.
return;
var dld = new DeleteAllLocalDefs(); // mids.vars - все захваченные переменные
pd.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все переменные и вынести их в отдельный список var_def_statement
mids.vars.Except(dld.LocalDeletedDefsNames); // параметры остались. Их тоже надо исключать - они и так будут обработаны
// В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать
LoweringVisitor.Accept(pd);
var cfa = new ConstructFiniteAutomata((pd.proc_body as block).program_code);
cfa.Transform();
(pd.proc_body as block).program_code = cfa.res;
// Конструируем определение класса
var cct = GenClassesForYield(pd, dld.LocalDeletedDefs); // все удаленные описания переменных делаем описанием класса
UpperNodeAs<declarations>().InsertBefore(pd, cct);
mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть
}
public override void visit(yield_node yn)
{
hasYields = true;
if (mids != null) // если мы - внутри процедуры
yn.visit(mids);
else throw new SyntaxError("Yield must be in functions only", "", yn.source_context, yn);
// mids.vars - надо установить, какие из них - локальные, какие - из этого класса, какие - являются параметрами функции, а какие - глобальные (все остальные)
// те, которые являются параметрами, надо скопировать в локальные переменные и переименовать использование везде по ходу данной функции
// самое сложное - переменные-поля этого класса - они требуют в создаваемом классе, реализующем итератор, хранить Self текущего класса и добавлять это Self везде по ходу алгоритма
// вначале будем считать, что переменные-поля этого класса и переменные-параметры не захватываются yield
//base.visit(yn);
}
}
class ConstructFiniteAutomata
{
public statement_list res = new statement_list();
statement_list stl;
int curState = 0;
statement_list curStatList;
statement_list StatListAfterCase = new statement_list();
case_node cas; // формируемый case
public ConstructFiniteAutomata(statement_list stl)
{
this.stl = stl;
}
public void Process(statement st)
{
if (!(st is yield_node || st is labeled_statement))
{
curStatList.Add(st);
}
if (st is yield_node)
{
var yn = st as yield_node;
curState += 1;
curStatList.AddMany(
new assign(Consts.Current, yn.ex),
new assign(Consts.State, curState),
new assign("Result", true),
new procedure_call("exit")
);
curStatList = new statement_list();
case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList);
cas.conditions.variants.Add(cv);
}
if (st is labeled_statement)
{
var ls = st as labeled_statement;
curStatList = StatListAfterCase;
curStatList.Add(new labeled_statement(ls.label_name));
Process(ls.to_statement);
}
}
public void Transform()
{
cas = new case_node(new ident(Consts.State));
curStatList = new statement_list();
case_variant cv = new case_variant(new expression_list(new int32_const(curState)), curStatList);
cas.conditions.variants.Add(cv);
foreach (var st in stl.subnodes)
Process(st);
stl.subnodes = BaseChangeVisitor.SeqStatements(cas, StatListAfterCase).ToList();
//statement_list res = new statement_list(cas);
res = stl;
}
}
}

View file

@ -1,15 +0,0 @@
label A,B,C;
var
i,j: integer;
t,t1: real := 2+3;
begin
write(1+i,(t+2)*3);
i := 5;
begin
i := i + 1;
goto A;
j := 2;
end;
A: write(2);
end.

View file

@ -1,15 +0,0 @@
begin
while True do
begin
x := 3;
end;
if x>0 then
x := 1
else
begin
x := 2;
write(1);
end;
if x>1 then
x := y
end.

View file

@ -1,7 +0,0 @@
begin
while 2*2=4 do
begin
while x>0 do
x := 3;
end;
end.

View file

@ -1,4 +0,0 @@
begin
if True then
var x := 0;
end.

View file

@ -1,10 +0,0 @@
var x: integer;
begin
x := 1;
while x<5 do
begin
write(x);
x += 2;
x += 3;
end;
end.

View file

@ -1,22 +0,0 @@
procedure p;
var
x,y: integer;
s: string;
begin
var p1: integer;
end;
function f: integer;
var
a: real;
p1,s,ffff: integer;
begin
var p1,s,d: integer;
end;
var a,p1: real;
begin
var p3,p1,p5,p6: integer;
p1 := 3;
end.

View file

@ -1,8 +0,0 @@
var
a,p1: real;
s: string;
begin
var p3,p1,p5,p6: integer;
p1 := 3;
end.

View file

@ -1,3 +0,0 @@
begin
var a := 2.5*3+a*(2+1);
end.

View file

@ -1,3 +0,0 @@
var a := 2 + 3;
begin
end.

View file

@ -1,40 +0,0 @@
var i: integer;
const ccc = 2+3+4;
procedure p(jjj: integer; var kkk: integer);
var i: integer;
const ccc: integer = 2;
type bcd = integer;
begin
var k: integer;
// yield x111.x222+fff;
// yield aaa[i]^.d+(bbb.c*nnn^)*fff(4);
end;
function f(var i,j,k: integer): integer;
var i: integer;
begin
var k: integer;
k^[2].t[3]^ := a + 1 * 2*(3+k^[2].t[3]^);
end;
type C = class
ck: integer;
procedure x1;
var cxk: integer;
begin
var cik: integer;
end;
function f1(): integer;
var cfk: integer;
begin
var cfik: integer;
write(1+2+3+4,5*6);
end;
end;
begin
var ii: integer;
end.

View file

@ -1,21 +0,0 @@
{function p: integer;
var l,m,n: integer;
begin
var i,j,k: integer;
yield j*dd;
yield i;
end;}
procedure q;
var l,m,n: integer;
kk,jj: real;
begin
var i,j,k,mmm: integer;
yield x111.x222+fff;
yield l*k;
yield i*n;
end;
begin
end.

View file

@ -1,8 +0,0 @@
procedure q;
begin
var i,j,k,mmm: integer;
end;
begin
end.

View file

@ -1,11 +0,0 @@
function Gen: sequence of integer;
begin
yield 1;
yield 5;
end;
begin
var q := Gen();
foreach var x in q do
Print(x);
end.

View file

@ -1,16 +0,0 @@
function Gen(n: integer): sequence of integer;
var j,k: real;
begin
var i := 1;
j := 5;
while i<j do
begin
yield i*i;
i += 1;
end;
end;
begin
foreach var x in Gen(5) do
Print(x);
end.