Closed PressFforlove closed 1 year ago
Hi @PressFforlove. The short answer is no, there is no direct support in the ast for modifying the tree. Depending on what you want to do there are a couple of options you could take. If you want to do a lot a manipulation I would suggest using the PSyIR internal representation and associated tools, which is part of another project called PSyclone but uses fparser2 to parse the Fortran code in the first instance. If you want to make relatively small changes to the Fortran then you can modify the fparser2 ast directly by turning tuples into lists and back again. The code below shows how you could modify a "+" to a "-" in both approaches.
# PSyIR example
from psyclone.psyir.frontend.fortran import FortranReader
from psyclone.psyir.backend.fortran import FortranWriter
from psyclone.psyir.nodes import BinaryOperation
code = (
"program test\n"
" integer :: a, b, c\n"
" a = b + c\n"
"end program")
psyir = FortranReader().psyir_from_source(code)
print(psyir.view())
assignment = psyir.children[0].children[0]
add = assignment.rhs
rhs_add = add.children[1].detach()
lhs_add = add.children[0].detach()
minus = BinaryOperation.create(
BinaryOperation.Operator.SUB, lhs_add, rhs_add)
add.replace_with(minus)
print(psyir.view())
print(FortranWriter()(psyir))
# fparser2 example
from fparser.common.readfortran import FortranStringReader
from fparser.two.parser import ParserFactory
reader = FortranStringReader(code, ignore_comments=False)
f2008_parser = ParserFactory().create(std="f2008")
parse_tree = f2008_parser(reader)
print(repr(parse_tree))
main_program = parse_tree.children[0]
execution_part = main_program.children[2]
assignment = execution_part.children[0]
level_2_expr = assignment.children[2]
# As both "+" and "-" are a level-2-expr we can replace the string.
child_list = list(level_2_expr.items)
child_list[1] = "-"
level_2_expr.items = tuple(child_list)
print(repr(parse_tree))
print(parse_tree)`
thank you very much~ it helps a lot~
Note that it would be quite simple in PSyclone to add a method to just change an operation, which would significantly simplify the PSyclone version, e.g. in Rupert's example:
add = assignment.rhs
rhs_add = add.children[1].detach()
lhs_add = add.children[0].detach()
minus = BinaryOperation.create(
BinaryOperation.Operator.SUB, lhs_add, rhs_add)
add.replace_with(minus)
we would then just need:
add = assignment.rhs
add.operator = BinaryOperation.Operator.SUB
(though you would likely use a better name for the variable :) )
We just never had a need to do that :)
thank you for your help~ i will try PSyclone to do this~
Hello there, i am new in fparser, and i am trying to do some transform in ast. But i meet some problem while doing so. I want to change some binaryOp in ast,such as "+", "-","/", "*",which is str in ast. For example: change “a+b” to "a-b" But i can't directly change the str in place the ast. The reason is that, in fparser's ast, a code line like c = a + b is an {Assignment_Stmt} class,in which "a + b" is stored in {tuple}(E.G. children = {tuple}[3], children[0] = a, children[1]=str("+"),children[2]="b"). In python, str and tuple are both immutable object. Is there any option to make the ast structure of "c = a + b" mutable object, that i can do this transform inplace? Or is there any interface in ast , so that i can use the interface to change the str?
Also, i come up a solution that iterate the parent node until the data structure is {list}, and then replace the children with a brand new children node which changed some specific childNodes. But i don't know how to copy the node while change some specific childNode in python.Another problem is that, when i iterate to the parents, it is unclear to detemine where will i meet the list structure, which make me more confused.
Any help will be apprecited, thank you for your attention to this issue~