public void ShouldSubstituteRuleBodyOnParserAssign() { // Arrange var op = peg.Operators; var testNonTerminal = op.NonTerminal(ParsingRuleNames.NonTerminalA); // Act bool before = testNonTerminal.HasNonTerminalParsingRuleBodies; peg.Parser(ParsingRuleNames.Start, new[] { peg.Rule(ParsingRuleNames.Start, testNonTerminal), peg.Rule(ParsingRuleNames.NonTerminalA, op.Terminal(TokenNames.A)) }); bool after = testNonTerminal.HasNonTerminalParsingRuleBodies; // Assert Assert.False(before); Assert.True(after); }
private void BuildSemantics() { var actions = _inputPeg.DefaultSemanticActions; actions.SetDefaultGenericPassthroughAction <GenericAstResult>(); actions.OrderedChoiceAction = (_, subResults, matchedPeg) => subResults.First(); actions.SetNonTerminalAction(RuleName.Operator, (_, subResults, matchedPeg) => subResults.First()); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Start, (_, subResults, matchedPeg) => { var oneOrMore = ((GenericAstResult)subResults.First()).SubResults.Cast <RuleAstResult <TTokenTypeName, TNonTerminalName, TActionResult> >(); var ruleCollectionResult = new RuleCollectionResult <TTokenTypeName, TNonTerminalName, TActionResult>(); ruleCollectionResult.Rules = oneOrMore.Select(ruleAstResult => _outputPeg.Rule(ruleAstResult.RuleName, ruleAstResult.Operator)); return(ruleCollectionResult); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Rule, (_, subResults, matchedPeg) => { var resultsArray = ((GenericAstResult)subResults.First()).SubResults; var resultNonTermnial = (GenericAstResult)resultsArray[0]; var nonTerminalName = resultNonTermnial.MatchedTokens.GetMatchedString(); if (!Enum.TryParse(typeof(TNonTerminalName), nonTerminalName, out object nameObj)) { throw new Exception($"Invalid nonterminal name given: {nonTerminalName} is undeclared in {nameof(TNonTerminalName)}"); } TNonTerminalName name = (TNonTerminalName)nameObj; return(new RuleAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { RuleName = name, Operator = ((OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>)resultsArray[2]).Operator }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.NonTerminal, (_, subresults, matchedPeg) => { var result = (GenericAstResult)subresults.First(); var nonTerminalName = result.MatchedTokens.GetMatchedString(); if (!Enum.TryParse(typeof(TNonTerminalName), nonTerminalName, out object nameObj)) { throw new Exception($"Invalid nonterminal name given: {nonTerminalName} is undeclared in {nameof(TNonTerminalName)}"); } TNonTerminalName name = (TNonTerminalName)nameObj; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.NonTerminal(name) }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Empty, (_, subresults, matchedPeg) => { return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.EmptyString() }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Brackets, (_, subResults, matchedPeg) => { return(((GenericAstResult)(subResults.First())).SubResults[1] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.And, (_, subResults, matchedPeg) => { var op = ((GenericAstResult)subResults.First()).SubResults[2] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.AndPredicate(op.Operator) }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Not, (_, subResults, matchedPeg) => { var op = ((GenericAstResult)subResults.First()).SubResults[2] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.NotPredicate(op.Operator) }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.OneOrMore, (_, subResults, matchedPeg) => { var firstSubExpression = (GenericAstResult)subResults.First(); var subExpression = firstSubExpression.SubResults[0] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.OneOrMore(subExpression.Operator) }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.ZeroOrMore, (_, subResults, matchedPeg) => { var firstSubExpression = (GenericAstResult)subResults.First(); var subExpression = firstSubExpression.SubResults[0] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.ZeroOrMore(subExpression.Operator) }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Optional, (_, subResults, matchedPeg) => { var firstSubExpression = (GenericAstResult)subResults.First(); var subExpression = firstSubExpression.SubResults[0] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.Optional(subExpression.Operator) }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Terminal, (_, subresults, matchedPeg) => { var result = (GenericAstResult)subresults.First(); var terminalName = ((GenericAstResult)result.SubResults[1]).MatchedTokens.GetMatchedString(); if (!Enum.TryParse(typeof(TTokenTypeName), terminalName, out object nameObj)) { throw new Exception($"Invalid nonterminal name given: {terminalName} is undeclared in {nameof(TTokenTypeName)}"); } TTokenTypeName name = (TTokenTypeName)nameObj; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.Terminal(name) }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Sequence, (_, subResults, matchedPeg) => { var subSubResults = ((GenericAstResult)subResults.First()).SubResults; var head = subSubResults[0] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; var tail = subSubResults[1] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.Sequence(head.Operator, tail.Operator) }); }); _inputPeg.DefaultSemanticActions.SetNonTerminalAction(RuleName.Choice, (_, subResults, matchedPeg) => { var subSubResults = ((GenericAstResult)subResults.First()).SubResults; var head = subSubResults[0] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; var tail = subSubResults[2] as OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult>; return(new OperatorAstResult <TTokenTypeName, TNonTerminalName, TActionResult> { Operator = _outputPeg.Operators.OrderedChoice(head.Operator, tail.Operator) }); }); }
private void BuildParser() { var op = _inputPeg.Operators; var start = _inputPeg.Rule(RuleName.Start, op.OneOrMore(op.NonTerminal(RuleName.Rule))); var rule = _inputPeg.Rule(RuleName.Rule, op.Sequence(op.Terminal(TokenNames.Identifier), op.Terminal(TokenNames.Arrow), op.NonTerminal(RuleName.Operator), op.Optional(op.Terminal(TokenNames.SemiColon)))); var @operator = _inputPeg.Rule(RuleName.Operator, // NB: Order matters here op.OrderedChoice(op.NonTerminal(RuleName.Choice), op.NonTerminal(RuleName.Sequence), op.NonTerminal(RuleName.Optional), op.NonTerminal(RuleName.ZeroOrMore), op.NonTerminal(RuleName.OneOrMore), op.NonTerminal(RuleName.Terminal), op.NonTerminal(RuleName.NonTerminal), op.NonTerminal(RuleName.Brackets), op.NonTerminal(RuleName.Empty), op.NonTerminal(RuleName.And), op.NonTerminal(RuleName.Not) )); var and = _inputPeg.Rule(RuleName.And, op.Sequence(op.Terminal(TokenNames.And), op.Terminal(TokenNames.OpenRound), op.NonTerminal(RuleName.Operator), op.Terminal(TokenNames.CloseRound))); var not = _inputPeg.Rule(RuleName.Not, op.Sequence(op.Terminal(TokenNames.Not), op.Terminal(TokenNames.OpenRound), op.NonTerminal(RuleName.Operator), op.Terminal(TokenNames.CloseRound))); var oneOrMore = _inputPeg.Rule(RuleName.OneOrMore, op.Sequence(op.NonTerminal(RuleName.Operator), op.Terminal(TokenNames.OneOrMore))); var zeroOrMore = _inputPeg.Rule(RuleName.ZeroOrMore, op.Sequence(op.NonTerminal(RuleName.Operator), op.Terminal(TokenNames.ZeroOrMore))); var terminal = _inputPeg.Rule(RuleName.Terminal, op.Sequence(op.Terminal(TokenNames.OpenSquare), op.Terminal(TokenNames.Identifier), op.Terminal(TokenNames.CloseSquare))); var emptyString = _inputPeg.Rule(RuleName.Empty, op.Sequence(op.Terminal(TokenNames.OpenSquare), op.Terminal(TokenNames.CloseSquare))); var nonterminal = _inputPeg.Rule(RuleName.NonTerminal, op.Terminal(TokenNames.Identifier)); var optional = _inputPeg.Rule(RuleName.Optional, op.Sequence(op.NonTerminal(RuleName.Operator), op.Terminal(TokenNames.Optional))); var sequence = _inputPeg.Rule(RuleName.Sequence, op.Sequence(op.NonTerminal(RuleName.Operator), op.NonTerminal(RuleName.Operator))); var brackets = _inputPeg.Rule(RuleName.Brackets, op.Sequence(op.Terminal(TokenNames.OpenRound), op.NonTerminal(RuleName.Operator), op.Terminal(TokenNames.CloseRound))); var choice = _inputPeg.Rule(RuleName.Choice, op.Sequence(op.NonTerminal(RuleName.Operator), op.Terminal(TokenNames.Choice), op.NonTerminal(RuleName.Operator))); _parser = _inputPeg.Parser(RuleName.Start, new[] { start, rule, sequence, @operator, terminal, optional, brackets, choice, nonterminal, emptyString, oneOrMore, zeroOrMore, and, not }); }