-- This is an Abstract Syntax Description Lanuguage (ASDL) that describes the -- Fortran's Abstract Syntax Tree (AST). See [1] for a short background -- information and motivation and see the paper [2] for a detailed motivation, -- explanation and specification of the language. See [3] for further examples -- of ASDL usage in a real compiler. -- -- [1] https://eli.thegreenplace.net/2014/06/04/using-asdl-to-describe-asts-in-compilers/ -- [2] Wang, D. C., Appel, A. W., Korn, J. L., & Serra, C. S. (1997). The Zephyr Abstract Syntax Description Language. USENIX Conference on Domain-Specific Languages, (October), 213–228. -- [3] https://arxiv.org/abs/cs/9810013 -- -- ASDL's builtin types are: -- * identifier -- * int (signed integers of infinite precision) -- * string -- We extend these by: -- * node (any ASDL node) -- * bool -- -- Specific tools may choose to produce language interfaces that represent -- these types and the ASDL tree in a language specific way (e.g. use finite -- precision integers and signal an error otherwise). -- -- At the AST level we strictly only represent local syntax (no semantics). That -- way each syntax construct is parsed locally, no need to do any non-local -- lookups to figure out what AST node to construct. That is the job of the AST -- to ASR conversion to do non-local lookups to figure out what is what (i.e., -- disambiguate) and report any errors. module AST { unit = TranslationUnit(node* items) mod = Module(identifier name, trivia? trivia, unit_decl1* use, implicit_statement* implicit, unit_decl2* decl, stmt* body, program_unit* contains, location start_name, location end_name) | Submodule(identifier id, identifier? parent_name, identifier name, trivia? trivia, unit_decl1* use, implicit_statement* implicit, unit_decl2* decl, stmt* body, program_unit* contains, location start_name, location end_name) | BlockData(identifier? name, trivia? trivia, unit_decl1* use, implicit_statement* implicit, unit_decl2* decl, stmt* body) | Program(identifier name, trivia? trivia, unit_decl1* use, implicit_statement* implicit, unit_decl2* decl, stmt* body, program_unit* contains, location start_name, location end_name) program_unit = Subroutine(identifier name, arg* args, decl_attribute* attributes, bind? bind, trivia? trivia, unit_decl1* use, import_statement* import, implicit_statement* implicit, unit_decl2* decl, stmt* body, program_unit* contains, identifier* temp_args, location start_name, location end_name) | Procedure(identifier name, arg* args, decl_attribute* attributes, trivia? trivia, unit_decl1* use, import_statement* import, implicit_statement* implicit, unit_decl2* decl, stmt* body, program_unit* contains) | Function(identifier name, arg* args, decl_attribute* attributes, expr? return_var, bind? bind, trivia? trivia, unit_decl1* use, import_statement* import, implicit_statement* implicit, unit_decl2* decl, stmt* body, program_unit* contains, identifier* temp_args, location start_name, location end_name) unit_decl1 = Use(decl_attribute* nature, identifier module, use_symbol* symbols, bool only_present, trivia? trivia) unit_decl2 = Declaration(decl_attribute? vartype, decl_attribute* attributes, var_sym* syms, trivia? trivia) | DeclarationPragma(pragma_type type, string text, trivia? trivia) | Interface(interface_header header, trivia? trivia, interface_item* items) | DerivedType(identifier name, identifier* namelist, trivia? trivia, decl_attribute* attrtype, unit_decl2* items, procedure_decl* contains) | Template(identifier name, identifier* namelist, unit_decl2* decl, program_unit* contains) | Enum(decl_attribute* attr, trivia? trivia, unit_decl2* items) | Instantiate(identifier name, decl_attribute* args, use_symbol* symbols) | Requirement(identifier name, identifier* namelist, unit_decl2* decl, program_unit* funcs) | Require(unit_require* reqs) | Union(identifier name, trivia? trivia, decl_attribute* attrtype, unit_decl2* items) interface_header = InterfaceHeader() | InterfaceHeaderName(identifier name) | InterfaceHeaderAssignment() | InterfaceHeaderOperator(intrinsicop op) | InterfaceHeaderDefinedOperator(string operator_name) | AbstractInterfaceHeader() | InterfaceHeaderWrite(identifier id) | InterfaceHeaderRead(identifier id) interface_item = InterfaceProc(program_unit proc) | InterfaceModuleProcedure(identifier* names, decl_attribute* attributes, trivia? trivia) import_statement = Import(identifier* symbols, import_modifier mod, trivia? trivia) import_modifier = ImportDefault | ImportOnly | ImportNone | ImportAll implicit_statement = ImplicitNone(implicit_none_spec* specs, trivia? trivia) | Implicit(implicit_spec* specs, trivia? trivia) implicit_spec = ImplicitSpec(decl_attribute type, letter_spec* specs) implicit_none_spec = ImplicitNoneExternal(int dummy) | ImplicitNoneType() letter_spec = LetterSpec(identifier? start, identifier end) stmt -- Single-line statements (each has a `label`): = Allocate(int label, fnarg* args, keyword* keywords, trivia? trivia) | Assign(int label, int assign_label, identifier variable, trivia? trivia) | Assignment(int label, expr target, expr value, trivia? trivia) | InferAssignment(int label, expr target, expr value, trivia? trivia) | Associate(int label, expr target, expr value, trivia? trivia) | Backspace(int label, expr* args, keyword* kwargs, trivia? trivia) | Close(int label, expr* args, keyword* kwargs, trivia? trivia) | Continue(int label, trivia? trivia) | Cycle(int label, identifier? stmt_name, trivia? trivia) | Deallocate(int label, fnarg* args, keyword* keywords, trivia? trivia) | Endfile(int label, expr* args, keyword* kwargs, trivia? trivia) | Entry(int label, identifier name, arg* args, expr? return_var, bind? bind, trivia? trivia) | ErrorStop(int label, expr? code, expr? quiet, trivia? trivia) | EventPost(int label, expr variable, event_attribute* stat, trivia? trivia) | EventWait(int label, expr variable, event_attribute* spec, trivia? trivia) | Exit(int label, identifier? stmt_name, trivia? trivia) | Flush(int label, expr* args, keyword* kwargs, trivia? trivia) | ForAllSingle(int label, identifier? stmt_name, concurrent_control *control, expr? mask, stmt assign, trivia? trivia) | Format(int label, string fmt, trivia? trivia) | DataStmt(int label, data_stmt_set* items, trivia? trivia) | FormTeam(int label, expr team_number, identifier team_var, event_attribute* sync_stat, trivia? trivia) | GoTo(int label, identifier? int_var, expr? goto_label, expr* labels, trivia? trivia) | Include(int label, string filename, trivia? trivia) | Inquire(int label, expr* args, keyword* kwargs, expr* values, trivia? trivia) | Nullify(int label, expr* args, keyword* kwargs, trivia? trivia) | Open(int label, expr* args, keyword* kwargs, trivia? trivia) | Return(int label, expr? value, trivia? trivia) | Pragma(int label, pragma_type type, bool end, string construct_name, expr* clauses, trivia? trivia) | Print(int label, expr? fmt, expr* values, trivia? trivia) | Read(int label, expr? format, argstar* args, kw_argstar* kwargs, expr* values, trivia? trivia) | Rewind(int label, expr* args, keyword* kwargs, trivia? trivia) | Stop(int label, expr? code, expr? quiet, trivia? trivia) | SubroutineCall(int label, identifier name, struct_member* member, fnarg* args, keyword* keywords, decl_attribute* temp_args, trivia? trivia) | SyncAll(int label, event_attribute* stat, trivia? trivia) | SyncImages(int label, expr? image_set, symbol sym, event_attribute* stat, trivia? trivia) | SyncMemory(int label, event_attribute* stat, trivia? trivia) | SyncTeam(int label, expr value, event_attribute* stat, trivia? trivia) | Write(int label, argstar* args, kw_argstar* kwargs, expr* values, trivia? trivia) -- Multi-line statements (each has a `label` and `stmt_name`): | AssociateBlock(int label, identifier? stmt_name, var_sym* syms, stmt* body, trivia? t_inside, trivia? trivia) | Block(int label, identifier? stmt_name, unit_decl1* use, import_statement* import,unit_decl2* decl, stmt* body, trivia? t_inside, trivia? trivia) | ChangeTeam(int label, identifier? stmt_name, expr team_value, team_attribute* coarray_assoc, event_attribute* sync, stmt* body, trivia? t_inside, trivia? trivia, event_attribute* sync_stat) | Critical(int label, identifier? stmt_name, event_attribute* sync_stat, stmt* body, trivia? t_inside, trivia? trivia) | DoConcurrentLoop(int label, identifier? stmt_name, concurrent_control *control, expr? mask, concurrent_locality* locality, stmt* body, trivia? t_inside, trivia? trivia) | DoLoop(int label, identifier? stmt_name, int do_label, identifier? var, expr? start, expr? end, expr? increment, stmt* body, trivia? t_inside, trivia? trivia, location var_loc) | ForAll(int label, identifier? stmt_name, concurrent_control *control, expr? mask, concurrent_locality* locality, stmt* body, trivia? t_inside, trivia? trivia) | If(int label, identifier? stmt_name, expr test, stmt* body, stmt* orelse, trivia? if_trivia, trivia? else_trivia, trivia? trivia) | IfArithmetic(int label, identifier? stmt_name, expr test, int lt_label, int eq_label, int gt_label, trivia? trivia) | Select(int label, identifier? stmt_name, expr test, case_stmt* body, trivia? t_inside, trivia? trivia) | SelectRank(int label, identifier? stmt_name, identifier? assoc_name, expr selector, rank_stmt* body, trivia? t_inside, trivia? trivia) | SelectType(int label, identifier? stmt_name, identifier? assoc_name, expr selector, type_stmt* body, trivia? t_inside, trivia? trivia) | Where(int label, identifier? stmt_name, expr test, stmt* body, stmt* orelse, trivia? t_inside, trivia? trivia) | WhileLoop(int label, identifier? stmt_name, expr test, stmt* body, trivia? t_inside, trivia? trivia) expr = BoolOp(expr left, boolop op, expr right) | BinOp(expr left, operator op, expr right) | DefBinOp(expr left, string op, expr right) | StrOp(expr left, stroperator op, expr right) | UnaryOp(unaryop op, expr operand) | DefUnaryOp(string op, expr operand) | Compare(expr left, cmpop op, expr right) | FuncCallOrArray(identifier func, struct_member* member, fnarg* args, keyword* keywords, fnarg* subargs, decl_attribute* temp_args) | CoarrayRef(identifier name, struct_member* member, fnarg* args, keyword* fnkw, coarrayarg* coargs, keyword* cokw) | ArrayInitializer(decl_attribute? vartype, identifier? classtype, expr* args) | ImpliedDoLoop(expr* values, identifier var, expr start, expr end, expr? increment) | Num(int n, string? kind) | Real(string n) | Complex(expr re, expr im) | String(string s, string? kind) | Substring(string s, fnarg* args) | BOZ(string s) | Name(identifier id, struct_member* member) | Logical(bool value, string? kind) | DataImpliedDo(expr* object_list, decl_attribute? type, identifier var, expr start, expr end, expr? increment) | Parenthesis(expr operand) -- All statement nodes have an optional trivia?, here is the meaning: -- nullptr ... Equivalent to \n (the statement ends with \n) -- Meaning of trivia_node (in both `inside` and `after`): -- Comment ...... Comment followed by \n (previous line must be ended) -- EOLComment ... Ends the current line with a comment followed by \n -- EndOfLine .... Ends the current line with \n -- Semicolon .... ";" (just one character, does not end the line) -- The trivia starts with an open line, must be first ended by either -- EOLComment or EndOfLine. trivia = TriviaNode(trivia_node* inside, trivia_node* after) trivia_node = Comment(string comment) | EOLComment(string comment) | EndOfLine() | Semicolon() boolop = And | Or | Xor | Eqv | NEqv operator = Add | Sub | Mul | Div | Pow stroperator = Concat unaryop = Invert | Not | UAdd | USub cmpop = Eq | NotEq | Lt | LtE | Gt | GtE intrinsicop = AND | OR | XOR | EQV | NEQV | PLUS | MINUS | STAR | DIV | POW | NOT | EQ | NOTEQ | LT | LTE | GT | GTE | CONCAT procedure_decl = DerivedTypeProc(identifier? name, decl_attribute* attr, use_symbol* symbols, trivia? trivia) | GenericOperator(decl_attribute* attr, intrinsicop op, identifier* names, trivia? trivia) | GenericDefinedOperator(decl_attribute* attr, string optype, identifier* names, trivia? trivia) | GenericAssignment(decl_attribute* attr, identifier* names, trivia? trivia) | GenericName(decl_attribute* attr, identifier name, identifier* names, trivia? trivia) | GenericWrite(decl_attribute* attr, identifier id, identifier* names, trivia? trivia) | GenericRead(decl_attribute* attr, identifier id, identifier* names, trivia? trivia) | FinalName(identifier name, trivia? trivia) | Private(trivia? trivia) decl_attribute = AttrBind(bind bind) | AttrDimension(dimension* dim) | AttrCodimension(codimension* codim) | AttrCommon(common_block* blks) | AttrEquivalence(equi* args) | AttrExtends(identifier name) | AttrIntent(attr_intent intent) | AttrNamelist(identifier name) | AttrPass(identifier? name) | SimpleAttribute(simple_attribute attr) | AttrType(decl_type type, kind_item* kind, decl_attribute? attr, identifier? name, symbol sym) | AttrTypeList(decl_type type, decl_attribute* attr) | AttrAssignment() | AttrIntrinsicOperator(intrinsicop op) | AttrDefinedOperator(string op_name) simple_attribute = AttrAbstract | AttrAllocatable | AttrAsynchronous | AttrContiguous | AttrDeferred | AttrElemental | AttrEnumerator | AttrExternal | AttrImpure | AttrIntrinsic | AttrKind | AttrLen | AttrModule | AttrNoPass | AttrNonDeferred | AttrNon_Intrinsic | AttrOptional | AttrParameter | AttrPointer | AttrPrivate | AttrProtected | AttrPublic | AttrPure | AttrRecursive | AttrNonRecursive | AttrSave | AttrSequence | AttrTarget | AttrValue | AttrVolatile attr_intent = In | Out | InOut decl_type = TypeClass | TypeCharacter | TypeComplex | TypeDoublePrecision | TypeDoubleComplex | TypeInteger | TypeLogical | TypeProcedure | TypeReal | TypeType | TypeList | TypeSet | TypeDict | TypeTuple event_attribute = AttrStat(identifier variable) | AttrErrmsg(identifier variable) | AttrNewIndex(expr value) | AttrEventWaitKwArg(identifier id, expr value) team_attribute = CoarrayAssociation(expr coarray, expr selector) var_sym = (identifier? name, dimension* dim, codimension* codim, expr? length, expr? initializer, symbol sym, decl_attribute? spec) common_block = (identifier? name, var_sym* objects) kind_item = (identifier? id, expr? value, kind_item_type type) kind_item_type = Star | Colon | Value dimension = (expr? start, expr? end, dimension_type end_star) dimension_type = DimensionExpr | DimensionStar | AssumedRank codimension = (expr? start, expr? end, codimension_type end_star) codimension_type = CodimensionExpr | CodimensionStar symbol = None | Arrow | Equal | Asterisk | DoubleAsterisk | Slash | SlashInit equi = (expr* set_list) -- Encoding of an array dimension declaration: -- start end end_star -- Declaration: -- X(n) 1 n Expr # Note: X(n) is equivalent to X(1:n) -- X(:) () () Expr -- X(a:) a () Expr -- X(:b) () b Expr -- X(a:b) a b Expr -- X(*) () () Star -- X(a:*) a () Star -- Null for `expr` means it's a star kw_argstar = (identifier arg, expr? value) argstar = (expr? value) -- The identifier is wrapped up in a product type so that location information -- is included: -- Null for `arg` means, it's a star arg = (identifier? arg) -- Encoding of array elements and sections in fnarg: -- start end step label -- element: -- X(i) () i () 0 -- X(*10) () () () 10 -- section: -- X(:) () () 1 0 -- X(a:) a () 1 0 -- X(:b) () b 1 0 -- X(a:b) a b 1 0 -- X(::c) () () c 0 -- X(a::c) a () c 0 -- X(:b:c) () b c 0 -- X(a:b:c) a b c 0 -- fnarg = (expr? start, expr? end, expr? step, int label) coarrayarg = (expr? start, expr? end, expr? step, codimension_type star) keyword = (identifier arg, expr value) struct_member = (identifier name, fnarg* args) bind = Bind(expr* args, keyword* kwargs) array_index = ArrayIndex(expr? left, expr? right, expr? step) case_stmt = CaseStmt(case_cond* test, trivia? trivia, stmt* body) | CaseStmt_Default(trivia? trivia, stmt* body) case_cond = CaseCondExpr(expr cond) | CaseCondRange(expr? start, expr? end) rank_stmt = RankExpr(expr value, trivia? trivia, stmt* body) | RankStar(trivia? trivia, stmt* body) | RankDefault(trivia? trivia, stmt* body) type_stmt = TypeStmtName(identifier? name, trivia? trivia, stmt* body) | TypeStmtType(decl_attribute? vartype, trivia? trivia, stmt* body) | ClassStmt(identifier? id, trivia? trivia, stmt* body) | ClassDefault(trivia? trivia, stmt* body) use_symbol = UseSymbol(identifier remote_sym, identifier? local_rename) | UseAssignment() | IntrinsicOperator(intrinsicop op) | DefinedOperator(string opName) | RenameOperator(string local_defop, string use_defop) | UseWrite(identifier id) | UseRead(identifier id) concurrent_control = ConcurrentControl(decl_attribute? type, identifier? var, expr? start, expr? end, expr? increment) concurrent_locality = ConcurrentLocal(identifier *vars) | ConcurrentLocalInit(identifier *vars) | ConcurrentShared(identifier *vars) | ConcurrentDefault() | ConcurrentReduce(reduce_op op, identifier *vars) reduce_op = ReduceAdd | ReduceSub | ReduceMul | ReduceMIN | ReduceMAX | ReduceIAND | ReduceIOR | ReduceIEOR data_stmt_set = DataStmtSet(expr* object, expr* value) pragma_type = LFortranPragma | OMPPragma unit_require = UnitRequire(identifier name, decl_attribute* namelist) }