Skip to content

Instantly share code, notes, and snippets.

@ppopoff
Last active November 9, 2015 01:01
Show Gist options
  • Save ppopoff/1bbf022327750f37ebcc to your computer and use it in GitHub Desktop.
Save ppopoff/1bbf022327750f37ebcc to your computer and use it in GitHub Desktop.
import org.parboiled2._
/**
* Constants and char predicates
*/
object BkvRecognizer {
val WhitespaceChars = "\n\t "
val IdentifierChar = CharPredicate.AlphaNum ++ '.' ++ '_'
/**
* Identifier must start only with a letter or underscore,
* and contain latin letters, digits, underscore and dots
*/
val IdentifierFirstChar = CharPredicate.Alpha ++ '_'
val IdentifierChar = CharPredicate.AlphaNum ++ '.' ++ '_'
val BlockBeginning = '{'
val BlockEnding = '}'
}
/**
* A recognizer for BKV's grammar
*
* Recognizer != Parser. It doesn't extract any data.
* It just matches the input
*/
class BkvRecognizer(val input: ParserInput) extends Parser with QuotedStringSupport {
import BkvRecognizer._
def WhiteSpace = rule {
anyOf(WhitespaceChars)
}
def OptWs = rule {
zeroOrMore(WhiteSpace)
}
def Newline = rule {
'\r'.? ~ '\n'
}
def Identifier = rule {
IdentifierFirstChar ~ zeroOrMore(IdentifierChar)
}
def Key = rule {
Identifier
}
def Value = rule {
QuotedString
}
def KeyValuePair = rule {
Key ~ OptWs ~ "=" ~ OptWs ~ Value
}
def Block = rule {
BlockName ~ OptWs ~ BlockBeginning ~ Nodes ~ BlockEnding
}
def BlockName = rule {
Identifier
}
// Recursive call. Type MUST be specified
def Node: Rule0 = rule {
KeyValuePair | Block
}
def Nodes = rule {
OptWs ~ zeroOrMore(Node).separatedBy(Newline ~ OptWs) ~ OptWs
}
def Root = rule {
Nodes ~ EOI
}
}
import org.parboiled2._
object QuotedStringSupport {
/**
* Look here for the example.
* https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences
*/
val CharsToBeEscaped = "abfnrtv\\\""
val BackSlash = '\\'
/**
* All printable characters except double quotation and backslash
*/
val AllowedChars = CharPredicate.Printable -- BackSlash -- '"'
}
/**
* Support for strings with double quotations
* and c-like escaping rules
*/
trait QuotedStringSupport { this: Parser =>
import QuotedStringSupport._
def QuotedString: Rule0 = rule {
'"' ~ QuotedStringContent ~ '"'
}
def QuotedStringContent: Rule0 = rule {
zeroOrMore(AllowedChars | DoubleQuotedStringEscapeSequence)
}
def DoubleQuotedStringEscapeSequence = rule {
'\\' ~ anyOf(CharsToBeEscaped)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment