} 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] == '\"')
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);
}
}
}
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();
}
}
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;
}
}
}
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;
}
}
}
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;
}
}
}
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("Параметр функции не может иметь имя \"result\"");
}
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; }