Проект с визиторами

This commit is contained in:
miks1965 2015-06-28 10:53:10 +03:00
parent cafd26fe61
commit ec8e54ddaf
26 changed files with 1269 additions and 3 deletions

View file

@ -15,7 +15,7 @@ internal static class RevisionClass
public const string Major = "2";
public const string Minor = "2";
public const string Build = "0";
public const string Revision = "966";
public const string Revision = "967";
public const string MainVersion = Major + "." + Minor;
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;

View file

@ -1,4 +1,4 @@
%MINOR%=2
%REVISION%=966
%REVISION%=967
%MAJOR%=2
%COREVERSION%=0

View file

@ -1 +1 @@
!define VERSION '2.2.0.966'
!define VERSION '2.2.0.967'

View file

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ParsePABC1", "ParsePABC1\ParsePABC1.csproj", "{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxTree", "..\..\PascalABC.NET\!PABC_Git\SyntaxTree\SyntaxTree.csproj", "{C2CAC65A-B2AE-4CCC-B067-E6B8E75DF73A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCompletion", "..\..\PascalABC.NET\!PABC_Git\CodeCompletion\CodeCompletion.csproj", "{1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}"
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
{1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
class AllVarsInProcYields : CollectUpperNamespacesVisitor
{
public FindMainIdentsVisitor mids = new FindMainIdentsVisitor();
public Dictionary<procedure_definition, ISet<string>> d = new Dictionary<procedure_definition, ISet<string>>();
public int countNodesVisited;
public AllVarsInProcYields()
{
PrintInfo = false;
}
public override void Enter(syntax_tree_node st)
{
base.Enter(st);
countNodesVisited++;
if (st is procedure_definition)
{
// пока вложенные процедуры не анализируются, хотя надо
mids.vars.Clear();
}
// сокращение обходимых узлов. Как сделать фильтр по тем узлам, которые необходимо обходить? Например, все операторы (без выражений и описаний), все описания (без операторов)
if (st is assign || st is var_def_statement || st is procedure_call || st is procedure_header || st is expression)
{
visitNode = false;
}
}
public override void Exit(syntax_tree_node st)
{
if (st is procedure_definition)
{
if (mids.vars.Count>0)
{
d[st as procedure_definition] = new HashSet<string>(mids.vars);
}
var fld = new FindLocalDefsVisitor();
st.visit(fld);
fld.Print();
var t = fld.ids.Intersect(mids.vars); // идентификаторы, захваченные из локального контекста
}
base.Exit(st);
}
public override void visit(yield_node yn)
{
yn.visit(mids);
// mids.vars - надо установить, какие из них - локальные, какие - из этого класса, какие - являются параметрами функции, а какие - глобальные (все остальные)
// те, которые являются параметрами, надо скопировать в локальные переменные и переименовать использование везде по ходу данной функции
// самое сложное - переменные-поля этого класса - они требуют в создаваемом классе, реализующем итератор, хранить Self текущего класса и добавлять это Self везде по ходу алгоритма
// вначале будем считать, что переменные-поля этого класса и переменные-параметры не захватываются yield
//base.visit(yn);
}
public void PrintDict()
{
foreach (var a in d)
{
Console.Write("{0}: {1} ", a.Key.proc_header.name.meth_name, a.Value.Count);
foreach (var v in a.Value)
Console.Write("{0}, ", v);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("countNodesVisited={0}", countNodesVisited);
}
}
}
}

View file

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

View file

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
class BaseChangeVisitor : CollectUpperNodesVisitor
{
public void Replace(syntax_tree_node from, syntax_tree_node to)
{
var upper = UpperNode();
if (upper == null)
throw new Exception("У корневого элемента нельзя получить UpperNode");
int ind = -1;
for (var i = 0; i < upper.subnodes_count; i++)
if (from == upper[i])
{
ind = i;
break;
}
upper[ind] = to;
}
public statement_list UpperStatementList()
{
var stl = UpperNode() as statement_list;
if (stl == null)
throw new Exception("оператор вложен не в statement_list");
return stl;
}
public bool DeleteInStatementList(statement st)
{
var stl = UpperStatementList();
bool b = stl.subnodes.Remove(st);
return b;
}
public bool DeleteInIdentList(ident id)
{
var idl = UpperNode() as ident_list;
if (idl==null)
throw new Exception("идентификатор не вложен в id_list");
var b = idl.idents.Remove(id);
return b;
}
public void ReplaceStatement(statement from, statement to)
{
var stl = UpperStatementList();
var ind = stl.subnodes.IndexOf(from);
if (ind == -1)
throw new Exception("оператор from не найден - некорректный вызов ReplaceStatement");
stl.subnodes[ind] = to;
}
public void ReplaceStatement(statement from, List<statement> to)
{
var stl = UpperStatementList();
var ind = stl.subnodes.IndexOf(from);
if (ind == -1)
throw new Exception("оператор from не найден - некорректный вызов ReplaceStatement");
stl.subnodes.RemoveAt(ind);
stl.subnodes.InsertRange(ind, to);
}
}
}

View file

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

View file

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
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;
var f = tds.types_decl.Find(td => td.type_def == cl);
if (PrintInfo)
Console.WriteLine(" " + f.type_name);
base.visit(cl);
}
}
}

View file

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
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

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
public class FindLocalDefsVisitor : WalkingVisitor // Запускать только для подпрограмм
{
public ISet<string> ids = new HashSet<string>();
private bool indef = false;
public override void visit(ident id)
{
if (indef)
ids.Add(id.name);
}
public override void visit(var_def_statement defs)
{
indef = true;
ProcessNode(defs.vars); // исключаем типы - просматриваем только имена переменных
indef = false;
}
public void Print()
{
foreach (var x in ids)
Console.Write(x + ", ");
Console.WriteLine();
}
}
public class FindMainIdentsVisitor : WalkingVisitor // в выражении yield это надо будет.
{
public HashSet<string> vars = new HashSet<string>();
public override void visit(ident id)
{
vars.Add(id.name);
}
public override void visit(dot_node dn)
{
ProcessNode(dn.left);
if (dn.right.GetType() != typeof(ident))
ProcessNode(dn.right);
}
}
}

View file

@ -0,0 +1,56 @@
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 ChangeWhileVisitor : BaseChangeVisitor
{
int lbnum = 0;
public string newLabelName()
{
lbnum++;
return "lb#" + lbnum.ToString();
}
public override void Exit(syntax_tree_node st)
{
if (st.GetType() == typeof(while_node))
{
var wn = st as while_node;
var stl = new statement_list();
var gt1 = new goto_statement(newLabelName());
var gt2 = new goto_statement(newLabelName());
var gt3 = new goto_statement(newLabelName());
var if0 = new if_node(wn.expr, gt1, null);
var lb3 = new labeled_statement(gt3.label, if0);
var lb1 = new labeled_statement(gt1.label, wn.statements);
var lb2 = new labeled_statement(gt2.label, new empty_statement());
stl.Add(lb3).Add(gt2).Add(lb1).Add(gt3).Add(lb2);
//var op = new if_node(wn.expr, wn.statements, null);
Replace(wn, stl);
// в declarations ближайшего блока добавить описание labels
block bl = listNodes.FindLast(x => x is block) as block;
var il = new ident_list();
il.Add(gt1.label).Add(gt2.label).Add(gt3.label);
var ld = new label_definitions(il);
bl.defs.Add(ld);
}
base.Exit(st);
}
}
}

View file

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
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

@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
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 = UpperNode() as variable_definitions;
uvdsl.var_definitions.Remove(vd); // Проблема - мы удаляем первую var_def_statement и вторая становится первой. А в цикле обхода - индексы что естественно
if (uvdsl.var_definitions.Count == 0)
{
var d = UpperNode(2) as declarations;
d.defs.Remove(uvdsl);
}
}
}
}
public override void visit(variable_definitions vd)
{
if (vd.var_definitions != null)
for (int i = vd.var_definitions.Count - 1; i >= 0; --i) // в обратном порядке - тогда удаление текущего элемента работает корректно
ProcessNode(vd.var_definitions[i]);
}
public override void visit(declarations d)
{
if (d.defs != null)
for (int i = d.defs.Count - 1; i >= 0; --i) // в обратном порядке - тогда удаление текущего элемента работает корректно
ProcessNode(d.defs[i]);
}
public void AfterProcTraverse()
{
idsToDelete.ExceptWith(deletedIdsToDeleteInLocalScope); // исключаем из множества удаляемых идентификаторов те, которые мы нашли и удалили в секции var_statement. Это надо делать не для каждого описания, а в конце подпрограммы после удаления из всех секций var_statement
}
}
}

View file

@ -0,0 +1,36 @@
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 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

@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
class CalcConstExprs : BaseChangeVisitor // вычисление целых и вещественных константных выражений на этапе парсинга
{
public override void Exit(syntax_tree_node st)
{
bracket_expr bre = st as bracket_expr;
if (bre != null)
{
if (bre.expr is int32_const)
Replace(st, bre.expr);
}
bin_expr vs = st as bin_expr;
if (vs != null)
{
if (vs.left is int32_const && vs.right is int32_const)
{
var a = vs.left as int32_const;
var b = vs.right as int32_const;
var op = vs.operation_type;
syntax_tree_node res;
switch (op)
{
case Operators.Plus:
res = new int32_const(a.val + b.val);
break;
case Operators.Minus:
res = new int32_const(a.val - b.val);
break;
case Operators.Multiplication:
res = new int32_const(a.val * b.val);
break;
case Operators.Division:
res = new double_const((double)a.val / b.val);
break;
case Operators.Greater:
res = new bool_const(a.val > b.val);
break;
case Operators.Less:
res = new bool_const(a.val < b.val);
break;
case Operators.GreaterEqual:
res = new bool_const(a.val >= b.val);
break;
case Operators.LessEqual:
res = new bool_const(a.val <= b.val);
break;
default:
res = vs;
break;
}
Replace(vs, res);
}
if (vs.left is int32_const && vs.right is double_const || vs.right is int32_const && vs.left is double_const || vs.left is double_const && vs.right is double_const)
{
double x,y;
if (vs.left is int32_const)
x = (vs.left as int32_const).val;
else
x = (vs.left as double_const).val;
if (vs.right is int32_const)
y = (vs.right as int32_const).val;
else
y = (vs.right as double_const).val;
var op = vs.operation_type;
syntax_tree_node res;
switch (op)
{
case Operators.Plus:
res = new double_const(x + y);
break;
case Operators.Minus:
res = new double_const(x - y);
break;
case Operators.Multiplication:
res = new double_const(x * y);
break;
case Operators.Division:
res = new double_const(x / y);
break;
case Operators.Greater:
res = new bool_const(x > y);
break;
case Operators.Less:
res = new bool_const(x < y);
break;
case Operators.GreaterEqual:
res = new bool_const(x >= y);
break;
case Operators.LessEqual:
res = new bool_const(x <= y);
break;
default:
res = vs;
break;
}
Replace(vs, res);
}
}
base.Exit(st); // это обязательно!
}
}
}

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BAA767F1-6544-4A44-BA17-5FBFCF6F2D99}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ParsePABC1</RootNamespace>
<AssemblyName>ParsePABC1</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Compiler">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\Compiler.dll</HintPath>
</Reference>
<Reference Include="CompilerTools">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\CompilerTools.dll</HintPath>
</Reference>
<Reference Include="Errors">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\Errors.dll</HintPath>
</Reference>
<Reference Include="Localization">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\Localization.dll</HintPath>
</Reference>
<Reference Include="ParserTools">
<HintPath>..\..\..\PascalABC.NET\!PABC_SVN1\bin\ParserTools.dll</HintPath>
</Reference>
<Reference Include="PascalABCParser">
<HintPath>..\..\..\PascalABC.NET\!PABC_Git\bin\PascalABCParser.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AllVarsInProcYieldsProba.cs" />
<Compile Include="BaseVisitors\BaseEnterExitVisitor.cs" />
<Compile Include="BaseVisitors\BaseChangeVisitor.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="ChangeWhileVisitor.cs" />
<Compile Include="BaseVisitors\CollectNamespaces.cs" />
<Compile Include="BaseVisitors\CollectUpperNodesVisitor.cs" />
<Compile Include="CountNodesVisitor.cs" />
<Compile Include="DeleteLocalDefs.cs" />
<Compile Include="DeleteRedundantBeginEnds.cs" />
<Compile Include="Optimization\CalcConstExprs.cs" />
<Compile Include="ProcessYieldsCapturedVars.cs" />
<Compile Include="Program.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SimplePrettyPrinterVisitor.cs" />
<Compile Include="BaseVisitors\SmallHelperVisitors.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\PascalABC.NET\!PABC_Git\CodeCompletion\CodeCompletion.csproj">
<Project>{1ab15f6e-c22e-499a-a7ed-54ba7de5cfa6}</Project>
<Name>CodeCompletion</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\PascalABC.NET\!PABC_Git\SyntaxTree\SyntaxTree.csproj">
<Project>{c2cac65a-b2ae-4ccc-b067-e6b8e75df73a}</Project>
<Name>SyntaxTree</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,104 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PascalABCCompiler;
using PascalABCCompiler.SyntaxTree;
namespace ParsePABC1
{
class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor
{
int clnum = 0;
public string newClassName()
{
clnum++;
return "clyield#" + clnum.ToString();
}
public FindMainIdentsVisitor mids = new FindMainIdentsVisitor(); // захваченные переменные процедуры по всем её yield
public int countNodesVisited;
public bool hasYields = false;
public ProcessYieldCapturedVarsVisitor()
{
//PrintInfo = false;
}
/*public override void visit(procedure_definition pd)
{
} */
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;
}
if (st is procedure_definition)
{
mids.vars.Clear(); // очищать при входе в процедуру
}
}
public override void Exit(syntax_tree_node st)
{
if (st is procedure_definition) // т.е. мы разобрали процедуру и уже выходим. Это значит, что пока yield будет обрабатываться только в процедурах. Так это и надо.
{
if (!hasYields)
return;
var dld = new DeleteLocalDefs(mids.vars); // mids.vars - все захваченные переменные
st.visit(dld); // Удалить в локальных и блочных описаниях этой процедуры все захваченные переменные
// В результате работы в mids.vars что-то осталось. Это не локальные переменные и с ними непонятно что делать
dld.AfterProcTraverse();
var cm = new class_members(access_modifer.public_modifer);
foreach (var m in dld.BlockDeletedIds)
cm.Add(m);
cm.Add(st as procedure_definition);
var cc = new type_declaration(newClassName(), SyntaxTreeBuilder.BuildClassDefinition(true, cm), SyntaxTreeBuilder.BuildGenSC);
var cct = new type_declarations(cc, null);
Replace(st, cct);
/*Console.WriteLine("Удаленные переменные: " + (st as procedure_definition).proc_header.name.meth_name.name);
foreach (var dd in dld.deletedIdsToDeleteInLocalScope)
Console.Write(dd + " ");
Console.WriteLine();
Console.WriteLine("Оставшиеся переменные: " + (st as procedure_definition).proc_header.name.meth_name.name);
foreach (var dd in mids.vars)
Console.Write(dd + " ");
Console.WriteLine();*/
}
base.Exit(st);
}
public override void visit(yield_node yn)
{
hasYields = true;
yn.visit(mids);
// mids.vars - надо установить, какие из них - локальные, какие - из этого класса, какие - являются параметрами функции, а какие - глобальные (все остальные)
// те, которые являются параметрами, надо скопировать в локальные переменные и переименовать использование везде по ходу данной функции
// самое сложное - переменные-поля этого класса - они требуют в создаваемом классе, реализующем итератор, хранить Self текущего класса и добавлять это Self везде по ходу алгоритма
// вначале будем считать, что переменные-поля этого класса и переменные-параметры не захватываются yield
//base.visit(yn);
}
public override void visit(declarations d) // в обратном порядке
{
if (d.defs != null)
for (int i = d.defs.Count - 1; i >= 0; --i) // в обратном порядке - тогда удаление текущего элемента работает корректно
ProcessNode(d.defs[i]);
}
}
}

View file

@ -0,0 +1,67 @@
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\ex1.pas");
if (cu == null)
return;
/*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 HashSet<string>();
ld.Add("a");
ld.Add("p1");
ld.Add("s");
var dld = new DeleteLocalDefs(ld);
cu.visit(dld);*/
/*var p = new ProcessYieldCapturedVarsVisitor();
cu.visit(p);*/
var p = new CalcConstExprs();
cu.visit(p);
cu.visit(new SimplePrettyPrinterVisitor());
}
}
}

View file

@ -0,0 +1,62 @@
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

@ -0,0 +1,36 @@
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

@ -0,0 +1,183 @@
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 ParsePABC1
{
class SimplePrettyPrinterVisitor: WalkingVisitor
{
int off = 0;
bool printNodeType = false;
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 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;
PrintlnNoOffset("class");
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)
{
}
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 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)
{
off -= 2;
}
else if (st is class_definition)
{
off -= 2;
Println("end;");
}
}
}
}

Binary file not shown.