Relay.g4 3.89 KB
Newer Older
1 2
grammar Relay;

3 4
SEMVER: 'v0.0.1' ;

5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Lexing
// comments
WS : [ \t\n\r]+ -> skip ;
LINE_COMMENT : '//' .*? '\n' -> skip ;
COMMENT : '/*' .*? '*/' -> skip ;

// operators
MUL: '*' ;
DIV: '/' ;
ADD: '+' ;
SUB: '-' ;
LT: '<' ;
GT: '>' ;
LE: '<=' ;
GE: '>=' ;
EQ: '==' ;
NE: '!=' ;

opIdent: CNAME ;
GLOBAL_VAR: '@' CNAME ;
25 26
LOCAL_VAR: '%' CNAME;
GRAPH_VAR: '%' NAT;
27 28 29 30 31 32 33 34 35 36

MUT: 'mut' ;

BOOL_LIT
  : 'True'
  | 'False'
  ;

// non-negative floats
FLOAT
37 38
  : NAT '.' NAT EXP? // 1.35, 1.35E-9, 0.3, 4.5
  | NAT EXP // 1e10 3e4
39 40 41
  ;

// non-negative ints
42 43
NAT: DIGIT+ ;
fragment EXP: [eE] [+\-]? NAT ; // \- since - means "range" inside [...]
44 45 46 47 48 49 50 51

CNAME: ('_'|LETTER) ('_'|LETTER|DIGIT)* ;
fragment LETTER: [a-zA-Z] ;
fragment DIGIT: [0-9] ;

// Parsing

// A Relay program is a list of global definitions or an expression.
52
prog: SEMVER (defn* | expr) EOF ;
53 54 55 56 57 58

// option: 'set' ident BOOL_LIT ;

expr
  // operators
  : '(' expr ')'                              # parens
59 60
  // function application
  | expr '(' (expr (',' expr)*)? ')'          # call
61 62 63 64 65 66
  | '-' expr                                  # neg
  | expr op=('*'|'/') expr                    # binOp
  | expr op=('+'|'-') expr                    # binOp
  | expr op=('<'|'>'|'<='|'>=') expr          # binOp
  | expr op=('=='|'!=') expr                  # binOp

67
  // function definition
68 69 70 71 72 73 74 75 76 77 78
  | func                                      # funcExpr

  // tuples and tensors
  | '(' ')'                                   # tuple
  | '(' expr ',' ')'                          # tuple
  | '(' expr (',' expr)+ ')'                  # tuple
  | '[' (expr (',' expr)*)? ']'               # tensor

  | 'if' '(' expr ')' body 'else' body        # ifElse

  // sequencing
79 80
  | 'let' MUT? var '=' expr ';' expr          # let
  | 'let' MUT? var '=' '{' expr '}' ';' expr  # let
81
  // sugar for let %_ = expr; expr
82 83
  | expr ';' expr                             # let
  | ident '=' expr ';' expr                   # graph
84 85 86 87 88 89 90

  // mutable update
  // | ident '=' expr                            # writeRef
  // | expr '^'                                  # readRef

  | ident                                     # identExpr
  | scalar                                    # scalarExpr
91 92
  // | expr '.' NAT                           # project
  // | 'debug'                                # debug
93 94
  ;

95 96 97 98 99 100 101 102
func: 'fn'        '(' argList ')' ('->' type_)? body ;
defn: 'def' ident '(' argList ')' ('->' type_)? body ;

argList
  : varList
  | attrList
  | varList ',' attrList
  ;
103

104
varList: (var (',' var)*)? ;
105 106
var: ident (':' type_)? ;

107 108 109
attrList: (attr (',' attr)*)? ;
attr: CNAME '=' expr ;

110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
// TODO(@jmp): for improved type annotations
// returnAnno: (ident ':')? type_ ;

// relations: 'where' relation (',' relation)* ;
// relation: ident '(' (type_ (',' type_)*)? ')' ;

type_
  : '(' ')'                                         # tupleType
  | '(' type_ ',' ')'                               # tupleType
  | '(' type_ (',' type_)+ ')'                      # tupleType
  | identType                                       # identTypeType
  | 'Tensor' '[' shapeSeq ',' type_ ']'             # tensorType
  // currently unused
  // | identType '[' (type_ (',' type_)*)? ']'         # callType
  | 'fn' '(' (type_ (',' type_)*)? ')' '->' type_   # funcType
  | '_'                                             # incompleteType
126
  | NAT                                             # intType
127 128 129 130 131 132 133 134 135 136 137 138
  ;

shapeSeq
  : '(' ')'
  | '(' shape ',' ')'
  | '(' shape (',' shape)+ ')'
  ;

shape
  : '(' shape ')'                   # parensShape
  // | type_ op=('*'|'/') type_        # binOpType
  // | type_ op=('+'|'-') type_        # binOpType
139
  | NAT                             # intShape
140 141 142
  ;

identType: CNAME ;
143 144 145 146
// int8, int16, int32, int64
// uint8, uint16, uint32, uint64
// float16, float32, float64
// bool
147 148 149 150 151

body: '{' expr '}' ;

scalar
  : FLOAT    # scalarFloat
152
  | NAT      # scalarInt
153 154 155 156 157 158 159
  | BOOL_LIT # scalarBool
  ;

ident
  : opIdent
  | GLOBAL_VAR
  | LOCAL_VAR
160
  | GRAPH_VAR
161
  ;