📄 plxanalyzer.cs
字号:
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace PLX
{
class PLXAnalyzer
{
#region Error Message
readonly int ER_EQL_NOT_BECOMES = 1; //要用=,不能用:=
readonly int ER_ONLY_NUMBER = 2; //必须给常量赋常数
readonly int ER_ONLY_EQL = 3; //这里必须是一个=
readonly int ER_ONLY_IDIENT = 4; //这里必须是一个标识符
readonly int ER_MISS_COMMA_OR_SEMICOLON = 5; //丢了一个分号或逗号
readonly int ER_DECLARATION = 6; //声明时出现了不正确的标识符
readonly int ER_WAIT_STATEMENT = 7; //等待一条语句
readonly int ER_ID_REDUNDANCY = 8; //标识符重复定义
readonly int ER_NO_CONSTID = 9; //不能调用常量标识符
readonly int ER_INCORRECT_SYMBOL = 10; //语句里有不正确的符号
readonly int ER_ID_NOTFOUND = 11; //该标识符没有声明
readonly int ER_TYPE_NOT_MATCH = 12; //声明的类型与赋值的类型不匹配
readonly int ER_ONLY_BECOMES = 13; //赋值符是:=
readonly int ER_FOLLOW_WRONG_SYMBOL = 14; //该语句跟着一个不正确的使用符号
readonly int ER_ILLEGAL_CALL = 15; //call常数或者变量是不允许的
readonly int ER_WAIT_THEN = 16; //等待then
readonly int ER_WAIT_END = 17; //等待end
readonly int ER_WAIT_DO = 18; //等待do
readonly int ER_WAIT_UNTIL = 19; //等待until
readonly int ER_WAIT_RELATION_OPR = 20; //等待关系运算符
readonly int ER_NO_PROCEDUREID = 21; //表达式里不允许有过程标识符
readonly int ER_MISS_LPAREN = 22; //丢失左(
readonly int ER_MISS_RPAREN = 23; //丢失右)
readonly int ER_MIN_ARRAY_LENGHT = 24; //数组的项数必须大于等于1
readonly int ER_ARRAY_ITEMS_NOT_MATCH = 25; //数组的项数与声明时不符
readonly int ER_EXCEED_BIT = 26; //数字常量超过32位
readonly int ER_MUST_NUMBER_OR_CONST = 27; //必须是数字或常量
readonly int ER_MISS_LSQBRACKET = 28; //丢失左[
readonly int ER_MISS_RSQBRACKET = 29; //丢失右]
readonly int ER_MISS_LBGBRACKET = 30; //丢失左{
readonly int ER_MISS_RBGBRACKET = 31; //丢失右}
readonly int ER_ILLEGAL_ARRAY_INDEX = 32; //非法的数组索引
readonly int ER_MUST_BEGINWITH_PROGRAM = 33; //程序必须以program开始
readonly int ER_MUST_ENDWITH_DOT = 34; //程序必须以.结束
readonly int ER_ONLY_LOGICAL_VAR_OR_CONST = 35; //这里必须是一个逻辑变量或者常量
readonly int ER_ONLY_INT_VAR_OR_CONST = 36; //这里必须是一个INTGER变量或者常量
readonly int ER_WRONG_BEGINID_INTFACTOR = 37; //算术表达式不能以此符号开始
readonly int ER_WRONG_BEGINID_LOGICALFACTOR = 38; //逻辑表达式不能以此符号开头
readonly int ER_WRONG_BEGINID_OPRFACTOR = 39; //关系表达式不能以此符号开头
readonly string[] strErrorMsg = new string[]
{
"要用=,不能用:=" ,
"必须给常量赋常数" ,
"这里必须是一个=" ,
"这里必须是一个标识符" ,
"丢了一个分号或逗号" ,
"声明时出现了不正确的标识符" ,
"等待一条语句" ,
"标识符重复定义" ,
"不能调用常量标识符" ,
"语句里有不正确的符号" ,
"该标识符没有声明" ,
"声明的类型与赋值的类型不匹配" ,
"赋值符是:=" ,
"该语句跟着一个不正确的使用符号" ,
"call常数或者变量是不允许的" ,
"等待then" ,
"等待end" ,
"等待do" ,
"等待until" ,
"等待关系运算符" ,
"表达式里不允许有过程标识符" ,
"丢失左(" ,
"丢失右)" ,
"数组的项数必须大于等于1" ,
"数组的项数与声明时不符" ,
"数字常量超过位" ,
"必须是数字或常量" ,
"丢失左[" ,
"丢失右]" ,
"丢失左{" ,
"丢失右}" ,
"非法的数组索引" ,
"程序必须以program开始" ,
"程序必须以.结束" ,
"这里必须是一个逻辑变量或者常量" ,
"这里必须是一个INTGER变量或者常量",
"算术表达式不能以此符号开始",
"逻辑表达式不能以此符号开始"
};
#endregion
#region Const Definition
const int NUM_OF_REAERVED_WORDS = 21;
const int NUM_OF_OPR_WORDS = 17;
const int LENGTH_OF_ID_TABLE = 100;
const int MAX_NO_OF_DIGITS_IN_NUM = 32;
const int LENGTH_OF_ID = 10;
const int LEVMAX = 3;
const int CXMAX = 200; //size of code array
#endregion
#region Private Attributes
private int arraysize;
private int codeIndex = 0;
private int tabIndex = 0; //Index of wordtab
private int cc = 0, ll = 0,num; //cc:character count, ll:line length, num:last number read
private int level;
private int cx0;
private string strCh = " "; //last character read
private string strID; //last identifier read
private string strSourceCode;
private string strErrorOut;
private string strMIDOut;
private symbol sym;
#endregion
#region Property
public string StrSourceCode
{
get
{
return strSourceCode;
}
set
{
strSourceCode = value;
}
}
public string StrErrorOut
{
get
{
return strErrorOut;
}
//set
//{
// value = strErrorOut;
//}
}
public string StrMIDOut
{
get
{
return strMIDOut;
}
}
public int LL
{
get
{
return ll;
}
set
{
ll = value;
}
}
public int CC
{
get
{
return cc;
}
set
{
cc = value;
}
}
#endregion
#region Symbol
public enum symbol
{
nul, ident, number, plus, minus, times, slash, mod, eql, neq, lss, leq, gtr, geq, lparen, rparen, lsqbracket, rsqbracket,
lbgbracket, rbgbracket, comma, semicolon, period, becomes, progsym, procsym, intesym, logisym, constsym, callsym, ifsym, thensym,
elsesym, whilesym, repeatsym, beginsym, endsym, orsym, andsym, notsym, truesym, falsesym, dosym, untilsym, writesym
};
string[] word = new string[NUM_OF_REAERVED_WORDS]{"and","begin","call","const","do","else","end","false","if","integer","logical","not","or","procedure","program",
"repeat","then","true","until","while", "write"};
symbol[] wsym = new symbol[NUM_OF_REAERVED_WORDS]{symbol.andsym,symbol.beginsym,symbol.callsym,symbol.constsym,symbol.dosym,symbol.elsesym,symbol.endsym,
symbol.falsesym,symbol.ifsym,symbol.intesym,symbol.logisym,symbol.notsym,symbol.orsym,symbol.procsym,
symbol.progsym,symbol.repeatsym,symbol.thensym,symbol.truesym,symbol.untilsym,symbol.whilesym,symbol.writesym};
symbol[] ssym = new symbol[NUM_OF_OPR_WORDS] {symbol.plus,symbol.minus,symbol.times,symbol.slash,symbol.lparen,symbol.rparen,symbol.lsqbracket,symbol.rsqbracket,
symbol.lbgbracket,symbol.rbgbracket,symbol.eql, symbol.comma,symbol.semicolon,symbol.period,symbol.lss,symbol.gtr,symbol.mod};
symbol[] dsbegsys = new symbol[] { symbol.intesym, symbol.logisym, symbol.procsym, symbol.constsym };
symbol[] ssbegsys = new symbol[] { symbol.callsym, symbol.ifsym, symbol.whilesym, symbol.repeatsym, symbol.writesym };
symbol[] afbegsys = new symbol[] { symbol.ident, symbol.number, symbol.lparen };
symbol[] bfbegsys = new symbol[] { symbol.ident, symbol.truesym, symbol.falsesym, symbol.notsym, symbol.lparen,symbol.number};
symbol[] dsfollsys = new symbol[] { symbol.intesym, symbol.logisym, symbol.procsym, symbol.constsym, symbol.semicolon };
symbol[] ssfollsys = new symbol[] { symbol.callsym, symbol.ifsym, symbol.whilesym, symbol.repeatsym, symbol.writesym, symbol.semicolon, symbol.endsym, symbol.elsesym, symbol.untilsym };
symbol[] aefollsys = new symbol[] { symbol.callsym, symbol.ifsym, symbol.whilesym, symbol.repeatsym, symbol.writesym, symbol.semicolon, symbol.endsym, symbol.minus, symbol.ident, symbol.number };
symbol[] atfollsys = new symbol[] { symbol.callsym, symbol.ifsym, symbol.whilesym, symbol.repeatsym, symbol.writesym, symbol.semicolon, symbol.endsym, symbol.minus, symbol.ident, symbol.number, symbol.plus };
symbol[] affollsys = new symbol[] { symbol.callsym, symbol.ifsym, symbol.whilesym, symbol.repeatsym, symbol.writesym, symbol.semicolon, symbol.endsym, symbol.minus, symbol.ident, symbol.number, symbol.plus, symbol.times, symbol.slash, symbol.mod, symbol.lparen };
symbol[] befollsys = new symbol[] { symbol.ident, symbol.number, symbol.truesym, symbol.falsesym, symbol.notsym, symbol.lparen, symbol.semicolon, symbol.endsym, symbol.thensym, symbol.dosym };
symbol[] btfollsys = new symbol[] { symbol.ident, symbol.number, symbol.truesym, symbol.falsesym, symbol.notsym, symbol.lparen, symbol.semicolon, symbol.endsym, symbol.thensym, symbol.dosym, symbol.orsym };
symbol[] bffollsys = new symbol[] { symbol.ident, symbol.number, symbol.truesym, symbol.falsesym, symbol.notsym, symbol.lparen, symbol.semicolon, symbol.endsym, symbol.thensym, symbol.dosym, symbol.orsym, symbol.andsym };
#endregion
#region Other Definition
public struct wordTab
{
public string name;
public objekt kind;
public int value; //constant:value;array:arraysize
public int level;
public int addr; //variable,procedure address
public int size; //reserve storage unit
};
wordTab[] wordtab = new wordTab[LENGTH_OF_ID_TABLE];
//记录行号
public static int lineNum;
public enum objekt { integer, logical, procedure, constant, array };
private string strSingleChPattern = @"[\+\-\*\/\[\]\{\}\(\)<>=.,;%]";
int[] ssymAscii = new int[NUM_OF_OPR_WORDS] { '+', '-', '*', '/', '(', ')', '[', ']', '{', '}', '=', ',', ';', '.', '<', '>', '%' };
#endregion
#region Instruction
public enum fct{lit,opr,lod,loa,sto,sta,cal,ini,jmp,jpc};
public struct Instruction
{
public fct fct;
public int level;
public int address;
};
public Instruction[] code = new Instruction[CXMAX];
#endregion
public PLXAnalyzer() { }
public void Error(int errorID)
{
strErrorOut += "Line " + lineNum + ": " + strErrorMsg[errorID - 1] + "\n";
}
public void GetSym()
{
while (AssistOpr.IsWhiteSpace(strCh))
Getch();
if (strCh == "\\")
{
HandleComment();
while (AssistOpr.IsWhiteSpace(strCh)) //处理注释之后仍要处理whitespace
Getch();
}
if (Regex.IsMatch(strCh, "[A-Za-z]"))
{
HandleIDorReservedWords();
}
else if (Regex.IsMatch(strCh, "[0-9]"))
{
HandleConstantNumber();
}
else if (strCh == ":")
{
HandleAssignmentSym();
}
else if (strCh == "<")
{
HandleLssAndLeqSym();
}
else if (strCh == ">")
{
HandleGtrAndGeqSym();
}
else if (strCh == "/")
{
HandleNeqSym();
}
else if (Regex.IsMatch(strCh, strSingleChPattern))
{
HandleSingleCh();
}
}
public void Getch()
{
if(cc != ll)
strCh = strSourceCode.Substring(cc++, 1);
}
public void Test(symbol[] s1, symbol[] s2, int errorID)
{
if (!AssistOpr.IsContain<symbol>(s1, sym))
{
Error(errorID);
if (s2 != null)
{
while (!AssistOpr.IsContain<symbol>(s2, sym))
GetSym();
}
}
}
public string ListMidCode()
{
for(int i = 0; i < codeIndex ; i++)
strMIDOut += i.ToString() + "\t" + code[i].fct + "\t" + code[i].level + "\t" + code[i].address + "\n";
return StrMIDOut;
}
protected void Gen(fct x, int y, int z)
{
if (codeIndex > CXMAX)
{
strErrorOut = "程序过长!";
return;
}
code[codeIndex].fct = x;
code[codeIndex].level = y;
code[codeIndex++].address = z;
}
protected void HandleComment()
{
do Getch();
while (strCh != "\n");
}
protected void HandleIDorReservedWords()
{
int k = 0, i, j;
StringBuilder strTempCh = new StringBuilder(LENGTH_OF_ID);
do
{
strTempCh.Append(strCh);
Getch();
}
while (Regex.IsMatch(strCh, "[A-Za-z0-9]"));
strID = strTempCh.ToString();
i = 0;
j = NUM_OF_REAERVED_WORDS - 1;
while (i <= j)
{
k = (i + j) / 2;
int compResult = strID.CompareTo(word[k]);
if (compResult == 0) break;
else if (compResult < 0)
j = k - 1;
else if (compResult > 0)
i = k + 1;
}
if (i <= j)
sym = wsym[k];
else
sym = symbol.ident;
}
protected void HandleConstantNumber()
{
int k = 0;
num = 0;
sym = symbol.number;
do
{
num = 10 * num + Convert.ToInt16(strCh);
k += 1;
Getch();
}
while (Regex.IsMatch(strCh, "[0-9]"));
if (k > MAX_NO_OF_DIGITS_IN_NUM)
{
Error(ER_EXCEED_BIT);
}
}
protected void HandleAssignmentSym()
{
Getch();
if (strCh == "=")
{
sym = symbol.becomes;
Getch();
}
else
{
sym = symbol.nul;
}
}
protected void HandleLssAndLeqSym()
{
Getch();
if (strCh == "=")
{
sym = symbol.leq;
Getch();
}
else
{
sym = symbol.lss;
}
}
protected void HandleGtrAndGeqSym()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -