2010-01-05

Konkret syntax från abstrakt syntax

Tittade lite på ast-modulen i Python, där ast står för Abstract Syntax Tree. Man kan använda den för att parsa Python-kod och analysera eller modifiera parse-trädet. Rätt coolt. Så här kan det se när en Python-n00b använder ast för att leta upp och skriva ut en funktion i en källkodsfil:


import ast

def find_last_line(func):
last_line = 0

for n in ast.walk(func):
if isinstance(n, ast.stmt) and n.lineno > last_line:
last_line = n.lineno

return last_line

def find_func(func_name, parse_tree):
for n in ast.iter_child_nodes(parse_tree):
if isinstance(n, ast.FunctionDef) and n.name == func_name:
return n

def read_file(filename):
f = open(filename, 'r')
text = f.read()
f.close()

return text

source = read_file('test_ast.py')
lines = source.split('\n')

p = ast.parse(source)

func_node = find_func('find_func', p)
last_line = find_last_line(func_node)

for l in lines[func_node.lineno-1:last_line]:
print l


Kanske inte världens mest solida kod, men vafan. Funkar det då? Ja, det är väl för i helvete klart att det funkar:


Olsson:testo linusakerlund$ python test_ast.py
def find_func(func_name, parse_tree):
for n in ast.iter_child_nodes(parse_tree):
if isinstance(n, ast.FunctionDef) and n.name == func_name:
return n
Olsson:testo linusakerlund$


Sensmoral: det är trevligt med högnivåspråk ibland.

14 kommentarer:

UL-Tomten sa...

Meddela Blogger om tvivelaktigt innehåll på den här sidan.

puterman sa...

Menade du "Meddela Blogger om otvivelaktigt innehåll på den här sidan"?

Simon sa...

Det glädjer mig att du använder Python! :-)

Det gör mig lite ledsen att det där find_last_line-grejset ska behövas. :-(

Det finns någon slags "dump" du kan använda på funktionens objekt, men då får du väl någon slags återskapning och inte hur koden såg ut exakt. Gissar jag. Jag har inte provat. Jag tänker inte heller prova.

puterman sa...

Jag förstår inte vad du är ledsen över, och det var jag som var din spökskrivare på kompilator-kursen, så jag tror inte att jag borde behöva förklara för dig varför det ser ut som det gör. Skulle i och för sig inte behöva söka igenom hela trädet, sista uttrycket och dess subträd borde räcka, men in the spirit of KISS (rockgruppen) så gör jag som jag gör.

UL-Tomten sa...

Nu blev jag kissnödig.

wv: någonslagsdump

Någon slags "dump" sa...

vem pratar om mig

puterman sa...

Någon slags damp som i serialisering (pickle) ist nicht workensich.

Och det kanske inte var så tydligt, men det här exemplet handlade inte om att skriva ut funktionsdefinitioner, utan om att titta lite på ast. Det slutgiltiga målet är att med hjälp av ast, en syntax-highlighter, en textrendrerare och kanske Core Animation bygga en prototyp av en sådan kod-browser som jag beskrev i ett inlägg för några dagar sedan. Vi får väl se om det blir något.

Olof sa...

"Det slutgiltiga målet är att med hjälp av ast, en syntax-highlighter, en textrendrerare och kanske Core Animation bygga en prototyp av en sådan kod-browser som jag beskrev i ett inlägg för några dagar sedan."

it isnt possible lol

puterman sa...

lol :(

hjon sa...

LantLOLlor!

UL-Tomten sa...

Meddela Blogger om tvivelaktigt inne-LOL på den här sidan. :)

puterman sa...

LOL

[wv: slitr]

Simon sa...

Nej, alltså, det som gör mig ledsen — :-( — är inte din kod i sig utan att den behövs, liksom, typ, vore det inte rimligt att func-objektet erbjöd någon slags property eller metod som kunde svara på vilka fysiska kodrader (eller t o m vilket spann av teckenpositioner i källkoden) som dess abstrakta innehåll motsvarar.

Själv har jag en medeltida version av Python (2.5.2, den här modulen kom visst i 2.6) installerad och vågar inte uppgradera då jag för närvarande inte vill riskera att brejka vissa livsnödvändiga grejer. LOL!

puterman sa...

Jo, det låter ju rimligt, men av någon anledning finns bara info om rad och offset för början av funktionen.