Skip to content

Instantly share code, notes, and snippets.

@AndyG
AndyG / Node.kt
Created February 24, 2018 00:00
Basic Abstract Syntax Tree Node
open class Node {
private var children: MutableCollection<Node>? = null
fun getChildren(): Collection<Node>? = children
fun hasChildren(): Boolean = children?.isNotEmpty() == true
fun addChild(child: Node) {
children = (children ?: ArrayList()).apply {
@AndyG
AndyG / Rule.kt
Last active February 24, 2018 00:16
Basic Rule
abstract class Rule(val pattern: Pattern) {
abstract fun parse(matcher: Matcher, parser: Parser): Node
}
@AndyG
AndyG / Parser.kt
Last active April 3, 2018 23:22
Basic Recursive Parser
class Parser(private val rules: List<Rule>) {
fun parse(source: CharSequence): List<Node> {
val ast = ArrayList<Node>()
var mutableSource = source
while (mutableSource.isNotEmpty()) {
// Find a rule that matches the source.
for (rule in rules) {
@AndyG
AndyG / Parser.kt
Created February 27, 2018 21:57
Parser Nefarious Line
for (rule in rules) {
val matcher = rule.pattern.matcher(mutableSource)
if (matcher.find()) {
// Do stuff with the rule that matched the text
}
}
@AndyG
AndyG / Parser.kt
Last active February 28, 2018 05:23
Fixed Rule
for (rule in rules) {
val matcher = rule.matcher.reset(mutableSource) // Faster than creating a new Matcher
if (matcher.find()) {
// Do stuff with the rule that matched the text
}
}
@AndyG
AndyG / TextNode.kt
Created February 28, 2018 23:45
SimpleAST TextNode
class TextNode(val content: String) : SpannableRenderableNode() {
override fun render(builder: SpannableStringBuilder, context: Context?) {
builder.append(content)
}
}
@AndyG
AndyG / StyleNode.kt
Created February 28, 2018 23:50
SimpleAST StyleNode
class StyleNode(val styles: List<CharacterStyle>) : SpannableRenderableNode() {
override fun render(builder: SpannableStringBuilder, context: Context?) {
// No matter what happens in this world, never forget where you came from.
val startIndex = builder.length
// First render all child nodes, as these are the nodes we want to apply the styles to.
getChildren()?.forEach { (it as SpannableRenderableNode).render(builder, context) }
styles.forEach { builder.setSpan(it, startIndex, builder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) }
}
@AndyG
AndyG / BoldRule.kt
Last active April 3, 2018 23:21
Old Bold Rule
// Matches: **This text should be bold.**
val PATTERN_BOLD = Pattern.compile("^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)")
class BoldRule : Parser.Rule(PATTERN_BOLD) {
override fun parse(matcher: Matcher, parser: Parser): Node {
val boldSpan = StyleSpan(Typeface.BOLD)
// Recursively parse inside the **delimiters**
val childNodes = parser.parse(matcher.group(1))
return StyleNode(StyleSpan(Typeface.BOLD, childNodes))
@AndyG
AndyG / BoldRule.kt
Last active March 2, 2018 02:28
New Bold Rule
// **This text should be bold.**
val PATTERN_BOLD = Pattern.compile("^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)")
class BoldRule : Rule(PATTERN_BOLD) {
override fun parse(matcher: Matcher, parser: Parser): ParseSpec {
val boldNode = StyleNode(StyleSpan(Typeface.BOLD))
val innerParseStartIndex = matcher.start(1)
val innerParseEndIndex = matcher.end(1)
// Don't actually recursively parse, just return a ParseSpec that informs the Parser
@AndyG
AndyG / init.vim
Last active November 19, 2018 19:02
Neovim config file w/ vim-plug.
" Allow filetype-specific plugins.
filetype plugin on
" Update faster (mainly for git stuff).
set updatetime=100
" Split navigation with tab and backspace.
nnoremap <Tab> <c-w>w
nnoremap <bs> <c-w>W