public static OperatorPriority GetPriority(PhraseTypeEnum pt) { if (pt == PhraseTypeEnum.ln || pt == PhraseTypeEnum.log || pt == PhraseTypeEnum.lg) { return(OperatorPriority.P5); } else if (pt == PhraseTypeEnum.sin || pt == PhraseTypeEnum.end || pt == PhraseTypeEnum.tg || pt == PhraseTypeEnum.abs || pt == PhraseTypeEnum.when || pt == PhraseTypeEnum.case_ || pt == PhraseTypeEnum.atg || pt == PhraseTypeEnum.then) { return(OperatorPriority.P4); } else if (pt == PhraseTypeEnum.greater) { return(OperatorPriority.P6); } else if (pt == PhraseTypeEnum.less) { return(OperatorPriority.P6); } else if (pt == PhraseTypeEnum.equal) { return(OperatorPriority.P6); } else if (pt == PhraseTypeEnum.plus) { return(OperatorPriority.P1); } else if (pt == PhraseTypeEnum.minus) { return(OperatorPriority.P1); } else if (pt == PhraseTypeEnum.mutiple) { return(OperatorPriority.P2); } else if (pt == PhraseTypeEnum.mod || pt == PhraseTypeEnum.divide) { return(OperatorPriority.P2); } else if (pt == PhraseTypeEnum.leftbracket) { return(OperatorPriority.P0); } else if (pt == PhraseTypeEnum.sharp) { return(OperatorPriority.P0); } else { return(OperatorPriority.Unknown); } }
/// <summary> /// 根据运算符返回对应的运算目数 /// </summary> /// <param name="Phrase">运算符</param> /// <returns>运算目数</returns> public static OperandType OperandCount(PhraseTypeEnum pt) { //分析运算符的目数 if (pt == PhraseTypeEnum.end || pt == PhraseTypeEnum.sin || pt == PhraseTypeEnum.when || pt == PhraseTypeEnum.case_ || pt == PhraseTypeEnum.case_ || pt == PhraseTypeEnum.then || pt == PhraseTypeEnum.atg || pt == PhraseTypeEnum.cbrt || pt == PhraseTypeEnum.else_ || pt == PhraseTypeEnum.lg || pt == PhraseTypeEnum.ln || pt == PhraseTypeEnum.tg || pt == PhraseTypeEnum.abs || pt == PhraseTypeEnum.equal || pt == PhraseTypeEnum.greater || pt == PhraseTypeEnum.less) { return(OperandType.O1); } else if (pt == PhraseTypeEnum.divide || pt == PhraseTypeEnum.plus || pt == PhraseTypeEnum.minus || pt == PhraseTypeEnum.mutiple || pt == PhraseTypeEnum.mod || pt == PhraseTypeEnum.log) { return(OperandType.O2); } else { return(OperandType.O0); } }
/// <summary> /// 词法分析 /// </summary> /// <returns>是否成功</returns> private bool Analyze() { int i = 0; int startpos = 0, endpos = 0; //设置初态 _prestate = DFAState.S0; while (i < _chArray.Length) { //未知态处理,出错返回 if (_prestate == DFAState.SX) { _succeed = false; return(false); } if (Char.IsLetter(_chArray[i])) { //字母 if (_prestate == DFAState.S0) { //初态变字母串 _prestate = DFAState.S3; } else if (_prestate == DFAState.S1) { endpos = i - 1; //保存结束位置 ////检查字母串的匹配类型 //if (CheckString(startpos, endpos) == true) //{ // SavePhrase(startpos, endpos); // startpos = i; //} _prestate = DFAState.S3; } else if (_prestate == DFAState.S2) { endpos = i - 1; //保存结束位置 //检查字母串的匹配类型 if (CheckString(startpos, endpos) == true) { SavePhrase(startpos, endpos); startpos = i; } _prestate = DFAState.S3; } else if (_prestate == DFAState.S17) { endpos = i - 1; //保存结束位置 //检查字母串的匹配类型 if (CheckString(startpos, endpos) == true) { SavePhrase(startpos, endpos); startpos = i; } _prestate = DFAState.S3; } else if (_prestate != DFAState.S3) { //处理前一个词 endpos = i - 1; //保存结束位置 SavePhrase(startpos, endpos); //非字母串转换为字母串 _prestate = DFAState.S3; //保存开始位置 startpos = i; } else //之前的状态为字母串DFAState.S3 { endpos = i - 1; //保存结束位置 //检查字母串的匹配类型 if (CheckString(startpos, endpos) == true) { SavePhrase(startpos, endpos); startpos = i; } } } else if (Char.IsDigit(_chArray[i])) { //数字 if (_prestate == DFAState.S0) { //初态 _prestate = DFAState.S1; startpos = i; //保存开始位置 } else if (_prestate == DFAState.S1) { //整数串,状态不变 } else if (_prestate == DFAState.S2) //浮点数串 { _prestate = DFAState.S2; } else if (_prestate == DFAState.S3) //字母 { _prestate = DFAState.S2; } else if (_prestate == DFAState.S17) //_ { _prestate = DFAState.S2; } else { //处理前一个词 endpos = i - 1; //保存结束位置 //字符串类型检查 if (_prestate == DFAState.S3 && CheckString(startpos, endpos) == false) { return(false); //如果前一个状态为字符串态,且字符串匹配失败,则退出 } else { SavePhrase(startpos, endpos); } //从非数字串转换为整数串 _prestate = DFAState.S1; //保存开始位置 startpos = i; } } else if (_chArray[i] == '.') { //小数点 if (_prestate == DFAState.S1 || _prestate == DFAState.S0) { _prestate = DFAState.S2; //由整数串或初态变为浮点数串 } else { //未知态 // 需要讨论: 是否保存前一个词 //_prestate = DFAState.SX; } } else if (_chArray[i] == '_') { _prestate = DFAState.S17; } else if (Char.IsWhiteSpace(_chArray[i])) { //空格,跳过 //处理前一个词 endpos = i - 1; //字符串类型检查 //if (_prestate == DFAState.S3 && CheckString(startpos, endpos) == false) // return false; //如果前一个状态为字符串态,且字符串匹配失败,则退出 //else SavePhrase(startpos, endpos); startpos = i + 1; _prestate = DFAState.S0; } //else if (_chArray[i] == '+' || _chArray[i] == '-' || _chArray[i] == '*' || _chArray[i] == '/' || _chArray[i] == '^' || _chArray[i] == '%' || _chArray[i] == '(' || _chArray[i] == ')' || _chArray[i] == '!' || _chArray[i] == '#' || _chArray[i] == '@' || _chArray[i] == '=') else if (_chArray[i] == '+' || _chArray[i] == '-' || _chArray[i] == '*' || _chArray[i] == '/' || _chArray[i] == '(' || _chArray[i] == ')' || _chArray[i] == '#' || _chArray[i] == '=' || _chArray[i] == '>' || _chArray[i] == '<') { if (_prestate != DFAState.S0) { //处理前一个词 endpos = i - 1; //字符串类型检查 //if (_prestate == DFAState.S3 && CheckString(startpos, endpos) == false) // return false; //如果前一个状态为字符串态,且字符串匹配失败,则退出 //else SavePhrase(startpos, endpos); } if (_chArray[i] == '-') { if (_ps.PhraseTypeResult.Length > 0) { PhraseTypeEnum prept = _ps.PhraseTypeResult[_ps.PhraseTypeResult.Length - 1]; if (prept != PhraseTypeEnum.ax && prept != PhraseTypeEnum.bx && prept != PhraseTypeEnum.cx && prept != PhraseTypeEnum.dx && prept != PhraseTypeEnum.ex && prept != PhraseTypeEnum.fx && prept != PhraseTypeEnum.clr && prept != PhraseTypeEnum.sto && prept != PhraseTypeEnum.rightbracket && prept != PhraseTypeEnum.number) { _chArray[i] = '@'; } } else { _chArray[i] = '@'; } } if (_chArray[i] == '+') { _prestate = DFAState.S4; } else if (_chArray[i] == '-') { _prestate = DFAState.S5; } else if (_chArray[i] == '*') { _prestate = DFAState.S6; } else if (_chArray[i] == '/') { _prestate = DFAState.S7; } else if (_chArray[i] == '=') //not support so far { _prestate = DFAState.S11; } else if (_chArray[i] == '>') //not support so far { _prestate = DFAState.S11; } else if (_chArray[i] == '<') //not support so far { _prestate = DFAState.S11; } else if (_chArray[i] == '%') { _prestate = DFAState.S8; } else if (_chArray[i] == '^') { _prestate = DFAState.S10; } else if (_chArray[i] == '(') { _prestate = DFAState.S12; } else if (_chArray[i] == ')') { _prestate = DFAState.S13; } else if (_chArray[i] == '!') { _prestate = DFAState.S9; } else if (_chArray[i] == '#') { _prestate = DFAState.S14; } else if (_chArray[i] == '@') { _prestate = DFAState.S15; } //保存开始位置 startpos = i; } else { //未知字符,进入未知态 //_prestate=DFAState.SX; _prestate = DFAState.S3; } i++; } return(true); }
/// <summary> /// 添加一个词和它对应的词类 /// </summary> /// <param name="phrase">词</param> /// <param name="pt">词类</param> public void AddPhraseResult(string phrase, PhraseTypeEnum pt) { _scOutput.Add(phrase); _stcOutput.Add(pt); }
/// <summary> /// 添加一个词类 /// </summary> /// <param name="pt">词类</param> public void AddPhraseType(PhraseTypeEnum pt) { _stcOutput.Add(pt); }
/// <summary> /// 虚拟运算(不进行真实的计算) /// </summary> /// <returns>是否有错误发生</returns> private bool FakeCalculate() { PhraseTypeEnum pt = (PhraseTypeEnum)_optr.Pop(); OperandType oc = Operator.OperandCount(pt); //栈顶运算符目数 PhraseTypeEnum temp_pt; //存储_op中pop出的一个符号 switch (oc) { case OperandType.O0: //0目运算符,不存在 _lastOpForError = pt; return(false); //_op.Pop(); //break; case OperandType.O1: //1目运算符 if (_opnd.Count >= 1) { _opnd.Pop(); _op.Pop(); //抛出数符 } else { //没有足够的数符用于匹配运算符,出错 _lastOpForError = pt; return(false); } temp_pt = (PhraseTypeEnum)_op.Pop(); //抛出运算符,邻近符号检查 if (Operator.OperatorCmp((PhraseTypeEnum)_op.Peek(), temp_pt) == PriorityCmpType.Unknown) { _lastOpForError = pt; return(false); } _opnd.Push(PhraseTypeEnum.number); _op.Push(PhraseTypeEnum.number); break; case OperandType.O2: //2目运算符 if (_opnd.Count >= 2) { _opnd.Pop(); _opnd.Pop(); _op.Pop(); //抛出数符 } else { _lastOpForError = pt; return(false); } temp_pt = (PhraseTypeEnum)_op.Pop(); //抛出数符,邻近符号检查 if (Operator.OperatorCmp((PhraseTypeEnum)_op.Peek(), temp_pt) == PriorityCmpType.Unknown) { _lastOpForError = pt; return(false); } temp_pt = (PhraseTypeEnum)_op.Pop(); //抛出运算符,邻近符号检查 if (Operator.OperatorCmp((PhraseTypeEnum)_op.Peek(), temp_pt) == PriorityCmpType.Unknown) { _lastOpForError = pt; return(false); } _opnd.Push(PhraseTypeEnum.number); _op.Push(PhraseTypeEnum.number); break; } return(true); }
/// <summary> /// 检查文法 /// </summary> /// <returns>是否正确</returns> public bool Check() { msg = string.Empty; _optr.Clear(); _optr.Push(PhraseTypeEnum.sharp); //将#作为栈操作结束标志 _opnd.Clear(); _op.Clear(); _op.Push(PhraseTypeEnum.sharp); //将#作为栈操作结束标志 int i = 0; while (i < _ps.Length) { PhraseTypeEnum temp_pt = _ps.PhraseTypeResult[i]; if (temp_pt == PhraseTypeEnum.case_) { int n1 = -1, n2 = -1, n3 = -1, n4 = -1; int k1 = -1, k2 = -1, k3 = -1, k4 = -1; n1 = i + 1; while (n1 < _ps.Length) { if (_ps.PhraseTypeResult[n1] == PhraseTypeEnum.when) { k1 = n1; break; } n1++; } n2 = n1 + 1; while (n2 < _ps.Length) { if (_ps.PhraseTypeResult[n2] == PhraseTypeEnum.then) { k2 = n2; break; } n2++; } n3 = n2 + 1; while (n3 < _ps.Length) { if (_ps.PhraseTypeResult[n3] == PhraseTypeEnum.else_) { k3 = n3; break; } n3++; } n4 = n3 + 1; while (n4 < _ps.Length) { if (_ps.PhraseTypeResult[n4] == PhraseTypeEnum.end) { k4 = n4; break; } n4++; } if (k4 == -1) { msg = "case when then else end 语句不完整"; return(false); } if ((k4 - k3) == 1) { msg = "case when then else end 语句有误,else和end之间不能为空"; return(false); } if ((k3 - k2) == 1) { msg = "case when then else end 语句有误,then和else之间不能为空"; return(false); } if ((k2 - k1) == 1) { msg = "case when then else end 语句有误,when和then之间不能为空"; return(false); } i = k4; temp_pt = PhraseTypeEnum.number; } //运算前算符相邻检查 PriorityCmpType temp_pct = (PriorityCmpType)Operator.OperatorCmp((PhraseTypeEnum)_op.Peek(), temp_pt); if (temp_pct == PriorityCmpType.Unknown) { _lastOpForError = temp_pt; return(false); } //假运算处理 if (temp_pt == PhraseTypeEnum.number || temp_pt == PhraseTypeEnum.e || temp_pt == PhraseTypeEnum.pi || temp_pt == PhraseTypeEnum.ans || temp_pt == PhraseTypeEnum.ax || temp_pt == PhraseTypeEnum.bx || temp_pt == PhraseTypeEnum.cx || temp_pt == PhraseTypeEnum.dx || temp_pt == PhraseTypeEnum.ex || temp_pt == PhraseTypeEnum.fx) { //是数 _opnd.Push(PhraseTypeEnum.number); _op.Push(PhraseTypeEnum.number); } else //是运算符 { //运算结束 if ((PhraseTypeEnum)_optr.Peek() == PhraseTypeEnum.sharp && temp_pt == PhraseTypeEnum.sharp) { break; } temp_pct = (PriorityCmpType)Operator.OperatorCmp2((PhraseTypeEnum)_optr.Peek(), temp_pt); if (temp_pct == PriorityCmpType.Higher) { do { if (this.FakeCalculate() == false) //虚拟运算 { return(false); } } while ((PriorityCmpType)Operator.OperatorCmp2((PhraseTypeEnum)_optr.Peek(), temp_pt) == PriorityCmpType.Higher); //当相邻PhraseTypeEnum优先级相等时 if ((PriorityCmpType)Operator.OperatorCmp2((PhraseTypeEnum)_optr.Peek(), temp_pt) == PriorityCmpType.Equal) { _optr.Pop(); //抛出相等的prePhraseTypeEnum //对类似于(number)的情况做处理 PhraseTypeEnum pt1 = (PhraseTypeEnum)_op.Pop(); _op.Pop(); _op.Push(pt1); } else { _optr.Push(temp_pt); _op.Push(temp_pt); } } else if (temp_pct == PriorityCmpType.Lower) { _optr.Push(temp_pt); _op.Push(temp_pt); } else if (temp_pct == PriorityCmpType.Equal) { _optr.Pop(); PhraseTypeEnum pt1 = (PhraseTypeEnum)_op.Pop(); _op.Pop(); _op.Push(pt1); } else { //出现了不允许相邻的符号 _lastOpForError = (PhraseTypeEnum)_optr.Peek(); return(false); } } i++; } //数栈检查,如果并非只剩一个元素报错 if (_opnd.Count != 1) { _lastOpForError = PhraseTypeEnum.unknown; return(false); } return(true); }
/// <summary> /// 有间隔相邻符号比较(只包含数符) /// </summary> /// <param name="prePt">前一个符号</param> /// <param name="postPt">后一个符号</param> /// <returns>优先级比较值</returns> public static PriorityCmpType OperatorCmp2(PhraseTypeEnum prePt, PhraseTypeEnum postPt) { int result = _priorityTable2[(int)prePt, (int)postPt]; return((PriorityCmpType)result); }