我需要将像array_name [i,i * k,i-k]这样的表达式转换为反向波兰表示法。
我基本上正在尝试翻译这样的表达式:
if(array_name[i, j+k]>=a+b) array_name[i, j*k] = a+2; else x = a / b;
使用正则表达式进入RPN。
我已经有了一个非常丑陋的大型正则表达式,匹配:if, else, + - * / = == ( ) <= >= < > !=
以及与此模式匹配的所有单词:[a-zA-z][a-zA-z0-9_]*
。而且我还有将infix算术表达式转换为RPN的代码。这是:
/// <summary>
/// Returns the collection of all the lexemes of the expression
/// using Regex.
/// The Regex created works fine with 'if else' constructions and is good
///with
///any variable name possible in C#, with arithmetical expressions,
///like +, -, /, and all the boolean operators.
/// </summary>
/// <param name="input">String expression in infix notation.</param>
/// <returns>Collection of all the lexemes of the expression</returns>
private static MatchCollection GetMatchCollection(string input)
{
var rx =
new Regex(
@"/\bif\b|\belse\b|\(|\)|\+|\-|\*|\<=|\>=|\\|\>|\<|(?<![!=])[!=]=(?!=)|([a-zA-Z][a-zA-z0-9_]*)|(\d+\.?\d*)|(?<!=)=(?!=)|\/|/^/g");
return rx.Matches(input);
}
/// <summary>
/// Translates the infix expression into RPN
/// </summary>
/// <param name="input">String expression in infix notation.</param>
/// <returns>RPN expression</returns>
public static string Translate(string input)
{
var mc = GetMatchCollection(input);
var id = new Regex(@"[a-zA-z][a-zA-z0-9_]*"); // regex for identifiers
var num = new Regex(@"\d+\.?\d*"); // regex for decimals
var skobki = new Regex(@"\(|\)"); // regex for braces
object[] operators =
{
"(", ")", "else", "*", "/", "+", "-", "=", "<", ">", "<=", ">=", "==", "!=", "&&",
"||", "if"
}; // operators by priority
var opers = new Regex(@"\(|\)|\+|\-|\*|\/|<=?|>=?|!=|=|&&|\|\|\bif\b|\belse\b"); // regex for operators
var stOper = new Stack();
var expr = new ArrayList();
foreach (Match m in mc)
{
var m1 = id.Match(m.Value);
if (m1.Success) { expr.Add(m1.Value); continue; }
m1 = num.Match(m.Value);
if (m1.Success) { expr.Add(m1.Value); continue; }
m1 = skobki.Match(m.Value);
if (m1.Success)
{
if (m1.Value == "(") { stOper.Push(m1.Value); continue; }
var op = stOper.Pop().ToString();
while (op != "(")
{
expr.Add(op);
op = stOper.Pop().ToString();
}
continue;
}
m1 = opers.Match(m.Value);
if (m1.Success)
{
try
{
while (Array.IndexOf(operators, m1.Value) > Array.IndexOf(operators, stOper.Peek()))
{
if (stOper.Peek().ToString() == "(") break;
expr.Add(stOper.Pop().ToString());
}
}
catch (Exception)
{
// stack is empty
}
stOper.Push(m1.Value);
}
}
while (stOper.Count != 0)
{
expr.Add(stOper.Pop().ToString());
}
// Make the RPN expression string
// from the ArrayList expr.
var res = new StringBuilder();
foreach (var s in expr)
res.Append(s).Append(' ');
return res.ToString();
}
如何修改代码以使方法public static string Translate(string input)
将像array_name [i,k * i-1]这样的简单表达式转换为RPN表达式?
请注意,public static string Translate(string input)
方法仅适用于简单的算术表达式,但不适用于我在上面提供的方法(if-else语句)。
答案 0 :(得分:2)
正则表达式不是要走的路。 Parse parser generator可能会将一些abstract syntax tree用于trivial,并将其输出到RPN,即{{3}}。
答案 1 :(得分:0)
解决了这个问题。这是算法。
class InfixToPostfixConverter
{
private readonly Stack<string> _stack;
private readonly string[] _input;
private readonly Dictionary<string, int> _priorities;
private readonly List<string> _poliz;
public InfixToPostfixConverter(string input)
{
_input = input.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
_stack = new Stack<string>();
_poliz = new List<string>();
_priorities = new Dictionary<string, int>
{
{"(", 0},
{")", 0},
{"[", 0},
{"if", 0},
{"flag", 0},
{">", 1},
{"<", 1},
{"<=", 1},
{">=", 1},
{"=", 1},
{"==", 1},
{"!=", 1},
{"+", 2},
{"-", 2},
{"*", 3},
{"/", 3},
{"^", 4},
{"@", 5}
};
}
public string Translate()
{
return ConvertInfixToPostfix();
}
private string ConvertInfixToPostfix()
{
int countAts = 0;
bool reachedElse = false;
foreach (var lexeme in _input)
{
if (lexeme.Equals("if"))
{
_stack.Push(lexeme);
_stack.Push("flag");
}
else if (lexeme.Equals("else"))
{
_poliz.Add("null");
_poliz.Add("1B");
reachedElse = true;
_poliz[_poliz.FindIndex(x => x.Equals("null"))] = _poliz.Count.ToString();
}
else if (Regex.IsMatch(lexeme, @"[a-zA-Z][a-zA-z0-9_]*|\d+\.?\d*")
&& !lexeme.Equals("if") && !lexeme.Equals("else"))
{
_poliz.Add(lexeme);
}
else if (lexeme.Equals(";"))
{
if (!reachedElse)
{
while (_stack.Count != 0 && !_stack.Peek().Equals("if"))
{
_poliz.Add(_stack.Pop());
}
if (_stack.Count != 0)
{
_stack.Pop();
}
}
else
{
while (_stack.Count != 0)
{
_poliz.Add(_stack.Pop());
}
_poliz[_poliz.FindIndex(x => x.Equals("null"))] = _poliz.Count.ToString();
}
}
else if (lexeme.Equals(","))
{
countAts++;
while (_stack.Count != 0 && !_stack.Peek().Equals("["))
{
_poliz.Add(_stack.Pop());
}
}
else if (lexeme.Equals(")") || lexeme.Equals("]"))
{
var brace = lexeme.Equals(")") ? "(" : "[";
while (_stack.Count != 0 && !_stack.Peek().Equals(brace))
{
_poliz.Add(_stack.Pop());
}
_stack.Pop();
if (_stack.Peek().Equals("flag"))
{
_stack.Pop();
_poliz.Add((_poliz.Count + 3).ToString());
_poliz.Add("null");
_poliz.Add("3Y");
}
if (lexeme.Equals("]"))
{
countAts++;
_poliz.Add(countAts.ToString());
_poliz.Add(_stack.Pop());
countAts = 0;
}
}
else
{
if (_stack.Count != 0 && !lexeme.Equals("(") && !lexeme.Equals("["))
{
for (;
_stack.Count != 0 &&
_priorities[lexeme] <= _priorities[_stack.Peek()];
_poliz.Add(_stack.Pop())) {}
}
if (lexeme.Equals("["))
{
countAts++;
_stack.Push("@");
}
_stack.Push(lexeme);
}
}
return _poliz.Aggregate(string.Empty, (current, x) => current + (x + " "));
}
}