Смекни!
smekni.com

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

}

public Moment(Subroutine sub) {

m_sub = sub;

m_pos = 1;

s_break = 0;

}

public void GoTo(int to) {

m_pos = to;

}

public void Next() {

m_pos++;

}

public void Run() {

while (m_pos < m_sub.m_count) {

if (s_break == 1)

throw new CalcException("Прервано пользователем");

(m_sub.m_operators[m_pos] as IOperator).Execute(this);

}

}

public void Return() {

m_pos = m_sub.m_count;

}

public IOperator Current {

get { return m_sub.m_operators[m_pos] as IOperator; }

}

}

}

}

17. Класс Facade.

using System.Threading;

using interpr.logic;

using interpr.logic.operators;

namespace interpr {

public class Facade {

private static Facade s_instance = null;

public static void Create(IConsole console) {

if (s_instance == null)

s_instance = new Facade(console);

}

public static Facade Instance {

get { return s_instance; }

}

private IConsole m_console;

private InterprEnvironment m_env;

private string m_cmd;

private bool m_doing = false;

private Facade(IConsole console) {

m_console = console;

m_env = InterprEnvironment.Instance;

m_env.CurrentConsole = m_console;

}

public delegate void CommandDoneHandler();

public event CommandDoneHandler Done;

private void ThrStart() {

m_doing = true;

Command cmd;

do {

try {

cmd = LineCompiler.CompileCommand(m_cmd);

}

catch (SyntaxErrorException ex) {

m_env.CurrentConsole.PrintLn("Ошибка : " + ex.Message);

break;

}

try {

cmd.Execute();

}

catch (CalcException ex) {

m_env.CurrentConsole.PrintLn("Ошибка : " + ex.Message);

m_env.CurrentNamespace = m_env.ConsoleNamespace;

break;

}

} while (false);

Done();

m_doing = false;

}

public void ExecuteCommand(string cmd) {

if (m_doing)

throw new OtherException("Error in Bridge.ExecuteCommand()");

m_cmd = cmd;

new Thread(new ThreadStart(ThrStart)).Start();

}

private void DoRestart() {

if (m_doing)

Subroutine.Moment.Break();

while (m_doing) {}

InterprEnvironment.Reset();

m_env = InterprEnvironment.Instance;

m_env.CurrentConsole = m_console;

m_env.LoadSubs();

}

public void Restart() {

new Thread(new ThreadStart(DoRestart)).Start();

}

public bool Busy {

get { return m_doing; }

}

public void SaveVariables() {

m_env.SaveVars();

}

public void LoadSubs() {

m_env.LoadSubs();

}

public ConsoleNamespace.VariableReport[] GetVariables() {

return m_env.GetGlobalVarsList();

}

public string[] GetSubs() {

return m_env.LoadedSubs;

}

public void DeleteVariable(string name) {

m_env.ConsoleNamespace.Remove(name);

}

public bool LoadSub(string name) {

return m_env.LoadSub(name);

}

public void UnloadSub(string name) {

m_env.UnloadSub(name);

}

public bool NotRestored {

get {

return m_env.NotRestored;

}

}

}

}

18. Класс SourceBox.

using System;

using System.ComponentModel;

using System.Drawing;

using System.Windows.Forms;

namespace interpr {

public class SourceBox : UserControl {

private RichTextBox m_tb;

private TextBox m_tb_2;

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

private int m_curline = 0;//текущаястрока

private int m_lincount = 0;//общеечислострок

private HighlightParser m_hp = new HighlightParser();

private static Font s_nfont =

new Font("Lucida Console", 10, FontStyle.Regular);

private static Font s_cfont =

new Font("Lucida Console", 12, FontStyle.Bold);

private int GetCurrentLine() {

return m_tb.GetLineFromCharIndex(m_tb.SelectionStart);

}

private int GetLinesCount() {

return m_tb.Lines.Length;

}

private String GetLine(int index) {

return m_tb.Lines[index];

}

private void m_tb_KeyPress(object sender, KeyPressEventArgs e) {

if (e.KeyChar == '&bsol;r') {

string txt = m_tb.Text;

int i = m_tb.SelectionStart - 2;

int j;

while (i >= 0) {

if (txt[i] == '&bsol;n')

return;

else if (txt[i] == '&bsol;t') {

j = 0;

while ((i >= 0) && (txt[i] == '&bsol;t')) {

j++;

i--;

}

if ((i < 0) || (txt[i] == '&bsol;n')) {

m_tb.SelectedText = new String('&bsol;t', j);

return;

}

}

i--;

}

}

}

private bool GetLinePos(int index, out int beg, out int len) {

if ((index < 0) || (index >= GetLinesCount())) {

beg = len = 0;

return false;

}

int i;

string[] ls = m_tb.Lines;

beg = 0;

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

beg += ls[i].Length + 1;

len = ls[index].Length;

return true;

}

private void SelectLine(int index) {

int beg, len;

if (!GetLinePos(index, out beg, out len))

throw new IndexOutOfRangeException();

m_tb.SelectionStart = beg;

m_tb.SelectionLength = len;

}

private void HighlightLine(int index) {

int beg, len;

int curbeg = m_tb.SelectionStart;

int curlen = m_tb.SelectionLength;

GetLinePos(index, out beg, out len);

string str = m_tb.Lines[index];

m_hp.Reset(str);

while (m_hp.HasMore()) {

int tbeg, tlen;

HighlightParser.TokenType type;

m_hp.GetNext(out tbeg, out tlen, out type);

m_tb.SelectionStart = beg + tbeg;

m_tb.SelectionLength = tlen;

switch (type) {

case HighlightParser.TokenType.Comment:

{

m_tb.SelectionColor = Color.DarkGreen;

break;

}

case HighlightParser.TokenType.Identifier:

{

m_tb.SelectionColor = Color.Purple;

break;

}

case HighlightParser.TokenType.Keyword:

{

m_tb.SelectionColor = Color.Blue;

break;

}

case HighlightParser.TokenType.Number:

{

m_tb.SelectionColor = Color.Red;

break;

}

case HighlightParser.TokenType.String:

{

m_tb.SelectionColor = Color.Brown;

break;

}

case HighlightParser.TokenType.Other:

{

m_tb.SelectionColor = Color.Black;

break;

}

}

}

m_tb.SelectionStart = curbeg;

m_tb.SelectionLength = curlen;

}

public enum LineState {

ErrorLine,

CurrentLine,

NormalLine

}

private void ColorLine(int index, LineState state) {

int curbeg = m_tb.SelectionStart;

int curlen = m_tb.SelectionLength;

SelectLine(index);

switch (state) {

case LineState.ErrorLine:

{

m_tb.SelectionColor = Color.Red;

break;

}

case LineState.CurrentLine:

{

m_tb.SelectionFont = s_cfont;

break;

}

case LineState.NormalLine:

{

m_tb.SelectionFont = s_nfont;

HighlightLine(index);

break;

}

}

m_tb.SelectionStart = curbeg;

m_tb.SelectionLength = curlen;

}

private void HighlightText(bool anyway) {

int l = GetCurrentLine();

int lc = GetLinesCount();

if ((l != m_curline) || (lc != m_lincount) || anyway) {

m_tb_2.Focus();

m_curline = l;

m_lincount = lc;

int bi = m_tb.GetCharIndexFromPosition(new Point(0, 0));

int ei = m_tb.GetCharIndexFromPosition(new Point(m_tb.Size));

int bl = m_tb.GetLineFromCharIndex(bi);

int el = m_tb.GetLineFromCharIndex(ei);

if (bl > 0) bl--;

if (el < lc) el++;

for (int i = bl; i < el; i++)

HighlightLine(i);

m_tb.Focus();

}

}

private void m_tb_KeyUp(object sender, KeyEventArgs e) {

HighlightText(false);

}

private void m_tb_MouseUp(object sender, MouseEventArgs e) {

if (e.Button == MouseButtons.Left)

HighlightText(true);

}

public string[] Lines {

get { return (string[]) m_tb.Lines.Clone(); }

}

public bool LoadFile(string filename) {

try {

m_tb.LoadFile(filename, RichTextBoxStreamType.PlainText);

HighlightText(true);

return true;

}

catch {

return false;

}

}

public bool SaveFile(string filename) {

try {

m_tb.SaveFile(filename, RichTextBoxStreamType.PlainText);

return true;

}

catch {

return false;

}

}

public int CurrentLine {

get { return m_tb.GetLineFromCharIndex(m_tb.SelectionStart); }

}

private class HighlightParser {

private char[] m_a;

private int m_len;

private int m_cur;

public enum TokenType {

String,

Number,

Keyword,

Comment,

Identifier,

Other

}

public void Reset(string str) {

m_a = str.ToCharArray();

m_len = str.Length;

m_cur = 0;

while ((m_cur < m_len) && Char.IsWhiteSpace(m_a[m_cur]))

m_cur++;

}

public bool HasMore() {

return m_cur < m_len;

}

private bool IsKeyword(string str) {

return

(str == "if") ||

(str == "else") ||

(str == "elseif") ||

(str == "endif") ||

(str == "while") ||

(str == "loop") ||

(str == "return") ||

(str == "result") ||

(str == "call") ||

(str == "print") ||

(str == "println") ||

(str == "readln") ||

(str == "clear") ||

(str == "for") ||

(str == "next") ||

(str == "error");

}

public void GetNext(out int beg, out int len, out TokenType type) {

if (m_cur >= m_len)

throw new IndexOutOfRangeException();

beg = m_cur;

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

m_cur++;

while ((m_cur < m_len) && (m_a[m_cur] != '&bsol;"'))

m_cur++;

if (m_cur < m_len)

m_cur++;

len = m_cur - beg;

type = TokenType.String;

}

else if (isL(m_a[m_cur])) {

m_cur++;

while ((m_cur < m_len) && isLD(m_a[m_cur]))

m_cur++;

len = m_cur - beg;

if (IsKeyword(new string(m_a, beg, len)))

type = TokenType.Keyword;

else

type = TokenType.Identifier;

}

else if (m_a[m_cur] == '#') {

len = m_len - m_cur;

m_cur = m_len;

type = TokenType.Comment;

}

else if (m_a[m_cur] == '.') {

if (GetNumber()) {

len = m_cur - beg;

type = TokenType.Number;

}

else {

m_cur = beg + 1;

len = 1;

type = TokenType.Other;

}

}

else if (char.IsDigit(m_a[m_cur])) {

GetNumber();

len = m_cur - beg;

type = TokenType.Number;

}

else {

m_cur++;

len = 1;

type = TokenType.Other;

}

while ((m_cur < m_len) && Char.IsWhiteSpace(m_a[m_cur]))

m_cur++;

}

private bool GetNumber() {

if (!((m_a[m_cur] == '.') || char.IsDigit(m_a[m_cur])))

return false;

while ((m_cur < m_len) && char.IsDigit(m_a[m_cur]))

m_cur++;

if (m_cur == m_len)

return true;

else if (m_a[m_cur] == '.') {

m_cur++;

while ((m_cur < m_len) && char.IsDigit(m_a[m_cur]))

m_cur++;

if (m_cur == m_len)

return true;

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

int p1 = m_cur;

m_cur++;

if (m_cur == m_len) {

m_cur = p1;

return true;

}

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

m_cur++;

if ((m_cur == m_len) || !char.IsDigit(m_a[m_cur])) {

m_cur = p1;

return true;

}

while ((m_cur < m_len) && char.IsDigit(m_a[m_cur]))

m_cur++;

return true;

}

else if (char.IsDigit(m_a[m_cur])) {

while ((m_cur < m_len) && char.IsDigit(m_a[m_cur]))

m_cur++;

return true;

}

else {

m_cur = p1;

return true;

}

}

else

return true;

}

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

int p1 = m_cur;

m_cur++;

if (m_cur == m_len) {

m_cur = p1;

return true;

}

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

m_cur++;

if ((m_cur == m_len) || !char.IsDigit(m_a[m_cur])) {

m_cur = p1;

return true;

}

while ((m_cur < m_len) && char.IsDigit(m_a[m_cur]))

m_cur++;

return true;

}

else if (char.IsDigit(m_a[m_cur])) {

while ((m_cur < m_len) && char.IsDigit(m_a[m_cur]))

m_cur++;

return true;

}

else {

m_cur = p1;

return true;

}

}

else

return true;

}

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 isL(char c) {

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

}

}

}

}

19. Класс Form1.

using System;

using System.ComponentModel;

using System.Windows.Forms;

namespace interpr {

public class Form1 : Form {

private Panel panel1;

private Button button1;

private Button button2;

private Button button3;

private Button button4;

private Button button5;

private ConsoleBox consoleBox1;

private Facade m_fasade;

private void Form1_Load(object sender, EventArgs e) {

Facade.Create(consoleBox1);

m_fasade = Facade.Instance;

if (m_fasade.NotRestored) {

MessageBox.Show("Ошибка! Переменные не были успешно восстановлены.");

}

m_fasade.Done += new Facade.CommandDoneHandler(EndExec);

m_fasade.LoadSubs();

consoleBox1.Prompt();

}

private void EndExec() {

consoleBox1.Prompt();

}

private void button1_Click(object sender, EventArgs e) {

if (m_fasade.Busy) {

MessageBox.Show("Не могу открыть окно функций во время выполнения комманды!");

return;

}

FunctionsForm ff = new FunctionsForm(m_fasade);

ff.ShowDialog();

EditorForm ef = ff.LastOpenedEditorForm;

if (ef != null) {

ef.Activate();

ff.SetLastEditorFormNull();

}

else

consoleBox1.Focus();

}

private void button2_Click(object sender, EventArgs e) {

if (m_fasade.Busy) {

MessageBox.Show("Не могу открыть окно переменных во время выполнения комманды!");

return;

}

VariablesForm vf = new VariablesForm(m_fasade);

vf.ShowDialog();

consoleBox1.Focus();

}

private void consoleBox1_GetCommand(object sender, ConsoleBoxGetCommandEventArgs e) {

if (e.Command.Length > 0)

m_fasade.ExecuteCommand(e.Command);

else

consoleBox1.Prompt();

}

private void button3_Click(object sender, EventArgs e) {

m_fasade.Restart();

if (m_fasade.NotRestored) {

MessageBox.Show("Ошибка! Переменные не были успешно восстановлены.");

}

consoleBox1.Focus();

}

private void button5_Click(object sender, EventArgs e) {

if (m_fasade.Busy) {

MessageBox.Show("Не могу сохранить переменные во время выполнения программы");

return;

}

m_fasade.SaveVariables();

consoleBox1.Focus();

}

private void Form1_Closing(object sender, CancelEventArgs e) {

if (EditorForm.ThereAreOpened()) {

MessageBox.Show("Сначалазакройтевсеокнаредакторакода.");

e.Cancel = true;

return;

}

m_fasade.SaveVariables();

}

private void button4_Click(object sender, EventArgs e) {

this.Close();

}

}

}


Использованная литература и документация.

1. А. Ахо, Дж. Хопкрофт, Д. Ульман. Структуры данных и алгоритмы – М. «Вильямс», 2003.

2. Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес. Приемы объектно-ориентированного проектирования: паттерны проектирования – СПб., «Питер», 2001.

3. Д. Грис. Конструирование компиляторов для цифровых вычислительных машин – М. «Мир», 1975.

4. Г. Корнелл, Дж. Моррисон. Программирование на VB.NET. Учебный курс – СПб., «Питер», 2002.

5. Э. Троелсен. C# и платформа .NET – СПб., «Питер», 2004.

6. MSDN Library – April 2003.