Смекни!
smekni.com

Интерактивный интерпретатор (стр. 9 из 12)

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() + @"&bsol;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);

}

}

}

4. Класс Namespace.

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

}

}

}

5. Интерфейс IСomputable.

namespace interpr.logic {

public interface IComputable {

logic.vartypes.VarBase Compute();

}

}

6. Класс Call.

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);

}

}

}

7. Класс ArgList

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

}

}

}

8. Класс Expression.

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("Ошибкапривычислениивыражения");