• Nhận tập mã lệnh, tách ra từng dòng. • Tiến hành các bước khởi tạo cần thiết.
• Vòng lặp qua từng dòng lệnh nếu chưa gặp lỗi: o Phân tích dòng lệnh, tạo cấu trúc ngữ nghĩa.
o Tùy thuộc phân loại ngữ nghĩa mà gọi hàm thi hành tương ứng.
d. Viết mã lệnh
Syntax: [ Download ] [ Hide ] [ Select ] [ Contract ]
Using csharp Syntax Highlighting
using System;
using System.Collections.Generic;
namespace BieuThuc.LienHoa {
class Interpreter {
// Các ủy thác hàm nhập xuất
public delegate string stdinDelegate();
public delegate void stdoutDelegate(string s);
public delegate void stderrDelegate(string s);
#region Các biến toàn cục
// Các lớp hỗ trợ
private Parser mParser;
private Lexer mLexer;
private Error mError;
// Các hàm nhập xuất
private stdinDelegate stdin;
private stdoutDelegate stdout;
private stderrDelegate stderr;
// Ngăn xếp các đối số
private Stack<Memory.Record> FunctionArguments;
// Mảng các lệnh
private string[] CodeLines;
// Chỉ mục dòng lệnh
public int CurrentLine;
// Cờ lỗi
public bool NoError;
// Dấu xuống dòng
public string LineTerminator = "\r\n";
#endregion
#region Các hàm chính
public Interpreter(stdinDelegate i, stdoutDelegate o, stderrDelegate e) {
this.stdin = i;
this.stdout = o;
this.stderr = e;
this.mError = new Error(this, e);
this.mMemory = new Memory(this.mError);
this.mLexer = new Lexer(this.mError);
this.mParser = new Parser(this.mLexer, this.mError);
this.FunctionArguments = new Stack<Memory.Record>();
this.NoError = true;
this.FuncTable = new FuncDelegate[] {
f_sqrt, f_abs, f_sin, f_cos, f_tan, f_asin, f_acos, f_atan, f_left, f_mid, f_right, f_chr, f_ord, f_len, f_toint, f_tofloat,
f_readln, f_print, f_println };
}
public bool Run(string code) {
int LinesCount;
Parser.Semantics sem = new Parser.Semantics();
string[] sep = new string[] { "\n" };
CodeLines = code.Replace("\r\n", "\n").Split(sep, StringSplitOptions.None);
LinesCount = CodeLines.Length;
Init();
while (NoError && CurrentLine < LinesCount) {
if (mParser.Parse(CodeLines[CurrentLine+ +], ref sem) == false)return false;
switch (sem.Class) {
case Parser.SemanticsClass.Declare:
if (ExecuteDeclare(sem) == false) return false;
break;
case Parser.SemanticsClass.DeclareEx:
if (ExecuteDeclareEx(sem) == false) return false;
break;
case Parser.SemanticsClass.Assign:
if (ExecuteAssign(sem) == false) return false;
break;
case Parser.SemanticsClass.FunctionCall:
if (ExecuteFunctionCall(sem) == false) returnfalse;
break; default: break; } } return true; }
private void Init() {
CurrentLine = 0;
mMemory.ClearMemory();
}
private bool ExecuteDeclare(Parser.Semantics sem) {
Memory.Record r = new Memory.Record();
switch ((Lexer.KeywordClass)sem.TokenList[0].IntValue) {
case Lexer.KeywordClass.INT:
r.IntValue = 0;
break;
case Lexer.KeywordClass.FLOAT:
r.FloatValue = 0f;
break;
case Lexer.KeywordClass.STRING:
r.StringValue = string.Empty;
break;
}
if (mMemory.AddRecord(sem.Identifier, r) == false) return false;
return true;
}
private bool ExecuteDeclareEx(Parser.Semantics sem) {
Memory.Record r = new Memory.Record();
switch ((Lexer.KeywordClass)sem.TokenList[0].IntValue) {
case Lexer.KeywordClass.INT:
r.IntValue = 0;
break;
case Lexer.KeywordClass.FLOAT:
r.FloatValue = 0f;
break;
case Lexer.KeywordClass.STRING:
r.StringValue = string.Empty;
break;
}
if (Evaluate(sem, 1, ref r) == false) return false;
if (mMemory.AddRecord(sem.Identifier, r) == false) return false;
}
private bool ExecuteAssign(Parser.Semantics sem) {
Memory.Record r = new Memory.Record();
if (Evaluate(sem, 0, ref r) == false) return false;
if (mMemory.ModifyRecord(sem.Identifier, r) == false) return false;
return true;
}
private bool ExecuteFunctionCall(Parser.Semantics sem) {
Memory.Record r = new Memory.Record();
if (Evaluate(sem, 0, ref r) == false) return false;
return true;
}
private bool Evaluate(Parser.Semantics sem, int startpos, ref Memory.Record r) {
Stack<Memory.Record> res = new Stack<Memory.Record>();
Lexer.Token tmp;
Memory.Record a = new Memory.Record();
Memory.Record b = new Memory.Record();
int total = sem.TokenList.Count;
int argcount = 0;
for (int i = startpos; i < total; ++i) {
tmp = sem.TokenList[i ];
switch (tmp.Class) {
case Lexer.TokenClass.NumInt:
res.Push(new Memory.Record(tmp.IntValue));
break;
case Lexer.TokenClass.NumFloat:
res.Push(new Memory.Record(tmp.FloatValue));
break;
case Lexer.TokenClass.String:
res.Push(new Memory.Record(tmp.StringValue));
break;
case Lexer.TokenClass.Ident:
res.Push(a);
break;
case Lexer.TokenClass.Plus:
b = res.Pop();
a = res.Pop();
res.Push(a + b);
break;
case Lexer.TokenClass.Minus:
b = res.Pop();
a = res.Pop();
res.Push(a - b);
break;
case Lexer.TokenClass.Mul:
b = res.Pop();
a = res.Pop();
res.Push(a * b);
break;
case Lexer.TokenClass.Div:
b = res.Pop();
a = res.Pop();
if (b.IntValue == 0) {
mError.RaiseError(Error.ErrorConstant.DivisionByZero);
return false; } else { res.Push(a / b); } break;
case Lexer.TokenClass.Mod:
b = res.Pop();
a = res.Pop();
if (b.IntValue == 0) {
mError.RaiseError(Error.ErrorConstant.DivisionByZero);
return false; } else { res.Push(a % b); } break;
case Lexer.TokenClass.Pow:
b = res.Pop();
res.Push(a.Pow(b));
break;
case Lexer.TokenClass.UMinus:
res.Push(-res.Pop());
break;
case Lexer.TokenClass.Func:
// Tính số lượng đối số cần lấy
argcount = mParser.FunctionArgCount[tmp.IntValue];
// Lấy các đối số từ ngăn xếp
for (int k = 0; k < argcount; ++k)
FunctionArguments.Push(res.Pop());
// Gọi hàm
if (FuncTable[tmp.IntValue] (ref a) == false)return false;
// Lưu kết quả res.Push(a); break; } //switch } //while r = res.Pop(); return true; } #endregion
#region Các hàm cho sẵn của chương trình
private delegate bool FuncDelegate(ref Memory.Record r);
private FuncDelegate[] FuncTable;
private bool f_sqrt(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
case Memory.DataType.Float:
r.FloatValue = (float)Math.Sqrt(a.FloatValue);
break; default: r.FloatValue = 0f; break; } return true; }
private bool f_abs(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
r.IntValue = Math.Abs(a.IntValue);
break;
case Memory.DataType.Float:
r.FloatValue = Math.Abs(a.FloatValue);
break; default: r.IntValue = 0; break; } return true; }
private bool f_sin(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
case Memory.DataType.Float:
r.FloatValue = (float)Math.Sin(a.FloatValue);
break; default: r.FloatValue = 0f; break; } return true; }
private bool f_cos(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
case Memory.DataType.Float:
r.FloatValue = (float)Math.Cos(a.FloatValue);
break; default: r.FloatValue = 0f; break; } return true;
}
private bool f_tan(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
case Memory.DataType.Float:
r.FloatValue = (float)Math.Tan(a.FloatValue);
break; default: r.FloatValue = 0f; break; } return true; }
private bool f_asin(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
case Memory.DataType.Float:
r.FloatValue = (float)Math.Asin(a.FloatValue);
break; default: r.FloatValue = 0f; break; } return true; }
private bool f_acos(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
case Memory.DataType.Float:
r.FloatValue = (float)Math.Acos(a.FloatValue);
break; default: r.FloatValue = 0f; break; } return true;
}
private bool f_atan(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
case Memory.DataType.Float:
r.FloatValue = (float)Math.Atan(a.FloatValue);
break; default: r.FloatValue = 0f; break; } return true; }
private bool f_left(ref Memory.Record r) {
string a1s = FunctionArguments.Pop().StringValue;
Memory.Record a2 = FunctionArguments.Pop();
try
{
r.StringValue = a1s.Substring(0, a2.IntValue);
} catch (ArgumentOutOfRangeException) { r.StringValue = a1s; } return true; }
private bool f_mid(ref Memory.Record r) {
string a1s = FunctionArguments.Pop().StringValue;
Memory.Record a2 = FunctionArguments.Pop();
Memory.Record a3 = FunctionArguments.Pop();
try
{
r.StringValue = a1s.Substring(a2.IntValue, a3.IntValue);
}
catch (ArgumentOutOfRangeException) {
r.StringValue = a1s;
return true;
}
private bool f_right(ref Memory.Record r) {
string a1s = FunctionArguments.Pop().StringValue;
Memory.Record a2 = FunctionArguments.Pop();
try
{
r.StringValue = a1s.Substring(a1s.Length - a2.IntValue);
} catch (ArgumentOutOfRangeException) { r.StringValue = a1s; } return true; }
private bool f_chr(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
switch (a.Type) {
case Memory.DataType.Int:
case Memory.DataType.Float:
try
{
r.StringValue = ((char)a.IntValue).ToString();
}
catch (ArgumentOutOfRangeException) {
r.StringValue = string.Empty;
} break;
default:
r.StringValue = string.Empty;
break;
}
return true;
}
private bool f_ord(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
try
{
} catch (IndexOutOfRangeException) { r.IntValue = 0; } return true; }
private bool f_len(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
r.IntValue = a.StringValue.Length;
return true;
}
private bool f_toint(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
int i;
float f;
if (a.Type == Memory.DataType.String) {
float.TryParse(a.StringValue, out f);
i = (int)f; } else { i = a.IntValue; } r.IntValue = i; return true; }
private bool f_tofloat(ref Memory.Record r) {
Memory.Record a = FunctionArguments.Pop();
float f;
if (a.Type == Memory.DataType.String)
float.TryParse(a.StringValue, out f);
else
f = a.FloatValue;
r.FloatValue = f;
return true;
private bool f_readln(ref Memory.Record r) { string s = stdin(); r.StringValue = s; return true; }
private bool f_print(ref Memory.Record r) {
string s = FunctionArguments.Pop().StringValue;
r.IntValue = s.Length;
stdout(s);
return true;
}
private bool f_println(ref Memory.Record r) {
string s = FunctionArguments.Pop().StringValue;
r.IntValue = s.Length; stdout(s + LineTerminator); return true; } #endregion } }
Parsed in 0.092 seconds, using GeSHi 1.0.8.4
7. Giao diện