Analisis Léxico

El análisis léxico consiste en convertir una secuencia de caractéres en una secuencia de tokens, para esto se considera en un principio una sola cadena a la cuál se tiene que depurar quitando espacios, tabulaciones, saltos de linea y comentarios. Una vez teniendo los lexemas se trata de relacionar o dar significado, asociandolo a un tipo de token.

Un token se define como un bloque de texto, habitualmente indivisible conocido como lexema. Un analizador léxico procesa los lexemas y los categoriza de acuerdo a su función, dándole asi significado, está asignacion se conoce como "tokenización".

El programa que hace este trabajo se le llama analizador léxico o lexer, PLY es uno que utilizaré en este curso para generar mi Lexer.

Los tokens se definen en muchos analizadores léxicos mediante Expresiones regulares, al leer la cadena la categoriza en tokens, si encuentra un error lo reporta. Consiguiente al Tokenizer sigue el Parser, que se encarga de verificar la estructura de los tokens, esto es llamado análisis sintáctico.

lex.py se usa para tokenizar una cadena de entrada. Por ejemplo suponga que está creando su lenguaje de programación y el usuario proporciona la siguiente cadena.
x = 3 + 42 * (s - t)
El Tokenizer divide la cadena en tokens de la siguiente forma:

'x','=', '3', '+', '42', '*', '(', 's', '-', 't', ')'

En Pyhon Lex se utilizan mayúsculas para indicar un token.

'ID', 'EQUALS', 'NUMBER', 'PLUS', 'NUMBER', 'TIMES',
'LPAREN', 'ID', 'MINUS','ID', 'RPAREN'


Especificamente, la entrada se quiebra en una tupla doble que indica el tipo y valor del token.

('ID','x'), ('EQUALS','='), ('NUMBER','3'),
('PLUS','+'), ('NUMBER','42), ('TIMES','*'),
('LPAREN','('), ('ID','s'), ('MINUS','-'),
('ID','t'), ('RPAREN',')'

Ejemplo de Tokenizer en Python utilizando la libreria PLY.
Este simple tokenizer sirve para definir los tokens de una calculadora.

#----------------------------------------------------------
# calclex.py
#
# tokenizer for a simple expression evaluator for
# numbers and +,-,*,/
# ------------------------------------------------------------
import ply.lex as lex

# List of token names. This is always required
tokens = (
'NUMBER',
'PLUS',
'MINUS',
'TIMES',
'DIVIDE',
'LPAREN',
'RPAREN',
)

# Regular expression rules for simple tokens
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'

# A regular expression rule with some action code
def t_NUMBER(t):
r'\d+'
try:
t.value = int(t.value)
except ValueError:
print "Line %d: Number %s is too large!" % (t.lineno,t.value)
t.value = 0
return t

# Define a rule so we can track line numbers
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)

# A string containing ignored characters (spaces and tabs)
t_ignore = ' \t'

# Error handling rule
def t_error(t):
print "Illegal character '%s'" % t.value[0]
t.lexer.skip(1)

# Build the lexer
lex.lex()

To use the lexer, you first need to feed it some input text using its input() method. After that, repeated calls to token() produce tokens. The following code shows how this works:

# Test it out
data = '''
3 + 4 * 10
+ -20 *2
'''

# Give the lexer some input
lex.input(data)

# Tokenize
while 1:
tok = lex.token()
if not tok: break # No more input
print tok

When executed, the example will produce the following output:

$ python example.py
LexToken(NUMBER,3,2,1)
LexToken(PLUS,'+',2,3)
LexToken(NUMBER,4,2,5)
LexToken(TIMES,'*',2,7)
LexToken(NUMBER,10,2,10)
LexToken(PLUS,'+',3,14)
LexToken(MINUS,'-',3,16)
LexToken(NUMBER,20,3,18)
LexToken(TIMES,'*',3,20)
LexToken(NUMBER,2,3,21)


The tokens returned by lex.token() are instances of LexToken. This object has attributes tok.type, tok.value, tok.lineno, and tok.lexpos. The following code shows an example of accessing these attributes:
# Tokenize
while 1:
tok = lex.token()
if not tok: break # No more input
print tok.type, tok.value, tok.line, tok.lexpos