Jak používat flex s mým vlastním analyzátor?

hlasů
1

Chci opustit lexikální analýzu Lex ale rozvíjet analyzátor na vlastní pěst.

Udělal jsem hlavičku token.h který má výčty za symbolických typů a jednoduchý hierarchie tříd,

Za lex pravidla:

[0-9]+ {yylval = new NumToken(std::stoi(yytext));return NUM;}

Jak získám ukazatel NumToken z analyzátoru kódu? Dejme tomu, že chci jen vytisknout žetony ..

while(true)
{
    auto t = yylex();
    //std::cout <<yylval.data<<std::endl; // What goes here ?
}

Zvládnu to s yacc / bizon, ale nemůže najít žádnou dokumentaci nebo příklad o tom, jak to udělat ručně.

Položena 21/02/2015 v 06:57
zdroj uživatelem
V jiných jazycích...                            


1 odpovědí

hlasů
1

V tradiční bizona / flex analyzátoru, yylvalje globální proměnná je definována v analyzátoru generovaného bizonů a deklarované v záhlaví souboru vytvořeného bizonů (což by mělo být # include'd do generovaného skener). Tak jednoduché řešení by bylo jen zopakovat, že: deklarovat yylval(jako globální) v token.ha definovat jej někde v analyzátoru.

Ale moderní styl programování se posunul pryč od používání globals (pro dobrý důvod), a dokonce i flexpřinese skenery, které nejsou závislé na globálním stavu, pokud o to požádá. Žádat o skener, určete

%option reentrant

v definici skeneru. Ve výchozím nastavení, změní se prototyp yylexna adresu:

int yylex(yyscan_t yyscanner);

kde yyscan_tje neprůhledný ukazatel. (Toto je C, tak to znamená, že to je void*). Můžete si přečíst o podrobnostech v příručce Flex ; Nejdůležitější stánek s jídlem je, že můžete požádat flex také vytvořit soubor záhlaví (s %option header-file), takže další překladové jednotky mohou odkazovat na různé funkce pro vytváření, zničení a manipulaci s yyscan_t, a že je potřeba minimálně vytvořit tak, že yylexmá někam uložit svůj stav. (V ideálním případě byste ji také zničit.) [Poznámka 1].

Očekávaný způsob, jak používat vyduté skener z bisonje umožnit %option bison-bridge(a %option bison-locationpokud váš lexer generuje informace o umístění zdroje pro každou tokenu). To bude přidat další parametr s yylexprototypem:

int yylex(YYSTYPE *yylval_param, yyscan_t scanner);

S `% opcí bizon-míst, dva parametry, které znějí:

int yylex(YYSTYPE *yylval_param,
          YYLTYPE *yylloc_param,
          yyscan_t scanner);

Sémantický typ YYSTYPEa typ umístění YYLTYPEjsou není prohlášena za kódem flex-tvořil. Musí se objeví v token.hzáhlaví vám #include do skeneru.

Záměrem parametrů bizon-most je poskytnout mechanismus pro návrat sémantického hodnotu yylvalvolajícímu (tj analyzátoru). Vzhledem k tomu, yylvalje v podstatě stejný jako parametr yylval_param[Poznámka 2], bude to ukazatel na skutečnou sémantickou hodnotu, takže je třeba psát (například) yylval->data = ...ve svých flex akce.

Takže to je jeden ze způsobů, jak to udělat.

Případný jednodušší alternativou bison-bridgeje jen poskytnout svůj vlastní yylexprototyp, který můžete dělat s makro YY_DECL. Například byste mohli udělat něco takového (pokud YYSTYPE bylo něco jednoduchého):

#define YY_DECL std::pair<int, YYSTYPE> yylex(yyscan_t yyscanner)

Potom pravidlo mohl vrátit dvojici:

[0-9]+ {return std::make_pair(NUM, new NumToken(std::stoi(yytext));}

Je zřejmé, že existuje mnoho variant na toto téma.


Poznámky

  1. Bohužel, generované záhlaví obsahuje poměrně hodně zbytečné zavazadla, včetně banda definice maker pro standardní „globals“, které nebude fungovat, protože v řetězit skeneru tyto proměnné mohou být použity pouze v flex akci.

  2. Snímač generuje se bison-bridgedefinuje yylvaljako makro, které odkazuje na pole v neprůhledné státní struktury, a ukládá yylval_paramdo této oblasti. yyget_lvala yyset_lvalfunkce jsou poskytnuty za účelem získání nebo nastavení tohoto pole z vnější strany yylex. Nevím, proč; Zdá se někde mezi zbytečné a nebezpečné, protože stát bude obsahovat ukazatel na hodnotu, jak je dodáván ve volání yylex, což může být i visící ukazatel jednou vrátí volání.

Odpovězeno 21/02/2015 v 18:12
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more