Documentation
¶
Overview ¶
Example (ParseAndPrintAST) ¶
Example_parseAndPrintAST demonstrates parsing a simple Fortran program and printing its Abstract Syntax Tree (AST) in a visual format.
package main
import (
"fmt"
"strings"
"github.com/soypat/go-fortran"
"github.com/soypat/go-fortran/ast"
)
func main() {
// Sample Fortran 90 program
src := `
PROGRAM hello
IMPLICIT NONE
INTEGER :: x, y
REAL :: result
x = 10
y = 20
result = x + y
PRINT *, 'Result:', result
END PROGRAM hello
`
// Create parser and parse the program
var parser fortran.Parser90
err := parser.Reset("example.f90", strings.NewReader(src))
if err != nil {
fmt.Println("Error:", err)
return
}
// Parse the first program unit
unit := parser.ParseNextProgramUnit()
if !unit.IsValid() {
fmt.Println("No program unit found")
return
}
// Check for parsing errors
if len(parser.Errors()) > 0 {
fmt.Println("Parse errors:")
for _, e := range parser.Errors() {
fmt.Println(" ", e)
}
return
}
// Print the AST in a visual tree format
fmt.Println("Abstract Syntax Tree:")
fmt.Println("=====================")
ast.Print(unit)
// TODO: fix this after transpiler totally finished and not expected to change.
// OMIT Output for now:
// Abstract Syntax Tree:
// =====================
// ProgramBlock {
// Name: "hello"
// Body: ast.Statement (len=7) [
// 0: ImplicitStatement {
// IsNone: true
// Label: ""
// Position: Position {
// Start: 19
// End: 32
// }
// }
// 1: TypeDeclaration {
// TypeSpec: "INTEGER"
// Entities: ast.DeclEntity (len=2) [
// 0: DeclEntity {
// Name: "x"
// Initializer: ""
// }
// 1: DeclEntity {
// Name: "y"
// Initializer: ""
// }
// ]
// Label: ""
// Position: Position {
// Start: 35
// End: 50
// }
// }
// 2: TypeDeclaration {
// TypeSpec: "REAL"
// Entities: ast.DeclEntity (len=1) [
// 0: DeclEntity {
// Name: "result"
// Initializer: ""
// }
// ]
// Label: ""
// Position: Position {
// Start: 53
// End: 67
// }
// }
// 3: AssignmentStmt {
// Target: Identifier {
// Value: "x"
// Position: Position {
// Start: 71
// End: 72
// }
// }
// Value: IntegerLiteral {
// Value: 10
// Raw: "10"
// Position: Position {
// Start: 75
// End: 77
// }
// }
// Label: ""
// Position: Position {
// Start: 71
// End: 77
// }
// }
// 4: AssignmentStmt {
// Target: Identifier {
// Value: "y"
// Position: Position {
// Start: 80
// End: 81
// }
// }
// Value: IntegerLiteral {
// Value: 20
// Raw: "20"
// Position: Position {
// Start: 84
// End: 86
// }
// }
// Label: ""
// Position: Position {
// Start: 80
// End: 86
// }
// }
// 5: AssignmentStmt {
// Target: Identifier {
// Value: "result"
// Position: Position {
// Start: 89
// End: 95
// }
// }
// Value: BinaryExpr {
// Op: 91
// Left: Identifier {
// Value: "x"
// Position: Position {
// Start: 98
// End: 99
// }
// }
// Right: Identifier {
// Value: "y"
// Position: Position {
// Start: 102
// End: 103
// }
// }
// Position: Position {
// Start: 98
// End: 103
// }
// }
// Label: ""
// Position: Position {
// Start: 89
// End: 103
// }
// }
// 6: PrintStmt {
// Format: Identifier {
// Value: "*"
// Position: Position {
// Start: 112
// End: 112
// }
// }
// OutputList: ast.Expression (len=2) [
// 0: StringLiteral {
// Value: "Result:"
// Position: Position {
// Start: 115
// End: 122
// }
// }
// 1: Identifier {
// Value: "result"
// Position: Position {
// Start: 126
// End: 132
// }
// }
// ]
// Label: ""
// Position: Position {
// Start: 106
// End: 132
// }
// }
// ]
// Label: ""
// Position: Position {
// Start: 3
// End: 133
// }
// }
}
Output:
Example (ParseModule) ¶
Example_parseModule demonstrates parsing a Fortran module with specification statements and contained procedures.
package main
import (
"fmt"
"strings"
"github.com/soypat/go-fortran"
"github.com/soypat/go-fortran/ast"
"github.com/soypat/go-fortran/token"
)
func main() {
src := `
MODULE math_utils
IMPLICIT NONE
PRIVATE
PUBLIC :: add, multiply
INTEGER, PARAMETER :: VERSION = 1
CONTAINS
FUNCTION add(a, b) RESULT(sum)
INTEGER, INTENT(IN) :: a, b
INTEGER :: sum
sum = a + b
END FUNCTION add
FUNCTION multiply(a, b)
INTEGER :: a, b, multiply
multiply = a * b
END FUNCTION multiply
END MODULE math_utils
`
var parser fortran.Parser90
err := parser.Reset("math_utils.f90", strings.NewReader(src))
if err != nil {
fmt.Println("Error:", err)
return
}
unit := parser.ParseNextProgramUnit()
if !unit.IsValid() {
fmt.Println("No program unit found")
return
}
if len(parser.Errors()) > 0 {
fmt.Println("Parse errors:")
for _, e := range parser.Errors() {
fmt.Println(" ", e)
}
return
}
// Print just the module structure (not the full AST)
if unit.Token == token.MODULE {
mod := unit
fmt.Printf("Module: %s\n", mod.Name)
fmt.Printf(" Specification statements: %d\n", len(mod.Body))
fmt.Printf(" Contained procedures: %d\n", len(mod.Contains))
fmt.Println("\nSpecification statements:")
for i, stmt := range mod.Body {
switch s := stmt.(type) {
case *ast.ImplicitStatement:
if s.IsNone {
fmt.Printf(" %d: IMPLICIT NONE\n", i)
}
case *ast.TypeDeclaration:
fmt.Printf(" %d: %s declaration with %d entities\n", i, s.Type.Token.String(), len(s.Entities))
default:
fmt.Printf(" %d: %T\n", i, stmt)
}
}
fmt.Println("\nContained procedures:")
for i, proc := range mod.Contains {
fmt.Printf(" %d: %s %s\n", i, proc.Token.String(), proc.Name)
}
}
// omit Output:
// Module: math_utils
// Specification statements: 2
// Contained procedures: 2
//
// Specification statements:
// 0: IMPLICIT NONE
// 1: INTEGER declaration with 1 entities
//
// Contained procedures:
// 0: FUNCTION add
// 1: FUNCTION multiply
}
Output:
Example (ParseSubroutine) ¶
Example_parseSubroutine demonstrates parsing a subroutine with parameters and specification statements.
package main
import (
"fmt"
"strings"
"github.com/soypat/go-fortran"
)
func main() {
src := `
SUBROUTINE swap(a, b)
IMPLICIT NONE
REAL, INTENT(INOUT) :: a, b
REAL :: temp
temp = a
a = b
b = temp
END SUBROUTINE swap
`
var parser fortran.Parser90
parser.Reset("swap.f90", strings.NewReader(src))
sub := parser.ParseNextProgramUnit()
if !sub.IsValid() {
panic("no program unit")
}
fmt.Printf("Subroutine: %s\n", sub.Name)
// Extract parameter names
var paramNames []string
for _, p := range sub.Parameters {
paramNames = append(paramNames, p.Name)
}
fmt.Printf("Parameters: %v\n", paramNames)
fmt.Printf("Specification statements: %d\n", len(sub.Body))
}
Output: Subroutine: swap Parameters: [a b] Specification statements: 6
Index ¶
- type Lexer90
- func (l *Lexer90) AppendPositionString(b []byte) []byte
- func (l *Lexer90) Err() error
- func (l *Lexer90) IsDone() bool
- func (l *Lexer90) LineCol() (line, col int)
- func (l *Lexer90) NextToken() (tok token.Token, startPos int, literal []byte)
- func (l *Lexer90) Parens() int
- func (l *Lexer90) Pos() int
- func (l *Lexer90) PositionString() string
- func (l *Lexer90) Reset(source string, r io.Reader) error
- func (l *Lexer90) SkipLines(n int) error
- func (l *Lexer90) Source() string
- func (l *Lexer90) TokenLineCol() (line, col int)
- type Parser90
- type ParserError
- type ParserUnitData
- func (p *ParserUnitData) AltReturnCount() int
- func (p *ParserUnitData) AppendVarinfo(dst []Varinfo) []Varinfo
- func (p *ParserUnitData) Namelist(name string) *ast.NamelistGroup
- func (p *ParserUnitData) ProcedureParams() []Varinfo
- func (p *ParserUnitData) Var(name string) (vi *Varinfo)
- func (p *ParserUnitData) Varb(name []byte) (vi *Varinfo)
- type REPL
- func (repl *REPL) Contained(name string) *ParserUnitData
- func (repl *REPL) ContainedOrUsed(name string) *ParserUnitData
- func (repl *REPL) DefineStmtFunc(name string, params []string, expr f90.Expression, decl *f90.DeclEntity)
- func (repl *REPL) Eval(dst *Varinfo, expr f90.Expression) (err error)
- func (repl *REPL) GetUsed(name string) *ParserUnitData
- func (repl *REPL) InferType(dst *Varinfo, expr f90.Expression) error
- func (repl *REPL) Namelist(name string) *ast.NamelistGroup
- func (repl *REPL) PushHostScope(vars []Varinfo) (pop func())
- func (repl *REPL) PushVar(v Varinfo) (remove func())
- func (repl *REPL) RegisterUnits(pu ...f90.Unit) error
- func (repl *REPL) RegisteredUnit(name string) *f90.Unit
- func (repl *REPL) Reset()
- func (repl *REPL) ScopeParams() []Varinfo
- func (repl *REPL) SetScope(pu f90.Unit) (err error)
- func (repl *REPL) Use(name string, only ...string) (err error)
- func (repl *REPL) Var(name string) *Varinfo
- type ToGo
- func (tg *ToGo) AppendCommonDecls(dst []ast.Decl) []ast.Decl
- func (tg *ToGo) Contained(name string) *ParserUnitData
- func (tg *ToGo) ContainedOrUsed(name string) *ParserUnitData
- func (tg *ToGo) ImportDecl() ast.Decl
- func (tg *ToGo) Reset()
- func (tg *ToGo) SetDeferredSource(source string)
- func (tg *ToGo) SetSource(source string, r io.ReaderAt)
- func (tg *ToGo) TransformUnits(dst []ast.Decl, units ...f90.Unit) (_ []ast.Decl, err error)
- type Value
- type VarFlags
- type Varinfo
- func (p *Varinfo) Charlen() ast.Expression
- func (p *Varinfo) CommonBlock() string
- func (p *Varinfo) DeclPos() (source string, line, col int)
- func (p *Varinfo) Dimensions() *ast.ArraySpec
- func (p *Varinfo) Flags() VarFlags
- func (p *Varinfo) Identifier() string
- func (p *Varinfo) IsAllocatable() bool
- func (p *Varinfo) IsArray() bool
- func (p *Varinfo) IsChar() bool
- func (p *Varinfo) IsCharArray() bool
- func (p *Varinfo) IsParameter() bool
- func (p *Varinfo) IsPointer() bool
- func (p *Varinfo) IsStmtFunc() bool
- func (p *Varinfo) Kind() ast.Expression
- func (p *Varinfo) StmtFuncExpr() ast.Expression
- func (p *Varinfo) StmtFuncParams() []string
- func (p *Varinfo) TypeToken() token.Token
- func (p *Varinfo) Value() Value
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Lexer90 ¶
type Lexer90 struct {
// contains filtered or unexported fields
}
Lexer90 is a lexer for the Fortran 90 programming language.
func (*Lexer90) AppendPositionString ¶
AppendPositionString appends Lexer90.PositionString to the buffer and returns the result.
func (*Lexer90) Err ¶
func (l *Lexer90) Err() error
Err returns the lexer error, or nil if the error is EOF.
func (*Lexer90) LineCol ¶
LineCol returns the current line number and column number (utf8 relative).
func (*Lexer90) NextToken ¶
Next token parses the upcoming token and returns the literal representation of the token for identifiers, strings and numbers. The returned byte slice is reused between calls to NextToken.
func (*Lexer90) Pos ¶
Pos returns the absolute position of the lexer in bytes from the start of the file.
func (*Lexer90) PositionString ¶
PositionString returns the "source:line:column" representation of the lexer's current position.
func (*Lexer90) Reset ¶
Reset discards all state and buffered data and begins a new lexing procedure on the input r. It performs a single utf8 read to initialize.
func (*Lexer90) Source ¶
Source returns the name the lexer was reset/initialized with. Usually a filename.
func (*Lexer90) TokenLineCol ¶
TokenLineCol returns the line/col where the last returned token started.
type Parser90 ¶
type Parser90 struct {
// contains filtered or unexported fields
}
func (*Parser90) Errors ¶
func (p *Parser90) Errors() []ParserError
func (*Parser90) IsDone ¶
IsDone returns true if the parser is done parsing, whether it be by EOF or error(s) encountered.
func (*Parser90) ParseNextProgramUnit ¶
ParseNextProgramUnit parses and returns the next program unit from the input. Returns nil when EOF is reached or no more units are available. This method can be called repeatedly to incrementally parse a Fortran file. Phase 1: Parses only top-level program units (PROGRAM, SUBROUTINE, FUNCTION, MODULE)
type ParserError ¶
type ParserError struct {
// contains filtered or unexported fields
}
func (*ParserError) Error ¶
func (pe *ParserError) Error() string
func (ParserError) String ¶
func (pe ParserError) String() string
type ParserUnitData ¶
type ParserUnitData struct {
// contains filtered or unexported fields
}
func (*ParserUnitData) AltReturnCount ¶
func (p *ParserUnitData) AltReturnCount() int
AltReturnCount returns the number of alternate return (*) parameters declared.
func (*ParserUnitData) AppendVarinfo ¶
func (p *ParserUnitData) AppendVarinfo(dst []Varinfo) []Varinfo
func (*ParserUnitData) Namelist ¶
func (p *ParserUnitData) Namelist(name string) *ast.NamelistGroup
Namelist returns the NAMELIST group with the given name, or nil if not found.
func (*ParserUnitData) ProcedureParams ¶
func (p *ParserUnitData) ProcedureParams() []Varinfo
ProcedureParams returns the varinfos corresponding to parameters of the function, in order.
func (*ParserUnitData) Var ¶
func (p *ParserUnitData) Var(name string) (vi *Varinfo)
func (*ParserUnitData) Varb ¶
func (p *ParserUnitData) Varb(name []byte) (vi *Varinfo)
type REPL ¶
type REPL struct {
// contains filtered or unexported fields
}
func (*REPL) Contained ¶
func (repl *REPL) Contained(name string) *ParserUnitData
func (*REPL) ContainedOrUsed ¶
func (repl *REPL) ContainedOrUsed(name string) *ParserUnitData
func (*REPL) DefineStmtFunc ¶
func (repl *REPL) DefineStmtFunc(name string, params []string, expr f90.Expression, decl *f90.DeclEntity)
DefineStmtFunc registers a statement function in the current scope. Statement functions are one-line inline functions like: FUNCNAME(X) = expr
func (*REPL) Eval ¶
func (repl *REPL) Eval(dst *Varinfo, expr f90.Expression) (err error)
Eval evaluates a Fortran expression into dst. Caller provides dst to avoid allocations; dst can be reused across calls. On success dst.Value() holds the result with val.tok set to the evaluated type.
func (*REPL) GetUsed ¶
func (repl *REPL) GetUsed(name string) *ParserUnitData
func (*REPL) InferType ¶
func (repl *REPL) InferType(dst *Varinfo, expr f90.Expression) error
InferType infers the type of expr without evaluating it. Sets dst.val.tok to the result type.
func (*REPL) Namelist ¶
func (repl *REPL) Namelist(name string) *ast.NamelistGroup
Namelist returns the NAMELIST group with the given name, or nil if not found.
func (*REPL) PushHostScope ¶
PushHostScope sets host-associated variables from an enclosing MODULE or PROGRAM for contained procedure transpilation. Returns pop to restore prior state. Call pop after CONTAINS processing is complete.
func (*REPL) PushVar ¶
PushLoopVar temporarily adds an implied DO loop variable to the current scope. Returns a function that removes the variable when called. Usage: defer repl.PushLoopVar(name)()
func (*REPL) RegisterUnits ¶
RegisterUnits registers a set of program units to the REPL. These units are registered at a top level and are not accessed except in the case of function/subroutine lookup.
func (*REPL) RegisteredUnit ¶
RegisteredUnit returns a program unit that was previously registered with RegisterUnit.
func (*REPL) ScopeParams ¶
type ToGo ¶
type ToGo struct {
// contains filtered or unexported fields
}
func (*ToGo) AppendCommonDecls ¶
AppendCommonDecls appends COMMON block declarations and fenv to dst. Generates: var fenv = fortio.NewEnvironment() Generates: var BLK = intrinsic.NewCommonBlock("BLK", totalSize) Should be called after all program units have been processed.
func (*ToGo) Contained ¶
func (tg *ToGo) Contained(name string) *ParserUnitData
func (*ToGo) ContainedOrUsed ¶
func (tg *ToGo) ContainedOrUsed(name string) *ParserUnitData
func (*ToGo) ImportDecl ¶
func (*ToGo) SetDeferredSource ¶
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value holds a runtime Fortran value for REPL evaluation.
Two type concepts exist in varinfo:
- val.tok (Value.Token): The evaluated result's runtime type
- decl.Type.Token: The declared type from AST
For declared variables both match. For ephemeral results (intermediates like 2+3.0), decl comes from templates (_tgtFloat32 etc), val.tok tracks the actual evaluated type after promotion.
func (*Value) StringValue ¶
type VarFlags ¶
type VarFlags uint64
VarFlags tracks attributes and semantic properties of Fortran variables. Flags are set during parsing and used during transpilation to determine the correct Go representation and access patterns.
const ( // VFlagImplicit: Type was inferred from IMPLICIT rules rather than explicit declaration. // Set when: Variable used without prior declaration, type derived from first letter. VFlagImplicit VarFlags = 1 << iota // VFlagUsed: Symbol is referenced somewhere in the code. // Set when: Any use of the identifier in expressions or statements. VFlagUsed // VFlagPointer: Variable has POINTER attribute or is a Cray-style pointer. // Set when: "INTEGER, POINTER :: x" (F90) or "POINTER (ptr, pointee)" (Cray ptr). // For Cray: the pointer variable (ptr) holds an address, not auto-dereferenced. // For F90 POINTER: typically combined with VFlagDimension for pointer arrays. VFlagPointer // VFlagTarget: Variable has TARGET attribute (can be pointed to by F90 pointers). // Set when: "INTEGER, TARGET :: x" VFlagTarget // VFlagParameter: Is a dummy argument (parameter) of a function/subroutine. // Set when: Variable appears in procedure's parameter list. VFlagParameter // VFlagAllocatable: Variable has ALLOCATABLE attribute. // Set when: "INTEGER, ALLOCATABLE :: arr(:)" - dynamic allocation via ALLOCATE. VFlagAllocatable // VFlagCommon: Variable is in a COMMON block (shared storage). // Set when: Variable appears in a COMMON statement. VFlagCommon // VFlagPointee: Cray-style pointee accessed through a pointer variable. // Set when: "POINTER (ptr, pointee)" - pointee is accessed via ptr. // Access to pointee requires dereferencing the pointer variable. VFlagPointee // VFlagDimension: Variable is an array (has DIMENSION attribute or explicit bounds). // Set when: "INTEGER :: arr(10)" or "INTEGER, DIMENSION(:) :: arr" // Go type: *intrinsic.Array[T] VFlagDimension // VFlagIntentOut: Parameter has INTENT(OUT) - callee provides value. VFlagIntentOut // VFlagIntentIn: Parameter has INTENT(IN) - caller provides value. VFlagIntentIn // VFlagArrayInit: Array has been initialized via DATA or inline initializer. VFlagArrayInit // VFlagArraySpec: ArraySpec was used in the type declaration. VFlagArraySpec // VFlagReturned: Variable is the function return value. VFlagReturned // VFlagRecursive: Function/subroutine has RECURSIVE attribute. VFlagRecursive // VFlagEquivalenced: Variable shares storage via EQUIVALENCE statement. // Set when: "EQUIVALENCE (a, b)" - scalars become PointerTo[T] in Go. VFlagEquivalenced // VFlagConstantParameter: Compile-time constant (PARAMETER statement or attribute). // Set when: "PARAMETER (PI = 3.14159)" or "REAL, PARAMETER :: PI = 3.14" VFlagConstantParameter // VFlagStmtFunc: Statement function (one-line inline function). // Set when: "AREA(R) = 3.14159 * R * R" VFlagStmtFunc )
type Varinfo ¶
type Varinfo struct {
// contains filtered or unexported fields
}
func (*Varinfo) Charlen ¶
func (p *Varinfo) Charlen() ast.Expression
func (*Varinfo) CommonBlock ¶
func (*Varinfo) Dimensions ¶
func (*Varinfo) Identifier ¶
func (*Varinfo) IsAllocatable ¶
func (*Varinfo) IsChar ¶
IsChar returns true if this is a character type (not an array of characters).
func (*Varinfo) IsCharArray ¶
IsCharArray returns true if this is an array of character type.
func (*Varinfo) IsParameter ¶
func (*Varinfo) IsPointer ¶
IsPointer returns true if accessing this variable requires automatic pointer dereferencing.
Fortran pointer semantics:
- VFlagPointer (Cray pointer): In "POINTER (NPAA, AA(1))", NPAA holds an address. Accessing NPAA returns the address VALUE, not the pointed-to data. Never auto-deref.
- VFlagPointee: AA in the above example. Accessing AA(i) implicitly dereferences NPAA to reach the data. Pointees need auto-dereferencing.
- VFlagEquivalenced: Variables sharing storage via EQUIVALENCE. In Go, we use pointers so they share memory, and accessing them requires dereferencing.
Returns false for VFlagPointer because you want the address, not what it points to. Returns false for arrays (VFlagDimension) which have their own access patterns. Returns false for CHARACTER types which use intrinsic.CharacterArray.
Note: VFlagIntentOut is handled separately via wrapPointer() in function call transpilation.
func (*Varinfo) IsStmtFunc ¶
func (*Varinfo) Kind ¶
func (p *Varinfo) Kind() ast.Expression
func (*Varinfo) StmtFuncExpr ¶
func (p *Varinfo) StmtFuncExpr() ast.Expression
func (*Varinfo) StmtFuncParams ¶
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
fortran2go
command
|
|
|
fortrangrep
command
fortrangrep searches Fortran source files with comment awareness.
|
fortrangrep searches Fortran source files with comment awareness. |
|
fortranpp
command
fortranpp preprocesses Fortran source files by expanding INCLUDE statements.
|
fortranpp preprocesses Fortran source files by expanding INCLUDE statements. |
|
fortranvar
command
fortranvar prints variable information from Fortran source files.
|
fortranvar prints variable information from Fortran source files. |
|
fortio
Package fortio provides Fortran I/O types and operations.
|
Package fortio provides Fortran I/O types and operations. |