Смекни!
smekni.com

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

} else if (firsttoken == "call") {

Expression expr = new Expression(p);

return new CallCommand(expr);

} else {

p.Reset();

Expression expr1 = new Expression(p);

return new PrintLnCommand(expr1);

}

} catch (SyntaxErrorException ex) {

throw ex;

} catch (Exception ex) {

throw new SyntaxErrorException(ex.Message);

}

}

public static IOperator CompileOperator(string str) {

Parser p = new Parser(str);

if (!p.HasMore()) {

return new EmptyCommand();

}

String pstr = p.GetString();

p.MoveNext();

string firsttoken = (p.Current as String);

if (firsttoken == "for") {

try {

return ParseForStatement(p.GetString());

} catch (SyntaxErrorException ex) {

throw ex;

} catch (Exception ex) {

throw new SyntaxErrorException(ex.Message);

}

}

int posa = pstr.IndexOf(":=");

if (posa >= 0) {

int cq = 0;

for (int iq = 0; iq < posa; iq++)

if (pstr[iq] == '&bsol;"')

cq++;

if (cq%2 == 0) {

try {

if (posa == 0)

throw new SyntaxErrorException("Синтаксическаяошибка");

try {

if (pstr[posa - 1] == '}') {

int posob = pstr.IndexOf('{');

if ((posob < 0) || (posob > posa))

throw new SyntaxErrorException("Синтаксическаяошибка");

return new AssignCommand(pstr.Substring(0, posob),

pstr.Substring(posob + 1, posa - posob - 2),

pstr.Substring(posa + 2));

} else {

return new AssignCommand(pstr.Substring(0, posa),

pstr.Substring(posa + 2));

}

} catch {

throw new SyntaxErrorException("Синтаксическаяошибка");

}

} catch (CalcException ex) {

throw new SyntaxErrorException(ex.Message);

}

}

}

try {

if (firsttoken == "clear") {

if (!p.MoveNext())

throw new SyntaxErrorException("Синтаксическаяошибка");

Command cc = new ClearCommand(p.Current as String);

if (p.MoveNext())

throw new SyntaxErrorException("Синтаксическаяошибка");

return cc;

} else if (firsttoken == "next") {

if (p.MoveNext())

throw new SyntaxErrorException("Синтаксическаяошибка");

return new NextOperator();

} else if (firsttoken == "else") {

if (p.MoveNext())

throw new SyntaxErrorException("Синтаксическаяошибка");

return new ElseOperator();

} else if (firsttoken == "endif") {

if (p.MoveNext())

throw new SyntaxErrorException("Синтаксическаяошибка");

return new EndifOperator();

} else if (firsttoken == "loop") {

if (p.MoveNext())

throw new SyntaxErrorException("Синтаксическаяошибка");

return new LoopOperator();

} else if (firsttoken == "return") {

if (p.MoveNext())

throw new SyntaxErrorException("Синтаксическаяошибка");

return new ReturnOperator();

} else if (firsttoken == "error") {

if (p.MoveNext())

throw new SyntaxErrorException("Синтаксическаяошибка");

return new ErrorOperator();

}

Expression expr = new Expression(p);

if (firsttoken == "print")

return new PrintCommand(expr);

else if (firsttoken == "println")

return new PrintLnCommand(expr);

else if (firsttoken == "call")

return new CallCommand(expr);

else if (firsttoken == "while")

return new WhileOperator(expr);

else if (firsttoken == "if")

return new IfOperator(expr);

else if (firsttoken == "elseif")

return new ElseifOperator(expr);

else

throw new SyntaxErrorException("Синтаксическаяошибка");

} catch (SyntaxErrorException ex) {

throw ex;

} catch (Exception ex) {

throw new SyntaxErrorException(ex.Message);

}

}

private static IOperator ParseForStatement(string str) {

str = str.Substring(3);

int assignpos = str.IndexOf(":=");

if (assignpos < 0)

throw new SyntaxErrorException("Неправильныйсинтаксисоператора for");

string countername = str.Substring(0, assignpos).Trim();

if (!Parser.IsID(countername))

throw new SyntaxErrorException("Неправильныйсинтаксисоператора for");

str = str.Substring(assignpos + 2);

int colonpos = str.IndexOf(":");

if (colonpos < 0)

throw new SyntaxErrorException("Неправильныйсинтаксисоператора for");

string expr1str = str.Substring(0, colonpos);

string expr2str = str.Substring(colonpos + 1);

Expression expr1 = new Expression(expr1str);

Expression expr2 = new Expression(expr2str);

return new ForOperator(countername, expr1, expr2);

}

}

}

12. Интерфейс IOperator.

namespace interpr.logic.operators {

public enum OperatorKind {

Plain,

If,

Elseif,

Else,

Endif,

While,

Loop,

For,

Next,

Return

}

public interface IOperator {

void Execute(Subroutine.Moment pos);

OperatorKind GetKind();

}

}

13. Класс Command.

namespace interpr.logic.operators {

public abstract class Command : IOperator {

public abstract void Execute();

public void Execute(Subroutine.Moment pos) {

Execute();

pos.Next();

}

public OperatorKind GetKind() {

return OperatorKind.Plain;

}

}

}

14. Класс ForOperator.

using interpr.logic.vartypes;

namespace interpr.logic.operators {

public class ForOperator : IOperator {

private int m_next_pos = -1;

private string m_counter_var = null;

private Expression m_begin = null;

private Expression m_end = null;

private IntVar m_end_res = null;

public ForOperator(string counter, Expression beg, Expression end) {

m_counter_var = counter;

m_begin = beg;

m_end = end;

}

public int NextPos {

get {

if (m_next_pos < 0)

throw new OtherException("Error in LoopOperator.NextPos");

return m_next_pos;

}

set { m_next_pos = value; }

}

public void Step(Subroutine.Moment pos, int forpos) {

Namespace cn = InterprEnvironment.Instance.CurrentNamespace;

VarBase res = cn[m_counter_var];

if (!res.IsInt())

throw new CalcException("Тип переменной - счетчика цикла был изменен");

int resval = (res as IntVar).Val;

resval++;

res = new IntVar(resval);

cn[m_counter_var] = res;

if (resval > m_end_res.Val)

pos.GoTo(m_next_pos + 1);

else

pos.GoTo(forpos + 1);

}

public void Execute(Subroutine.Moment pos) {

VarBase resb, rese;

resb = m_begin.Calculate();

if (!resb.IsInt())

thrownewCalcException("Границы изменения счетчика должны быть целыми");

IntVar resbi = resb as IntVar;

Namespace cn = InterprEnvironment.Instance.CurrentNamespace;

cn[m_counter_var] = resb;

rese = m_end.Calculate();

if (!rese.IsInt())

thrownewCalcException("Границы изменения счетчика должны быть целыми");

m_end_res = rese as IntVar;

if (resbi.Val > m_end_res.Val)

pos.GoTo(m_next_pos + 1);

else

pos.Next();

}

public OperatorKind GetKind() {

return OperatorKind.For;

}

}

}

15. КлассNextOperator

namespace interpr.logic.operators {

public class NextOperator : IOperator {

private int m_for_pos = -1;

private ForOperator m_for_op = null;

public NextOperator() {}

public int ForPos {

get {

if (m_for_pos < 0)

throw new OtherException("Error in NextOperator.ForPos");

return m_for_pos;

}

set { m_for_pos = value; }

}

public ForOperator ForOp {

get { return m_for_op; }

set { m_for_op = value; }

}

public void Execute(interpr.logic.Subroutine.Moment pos) {

m_for_op.Step(pos, m_for_pos);

}

public interpr.logic.operators.OperatorKind GetKind() {

return OperatorKind.Next;

}

}

}

16. Класс Subroutine.

using System;

using System.Collections;

using System.Threading;

using interpr.logic.vartypes;

using interpr.logic.operators;

namespace interpr.logic {

public sealed class Subroutine {

private void AnalyseHeader(string str) {

Parser header_p = new Parser(str);

if (!header_p.MoveNext())

throw new SyntaxErrorException("Ошибка в заголовке функции");

if ((header_p.Current as System.String) != m_name)

throw new SyntaxErrorException("Имя функции не совпадает с именем файла");

if ((!header_p.MoveNext()) || ((header_p.Current as String) != "["))

throw new SyntaxErrorException("Ошибка в заголовке функции");

if ((!header_p.MoveNext()))

throw new SyntaxErrorException("Ошибка в заголовке функции");

if ((header_p.Current as System.String != "]")) {

string readstr;

while (true) {

readstr = (header_p.Current as System.String);

if (!Parser.IsID(readstr))

throw new SyntaxErrorException("Ошибка в заголовке функции");

m_args.Add(readstr);

if (!header_p.MoveNext())

throw new SyntaxErrorException("Ошибка в заголовке функции");

readstr = (header_p.Current as System.String);

if (readstr == ",") {

if (!header_p.MoveNext())

throw new SyntaxErrorException("Ошибка в заголовке функции");

}

else if (readstr == "]")

break;

else

throw new SyntaxErrorException("Ошибка в заголовке функции");

}

}

if (header_p.MoveNext())

throw new SyntaxErrorException("Ошибка в заголовке функции");

if (m_args.IndexOf("result") >= 0)

throw new SyntaxErrorException("Параметр функции не может иметь имя &bsol;"result&bsol;"");

}

public Subroutine(string[] code, string name) {

m_name = name;

if (code.Length == 0)

throw new SyntaxErrorException("Файл функции пуст");

AnalyseHeader(code[0]);

int clen = code.Length;

int i = 0;

try {

Stack stk = new Stack();

m_operators.Add(newEmptyCommand()); //чтобы индексация начиналась с единицы

for (i = 1; i < clen; i++) {

IOperator op = LineCompiler.CompileOperator(code[i]);

if (op == null)

throw new SyntaxErrorException("Синтаксическая ошибка");

m_operators.Add(op);

switch (op.GetKind()) {

case OperatorKind.If:

case OperatorKind.While:

case OperatorKind.For:

{

stk.Push(i);

break;

}

case OperatorKind.Elseif:

{

if (stk.Count == 0)

throw new SyntaxErrorException("Лишнее elseif");

int j = (int) stk.Pop();

switch ((m_operators[j] as IOperator).GetKind()) {

case OperatorKind.If:

{

(m_operators[j] as IfOperator).NextPos = i;

break;

}

case OperatorKind.Elseif:

{

(m_operators[j] as ElseifOperator).NextPos = i;

break;

}

default:

throw new SyntaxErrorException("Лишнее elseif");

}

stk.Push(i);

break;

}

case OperatorKind.Else:

{

if (stk.Count == 0)

throw new SyntaxErrorException("Лишнее else");

int j = (int) stk.Pop();

stk.Push(i);

switch ((m_operators[j] as IOperator).GetKind()) {

case OperatorKind.If:

{

(m_operators[j] as IfOperator).NextPos = i;

break;

}

case OperatorKind.Elseif:

{

(m_operators[j] as ElseifOperator).NextPos = i;

break;

}

default:

throw new SyntaxErrorException("Лишнее else");

}

break;

}

case OperatorKind.Endif:

{

if (stk.Count == 0)

throw new SyntaxErrorException("Лишнее endif");

int j = (int) stk.Pop();

switch ((m_operators[j] as IOperator).GetKind()) {

case OperatorKind.If:

{

(m_operators[j] as IfOperator).NextPos = i;

break;

}

case OperatorKind.Elseif:

{

(m_operators[j] as ElseifOperator).NextPos = i;

break;

}

case OperatorKind.Else:

{

(m_operators[j] as ElseOperator).NextPos = i;

break;

}

default:

throw new SyntaxErrorException("Лишнее endif");

}

break;

}

case OperatorKind.Loop:

{

if (stk.Count == 0)

throw new SyntaxErrorException("Лишнее loop");

int j = (int) stk.Pop();

if ((m_operators[j] as IOperator).GetKind() != OperatorKind.While)

throw new SyntaxErrorException("Лишнее loop");

(m_operators[i] as LoopOperator).WhilePos = j;

(m_operators[j] as WhileOperator).LoopPos = i;

break;

}

case OperatorKind.Next:

{

if (stk.Count == 0)

throw new SyntaxErrorException("Лишнее next");

int j = (int) stk.Pop();

if ((m_operators[j] as IOperator).GetKind() != OperatorKind.For)

throw new SyntaxErrorException("Лишнее next");

(m_operators[i] as NextOperator).ForPos = j;

(m_operators[i] as NextOperator).ForOp = (m_operators[j] as ForOperator);

(m_operators[j] as ForOperator).NextPos = i;

break;

}

}

}

if (stk.Count != 0)

throw new SyntaxErrorException("Не закрытый блок");

}

catch (SyntaxErrorException ex) {

throw new LineSyntaxException(ex.Message, m_name, i + 1);

}

m_count = m_operators.Count;

}

private string m_name;

private ArrayList m_args = new ArrayList();

private ArrayList m_operators = new ArrayList();

private int m_count;

public int ReqCount {

get { return m_args.Count; }

}

public VarBase Perform(ArgList al) {

Namespace ns = new Namespace(InterprEnvironment.Instance.CurrentNamespace);

ns["result"] = new IntVar(0);

int argc = m_args.Count;

if (al.Count != argc)

throw new CalcException("Неверное число параметров");

al.Reset();

for (int i = 0; i < argc; i++) {

ns[m_args[i] as System.String] = al.Get();

}

InterprEnvironment.Instance.CurrentNamespace = ns;

Moment moment = new Moment(this);

if (m_count > 1) {

try {

moment.Run();

}

catch (SyntaxErrorException ex) {

throw ex;

}

catch (CalcException ex) {

throw new CalcException("Ошибка в функции " + m_name + "[] в строке " + (moment.Pos + 1) + " : " + ex.Message);

}

}

VarBase res = ns["result"];

InterprEnvironment.Instance.CurrentNamespace = ns.PreviousNamespace;

if (res == null)

thrownewCalcException("Ошибка в функции " + m_name + "[] : переменная result не определена на момент выхода");

return res;

}

public class Moment {

private Subroutine m_sub;

private int m_pos;

private static int s_break = 0;

public static void Break() {

Interlocked.Exchange(ref s_break, 1);

}

public int Pos {

get { return m_pos; }