summaryrefslogtreecommitdiff
path: root/lib/compiler/src/core_parse.yrl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compiler/src/core_parse.yrl')
-rw-r--r--lib/compiler/src/core_parse.yrl383
1 files changed, 383 insertions, 0 deletions
diff --git a/lib/compiler/src/core_parse.yrl b/lib/compiler/src/core_parse.yrl
new file mode 100644
index 0000000000..4e98a8c2da
--- /dev/null
+++ b/lib/compiler/src/core_parse.yrl
@@ -0,0 +1,383 @@
+%% -*-Erlang-*-
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1999-2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Core Erlang YECC parser grammar
+
+%% Have explicit productions for annotated phrases named anno_XXX.
+%% This just does an XXX and adds the annotation.
+
+Nonterminals
+
+module_definition module_export module_attribute module_defs
+exported_names exported_name
+attribute_list attribute
+function_definition function_definitions
+
+constant constants atomic_constant tuple_constant cons_constant tail_constant
+other_pattern atomic_pattern tuple_pattern cons_pattern tail_pattern
+binary_pattern segment_patterns segment_pattern
+
+expression single_expression
+literal literals atomic_literal tuple_literal cons_literal tail_literal
+nil tuple cons tail
+binary segments segment
+
+let_expr let_vars letrec_expr case_expr fun_expr
+function_name
+application_expr call_expr primop_expr arg_list
+receive_expr timeout try_expr
+sequence catch_expr
+variable clause clause_pattern
+
+annotation anno_fun anno_expression anno_expressions
+anno_variable anno_variables anno_pattern anno_patterns
+anno_function_name
+anno_clause anno_clauses.
+
+Terminals
+
+%% Separators
+
+'(' ')' '{' '}' '[' ']' '|' ',' '->' '=' '/' '<' '>' ':' '-|' '#'
+
+%% Keywords (atoms are assumed to always be single-quoted).
+
+'module' 'attributes' 'do' 'let' 'in' 'letrec'
+'apply' 'call' 'primop'
+'case' 'of' 'end' 'when' 'fun' 'try' 'catch' 'receive' 'after'
+
+%% Literal tokens (provided by the tokeniser):
+
+char integer float atom string var.
+
+%% Literal tokens NOT provided by the tokenise:
+
+nil -> '[' ']' : {nil,tok_line('$1')}.
+
+%% Declare the start rule for parsing
+
+Rootsymbol module_definition.
+
+
+%% Grammar
+
+module_definition ->
+ 'module' atom module_export module_attribute module_defs 'end' :
+ #c_module{name=#c_literal{val=tok_val('$2')},exports='$3',
+ attrs='$4',defs='$5'}.
+module_definition ->
+ '(' 'module' atom module_export module_attribute module_defs 'end'
+ '-|' annotation ')' :
+ #c_module{anno='$9',name=tok_val('$3'),exports='$4',
+ attrs='$5',defs='$6'}.
+
+module_export -> '[' ']' : [].
+module_export -> '[' exported_names ']' : '$2'.
+
+exported_names -> exported_name ',' exported_names : ['$1' | '$3'].
+exported_names -> exported_name : ['$1'].
+
+exported_name -> function_name : '$1'.
+
+module_attribute -> 'attributes' '[' ']' : [].
+module_attribute -> 'attributes' '[' attribute_list ']' : '$3'.
+
+attribute_list -> attribute ',' attribute_list : ['$1' | '$3'].
+attribute_list -> attribute : ['$1'].
+
+attribute -> atom '=' literal :
+ {#c_literal{val=tok_val('$1')},'$3'}.
+
+module_defs -> function_definitions : '$1'.
+
+annotation -> '[' ']' : [].
+annotation -> '[' constants ']' : '$2'.
+
+function_definitions ->
+ function_definition function_definitions : ['$1' | '$2'].
+function_definitions ->
+ '$empty' : [].
+
+function_definition ->
+ anno_function_name '=' anno_fun :
+ {'$1','$3'}.
+
+anno_fun -> '(' fun_expr '-|' annotation ')' :
+ core_lib:set_anno('$2', '$4').
+anno_fun -> fun_expr : '$1'.
+
+%% Constant terms for annotations and attributes.
+%% These are represented by straight unabstract Erlang.
+
+constant -> atomic_constant : '$1'.
+constant -> tuple_constant : '$1'.
+constant -> cons_constant : '$1'.
+
+constants -> constant ',' constants : ['$1' | '$3'].
+constants -> constant : ['$1'].
+
+atomic_constant -> char : tok_val('$1').
+atomic_constant -> integer : tok_val('$1').
+atomic_constant -> float : tok_val('$1').
+atomic_constant -> atom : tok_val('$1').
+atomic_constant -> string : tok_val('$1').
+atomic_constant -> nil : [].
+
+tuple_constant -> '{' '}' : {}.
+tuple_constant -> '{' constants '}' : list_to_tuple('$2').
+
+cons_constant -> '[' constant tail_constant : ['$2'|'$3'].
+
+tail_constant -> ']' : [].
+tail_constant -> '|' constant ']' : '$2'.
+tail_constant -> ',' constant tail_constant : ['$2'|'$3'].
+
+%% Patterns
+%% We have to be a little sneaky here as we would like to be able to
+%% do:
+%% V = {a}
+%% ( V = {a} -| <anno> )
+%% ( V -| <anno> ) = {a}
+%% V = ( {a} -| <anno> )
+%% ( ( V -| <anno> ) = ( {a} -| <anno> ) -| <anno> )
+
+anno_pattern -> '(' other_pattern '-|' annotation ')' :
+ core_lib:set_anno('$2', '$4').
+anno_pattern -> other_pattern : '$1'.
+anno_pattern -> anno_variable : '$1'.
+
+anno_patterns -> anno_pattern ',' anno_patterns : ['$1' | '$3'].
+anno_patterns -> anno_pattern : ['$1'].
+
+other_pattern -> atomic_pattern : '$1'.
+other_pattern -> tuple_pattern : '$1'.
+other_pattern -> cons_pattern : '$1'.
+other_pattern -> binary_pattern : '$1'.
+other_pattern -> anno_variable '=' anno_pattern :
+ #c_alias{var='$1',pat='$3'}.
+
+atomic_pattern -> atomic_literal : '$1'.
+
+tuple_pattern -> '{' '}' : c_tuple([]).
+tuple_pattern -> '{' anno_patterns '}' : c_tuple('$2').
+
+cons_pattern -> '[' anno_pattern tail_pattern :
+ #c_cons{hd='$2',tl='$3'}.
+
+tail_pattern -> ']' : #c_literal{val=[]}.
+tail_pattern -> '|' anno_pattern ']' : '$2'.
+tail_pattern -> ',' anno_pattern tail_pattern :
+ #c_cons{hd='$2',tl='$3'}.
+
+binary_pattern -> '#' '{' '}' '#' : #c_binary{segments=[]}.
+binary_pattern -> '#' '{' segment_patterns '}' '#' : #c_binary{segments='$3'}.
+
+segment_patterns -> segment_pattern ',' segment_patterns : ['$1' | '$3'].
+segment_patterns -> segment_pattern : ['$1'].
+
+segment_pattern -> '#' '<' anno_pattern '>' '(' anno_patterns ')':
+ case '$6' of
+ [S,U,T,Fs] ->
+ #c_bitstr{val='$3',size=S,unit=U,type=T,flags=Fs};
+ true ->
+ return_error(tok_line('$1'),
+ "expected 4 arguments in binary segment")
+ end.
+
+variable -> var : #c_var{name=tok_val('$1')}.
+
+anno_variables -> anno_variable ',' anno_variables : ['$1' | '$3'].
+anno_variables -> anno_variable : ['$1'].
+
+anno_variable -> variable : '$1'.
+anno_variable -> '(' variable '-|' annotation ')' :
+ core_lib:set_anno('$2', '$4').
+
+%% Expressions
+%% Must split expressions into two levels as nested value expressions
+%% are illegal.
+
+anno_expression -> expression : '$1'.
+anno_expression -> '(' expression '-|' annotation ')' :
+ core_lib:set_anno('$2', '$4').
+
+anno_expressions -> anno_expression ',' anno_expressions : ['$1' | '$3'].
+anno_expressions -> anno_expression : ['$1'].
+
+expression -> '<' '>' : #c_values{es=[]}.
+expression -> '<' anno_expressions '>' : #c_values{es='$2'}.
+expression -> single_expression : '$1'.
+
+single_expression -> atomic_literal : '$1'.
+single_expression -> tuple : '$1'.
+single_expression -> cons : '$1'.
+single_expression -> binary : '$1'.
+single_expression -> variable : '$1'.
+single_expression -> function_name : '$1'.
+single_expression -> fun_expr : '$1'.
+single_expression -> let_expr : '$1'.
+single_expression -> letrec_expr : '$1'.
+single_expression -> case_expr : '$1'.
+single_expression -> receive_expr : '$1'.
+single_expression -> application_expr : '$1'.
+single_expression -> call_expr : '$1'.
+single_expression -> primop_expr : '$1'.
+single_expression -> try_expr : '$1'.
+single_expression -> sequence : '$1'.
+single_expression -> catch_expr : '$1'.
+
+literal -> atomic_literal : '$1'.
+literal -> tuple_literal : '$1'.
+literal -> cons_literal : '$1'.
+
+literals -> literal ',' literals : ['$1' | '$3'].
+literals -> literal : ['$1'].
+
+atomic_literal -> char : #c_literal{val=tok_val('$1')}.
+atomic_literal -> integer : #c_literal{val=tok_val('$1')}.
+atomic_literal -> float : #c_literal{val=tok_val('$1')}.
+atomic_literal -> atom : #c_literal{val=tok_val('$1')}.
+atomic_literal -> string : #c_literal{val=tok_val('$1')}.
+atomic_literal -> nil : #c_literal{val=[]}.
+
+tuple_literal -> '{' '}' : c_tuple([]).
+tuple_literal -> '{' literals '}' : c_tuple('$2').
+
+cons_literal -> '[' literal tail_literal : c_cons('$2', '$3').
+
+tail_literal -> ']' : #c_literal{val=[]}.
+tail_literal -> '|' literal ']' : '$2'.
+tail_literal -> ',' literal tail_literal : #c_cons{hd='$2',tl='$3'}.
+
+tuple -> '{' '}' : c_tuple([]).
+tuple -> '{' anno_expressions '}' : c_tuple('$2').
+
+cons -> '[' anno_expression tail : c_cons('$2', '$3').
+
+tail -> ']' : #c_literal{val=[]}.
+tail -> '|' anno_expression ']' : '$2'.
+tail -> ',' anno_expression tail : c_cons('$2', '$3').
+
+binary -> '#' '{' '}' '#' : #c_literal{val = <<>>}.
+binary -> '#' '{' segments '}' '#' : #c_binary{segments='$3'}.
+
+segments -> segment ',' segments : ['$1' | '$3'].
+segments -> segment : ['$1'].
+
+segment -> '#' '<' anno_expression '>' '(' anno_expressions ')':
+ case '$6' of
+ [S,U,T,Fs] ->
+ #c_bitstr{val='$3',size=S,unit=U,type=T,flags=Fs};
+ true ->
+ return_error(tok_line('$1'),
+ "expected 4 arguments in binary segment")
+ end.
+
+function_name -> atom '/' integer :
+ #c_var{name={tok_val('$1'),tok_val('$3')}}.
+
+anno_function_name -> function_name : '$1'.
+anno_function_name -> '(' function_name '-|' annotation ')' :
+ core_lib:set_anno('$2', '$4').
+
+let_vars -> anno_variable : ['$1'].
+let_vars -> '<' '>' : [].
+let_vars -> '<' anno_variables '>' : '$2'.
+
+sequence -> 'do' anno_expression anno_expression :
+ #c_seq{arg='$2',body='$3'}.
+
+fun_expr -> 'fun' '(' ')' '->' anno_expression :
+ #c_fun{vars=[],body='$5'}.
+fun_expr -> 'fun' '(' anno_variables ')' '->' anno_expression :
+ #c_fun{vars='$3',body='$6'}.
+
+let_expr -> 'let' let_vars '=' anno_expression 'in' anno_expression :
+ #c_let{vars='$2',arg='$4',body='$6'}.
+
+letrec_expr -> 'letrec' function_definitions 'in' anno_expression :
+ #c_letrec{defs='$2',body='$4'}.
+
+case_expr -> 'case' anno_expression 'of' anno_clauses 'end' :
+ #c_case{arg='$2',clauses='$4'}.
+
+anno_clauses -> anno_clause anno_clauses : ['$1' | '$2'].
+anno_clauses -> anno_clause : ['$1'].
+
+anno_clause -> clause : '$1'.
+anno_clause -> '(' clause '-|' annotation ')' :
+ core_lib:set_anno('$2', '$4').
+
+clause -> clause_pattern 'when' anno_expression '->' anno_expression :
+ #c_clause{pats='$1',guard='$3',body='$5'}.
+
+clause_pattern -> anno_pattern : ['$1'].
+clause_pattern -> '<' '>' : [].
+clause_pattern -> '<' anno_patterns '>' : '$2'.
+
+application_expr -> 'apply' anno_expression arg_list :
+ #c_apply{op='$2',args='$3'}.
+
+call_expr ->
+ 'call' anno_expression ':' anno_expression arg_list :
+ #c_call{module='$2',name='$4',args='$5'}.
+
+primop_expr -> 'primop' anno_expression arg_list :
+ #c_primop{name='$2',args='$3'}.
+
+arg_list -> '(' ')' : [].
+arg_list -> '(' anno_expressions ')' : '$2'.
+
+try_expr ->
+ 'try' anno_expression 'of' let_vars '->' anno_expression
+ 'catch' let_vars '->' anno_expression :
+ Len = length('$8'),
+ if Len =:= 2; Len =:= 3 ->
+ #c_try{arg='$2',vars='$4',body='$6',evars='$8',handler='$10'};
+ true ->
+ return_error(tok_line('$7'),
+ "expected 2 or 3 exception variables in 'try'")
+ end.
+
+catch_expr -> 'catch' anno_expression : #c_catch{body='$2'}.
+
+receive_expr -> 'receive' timeout :
+ {T,A} = '$2',
+ #c_receive{clauses=[],timeout=T,action=A}.
+receive_expr -> 'receive' anno_clauses timeout :
+ {T,A} = '$3',
+ #c_receive{clauses='$2',timeout=T,action=A}.
+
+timeout ->
+ 'after' anno_expression '->' anno_expression : {'$2','$4'}.
+
+%% ====================================================================== %%
+
+
+Erlang code.
+
+%% The following directive is needed for (significantly) faster compilation
+%% of the generated .erl file by the HiPE compiler. Please do not remove.
+-compile([{hipe,[{regalloc,linear_scan}]}]).
+
+-include("core_parse.hrl").
+
+-import(cerl, [c_cons/2,c_tuple/1]).
+
+tok_val(T) -> element(3, T).
+tok_line(T) -> element(2, T).