Redivider
Redivider is an esoteric programming language by User:Ihope127. A program consists of <token>s separated by whitespace; this whitespace is optional unless it comes between two <word>s.
<token> ::= <word> | "(" | "," | ")" | ":" | "|" | "+" | "{" | ";" | "}" | "." | "[" | "]" | <string> | <regex> | "#" anything newline <word> ::= {letter or digit} <string> ::= quotemark <stringguts> quotemark <regex> ::= "/" <regexguts> "/"
<stringguts> consists of ASCII characters other than " and \ as well as escape codes. Escape codes must include \\, representing \; \", representing "; \n, representing the newline character; \0nnn where n is an octal digit, representing the character with code nnn; \0xnn where n is a hexadecimal digit, representing the character with code nn; and \X, where X is an ASCII character mnemonic (NUL through US and DEL). Escape codes are parsed greedily (only matters for \SO vs. \SOH) and all other escape codes are undefined.
<regexguts> is the same as <stringguts> except that regex special characters might not represent themselves; the regex engine handles escaping.
The syntax, ignoring whitespace and # (which denotes a comment):
<program> ::= {<declaration>} <declaration> ::= <word> ["(" [<word> {"," <word>}] ")"] ":" <piexpr> "." <piexpr> ::= <plexpr> "|" <piexpr> | <plexpr> <plexpr> ::= <wexpr> "+" <plexpr> | <wexpr> <wexpr> ::= <word> | <word> <params> | "{" <blockguts> "}" | "(" <piexpr> ")" | <wexpr> "[" <piexpr> "]" | <string> | <regex> <params> ::= ["(" [<piexpr> {"," <piexpr>}] ")"] <blockguts> ::= {<blockline> ";"} <piexpr> <blockline> ::= [<word> ":"] <piexpr>
A declaration defines a parser. A parser takes an input string and then either soft fails, hard fails, or succeeds; if it succeeds, then it also returns a result and a new input string.
The left hand side of the parser declaration gives the parser's name and any parameters' names. The right hand side is an expression for the parser that may include any of the parameters.
parser1 | parser2
The pipe denotes alternation. First, the input string is fed into the left parser. If it succeeds, the alternation also succeeds, returning the same result and input string. It if soft fails, the alternation then becomes equal to the right parser. If it hard fails, the alternation hard fails. (Note that it is usually possible to tell quite quickly whether or not a parser soft fails; if it does not, the right parser may be thrown away.)
parser1 + parser2
The plus sign denotes concatenation. First, the input string is fed into the left parser. If it soft fails, the concatenation soft fails, and if it hard fails, the concatenation hard fails. If it succeeds, then the new input string is fed into the right parser. If it either soft fails or hard fails, the concatenation hard fails. If it succeeds, the concatenation also succeeds, returning the string concatenation of the two result strings as the result and the input string of the right parser as the new input string.
{ ... parserj ; ... } { ... namek: parserk ; ... } { ... parsern }
A block consists of a number of parsers performed in sequence. If the first parser soft fails, the block soft fails. If any other parser fails, or the first parser hard fails, then the block hard fails. Normally, the first parser's input string is the block's input string, the last parser's result and new input string are the block's result and new input string, and each parser's input string is the new input string of the parser before it. A name followed by a colon denotes that the following parser's result is to be bound to the variable with that name. Variables are local to the block, so they may not be referenced anywhere else, and different instances of the same block use different instances of the variables.
name parser1 ( ) parser1 ( parser2, ... )
A name followed by a list of parameters denotes the parser found by evaluating the parameters left to right, as in a block, then substituting the results into the appropriate declaration, which is considered the last expression in the block. (A name without the list of parameters denotes the variable if it is in scope, the parser otherwise.)
parser1 [ parser2 ]
A parser followed by another parser in brackets first runs the second parser, soft failing if it soft fails and hard failing if it hard fails, then runs the first parser with the second parser's result as the input string, hard failing if it fails. The result of the whole thing is the first parser's result and the new input string of the whole thing is the second parser's new input string.
"string literal" /regex literal/
A string literal denotes the parser that succeeds, returning the corresponding string as the result and the input string as the new input string. A regex literal denotes the parser that soft fails if the regex does not match the beginning of the string (or, if the regex ends in $, the entire string), otherwise succeeding, with the portion of the string that was matched as the result and the portion that was not matched as the new input string.
Examples
Transforms simple in-fix mathematical expressions into post-fix reverse polish notation. --MizardX 01:11, 12 November 2008 (UTC)
# Transforms strip_white: { /\s*/; /.*/ }. # Terminals number: strip_white[ /\s*\d+/ ]. var: strip_white[ /\s*[^\W\d_][^\W_]*/ ]. plus: strip_white[ /\s*\+/ ]. minus: strip_white[ /\s*-/ ]. times: strip_white[ /\s*\*/ ]. div: strip_white[ /\s*\// ]. lparen: strip_white[ /\s*\(/ ]. rparen: strip_white[ /\s*\)/ ]. # Non terminals expr: { head: term; tail: expr_tail; head + tail }. expr_tail: { op: plus | minus; " " + expr + " " + op } | "". term: { head: factor; tail: term_tail; head + tail }. term_tail: { op: times | div; " " + expr + " " + op } | "". factor: number | var | { lparen; exp: expr; rparen; exp }.
See also
- Redivider/Brainfuck Interpreter (interpreter for Brainfuck written in Redivider).
- Redivider/Underload Interpreter (interpreter for Underload written in Redivider).
External resources
- Redivider Interpreter written in Python, v2.0 (www.vjn.fi)