Le projet est un compilateur qui prend un programme source écrit en C# (entrée) puis le traduit en un programme cible écrit en Visual Basic (sortie) . Ce processus se fait en passant par trois modules ( Tokenizer
, Parser
et Translator
) respectivement. Chaque module sera expliqué séparément dans ce rapport.
Tokenizer / Lexical Analyzer est un programme qui prend une séquence de caractères (entrée) et génère une séquence de jetons (sortie).
Le tokenizer dispose d'une liste de définitions pour chaque jeton possible qu'il peut produire en regroupant une séquence de caractères. Chaque définition de jeton comprend :
Les tableaux suivants représentent toutes les définitions utilisées dans le projet, avec un exemple de valeur(s) correspondante(s) pour chacune.
Taper | Expression régulière | Valeur(s) correspondante(s) |
---|---|---|
En utilisant | en utilisant | using |
Classe | classe | class |
Si | si | if |
Autre | autre | else |
Pour | pour | for |
Faire | faire | do |
Alors que | alors que | while |
Changer | changer | switch |
Cas | cas | case |
Casser | casser | break |
Défaut | défaut | default |
Retour | retour | return |
Nul | nul | null |
Vrai | vrai | true |
FAUX | FAUX | false |
FAUX | (vide | var) | (bool | char | short | int | long | float | double | decimal | string | String) ([] | ?) ? | void bool char? int[] |
Taper | Expression régulière | Valeur(s) correspondante(s) |
---|---|---|
Nombre | d*.d+ | d+ | 77 .25 3.14 |
Chaîne | "[^"]*" | "This is string" |
Identifiant | [a-zA-Z_]w* | fact _private iD_1 |
Commentaire | (?<=//) .*? (?=(r | n | //)) | // inline comment |
Commentaire multiligne | (?<=/*) (?:(?!*/)(?:.|[rn]))* (?=*/) | /*multi line comment */ |
Taper | Expression régulière | Valeur(s) correspondante(s) |
---|---|---|
Et | && | & | && & |
Ou | || | | | || | |
Pas | ! | ! |
Égal | = | = |
PlusÉgal | += | += |
MoinsÉgal | -= | -= |
DoubleÉgal | == | == |
Pas égal | != | != |
Moins que | < | < |
Plus grand que | > | > |
Moins que ou égal | <= | <= |
Supérieur à ou égal | >= | >= |
Taper | Expression régulière | Valeur(s) correspondante(s) |
---|---|---|
OuvertRoundBracket | ( | ( |
FermerRoundBracket | ) | ) |
OuvrirCurlyBracket | { | { |
FermerCurlyBracket | } | } |
OpenSquareBracket | [ | [ |
FermerCarréSupport | ] | ] |
Plus | + | + |
Moins | - | - |
DoublePlus | ++ | ++ |
DoubleMinus | -- | -- |
Pour cent | % | % |
Astérisque | * | * |
Barre oblique inverse | \ |
|
Barre oblique | / | / |
DoubleForwardSlashes | // | // |
ForwardSlashAstérisque | /* | /* |
AstérisqueForwardSlash | */ | */ |
Point | . | . |
Virgule | , | , |
Côlon | : | : |
Point-virgule | ; | ; |
Tous ces types de jetons sont regroupés sous forme d'énumération dans le fichier 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 // ;
}
et leurs définitions sont créées et stockées dans List<TokenDefinition> dans le fichier 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 , @";" ) ,
} ;
.. .
Lorsque le tokenizer fait face à une séquence de caractères comme ++
il devient confus, s'agit-il d'un jeton de type DoublePluses ? Ou deux jetons séquentiels de type Plus ? Ce problème s'applique également à d'autres jetons qui se chevauchent comme : { +
, +=
} & { -
, --
} & { -
, -=
} & { /
, //
}
Solution:
Chaque jeton se verra attribuer une propriété Priority avec la valeur par défaut 0 (priorité la plus élevée) , et lorsque deux jetons se chevauchent comme +
et +=
nous diminuons la priorité du jeton de longueur la plus courte +
à 1 .
Désormais, le tokenizer ne sera plus confondu entre +
et +=
et prendra celui avec la priorité la plus élevée +=
.
Lorsque le tokenizer fait face à une séquence de caractères telle que "String + String = String"
il produira trois types de jetons qui sont :
"String + String = String"
+
=
mais nous n'avons besoin que du jeton de type String !!
Solution:
Chaque jeton se verra attribuer des propriétés Start Index et End Index , de sorte que les jetons précédents auront :
Taper | Valeur | Index de démarrage | Fin de l'index |
---|---|---|---|
Chaîne | "String + String = String" | 0 | 25 |
Plus | + | 8 | 9 |
Égal | = | 17 | 18 |
et nous ignorons tout démarrage de jeton à portée d'un autre.
Désormais, le tokenizer ne produira qu’un seul jeton de type String et ignorera ceux qui sont à l’intérieur.
Parser / Syntax Analyzer est un programme qui prend une séquence de jetons - générés à partir du Tokenizer - et les regroupe pour former des structures spécifiées par les productions de grammaire libre de contexte (CFG) utilisées.
Résumé:
CAPITAL_CASE
: Non-Terminalsmall_case
: Terminal|
: Suppléants (Ou)ε
: Vide 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 informatique, la forme Backus – Naur (forme normale BNF ou Backus) est une notation utilisée pour décrire la syntaxe des langages de programmation ou d'autres langages formels. Il a été développé par John Backus et Peter Naur. BNF peut être décrit comme une notation métasyntaxe pour les grammaires sans contexte.
-- Formulaire Backus-Naur @ Wikipédia
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :
référencé par :