get { return m_current_console; }
set { m_current_console = value; }
}
public Operation GetFunction(string name) {
if (name == "abs")
return Operation.ABS;
...........................
if (name == "size")
return Operation.SIZE;
return new SubName(name);
}
public string[] LoadedSubs {
get { return m_subsman.SubroutineNames; }
}
private class SubroutinesManager {
private ArrayList m_subs = new ArrayList();
private ArrayList m_names = new ArrayList();
private SubroutinesManager() {
DirectoryInfo di =
new DirectoryInfo(Directory.GetCurrentDirectory() + @"\subroutines");
if (!di.Exists) {
di.Create();
}
}
public bool Load(string name) {
FileInfo fi = new FileInfo(Directory.GetCurrentDirectory() + @"\subroutines\" + name);
if (!fi.Exists)
throw new OtherException("Error in SubroutinesManager.Load()");
return LoadFile(fi);
}
private bool LoadFile(FileInfo file) {
try {
StreamReader sr = file.OpenText();
LinkedList ll = new LinkedList();
try {
while (sr.Peek() != -1) {
ll.AddFirst(sr.ReadLine());
}
} finally {
sr.Close();
}
string[] strs = new String[ll.Count];
int i = 0;
while (!ll.IsEmpty()) {
strs[i] = (ll.RemoveLast() as String);
i++;
}
Subroutine sub;
try {
sub = new Subroutine(strs, file.Name);
} catch (LineSyntaxException ex) {
InterprEnvironment.Instance.CurrentConsole.PrintLn("Синтаксическаяошибкав " + ex.Function + "[] at line " + ex.Line + " " + ex.Message);
return false;
} catch (SyntaxErrorException ex) {
InterprEnvironment.Instance.CurrentConsole.PrintLn("Синтаксическаяошибкав " + file.Name + " " + ex.Message);
return false;
}
Set(file.Name, sub);
} catch {
throw new OtherException("Error in Environment.Load()");
}
return true;
}
public Subroutine this[string name] {
get {
int sres = m_names.IndexOf(name);
if (sres < 0)
return null;
else
return m_subs[sres] as Subroutine;
}
}
private void Set(string name, Subroutine sub) {
int sres = m_names.IndexOf(name);
if (sres >= 0) {
m_names.RemoveAt(sres);
m_subs.RemoveAt(sres);
}
m_names.Add(name);
m_subs.Add(sub);
}
private static SubroutinesManager s_inst = null;
public static SubroutinesManager GetInstance() {
if (s_inst == null)
s_inst = new SubroutinesManager();
return s_inst;
}
public string[] SubroutineNames {
get {
int count = m_names.Count;
string[] res = new string[count];
for (int i = 0; i < count; i++) {
res[i] = (m_names[i] as String);
}
for (int i = 0; i < count - 1; i++) {
int k = i;
for (int j = i + 1; j < count; j++)
k = (string.Compare(res[j], res[k]) < 0) ? j : k;
if (i != k) {
string temp = res[i];
res[i] = res[k];
res[k] = temp;
}
}
return res;
}
}
public void ReloadAll() {
m_subs = new ArrayList();
m_names = new ArrayList();
DirectoryInfo di =
new DirectoryInfo(Directory.GetCurrentDirectory() + @"\subroutines");
if (!di.Exists) {
di.Create();
}
foreach (FileInfo file in di.GetFiles()) {
if (Parser.IsID(file.Name)) {
LoadFile(file);
}
}
}
public void Unload(string name) {
int index = m_names.IndexOf(name);
if (index >= 0) {
m_names.RemoveAt(index);
m_subs.RemoveAt(index);
}
}
}
public Subroutine GetSub(string name) {
Subroutine res = m_subsman[name];
if (res == null)
throw new CalcException("Функция " + name + " несуществует");
return res;
}
public void UnloadSub(string name) {
m_subsman.Unload(name);
}
}
}
using System;
using System.Collections;
using interpr.logic.vartypes;
namespace interpr.logic {
public class NamespaceSerializationException : Exception {
public NamespaceSerializationException() : base() {}
}
public class Namespace {
protected class Pair {
internal string m_str;
internal VarBase m_var;
}
protected ArrayList m_list = new ArrayList();
protected int m_n = 0;
private Namespace m_previous_namespace = null;
public Namespace PreviousNamespace {
get { return m_previous_namespace; }
}
public Namespace(Namespace previous) {
m_previous_namespace = previous;
}
protected Namespace() {}
public VarBase Get(string name) {
if (m_n == 0)
return null;
int i = 0;
Pair p;
do {
p = (m_list[i++] as Pair);
if (p.m_str == name)
return p.m_var;
} while (i < m_n);
return null;
}
public void Assign(VarBase var, string name) {
Pair p;
if (m_n != 0) {
int i = 0;
do {
p = (m_list[i++] as Pair);
if (p.m_str == name) {
p.m_var = var;
return;
}
} while (i < m_n);
}
p = new Pair();
p.m_var = var;
p.m_str = name;
m_list.Add(p);
m_n++;
}
public void AssignToElement(SingleVar var, string name, int index) {
Pair p;
if (m_n != 0) {
int i = 0;
do {
p = (m_list[i++] as Pair);
if (p.m_str == name) {
if (!p.m_var.IsArray())
thrownewCalcException("Переменная не является массивом");
(p.m_var as ArrayVar)[index] = var;
return;
}
} while (i < m_n);
}
p = new Pair();
p.m_var = new ArrayVar();
(p.m_var as ArrayVar)[index] = var;
p.m_str = name;
m_list.Add(p);
m_n++;
}
public void Remove(String name) {
if (m_n == 0)
return;
int i = 0;
do {
Pair p = (m_list[i++] as Pair);
if (p.m_str == name) {
m_list.RemoveAt(i - 1);
m_n--;
return;
}
} while (i < m_n);
}
public VarBase this[string name] {
set { Assign(value, name); }
get { return Get(name); }
}
}
}
namespace interpr.logic {
public interface IComputable {
logic.vartypes.VarBase Compute();
}
}
using interpr.logic.vartypes;
namespace interpr.logic {
public class Call : IComputable {
private Operation m_op;
private ArgList m_al = null;
public Call(Operation op) {
m_op = op;
}
public void SetArgList(ArgList al) {
m_al = al;
}
public int ReqCount {
get { return m_op.ReqCount; }
}
public VarBase Compute() {
return m_op.Perform(m_al);
}
}
}
using interpr.logic.vartypes;
namespace interpr.logic {
public class ArgList {
private bool m_read = false;
private LinkedList m_list = new LinkedList();
private LinkedList.Iterator m_i = null;
public void Add(VarBase var) {
if (m_read)
throw new OtherException("Write to the argument list after reading begin");
m_list.Add(var);
}
public VarBase Get() {
if (!m_read)
throw new OtherException("Try to read from argument list before reset");
if (!m_i.HasPrevious)
throw new OtherException("Try to read from empty argument list");
m_read = true;
IComputable obj = (m_i.Previous() as IComputable);
if (obj == null)
throw new CalcException("Переменная не инициализированна.");
return obj.Compute();
}
public void Reset() {
m_read = true;
m_i = m_list.GetIterator(m_list.Count);
}
public int Count {
get { return m_list.Count; }
}
}
}
using System;
using interpr.logic.vartypes;
namespace interpr.logic {
public class Expression {
public Expression(String str) {
Parser p = new Parser(str);
Analyse(p);
}
public Expression(Parser p) {
Analyse(p);
}
private class Element {
internal IComputable m_o;
internal Element m_next;
internal Element(IComputable obj, Element next) {
m_o = obj;
m_next = next;
}
}
private Element m_top = null;
private Element m_bottom = null;
private int m_c = 0;
private void AddFront(IComputable obj) {
m_c++;
if (m_c == 1)
m_top = m_bottom = new Element(obj, null);
else {
Element t = new Element(obj, null);
m_bottom.m_next = t;
m_bottom = t;
}
}
private void Analyse(Parser p) {
try {
LinkedList l = new LinkedList();
while (p.MoveNext())
l.Add(p.Current);
OPZ(l);
}
catch (CalcException ex) {
throw ex;
}
catch {
throw new SyntaxErrorException("Синтаксическаяошибкаввыражении");
}
}
private void OPZ(LinkedList tokens) {
/* ** Бинарная операция выталкивает из стека в результат
* все операции с большим или равным приоритетом, затем
* записывается в стек сама
* ** Унарная операция записывается в стек
* ** Открывающая скобка записывается в стек
* ** Закрывающая скобка выталкивает в результат все операции
* из стека до открывающей скобки, затем
* скобки уничтожаются и выталкиваются унарные операции
* ** Переменная или константа сразу пишутся в результат, затем
* выталкиваются из стека унарные операции
* ** При вызове функции
* сначала отдельно разбираются все операнды, затем в результат
* дописывается сама функция, как операция
* ** Обращение к элементу массива обрабатывается аналогично
* В конце все оставшиеся в стеке операции выталкиваются в результат
*/
InterprEnvironment env = InterprEnvironment.Instance;
if (tokens.IsEmpty()) return;
LinkedList.Iterator itr = tokens.GetIterator();
LinkedList stk = new LinkedList();
while (itr.HasMore) {
string si = (itr.Step() as System.String);
if (si == "(") {
stk.Add(O_BR);
}
else if (si == ")") {
while (true) {
object o = stk.RemoveLast();
if (o == O_BR) break;
AddFront(new Call(o as Operation));
}
while ((!stk.IsEmpty()) && IsUnary(stk.Last)) {
AddFront(new Call(stk.RemoveLast() as Operation));
}
}
else if (Parser.IsID(si)) {
bool bfun = false;
bool barray = false;
if (itr.HasMore) {
string s = (itr.Step() as System.String);
if (s == "[")
bfun = true;
else if (s == "{")
barray = true;
else
itr.Previous();
}
if (bfun) {
LinkedList l = null;
while (true) {
l = new LinkedList();
int level = 0;
while (true) {
if (!itr.HasMore)
throw new SyntaxErrorException("Синтаксическаяошибкаввыражении");
string sj = (itr.Step() as System.String);
if (sj == "[") {
level++;
l.Add(sj);
}
else if (sj == "]") {
if (level == 0)
goto label1;
else {
level--;
l.Add(sj);
}
}
else if (sj == ",") {
if (level > 0)
l.Add(sj);
else
break;
}
else
l.Add(sj);
}
OPZ(l);
}
label1:
if (l != null)
OPZ(l);
Operation sub = env.GetFunction(si);
AddFront(new Call(sub));
while ((stk.Count > 0) && IsUnary(stk.Last)) {
AddFront(new Call((Operation) stk.RemoveLast()));
}
}
else if (barray) {
LinkedList l = new LinkedList();
int level = 0;
while (true) {
if (!itr.HasMore)
throw new SyntaxErrorException("Синтаксическаяошибкаввыражении");
String sj = (String) itr.Step();
if (sj == "{") {
level++;
l.Add(sj);
}
else if (sj == "}") {
if (level == 0)
break;
else {
level--;
l.Add(sj);
}
}
else
l.Add(sj);
}
OPZ(l);
VarName v = new VarName(si);
AddFront(v);
AddFront(new Call(Operation.INDEX));
while ((stk.Count > 0) && IsUnary(stk.Last)) {
AddFront(new Call(stk.RemoveLast() as Operation));
}
}
else {
VarName v = new VarName(si);
AddFront(v);
while ((stk.Count > 0) && IsUnary(stk.Last)) {
AddFront(new Call(stk.RemoveLast() as Operation));
}
}
}
else {
Operation op = StrToOperation(si);
if (op == null) {
SingleVar sv = SingleVar.FromString(si);
if (si == null)
throw new SyntaxErrorException("Синтаксическаяошибкаввыражении");
AddFront(sv);
while ((stk.Count > 0) && IsUnary(stk.Last)) {
AddFront(new Call(stk.RemoveLast() as Operation));
}
}
else {
//operation
if (op == Operation.ADD) {
itr.Previous();
if (!itr.HasPrevious) {
stk.Add(Operation.UPLUS);
itr.Step();
continue;
}
String strpr = (String) itr.Previous();
itr.Step();
itr.Step();
if ((StrToOperation(strpr) != null) || (strpr == "(") ||
(strpr == "[") || (strpr == "{")) {
stk.Add(Operation.UPLUS);
continue;
}
}
else if (op == Operation.SUB) {
itr.Previous();
if (!itr.HasPrevious) {
stk.Add(Operation.UMINUS);
itr.Step();
continue;
}
String strpr = (String) itr.Previous();
itr.Step();
itr.Step();
if ((StrToOperation(strpr) != null) || (strpr == "(") ||
(strpr == "[") || (strpr == "{")) {
stk.Add(Operation.UMINUS);
continue;
}
}
else if (op == Operation.NOT) {
stk.Add(op);
continue;
}
if (stk.IsEmpty() || (stk.Last == O_BR)) {
stk.Add(op);
}
else {
int pr = Priority(op);
while (true) {
if (stk.IsEmpty())
break;
Object stktop = stk.Last;
if (stktop is Operation) {
int pr1 = Priority(stktop as Operation);
if ((pr <= pr1) && (pr1 < 6)) {
AddFront(new Call(stktop as Operation));
stk.RemoveLast();
}
else
break;
}
else
break;
}
stk.Add(op);
}
}
}
}
while (!stk.IsEmpty()) {
Object o = stk.RemoveLast();
AddFront(new Call(o as Operation));
}
}
public VarBase Calculate() {
if (m_c == 0)
throw new CalcException("Ошибка: пустоевыражение.");
Element top1 = null;
Element cur = m_top;
try {
for (; cur != null; cur = cur.m_next) {
if (cur.m_o is Call) {
int rc = (cur.m_o as Call).ReqCount;
ArgList al = new ArgList();
for (int i = 0; i < rc; i++) {
if (top1 == null)
throw new CalcException("Ошибкапривычислениивыражения");