【编译原理】TOP50计算机编程语言分析总结——Fortran

实验2:TOP50计算机编程语言分析总结——Fortran

一、实验目的

1:深入了解Fortran编程语言,理解其语言特性和应用领域。

2:掌握词法分析的原理,了解如何将源代码中的字符序列转换为token序列。

3:掌握语法分析的原理,学会根据语言的语法规则分析记号序列并生成语法树。

4:理解从源代码到可执行程序的编译过程,深入理解计算机程序的执行机制。

5:比较不同编程语言的特点,了解不同编程语言在设计理念、语言特性、应用场景等方面的异同。

二、实验要求

1:描述Fortran语言的总体特点。

2:完成Fortran语言的词法分析研究。

3:完成Fortran语言的语法分析研究。

4:完成Fortran语言的实际编译过程研究。

5:完成Fortran语言的编程案例,实现至少3个小程序,例如堆排序算法、鸡兔同笼问题等。

6:比较Fortran语言和C语言。

三、实验步骤

1:背景研究。

在维基百科上查询Fortran语言,阅读其发展背景、历史和特性等方面的信息。

2:编译程序研究。

典型的编译程序的7个逻辑部分,如下图所示。按照该流程进行词法分析和语法分析。

3:编写案例程序。

设计3个小程序,在Fortran语言和C语言下进行程序的编写,并对比两种语言的特性。

四、实验内容/结果

【1:总体特点】

Fortran语言全称为Formula Translation,是通用的编译型指令式编程语言,其编译器是计算机科学史上出现的第一个编译器。最初,Fortran由IBM在1950年代开发,最新版本为Fortran 2018。

在编程范型方面,Fortran语言采用多重范型,包括指令式、过程式、结构化、面向对象、阵列式、泛型。其类型系统为强类型、静态,文件扩展名为.f、.for或.f90。

在实际应用方面,Fortran编译器支持多种操作系统,如Windows、Linux和macOS,具有良好的跨平台兼容性。Fortran语言包括强大的数组和矩阵操作能力、模块化的程序结构、强类型系统、丰富的内建函数和库支持,特别适用于数值计算和科学技术。应用领域主要包括:数值天气预报、有限元分析、计算流体力学、地球物理学、计算物理学、晶体学和计算化学。

【2:词法分析】

词法分析器的任务是将输入的字符流string转换为记号流tokens,即识别和分类源代码中的字符序列为有效的词法单元。

  • 词法单元的定义

Fortran语言中的词法单元主要可以分为关键字、标识符、常数、运算符、分隔符。

  1. 关键字:是预定义的单词,具有特定的语义。例如PROGRAM, FUNCTION, SUBROUTINE, IF, THEN, ELSE, ENDIF, DO, WHILE, CONTINUE, STOP, RETURN等。
  2. 标识符:用于变量名、函数名等。通常由字母开始,后接字母、数字或下划线。具体的正则表达式为[A-Za-z][A-Za-z0-9_]*
  3. 常数:包括整数、浮点数、复数、逻辑值和字符串等。例如,整数表示为整数表示为[0-9]+,浮点数表示为[0-9]+\.[0-9]*([Ee][+-]?[0-9]+)?,字符串表示为"([^"]*)"
  4. 运算符:算术运算符(例如+、-、*、/),关系运算符(例如==、/=、<、>),逻辑运算符(例如.AND.、.OR.)等。
  5. 分隔符:用于分隔语句和表达式的各个部分,例如括号、逗号和分号等。
  6. 注释:注释从感叹号!开始,延续到行尾。其正则表达式为![^\n]*
  • 词法分析过程

    Fortran语言中的词法分析的基本步骤通常包括字符读取、词法单元识别、空白处理、注释处理。

  1. 字符读取:从源代码中读取字符。
  2. 词法单元识别:根据字符组合的模式识别词法单元。例如,连续字母组合可能是关键字或标识符,数字序列可能是整数或浮点数。
  3. 空白处理:忽略空白字符,例如不包含在字符串常量内的空格、制表符和换行符。
  4. 注释处理:识别并忽略注释。Fortran中的注释通常以 ! 开始,持续到行末。
  • 有限自动机的设计

有限自动机可以识别正规文法所定义的语言和正规式所表示的集合。在自动机中,每种词法单元都需要一个明确的状态转换过程。

以下根据Fortran 95的词法规则,利用C++语言构造了一个简易的词法分析器,包含1个lex.h文件、1个lex.cpp文件和1个main.cpp文件。文件中的代码,如第七部分的表所示。

在运行之前,需要将3个文件放在同一个文件夹中,可在根目录下打开cmd窗口,输入命令【g++ -o lex main.cpp lex.cpp】,即可生成1个lex.exe可执行文件。然后,继续在终端输入命令【lex.exe input.txt】,即可得到词法分析的结果。其中,input.txt文件是用户自己创建的含有符合Fortran语法代码的文本文件。

此处构建一个整型四则运算的代码,测试的input.txt文件内容如下图所示。

运行词法分析器后的结果,如下图所示。从结果可以发现,在txt文件中共包含8行代码,记号共有22个,标识符共有4个,整型数字共有3个。

在lex文件中,getNextToken函数通过一个switch-case语言完成了字符识别过程的状态转换。这个自动状态机包含的状态如下:START、INID、INSTRING、ININT、INREAL、INCOMMENT。同时,自动状态机还包含根据输入字符从一个状态转移到另一个状态的逻辑。

自动机中每个状态的转换流程如下:

【START】

  1. 如果是空格或特定的控制字符,则保持在 START 状态。
  2. 遇到字母时,转移到 INID。
  3. 遇到数字时,转移到 ININT。
  4. 遇到引号 (' 或 "),转移到INSTRING。
  5. 遇到 '!',转移到 INCOMMENT。
  6. 根据特定字符,决定输出相应的Token或转移到其他状态。
  7. 其他情况通常转移到ERR状态。

【INID】

  1. 如果接收到字母、数字或下划线,保持在INID。
  2. 否则,返回到START并生成IDENT或keyword的Token。

【ININT】

  1. 如果继续接收到数字,保持在ININT。
  2. 遇到 '.' 转移到INREAL。
  3. 否则返回到START并生成ICONST Token。

【INREAL】

  1. 继续接收数字或 '.',检查是否构成有效的浮点数。
  2. 如果是有效的浮点数,返回RCONST Token。
  3. 如果不是,返回到START并可能返回ERR或DOT Token。

【INSTRING】

  1. 接收到与开始引号相同的引号时,返回到START并生成SCONST Token。
  2. 如果遇到非法结束,返回ERR。

【INCOMMENT】

  1. 忽略所有直到遇到换行符,然后返回到START。

【3:语法分析】

语法分析器的任务是将输入的记号流tokens根据语法规则转换为抽象语法树AST,即确定程序的结构并验证代码的语法正确性。

  • 语法分析的基本概念

    语法分析主要通过两种技术实现:自顶向下解析和自底向上解析。自顶向下解析方法是指,从根节点开始,按照语法规则尝试将输入tokens拼装成高层的语法结构。自底向上解析是指,从输入tokens开始,尝试将它们组合成更复杂的语法结构,直到构建出整个程序的语法树。

  • 语法分析方法

在编译原理中,常用的语法分析方法分为递归下降分析、LL分析和LR分析。

递归下降分析方法通过为每个非终结符编写一个函数,这些函数递归地调用彼此以匹配输入的tokens和文法的产生式。

LL分析方法从左到右读取输入,并进行最左推导,通常需要构造一个预测分析表来决定对于给定的输入和当前的非终结符应用哪条规则。

LR分析方法从左到右读取输入并进行最右推导的逆过程,通常需要较为复杂的生成工具来构建分析表。

  • Fortran语言的主要语法元素

Fortran语言的主要语法元素包括:程序结构、数据声明、控制结构、输入输出、过程调用。

  1. 程序结构:Fortran程序由一个或多个程序单元组成,包括主程序、模块、子程序和函数。
  2. 数据声明:变量和数组的声明,包括类型(如 INTEGER, REAL, COMPLEX 等)和维度。
  3. 控制结构:包括条件语句(如 IF, SELECT CASE)和循环结构(如 DO, DO WHILE)。
  4. 输入输出:使用 READ, WRITE, PRINT 等语句进行数据的输入输出。
  5. 过程调用:调用内部或外部定义的子程序和函数。
  • Fortran的上下文无关文法及其产生式规则

上下文无关文法用于定义编程语言的语法结构。在上下文无关文法中,产生式用来表示一个符号(非终结符)如何被其他符号(终结符和/或非终结符)替代。在Fortran语言中,每个产生式定义了Fortran语言的一个语法结构。具体的产生式规则内容,如第八部分所示。

此处以第1条产生式规则为例进行解释,其内容如下图所示。

R201规则说明一个可执行程序可以由一个程序单元(xProgramUnit)构成,或者由另一个可执行程序后接一个程序单元构成。这实质上表明可执行程序可以包含一个或多个程序单元。

R202规则定义了程序单元的不同可能形式。程序单元可以是主程序(xMainProgram)、函数子程序(xFunctionSubprogram)、子程序(xSubroutineSubprogram)、或者数据块子程序(xBlockDataSubprogram)。

  • Fortran的通用等价类

在上下文无关文法中中使用的许多符号表示语义等同的短语。有些是为了使标准散文更清晰,有些则是为了避免歧义。一旦建立抽象语法树,就没有理由再将它们区分开来,因此需要用等价类中的一个成员来代替该类中的所有符号。

Fortran 77和Fortran 90共同的通用等价类,以及Fortran 90特有的通用等价类,如下表所示。

Fortran 77和Fortran 90共同的通用等价类

xProgramUnit ::=

       xMainProgram xSubroutineSubprogram xFunctionSubprogram

       xBlockDataSubprogram.

xSubprogramRange ::=

       xFunctionRange xSubroutineRange .

xComblock ::=

       xSavedCommonBlock .

xFormalParameter ::=

       xFunctionPar xSubroutinePar.

xFormatIdentifier ::=

       xRdFmtId.

xFormalParameterList ::=

       xFunctionParList xFunctionPars xSubroutineParList xSubroutinePars.

xBody ::=

       xConditionalBody xBlockDataBody .

xBodyConstruct ::=

       xSpecificationPartConstruct xDeclarationConstruct

       xExecutionPartConstruct xExecutableConstruct

       xBlockDataBodyConstruct .

xLoopControl ::=

       xCommaLoopControl.

xCharSelector ::=

       xLengthSelector.

xArg ::=

       xSubroutineArg .

xArgList ::=

       xSubroutineArgList .

xExpr ::=

       xPrimary xLevel1Expr xLevel2Expr xLevel3Expr xLevel4Expr xLevel5Expr

       xFunctionReference

       xAddOperand xMultOperand xEquivOperand xOrOperand xAndOperand

       xSFPrimary xSFTerm xSFFactor xSFExpr

       xUFPrimary xUFExpr xUFTerm xUFFactor

       xCPrimary xCExpr xCOperand

       xRdFmtIdExpr xCommaExp .

xExprList ::=

       xSFExprList .

xStmt ::=

       xSpecificationStmt xActionStmt

       xImplicitStmt

       xIfThenStmt xElseIfStmt xElseStmt

       xParameterStmt xFormatStmt xEntryStmt xTypeDeclarationStmt

       xCommonStmt xDataStmt xDimensionStmt

       xEquivalenceStmt xExternalStmt xIntrinsicStmt xSaveStmt

       xArithmeticIfStmt

       xAssignmentStmt xAssignStmt xBackspaceStmt xCallStmt xCloseStmt

       xContinueStmt xEndfileStmt xGotoStmt xComputedGotoStmt

       xAssignedGotoStmt xIfStmt xInquireStmt xOpenStmt xPauseStmt

       xPrintStmt xReadStmt xReturnStmt xRewindStmt xStmtFunctionStmt

       xStopStmt xWriteStmt xLabelDoStmt .

xBinOp ::=

       xConcatOp xPowerOp xMultOp xAddOp xRelOp xAndOp xOrOp xEquivOp.

xUnOp ::=

       xNotOp xSign .

xVariableName ::=

       xVariableComma .

xIoControlSpec ::=

       xCloseSpec xRdCtlSpec xConnectSpec xInquireSpec xPositionSpec .

xIoControlSpecList ::=

       xCloseSpecList xRdIoCtlSpecList xPositionSpecList xConnectSpecList

       xInquireSpecList .

xArraySpec ::=

       xExplicitShapeSpecList xAssumedSizeSpec.

xDataStmtObject ::=

       xDataIDoObject.

xOutputItemList ::=

       xOutputItemList1 .

xFmtSpec ::=

       xFormatedit xFormatsep xEditElement.

Fortran 90特有的通用等价类

xProgramUnit ::=
       xModule xModuleSubprogram .
 
xHeader ::=
  xModuleStmt
  .
 
xBody ::=
       xBlockDoConstruct xModuleBody xSubprogramInterfaceBody
       xInterfaceBody xInterfaceBlockBody xCaseConstruct
       xSelectCaseBody xWhere xWhereConstruct xElseWhere
       xBodyPlusInternals .
 
xLine ::=
  xEndModuleStmt
  .
 
xSubprogramRange ::=
  xFunctionInterfaceRange xSubroutineInterfaceRange .
 
xArg ::=
       xFunctionArg .
 
xArgList ::=
       xFunctionArgList .
 
xExpr ::=
       xArrayConstructor xTarget xMaskExpr .
 
xPointerObject ::=
       xPointerField.
 
xAcValueList ::=
       xAcValueList1.
 
xStmt ::=
       xUseStmt
       xDerivedTypeDef xModuleSubprogramPartConstruct xContainsStmt
       xAccessStmt xAllocatableStmt
       xIntentStmt xNamelistStmt xOptionalStmt xPointerStmt xTargetStmt
       xEndDoStmt
       xAllocateStmt xCycleStmt xDeallocateStmt xExitStmt
       xNullifyStmt xPointerAssignmentStmt
       xWhereStmt xElsewhereStmt xWhereConstructStmt
       xCaseStmt xCaseBodyConstruct
       xDerivedTypeBodyConstruct
       xPrivateSequenceStmt xComponentDefStmt
       xInterfaceBodyPartConstruct xModuleProcedureStmt.
 
xArraySpec ::=
       xComponentArraySpec xExplicitShapeSpecList xDeferredShapeSpecList
       xAssumedShapeSpecList xAssumedSizeSpec.
  • Fortran语言的递归下降分析示例

假设有以下Fortran程序,这个程序做了以下事情:①声明三个整数变量 a, b, 和 c。②输出一行提示用户输入两个数字。③从标准输入读取两个整数到变量 a 和 b。④计算 a 和 b 的和,并将结果存储在 c 中。⑤输出计算结果。

program example

  integer :: a, b, c

  print *, 'Enter two numbers'

  read *, a, b

  c = a + b

  print *, 'Result is ', c

end program example

为了解析这样的程序,需要定义几个解析函数,每个函数负责解析程序的一个特定部分。例如,parse_program 函数用来解析整个程序,包括程序的开始和结束,以及程序内的所有语句。parse_declaration 函数解析数据声明行,例如 integer :: a, b, c。parse_statement 函数用于解析如输入输出语句(print、read)和赋值语句。

通过上面的解析,可以得到以下抽象语法树。

Program: example

├── Declaration: integer

│   ├── a

│   ├── b

│   └── c

├── Print: "Enter two numbers"

├── Read

│   ├── a

│   └── b

├── Assignment

│   ├── c

│   └── Expression: a + b

└── Print: "Result is ", c

上述AST的分析如下:Program是根节点,表示整个程序,且程序名是example。Declaration是声明节点,显示声明的类型(integer)和变量名(a, b, c)。Print是打印操作,包含打印的具体内容。Read是读取操作,显示读取的变量。Assignment是赋值操作,左侧是被赋值的变量,右侧是赋值表达式。Expression是表达式节点,用于表示简单的加法操作。

  • Fortran语言的LL(1)分析示例

(1)产生式规则

Fortran语言中的简单规则包括变量声明、赋值语句、控制流语句等,对规则进行文法推导可以得到以下产生式。

【程序结构】

  1. Program → program ID Declarations Statements end program ID

【声明部分】

  1. Declarations → Declaration Declarations | ε
  2. Declaration → type :: ID_list

【语句部分】

  1. Statements → Statement Statements | ε
  2. Statement → ID = Expr | print *, Expr | if (Cond) Statement | do ID = Expr, Expr Statement end do

【表达式】

  1. Expr → Expr + Term | Expr - Term | Term
  2. Term → Term * Factor | Term / Factor | Factor
  3. Factor → ID | NUM

【条件表达式】

  1. Cond → Expr Relop Expr
  2. Relop → < | > | == | >= | <= | /=

【标识符和数字列表】

  1. ID_list → ID , ID_list | ID

(2)文法推导

考虑一个简单的Fortran程序,它声明一个整数变量,计算一个简单的算术表达式,并打印结果。程序如下:

program Calc

    integer :: a, b

    a = 5

    b = a * 2

    print *, b

end program Calc

【推导程序结构】

Program → program ID Declarations Statements end program ID

在这里,第一个和最后一个 ID 都是 Calc。

【推导声明部分】

Declarations → Declaration Declarations

Declaration → type :: ID_list

ID_list → ID , ID_list | ID

对于 integer :: a, b,ID_list 推导为 a , b。

【推导语句部分】

Statements → Statement Statements

Statement → ID = Expr 或 print *, Expr

Expr → Expr + Term | Term

Term → Term * Factor | Factor

Factor → ID | NUM

对于 a = 5 和 b = a * 2,这些语句通过表达式推导出来。

【推导表达式】

对于 b = a * 2,Expr 需要被推导为 Term,其中 Term 推导为 Term * Factor,进一步推导出 a * 2。

(3)消除左递归

左递归的存在会使递归下降解析器陷入无限循环。因此,需要将左递归转换为右递归。

【表达式(Expr)】

原规则:Expr → Expr + Term | Expr - Term | Term

修改为:

Expr → Term Expr'

Expr' → + Term Expr' | - Term Expr' | ε

【项(Term)】

原规则:Term → Term * Factor | Term / Factor | Factor

修改为:

Term → Factor Term'

Term' → * Factor Term' | / Factor Term' | ε

【声明(Declarations)】

原规则:Declarations → Declaration Declarations | ε

修改为:

Declarations → Declaration MoreDeclarations

MoreDeclarations → Declarations | ε

【语句(Statements)】

原规则:Statements → Statement Statements | ε

修改为:

Statements → Statement MoreStatements

MoreStatements → Statements | ε

经过上述的变换,可以将原始的左递归结构转换成了可以由LL(1)解析器处理的右递归结构,并通过引入新的非终结符(如Expr'和Term')来维护原有的语义。同时,通过添加MoreDeclarations和MoreStatements非终结符,保留了语句和声明的重复结构,同时消除了潜在的左递归问题。

(4)生成FIRST集和FOLLOW集

FIRST集是从某个非终结符开始可能导出的起始终结符集合。可以按照以下规则计算FIRST集:

  1. 如果X是终结符,FIRST(X) = {X}。
  2. 如果X是非终结符且X → Y1Y2...Yk是一个产生式,那么将FIRST(Y1) (除去ε) 加入到FIRST(X)中。如果Y1包含ε,继续将FIRST(Y2)加入到FIRST(X)中,依此类推。
  3. 如果X → ε是一个产生式,将ε加入到FIRST(X)中。

FOLLOW集是在输入字符串中紧跟在某个非终结符后面可能出现的终结符集合。可以按照以下规则计算FOLLOW集:

  1. 如果有一个产生式A → αBβ,那么所有在FIRST(β)中的元素 (除去ε) 都在FOLLOW(B)中。
  2. 如果β能够推导出ε,或者产生式形式为A → αB,则FOLLOW(A)中的所有元素都在FOLLOW(B)中。

根据上述规则,可以计算出示例的FIRST集和FOLLOW集,如下表所示。

非终结符

FIRST

FOLLOW

Program

{program}

{$}

Declarations

{type, ε}

{ID, end}

MoreDeclarations

{type, ε}

{ID, end}

Declaration

{type}

{type, ID, end}

ID_list

{ID}

{::, ,}

Statements

{ID, print, if, do, ε}

{end}

MoreStatements

{ID, print, if, do, ε}

{end}

Statement

{ID, print, if, do}

{ID, end, do, print, if}

Expr

{ID, NUM}

{==, <, >, <=, >=, /=, ;, do, ,, end}

Expr'

{+, -, ε}

{==, <, >, <=, >=, /=, ;, do, ,, end}

Term

{ID, NUM}

{+, -, ==, <, >, <=, >=, /=, ;, do, ,, end}

Term'

{*, /, ε}

{+, -, ==, <, >, <=, >=, /=, ;, do, ,, end}

Factor

{ID, NUM}

{*, /, +, -, ==, <, >, <=, >=, /=, ;, do, ,, end}

Cond

{ID, NUM}

{)}

Relop

{<, >, ==, >=, <=, /=}

{ID, NUM}

(5)生成SELECT集

根据FIRST集和FOLLOW集,可以计算出SELECT集如下:

Program → program ID Declarations Statements end program ID

SELECT集: {program}(因为FIRST集是{program})

Declarations → Declaration MoreDeclarations

SELECT集: {type}(取自FIRST(Declaration))

MoreDeclarations → ε

SELECT集: {ID, end}(取自FOLLOW(MoreDeclarations),因为ε在FIRST集中)

Statement → ID = Expr

SELECT集: {ID}(取自FIRST(ID))

*Statement → print , Expr

SELECT集: {print}(取自FIRST(print))

Expr' → + Term Expr'

SELECT集: {+}(取自FIRST(+))

Term' → ε

SELECT集: {+,-,==,<,>,<=,>=,/=,;,do,,,end}(取自FOLLOW(Term'),因为ε在FIRST集中)


(6)预测分析表

    最终的预测分析表,如下图所示。

(7)生成抽象语法树

经过LFortran编译后生成的AST如下:

(TranslationUnit

    [(Program

        expr2

        ()

        []

        []

        [(Declaration

            (AttrType

                TypeInteger

                []

                ()

                ()

                None

            )

            []

            [(a

            []

            []

            ()

            None

            ())

            (b

            []

            []

            ()

            None

            ())]

            ()

        )]

        [(=

            0

            a

            5

            ()

        )

        (=

            0

            b

            (* a 2)

            ()

        )

        (Print

            0

            ()

            [b]

            ()

        )]

        []

    )]

)

【4:实际编译过程】

Fortran语言的编译过程是将源代码转换成可执行程序的一系列步骤,这个过程涵盖了多个阶段,从预处理和词法分析开始,到代码优化和生成机器代码结束。

【预处理】阶段

宏处理:处理所有的宏定义,例如用 #define 声明的宏。这些宏会在编译之前被展开,替换源代码中的相应部分。

文件包含:处理源文件中的包含指令,如 #include,这通常用于包含头文件或其他源文件。

条件编译:根据条件编译指令(如 #ifdef, #ifndef, #endif)决定哪些代码部分将被编译。

【词法分析】阶段

词法单元生成:将预处理后的源代码转换为一系列的词法单元(tokens)。这些词法单元包括关键字、标识符、常量、运算符等。

【语法分析】阶段

构建抽象语法树(AST):根据Fortran的语法规则,将词法单元序列组织成一个结构化的抽象语法树。每个节点代表一个构造(如表达式、语句、控制结构等)。

【语义分析】阶段

类型检查:确保表达式中的操作符和操作数类型匹配,例如不允许将整型与字符串直接相加。

声明与定义的匹配:确认所有使用的变量和函数都已经被正确声明和定义。

绑定:将变量和函数的名称绑定到其定义的内存地址或者其他标识符。

【中间代码生成】阶段

生成中间表示:将AST转换成一种更接近机器语言但仍具有高级语言特性的中间表示(如三地址代码)。

优化中间代码:进行一些初步的代码优化,如消除无用代码、简化复杂的表达式。

【代码优化】阶段

高级优化:执行更复杂的优化技术,比如循环优化、常量折叠、强度削减、公共子表达式消除等,以提高代码的运行效率。

【目标代码生成】阶段

机器代码生成:将优化后的中间代码转换为目标机器上的机器代码。这包括分配寄存器、生成机器指令等。

【链接】阶段

解决外部依赖:将当前程序的目标代码与其他库或模块的目标代码合并,解决所有外部调用的引用,生成最终的可执行文件。

【5:编程案例】

(1)堆排序算法

    两种编程语言的代码编写,如下表所示。

Fortran语言代码

program expr2

       implicit none

    integer, parameter :: n = 10

    integer :: i, arr(n)

    ! 初始化数组

    arr = (/ 10, 4, 5, 30, 3, 300, 35, 40, 1, 50 /)

    ! 堆排序

    call heapSort(arr, n)

    ! 输出排序后的数组

    print *, "Sorted array:"

    do i = 1, n

        print *, arr(i)

    end do

contains

    subroutine heapSort(arr, n)

        integer, intent(inout) :: arr(n)

        integer, intent(in) :: n

        integer :: i, j, temp

        ! 建立堆

        do i = n / 2, 1, -1

            call heapify(arr, n, i)

        end do

        ! 从堆中依次取出元素

        do i = n, 2, -1

            ! 移动当前根到末尾

            temp = arr(1)

            arr(1) = arr(i)

            arr(i) = temp

            ! 调整剩余堆

            call heapify(arr, i - 1, 1)

        end do

    end subroutine heapSort

    subroutine heapify(arr, n, i)

        integer, intent(inout) :: arr(n)

        integer, intent(in) :: n, i

        integer :: largest, l, r, temp

        largest = i

        l = 2 * i

        r = 2 * i + 1

        ! 如果左子节点更大,更新largest

        if (l <= n .and. arr(l) > arr(largest)) then

            largest = l

        endif

        ! 如果右子节点更大,更新largest

        if (r <= n .and. arr(r) > arr(largest)) then

            largest = r

        endif

        ! 如果最大不是根节点,交换并继续堆化

        if (largest /= i) then

            temp = arr(i)

            arr(i) = arr(largest)

            arr(largest) = temp

            call heapify(arr, n, largest)

        endif

    end subroutine heapify

end program

C语言代码

#include <stdio.h>

void heapify(int arr[], int n, int i) {

    int largest = i;

    int l = 2 * i + 1; // 在C中,数组索引从0开始

    int r = 2 * i + 2;

    int temp;

    // 如果左子节点更大,更新largest

    if (l < n && arr[l] > arr[largest]) {

        largest = l;

    }

    // 如果右子节点更大,更新largest

    if (r < n && arr[r] > arr[largest]) {

        largest = r;

    }

    // 如果最大不是根节点,交换并继续堆化

    if (largest != i) {

        temp = arr[i];

        arr[i] = arr[largest];

        arr[largest] = temp;

        heapify(arr, n, largest);

    }

}

void heapSort(int arr[], int n) {

    int i, temp;

    // 建立堆

    for (i = n / 2 - 1; i >= 0; i--) {

        heapify(arr, n, i);

    }

    // 从堆中依次取出元素

    for (i = n - 1; i > 0; i--) {

        // 移动当前根到末尾

        temp = arr[0];

        arr[0] = arr[i];

        arr[i] = temp;

        // 调整剩余堆

        heapify(arr, i, 0);

    }

}

int main() {

    int arr[10] = {10, 4, 5, 30, 3, 300, 35, 40, 1, 50};

    int n = 10;

    int i;

    // 堆排序

    heapSort(arr, n);

    // 输出排序后的数组

    printf("Sorted array:\n");

    for (i = 0; i < n; i++) {

        printf("%d\n", arr[i]);

    }

    return 0;

}

Fortran语言运行结果,如下图所示。

C语言运行结果,如下图所示。

(2)鸡兔同笼问题

两种编程语言的代码编写,如下表所示。

Fortran语言代码

program expr2

    implicit none

    integer :: heads, legs, rabbits, chickens

    heads = 10

    legs = 28

    ! 计算兔子和鸡的数量

    call solve_chicken_rabbit(heads, legs, chickens, rabbits)

    ! 输出结果

    if (chickens >= 0 .and. rabbits >= 0) then

        print *, 'Number of chickens:', chickens

        print *, 'Number of rabbits:', rabbits

    else

        print *, 'No solution found.'

    end if

contains

    subroutine solve_chicken_rabbit(h, l, c, r)

        integer, intent(in) :: h, l

        integer, intent(out) :: c, r

        r = (l - 2 * h) / 2

        c = h - r

        if (c < 0 .or. r < 0 .or. 2*c + 4*r /= l) then

            c = -1

            r = -1

        end if

    end subroutine solve_chicken_rabbit

end program

C语言代码

#include <stdio.h>

void solve_chicken_rabbit(int h, int l, int *c, int *r) {

    *r = (l - 2 * h) / 2;

    *c = h - *r;

    if (*c < 0 || *r < 0 || 2 * (*c) + 4 * (*r) != l) {

        *c = -1;

        *r = -1;

    }

}

int main() {

    int heads = 10;

    int legs = 28;

    int rabbits, chickens;

    // 计算兔子和鸡的数量

    solve_chicken_rabbit(heads, legs, &chickens, &rabbits);

    // 输出结果

    if (chickens >= 0 && rabbits >= 0) {

        printf("Number of chickens: %d\n", chickens);

        printf("Number of rabbits: %d\n", rabbits);

    } else {

        printf("No solution found.\n");

    }

    return 0;

}

Fortran语言运行结果,如下图所示。

C语言运行结果,如下图所示。

(3)欧几里得算法

两种编程语言的代码编写,如下表所示。

Fortran语言代码

program expr2

    implicit none

    integer :: a, b

    a = 999

    b = 666

    ! 输出它们的最大公约数

    print *, 'The GCD of', a, 'and', b, 'is', gcd(a, b)

contains

    ! 递归实现的欧几里得算法

    recursive function gcd(x, y) result(g)

        integer, intent(in) :: x, y

        integer :: g

        if (y == 0) then

            g = x

        else

            g = gcd(y, mod(x, y))

        end if

    end function gcd

end program

C语言代码

#include <stdio.h>

// 递归实现的欧几里得算法

int gcd(int x, int y) {

    if (y == 0)

        return x;

    else

        return gcd(y, x % y);

}

int main() {

    int a = 999;

    int b = 666;

    // 输出它们的最大公约数

    printf("The GCD of %d and %d is %d\n", a, b, gcd(a, b));

    return 0;

}

Fortran语言运行结果,如下图所示。

C语言运行结果,如下图所示。

【6:对比C语言】

(1)语法和结构

Fortran语言支持显式的并行处理指令和数组操作。其语法支持科学计算中常见的抽象,如复数、矩阵乘法等,这些都直接内置在语言中。

C语言提供了丰富的数据类型和控制结构,但不直接支持像Fortran那样的高级数学结构。C语言的语法更灵活,支持指针、宽范围的数据类型和结构体,更适合进行底层的系统编程。

(2)编译器和优化

Fortran语言的编译器通常专注于数值计算的优化,如循环展开、数组合并、数据局部性优化等。Fortran语言的编译器经常需要处理高维数组的有效存储和访问,以及并行执行的优化。

C语言编译器更侧重于内存和指针操作的优化,如内联函数、分支预测、指令重排和寄存器分配。C语言编译器还需要处理更复杂的内存管理策略,因为C语言允许直接的内存地址操作。

(3)错误处理和安全性

Fortran语言通常认为在数组操作和数值处理方面比C语言更安全,因为数组越界错误和指针错误在Fortran语言中更少见。

C语言由于其灵活性和低级特性,C语言程序更容易出现内存泄露、缓冲区溢出等安全问题。

(4)词法分析

Fortran语言的词法元素包括关键字、标识符、数字、运算符和格式说明符。早期版本的Fortran语言的词法分析器在固定和自由源代码格式处理等方面存在问题。

C语言的词法结构相对简单。标记包括关键字、标识符、常量、字符串字面量和运算符。C语言的预处理器指令(如#define和#include)增加了词法分析的复杂性。

(5)语法分析

Fortran语言的语法设计更专注于数学表达式和数组操作,在语法上相对直接。Fortran语言支持显式的数组切片和复杂数学函数调用,这些都是直接内置的。但是,Fortran语言中的隐式变量声明和数组维度的处理在语法分析时需要特别注意。此外,程序单元之间的依赖和接口(如模块和子程序调用)需要在语法分析阶段进行正确处理。

C语言具有相对复杂的语法结构,支持广泛的控制结构和数据类型。这导致语法分析相对复杂,需要处理多种语句和表达式的嵌套。因此,C语言的指针语法、函数指针、类型转换和复合字面量等特性,要求语法分析器必须非常灵活和强大。

五、总结

1:Fortran语言的编译器优化主要针对数值计算的高效执行,而C语言的编译器则更侧重于通用性和底层操作的优化。

2:Fortran的词法分析需特别注意代码的列布局,以及连续行和注释的处理。在C语言中,预处理器的概念增加了词法分析的复杂度,因为必须先处理如宏定义和条件编译指令等预处理操作,然后才是传统的标记化过程。

3:Fortran语言在语法分析时更多地关注高效的数组和数学表达式处理,例如如何高效地处理数组切片和复杂的内置数学函数调用。C语言的语法分析必须处理复杂的表达式和多层嵌套的控制结构,还有类型系统中的各种隐式和显式转换。

六、参考文献

1:维基百科。
https://zh.wikipedia.org/wiki/Fortran

2:官网。
The Fortran Programming Language — Fortran Programming Language

3:WIKIBOOKS。
https://en.wikibooks.org/wiki/Fortran

4:Fortran语法分析。
FORTRAN Syntactic Analysis

5:LFortran在线编译器。
LFortran

七、简易词法分析器的源代码

lex.h

#ifndef LEX_H_

#define LEX_H_

#include <string>

#include <iostream>

#include <map>

using namespace std;

//Definition of all the possible token types

enum Token {

    // keywords OR RESERVED WORDS

    IF, ELSE, PRINT, INTEGER, REAL,

    CHARACTER, END, THEN, PROGRAM,

    LEN,

    // identifiers

    IDENT,

    // an integer, real, logical and string constants

    ICONST, RCONST, SCONST, BCONST,

    // the arithmetic operators, logic operators, relational operators

    PLUS, MINUS, MULT, DIV, ASSOP, EQ, POW,

    GTHAN, LTHAN, CAT,

    //Delimiters

    COMMA, LPAREN, RPAREN, DOT, DCOLON, DEF,

    // any error returns this token

    ERR,

    // when completed (EOF), return this token

    DONE,

};

//Class definition of LexItem

class LexItem {

    Token   token;

    string  lexeme;

    int lnum;

public:

    LexItem() {

        token = ERR;

        lnum = -1;

    }

    LexItem(Token token, string lexeme, int line) {

        this->token = token;

        this->lexeme = lexeme;

        this->lnum = line;

    }

    bool operator==(const Token token) const { return this->token == token; }

    bool operator!=(const Token token) const { return this->token != token; }

    Token   GetToken() const { return token; }

    string  GetLexeme() const { return lexeme; }

    int GetLinenum() const { return lnum; }

};


 

extern ostream& operator<<(ostream& out, const LexItem& tok);

extern LexItem id_or_kw(const string& lexeme, int linenum);

extern LexItem getNextToken(istream& in, int& linenum);

#endif /* LEX_H_ */

lex.cpp

#include <algorithm>

#include "lex.h"

LexItem id_or_kw(const string& lexeme, int linenum) {

    string upper = lexeme;

    string lower = lexeme;

    transform(upper.begin(), upper.end(), upper.begin(), ::toupper);

    transform(lower.begin(), lower.end(), lower.begin(), ::tolower);

    static map<string, Token> tokenKeywords_upper {

            {"PROGRAM", PROGRAM}, {"IF", IF}, {"ELSE", ELSE}, {"PRINT", PRINT},

            {"INTEGER", INTEGER}, {"REAL", REAL}, {"CHARACTER", CHARACTER},

            {"END", END}, {"THEN", THEN}, {"LEN", LEN}

    };

    static map<string, Token> tokenKeywords_lower {

            {"program", PROGRAM}, {"if", IF}, {"else", ELSE}, {"print", PRINT},

            {"integer", INTEGER}, {"real", REAL}, {"character", CHARACTER},

            {"end", END}, {"then", THEN}, {"len", LEN}

    };

    auto it = tokenKeywords_upper.find(upper);

    if (it != tokenKeywords_upper.end()) {

        return LexItem(it->second, lexeme, linenum);

    } else if ((it = tokenKeywords_lower.find(lower)) != tokenKeywords_lower.end()) {

        return LexItem(it->second, lexeme, linenum);

    } else {

        return LexItem(IDENT, lexeme, linenum);

    }

}

ostream& operator<<(ostream& out, const LexItem& tok) {

    switch (tok.GetToken()) {

        case IF:

            out << "IF";

            break;

        case ELSE:

            out << "ELSE";

            break;

        case PRINT:

            out << "PRINT";

            break;

        case INTEGER:

            out << "INTEGER";

            break;

        case REAL:

            out << "REAL";

            break;

        case CHARACTER:

            out << "CHARACTER";

            break;

        case END:

            out << "END";

            break;

        case THEN:

            out << "THEN";

            break;

        case PROGRAM:

            out << "PROGRAM";

            break;

        case LEN:

            out << "LEN";

            break;

        case IDENT:

            out << "IDENT";

            break;

        case ICONST:

            out << "ICONST";

            break;

        case RCONST:

            out << "RCONST";

            break;

        case SCONST:

            out << "SCONST";

            break;

        case BCONST:

            out << "BCONST";

            break;

        case PLUS:

            out << "PLUS";

            break;

        case MINUS:

            out << "MINUS";

            break;

        case MULT:

            out << "MULT";

            break;

        case DIV:

            out << "DIV";

            break;

        case ASSOP:

            out << "ASSOP";

            break;

        case EQ:

            out << "EQ";

            break;

        case POW:

            out << "POW";

            break;

        case GTHAN:

            out << "GTHAN";

            break;

        case LTHAN:

            out << "LTHAN";

            break;

        case CAT:

            out << "CAT";

            break;

        case COMMA:

            out << "COMMA";

            break;

        case LPAREN:

            out << "LPAREN";

            break;

        case RPAREN:

            out << "RPAREN";

            break;

        case DOT:

            out << "DOT";

            break;

        case DCOLON:

            out << "DCOLON";

            break;

        case DEF:

            out << "DEF";

            break;

        case ERR:

            out << "ERR";

            break;

        case DONE:

            out << "DONE";

            break;

    }

    if (tok.GetToken() == ICONST || tok.GetToken() == RCONST || tok.GetToken() == BCONST) {

        out << ": (" << tok.GetLexeme() << ")";

    }

    if (tok.GetToken() == IDENT) {

        out << ": '" << tok.GetLexeme() << "'";

    }

    if (tok.GetToken() == SCONST) {

        out << ": \"" << tok.GetLexeme() << "\"";

    }

    out << endl;

    return out;

}

LexItem getNextToken(istream& in, int& linenum) {

    enum tokenState {START, INID, INSTRING, ININT, INREAL, INCOMMENT} lexState = START;

    string lexeme;

    char character, nextChar, quoteMark;

    bool checker = false;

    while (in.get(character)) {

        switch (lexState) {

            case START:

                if (character == '\n') {

                    if (in.peek() != EOF) {

                        linenum++;

                    }

                    continue;

                }

                if(character == '\r'){

                    continue;

                }

                if (isspace(character)) { if(in.peek() == EOF){linenum--;} continue; }

                lexeme = character;

                if (isdigit(character)) { lexState = ININT; continue;}

                else if (isalpha(character)) { lexState = INID; continue;}

                else if (character == '\'' || character == '\"') { lexState = INSTRING; lexeme += (char)in.peek(); continue;}

                else if (character == '!') {

                    lexState = INCOMMENT;

                }

                else if (character == ':') {

                    if (in.peek() == ':') {

                        in.get(character);

                        return LexItem(DCOLON, lexeme, linenum);

                    }

                    return LexItem(ERR, lexeme, linenum);

                }

                else if (character == '.') {

                    lexState = INREAL;

                    checker = true;

                    continue;

                }

                else {

                    if (character == '+') { return LexItem(PLUS, lexeme, linenum); }

                    if (character == '-') { return LexItem(MINUS, lexeme, linenum); }

                    if (character == '*') {

                        if (in.peek() == '*') {

                            in.get(character);

                            return LexItem(POW, lexeme, linenum);

                        }

                        else if (in.peek() == ',') {

                            return LexItem(DEF, lexeme, linenum);

                        }

                        else {

                            return LexItem(MULT, lexeme, linenum);

                        }

                    }

                    if (character == '/') {

                        if (in.peek() == '/') {

                            in.get(character);

                            return LexItem(CAT, lexeme, linenum);

                        } else {

                            return LexItem(DIV, lexeme, linenum);

                        }

                    }

                    if (character == '=') {

                        if (in.peek() == '=') {

                            in.get(character);

                            return LexItem(EQ, lexeme, linenum);

                        } else {

                            return LexItem(ASSOP, lexeme, linenum);

                        }

                    }

                    if (character == '>') { return LexItem(GTHAN, lexeme, linenum); }

                    if (character == '<') { return LexItem(LTHAN, lexeme, linenum); }

                    if (character == '(') { return LexItem(LPAREN, lexeme, linenum); }

                    if (character == ')') { return LexItem(RPAREN, lexeme, linenum); }

                    if (character == ',') {

                        return LexItem(COMMA, lexeme, linenum);

                    }

                    else {

                        return LexItem(ERR, lexeme, linenum);

                    }

                }

                break;

            case INCOMMENT:

                if (character == '\n') {

                    linenum++;

                    lexState = START;

                }

                break;

            case INID:

                if (isalnum(character) || character == '_') {

                    lexeme += character;

                    if (isalnum(in.peek()) || in.peek() == '_') {

                        continue;

                    }

                    else {

                        LexItem result = id_or_kw(lexeme, linenum);

                        return result;

                    }

                }

                else {

                    in.putback(character);

                    return id_or_kw(lexeme, linenum);

                }

                continue;

            case INSTRING:

                quoteMark = lexeme[0];

                while (in.get(nextChar)) {

                    if (nextChar == '\n') {

                        return LexItem(ERR, lexeme , linenum);

                    }

                    lexeme += nextChar;

                    if (nextChar == quoteMark) {

                        return LexItem(SCONST, lexeme.substr(1,lexeme.length()-2), linenum);

                    }

                }

                return LexItem(ERR, lexeme, linenum);

            case ININT:

                if (isdigit(character)) {

                    lexeme += character;

                }

                else if (character == '.') {

                    checker = true;

                    lexeme += character;

                    lexState = INREAL;

                    continue;

                }

                else {

                    in.putback(character);

                    return LexItem(ICONST, lexeme, linenum);

                }

                continue;

            case INREAL:

                while (isdigit(character) || (character == '.' && checker)) {

                    lexeme += character;

                    in.get(character);

                    if (character == '.') {

                        lexeme += character;

                        return LexItem(ERR, lexeme, linenum);

                    }

                    checker = isdigit(in.peek());

                }

                if (lexeme.back() == '.') {

                    in.putback(character);

                    return LexItem(DOT, ".", linenum);

                }

                in.putback(character);

                return LexItem(RCONST, lexeme, linenum);

        }

    }

    if( in.eof() )

        return LexItem(DONE, "", linenum);

    return LexItem(ERR, "some strange I/O error", linenum);

}

main.cpp

#include <fstream>

#include "lex.h"

using namespace std;

map<string, Token> tokenKeywords_upper_modified {

        {"PROGRAM", PROGRAM}, {"IF", IF}, {"ELSE", ELSE}, {"PRINT", PRINT},

        {"INTEGER", INTEGER}, {"REAL", REAL}, {"CHARACTER", CHARACTER},

        {"END", END}, {"THEN", THEN}, {"LEN", LEN}

};

map<string, Token> tokenKeywords_lower_modified {

        {"program", PROGRAM}, {"if", IF}, {"else", ELSE}, {"print", PRINT},

        {"integer", INTEGER}, {"real", REAL}, {"character", CHARACTER},

        {"end", END}, {"then", THEN}, {"len", LEN}

};

void getFileStatus(istream& file, string& filename) {

    if (!file) {

        cerr << "CANNOT OPEN THE FILE " << filename << endl;

        exit(1);

    }

    if (file.peek() == EOF) {

        cerr << "Empty File." << endl;

        exit (1);

    }

}

int main(int argc, char* argv[]) {

    int nonFlagArg = 0;

    int totalTokens = 0;

    int lineNumber = 1;

    LexItem token;

    string filename;

    map<int,int> integerConstants;

    map<string,int> realConstants;

    map<string,int>::iterator reals;

    map<string,int> stringLiterals;

    map<string,int>::iterator strings;

    map<string,int>::iterator key;

    map<string,int> keywords_modified;

    map<string,int> keywords_upper_modified;

    map<string,int> keywords_lower_modified;

    map<string,int> identifiers;

    map<int,int>::iterator it;

    map<string,bool>  flag_arguments{

            {"-all", false},

            {"-int", false},

            {"-real", false},

            {"-str", false},

            {"-id", false},

            {"-kw", false}

    };

    if (argc == 1) {

        cerr << "NO SPECIFIED INPUT FILE." << endl;

        exit(1);

    }

    for (int i = 1; i < argc; i++) {

        string argument = argv[i];

        map<string, bool>::iterator it = flag_arguments.find(argument);

        if (it != flag_arguments.end()) {

            it->second = true;

            continue;

        }

        else if(argument[0] == '-'){

            cerr << "UNRECOGNIZED FLAG " << "{" << argument << "}" << endl;

            return 0;

        }

        nonFlagArg++;

    }

    if (nonFlagArg != 1) {

        cerr << "ONLY ONE FILE NAME IS ALLOWED." << endl;

        exit (1);

    }

    filename = argv[1];

    ifstream file(filename.c_str());

    getFileStatus(file, filename);

    while (true) {

        token = getNextToken(file, lineNumber);

        if (token.GetToken() == ERR || token.GetToken() == DONE) {

            break;

        }

        totalTokens++;

        if (flag_arguments["-all"]) {

            cout << token;

        }

        if (token.GetToken() == ICONST) {

            int value = stoi(token.GetLexeme());

            integerConstants[value]++;

        }

        else if (token.GetToken() == IDENT) {

            identifiers[token.GetLexeme()]++;

        }

        else if (token.GetToken() == RCONST) {

            realConstants[token.GetLexeme()]++;

        }

        else if (token.GetToken() == SCONST) {

            stringLiterals[token.GetLexeme()]++;

        }

        else if (token.GetToken() == tokenKeywords_upper_modified[token.GetLexeme()]) {

            keywords_modified[token.GetLexeme()]++;

        }

        else if (token.GetToken() == tokenKeywords_lower_modified[token.GetLexeme()]) {

            keywords_modified[token.GetLexeme()]++;

        }

    }

    if (token.GetToken() ==  ERR) {

        cerr << "Error in line " << lineNumber << ": Unrecognized Lexeme {" << token.GetLexeme() << "}" << endl;

        exit(1);

    }

    cout << endl;

    cout << "Lines: " << lineNumber << endl;

    cout << "Total Tokens: " << totalTokens << endl;

    cout << "Identifiers: " << identifiers.size() << endl;

    cout << "Integers: " << integerConstants.size() << endl;

    cout << "Reals: " << realConstants.size() << endl;

    cout << "Strings: " << stringLiterals.size() << endl;

    map<string,int>::iterator id;

    if (flag_arguments["-id"]) {

        cout << "IDENTIFIERS:" << endl;

        for (id = identifiers.begin(); id != identifiers.end(); id++) {

            cout << id->first << " (" << id->second << ")";

            if (next(id) != identifiers.end()) {

                cout << ", ";

            }

        }

        cout << endl;

    }

    if (flag_arguments["-kw"]) {

        cout << "KEYWORDS:" << endl;

        if (keywords_modified.size() > 1) {

            for (auto key_up = keywords_modified.begin(); key_up != keywords_modified.end(); key_up++) {

                cout << key_up->first << " (" << key_up->second << ")";

                if (next(key_up) != keywords_modified.end()) {

                    cout << ", ";

                }

            }

        }

        if (keywords_lower_modified.size() > 1) {

            for (auto key_low = keywords_modified.begin(); key_low != keywords_modified.end(); key_low++) {

                cout << key_low->first << " (" << key_low->second << ")";

                if (next(key_low) != keywords_modified.end()) {

                    cout << ", ";

                }

            }

        }

        cout << endl;

    }

    if (flag_arguments["-int"]) {

        cout << "INTEGERS:" << endl;

        for (it = integerConstants.begin(); it != integerConstants.end(); it++) {

            cout << it->first;

            if (next(it) != integerConstants.end()) {

                cout << ", ";

            }

        }

        cout << endl;

    }

    if (flag_arguments["-real"]) {

        cout << "REALS:" << endl;

        for (reals = realConstants.begin(); reals != realConstants.end(); reals++) {

            if (reals->first[0] == '.') {

                cout << "0" << reals->first;

            }

            else {

                cout << reals->first;

            }

            if (next(reals) != realConstants.end()) {

                cout << ", ";

            }

        }

        cout << endl;

    }

    if (flag_arguments["-str"]) {

        cout << "STRINGS:" << endl;

        for (strings = stringLiterals.begin(); strings != stringLiterals.end(); strings++) {

            cout << "\"" << strings->first << "\"";

            if (next(strings) != stringLiterals.end()) {

                cout << ", ";

            }

        }

        cout << endl;

    }

    return 0;

}

八、Fortran的产生式规则

Fortran 77和Fortran 90共同的产生式规则

% 1
% R201
xExecutableProgram:
  xProgramUnit / xExecutableProgram xProgramUnit .
 
% R202
xProgramUnit:
  xMainProgram /
  xFunctionSubprogram /
  xSubroutineSubprogram /
  xBlockDataSubprogram .
 
% 2
% R1101
xMainProgram:
  xMainRange /
  xProgramStmt xMainRange .
xMainRange:
  xBody xEndProgramStmt /
  xEndProgramStmt .
xEndProgramStmt: xLblDef 'end' xEOS .
 
xBody:
  xBodyConstruct / xBody xBodyConstruct .
xBodyConstruct:
  xSpecificationPartConstruct / xExecutableConstruct .
 
% R204
xSpecificationPartConstruct:
  xImplicitStmt / xParameterStmt / xFormatStmt / xEntryStmt /
  xDeclarationConstruct .
 
% R207
xDeclarationConstruct:
  xTypeDeclarationStmt / xSpecificationStmt .
 
% 3
% R1215
xFunctionSubprogram:
  xLblDef xFunctionPrefix xFunctionName xFunctionRange .
xFunctionRange:
  xFunctionParList xEOS xBody xEndFunctionStmt /
  xFunctionParList xEOS xEndFunctionStmt .
xEndFunctionStmt: xLblDef 'end' xEOS .
 
% 4
% R1219
xSubroutineSubprogram:
  xLblDef 'subroutine' xSubroutineName xSubroutineRange .
xSubroutineRange:
  xSubroutineParList xEOS xBody xEndSubroutineStmt /
  xSubroutineParList xEOS xEndSubroutineStmt .
xEndSubroutineStmt: xLblDef 'end' xEOS .
 
% 5
% R1110
xBlockDataSubprogram:
  xBlockDataStmt xBlockDataBody xEndBlockDataStmt /
  xBlockDataStmt xEndBlockDataStmt .
xEndBlockDataStmt: xLblDef 'end' xEOS .
 
xBlockDataBody:
  xBlockDataBodyConstruct / xBlockDataBody xBlockDataBodyConstruct .
xBlockDataBodyConstruct:
  xSpecificationPartConstruct .
 
% 6
xSpecificationStmt:
  xCommonStmt /
  xDataStmt /
  xDimensionStmt /
  xEquivalenceStmt /
  xExternalStmt /
  xIntrinsicStmt /
  xSaveStmt .
 
% 7
xExecutionPartConstruct:
  xExecutableConstruct / xFormatStmt / xDataStmt / xEntryStmt .
 
xExecutableConstruct:
  xActionStmt /
  xDoConstruct /
  xIfConstruct .
 
xActionStmt:
  xArithmeticIfStmt /
  xAssignmentStmt / xAssignStmt /
  xBackspaceStmt /
  xCallStmt /
  xCloseStmt /
  xContinueStmt /
  xEndfileStmt /
  xGotoStmt / xComputedGotoStmt / xAssignedGotoStmt /
  xIfStmt /
  xInquireStmt /
  xOpenStmt /
  xPauseStmt /
  xPrintStmt /
  xReadStmt /
  xReturnStmt /
  xRewindStmt /
  xStmtFunctionStmt /
  xStopStmt /
  xWriteStmt .
 
% 8
xProgramStmt:
  xLblDef 'program' xProgramName xEOS .
 
% 9 see Entry Statement
 
% 10
/* Must be split on semantic grounds, due to the different scopes for the
 * function name and the dummy parameters (if any).  See 3
 *
 * xFunctionStmt:
 *   xLblDef xFunctionPrefix xName xFunctionParList xEOS .
 */
xFunctionPrefix: 'function' / xTypeSpec 'function' .
 
xFunctionParList: / '(' xFunctionPars ')' .
xFunctionPars: / xFunctionPar / xFunctionPars ',' xFunctionPar .
xFunctionPar: xDummyArgName .
 
% 11 parsed as 13, distinguished semantically
 
% 12
/* Must be split on semantic grounds, due to the different scopes for the
 * subroutine name and the dummy parameters (if any).  See 4
 *
 * xSubroutineStmt:
 *   xLblDef 'subroutine' xName xSubroutineParList xEOS.
 */
xSubroutineParList: / '(' xSubroutinePars ')' .
xSubroutinePars: / xSubroutinePar / xSubroutinePars ',' xSubroutinePar .
xSubroutinePar: xDummyArgName / '*' .
 
% 13
Entry Statement[4]
 
% 14
xBlockDataStmt:
  xLblDef 'blockdata' xBlockDataName xEOS /
  xLblDef 'blockdata' xEOS .
 
% 15
% R525
xDimensionStmt:
  xLblDef 'dimension' xArrayDeclaratorList xEOS .
 
% 16
xArrayDeclaratorList:
  xArrayDeclarator / xArrayDeclaratorList ',' xArrayDeclarator .
xArrayDeclarator: xVariableName '(' xArraySpec ')' .
 
% R512
xArraySpec: xExplicitShapeSpecList / xAssumedSizeSpec .
 
% R513
xExplicitShapeSpecList:
  xExplicitShapeSpec / xExplicitShapeSpecList ',' xExplicitShapeSpec .
xExplicitShapeSpec: xLowerBound ':' xUpperBound / xUpperBound .
 
% R514
xLowerBound: Specification Expression[5] .
 
% R515
xUpperBound: Specification Expression[5] .
 
% R518
xAssumedSizeSpec:
  '*' /
  xLowerBound ':' '*' /
  xExplicitShapeSpecList ',' '*' /
  xExplicitShapeSpecList ',' xLowerBound ':' '*' .
 
% 17
% R545
xEquivalenceStmt:
  xLblDef 'equivalence' xEquivalenceSetList xEOS .
 
% R546
xEquivalenceSetList:
  xEquivalenceSet / xEquivalenceSetList ',' xEquivalenceSet .
xEquivalenceSet: '(' xEquivalenceObject ',' xEquivalenceObjectList ')' .
 
% 18
% R547
xEquivalenceObjectList:
  xEquivalenceObject / xEquivalenceObjectList ',' xEquivalenceObject .
xEquivalenceObject: Equivalence Entity[6] .
 
% 19
% R548
xCommonStmt:
  xLblDef 'common' xComlist xEOS .
xComlist:
  xCommonBlockObject /
  xComblock xCommonBlockObject /
  xComlist ',' xCommonBlockObject /
  xComlist xComblock xCommonBlockObject /
  xComlist ',' xComblock xCommonBlockObject .
xComblock: '/' '/' / '/' xCommonBlockName '/' .
xCommonBlockObject: xVariableName / xArrayDeclarator .
 
% 20
% R501
xTypeDeclarationStmt:
  xLblDef xTypeSpec xEntityDeclList xEOS .
 
% R502
xTypeSpec:
  'integer' /
  'real' /
  'doubleprecision' /
  'complex' /
  'logical' /
  'character' /
  'character' xLengthSelector .
 
% R504
xEntityDeclList: xEntityDecl / xEntityDeclList ',' xEntityDecl .
xEntityDecl:
  xObjectName /
  xObjectName '(' xArraySpec ')' /
  xObjectName '*' xCharLength /
  xObjectName '(' xArraySpec ')' '*' xCharLength .
 
% R507
xLengthSelector: '*' xCharLength .
 
% 21
% R540
xImplicitStmt:
  xLblDef 'implicit' xImplicitSpecList xEOS .
 
% R541
xImplicitSpecList: xImplicitSpec / xImplicitSpecList ',' xImplicitSpec .
xImplicitSpec: xTypeSpec Letter Specifications[7] .
 
% 22
% R508
xCharLength: '(' xTypeParamValue ')' / Scalar Integer Literal Constant[8] .
 
% R509
xTypeParamValue: Specification Expression[5] / '*' .
 
% 23
% R538
xParameterStmt:
  xLblDef 'parameter' '(' xNamedConstantDefList ')' xEOS .
 
% R539
xNamedConstantDefList:
  xNamedConstantDef / xNamedConstantDefList ',' xNamedConstantDef .
xNamedConstantDef: xNamedConstant '=' Constant Expression[9] .
 
% R307
xNamedConstant: xIdent .
xNamedConstantUse: xIdent .
 
% 24
% R1207
xExternalStmt:
  xLblDef 'external' xExternalNameList xEOS .
xExternalNameList: xExternalName / xExternalNameList ',' xExternalName .
 
% 25
% R1208
xIntrinsicStmt:
  xLblDef 'intrinsic' xIntrinsicList xEOS .
xIntrinsicList:
  xIntrinsicProcedureName / xIntrinsicList ',' xIntrinsicProcedureName .
 
% 26
% R523
xSaveStmt:
  xLblDef 'save' xEOS /
  xLblDef 'save' xSavedEntityList xEOS .
 
% R524
xSavedEntityList: xSavedEntity / xSavedEntityList ',' xSavedEntity .
xSavedEntity: xVariableName / xSavedCommonBlock .
xSavedCommonBlock: '/' xCommonBlockName '/' .
 
% 27
% R529
xDataStmt:
  xLblDef 'data' xDatalist xEOS .
xDatalist: xDataStmtSet / xDatalist xDataStmtSet / xDatalist ',' xDataStmtSet .
 
% R530
xDataStmtSet: xDataStmtObjectList '/' xDataStmtValueList '/' .
 
% R531
xDataStmtObjectList: xDataStmtObject / xDataStmtObjectList ',' xDataStmtObject .
xDataStmtObject: xVariable / xDataImpliedDo .
 
% R532
xDataStmtValueList: xDataStmtValue / xDataStmtValueList ',' xDataStmtValue .
xDataStmtValue:
  xConstant /
  Scalar Integer Literal Constant[8] '*' xConstant /
  xNamedConstantUse '*' xConstant .
 
% 28
% R535
xDataImpliedDo:
  '(' xDataIDoObjectList ',' xImpliedDoVariable '=' xExpr ',' xExpr ')' /
  '(' xDataIDoObjectList ',' xImpliedDoVariable '=' xExpr ',' xExpr
    ',' xExpr ')' .
 
% R536
xDataIDoObjectList: xDataIDoObject / xDataIDoObjectList ',' xDataIDoObject .
xDataIDoObject: xArrayElement / xDataImpliedDo .
 
% 29
Assignment Statement[13]
 
% 30 see 31-33
 
% 31
xGotoStmt:
  xLblDef GoToKw xLblRef xEOS .
 
GoToKw: 'goto' .
 
% 32
xComputedGotoStmt:
  xLblDef GoToKw '(' xLblRefList ')' Integer Expression[10] xEOS /
  xLblDef GoToKw '(' xLblRefList ')' xCommaExp xEOS .
xCommaExp: ',' Integer Expression[10] .
xLblRefList: xLblRef / xLblRefList ',' xLblRef .
xLblRef: xLabel .
 
% 33
% R839
xAssignedGotoStmt:
  xLblDef GoToKw xVariableName xEOS /
  xLblDef GoToKw xVariableName '(' xLblRefList ')' xEOS /
  xLblDef GoToKw xVariableComma '(' xLblRefList ')' xEOS .
xVariableComma: xVariableName ',' .
 
% 34
% R840
xArithmeticIfStmt:
  xLblDef 'if' '(' Int-Real-Dp Expression[11] ')'
         xLblRef ',' xLblRef ',' xLblRef xEOS .
 
% 35
% R807
xIfStmt:
  xLblDef 'if' '(' Scalar Logical Expression[12] ')' xActionStmt .
 
% R802
xIfConstruct:
  xIfThenStmt xThenPart .
xThenPart:
  xEndIfStmt / xConditionalBody xEndIfStmt /
  xElseIfConstruct / xConditionalBody xElseIfConstruct /
  xElseConstruct / xConditionalBody xElseConstruct .
 
xElseIfConstruct:
  xElseIfStmt xThenPart .
 
xElseConstruct:
  xElseStmt xElsePart .
xElsePart:
  xEndIfStmt /
  xConditionalBody xEndIfStmt .
 
xConditionalBody:
  xExecutionPartConstruct / xConditionalBody xExecutionPartConstruct .
 
% 36
% R803
xIfThenStmt:
  xLblDef 'if' '(' Scalar Logical Expression[12] ')' 'then' xEOS .
 
% 37
% R804
xElseIfStmt:
  xLblDef 'elseif' '(' Scalar Logical Expression[12] ')' 'then' xEOS .
 
% 38
% R805
xElseStmt:
  xLblDef 'else' xEOS .
 
% 39
% R806
xEndIfStmt:
  xLblDef 'endif' xEOS.
 
% 40
% R818
xDoConstruct: xLabelDoStmt .
 
% R819
xLabelDoStmt:
  xLblDef 'do' xLblRef xCommaLoopControl xEOS .
xCommaLoopControl: ',' xLoopControl / xLoopControl .
 
% R821
xLoopControl:
  xVariableName '='
    Int-Real-Dp Expression[11] ',' Int-Real-Dp Expression[11] /
  xVariableName '='
    Int-Real-Dp Expression[11] ',' Int-Real-Dp Expression[11] ','
    Int-Real-Dp Expression[11] .
 
% 41
% R841
xContinueStmt:
  xLblDef 'continue' xEOS .
 
% 42
% R842
xStopStmt:
  xLblDef 'stop' xEOS /
  xLblDef 'stop' xIcon xEOS /
  xLblDef 'stop' xScon xEOS .
 
% 43
% R844
xPauseStmt:
  xLblDef 'pause' xEOS /
  xLblDef 'pause' xIcon xEOS /
  xLblDef 'pause' xScon xEOS .
 
% 44
xWriteStmt:
  xLblDef 'write' '(' xIoControlSpecList ')' xOutputItemList xEOS /
  xLblDef 'write' '(' xIoControlSpecList ')' xEOS .
 
% 45
xReadStmt:
  xLblDef 'read' xRdCtlSpec xInputItemList xEOS /
  xLblDef 'read' xRdCtlSpec xEOS /
  xLblDef 'read' xRdFmtId ',' xInputItemList xEOS /
  xLblDef 'read' xRdFmtId xEOS .
xRdCtlSpec: xRdUnitId / '(' xRdIoCtlSpecList ')' .
xRdUnitId: '(' xUFExpr ')' / '(' '*' ')' .
xRdIoCtlSpecList:
  xUnitIdentifier ',' xIoControlSpec /
  xUnitIdentifier ',' xFormatIdentifier /
  xIoControlSpec /
  xRdIoCtlSpecList ',' xIoControlSpec .
xRdFmtId:
  xLblRef / '*' / xCOperand /
  xCOperand xConcatOp xCPrimary /
  xRdFmtIdExpr xConcatOp xCPrimary .
xRdFmtIdExpr: '(' xUFExpr ')' .
 
% 46
xPrintStmt:
  xLblDef 'print' xFormatIdentifier ',' xOutputItemList xEOS /
  xLblDef 'print' xFormatIdentifier xEOS .
 
% 47
xIoControlSpecList:
  xUnitIdentifier $',' /
  xUnitIdentifier ',' xFormatIdentifier /
  xUnitIdentifier ',' xIoControlSpec /
  xIoControlSpec /
  xIoControlSpecList ',' xIoControlSpec .
 
% R912
xIoControlSpec:
  'fmt=' xFormatIdentifier /
  'unit=' xUnitIdentifier /
  'rec=' xExpr /
  'end=' xLblRef /
  'err=' xLblRef /
  'iostat=' xScalarVariable .
 
% 48
% R914
xInputItemList: xInputItem / xInputItemList ',' xInputItem .
xInputItem: xVariable / xInputImpliedDo .
 
% R915
xOutputItemList: xExpr / xOutputItemList1 .
xOutputItemList1:
  xExpr ',' xExpr /
  xExpr ',' xOutputImpliedDo /
  xOutputImpliedDo /
  xOutputItemList1 ',' xExpr /
  xOutputItemList1 ',' xOutputImpliedDo .
 
% 49
% R916
xInputImpliedDo:
  '(' xInputItemList ',' xImpliedDoVariable '=' xExpr ',' xExpr ')' /
  '(' xInputItemList ',' xImpliedDoVariable '=' xExpr ',' xExpr ',' xExpr ')' .
 
xOutputImpliedDo:
  '(' xExpr ',' xImpliedDoVariable '=' xExpr ',' xExpr ')' /
  '(' xExpr ',' xImpliedDoVariable '=' xExpr ',' xExpr ',' xExpr ')' /
  '(' xOutputItemList1 ',' xImpliedDoVariable '=' xExpr ',' xExpr ')' /
  '(' xOutputItemList1 ',' xImpliedDoVariable '=' xExpr ',' xExpr
    ',' xExpr ')' .
 
 
% 50
xOpenStmt:
  xLblDef 'open' '(' xConnectSpecList ')' xEOS .
 
% R905
xConnectSpecList:
  xUnitIdentifier /
  xConnectSpec / xConnectSpecList ',' xConnectSpec .
xConnectSpec:
  'unit=' xUnitIdentifier /
  'err=' xLblRef /
  'file=' xCExpr /
  'status=' xCExpr /
  'access=' xCExpr /
  'form=' xCExpr /
  'recl=' xExpr /
  'blank=' xCExpr /
  'iostat=' xScalarVariable .
 
% 51
xCloseStmt:
  xLblDef 'close' '(' xCloseSpecList ')' xEOS .
 
% R908
xCloseSpecList:
  xUnitIdentifier /
  xCloseSpec / xCloseSpecList ',' xCloseSpec .
xCloseSpec:
  'unit=' xUnitIdentifier /
  'err=' xLblRef /
  'status=' xCExpr /
  'iostat=' xScalarVariable .
 
% 52
% R923
xInquireStmt:
  xLblDef 'inquire' '(' xInquireSpecList ')' xEOS .
 
% R924
xInquireSpecList:
  xUnitIdentifier /
  xInquireSpec / xInquireSpecList ',' xInquireSpec .
xInquireSpec:
  'unit=' xUnitIdentifier /
  'file=' xCExpr /
  'err=' xLblRef /
  'iostat=' xScalarVariable /
  'exist=' xScalarVariable /
  'opened=' xScalarVariable /
  'number=' xScalarVariable /
  'named=' xScalarVariable /
  'name=' xScalarVariable /
  'access=' xScalarVariable /
  'sequential=' xScalarVariable /
  'direct=' xScalarVariable /
  'form=' xScalarVariable /
  'formatted=' xScalarVariable /
  'unformatted=' xScalarVariable /
  'recl=' xExpr /
  'nextrec=' xScalarVariable /
  'blank=' xScalarVariable .
 
% 53
% R919
xBackspaceStmt:
  xLblDef 'backspace' xUnitIdentifier xEOS /
  xLblDef 'backspace' '(' xPositionSpecList ')' xEOS .
 
% 54
% R920
xEndfileStmt:
  xLblDef 'endfile' xUnitIdentifier xEOS /
  xLblDef 'endfile' '(' xPositionSpecList ')' xEOS .
 
% 55
% R921
xRewindStmt:
  xLblDef 'rewind' xUnitIdentifier xEOS /
  xLblDef 'rewind' '(' xPositionSpecList ')' xEOS .
 
% R922
xPositionSpecList:
  xUnitIdentifier ',' xPositionSpec / xPositionSpec /
  xPositionSpecList ',' xPositionSpec .
xPositionSpec:
  'unit=' xUnitIdentifier /
  'err=' xLblRef /
  'iostat=' xScalarVariable .
 
% 56
xUnitIdentifier: xUFExpr / '*' .
 
% 57
xFormatIdentifier: xLblRef / xCExpr / '*' .
 
% 58-59
xFormatStmt:
  xLblDef 'format' '(' xFmtSpec ')' xEOS .
 
% 60
xFmtSpec:
  xFormatedit / xFormatsep / xFormatsep xFormatedit /
  xFmtSpec xFormatsep /
  xFmtSpec xFormatsep xFormatedit /
  xFmtSpec ',' xFormatedit /
  xFmtSpec ',' xFormatsep /
  xFmtSpec ',' xFormatsep xFormatedit .
xFormatedit:
  xEditElement / xIcon xEditElement / xXcon /
  xPcon / xPcon xEditElement / xPcon xIcon xEditElement .
xEditElement:
  xFcon / xScon / xHcon / xIdent / '(' xFmtSpec ')' .
xFormatsep: '/' / ':' .
 
% 61 recognized by the lexical analyzer as xIcon
 
% 62 recognized by the lexical analyzer in the context of xIdent or xFcon
 
% 63 recognized by the lexical analyzer in the context of xFcon
 
% 64 recognized by the lexical analyzer in the context of xHcon or xXcon
 
% 65 recognized by the lexical analyzer in the context of xIdent
 
% 66-67 recognized by the lexical analyzer in the context of xFcon
 
% 68 recognized by the lexical analyzer in the context of xPcon
 
% 69 recognized by the lexical analyzer in the context of xScon or xHcon
 
% 70
/* This may turn out to be an assignment statement, but the form given here
 * allows for name analysis in the case that it actually IS a statement
 * function definition.
 */
xStmtFunctionStmt: xLblDef xName xStmtFunctionRange .
xStmtFunctionRange: '(' ')' '=' xExpr xEOS .
xStmtFunctionRange: '(' xSFDummyArgNameList ')' '=' xExpr xEOS .
xSFDummyArgNameList:
  xSFDummyArgName / xSFDummyArgNameList ',' xSFDummyArgName .
 
% 71
xCallStmt:
  xLblDef 'call' xSubroutineNameUse xEOS /
  xLblDef 'call' xSubroutineNameUse '(' xSubroutineArgList ')' xEOS .
xSubroutineArgList: / xSubroutineArg / xSubroutineArgList ',' xSubroutineArg .
xSubroutineArg: xExpr / xHcon / '*' xLblRef .
 
% 72
xReturnStmt:
  xLblDef 'return' xEOS /
  xLblDef 'return' xExpr xEOS .
 
% 73
xFunctionReference: xName '(' ')' .
 
xComplexDataRef:
  xName  '(' xSectionSubscriptList ')' /
  xComplexDataRef '(' xSectionSubscriptList ')' .
xSectionSubscriptList:
  xSectionSubscript / xSectionSubscriptList ',' xSectionSubscript .
xSectionSubscript: xExpr / xSubscriptTriplet .
 
% 74-75
% R723
xExpr: xLevel5Expr .
 
% 76-81
% R701
xPrimary:
  xUnsignedArithmeticConstant /
  xName /
  xComplexDataRef /
  xFunctionReference /
  '(' xExpr ')' .
 
% R703
xLevel1Expr: xPrimary .
 
% R705
xMultOperand: xLevel1Expr [xPowerOp xMultOperand] .
 
% R706
xAddOperand: [xAddOperand xMultOp] xMultOperand .
 
% R707
xLevel2Expr:
  [xLevel2Expr xAddOp] xAddOperand /
  xSign xAddOperand .   % We need to distinguish unary operators
 
% R708
xPowerOp: '**' .
 
% R709
xMultOp: '*' / '/' .
 
% R710
xAddOp: '+' / '-' .
xSign: '+' / '-' .
 
xUFExpr: xUFTerm / xSign xUFTerm / xUFExpr xAddOp xUFTerm .
xUFTerm: xUFFactor / xUFTerm xMultOp xUFFactor / xUFTerm xConcatOp xUFPrimary .
xUFFactor: xUFPrimary / xUFPrimary xPowerOp xUFFactor .
xUFPrimary:
  xIcon /
  xScon /
  xName /
  xFunctionReference /
  xComplexDataRef /
  '(' xUFExpr ')' .
 
% 82,83
xCExpr: [xCExpr xConcatOp] xCPrimary .
xCPrimary: xCOperand / '(' xCExpr ')' .
xCOperand:
  xScon /
  xName /
  xComplexDataRef /
  xFunctionReference .
 
xPrimary:
  xScon .
 
% R711
xLevel3Expr: [xLevel3Expr xConcatOp] xLevel2Expr .
 
% R712
xConcatOp: '//' .
 
% 84,85
% R715
xAndOperand: [xNotOp] xLevel4Expr .
 
% R716
xOrOperand: [xOrOperand xAndOp] xAndOperand .
 
% R717
xEquivOperand: [xEquivOperand xOrOp] xOrOperand .
 
% R718
xLevel5Expr: [xLevel5Expr xEquivOp] xEquivOperand .
 
% R719
xNotOp: '.not.' .
 
% R720
xAndOp: '.and.' .
 
% R721
xOrOp: '.or.' .
 
% R722
xEquivOp: '.eqv.' / '.neqv.' .
 
xPrimary: xLogicalConstant .
 
% 86
xLevel4Expr: [xLevel3Expr xRelOp] xLevel3Expr .
 
% 87
xRelOp: '.eq.' / '.ne.' / '.lt.' / '.le.' / '.gt.' / '.ge.' .
 
% 88
xArrayElement: xVariableName '(' xSectionSubscriptList ')' .
 
% 89
xSubstringRange: '(' xSubscriptTriplet ')' .
xSubscriptTriplet:
  ':' /
  ':' xExpr /
  xExpr ':' /
  xExpr ':' xExpr .
 
% 90-99
xName: xIdent .
 
% 100
xConstant:
  xNamedConstantUse /
  xUnsignedArithmeticConstant /
  '+' xUnsignedArithmeticConstant /
  '-' xUnsignedArithmeticConstant /
  xScon / xHcon /
  xLogicalConstant .
 
% 101
xUnsignedArithmeticConstant:
  xIcon / xRcon / xDcon / xComplexConst .
 
% 102 recognized by the lexical analyzer as xIcon
 
% 103 parsed as 102, distinguished semantically
 
% 104 recognized by the lexical analyzer in the context of 68, 105 or 106
 
% 105 recognized by the lexical analyzer as xRcon
 
% 106 recognized by the lexical analyzer as xDcon
 
% 107
xComplexConst: '(' xExpr ',' xExpr ')' .
 
% 108
xLogicalConstant: '.true.' / '.false.' .
 
% 109 recognized by the lexical analyzer as xScon
 
% 110
xLabel: xIcon .
 
% 111-116 are components of symbols recognized by the lexical analyzer
 
/* Nonterminal symbols that are not defined in the standard
 */
 
xBlockDataName: xIdent .
xCommonBlockName: xIdent .
xDummyArgName: xIdent .
xEntryName: xIdent .
xExternalName: xIdent .
xFunctionName: xIdent .
xImpliedDoVariable: xIdent .
xIntrinsicProcedureName: xIdent .
xObjectName: xIdent .
xProgramName: xIdent .
xSFDummyArgName: xIdent .
xSFVarName: xIdent $',' $')' .
xSubroutineName: xIdent .
xSubroutineNameUse: xIdent .
xVariableName: xIdent .
 
xScalarVariable: xVariableName / xArrayElement .
xVariable:
  xVariableName /
  xVariableName '(' xSubscriptList ')' /
  xVariableName xSubstringRange /
  xVariableName '(' xSubscriptList ')' xSubstringRange .
xSubscriptList:
  xSubscript / xSubscriptList ',' xSubscript .
xSubscript: xExpr .
 
xLblDef: / xLabel .

Fortran 90特有的产生式规则

% R201 see 1
 
% R202 see 1
xProgramUnit: xModule .
 
% R203 chain rule omitted
 
% R204 see 2
xSpecificationPartConstruct: xUseStmt .
 
% R205 see 2
 
% R206 see 2
 
% R207 see 2
xDeclarationConstruct: xDerivedTypeDef / xInterfaceBlock .
 
% R208 see 2
 
% R209 see 2
  
% R210
xBodyPlusInternals:
  xBody xContainsStmt xInternalSubprogram /
  xContainsStmt xInternalSubprogram /
  xBodyPlusInternals xInternalSubprogram .
 
% R211
xInternalSubprogram:
  xFunctionSubprogram / xSubroutineSubprogram .
 
% R212
xModuleSubprogramPartConstruct:
  xContainsStmt / xModuleSubprogram .
 
% R213
xModuleSubprogram:
  xFunctionSubprogram / xSubroutineSubprogram .
 
% R214 see 6
xSpecificationStmt:
  xAccessStmt /
  xAllocatableStmt /
  xIntentStmt /
  xNamelistStmt /
  xOptionalStmt /
  xPointerStmt /
  xTargetStmt .
 
% R215 see 7
xExecutableConstruct:
  xCaseConstruct /
  xWhereConstruct /
  xEndDoStmt .          /* see the note on R818 */
 
% R216 see 7
xActionStmt:
  xAllocateStmt /
  xCycleStmt /
  xDeallocateStmt /
  xExitStmt /
  xNullifyStmt /
  xPointerAssignmentStmt /
  xWhereStmt.
 
% R301-R304 are components of symbols recognized by the lexical analyzer
 
% R305 chain rules deleted
 
% R306 recognized by the lexical analyzer
 
% R307 see 23
 
% R308 chain rule deleted
 
% R309 chain rule deleted
 
% R310 recognized semantically
 
% R311
xDefinedOperator:
  xDop /
  xPowerOp / xMultOp / xAddOp / xRelOp / xNotOp / xAndOp / xOrOp / xEquivOp .
 
% R401 recognized by the lexical analyzer in the context of R413
 
% R402 recognized by the lexical analyzer in the context of R413, xIcon
 
% R404 see 101
xUnsignedArithmeticConstant: xIcon '_' xKindParam .
 
% R405
xKindParam: xIcon / xNamedConstantUse .
 
% R406 see 100
 
% R407
xBozLiteralConstant: xBcon / xOcon / xZcon .
 
% R408 recognized by the lexical analyzer as xBcon
 
% R409 recognized by the lexical analyzer as xOcon
 
% R410 recognized by the lexical analyzer as xZcon
 
% R411 component of a symbol recognized by the lexical analyzer
 
% R412 see 100
 
% R413 see 100
xUnsignedArithmeticConstant: xRcon '_' xKindParam / xDcon '_' xKindParam .
 
% R414-R416 components of symbols recognized by the lexical analyzer
 
% R417 see 107
 
% R418 chain rule deleted
 
% R419 chain rule deleted
 
% R420 see 100
xConstant:
  xIcon '_' xScon / xNamedConstantUse '_' xScon .
 
% R421 see 108
xLogicalConstant:
  '.true.' '_' xKindParam / '.false.' '_' xKindParam .
 
% R422
xDerivedTypeDef:
  xDerivedTypeStmt xDerivedTypeBody xEndTypeStmt .
xDerivedTypeBody:
  xDerivedTypeBodyConstruct / xDerivedTypeBody xDerivedTypeBodyConstruct .
xDerivedTypeBodyConstruct: xPrivateSequenceStmt / xComponentDefStmt .
 
% R423
xPrivateSequenceStmt:
  xLblDef 'private' xEOS /
  xLblDef 'sequence' xEOS .
 
% R424
xDerivedTypeStmt:
  xLblDef 'type' xTypeName xEOS /
  xLblDef 'type' ':' ':' xTypeName xEOS /
  xLblDef 'type' ',' xAccessSpec ':' ':' xTypeName xEOS .
 
% R425
xEndTypeStmt:
  xLblDef 'endtype' xTypeName xEOS /
  xLblDef 'endtype' xEOS /
  xLblDef 'end' 'type' xTypeName xEOS /
  xLblDef 'end' 'type' xEOS .
 
% R426
xComponentDefStmt:
  xLblDef xTypeSpec ',' xComponentAttrSpecList ':' ':' xComponentDeclList xEOS /
  xLblDef xTypeSpec ':' ':' xComponentDeclList xEOS /
  xLblDef xTypeSpec xComponentDeclList xEOS .
 
% R427
xComponentAttrSpecList:
  xComponentAttrSpec / xComponentAttrSpecList ',' xComponentAttrSpec .
xComponentAttrSpec:
  'pointer' / 'dimension' '(' xComponentArraySpec ')' .
 
% R428
xComponentArraySpec: xExplicitShapeSpecList / xDeferredShapeSpecList .
 
% R429
xComponentDeclList:
  xComponentDecl / xComponentDeclList ',' xComponentDecl .
xComponentDecl:
  xComponentName '(' xComponentArraySpec ')' '*' xCharLength /
  xComponentName '(' xComponentArraySpec ')' /
  xComponentName '*' xCharLength /
  xComponentName .
 
% R430
xStructureConstructor: xTypeName '(' xExprList ')' .
xExprList: xExpr / xExprList ',' xExpr .
 
% R431
xArrayConstructor: '(/' xAcValueList '/)' .
 
% R432
xAcValueList: xExpr / xAcValueList1 .
xAcValueList1:
  xExpr ',' xExpr /
  xExpr ',' xAcImpliedDo /
  xAcImpliedDo /
  xAcValueList1 ',' xExpr /
  xAcValueList1 ',' xAcImpliedDo .
 
% R433
xAcImpliedDo:
  '(' xExpr ',' xImpliedDoVariable '=' xExpr ',' xExpr ')' /
  '(' xExpr ',' xImpliedDoVariable '=' xExpr ',' xExpr ',' xExpr ')' /
  '(' xAcImpliedDo ',' xImpliedDoVariable '=' xExpr ',' xExpr ')' /
  '(' xAcImpliedDo ',' xImpliedDoVariable '=' xExpr ',' xExpr ',' xExpr ')' .
 
% R434 chain rule deleted
 
% R435 chain rule deleted
 
% R501 see 20
xTypeDeclarationStmt:
  xLblDef xTypeSpec xAttrSpecSeq ':' ':' xEntityDeclList xEOS /
  xLblDef xTypeSpec ':' ':' xEntityDeclList xEOS .
xAttrSpecSeq: ',' xAttrSpec / xAttrSpecSeq ',' xAttrSpec .
 
% R502 see 20
xTypeSpec:
  'integer' xKindSelector /
  'real' xKindSelector /
  'double' 'precision' /
  'complex' xKindSelector /
  'character' xCharSelector /
  'logical' xKindSelector /
  'type' '(' xTypeName ')' .
 
% R503
xAttrSpec:
  'parameter' /
  xAccessSpec /
  'allocatable' /
  'dimension' '(' xArraySpec ')' /
  'external' /
  'intent' '(' xIntentSpec ')' /
  'intrinsic' /
  'optional' /
  'pointer' /
  'save' /
  'target' .
 
% R504 see 20
xEntityDecl:
  xObjectName '=' xExpr /
  xObjectName '(' xArraySpec ')' '=' xExpr /
  xObjectName '*' xCharLength '=' xExpr /
  xObjectName '*' xCharLength '(' xArraySpec ')' '=' xExpr .
 
% R505
xKindSelector: '(' 'kind=' xExpr ')' / '(' xExpr ')' .
 
% R506 see 20
% R507 see 20
xCharSelector:
  '(' 'len=' xTypeParamValue ',' 'kind=' xExpr ')' /
  '(' 'len=' xTypeParamValue ',' xExpr ')' /
  '(' 'len=' xTypeParamValue ')' /
  '(' 'kind=' xExpr ')' /
  '(' xExpr ')' .
 
% R508 see 22
 
% R509 see 22
 
% R510
xAccessSpec:
  'public' / 'private' .
 
% R511
xIntentSpec:
  'in' / 'out' / 'inout' .
 
% R512 see 16
xArraySpec:
   xAssumedShapeSpecList / xDeferredShapeSpecList .
xAssumedShapeSpecList:
  xLowerBound ':' /
  xDeferredShapeSpecList ',' xLowerBound ':' /
  xAssumedShapeSpecList ',' xAssumedShapeSpec .
 
% R513 see 16
 
% R514 see 16
 
% R515 see 16
 
% R516
xAssumedShapeSpec:
  xLowerBound ':' / ':' .
 
% R517
xDeferredShapeSpecList:
  xDeferredShapeSpec / xDeferredShapeSpecList ',' xDeferredShapeSpec .
xDeferredShapeSpec: ':' .
 
% R518 see 16
 
% R519
xIntentStmt:
  xLblDef 'intent' '(' xIntentSpec ')' ':' ':' xIntentParList xEOS /
  xLblDef 'intent' '(' xIntentSpec ')' xIntentParList xEOS .
xIntentParList: xIntentPar / xIntentParList ',' xIntentPar .
xIntentPar: xDummyArgName .
 
% R520
xOptionalStmt:
  xLblDef 'optional' ':' ':' xOptionalParList xEOS /
  xLblDef 'optional' xOptionalParList xEOS .
xOptionalParList: xOptionalPar / xOptionalParList ',' xOptionalPar .
xOptionalPar: xDummyArgName .
 
% R521
xAccessStmt:
  xLblDef xAccessSpec ':' ':' xAccessIdList xEOS /
  xLblDef xAccessSpec xAccessIdList xEOS /
  xLblDef xAccessSpec xEOS .
 
% R522
xAccessIdList: xAccessId / xAccessIdList ',' xAccessId .
xAccessId: xGenericName / xGenericSpec .
 
% R523 see 26
xSaveStmt:
  xLblDef 'save' ':' ':' xSavedEntityList xEOS .
 
% R524 see 26
 
% R525 see 15
xDimensionStmt:
  xLblDef 'dimension' ':' ':' xArrayDeclaratorList xEOS .
 
% R526
xAllocatableStmt:
  xLblDef 'allocatable' ':' ':' xArrayAllocationList xEOS /
  xLblDef 'allocatable' xArrayAllocationList xEOS .
xArrayAllocationList:
  xArrayAllocation / xArrayAllocationList ',' xArrayAllocation .
xArrayAllocation:
  xArrayName / xArrayName '(' xDeferredShapeSpecList ')' .
 
% R527
xPointerStmt:
  xLblDef 'pointer' ':' ':' xPointerStmtObjectList xEOS /
  xLblDef 'pointer' xPointerStmtObjectList xEOS .
xPointerStmtObjectList:
  xPointerStmtObject / xPointerStmtObjectList ',' xPointerStmtObject .
xPointerStmtObject: xObjectName / xObjectName '(' xDeferredShapeSpecList ')' .
 
% R528
xTargetStmt:
  xLblDef 'target' ':' ':' xTargetObjectList xEOS /
  xLblDef 'target' xTargetObjectList xEOS .
xTargetObjectList:
  xTargetObject / xTargetObjectList ',' xTargetObject .
xTargetObject: xObjectName / xObjectName '(' xArraySpec ')' .
 
% R529 see 27
 
% R530 see 27
 
% R531 see 27
 
% R532 see 27
 
% R533 see 100
xConstant:
  xStructureConstructor /
  xBozLiteralConstant .
 
% R534 chain rule deleted
 
% R535 see 28
 
% R536 see 28
xDataIDoObject: xStructureComponent .
 
% R537 chain rule deleted
 
% R538 see 23
 
% R539 see 23
 
% R540 see 21
xImplicitStmt:
  xLblDef 'implicit' 'none' xEOS .
 
% R541 see 21
 
% R542 see 21
 
% R543
xNamelistStmt:
  xLblDef 'namelist' xNamelistGroups xEOS .
xNamelistGroups:
  '/' xNamelistGroupName '/' xNamelistGroupObject /
  xNamelistGroups '/' xNamelistGroupName '/' xNamelistGroupObject /
  xNamelistGroups ',' '/' xNamelistGroupName '/' xNamelistGroupObject /
  xNamelistGroups ',' xNamelistGroupObject .
 
% R544
xNamelistGroupObject: xVariableName .
 
% R545 see 17
 
% R546 see 17
 
% R547 see 18
 
% R548 see 19
 
% R549 see 19
 
% R601 /* ?????????????????????? */
xComplexDataRef:
  xName '%' xName /
  xComplexDataRef '%' xName .
 
% R603-R608 chain rules deleted
 
% R609 see 89
 
% R610 see 89
 
% R611 see 89
 
% R614
xStructureComponent:
  xVariableName xFieldSelector / xStructureComponent xFieldSelector .
xFieldSelector: '(' xSectionSubscriptList ')' '%' xName / '%' xName .
 
% R615
xArrayElement:
  xStructureComponent '(' xSectionSubscriptList ')' .
 
% R619
xSubscriptTriplet:
  xExpr ':' xExpr ':' xExpr /
  xExpr ':' ':' xExpr /
  ':' xExpr ':' xExpr /
  ':' ':' xExpr .
 
% R622
xAllocateStmt:
  xLblDef 'allocate' '(' xAllocationList ',' 'stat=' xVariable ')' xEOS /
  xLblDef 'allocate' '(' xAllocationList ')' xEOS .
 
% R623 chain rule deleted
 
% R624
xAllocationList: xAllocation / xAllocationList ',' xAllocation .
xAllocation: xAllocateObject / xAllocateObject xAllocatedShape .
xAllocatedShape: '(' xSectionSubscriptList ')' .
/* Need to use xSectionSubscriptList here to solve an LALR(1) conflict with the
 * xFieldSelector in R625.  (Can't tell which we have until the character
 * following the right paren, but we must reduce WITHIN the parens.)
 */
 
% R625
xAllocateObjectList:
  xAllocateObject / xAllocateObjectList ',' xAllocateObject .
xAllocateObject:
  xVariableName / xAllocateObject xFieldSelector .
 
% R626
/* Omitted to solve LALR(1) conflict.  see R624
 *
 * xAllocateShapeSpec: xExpr / xExpr ':' xExpr .
 */
 
% R627 chain rule deleted
 
% R628 chain rule deleted
 
% R629
xNullifyStmt:
  xLblDef 'nullify' '(' xPointerObjectList ')' xEOS .
xPointerObjectList:
  xPointerObject / xPointerObjectList ',' xPointerObject .
 
% R630
xPointerObject: xName / xPointerField .
xPointerField:
  xName '(' xSFExprList ')' '%' xName /
  xName '(' xSFDummyArgNameList ')' '%' xName /
  xName '%' xName /
  xPointerField xFieldSelector .
 
% R631
xDeallocateStmt:
  xLblDef 'deallocate' '(' xAllocateObjectList',' 'stat=' xVariable ')' xEOS /
  xLblDef 'deallocate' '(' xAllocateObjectList ')' xEOS .
 
% R701 see 74-85
xPrimary:
  xArrayConstructor .
xSFPrimary:
  xArrayConstructor .
 
% R702 chain rule deleted
 
% R703
xLevel1Expr:
  xDefinedUnaryOp xPrimary .
 
% R704
xDefinedUnaryOp:
  xDop .
 
% R708 see 74-81
 
% R709 see 74-81
 
% R710 see 74-81
 
% R712 see 82,83
 
% R714 see 87
xRelOp: '==' / '/=' / '<' / '<=' / '>' / '>=' .
 
% R719 see 84,85
 
% R720 see 84,85
 
% R721 see 84,85
 
% R722 see 84,85
 
% R723
xExpr:
  xExpr xDefinedBinaryOp xLevel5Expr .
 
% R724
xDefinedBinaryOp:
  xDop .
 
% R725-R734 chain rule deleted
 
% R735 see 29
xAssignmentStmt:
  xLblDef xName '%' xName '=' xExpr xEOS /
  xLblDef xName '%' xComplexDataRef '=' xExpr xEOS /
  xLblDef xName '(' xSFExprList ')' '%' xName '=' xExpr xEOS /
  xLblDef xName '(' xSFExprList ')' '%' xComplexDataRef '=' xExpr xEOS /
  xLblDef xName '(' xSFDummyArgNameList ')' '%' xName '=' xExpr xEOS /
  xLblDef xName '(' xSFDummyArgNameList ')' '%' xComplexDataRef '=' xExpr xEOS .
 
xSFExprList:
  xSFExpr ':' xExpr ':' xExpr /
  xSFExpr ':' ':' xExpr /
  ':' xExpr ':' xExpr /
  ':' ':' xExpr .
 
% R736
xPointerAssignmentStmt:
  xLblDef xName '=>' xTarget xEOS /
  xLblDef xName '%' xName '=>' xTarget xEOS /
  xLblDef xName '%' xComplexDataRef '=>' xTarget xEOS /
  xLblDef xName '(' xSFExprList ')' '%' xName '=>' xTarget xEOS /
  xLblDef xName '(' xSFExprList ')' '%' xComplexDataRef '=>' xTarget xEOS /
  xLblDef xName '(' xSFDummyArgNameList ')' '%' xName '=>' xTarget xEOS /
  xLblDef xName '(' xSFDummyArgNameList ')' '%' xComplexDataRef '=>'
    xTarget xEOS .
 
% R737
xTarget: xExpr .
 
% R738
xWhereStmt:
  xLblDef 'where' '(' xMaskExpr ')' xAssignmentStmt .
 
% R739
xWhereConstruct:
  xWhere xEndWhereStmt /
  xElseWhere xEndWhereStmt .
xWhere: xWhereConstructStmt / xWhere xAssignmentStmt .
xElseWhere: xWhere xElsewhereStmt / xElseWhere xAssignmentStmt .
 
% R740
xWhereConstructStmt:
  xLblDef 'where' '(' xMaskExpr ')' xEOS .
 
% R741
xMaskExpr: xExpr .
 
% R742
xElsewhereStmt:
  xLblDef 'elsewhere' xEOS .
 
% R743
xEndWhereStmt:
  xLblDef 'endwhere' xEOS /
  xLblDef 'end' 'where' xEOS .
 
% R801 see the note on R818
 
% R802 see 35
 
% R803 see 36
 
% R804 see 37
xElseIfStmt:
  xLblDef 'else' 'if' '(' xExpr ')' 'then' xEOS .
 
% R805 see 38
 
% R806 see 39
xEndIfStmt:
  xLblDef 'end' 'if' xEOS .
 
% R807 see 35
 
% R808
xCaseConstruct:
  xLblDef xName ':' 'selectcase' '(' xExpr ')' xEOS xSelectCaseRange /
  xLblDef 'selectcase' '(' xExpr ')' xEOS xSelectCaseRange /
  xLblDef xName ':' 'select' 'case' '(' xExpr ')' xEOS xSelectCaseRange /
  xLblDef 'select' 'case' '(' xExpr ')' xEOS xSelectCaseRange .
xSelectCaseRange:
  xSelectCaseBody xEndSelectStmt /
  xEndSelectStmt .
 
xSelectCaseBody:
  xCaseStmt / xSelectCaseBody xCaseBodyConstruct .
xCaseBodyConstruct:
  xCaseStmt / xExecutionPartConstruct .
 
% R810
xCaseStmt:
  xLblDef 'case' xCaseSelector xEOS /
  xLblDef 'case' xCaseSelector xName xEOS .
 
% R811
xEndSelectStmt:
  xLblDef 'endselect' [xEndName] xEOS /
  xLblDef 'end' 'select' [xEndName] xEOS .
 
% R812 chain rules deleted
 
% R813
xCaseSelector: '(' xCaseValueRangeList ')' / 'default' .
xCaseValueRangeList:
  xCaseValueRange / xCaseValueRangeList ',' xCaseValueRange .
 
% R814
xCaseValueRange:
   xExpr / xExpr ':' / ':' xExpr / xExpr ':' xExpr .
 
% R815 chain rules deleted
 
% R816 see 40
xDoConstruct: xBlockDoConstruct .
 
% R817
/* Block DO constructs cannot be recognized syntactically because there is
 * no requirement that there be an end do statement.
 *
 * xBlockDoConstruct:
 *   xDoStmt xBlock xEndDoStmt /
 *   xDoStmt xBlock .
 */
 
% R818
xBlockDoConstruct:
  xLblDef 'do' xLblRef xEOS /
  xLblDef 'do' xCommaLoopControl xEOS /
  xLblDef 'do' xEOS /
  xLblDef xName ':' 'do' xLblRef xCommaLoopControl xEOS /
  xLblDef xName ':' 'do' xLblRef xEOS /
  xLblDef xName ':' 'do' xCommaLoopControl xEOS /
  xLblDef xName ':' 'do' xEOS .
 
% R819 chain rule deleted
 
% R820 chain rule deleted
 
% R821 see 40
xLoopControl: 'while' '(' xExpr ')' .
 
% R822 chain rule deleted
 
% R823 chain rule deleted
 
% R824 see note on R818
 
% R825
xEndDoStmt:
  xLblDef 'enddo' [xEndName] xEOS /
  xLblDef 'end' 'do' [xEndName] xEOS .
 
% R826-R833 enforced semantically
 
% R834
xCycleStmt:
  xLblDef 'cycle' [xEndName] xEOS .
 
% R835
xExitStmt:
  xLblDef 'exit' [xEndName] xEOS .
 
% R836 see 31
GoToKw: 'go' 'to' .
 
% R837 see 32
 
% R838 see 29
 
% R839 see 33
 
% R840 see 34
 
% R841 see 41
 
% R842 see 42
 
% R843 see 42
 
% R901 see 56
 
% R902 chain rule deleted
 
% R903 chain rule deleted
 
% R904 see 50
 
% R905 see 50
xConnectSpec:
  'position=' xCExpr /
  'action=' xCExpr /
  'delim=' xCExpr /
  'pad=' xCExpr .
 
% R906 chain rule deleted
 
% R907 see 51
 
% R908 see 51
 
% R909 see 45
 
% R910 see 44
 
% R911 see 46
 
% R912 see 46
xIoControlSpec:
  'nml=' xNamelistGroupName /
  'advance=' xCExpr /
  'size=' xVariable /
  'eor=' xLblRef .
 
% R913 see 57
 
% R920 see 54
xEndfileStmt:
  xLblDef 'end' 'file' xUnitIdentifier xEOS /
  xLblDef 'end' 'file' '(' xPositionSpecList ')' xEOS .
 
% R923 see 52
xInquireStmt:
  xLblDef 'inquire' '(' 'iolength=' xScalarVariable ')' xOutputItemList xEOS .
 
% R924 see 52
xInquireSpec:
  'position=' xScalarVariable /
  'action=' xScalarVariable /
  'read=' xScalarVariable /
  'write=' xScalarVariable /
  'readwrite=' xScalarVariable /
  'delim=' xScalarVariable /
  'pad=' xScalarVariable .
 
% R1101 see 2
xMainRange: xBodyPlusInternals xEndProgramStmt .
 
% R1102 see 8
 
% R1103
xEndProgramStmt:
  xLblDef 'endprogram' [xEndName] xEOS /
  xLblDef 'end' 'program' [xEndName] xEOS .
 
% R1104
xModule:
  xModuleStmt xModuleBody xEndModuleStmt /
  xModuleStmt xEndModuleStmt .
xModuleBody:
  xSpecificationPartConstruct /
  xModuleSubprogramPartConstruct /
  xModuleBody xSpecificationPartConstruct /
  xModuleBody xModuleSubprogramPartConstruct .
 
% R1105
xModuleStmt:
  xLblDef 'module' xModuleName xEOS .
 
% R1106
xEndModuleStmt:
  xLblDef 'endmodule' [xEndName] xEOS /
  xLblDef 'end' 'module' [xEndName] xEOS /
  xLblDef 'end' xEOS .
 
% R1107
xUseStmt:
  xLblDef 'use' xName xEOS /
  xLblDef 'use' xName ',' 'only' ':' xEOS /
  xLblDef 'use' xName ',' xRenameList xEOS /
  xLblDef 'use' xName ',' 'only' ':' xOnlyList xEOS .
xRenameList: xRename / xRenameList ',' xRename .
xOnlyList: xOnly / xOnlyList ',' xOnly .
 
% R1108
xRename: xIdent '=>' xUseName .
 
% R1109
xOnly: xGenericSpec / xIdent '=>' xUseName / xUseName .
 
% R1110 see 5
 
% R1111 see 14
 
% R1112
xEndBlockDataStmt:
  xLblDef 'endblockdata' [xEndName] xEOS /
  xLblDef 'end' 'blockdata' [xEndName] xEOS /
  xLblDef 'endblock' 'data' [xEndName] xEOS /
  xLblDef 'end' 'block' 'data' [xEndName] xEOS .
 
% R1201
xInterfaceBlock:
  xInterfaceStmt xInterfaceBlockBody xEndInterfaceStmt .
xInterfaceBlockBody:
  xInterfaceBodyPartConstruct /
  xInterfaceBlockBody xInterfaceBodyPartConstruct .
xInterfaceBodyPartConstruct: xInterfaceBody / xModuleProcedureStmt .
 
% R1202
xInterfaceStmt:
  'interface' xGenericName xEOS /
  'interface' xGenericSpec xEOS /
  'interface' xEOS .
 
% R1203
xEndInterfaceStmt:
  xLblDef 'endinterface' xEOS /
  xLblDef 'end' 'interface' xEOS .
 
% R1204
xInterfaceBody:
  xLblDef xFunctionPrefix xFunctionName xFunctionInterfaceRange /
  xLblDef 'subroutine' xSubroutineName xSubroutineInterfaceRange .
xFunctionInterfaceRange:
  xFunctionParList xEOS xSubprogramInterfaceBody xEndFunctionStmt /
  xFunctionParList xEOS xEndFunctionStmt .
xSubroutineInterfaceRange:
  xSubroutineParList xEOS xSubprogramInterfaceBody xEndSubroutineStmt /
  xSubroutineParList xEOS xEndSubroutineStmt .
xSubprogramInterfaceBody:
  xSpecificationPartConstruct /
  xSubprogramInterfaceBody xSpecificationPartConstruct .
 
% R1205
xModuleProcedureStmt:
  xLblDef 'module' 'procedure' xProcedureNameList xEOS .
xProcedureNameList:
  xProcedureName / xProcedureNameList ',' xProcedureName .
xProcedureName: xIdent .
 
% R1206
xGenericSpec:
  'operator' '(' xDefinedOperator ')' /
  'assignment' '(' '=' ')' .
 
% R1207 see 24
 
% R1208 see 25
 
% R1209 see 73
xFunctionReference: xName '(' xFunctionArgList ')' .
 
% R1210 see 71
 
% R1211
xFunctionArgList:
  xFunctionArg /
  xFunctionArgList ',' xFunctionArg /
  xSectionSubscriptList ',' xFunctionArg .
xFunctionArg: xName '=' xExpr .
xSubroutineArg: xName '=' xExpr / xName '=' xHcon / xName '=' '*' xLblRef .
 
% R1212 chain rule deleted
 
% R1213 chain rule deleted
 
% R1214 chain rule deleted
 
% R1215 see 3
xFunctionRange:
  xFunctionParList 'result' '(' xName ')' xEOS xBodyPlusInternals
    xEndFunctionStmt /
  xFunctionParList 'result' '(' xName ')' xEOS xBody xEndFunctionStmt /
  xFunctionParList 'result' '(' xName ')' xEOS xEndFunctionStmt /
  xFunctionParList xEOS xBodyPlusInternals xEndFunctionStmt .
 
% R1216 see 10
 
% R1217 see 10
xFunctionPrefix:
  'recursive' 'function' /
  'recursive' xTypeSpec 'function' /
  xTypeSpec 'recursive' 'function' .
 
% R1218
xEndFunctionStmt:
  xLblDef 'endfunction' [xEndName] xEOS /
  xLblDef 'end' 'function' [xEndName] xEOS .
 
% R1219 see 4
xSubroutineSubprogram:
  xLblDef 'recursive' 'subroutine' xSubroutineName xSubroutineRange .
xSubroutineRange:
  xSubroutineParList xEOS xBodyPlusInternals xEndSubroutineStmt .
 
% R1220 see 12
 
% R1221 see 12
 
% R1222
xEndSubroutineStmt:
  xLblDef 'endsubroutine' [xEndName] xEOS /
  xLblDef 'end' 'subroutine' [xEndName] xEOS .
 
% R1223 see 13
xEntryStmt:
  xLblDef 'entry' xEntryName xSubroutineParList 'result' '(' xName ')' xEOS .
 
% R1224 see 72
 
% R1225
xContainsStmt:
  xLblDef 'contains' xEOS.
 
% R1226 see 70
 
/* Nonterminal symbols that are not defined in the standard
 */
 
xArrayName: xIdent .
xComponentName: xIdent .
xGenericName: xIdent .
xModuleName: xIdent .
xNamelistGroupName: xIdent .
xUseName: xIdent .
xTypeName: xIdent .
xEndName: xIdent .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MorleyOlsen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值