public Node doParse() { //% is epsilon. Stack<string> tokens = new Stack<string>(); tokens.Push("$"); tokens.Push("<MiniRE-program>"); Stack<Node> nodes = new Stack<Node>(); Node miniRE = new Node(); while (tokens.Count != 0) { string topElem = tokens.Pop(); string nextToken = scanner.peekToken(); if (nextToken == "$") { if (topElem == "$") break; else throw new RDParser.SyntaxError("All tokens not popped off stack"); } if (topElem.Contains('<') && topElem.Contains('>')) { //This is a non-term, we need to look up and replace. List<string> newrule; try { if (isID(nextToken)) newrule = parsetable.getRuleMatchingToken(topElem, "ID"); else if(isREGEX(nextToken)) newrule = parsetable.getRuleMatchingToken(topElem, "REGEX"); else if(isASCIISTR(nextToken)) newrule = parsetable.getRuleMatchingToken(topElem, "ASCII-STR"); else newrule = parsetable.getRuleMatchingToken(topElem, nextToken); } catch (KeyNotFoundException e) { throw new RDParser.SyntaxError("Invalid token in position."); } //Take the existing rule, create its node, add to top elem on stack, pop top elem if full. Node newElem = GetNodeFromRuleName(topElem); if (!(newrule.Count == 0 && newrule[0] == "%")) { if (nodes.Count != 0 && nodes.Peek().IsFull) nodes.Pop(); if (nodes.Count != 0) nodes.Peek().Nodes.Add(newElem); if (nodes.Count != 0 && nodes.Peek().IsFull && nodes.Peek() is MiniRE) { miniRE = nodes.Pop(); } else if (nodes.Count != 0 && nodes.Peek().IsFull) nodes.Pop(); if (!newElem.IsFull && newrule[0] != "%") { nodes.Push(newElem); } newrule = new List<string>(newrule); newrule.Reverse(); if (newrule.Count > 0 && newrule[0] != "%") { foreach (string s in newrule) { tokens.Push(s); } } } else { StringNode sn = new StringNode(); sn.Token = "%"; newElem.Nodes.Add(sn); nodes.Peek().Nodes.Add(newElem); if (nodes.Peek().IsFull && nodes.Peek() is MiniRE) miniRE = nodes.Pop(); } } else { nextToken = scanner.getToken(); //Is a terminal; must match top of stack, possibly do stuff with AST depending on token. if (topElem == nextToken) { switch (nextToken) { case "maxfreqstring": AssignmentStatement xyz = (AssignmentStatement)nodes.Peek(); xyz.Type = AssignmentStatementType.MaxFreqString; break; case "#": AssignmentStatement xyza = (AssignmentStatement)nodes.Peek(); xyza.Type = AssignmentStatementType.Length; break; case "replace": OtherStatement abc = (OtherStatement)nodes.Peek(); abc.Mode = OtherStatementMode.Replace; break; case "print": OtherStatement bcd = (OtherStatement)nodes.Peek(); bcd.Mode = OtherStatementMode.Print; break; case "recursivereplace": OtherStatement cde = (OtherStatement)nodes.Peek(); cde.Mode = OtherStatementMode.RecursiveReplace; break; case "diff": BinOp op1 = (BinOp)nodes.Peek(); StringNode n1 = new StringNode(); n1.Token = "diff"; op1.Nodes.Add(n1); break; case "union": BinOp op2 = (BinOp)nodes.Peek(); StringNode n2 = new StringNode(); n2.Token = "union"; op2.Nodes.Add(n2); break; case "inters": BinOp op3 = (BinOp)nodes.Peek(); StringNode n3 = new StringNode(); n3.Token = "inters"; op3.Nodes.Add(n3); break; default: break; } } else if (topElem == "REGEX" && nextToken[0] == '\'' && nextToken[nextToken.Length - 1] == '\'') { Regex re = new Regex(); re.Pattern = nextToken.Substring(1, nextToken.Length - 2); nodes.Peek().Nodes.Add(re); if (nodes.Peek().IsFull) nodes.Pop(); } else if (topElem == "ASCII-STR" && nextToken[0] == '"' && nextToken[nextToken.Length - 1] == '"') { Node top = nodes.Peek(); if (top is OtherStatement) { OtherStatement nd = (OtherStatement)top; nd.ReplaceText = nextToken.Substring(1, nextToken.Length-2); } else if (top is Filename) { Filename fn = (Filename)top; fn.Path = nextToken.Substring(1, nextToken.Length-2); } if (top.IsFull) nodes.Pop(); } else if (topElem == "ID") { StringNode sn = new StringNode(); sn.Token = nextToken; nodes.Peek().Nodes.Add(sn); if (nodes.Peek().IsFull) nodes.Pop(); } else { throw new RDParser.SyntaxError("Token did not match top of LL(1) Parse Stack."); } } } return miniRE; }
public void Union() { //begin //x = (find 'a(b|c)' in abc.txt) union (find 'bc in abc.txt) //end SymbolTable table = new SymbolTable(); MiniRE miniRe = new MiniRE(); StatementList sl = new StatementList(); miniRe.StatementList = sl; Statement statement = new Statement(); statement.Id = new StringNode("x"); sl.Statement = statement; AssignmentStatement as1 = new AssignmentStatement(); statement.AssignmentStatement = as1; Exp exp = new Exp(); as1.Exp = exp; #region First find Term t1 = new Term(); exp.Term = t1; Regex r1 = new Regex(); r1.Pattern = "([a-zA-Z])*ment([a-zA-Z])*"; t1.Regex = r1; Filename file1 = new Filename(); file1.Path = "../../../TestFiles/file1.txt"; t1.Filename = file1; #endregion ExpTail expTail = new ExpTail(); exp.Tail = expTail; BinOp bop = new BinOp(); expTail.Binop = bop; StringNode operation = new StringNode("union"); bop.Operation = operation; #region Second find Term t2 = new Term(); expTail.Term = t2; ExpTail expTail2 = new ExpTail(); expTail.Tail = expTail2; Regex r2 = new Regex(); r2.Pattern = "([a-zA-Z])*(a|A)([a-zA-Z])*"; t2.Regex = r2; Filename file2 = new Filename(); file2.Path = "../../../TestFiles/file2.txt"; t2.Filename = file2; #endregion miniRe.Execute(table); StringMatchList matches = (StringMatchList) table["x"]; Assert.AreEqual(8, matches.Length); String expected = "{\"mentor\"<'../../../TestFiles/file1.txt', 1>" + "\"filament\"<'../../../TestFiles/file1.txt', 1>" + "\"argument\"<'../../../TestFiles/file1.txt', 1>" + "\"argumentative\"<'../../../TestFiles/file1.txt', 1><'../../../TestFiles/file2.txt', 1>" + "\"Tournament\"<'../../../TestFiles/file1.txt', 1>" + "\"Argument\"<'../../../TestFiles/file2.txt', 1>" + "\"predicament\"<'../../../TestFiles/file2.txt', 1>" + "\"apple\"<'../../../TestFiles/file2.txt', 1>" + "}"; Assert.AreEqual(expected, matches.ToString()); }