fortran-src-0.10.0: src/Language/Fortran/Parser/Fixed/Fortran77.y
-- -*- Mode: Haskell -*-
-- vim: ft=haskell
{
module Language.Fortran.Parser.Fixed.Fortran77
( programParser
, blockParser
, statementParser
, expressionParser
, includesParser
) where
import Language.Fortran.Version
import Language.Fortran.Util.Position
import Language.Fortran.Parser.Monad
import Language.Fortran.Parser.ParserUtils
import Language.Fortran.Parser.Fixed.Lexer
import Language.Fortran.Parser.Fixed.Utils
import Language.Fortran.AST
import Language.Fortran.AST.Literal.Real
import Prelude hiding ( EQ, LT, GT ) -- Same constructors exist in the AST
import Data.Maybe ( isNothing, fromJust )
import qualified Data.List as List
}
%name programParser PROGRAM
%name blockParser BLOCK
%name statementParser STATEMENT
%name expressionParser EXPRESSION
%name includesParser INCLUDES
%monad { LexAction }
%lexer { lexer } { TEOF _ }
%tokentype { Token }
%error { parseError }
%token
'(' { TLeftPar _ }
')' { TRightPar _ }
'(/' { TLeftArrayPar _ }
'/)' { TRightArrayPar _ }
',' { TComma _ }
'.' { TDot _ }
'%' { TPercent _ }
':' { TColon _ }
include { TInclude _ }
program { TProgram _ }
function { TFunction _ }
subroutine { TSubroutine _ }
endprogram { TEndProgram _ }
endfunction { TEndFunction _ }
endsubroutine { TEndSubroutine _ }
blockData { TBlockData _ }
structure { TStructure _ }
union { TUnion _ }
map { TMap _ }
endstructure { TEndStructure _ }
endunion { TEndUnion _ }
endmap { TEndMap _ }
record { TRecord _ }
end { TEnd _ }
'=' { TOpAssign _ }
assign { TAssign _ }
to { TTo _ }
goto { TGoto _ }
if { TIf _ }
then { TThen _ }
else { TElse _ }
elsif { TElsif _ }
endif { TEndif _ }
call { TCall _ }
return { TReturn _ }
save { TSave _ }
continue { TContinue _ }
stop { TStop _ }
exit { TExit _ }
cycle { TCycle _ }
case { TCase _ }
selectcase { TSelectCase _ }
endselect { TEndSelect _ }
casedefault { TCaseDefault _ }
pause { TPause _ }
do { TDo _ }
doWhile { TDoWhile _ }
while { TWhile _ }
enddo { TEndDo _ }
read { TRead _ }
write { TWrite _ }
print { TPrint _ }
typeprint { TTypePrint _ }
open { TOpen _ }
close { TClose _ }
inquire { TInquire _ }
rewind { TRewind _ }
backspace { TBackspace _ }
endfile { TEndfile _ }
common { TCommon _ }
equivalence { TEquivalence _ }
external { TExternal _ }
dimension { TDimension _ }
byte { TType _ "byte" }
character { TType _ "character" }
integer { TType _ "integer" }
real { TType _ "real" }
doublePrecision { TType _ "doubleprecision" }
logical { TType _ "logical" }
complex { TType _ "complex" }
doubleComplex { TType _ "doublecomplex" }
intrinsic { TIntrinsic _ }
implicit { TImplicit _ }
parameter { TParameter _ }
pointer { TPointer _ }
entry { TEntry _ }
none { TNone _ }
data { TData _ }
automatic { TAutomatic _ }
static { TStatic _ }
format { TFormat _ }
blob { TBlob _ _ }
int { TInt _ _ }
boz { TBozLiteral _ _ }
exponent { TExponent _ _ }
bool { TBool _ _ }
'+' { TOpPlus _ }
'-' { TOpMinus _ }
'**' { TOpExp _ }
'*' { TStar _ }
'/' { TSlash _ }
'&' { TAmpersand _ }
eqv { TOpEquivalent _ }
neqv { TOpNotEquivalent _ }
or { TOpOr _ }
and { TOpAnd _ }
xor { TOpXOr _ }
not { TOpNot _ }
'<' { TOpLT _ }
'<=' { TOpLE _ }
'>' { TOpGT _ }
'>=' { TOpGE _ }
'==' { TOpEQ _ }
'!=' { TOpNE _ }
id { TId _ _ }
comment { TComment _ _ }
hollerith { THollerith _ _ }
string { TString _ _ }
label { TLabel _ _ }
newline { TNewline _ }
%left eqv neqv xor
%left or
%left and
%right not
%nonassoc '>' '<' '>=' '<=' '==' '!='
%nonassoc RELATIONAL
%left CONCAT
%left '+' '-'
%left '*' '/'
%right NEGATION
%right '**'
%%
maybe(p)
: p { Just $1 }
| {- empty -} { Nothing }
rev_list1(p)
: p { [$1] }
| rev_list1(p) p { $2 : $1 }
rev_list(p)
: rev_list1(p) { $1 }
| {- empty -} { [] }
list1(p)
: rev_list1(p) { reverse $1 }
list(p)
: rev_list(p) { reverse $1 }
-- This rule is to ignore leading whitespace
PROGRAM :: { ProgramFile A0 }
: NEWLINE PROGRAM_INNER { $2 }
| PROGRAM_INNER { $1 }
PROGRAM_INNER :: { ProgramFile A0 }
: PROGRAM_UNITS { ProgramFile (MetaInfo { miVersion = Fortran77, miFilename = "" }) (reverse $1) }
| {- empty -} { ProgramFile (MetaInfo { miVersion = Fortran77, miFilename = "" }) [] }
PROGRAM_UNITS :: { [ ProgramUnit A0 ] }
: PROGRAM_UNITS maybe(LABEL_IN_6COLUMN) PROGRAM_UNIT maybe(NEWLINE) { $3 : $1 }
| maybe(LABEL_IN_6COLUMN) PROGRAM_UNIT maybe(NEWLINE) { [ $2 ] }
PROGRAM_UNIT :: { ProgramUnit A0 }
: program NAME BLOCKS NEWLINE ENDPROG
{ PUMain () (getTransSpan $1 $5) (Just $2) (reverse $3) Nothing }
| TYPE_SPEC function NAME MAYBE_ARGUMENTS BLOCKS NEWLINE ENDFUN
{ PUFunction () (getTransSpan $1 $7) (Just $1) emptyPrefixSuffix $3 $4 Nothing (reverse $5) Nothing }
| function NAME MAYBE_ARGUMENTS BLOCKS NEWLINE ENDFUN
{ PUFunction () (getTransSpan $1 $6) Nothing emptyPrefixSuffix $2 $3 Nothing (reverse $4) Nothing }
| subroutine NAME MAYBE_ARGUMENTS BLOCKS NEWLINE ENDSUB
{ PUSubroutine () (getTransSpan $1 $6) emptyPrefixSuffix $2 $3 (reverse $4) Nothing }
| blockData BLOCKS NEWLINE END { PUBlockData () (getTransSpan $1 $4) Nothing (reverse $2) }
| blockData NAME BLOCKS NEWLINE END { PUBlockData () (getTransSpan $1 $5) (Just $2) (reverse $3) }
| comment { let (TComment s c) = $1 in PUComment () s (Comment c) }
END :: { Token }
: end { $1 }
| LABEL_IN_6COLUMN end { $2 }
ENDPROG :: { Token }
: END { $1 }
| endprogram MAYBE_ID { $1 }
| LABEL_IN_6COLUMN endprogram MAYBE_ID { $2 }
ENDFUN :: { Token }
: END { $1 }
| endfunction MAYBE_ID { $1 }
| LABEL_IN_6COLUMN endfunction MAYBE_ID { $2 }
ENDSUB :: { Token }
: END { $1 }
| endsubroutine MAYBE_ID { $1 }
| LABEL_IN_6COLUMN endsubroutine MAYBE_ID { $2 }
MAYBE_ARGUMENTS :: { Maybe (AList Expression A0) }
: '(' MAYBE_VARIABLES ')' { $2 }
| {- Nothing -} { Nothing }
MAYBE_ID :: { Maybe Name }
: id { let (TId _ name) = $1 in Just name }
| {- empty -} { Nothing }
NAME :: { Name } : id { let (TId _ name) = $1 in name }
INCLUDES :: { [ Block A0 ] }
: BLOCKS maybe(NEWLINE) { $1 }
BLOCKS :: { [ Block A0 ] }
: BLOCKS NEWLINE BLOCK { $3 : $1 }
| BLOCK { [ $1 ] }
| {- EMPTY -} { [ ] }
BLOCK :: { Block A0 }
: IF_BLOCK { $1 }
| LABEL_IN_6COLUMN STATEMENT { BlStatement () (getTransSpan $1 $2) (Just $1) $2 }
| STATEMENT { BlStatement () (getSpan $1) Nothing $1 }
| comment { let (TComment s c) = $1 in BlComment () s (Comment c) }
IF_BLOCK :: { Block A0 }
: if '(' EXPRESSION ')' then BLOCKS NEWLINE ELSE_BLOCKS
{ let (clauses, elseBlock, endSpan, endLabel) = $8
in BlIf () (getTransSpan $1 endSpan) Nothing Nothing (($3, reverse $6) :| clauses) elseBlock endLabel }
| LABEL_IN_6COLUMN if '(' EXPRESSION ')' then BLOCKS NEWLINE ELSE_BLOCKS
{ let (clauses, elseBlock, endSpan, endLabel) = $9
in BlIf () (getTransSpan $1 endSpan) (Just $1) Nothing (($4, reverse $7) :| clauses) elseBlock endLabel }
ELSE_BLOCKS :: { ([(Expression A0, [Block A0])], Maybe [Block A0], SrcSpan, Maybe (Expression A0)) }
: maybe(LABEL_IN_6COLUMN) elsif '(' EXPRESSION ')' then BLOCKS NEWLINE ELSE_BLOCKS
{ let (clauses, elseBlock, endSpan, endLabel) = $9
in (($4, reverse $7) : clauses, elseBlock, endSpan, endLabel) }
| maybe(LABEL_IN_6COLUMN) else BLOCKS NEWLINE maybe(LABEL_IN_6COLUMN) endif
{ ([], Just (reverse $3), getSpan $6, $5) }
| maybe(LABEL_IN_6COLUMN) endif
{ ([], Nothing, getSpan $2, $1) }
NEWLINE :: { Token }
: NEWLINE newline { $1 }
| newline { $1 }
STATEMENT :: { Statement A0 }
: LOGICAL_IF_STATEMENT { $1 }
| DO_STATEMENT { $1 }
| EXECUTABLE_STATEMENT { $1 }
| NONEXECUTABLE_STATEMENT { $1 }
LOGICAL_IF_STATEMENT :: { Statement A0 }
: if '(' EXPRESSION ')' EXECUTABLE_STATEMENT { StIfLogical () (getTransSpan $1 $5) $3 $5 }
DO_STATEMENT :: { Statement A0 }
: do LABEL_IN_STATEMENT DO_SPECIFICATION { StDo () (getTransSpan $1 $3) Nothing (Just $2) (Just $3) }
| do LABEL_IN_STATEMENT ',' DO_SPECIFICATION { StDo () (getTransSpan $1 $4) Nothing (Just $2) (Just $4) }
| do DO_SPECIFICATION { StDo () (getTransSpan $1 $2) Nothing Nothing (Just $2) }
| do { StDo () (getSpan $1) Nothing Nothing Nothing }
DO_SPECIFICATION :: { DoSpecification A0 }
: EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION ',' EXPRESSION { DoSpecification () (getTransSpan $1 $5) $1 $3 (Just $5) }
| EXPRESSION_ASSIGNMENT_STATEMENT ',' EXPRESSION { DoSpecification () (getTransSpan $1 $3) $1 $3 Nothing }
EXECUTABLE_STATEMENT :: { Statement A0 }
: EXPRESSION_ASSIGNMENT_STATEMENT { $1 }
| assign LABEL_IN_STATEMENT to VARIABLE { StLabelAssign () (getTransSpan $1 $4) $2 $4 }
| GOTO_STATEMENT { $1 }
| if '(' EXPRESSION ')' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT ',' LABEL_IN_STATEMENT { StIfArithmetic () (getTransSpan $1 $9) $3 $5 $7 $9 }
| doWhile '(' EXPRESSION ')'
{ StDoWhile () (getTransSpan $1 $4) Nothing Nothing $3 }
| do LABEL_IN_STATEMENT while '(' EXPRESSION ')'
{ StDoWhile () (getTransSpan $1 $6) Nothing (Just $2) $5 }
| do LABEL_IN_STATEMENT ',' while '(' EXPRESSION ')'
{ StDoWhile () (getTransSpan $1 $7) Nothing (Just $2) $6 }
| enddo { StEnddo () (getSpan $1) Nothing }
| call VARIABLE ARGUMENTS
{ StCall () (getTransSpan $1 $3) $2 $3 }
| call VARIABLE
{ StCall () (getTransSpan $1 $2) $2 (aEmpty () (emptySpan (ssTo (getSpan $2)))) }
-- ^ (!) empty list 0-span
| return { StReturn () (getSpan $1) Nothing }
| return EXPRESSION { StReturn () (getTransSpan $1 $2) $ Just $2 }
| save SAVE_ARGS { StSave () (getSpan ($1, $2)) $2 }
| continue { StContinue () $ getSpan $1 }
| stop INTEGER_OR_STRING { StStop () (getTransSpan $1 $2) $ Just $2 }
| stop { StStop () (getSpan $1) Nothing }
| exit { StExit () (getSpan $1) Nothing }
| cycle { StCycle () (getSpan $1) Nothing }
| pause INTEGER_OR_STRING { StPause () (getTransSpan $1 $2) $ Just $2 }
| pause { StPause () (getSpan $1) Nothing }
| selectcase '(' EXPRESSION ')'
{ StSelectCase () (getTransSpan $1 $4) Nothing $3 }
| casedefault { StCase () (getSpan $1) Nothing Nothing }
| casedefault id
{ let TId s id = $2 in StCase () (getTransSpan $1 s) (Just id) Nothing }
| case '(' INDICIES ')'
{ StCase () (getTransSpan $1 $4) Nothing (Just $ fromReverseList $3) }
| case '(' INDICIES ')' id
{ let TId s id = $5
in StCase () (getTransSpan $1 s) (Just id) (Just $ fromReverseList $3) }
| endselect { StEndcase () (getSpan $1) Nothing }
| endselect id
{ let TId s id = $2 in StEndcase () (getTransSpan $1 s) (Just id) }
-- IO Statements
| read CILIST IN_IOLIST { StRead () (getTransSpan $1 $3) $2 (Just $ aReverse $3) }
| read CILIST { StRead () (getTransSpan $1 $2) $2 Nothing }
| read FORMAT_ID ',' IN_IOLIST { StRead2 () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }
| read FORMAT_ID { StRead2 () (getTransSpan $1 $2) $2 Nothing }
| write CILIST OUT_IOLIST { StWrite () (getTransSpan $1 $3) $2 (Just $ aReverse $3) }
| write CILIST { StWrite () (getTransSpan $1 $2) $2 Nothing }
| print FORMAT_ID ',' OUT_IOLIST { StPrint () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }
| print FORMAT_ID { StPrint () (getTransSpan $1 $2) $2 Nothing }
| typeprint FORMAT_ID ',' OUT_IOLIST { StTypePrint () (getTransSpan $1 $4) $2 (Just $ aReverse $4) }
| typeprint FORMAT_ID { StTypePrint () (getTransSpan $1 $2) $2 Nothing }
| open CILIST { StOpen () (getTransSpan $1 $2) $2 }
| close CILIST { StClose () (getTransSpan $1 $2) $2 }
| inquire CILIST { StInquire () (getTransSpan $1 $2) $2 }
| rewind CILIST { StRewind () (getTransSpan $1 $2) $2 }
| rewind UNIT { StRewind2 () (getTransSpan $1 $2) $2 }
| endfile CILIST { StEndfile () (getTransSpan $1 $2) $2 }
| endfile UNIT { StEndfile2 () (getTransSpan $1 $2) $2 }
| backspace CILIST { StBackspace () (getTransSpan $1 $2) $2 }
| backspace UNIT { StBackspace2 () (getTransSpan $1 $2) $2 }
FORMAT_ID :: { Expression A0 }
: FORMAT_ID '/' '/' FORMAT_ID %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }
| INTEGER_LITERAL { $1 }
-- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,
-- hence putting it here would cause a reduce/reduce conflict.
| SUBSCRIPT { $1 }
| '*' { ExpValue () (getSpan $1) ValStar }
UNIT :: { Expression A0 }
: INTEGER_LITERAL { $1 }
| SUBSCRIPT { $1 }
| '*' { ExpValue () (getSpan $1) ValStar }
-- A crude approximation that makes parsing easy. Individual key value pairs
-- should be checket later on.
CILIST :: { AList ControlPair A0 }
: '(' UNIT ',' FORMAT_ID ',' CILIST_PAIRS ')' {
let { cp1 = ControlPair () (getSpan $2) Nothing $2;
cp2 = ControlPair () (getSpan $4) Nothing $4 }
in setSpan (getTransSpan $1 $7) $ cp1 `aCons` cp2 `aCons` aReverse $6
}
| '(' UNIT ',' FORMAT_ID ')' {
let { cp1 = ControlPair () (getSpan $2) Nothing $2;
cp2 = ControlPair () (getSpan $4) Nothing $4 }
in AList () (getTransSpan $1 $5) [ cp1, cp2 ]
}
| '(' UNIT ',' CILIST_PAIRS ')' {
let cp1 = ControlPair () (getSpan $2) Nothing $2
in setSpan (getTransSpan $1 $5) $ cp1 `aCons` aReverse $4
}
| '(' UNIT ')' {
let cp1 = ControlPair () (getSpan $2) Nothing $2
in AList () (getTransSpan $1 $3) [ cp1 ]
}
| '(' CILIST_PAIRS ')' { setSpan (getTransSpan $1 $3) $ aReverse $2 }
CILIST_PAIRS :: { AList ControlPair A0 }
: CILIST_PAIRS ',' CILIST_PAIR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| CILIST_PAIR { AList () (getSpan $1) [ $1 ] }
CILIST_PAIR :: { ControlPair A0 }
: id '=' CILIST_ELEMENT { let (TId s id) = $1 in ControlPair () (getTransSpan s $3) (Just id) $3 }
CILIST_ELEMENT :: { Expression A0 }
: CI_EXPRESSION { $1 }
| '*' { ExpValue () (getSpan $1) ValStar }
CI_EXPRESSION :: { Expression A0 }
: CI_EXPRESSION '+' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }
| CI_EXPRESSION '-' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }
| CI_EXPRESSION '*' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }
| CI_EXPRESSION '/' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }
| CI_EXPRESSION '**' CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }
| CI_EXPRESSION '/' '/' CI_EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }
| ARITHMETIC_SIGN CI_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }
| CI_EXPRESSION or CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }
| CI_EXPRESSION and CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }
| CI_EXPRESSION xor CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }
| not CI_EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }
| CI_EXPRESSION eqv CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }
| CI_EXPRESSION neqv CI_EXPRESSION { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }
| CI_EXPRESSION RELATIONAL_OPERATOR CI_EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }
| '(' CI_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }
| INTEGER_LITERAL { $1 }
| LOGICAL_LITERAL { $1 }
-- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,
-- hence putting it here would cause a reduce/reduce conflict.
| SUBSCRIPT { $1 }
-- Input IOList used in read like statements is much more restrictive as it
-- doesn't make sense to read into an integer.
-- While the output list can be an arbitrary expression. Hence, the grammar
-- rule separation.
IN_IOLIST :: { AList Expression A0 }
: IN_IOLIST ',' IN_IO_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}
| IN_IO_ELEMENT { AList () (getSpan $1) [ $1 ] }
IN_IO_ELEMENT :: { Expression A0 }
: SUBSCRIPT { $1 }
| '(' IN_IOLIST ',' DO_SPECIFICATION ')' { ExpImpliedDo () (getTransSpan $1 $5) (aReverse $2) $4 }
OUT_IOLIST :: { AList Expression A0 }
: OUT_IOLIST ',' EXPRESSION { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}
| EXPRESSION { AList () (getSpan $1) [ $1 ] }
SAVE_ARGS :: { Maybe (AList Expression A0) }
: SAVE_ARGS_LEVEL1 { Just $ fromReverseList $1 }
| {-EMPTY-} { Nothing }
SAVE_ARGS_LEVEL1 :: { [ Expression A0 ] }
: SAVE_ARGS_LEVEL1 ',' SAVE_ARG { $3 : $1 }
| SAVE_ARG { [ $1 ] }
SAVE_ARG :: { Expression A0 }
: COMMON_NAME { $1 } | VARIABLE { $1 }
INTEGER_OR_STRING :: { Expression A0 } : STRING { $1 } | INTEGER_LITERAL { $1 }
GOTO_STATEMENT :: { Statement A0 }
: goto LABEL_IN_STATEMENT { StGotoUnconditional () (getTransSpan $1 $2) $2 }
| goto VARIABLE { StGotoAssigned () (getTransSpan $1 $2) $2 Nothing }
| goto VARIABLE LABELS_IN_STATEMENT { StGotoAssigned () (getTransSpan $1 $3) $2 (Just $3) }
| goto VARIABLE ',' LABELS_IN_STATEMENT { StGotoAssigned () (getTransSpan $1 $4) $2 (Just $4) }
| goto LABELS_IN_STATEMENT EXPRESSION { StGotoComputed () (getTransSpan $1 $3) $2 $3 }
| goto LABELS_IN_STATEMENT ',' EXPRESSION { StGotoComputed () (getTransSpan $1 $4) $2 $4 }
EXPRESSION_ASSIGNMENT_STATEMENT :: { Statement A0 }
: ELEMENT '=' EXPRESSION { StExpressionAssign () (getTransSpan $1 $3) $1 $3 }
NONEXECUTABLE_STATEMENT :: { Statement A0 }
: external FUNCTION_NAMES { StExternal () (getTransSpan $1 $2) (aReverse $2) }
| intrinsic FUNCTION_NAMES { StIntrinsic () (getTransSpan $1 $2) (aReverse $2) }
| dimension INITIALIZED_ARRAY_DECLARATORS { StDimension () (getTransSpan $1 $2) (aReverse $2) }
| common COMMON_GROUPS { StCommon () (getTransSpan $1 $2) (aReverse $2) }
| equivalence EQUIVALENCE_GROUPS { StEquivalence () (getTransSpan $1 $2) (aReverse $2) }
| pointer POINTER_LIST { StPointer () (getTransSpan $1 $2) (fromReverseList $2) }
| data DATA_GROUPS { StData () (getTransSpan $1 $2) (fromReverseList $2) }
| automatic INITIALIZED_DECLARATORS { StAutomatic () (getTransSpan $1 $2) (aReverse $2) }
| static INITIALIZED_DECLARATORS { StStatic () (getTransSpan $1 $2) (aReverse $2) }
-- Following is a fake node to make arbitrary FORMAT statements parsable.
-- Must be fixed in the future. TODO
| format blob
{ let TBlob s blob = $2 in StFormatBogus () (getTransSpan $1 s) blob }
| DECLARATION_STATEMENT { $1 }
| implicit none { StImplicit () (getTransSpan $1 $2) Nothing }
| implicit IMP_LISTS { StImplicit () (getTransSpan $1 $2) $ Just $ aReverse $2 }
| parameter '(' PARAMETER_ASSIGNMENTS ')'
{ StParameter () (getTransSpan $1 $4) $ fromReverseList $3 }
| entry VARIABLE { StEntry () (getTransSpan $1 $2) $2 Nothing Nothing }
| entry VARIABLE ENTRY_ARGS { StEntry () (getTransSpan $1 $3) $2 (Just $3) Nothing }
| include STRING { StInclude () (getTransSpan $1 $2) $2 Nothing }
| structure MAYBE_NAME NEWLINE STRUCTURE_DECLARATIONS endstructure
{ StStructure () (getTransSpan $1 $5) $2 (fromReverseList $4) }
MAYBE_NAME :: { Maybe Name }
: '/' NAME '/' { Just $2 }
| {- empty -} { Nothing }
STRUCTURE_DECLARATIONS :: { [StructureItem A0] }
: STRUCTURE_DECLARATIONS STRUCTURE_DECLARATION_STATEMENT
{ if isNothing $2 then $1 else fromJust $2 : $1 }
| STRUCTURE_DECLARATION_STATEMENT { if isNothing $1 then [] else [fromJust $1] }
STRUCTURE_DECLARATION_STATEMENT :: { Maybe (StructureItem A0) }
: DECLARATION_STATEMENT NEWLINE
{ let StDeclaration () s t attrs decls = $1
in Just $ StructFields () s t attrs decls }
| union NEWLINE UNION_MAPS endunion NEWLINE
{ Just $ StructUnion () (getTransSpan $1 $5) (fromReverseList $3) }
| structure MAYBE_NAME NAME NEWLINE STRUCTURE_DECLARATIONS endstructure NEWLINE
{ Just $ StructStructure () (getTransSpan $1 $7) $2 $3 (fromReverseList $5) }
| comment NEWLINE { Nothing }
UNION_MAPS :: { [ UnionMap A0 ] }
: UNION_MAPS UNION_MAP { if isNothing $2 then $1 else fromJust $2 : $1 }
| UNION_MAP { if isNothing $1 then [] else [fromJust $1] }
UNION_MAP :: { Maybe (UnionMap A0) }
: map NEWLINE STRUCTURE_DECLARATIONS endmap NEWLINE
{ Just $ UnionMap () (getTransSpan $1 $5) (fromReverseList $3) }
| comment NEWLINE { Nothing }
ENTRY_ARGS :: { AList Expression A0 }
: ENTRY_ARGS_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }
ENTRY_ARGS_LEVEL1 :: { AList Expression A0 }
: ENTRY_ARGS_LEVEL1 ',' ENTRY_ARG { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| '(' ENTRY_ARG { AList () (getTransSpan $1 $2) [ $2 ] }
| '(' { AList () (getSpan $1) [ ] }
ENTRY_ARG :: { Expression A0 }
: VARIABLE { $1 }
| '*' { ExpValue () (getSpan $1) ValStar }
PARAMETER_ASSIGNMENTS :: { [ Declarator A0 ] }
: PARAMETER_ASSIGNMENTS ',' PARAMETER_ASSIGNMENT { $3 : $1 }
| PARAMETER_ASSIGNMENT { [ $1 ] }
PARAMETER_ASSIGNMENT :: { Declarator A0 }
: VARIABLE '=' CONSTANT_EXPRESSION
{ Declarator () (getTransSpan $1 $3) $1 ScalarDecl Nothing (Just $3) }
DECLARATION_STATEMENT :: { Statement A0 }
: TYPE_SPEC maybe(',') INITIALIZED_DECLARATORS
{ StDeclaration () (getTransSpan $1 $3) $1 Nothing (aReverse $3) }
IMP_LISTS :: { AList ImpList A0 }
: IMP_LISTS ',' IMP_LIST { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| IMP_LIST { AList () (getSpan $1) [ $1 ] }
IMP_LIST :: { ImpList A0 }
: IMP_TYPE_SPEC '(' IMP_ELEMENTS ')'
{ ImpList () (getTransSpan $1 $4) $1 $ aReverse $3 }
IMP_ELEMENTS :: { AList ImpElement A0 }
: IMP_ELEMENTS ',' IMP_ELEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| IMP_ELEMENT { AList () (getSpan $1) [ $1 ] }
IMP_ELEMENT :: { ImpElement A0 }
: id
{% let TId s id = $1
in case List.uncons id of
Just (c, "") -> return $ ImpElement () s c Nothing
_ -> fail "Implicit argument must be a character." }
| id '-' id
{% let { TId _ idFrom = $1;
TId _ idTo = $3;
s = getTransSpan $1 $3 }
in case List.uncons idFrom of
Just (cFrom, "") ->
case List.uncons idTo of
Just (cTo, "") -> return $ ImpElement () s cFrom (Just cTo)
_ -> fail "Implicit argument must be a character."
_ -> fail "Implicit argument must be a character." }
ELEMENT :: { Expression A0 }
: SUBSCRIPT { $1 }
DATA_GROUPS :: { [DataGroup A0] }
: DATA_GROUPS ',' DATA_GROUP { $3 : $1 }
| DATA_GROUPS DATA_GROUP { $2 : $1 }
| DATA_GROUP { [$1] }
DATA_GROUP :: { DataGroup A0 }
: DATA_NAMES '/' DATA_ITEMS '/' { DataGroup () (getTransSpan $1 $4) (aReverse $1) (aReverse $3) }
DATA_NAMES :: { AList Expression A0 }
: NAME_LIST { $1 }
| IMPLIED_DO { fromList () [ $1 ] }
DATA_ITEMS :: { AList Expression A0 }
: DATA_ITEMS ',' DATA_ITEM { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1}
| DATA_ITEM { AList () (getSpan $1) [ $1 ] }
DATA_ITEM :: { Expression A0 }
: INTEGER_CONSTANT '*' DATA_ITEM_LEVEL1 { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }
| DATA_ITEM_LEVEL1 { $1 }
DATA_ITEM_LEVEL1 :: { Expression A0 }
: SIGNED_NUMERIC_LITERAL { $1 }
-- | COMPLEX_LITERAL { $1 }
| VARIABLE { $1 }
| '(' SIGNED_NUMERIC_LITERAL ',' SIGNED_NUMERIC_LITERAL ')'
{% complexLit (getTransSpan $1 $5) $2 $4 }
| LOGICAL_LITERAL { $1 }
| STRING { $1 }
| HOLLERITH { $1 }
EQUIVALENCE_GROUPS :: { AList (AList Expression) A0 }
: EQUIVALENCE_GROUPS ',' '(' NAME_LIST ')' { setSpan (getTransSpan $1 $5) $ (setSpan (getTransSpan $3 $5) $ aReverse $4) `aCons` $1 }
| '(' NAME_LIST ')' { let s = (getTransSpan $1 $3) in AList () s [ setSpan s $ aReverse $2 ] }
POINTER_LIST :: { [ Declarator A0 ] }
: POINTER_LIST ',' POINTER { $3 : $1 }
| POINTER { [ $1 ] }
POINTER :: { Declarator A0 }
: '(' VARIABLE ',' VARIABLE ')'
{ Declarator () (getTransSpan $1 $5) $2 ScalarDecl Nothing (Just $4) }
COMMON_GROUPS :: { AList CommonGroup A0 }
: COMMON_GROUPS COMMON_GROUP { setSpan (getTransSpan $1 $2) $ $2 `aCons` $1 }
| INIT_COMMON_GROUP { AList () (getSpan $1) [ $1 ] }
COMMON_GROUP :: { CommonGroup A0 }
: COMMON_NAME UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }
| '/' '/' UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }
INIT_COMMON_GROUP :: { CommonGroup A0 }
: COMMON_NAME UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $2) (Just $1) $ aReverse $2 }
| '/' '/' UNINITIALIZED_DECLARATORS { CommonGroup () (getTransSpan $1 $3) Nothing $ aReverse $3 }
| UNINITIALIZED_DECLARATORS { CommonGroup () (getSpan $1) Nothing $ aReverse $1 }
COMMON_NAME :: { Expression A0 }
: '/' VARIABLE '/' { setSpan (getTransSpan $1 $3) $2 }
NAME_LIST :: { AList Expression A0 }
: NAME_LIST ',' ELEMENT
{ setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| ELEMENT { AList () (getSpan $1) [ $1 ] }
UNINITIALIZED_DECLARATORS :: { AList Declarator A0 }
: UNINITIALIZED_DECLARATORS ',' UNINITIALIZED_DECLARATOR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| UNINITIALIZED_DECLARATOR { AList () (getSpan $1) [ $1 ] }
UNINITIALIZED_DECLARATOR :: { Declarator A0 }
: UNINITIALIZED_ARRAY_DECLARATOR { $1 }
| UNINITIALIZED_VARIABLE_DECLARATOR { $1 }
UNINITIALIZED_ARRAY_DECLARATOR :: { Declarator A0 }
: VARIABLE '(' DIMENSION_DECLARATORS ')'
{ Declarator () (getTransSpan $1 $4) $1 (ArrayDecl (aReverse $3)) Nothing Nothing }
| VARIABLE '*' SIMPLE_EXPRESSION '(' DIMENSION_DECLARATORS ')'
{ Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $5)) (Just $3) Nothing }
| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' SIMPLE_EXPRESSION
{ Declarator () (getTransSpan $1 $6) $1 (ArrayDecl (aReverse $3)) (Just $6) Nothing }
UNINITIALIZED_VARIABLE_DECLARATOR :: { Declarator A0 }
: VARIABLE
{ Declarator () (getSpan $1) $1 ScalarDecl Nothing Nothing }
| VARIABLE '*' SIMPLE_EXPRESSION
{ Declarator () (getTransSpan $1 $3) $1 ScalarDecl (Just $3) Nothing }
INITIALIZED_DECLARATORS :: { AList Declarator A0 }
: INITIALIZED_DECLARATORS ',' INITIALIZED_DECLARATOR { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| INITIALIZED_DECLARATOR { AList () (getSpan $1) [ $1 ] }
INITIALIZED_DECLARATOR :: { Declarator A0 }
: INITIALIZED_ARRAY_DECLARATOR { $1 }
| INITIALIZED_VARIABLE_DECLARATOR { $1 }
INITIALIZED_ARRAY_DECLARATORS :: { AList Declarator A0 }
: INITIALIZED_ARRAY_DECLARATORS ',' INITIALIZED_ARRAY_DECLARATOR
{ setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| INITIALIZED_ARRAY_DECLARATOR { AList () (getSpan $1) [ $1 ] }
INITIALIZED_ARRAY_DECLARATOR :: { Declarator A0 }
: UNINITIALIZED_ARRAY_DECLARATOR { $1 }
| VARIABLE '(' DIMENSION_DECLARATORS ')' '/' SIMPLE_EXPRESSION_LIST '/'
{ Declarator () (getTransSpan $1 $7) $1 (ArrayDecl (aReverse $3)) Nothing
(Just (ExpInitialisation () (getSpan $6) (fromReverseList $6))) }
| VARIABLE '*' SIMPLE_EXPRESSION '(' DIMENSION_DECLARATORS ')' '/' SIMPLE_EXPRESSION_LIST '/'
{ Declarator () (getTransSpan $1 $9) $1 (ArrayDecl (aReverse $5)) (Just $3)
(Just (ExpInitialisation () (getSpan $8) (fromReverseList $8))) }
| VARIABLE '(' DIMENSION_DECLARATORS ')' '*' SIMPLE_EXPRESSION '/' SIMPLE_EXPRESSION_LIST '/'
{ Declarator () (getTransSpan $1 $9) $1 (ArrayDecl (aReverse $3)) (Just $6)
(Just (ExpInitialisation () (getSpan $8) (fromReverseList $8))) }
INITIALIZED_VARIABLE_DECLARATOR :: { Declarator A0 }
: UNINITIALIZED_VARIABLE_DECLARATOR { $1 }
| VARIABLE '/' SIMPLE_EXPRESSION '/'
{ Declarator () (getTransSpan $1 $4) $1 ScalarDecl Nothing (Just $3) }
| VARIABLE '*' SIMPLE_EXPRESSION '/' SIMPLE_EXPRESSION '/'
{ Declarator () (getTransSpan $1 $6) $1 ScalarDecl (Just $3) (Just $5) }
SIMPLE_EXPRESSION_LIST :: { [Expression A0] }
: SIMPLE_EXPRESSION_LIST ',' SIMPLE_EXPRESSION { $3 : $1 }
| SIMPLE_EXPRESSION { [ $1 ] }
SIMPLE_EXPRESSION :: { Expression A0 }
: INTEGER_CONSTANT '*' CONSTANT { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }
| CONSTANT { $1 }
| '(' '*' ')' { ExpValue () (getTransSpan $1 $3) ValStar }
| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }
CONSTANT :: { Expression A0 }
: VARIABLE { $1 }
| SIGNED_NUMERIC_LITERAL { $1 }
| LOGICAL_LITERAL { $1 }
| STRING { $1 }
| HOLLERITH { $1 }
INTEGER_CONSTANT :: { Expression A0 }
: VARIABLE { $1 }
| SIGNED_NUMERIC_LITERAL { $1 }
DIMENSION_DECLARATORS :: { AList DimensionDeclarator A0 }
: DIMENSION_DECLARATORS ',' DIMENSION_DECLARATOR
{ setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| DIMENSION_DECLARATOR { AList () (getSpan $1) [ $1 ] }
DIMENSION_DECLARATOR :: { DimensionDeclarator A0 }
: EXPRESSION ':' EXPRESSION { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $3) }
| EXPRESSION { DimensionDeclarator () (getSpan $1) Nothing (Just $1) }
| EXPRESSION ':' '*' { DimensionDeclarator () (getTransSpan $1 $3) (Just $1) (Just $ ExpValue () (getSpan $3) ValStar) }
| '*' { DimensionDeclarator () (getSpan $1) Nothing (Just $ ExpValue () (getSpan $1) ValStar) }
-- Here the procedure should be either a function or subroutine name, but
-- since they are syntactically identical at this stage subroutine names
-- are also emitted as function names.
FUNCTION_NAMES :: { AList Expression A0 }
: FUNCTION_NAMES ',' VARIABLE { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| VARIABLE { AList () (getSpan $1) [ $1 ] }
ARGUMENTS :: { AList Argument A0 }
: ARGUMENTS_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }
ARGUMENTS_LEVEL1 :: { AList Argument A0 }
: ARGUMENTS_LEVEL1 ',' CALLABLE_EXPRESSION { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| '(' CALLABLE_EXPRESSION { AList () (getTransSpan $1 $2) [ $2 ] }
| '(' { AList () (getSpan $1) [ ] }
-- Expression all by itself subsumes all other callable expressions.
CALLABLE_EXPRESSION :: { Argument A0 }
-- Explicitly parse special intrinsics for argument passing types
: '%' id '(' EXPRESSION ')'
{ let { args = AList () (getSpan $4) $ [Argument () (getSpan $4) Nothing (ArgExpr $4)];
TId _ name = $2;
intr = ExpFunctionCall () (getTransSpan $1 $5)
(ExpValue () (getTransSpan $1 $2) (ValIntrinsic ('%':name)))
args }
in Argument () (getTransSpan $1 $5) Nothing (ArgExpr intr) }
| id '=' EXPRESSION
{ let TId span keyword = $1
in Argument () (getTransSpan span $3) (Just keyword) (ArgExpr $3) }
| '(' VARIABLE ')'
{ let ExpValue _ _ (ValVariable v) = $2
in Argument () (getTransSpan $1 $3) Nothing (ArgExprVar () (getSpan $2) v) }
| EXPRESSION { Argument () (getSpan $1) Nothing (ArgExpr $1) }
EXPRESSION :: { Expression A0 }
: EXPRESSION '+' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }
| EXPRESSION '-' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }
| EXPRESSION '*' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }
| EXPRESSION '/' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }
| EXPRESSION '**' EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }
| EXPRESSION '/' '/' EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }
| ARITHMETIC_SIGN EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }
| EXPRESSION or EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }
| EXPRESSION xor EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }
| EXPRESSION and EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }
| not EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }
| EXPRESSION eqv EXPRESSION { ExpBinary () (getTransSpan $1 $3) Equivalent $1 $3 }
| EXPRESSION neqv EXPRESSION { ExpBinary () (getTransSpan $1 $3) NotEquivalent $1 $3 }
| EXPRESSION RELATIONAL_OPERATOR EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }
| '(' EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }
| NUMERIC_LITERAL { $1 }
| '(' EXPRESSION ',' EXPRESSION ')' {% complexLit (getTransSpan $1 $5) $2 $4 }
| LOGICAL_LITERAL { $1 }
| HOLLERITH { $1 }
-- There should be FUNCTION_CALL here but as far as the parser is concerned it is same as SUBSCRIPT,
-- hence putting it here would cause a reduce/reduce conflict.
| SUBSCRIPT { $1 }
| IMPLIED_DO { $1 }
| '(/' EXPRESSION_LIST '/)' {
let { exps = reverse $2;
expList = AList () (getSpan exps) exps }
in ExpInitialisation () (getTransSpan $1 $3) expList
}
| '*' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }
| '&' INTEGER_LITERAL { ExpReturnSpec () (getTransSpan $1 $2) $2 }
IMPLIED_DO :: { Expression A0 }
: '(' EXPRESSION ',' DO_SPECIFICATION ')' {
let expList = AList () (getSpan $2) [ $2 ]
in ExpImpliedDo () (getTransSpan $1 $5) expList $4
}
| '(' EXPRESSION ',' EXPRESSION ',' DO_SPECIFICATION ')' {
let expList = AList () (getTransSpan $2 $4) [ $2, $4 ]
in ExpImpliedDo () (getTransSpan $1 $7) expList $6
}
| '(' EXPRESSION ',' EXPRESSION ',' EXPRESSION_LIST ',' DO_SPECIFICATION ')' {
let { exps = reverse $6;
expList = AList () (getTransSpan $2 exps) ($2 : $4 : reverse $6) }
in ExpImpliedDo () (getTransSpan $1 $9) expList $8
}
EXPRESSION_LIST :: { [ Expression A0 ] }
: EXPRESSION_LIST ',' EXPRESSION { $3 : $1 }
| EXPRESSION { [ $1 ] }
STRING :: { Expression A0 } : string { let (TString s cs) = $1 in ExpValue () s (ValString cs) }
CONSTANT_EXPRESSION :: { Expression A0 }
: CONSTANT_EXPRESSION '+' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }
| CONSTANT_EXPRESSION '-' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }
| CONSTANT_EXPRESSION '*' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }
| CONSTANT_EXPRESSION '/' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }
| CONSTANT_EXPRESSION '**' CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }
| CONSTANT_EXPRESSION '/' '/' CONSTANT_EXPRESSION %prec CONCAT { ExpBinary () (getTransSpan $1 $4) Concatenation $1 $4 }
| ARITHMETIC_SIGN CONSTANT_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }
| CONSTANT_EXPRESSION or CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Or $1 $3 }
| CONSTANT_EXPRESSION xor CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) XOr $1 $3 }
| CONSTANT_EXPRESSION and CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) And $1 $3 }
| not CONSTANT_EXPRESSION { ExpUnary () (getTransSpan $1 $2) Not $2 }
| CONSTANT_EXPRESSION RELATIONAL_OPERATOR CONSTANT_EXPRESSION %prec RELATIONAL { ExpBinary () (getTransSpan $1 $3) $2 $1 $3 }
| '(' CONSTANT_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }
| NUMERIC_LITERAL { $1 }
| '(' CONSTANT_EXPRESSION ',' CONSTANT_EXPRESSION ')'
{% complexLit (getTransSpan $1 $5) $2 $4 }
| LOGICAL_LITERAL { $1 }
| SUBSCRIPT { $1 }
| HOLLERITH { $1 }
| '(/' EXPRESSION_LIST '/)' {
let { exps = reverse $2;
expList = AList () (getSpan exps) exps }
in ExpInitialisation () (getTransSpan $1 $3) expList
}
ARITHMETIC_CONSTANT_EXPRESSION :: { Expression A0 }
: ARITHMETIC_CONSTANT_EXPRESSION '+' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Addition $1 $3 }
| ARITHMETIC_CONSTANT_EXPRESSION '-' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Subtraction $1 $3 }
| ARITHMETIC_CONSTANT_EXPRESSION '*' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Multiplication $1 $3 }
| ARITHMETIC_CONSTANT_EXPRESSION '/' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Division $1 $3 }
| ARITHMETIC_CONSTANT_EXPRESSION '**' ARITHMETIC_CONSTANT_EXPRESSION { ExpBinary () (getTransSpan $1 $3) Exponentiation $1 $3 }
| ARITHMETIC_SIGN ARITHMETIC_CONSTANT_EXPRESSION %prec NEGATION { ExpUnary () (getTransSpan (fst $1) $2) (snd $1) $2 }
| '(' ARITHMETIC_CONSTANT_EXPRESSION ')' { setSpan (getTransSpan $1 $3) $2 }
| NUMERIC_LITERAL { $1 }
| '(' ARITHMETIC_CONSTANT_EXPRESSION ',' ARITHMETIC_CONSTANT_EXPRESSION ')'
{% complexLit (getTransSpan $1 $5) $2 $4 }
| VARIABLE { $1 }
| SUBSCRIPT { $1 }
RELATIONAL_OPERATOR :: { BinaryOp }
: '==' { EQ }
| '!=' { NE }
| '>' { GT }
| '>=' { GTE }
| '<' { LT }
| '<=' { LTE }
SUBSCRIPT :: { Expression A0 }
: SUBSCRIPT '.' VARIABLE
{ ExpDataRef () (getTransSpan $1 $3) $1 $3 }
| SUBSCRIPT '%' VARIABLE
{ ExpDataRef () (getTransSpan $1 $3) $1 $3 }
| SUBSCRIPT '(' ')'
{ ExpFunctionCall () (getTransSpan $1 $3) $1 (aEmpty () (getTransSpan $2 $3)) }
-- ^ (!) empty list spans brackets
| SUBSCRIPT '(' INDICIES ')'
{ ExpSubscript () (getTransSpan $1 $4) $1 (fromReverseList $3) }
| VARIABLE { $1 }
| STRING { $1 }
INDICIES :: { [ Index A0 ] }
: INDICIES ',' INDEX { $3 : $1 }
| INDEX { [ $1 ] }
INDEX :: { Index A0 }
: RANGE { $1 }
| EXPRESSION { IxSingle () (getSpan $1) Nothing $1 }
RANGE :: { Index A0 }
: ':' { IxRange () (getSpan $1) Nothing Nothing Nothing }
| ':' EXPRESSION { IxRange () (getTransSpan $1 $2) Nothing (Just $2) Nothing }
| EXPRESSION ':' { IxRange () (getTransSpan $1 $2) (Just $1) Nothing Nothing }
| EXPRESSION ':' EXPRESSION
{ IxRange () (getTransSpan $1 $3) (Just $1) (Just $3) Nothing }
ARITHMETIC_SIGN :: { (SrcSpan, UnaryOp) }
: '-' { (getSpan $1, Minus) }
| '+' { (getSpan $1, Plus) }
MAYBE_VARIABLES :: { Maybe (AList Expression A0) }
: VARIABLES { Just $ fromReverseList $1 } | {- EMPTY -} { Nothing }
VARIABLES :: { [ Expression A0 ] }
: VARIABLES ',' VARIABLE_OR_STAR { $3 : $1 }
| VARIABLE_OR_STAR { [ $1 ] }
VARIABLE_OR_STAR :: { Expression A0 }
: VARIABLE { $1 }
| '*' { ExpValue () (getSpan $1) ValStar }
| '&' { ExpValue () (getSpan $1) ValStar }
-- This may also be used to parse a function name, or an array name. Since when
-- are valid options in a production there is no way of differentiating them at
-- this stage.
-- This at least reduces reduce/reduce conflicts.
VARIABLE :: { Expression A0 }
: id { ExpValue () (getSpan $1) $ let (TId _ s) = $1 in ValVariable s }
INTEGER_LITERAL :: { Expression A0 }
: int { ExpValue () (getSpan $1) $ let (TInt _ i) = $1 in ValInteger i Nothing}
| boz { let TBozLiteral s b = $1 in ExpValue () s $ ValBoz b }
REAL_LITERAL :: { Expression A0 }
: int EXPONENT { makeRealLit (Just $1) Nothing Nothing (Just $2) }
| int '.' MAYBE_EXPONENT { makeRealLit (Just $1) (Just $2) Nothing $3 }
| '.' int MAYBE_EXPONENT { makeRealLit Nothing (Just $1) (Just $2) $3 }
| int '.' int MAYBE_EXPONENT { makeRealLit (Just $1) (Just $2) (Just $3) $4 }
MAYBE_EXPONENT :: { Maybe (SrcSpan, String) }
: EXPONENT { Just $1 }
| {-EMPTY-} { Nothing }
EXPONENT :: { (SrcSpan, String) }
: exponent { let (TExponent s exp) = $1 in (s, exp) }
SIGNED_NUMERIC_LITERAL :: { Expression A0 }
: ARITHMETIC_SIGN NUMERIC_LITERAL { ExpUnary () (getTransSpan (fst $1) $2) Minus $2 }
| NUMERIC_LITERAL { $1 }
NUMERIC_LITERAL :: { Expression A0 }
: INTEGER_LITERAL { $1 }
| REAL_LITERAL { $1 }
LOGICAL_LITERAL :: { Expression A0 }
: bool { let TBool s b = $1 in ExpValue () s $ ValLogical b Nothing }
HOLLERITH :: { Expression A0 } : hollerith { ExpValue () (getSpan $1) $ let (THollerith _ h) = $1 in ValHollerith h }
LABELS_IN_STATEMENT :: { AList Expression A0 }
: LABELS_IN_STATEMENT_LEVEL1 ')' { setSpan (getTransSpan $1 $2) $ aReverse $1 }
LABELS_IN_STATEMENT_LEVEL1 :: { AList Expression A0 }
: LABELS_IN_STATEMENT_LEVEL1 ',' LABEL_IN_STATEMENT { setSpan (getTransSpan $1 $3) $ $3 `aCons` $1 }
| '(' LABEL_IN_STATEMENT { AList () (getTransSpan $1 $2) [ $2 ] }
-- Labels that occur in the first 6 columns
LABEL_IN_6COLUMN :: { Expression A0 } : label { ExpValue () (getSpan $1) (let (TLabel _ l) = $1 in ValInteger l Nothing) }
-- Labels that occur in statements
LABEL_IN_STATEMENT :: { Expression A0 } : int { ExpValue () (getSpan $1) (let (TInt _ l) = $1 in ValInteger l Nothing) }
TYPE_SPEC :: { TypeSpec A0 }
: integer KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeInteger $2 }
| real KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeReal $2 }
| doublePrecision { TypeSpec () (getSpan $1) TypeDoublePrecision Nothing}
| logical KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeLogical $2 }
| complex KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeComplex $2 }
| doubleComplex { TypeSpec () (getSpan $1) TypeDoubleComplex Nothing}
| character CHAR_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeCharacter $2 }
| byte KIND_SELECTOR { TypeSpec () (getSpan ($1, $2)) TypeByte $2 }
| record '/' NAME '/' { TypeSpec () (getSpan ($1, $4)) (TypeCustom $3) Nothing }
KIND_SELECTOR :: { Maybe (Selector A0) }
: KIND_SELECTOR1 { Just $1 }
| {- EMPTY -} { Nothing }
KIND_SELECTOR1 :: { Selector A0 }
: '*' ARITHMETIC_CONSTANT_EXPRESSION
{ Selector () (getTransSpan $1 $2) Nothing (Just $2) }
| '*' '(' STAR ')' { Selector () (getTransSpan $1 $4) Nothing (Just $3) }
CHAR_SELECTOR :: { Maybe (Selector A0) }
: CHAR_SELECTOR1 { Just $1 }
| {- EMPTY -} { Nothing }
CHAR_SELECTOR1 :: { Selector A0 }
: '*' ARITHMETIC_CONSTANT_EXPRESSION
{ Selector () (getTransSpan $1 $2) (Just $2) Nothing }
| '*' '(' STAR ')'
{ Selector () (getTransSpan $1 $4) (Just $3) Nothing }
IMP_TYPE_SPEC :: { TypeSpec A0 }
: TYPE_SPEC { $1 }
STAR :: { Expression A0 }
STAR : '*' { ExpValue () (getSpan $1) ValStar }