El proyecto es un compilador que toma un programa fuente escrito en C# (entrada) y luego lo traduce a un programa de destino escrito en Visual Basic (salida) . Este proceso se realiza pasando por tres módulos ( Tokenizer
, Parser
y Translator
) respectivamente. Cada módulo se explicará por separado en este informe.
Tokenizer / Lexical Analyzer es un programa que toma una secuencia de caracteres (entrada) y genera una secuencia de tokens (salida).
El tokenizador tiene una lista de definiciones para cada token posible que puede producir agrupando una secuencia de caracteres. Cada definición de token consta de:
Las siguientes tablas representan todas las definiciones utilizadas en el proyecto, con un ejemplo de valores coincidentes para cada una.
Tipo | Expresión regular | Valor(es) coincidente(s) |
---|---|---|
Usando | usando | using |
Clase | clase | class |
Si | si | if |
Demás | demás | else |
Para | para | for |
Hacer | hacer | do |
Mientras | mientras | while |
Cambiar | cambiar | switch |
Caso | caso | case |
Romper | romper | break |
Por defecto | por defecto | default |
Devolver | devolver | return |
Nulo | nulo | null |
Verdadero | verdadero | true |
FALSO | FALSO | false |
FALSO | (nulo | var) | (bool | char | corto | int | largo | flotante | doble | decimal | cadena | Cadena) ([] | ?)? | void bool char? int[] |
Tipo | Expresión regular | Valor(es) coincidente(s) |
---|---|---|
Número | d*.d+ | d+ | 77 .25 3.14 |
Cadena | "[^"]*" | "This is string" |
Identificador | [a-zA-Z_]w* | fact _private iD_1 |
Comentario | (?<=//) .*? (?=(r | n | //)) | // inline comment |
Comentario multilínea | (?<=/*) (?:(?!*/)(?:.|[rn]))* (?=*/) | /*multi line comment */ |
Tipo | Expresión regular | Valor(es) coincidente(s) |
---|---|---|
Y | && | & | && & |
O | || | | | || | |
No | ! | ! |
Igual | = | = |
PlusIgual | += | += |
Menosigual | -= | -= |
doble igual | == | == |
No igual | != | != |
Menos que | < | < |
mayor que | > | > |
menor o igual | <= | <= |
Mayor que o igual | >= | >= |
Tipo | Expresión regular | Valor(es) coincidente(s) |
---|---|---|
Soporte redondo abierto | ( | ( |
CerrarRedondoSoporte | ) | ) |
AbiertoCurlyBracket | { | { |
CerrarRizadoSoporte | } | } |
SoporteCuadradoAbierto | [ | [ |
CerrarCuadradoSoporte | ] | ] |
Más | + | + |
Menos | - | - |
DoblePluses | ++ | ++ |
Doble desventajas | -- | -- |
Por ciento | % | % |
Asterisco | * | * |
barra invertida | \ |
|
barra diagonal | / | / |
Barras dobles hacia adelante | // | // |
Barra diagonalAsterisco | /* | /* |
AsteriscoAdelanteBarra | */ | */ |
Punto | . | . |
Coma | , | , |
Colon | : | : |
Punto y coma | ; | ; |
Todos estos tipos de tokens se agrupan como enumeración en el archivo TokenType.cs.
public enum TokenType
{
// Keywords
Using , // using
Class , // class
If , // if
Else , // else
For , // for
Do , // do
While , // while
Switch , // switch
Case , // case
Break , // break
Default , // default
Return , // return
Null , // null
True , // true
False , // false
DataType , // void | bool | char? | int[]
// Values
Number , // 77 | .25 | 3.14
String , // "I am 'Moaz'"
Comment , // Any Character After (//) and Before (r | n | //)
Identifier , // fact | _private | iD_1
MultilineComment , // Any Character After (/*) and Before (*/)
// Operators
And , // && | &
Or , // || | |
Not , // !
Equal , // =
PlusEqual , // +=
MinusEqual , // -=
DoubleEquals , // ==
NotEqual , // !=
LessThan , // <
GreaterThan , // >
LessThanOrEqual , // <=
GreaterThanOrEqual , // >=
// Symbols
OpenRoundBracket , // (
CloseRoundBracket , // )
OpenCurlyBracket , // {
CloseCurlyBracket , // }
OpenSquareBracket , // [
CloseSquareBracket , // ]
Plus , // +
Minus , // -
DoublePluses , // ++
DoubleMinuses , // --
Percent , // %
Asterisk , // *
BackSlash , //
ForwardSlash , // /
DoubleForwardSlashes , // //
ForwardSlashAsterisk , // /*
AsteriskForwardSlash , // */
Dot , // .
Comma , // ,
Colon , // :
Semicolon // ;
}
y sus definiciones se crean y almacenan en List<TokenDefinition> en el archivo Tokenizer.cs.
private readonly List < TokenDefinition > _tokenDefinitions = new List < TokenDefinition >
{
// Keywords
new TokenDefinition ( TokenType . Using , @"using" ) ,
new TokenDefinition ( TokenType . Class , @"class" ) ,
new TokenDefinition ( TokenType . If , @"if" ) ,
new TokenDefinition ( TokenType . Else , @"else" ) ,
new TokenDefinition ( TokenType . For , @"for" ) ,
new TokenDefinition ( TokenType . Do , @"do" , 1 ) ,
new TokenDefinition ( TokenType . While , @"while" ) ,
new TokenDefinition ( TokenType . Switch , @"switch" ) ,
new TokenDefinition ( TokenType . Case , @"case" ) ,
new TokenDefinition ( TokenType . Default , @"default" ) ,
new TokenDefinition ( TokenType . Break , @"break" ) ,
new TokenDefinition ( TokenType . Return , @"return" ) ,
new TokenDefinition ( TokenType . Null , @"null" ) ,
new TokenDefinition ( TokenType . True , @"true" ) ,
new TokenDefinition ( TokenType . False , @"false" ) ,
new TokenDefinition ( TokenType . DataType , @"(void|var)|(bool|char|short|int|long|float|double|decimal|String|string)([]|?)?" ) ,
// Values
new TokenDefinition ( TokenType . Number , @"d*.d+|d+" ) ,
new TokenDefinition ( TokenType . String , @"""[^""]*""" ) ,
new TokenDefinition ( TokenType . Identifier , @"[a-zA-Z_]w*" , 1 ) ,
new TokenDefinition ( TokenType . Comment , @"(?<=//).*?(?=(r|n|//))" ) ,
new TokenDefinition ( TokenType . MultilineComment , @"(?<=/*)(?:(?!*/)(?:.|[rn]))*(?=*/)" ) ,
// Operators
new TokenDefinition ( TokenType . And , @"&&|&" ) ,
new TokenDefinition ( TokenType . Or , @"||||" ) ,
new TokenDefinition ( TokenType . Not , @"!" , 1 ) ,
new TokenDefinition ( TokenType . Equal , @"=" , 1 ) ,
new TokenDefinition ( TokenType . PlusEqual , @"+=" ) ,
new TokenDefinition ( TokenType . MinusEqual , @"-=" ) ,
new TokenDefinition ( TokenType . DoubleEquals , @"==" ) ,
new TokenDefinition ( TokenType . NotEqual , @"!=" ) ,
new TokenDefinition ( TokenType . LessThan , @"<" , 1 ) ,
new TokenDefinition ( TokenType . GreaterThan , @">" , 1 ) ,
new TokenDefinition ( TokenType . LessThanOrEqual , @"<=" ) ,
new TokenDefinition ( TokenType . GreaterThanOrEqual , @">=" ) ,
// Symbols
new TokenDefinition ( TokenType . OpenRoundBracket , @"(" ) ,
new TokenDefinition ( TokenType . CloseRoundBracket , @")" ) ,
new TokenDefinition ( TokenType . OpenCurlyBracket , @"{" ) ,
new TokenDefinition ( TokenType . CloseCurlyBracket , @"}" ) ,
new TokenDefinition ( TokenType . OpenSquareBracket , @"[" ) ,
new TokenDefinition ( TokenType . CloseSquareBracket , @"]" ) ,
new TokenDefinition ( TokenType . Plus , @"+" , 1 ) ,
new TokenDefinition ( TokenType . Minus , @"-" , 1 ) ,
new TokenDefinition ( TokenType . DoublePluses , @"++" ) ,
new TokenDefinition ( TokenType . DoubleMinuses , @"--" ) ,
new TokenDefinition ( TokenType . Percent , @"%" ) ,
new TokenDefinition ( TokenType . Asterisk , @"*" , 1 ) ,
new TokenDefinition ( TokenType . BackSlash , @"\" ) ,
new TokenDefinition ( TokenType . ForwardSlash , @"/" , 1 ) ,
new TokenDefinition ( TokenType . DoubleForwardSlashes , @"//" ) ,
new TokenDefinition ( TokenType . ForwardSlashAsterisk , @"/*" ) ,
new TokenDefinition ( TokenType . AsteriskForwardSlash , @"*/" ) ,
new TokenDefinition ( TokenType . Dot , @"." ) ,
new TokenDefinition ( TokenType . Comma , @"," ) ,
new TokenDefinition ( TokenType . Colon , @":" ) ,
new TokenDefinition ( TokenType . Semicolon , @";" ) ,
} ;
.. .
Cuando el tokenizador se enfrenta a alguna secuencia de caracteres como ++
se confunde, ¿es un token de tipo DoublePluses ? ¿O dos tokens secuenciales de tipo Plus ? Este problema también se aplica a otros tokens superpuestos como: { +
, +=
} & { -
, --
} & { -
, -=
} & { /
, //
}
Solución:
A cada token se le asignará una propiedad de Prioridad con el valor predeterminado 0 (Prioridad más alta) , y cuando dos tokens se superponen como +
y +=
disminuimos la prioridad del token con una longitud más corta +
para que sea 1 .
Ahora, el tokenizador ya no se confundirá entre +
y +=
, y tomará el que tenga mayor prioridad +=
.
Cuando el tokenizador se enfrenta a alguna secuencia de caracteres como "String + String = String"
producirá tres tipos de tokens que son:
"String + String = String"
+
=
pero solo necesitamos el token con tipo String !!
Solución:
A cada token se le asignarán propiedades de índice inicial y de índice final , de modo que los tokens anteriores tendrán:
Tipo | Valor | Índice de inicio | Índice final |
---|---|---|---|
Cadena | "String + String = String" | 0 | 25 |
Más | + | 8 | 9 |
Igual | = | 17 | 18 |
e ignoramos cualquier inicio de token dentro del rango de otro.
Ahora, el tokenizador producirá solo un token de tipo String e ignorará los internos.
Parser/Syntax Analyser es un programa que toma una secuencia de tokens (generados a partir del Tokenizer) y los agrupa para formar estructuras especificadas por las producciones de gramática libre de contexto (CFG) que se utilizan.
Resumen:
CAPITAL_CASE
: No terminalsmall_case
: Terminal|
: Suplentes (O)ε
: Vacío PROGRAM --> IMPORTS CLASSES
IMPORTS --> IMPORT_STATEMENT IMPORTS | ε
IMPORT_STATEMENT --> using IDS;
CLASSES --> CLASS_STATEMENT CLASSES | ε
CLASS_STATEMENT --> class id { SUPER_STATEMENTS }
SUPER_STATEMENTS --> SUPER_STATEMENT SUPER_STATEMENTS | ε
SUPER_STATEMENT --> COMMENT_STATEMENT | FUNCTION_STATEMENT | INLINE_STATEMENT ;
COMMENT_STATEMENT --> // comment | /* multiline_comment */
FUNCTION_STATEMENT --> data_type id (DECLARES) { STATEMENTS }
INLINE_STATEMENT --> DECSIGN_STATEMENT | DECLARE_STATEMENT | INC_DEC_STATEMENT | ASSIGN_STATEMENT | CALL_STATEMENT
DECSIGN_STATEMENT --> data_type id = EXPRESSION
DECLARE_STATEMENT --> data_type id
INC_DEC_STATEMENT --> id INC_DEC_OPERATOR
ASSIGN_STATEMENT --> id ASSIGN_OPERATOR EXPRESSION
CALL_STATEMENT --> IDS(EXPRESSIONS)
STATEMENTS --> STATEMENT STATEMENTS | ε
STATEMENT --> SUPER_STATEMENT | STRUCT_STATEMENT
STRUCT_STATEMENT --> IF_STATEMENT | WHILE_STATEMENT | DO_WHILE_STATEMENT | FOR_STATEMENT | BLOCK_STATEMENT | RETURN_STATEMENT | SWITCH_STATEMENT
IF_STATEMENT --> if (CONDITION) STATEMENT ELSE_STATEMENT
ELSE_STATEMENT --> else STATEMENT | ε
WHILE_STATEMENT --> while (CONDITION) STATEMENT
DO_WHILE_STATEMENT --> do STATEMENT while (CONDITION);
FOR_STATEMENT --> for (INLINE_STATEMENT; CONDITION; INLINE_STATEMENT) STATEMENT
BLOCK_STATEMENT --> { STATEMENTS }
RETURN_STATEMENT --> return RETURN_STATEMENT_REST;
RETURN_STATEMENT_REST --> EXPRESSION | ε
SWITCH_STATEMENT --> switch (EXPRESSION) { CASES }
CASES --> CASE CASES | ε
CASE --> CASE_STATEMENT | DEFAULT_STATEMENT
CASE_STATEMENT --> case VALUE: STATEMENT break;
DEFAULT_STATEMENT --> default: STATEMENT break;
CONDITION --> EXPRESSION REL_OPERATOR EXPRESSION | true | false
EXPRESSION --> VALUE | id | ( EXPRESSION )
VALUE --> string | number | true | false | null
IDS --> id MORE_IDS
MORE_IDS --> .IDS | ε
DECLARES --> DECLARE_STATEMENT MORE_DECLARES | ε
MORE_DECLARES --> , DECLARES | ε
EXPRESSIONS --> EXPRESSION MORE_EXPRESSIONS | ε
MORE_EXPRESSIONS --> , EXPRESSIONS | ε
INC_DEC_OPERATOR --> ++ | --
ASSIGN_OPERATOR --> = | += | -=
REL_OPERATOR --> == | != | > | >= | < | <=
En informática, la forma Backus-Naur (BNF o forma normal de Backus) es una notación utilizada para describir la sintaxis de lenguajes de programación u otros lenguajes formales. Fue desarrollado por John Backus y Peter Naur. BNF puede describirse como una notación de metasintaxis para gramáticas libres de contexto.
- Forma Backus-Naur @ Wikipedia
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por:
referenciado por: