![]() |
|||
| HSG |
|
Wir haben gesehen, wie man zur Konstruktion eines Scanners systematisch vorgehen könnte. Diese Vorgänge lassen sich automatisieren. So ermöglichen Pakete wie Lex eine automatische Erzeugung eines Scanners. Wir benutzen die Python-Variante PLY. Es hat sich gezeigt, dass ply in Verbindung mit Idle fehlerhaft arbeitet. So ist es besser nach einer Änderung, Idle völlig neu zu starten. Alternativ kann man auf der Konsole arbeiten, z.B. python3 -i scanner_lex.py .
Folgendes Beispiel ist minimal, nicht optimal. Zur Dokumentation lese man zunächst die Abschnitte Lex Example, The tokens list, Specification of tokens der Dokumentation.
import ply.lex as lex
tokens = ('Bezeichner','pointfloat','ws')
t_Bezeichner = r'[A-Za-z_][\w]*'
t_pointfloat = r'(\d+)?\.\d+|(\d+\.)'
t_ws = r'\s+'
def t_error(t):
print('Unerwartetes Zeichen:',t.value[0])
t.lexer.skip(1)
s = lex.lex()
Tests
Nach Eingabe eines Strings wird das Scanner-Objekt s zu einem Generator, das mit s.token() fortlaufend die erzeugten Tokens herausgibt. Ein LexToken ist dabei ein Objekt, das über die Attribute Typ, Wert, Zeile und Position verfügt.
>>> s.input('a23 \n\r 12.34xxx \t\n')
>>> s.token()
LexToken(Bezeichner,'a23',1,0)
>>> s.token()
LexToken(ws,' \n\r ',1,3)
>>> s.token()
LexToken(pointfloat,'12.34',1,8)
>>> s.token()
LexToken(Bezeichner,'xxx',1,13)
>>> s.token()
LexToken(ws,' \t\n',1,16)
>>> s.token()
>>> s.input('a23 \n\r 12,34xxx \t\n')
>>> s.token()
LexToken(Bezeichner,'a23',1,0)
>>> s.token()
LexToken(ws,' \n\r ',1,3)
>>> s.token()
Unerwartetes Zeichen: 1
Unerwartetes Zeichen: 2
Unerwartetes Zeichen: ,
Unerwartetes Zeichen: 3
Unerwartetes Zeichen: 4
LexToken(Bezeichner,'xxx',1,13)
>>> s.token()
LexToken(ws,' \t\n',1,16)
>>>
Informiere dich zunächst über die ipigisi-Sprache.
Erstelle mit Hilfe von pyl.lex einen Scanner und teste diesen mit 3 Beispielen.