Skip to content

Instantly share code, notes, and snippets.

@sritchie
Created September 4, 2013 18:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sritchie/6440578 to your computer and use it in GitHub Desktop.
Save sritchie/6440578 to your computer and use it in GitHub Desktop.
// First pass at a thrift parser using instaparse:
(def instagram
(insta/parser
"
Document ::= <ws> Header* Definition*
SlashComment ::= <'//'> #'[^\n]'*
PoundComment ::= <'#'> #'[^\n]'*
BlockComment ::= '/*' #'(?s).'* '*/'
Comment ::= SlashComment | PoundComment | BlockComment | <ws>
ws ::= <[#'\\s*']> | (Comment <ws>)
Header ::= (Include | CppInclude | Namespace)
Include ::= <'include'> <ws> Literal <ws>
CppInclude ::= <'cpp_include'> <ws> Literal <ws>
Namespace ::= (( <'namespace'> <ws> ( NamespaceScope Identifier ) |
( <'smalltalk.category'> <ws> STIdentifier ) |
( <'smalltalk.prefix'> <ws> Identifier ) ) |
( <'php_namespace'> <ws> Literal ) |
( <'xsd_namespace'> <ws> Literal )) <ws>
NamespaceScope ::= ('*' | 'cpp' | 'java' | 'py' | 'perl' | 'rb' | 'cocoa' | 'csharp' | 'clojure') <ws>
Definition ::= (Const | Typedef | Enum | Senum | Struct | Exception | Service) <ws>
Const ::= <'const'> <ws> FieldType Identifier <'='> <ws> ConstValue ListSeparator?
Typedef ::= <'typedef'> <ws> DefinitionType Identifier
Enum ::= <'enum'> <ws> Identifier <'{'> <ws> (EnumEntry | DefaultEntry)* <ws> <'}'>
EnumEntry ::= Identifier <ListSeparator?>
DefaultEntry ::= Identifier DefaultValue <ListSeparator?>
DefaultValue ::= <'='> <ws> IntConstant <ws>
Senum ::= <'senum'> <ws> Identifier <'{'> (Literal ListSeparator?)* <'}'>
Struct ::= <'struct'> <ws> Identifier <ws> ('xsd_all'? | <ws>) <'{'> (<ws> Field <ws>)* <'}'>
Exception ::= <'exception'> <ws> Identifier <'{'> (<ws> Field)* <'}'>
Service ::= <'service'> <ws> Identifier ( <'extends'> <ws> Identifier )? <'{'> (<ws> Function <ws>)* <'}'>
Field ::= FieldID <ws> FieldReq? <ws> FieldType <ws> Identifier <ws> ('=' <ws> ConstValue)? <ws> XsdFieldOptions <ws> <ListSeparator>? <ws>
FieldID ::= (IntConstant <ws> <':'>) <ws>
FieldReq ::= ('required' | 'optional') <ws>
XsdFieldOptions ::= 'xsd_optional'? 'xsd_nillable'? XsdAttrs?
XsdAttrs ::= 'xsd_attrs' '{' Field* '}'
Function ::= <('oneway' ws)?> FunctionType Identifier '(' Field* ')' Throws? ListSeparator?
FunctionType ::= FieldType | 'void'
Throws ::= 'throws' '(' Field* ')'
FieldType ::= Identifier | BaseType | ContainerType
DefinitionType ::= BaseType | ContainerType
BaseType ::= ('bool' | 'byte' | 'i16' | 'i32' | 'i64' | 'double' | 'string' | 'binary' | 'slist') <ws>
ContainerType ::= MapType | SetType | ListType
MapType ::= <'map'> <ws> CppType? <'<'> <ws> FieldType <','> FieldType <'>'> <ws>
SetType ::= <'set'> <ws> CppType? <'<'> FieldType <'>'> <ws>
ListType ::= <'list'> <ws> <'<'> FieldType <'>'> CppType? <ws>
CppType ::= <'cpp_type'> <ws> Literal
ConstValue ::= (IntConstant | DoubleConstant | Literal | Identifier | ConstList | ConstMap)
IntConstant ::= ('+' | '-')? Digit+ <ws>
DoubleConstant ::= ('+' | '-')? Digit* ('.' Digit+)? ( ('E' | 'e') IntConstant )? <ws>
ConstList ::= <'['> (ConstValue ListSeparator?)* <']'> <ws>
ConstMap ::= <'{'> (ConstValue <':'> ConstValue <ListSeparator>?)* <'}'> <ws>
Literal ::= ((<'\\\"'> #'[^\"]+'* <'\\\"'>) | (<\"'\"> #'[^\\']+'* <\"'\">)) <ws>
Identifier ::= (( Letter | '_' ) ( Letter | Digit | '.' | '_' )*) <ws>
STIdentifier ::= ( Letter | '_' ) ( Letter | Digit | '.' | '_' | '-' )* <ws>
ListSeparator ::= (',' | ';') <ws>
<Letter> ::= #'[a-zA-Z]'
<Digit> ::= #'[0-9]'"))
// And the test. Enums are still busted.
(def forma
"/**
* Just some comment nastiness. // nested line.
*
*
*/
// And more comments by me.
# Bullshit.
// include \"DOESNTEXIST.thrift\"
include \"face.thrift\"
cpp_include \"boggle.thrift\"
namespace clojure forma.schema
namespace rb forma.schema
/**
* Thrift lets you do typedefs to get pretty names for your types. Standard
* C style here.
*/
typedef i32 MyInteger
/**
* Thrift also lets you define constants for use across languages. Complex
* types and structs are specified using JSON notation.
*/
const i32 INT32CONSTANT = 9853
struct /* random whitespace */ FireValue {
1: i32 temp330;
2: i32 conf50;
3: i32 bothPreds;
4: i32 count;
}
enum Operation {
ADD,
SUBTRACT = 2,
MULTIPLY // should have a value of 3
DIVIDE = 4
}
/**
* Structs can also be exceptions, if they are nasty.
*/
exception InvalidOperation {
1: i32 what,
2: string why
}
service Calculator extends face.SharedService {
/**
* A method definition looks like C code. It has a return type, arguments,
* and optionally a list of exceptions that it may throw. Note that argument
* lists and exception lists are specified using the exact same syntax as
* field lists in struct or exception definitions. NOTE: Overloading of
* methods is not supported; each method requires a unique name.
*/
void ping(),
i32 add(1:i32 num1, 2:i32 num2),
i32 calculate(1:i32 logid, 2:FireValue fv) throws (1:InvalidOperation ouch),
/**
* This method has an oneway modifier. That means the client only makes
* a request and does not listen for any response at all. Oneway methods
* must be void.
*
* The server may execute async invocations of the same client in parallel/
* out of order.
*/
oneway void zip(),
}
struct FormaValue {
1: FireValue fireValue;
2: double shortDrop;
3: double longDrop;
4: double tStat;
5: optional double paramBreak;
}
")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment