Skip to content

Instantly share code, notes, and snippets.

@gokr
Last active April 29, 2016 06:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gokr/c801d6a3d721d4712ac149f8eda3325f to your computer and use it in GitHub Desktop.
Save gokr/c801d6a3d721d4712ac149f8eda3325f to your computer and use it in GitHub Desktop.
Draft of EBNF for the Spry language
The language constructs are explained using an extended BNF, in which (a)* means 0 or more a's,
a+ means 1 or more a's, and (a)? means an optional a. Parentheses may be used to group elements.
{} are used to describe character sets. Stuff I can't figure out is described inside {{ }}.
# Ints are parsed using Nim parseInt, floats using parseFloat and strings using unescape
int = ['+' | '-'] digit (['_'] digit)*
exponent = ('e' | 'E' ) ['+' | '-'] digit ( ['_'] digit )*
float = ['+' | '-'] digit (['_'] digit)* (('.' (['_'] digit)* [exponent]) | exponent)
# Inside the string we replace any \\ by \, any \' by ', any \" by " and any
# \xHH (where HH is a hexadecimal value) with the corresponding character
string = '"' {{all sequences of characters except a \" not preceded by a \\}} '"'
# Literals are pluggable in the Parser, but these three are the core ones
literal = int | float | string
# Same definition as in Nim strutils
whitespace = {' ', '\x09', '\x0B', '\x0D', '\x0A', '\x0C'}
name = {{any sequence of characters not parsed as a literal}}
qualifiedname = name '::' name
evalnormalword = (name | qualifiedname)
evalselfword = '.' name
evalouterword = '..' name
evalword = evalouterword | evalselfword | evalnormalword
getnormalword = '^' (name | qualifiedname)
getselfword = '^.' name
getouterword = '^..' name
getword = getouterword | getselfword | getnormalword
argevalword = ':' name
arggetword = '^:' name
argword = argevalword | arggetword
word = evalword | getword | argword
block = '[' program ']'
paren = '(' program ')'
curly = '{' program '}'
# Comments are detected outside literals and consume the rest of the line
# They do NOT constitute nodes in Spry. Yet.
comment = '#' (any)* '\l'
node = literal | word | block | paren | curly
# A program is just a sequence of nodes separated by optional whitespace.
# Perhaps not exactly correct, two words *must* be separated by whitespace.
program = ((whitespace)? node (whitespace)?)*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment