gokernel
(usa Linux Mint)
Enviado em 26/08/2018 - 19:40h
"Natsu_Dragneel", escreveu:
Como você fez o lexer e o parser? Com alguma api?
Para fazer o Parser e o Lexer, foi tempo aprendendo ... aqui tenho um livro sobre C que tem um Lex que é baseado neste... mas muito limitado.
Vai uma pequena modificação do lex:
O Parse que fiz usa esse modelo do lex.
Fiz pequeno só para vc entender ...
//-------------------------------------------------------------------
//
// Tiny Lexical Analyzer:
//
// FILE:
// lex.c
//
// COMPILER:
// gcc lex.c -o lex -Wall
//
//-------------------------------------------------------------------
//
#include <stdio.h>
#define LEXER_NAME_SIZE 255
#define LEXER_TOKEN_SIZE 1024 * 4
typedef struct LEXER LEXER;
struct LEXER {
char *text;
char name [LEXER_NAME_SIZE];
char token [LEXER_TOKEN_SIZE];
//
int pos; // text [ pos ]
int tok;
int line;
int level; // in: '{' level++; | in '}' level--;
};
enum {
TOK_INT = 255,
TOK_IF,
TOK_FOR,
TOK_BREAK,
TOK_FUNCTION,
//-----------------------
TOK_ID,
TOK_STRING,
TOK_NUMBER,
//-----------------------
TOK_PLUS_PLUS, // ++
TOK_MINUS_MINUS, // --
TOK_EQUAL_EQUAL, // ==
TOK_NOT_EQUAL, // !=
TOK_AND_AND, // &&
TOK_PTR // ->
};
//-------------------------------------------------------------------
//
// return tok number or 0.
//
//-------------------------------------------------------------------
//
int lex (LEXER *l) {
register char *p;
register int c;
int next; // next char
p = l->token;
*p = 0;
top:
//
// aqui c "pega" o valor ... mas nao incrementa a "texto" posicao
//
c = l->text[ l->pos ];
//############## REMOVE SPACE #############
//
if (c <= 32) {
if (c == 0) {
l->tok = 0;
return 0;
}
if (c == '\n') l->line++;
l->pos++; //<<<<<<<<<< increment position >>>>>>>>>>
goto top;
}
//################ STRING #################
//
if (c == '"') {
l->pos++; // '"'
//
// acumula o "string"
//
// OBS: se o string for maior que o tamanho do ( LEXER->token ) ... vai dar "problema" ... ENTENDE ?
//
//
while ((c=l->text[l->pos]) && c != '"' && c != '\r' && c != '\n') {
l->pos++;
*p++ = c;
}
*p = 0;
if (c=='"') l->pos++; else printf ("String erro\n");
l->tok = TOK_STRING;
return TOK_STRING;
}
//########## WORD, IDENTIFIER ... #########
//
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_') {
for (;;) {
c = l->text[l->pos];
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_') {
l->pos++;
*p++ = c;
} else break;
}
*p = 0;
if (!strcmp(l->token, "int")) { l->tok = TOK_INT; return TOK_INT; }
if (!strcmp(l->token, "if")) { l->tok = TOK_IF; return TOK_IF; }
if (!strcmp(l->token, "for")) { l->tok = TOK_FOR; return TOK_FOR; }
if (!strcmp(l->token, "break")) { l->tok = TOK_BREAK; return TOK_BREAK; }
if (!strcmp(l->token, "function")) { l->tok = TOK_FUNCTION; return TOK_FUNCTION; }
l->tok = TOK_ID;
return TOK_ID;
}
//################# NUMBER ################
//
if (c >= '0' && c <= '9') {
for (;;) {
c = l->text[l->pos];
if ((c >= '0' && c <= '9') || c == '.') {
l->pos++;
*p++ = c;
} else break;
}
*p = 0;
l->tok = TOK_NUMBER;
return TOK_NUMBER;
}
*p++ = c;
*p = 0;
l->pos++;
l->tok = c;
return c;
}//: lex()
void lex_set (LEXER *l, char *text, char *name) {
if (l && text) {
l->pos = 0;
l->line = 1;
l->level = 0;
l->text = text;
if (name)
strcpy (l->name, name);
}
}//: lex_set()
int Parse (LEXER *l, char *text, char *name) {
lex_set (l, text, name);
while (lex(l)) {
printf ("TOKEN(%s)\n", l->token);
}
}
int main (void) {
LEXER l;
Parse (&l, "int a = 10, b = 20, c = 3, d = 5;", "string");
return 0;
}