@Cached public Rule DefinedHtmlTagName(StringVar tagName) { return Sequence( OneOrMore(Alphanumeric()), tagName.isSet() && match().equals(tagName.get()) || tagName.isNotSet() && tagName.set(match().toLowerCase()) && isHtmlTag(tagName.get()) ); }
@Cached public Rule EmphOrStrongClose(String chars) { return Sequence( Test(isLegalEmphOrStrongClosePos()), FirstOf( Sequence( Test(ValidEmphOrStrongCloseNode.class.equals(peek(0).getClass())), drop() ), Sequence( TestNot(Spacechar()), NotNewline(), chars, FirstOf((chars.length() == 2), TestNot(Alphanumeric())) ) ) ); }
@Cached public Rule HtmlTagBlock(StringVar tagName) { return Sequence( HtmlBlockOpen(tagName), ZeroOrMore( FirstOf( HtmlTagBlock(tagName), Sequence(TestNot(HtmlBlockClose(tagName)), ANY) ) ), HtmlBlockClose(tagName) ); }
@Cached public Rule EmphOrStrong(String chars) { return Sequence( Test(mayEnterEmphOrStrong(chars)), EmphOrStrongOpen(chars), push(new StrongEmphSuperNode(chars)), OneOrMore( TestNot(EmphOrStrongClose(chars)), Inline(), FirstOf( Sequence( //if current inline ends with a closing char for a current strong node: Test(isStrongCloseCharStolen(chars)), //and composes a valid strong close: chars.substring(0, 1), //which is not followed by another closing char (e.g. in __strong _nestedemph___): TestNot(chars.substring(0, 1)), //degrade current inline emph to unclosed and mark current strong node for closing stealBackStrongCloseChar() ), addAsChild() ) ), Optional(Sequence(EmphOrStrongClose(chars), setClosed())) ); }
@Cached public Rule CodeFence(Var<Integer> markerLength) { return Sequence( FirstOf(NOrMore('~', 3), NOrMore('`', 3)), (markerLength.isSet() && matchLength() == markerLength.get()) || (markerLength.isNotSet() && markerLength.set(matchLength())), Sp(), ZeroOrMore(TestNot(Newline()), ANY), // GFM code type identifier push(match()), Newline() ); }
@Cached public Rule ExplicitLink(boolean image) { return Sequence( Spn1(), '(', Sp(), LinkSource(), Spn1(), FirstOf(LinkTitle(), push("")), Sp(), ')', push(image ? new ExpImageNode(popAsString(), popAsString(), popAsNode()) : new ExpLinkNode(popAsString(), popAsString(), popAsNode()) ) ); }
@Cached public Rule LinkSource() { StringBuilderVar url = new StringBuilderVar(); return FirstOf( Sequence('(', LinkSource(), ')'), Sequence('<', LinkSource(), '>'), Sequence( OneOrMore( FirstOf( Sequence('\\', AnyOf("()"), url.append(matchedChar())), Sequence(TestNot(AnyOf("()>")), Nonspacechar(), url.append(matchedChar())) ) ), push(url.getString()) ), push("") ); }
@Cached public Rule ListItem(Rule itemStart, SuperNodeCreator itemNodeCreator) {
@Cached public Rule TaskListItem(Rule itemStart, SuperNodeTaskItemCreator itemNodeCreator) {
/** * Creates a new rule that repeatedly matches a given sub rule a certain fixed number of times. * <p>Note: This methods provides caching, which means that multiple invocations with the same * arguments will yield the same rule instance.</p> * * @param repetitions The number of repetitions to match. Must be >= 0. * @param rule the sub rule to match repeatedly. * @return a new rule */ @Cached @DontLabel public Rule NTimes(int repetitions, Object rule) { return NTimes(repetitions, rule, null); }
/** * Explicitly creates a rule matching the given character. Normally you can just specify the character literal * directly in you rule description. However, if you don't want to go through {@link #fromCharLiteral(char)}, * e.g. because you redefined it, you can also use this wrapper. * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * argument will yield the same rule instance.</p> * * @param c the char to match * @return a new rule */ @Cached @DontLabel public Rule Ch(char c) { return new CharMatcher(c); }
/** * Explicitly creates a rule matching the given character case-independently. * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * argument will yield the same rule instance.</p> * * @param c the char to match independently of its case * @return a new rule */ @Cached @DontLabel public Rule IgnoreCase(char c) { if (Character.isLowerCase(c) == Character.isUpperCase(c)) { return Ch(c); } return new CharIgnoreCaseMatcher(c); }
/** * Creates a rule matching a range of characters from cLow to cHigh (both inclusively). * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * arguments will yield the same rule instance.</p> * * @param cLow the start char of the range (inclusively) * @param cHigh the end char of the range (inclusively) * @return a new rule */ @Cached @DontLabel public Rule CharRange(char cLow, char cHigh) { return cLow == cHigh ? Ch(cLow) : new CharRangeMatcher(cLow, cHigh); }
/** * Creates a new rule that tries repeated matches of its subrule and succeeds if the subrule matches at least once. * If the subrule does not match at least once this rule fails. * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * argument will yield the same rule instance.</p> * * @param rule the subrule * @return a new rule */ @Cached @DontLabel public Rule OneOrMore(Object rule) { return new OneOrMoreMatcher(toRule(rule)); }
/** * Creates a new rule that tries a match on its subrule and always succeeds, independently of the matching * success of its sub rule. * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * argument will yield the same rule instance.</p> * * @param rule the subrule * @return a new rule */ @Cached @DontLabel public Rule Optional(Object rule) { return new OptionalMatcher(toRule(rule)); }
/** * Creates a new rule that tries repeated matches of its subrule. * Succeeds always, even if the subrule doesn't match even once. * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * argument will yield the same rule instance.</p> * * @param rule the subrule * @return a new rule */ @Cached @DontLabel public Rule ZeroOrMore(Object rule) { return new ZeroOrMoreMatcher(toRule(rule)); }
/** * <p>Creates a new rule that acts as an inverse syntactic predicate, i.e. tests the given sub rule against the * current input position without actually matching any characters. Succeeds if the sub rule fails and fails if the * sub rule succeeds. Since this rule does not actually consume any input it will never create a parse tree node.</p> * <p>Also it carries a {@link SuppressNode} annotation, which means all sub nodes will also never create a parse * tree node. This can be important for actions contained in sub rules of this rule that otherwise expect the * presence of certain parse tree structures in their context. * Also see {@link org.parboiled.annotations.SkipActionsInPredicates}</p> * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * argument will yield the same rule instance.</p> * * @param rule the subrule * @return a new rule */ @Cached @SuppressNode @DontLabel public Rule TestNot(Object rule) { Rule subMatcher = toRule(rule); return new TestNotMatcher(subMatcher); }
/** * Explicitly creates a rule matching the given string in a case-independent fashion. * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * argument will yield the same rule instance.</p> * * @param characters the characters of the string to match * @return a new rule */ @Cached @SuppressSubnodes @DontLabel public Rule IgnoreCase(char... characters) { if (characters.length == 1) return IgnoreCase(characters[0]); // optimize one-char strings Rule[] matchers = new Rule[characters.length]; for (int i = 0; i < characters.length; i++) { matchers[i] = IgnoreCase(characters[i]); } return ((SequenceMatcher) Sequence(matchers)).label('"' + String.valueOf(characters) + '"'); }
/** * Creates a new rule that only succeeds if all of its subrule succeed, one after the other. * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * arguments will yield the same rule instance.</p> * * @param rules the sub rules * @return a new rule */ @Cached @DontLabel public Rule Sequence(Object[] rules) { checkArgNotNull(rules, "rules"); return rules.length == 1 ? toRule(rules[0]) : new SequenceMatcher(toRules(rules)); }
/** * Creates a new rule that matches any of the given characters. * <p>Note: This methods carries a {@link Cached} annotation, which means that multiple invocations with the same * argument will yield the same rule instance.</p> * * @param characters the characters * @return a new rule */ @Cached @DontLabel public Rule AnyOf(Characters characters) { checkArgNotNull(characters, "characters"); if (!characters.isSubtractive() && characters.getChars().length == 1) { return Ch(characters.getChars()[0]); } if (characters.equals(Characters.NONE)) return NOTHING; return new AnyOfMatcher(characters); }