Смекни!
smekni.com

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

al.Add(top1.m_o.Compute());

top1 = top1.m_next;

}

(cur.m_o as Call).SetArgList(al);

top1 = new Element((cur.m_o as Call).Compute(), top1);

}

else {

top1 = new Element(cur.m_o, top1);

}

}

if ((top1 == null) || (top1.m_next != null))

throw new CalcException("Ошибка при вычислении выражения");

return top1.m_o.Compute();

}

catch (CalcException ex) {

throw ex;

}

catch {

throw new CalcException("Ошибкапривычислениивыражения");

}

}

private static Operation StrToOperation(String str) {

//не возвращает унарные плюс и минус

if (str == "+")

return Operation.ADD;

else if (str == "-")

return Operation.SUB;

else if (str == "*")

return Operation.MUL;

else if (str == "/")

return Operation.DIV;

else if (str == "~")

return Operation.NOT;

else if (str == "|")

return Operation.OR;

else if (str == "&")

return Operation.AND;

else if (str == "^")

return Operation.XOR;

else if (str == "~=")

return Operation.BE;

else if (str == "=")

return Operation.EQ;

else if (str == "<>")

return Operation.NE;

else if (str == ">=")

return Operation.GE;

else if (str == "<=")

return Operation.LE;

else if (str == ">")

return Operation.GT;

else if (str == "<")

return Operation.LT;

else

return null;

}

private static int Priority(Operation op) {

if ((op == Operation.OR) || (op == Operation.XOR) ||

(op == Operation.BE))

return 1;

else if (op == Operation.AND)

return 2;

else if ((op == Operation.EQ) || (op == Operation.NE) ||

(op == Operation.LE) || (op == Operation.LT) ||

(op == Operation.GE) || (op == Operation.GT))

return 3;

else if ((op == Operation.ADD) || (op == Operation.SUB))

return 4;

else if ((op == Operation.MUL) || (op == Operation.DIV))

return 5;

else

return 6;

}

private static bool IsBinary(Operation op) {

return Priority(op) < 6;

}

private static bool IsUnary(object obj) {

return ((obj == Operation.NOT) || (obj == Operation.UPLUS) ||

(obj == Operation.UMINUS));

}

private class BR_c {}

private static object O_BR = new BR_c();

}

}

9. Класс Operation (сокращенно).

using System;

using interpr.logic.vartypes;

namespace interpr.logic {

public abstract class Operation {

public abstract int ReqCount { get; }

public abstract VarBase Perform(ArgList al);

public static readonly Operation ABS = new ABS_c();

private class ABS_c : Operation {

public override int ReqCount {

get { return 1; }

}

public override VarBase Perform(ArgList al) {

if (al.Count != ReqCount)

throw new OtherException("Invalid argument list");

al.Reset();

VarBase arg1 = al.Get();

if (arg1 is IntVar)

return ((arg1 as IntVar).Val>0) ? (arg1.Clone() as IntVar) : (new IntVar(-((IntVar) arg1).Val));

else if (arg1 is RealVar)

return ((arg1 as RealVar).Val>0) ? (arg1.Clone() as RealVar) : (new RealVar(-((RealVar) arg1).Val));

else

throw new CalcException("Неправильныеаргументыфункции");

}

}

public static readonly Operation ADD = new ADD_c();

private class ADD_c : Operation {

public override int ReqCount {

get { return 2; }

}

public override VarBase Perform(ArgList al) {

if (al.Count != ReqCount)

throw new OtherException("Invalid argument list");

al.Reset();

VarBase arg1 = al.Get();

VarBase arg2 = al.Get();

if(!(arg1.IsSingle()&&arg2.IsSingle()))

throw new CalcException("Неверныетипыоперандов");

return (arg1 as SingleVar).add(arg2 as SingleVar);

}

}

public static readonly Operation AND = new AND_c();

private class AND_c : Operation {

public override int ReqCount {

get { return 2; }

}

public override VarBase Perform(ArgList al) {

if (al.Count != ReqCount)

throw new OtherException("Invalid argument list");

al.Reset();

VarBase arg1 = al.Get();

VarBase arg2 = al.Get();

if(!(arg1.IsSingle()&&arg2.IsSingle()))

throw new CalcException("Неверныетипыоперандов");

return (arg1 as SingleVar).and(arg2 as SingleVar);

}

}

.......................................................................................

}

}

10. Класс Parser.

using System;

using System.Collections;

namespace interpr.logic {

public class Parser : IEnumerable, IEnumerator {

private char[] m_a;

private int m_len;

private int m_cur = 0;

private int m_new_cur = -1;

private bool m_at_begin;

private static readonly string[] s_keywords =

new string[] {

"if",

"else",

"elseif",

"endif",

"while",

"loop",

"return",

"call",

"print",

"println",

"readln",

"clear",

"for",

"next",

"error"

};

private static readonly int s_keywords_length = s_keywords.Length;

private static bool IsLD(char c) {

return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || (c == '0')

|| ((c >= '1') && (c <= '9')) || (c == '_');

}

private static bool IsSp(char c) {

return (c == ' ') || (c == '&bsol;t');

}

public static bool IsID(string str) {

int l = str.Length;

if (l == 0)

return false;

if (char.IsDigit(str[0]) || (!IsLD(str[0])))

return false;

int i;

for (i = 1; i < str.Length; i++)

if (!IsLD(str[i]))

return false;

for (i = 0; i < s_keywords_length; i++)

if (str == s_keywords[i])

return false;

return true;

}

public void Reset() {

m_cur = 0;

m_new_cur = -1;

m_at_begin = true;

}

public string GetString() {

return new String(m_a, 0, m_len);

}

public bool HasMore() {

return m_cur < m_len;

}

public Parser(string str) {

char[] a = str.ToCharArray();

int n = a.Length;

int i = 0;

int j = 0;

m_a = new char[n];

while (i < n) {

if (a[i] == '#') {

break;

} else if (a[i] == '&bsol;"') {

m_a[j] = '&bsol;"';

i++;

j++;

while ((i < n) && (a[i] != '&bsol;"')) {

m_a[j] = a[i];

i++;

j++;

}

if (i == n)

throw new SyntaxErrorException("Не закрытая строковая константа");

else {

m_a[j] = '&bsol;"';

i++;

j++;

}

} else if (IsSp(a[i])) {

bool flag = false;

if ((i > 0) && (IsLD(a[i - 1]))) {

m_a[j] = ' ';

j++;

flag = true;

}

while ((i < n) && IsSp(a[i]))

i++;

if (((i == n) || (!IsLD(a[i]))) && flag)

j--;

} else {

m_a[j] = a[i];

i++;

j++;

}

}

m_len = j;

Reset();

}

private string GetCurrent() {

int cur = m_cur;

int beg = m_cur;

int end = m_len;

string res = null;

bool flag = true;

if ((m_a[cur] == '.') && ((cur < end - 1) && (!char.IsDigit(m_a[cur + 1]))) || (cur == end - 1)) {

flag = true;

} else if (char.IsDigit(m_a[cur]) || (m_a[cur] == '.')) {

flag = false;

while ((cur < end) && char.IsDigit(m_a[cur]))

cur++;

if (cur == end) {

res = new String(m_a, beg, cur - beg);

} else if ((m_a[cur] == 'e') || (m_a[cur] == 'E')) {

cur++;

if (cur == end) {

cur--;

res = new String(m_a, beg, cur - beg);

} else if ((m_a[cur] == '+') || (m_a[cur] == '-')) {

cur++;

if ((cur == end) || (!char.IsDigit(m_a[cur]))) {

cur -= 2;

res = new String(m_a, beg, cur - beg);

}

while ((cur < end) && char.IsDigit(m_a[cur]))

cur++;

res = new String(m_a, beg, cur - beg);

} else if (char.IsDigit(m_a[cur])) {

while ((cur < end) && char.IsDigit(m_a[cur]))

cur++;

res = new String(m_a, beg, cur - beg);

} else {

cur--;

res = new String(m_a, beg, cur - beg);

}

} else if (m_a[cur] == '.') {

cur++;

if ((cur == end) || (!char.IsDigit(m_a[cur]))) {

cur--;

res = new String(m_a, beg, cur - beg);

} else {

while ((cur < end) && char.IsDigit(m_a[cur]))

cur++;

if (cur == end)

res = new String(m_a, beg, cur - beg);

else if ((m_a[cur] == 'e') || (m_a[cur] == 'E')) {

cur++;

if (cur == end) {

cur--;

res = new String(m_a, beg, cur - beg);

} else if ((m_a[cur] == '+') || (m_a[cur] == '-')) {

cur++;

if ((cur == end) || (!char.IsDigit(m_a[cur]))) {

cur -= 2;

res = new String(m_a, beg, cur - beg);

}

while ((cur < end) && char.IsDigit(m_a[cur]))

cur++;

res = new String(m_a, beg, cur - beg);

} else if (char.IsDigit(m_a[cur])) {

while ((cur < end) && char.IsDigit(m_a[cur]))

cur++;

res = new String(m_a, beg, cur - beg);

} else {

cur--;

res = new String(m_a, beg, cur - beg);

}

} else

res = new String(m_a, beg, cur - beg);

}

} else

res = new String(m_a, beg, cur - beg);

}

if (flag) {

if (IsLD(m_a[cur])) {

while ((cur < end) && IsLD(m_a[cur]))

cur++;

res = new String(m_a, beg, cur - beg);

} else if (m_a[cur] == '&bsol;"') {

do {

cur++;

if (m_a[cur] == '&bsol;"') {

if ((cur < end - 1) && (m_a[cur + 1] == '&bsol;"'))

cur++;

else

break;

}

} while (true);

cur++;

res = new String(m_a, beg, cur - beg);

} else if (cur < end - 1) {

switch (m_a[cur]) {

case ':':

{

cur++;

if (m_a[cur] == '=') {

cur++;

res = ":=";

} else

res = ":";

break;

}

case '~':

{

cur++;

if (m_a[cur] == '=') {

cur++;

res = "~=";

} else

res = "~";

break;

}

case '>':

{

cur++;

if (m_a[cur] == '=') {

cur++;

res = ">=";

} else

res = ">";

break;

}

case '<':

{

cur++;

switch (m_a[cur]) {

case '=':

{

cur++;

res = "<=";

break;

}

case '>':

{

cur++;

res = "<>";

break;

}

default:

{

res = "<";

break;

}

}

break;

}

default:

{

res = m_a[cur].ToString();

cur++;

break;

}

}

} else {

res = m_a[cur].ToString();

cur++;

}

}

if ((cur < end) && IsSp(m_a[cur]))

cur++;

m_new_cur = cur;

return res;

}

public object Current {

get { return GetCurrent(); }

}

public bool MoveNext() {

if (m_at_begin) {

m_at_begin = false;

return HasMore();

}

if (m_new_cur < 0)

GetCurrent();

m_cur = m_new_cur;

m_new_cur = -1;

return HasMore();

}

public IEnumerator GetEnumerator() {

return this;

}

public static bool IsUserID(string name) {

if (!IsID(name))

return false;

if (name == "abs")

return false;

if (name == "cos")

return false;

if (name == "sin")

return false;

if (name == "tg")

return false;

if (name == "arccos")

return false;

if (name == "arcsin")

return false;

if (name == "arctg")

return false;

if (name == "exp")

return false;

if (name == "pow")

return false;

if (name == "ln")

return false;

if (name == "lg")

return false;

if (name == "log")

return false;

if (name == "sqrt")

return false;

if (name == "pi")

return false;

if (name == "idiv")

return false;

if (name == "iff")

return false;

if (name == "imod")

return false;

if (name == "random")

return false;

if (name == "substr")

return false;

if (name == "strlen")

return false;

if (name == "strpos")

return false;

if (name == "toint")

return false;

if (name == "toreal")

return false;

if (name == "tostring")

return false;

if (name == "isarray")

return false;

if (name == "issingle")

return false;

if (name == "isstring")

return false;

if (name == "isnum")

return false;

if (name == "isreal")

return false;

if (name == "isint")

return false;

if (name == "size")

return false;

return true;

}

}

}

11. Класс LineCompiler.

using System;

using interpr.logic.operators;

namespace interpr.logic {

public class LineCompiler {

private LineCompiler() {}

public static Command CompileCommand(string str) {

Parser p = new Parser(str);

if (!p.HasMore()) {

return new EmptyCommand();

}

String pstr = p.GetString();

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

}

}

}

p.MoveNext();

string firsttoken = (p.Current as String);

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;

}

if (firsttoken == "print") {

Expression expr = new Expression(p);

return new PrintCommand(expr);

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

Expression expr = new Expression(p);

return new PrintLnCommand(expr);