Skip to content

Instantly share code, notes, and snippets.

@dynajoe
Created October 25, 2018 03:10
Show Gist options
  • Save dynajoe/eeeff72c7ffebc1bb56153078694d90e to your computer and use it in GitHub Desktop.
Save dynajoe/eeeff72c7ffebc1bb56153078694d90e to your computer and use it in GitHub Desktop.
A PEG.js Grammar for Elm
{
function extractList(list, index) {
return list.map(function(element) { return element[index]; });
}
function buildList(head, tail, index) {
return [head].concat(extractList(tail, index));
}
function optionalList(value) {
return value !== null ? value : [];
}
}
start
= __ program:Program __ { return program; }
__
= (Ws / Comment)*
LParen = __ "(" __
RParen = __ ")" __
LBrace = __ "{" __
RBrace = __ "}" __
Statement
= module:ModuleDeclaration
imports:ImportStatement* {
return { ...module, imports: imports }
}
ModuleAlias = AsToken moduleName:ModuleName { return moduleName; }
ModuleDeclaration
= ModuleToken
moduleName:ModuleName
exposing:ModuleExports? {
return {
type: 'module',
module: moduleName,
exposing: exposing,
};
}
ImportStatement
= ImportToken
moduleName:ModuleName
alias:ModuleAlias?
exposing:ModuleExports? {
return {
type: 'import',
module: moduleName,
alias: alias || moduleName,
exposing: exposing,
};
}
ConstructorExport
= moduleName:ModuleName LParen ExposingAll RParen {
return {
type: 'constructor',
name: moduleName,
};
}
ExportedModule
= ExposingAll { return { type: 'all' }; }
/ fn:FunctionName { return { type: 'function', name: fn }; }
/ ctor:ConstructorExport { return ctor; }
/ module:ModuleName { return { type: 'module', name: module }; }
ExposingList =
head:ExportedModule
tail:(Comma t:ExportedModule { return t; })* { return [head].concat(tail); }
ModuleExports
= ExposingToken
LParen exposing:ExposingList RParen {
return exposing;
}
SingleLineComment
= "--" [^\n]* Ws* {
return { type: 'comment', comment: text() };
}
MultiLineComment
= "{-" (!"-}" ( MultiLineComment / . ))* "-}" Ws* {
return { type: 'comment', comment: text() };
}
Comment
= SingleLineComment
/ MultiLineComment
Comma
= Ws* "," Ws*
ExposingAll
= ".."
Ws
= [ \r\n\t]
FunctionName
= ([a-z][a-z0-9]+)+ { return text().trim(); }
/ LParen [:+-]+ RParen { return text().trim(); }
ModuleName
= ([A-Z][a-z0-9]i*)+ Ws* { return text().trim(); }
AsToken
= "as" Ws+
ModuleToken
= Ws* "module" Ws+
ExposingToken
= "exposing" Ws+
ImportToken
= "import" Ws+
Program
= statements:SourceElements? {
return {
type: "Program",
statements: optionalList(statements)
};
}
SourceElements
= head:SourceElement tail:(Ws SourceElement)* {
return buildList(head, tail, 1);
}
SourceElement
= Statement
/ Comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment