Keresés

Részletes keresés

NevemTeve Creative Commons License 2018.11.22 0 0 20

Azon is elgondolkoztam, hogy hogyan legyen a rekurzió, bal- vagy jobboldalasan:

#1
program: utasítás | utasítás program

#2

programutasításprogram utasítás

 

Először naivan azt hittem, hogy az első a jobb módszer, de most a második felé hajlok.

 

Olyasmi tesztet végeztem, ahol az input 'változó=érték' utasításokból áll; ha különböző változókról van szó, akkor az értékadások sorrendje nem számít, de ha ugyanannak a változónak adok értéket kétszer (többször), akkor azt várnám, hogy az utolsó hajtódjon végre utolsónak (vagyis az jusson érvényre, ne az első).

 

A teszt szerint #1 esetén az első értékadás 'nyer', vagyis a végrehajtási sorrend fordított.

 

#2 esetén az utolsó értékadás jut érvényre, vagyis a végrehajtás sorrendje megegyezik az utasítás sorrendjével.

 

Kieg: Ezt találtam a témában olvasnivalónak

http://dinosaur.compilertools.net/yacc/index.html

 

Left Recursion

 

The algorithm used by the Yacc parser encourages so called ``left recursive'' grammar rules: rules of the form

 

name: name rest_of_rule ;

 

NevemTeve Creative Commons License 2017.11.30 0 0 19

További érdekesség ezügyben, hogy a fejlődés során az YYPARSE_PARAM megszűnt létezni... valahogy azért sikerült egy kompatibilis állapotot létrehozni 3.0.2 és 2.5 között

 

#define YYLEX_PARAM pc

 

%pure-parser
%parse-param {parser_control *pc}
%lex-param {parser_control *pc}

Ebből a legelső sor azért kell, hogy a yylex hívásakor átmenjen a 'pc' paraméter a 2.5-ben, a 3.0.2-ben már nincs ez a rész:

#ifdef YYLEX_PARAM
# define YYLEX yylex (&yylval, YYLEX_PARAM)
#else
# define YYLEX yylex (&yylval, pc)
#endif

Előzmény: NevemTeve (18)
NevemTeve Creative Commons License 2016.04.12 0 0 18

Túlreagáltam, minden mükszik, a pure-parser átszervezése volt az egész mögött, de nem kell nagy kavarás hozzá.

Előzmény: NevemTeve (17)
NevemTeve Creative Commons License 2016.04.12 0 0 17

Mondjuk ezt szívesen kihagytam volna:

$ bison -o mobipars.c -v mobipars.y
mobipars.y:64.1-12: warning: deprecated directive, use '%pure-parser' [-Wdeprecated]
 %pure_parser
 ^^^^^^^^^^^^

 

$ bison -V
bison (GNU Bison) 3.0.2

Nyilván ha átírom s/%pure-parser/%pure_parser/ akkor szépen minden más gépen is bison-verziót kell növelnem, mert azok meg az opció új formáját nem ismerik még.

NevemTeve Creative Commons License 2014.11.01 0 0 16

Ez talán érdekes lehet, egy másik fórumból: http://www.linuxquestions.org/questions/showthread.php?p=5228567

NevemTeve Creative Commons License 2014.08.01 0 0 15

A lényeg: a $$ a szabály végén lévő kód esetén a szabály kimenetét jelenti, a szabály belsejében lévő kód esetén egy lokális értéket a vermen. Maga a bison doksi is hoz egy példát, épp most leltem:

 

stmt:

LET

'('

var

')'
{ $<context>$ = push_context (); declare_variable ($3); }
stmt

{ $$ = $6; pop_context ($<context>5); }

Itt az ötös elem (vagyis a $5) az a beágyazott kódrészlet, ami értékőrzőül szolgál (saját magán belül $$ az érték, a továbbiakban meg $5 -- szerintem nem egészen intuitív, talán jobb lenne, ha önmagában is menne a $5 (de nem megy)).

 

 

És mivel nincs neve, nem lehet %type-ot se mondani rá, ezért ezzel a furcsa szintaxissal kell típuskényszeríteni (ha egyáltalán használunk %type-ot, az én előző példámban épp nem használtunk))

Előzmény: NevemTeve (14)
NevemTeve Creative Commons License 2014.08.01 0 0 14

Nem mondhatnám, hogy különösebben értem, de itt egy példa-féle: egy if-számláló, amit a beágyazott if-ek miatt mentünk és visszaállítunk

 

if:     IF                { $$.ifcounter= ++ifcounter;
                            ++ifnest;
                            fprintf (stderr, "line %ld: before if, set ifcounter to %d, be
st=%dn",
                                lineno, ifcounter, ifnest);
                            fflush (stderr); }
        '(' expr ')' stmt
        opt_else          { $$.obj = NIF3($4, $6, $7);
                            ifcounter= $2.ifcounter;
                            --ifnest;
                            fprintf (stderr, "line %ld: after if, reset ifcounter to %d, ifnest=%dn",
                                lineno, ifcounter, ifnest);
                            fflush (stderr); };

opt_else:                 { $$.obj = NULL; }
        | ELSE stmt       { $$.obj = $2.obj; };

Előzmény: NevemTeve (1)
NevemTeve Creative Commons License 2010.04.07 0 0 13
Azóta fejlesztettem, kérésre a felesleges részekezt kinyiszálja:

input: <valami:tag masvalami:fld="value"/>

output:
<tag
fld
=
"value"
/>
Előzmény: NevemTeve (8)
NevemTeve Creative Commons License 2008.02.04 0 0 12
Mindent lehet, ha valaki akarja... én pl nem akarom...
Előzmény: DJG (11)
DJG Creative Commons License 2008.02.03 0 0 11
Ja. A Monót nem lehet AIX-re lefordítani? Unix, elvégre, és Solaris már van belőle...

Üdv,
Gábor
Előzmény: NevemTeve (10)
NevemTeve Creative Commons License 2008.02.03 0 0 10
Alapvetően BS2000 és AIX platformon kell mennie.
Előzmény: DJG (9)
DJG Creative Commons License 2008.02.03 0 0 9
Ahhoz még nem éreztél kedvet, hogy ilyen feladatokra a .NET-et használd (vagy Monót, ha Linux?). Jó, tudom, fujj, Microsoft, elvileg egyetértek, de muszáj bevallani, hogy ezt véletlenül nagyon jól megcsinálták.

Üdv,
Gábor
Előzmény: NevemTeve (8)
NevemTeve Creative Commons License 2008.01.28 0 0 8
De rég volt itt bármi is... annyir mondanék, hogy azóta is használom XML-parsolásra a yacc-ot (bisont, pontosabban), főleg azóta lett még szebb az élet, hogy a lexikális elemzővel megbeszéltem, hogy az ilyeneket egy lexikális egységként adja vissza:
input: <valami:tag valami:fld="value"/>
output:
<valami:tag
valami:fld
=
"value"
/>
NevemTeve Creative Commons License 2006.05.29 0 0 7
Azon kezdtem gondolkozni, hogy lehet-e multithread-ben használni a generált parser-t, úgy látom hogy a bison-nal lehet, némileg módosítani kell a programot.
http://osr600doc.sco.com/cgi-bin/info2html?(bison.info)Pure%2520Decl&lang=en
NevemTeve Creative Commons License 2004.12.22 0 0 6
Nem, mint mondtam, a Yacc egy programozási nyelv, amit a yacc nevű program C-re fordít. Nem általános célú nyelv, kifejezetten csak egy dologra jó: fordítóprogramokat lehet benne/vele készíteni.
Az slx és sly nekem nem mond semmit, nézz bele text-editorral, esetleg pasztézz be részleteket.
Előzmény: terrigena (4)
DJG Creative Commons License 2004.12.22 0 0 5
Nem, itt egészen másról van szó.

A fordítóprogramoknak a beérkezô forrásszöveget lexikálisan (mi egy azonosító, mi egy szám, satöbbi) elemezniük kell, majd az így felismert lexikai elemeket a lefordítani kívánt nyelv szintaktikai szabályai szerint fel kell dolgozniuk. Ez utóbbi lépés során azt is fel kell ismerniük, hogy milyen lexikai elemek milyen sorrendben és milyen összefüggések szerint következhetnek egymás után.

A lex-yacc-flex-bison és hasonló programok arra szolgálnak, hogy ha egy elemzendô programozási nyelv lexikai és szintaktikai szabályait formálisan leírod, akkor ebbôl ôk el tudják készíteni az adott nyelvet elemzô programot. Azaz, ezek programot generáló programok, és arra használják ôket, hogy a fordítóprogramok ilyen elemzéssel foglalkozó részét ne kézzel kelljen megírni. Több oka is van, hogy ez miért elônyös (túl a nyilvánvaló munkamegtakarításon), de ez már messze vezetne.

Üdv,
Gábor
Előzmény: terrigena (4)
terrigena Creative Commons License 2004.12.21 0 0 4
Köszi a gyors választ. A meghatározásából ítélve (parser generator - nyelvelemző) tovább tökéletesíti a c kódot? Egyébként a projekthez tartozik egy y fájl, meg egy slx és egy sly kiterjesztésű. Gondolom ezek is a bisonhoz tartozik, mert egymás mellett vannak azonos névvel (macro). Ők mire valók?
Előzmény: NevemTeve (3)
NevemTeve Creative Commons License 2004.12.21 0 0 3
Kérlek tisztelettel, a yacc (bison) egy fordítóprogram, amely yacc nyelvű forrásprogramból (.y kiterjesztés), C-nyelvű output-ot (.c kiterjesztés) állít elő. (Nevezhetjük előfordítónak (precompiler) is.)
Tehát a lényeg: nem helyettesíthető se C-fordítóval, se Assembler-rel, se Text-editorral, önálló program, önálló feladattal.
Előzmény: terrigena (2)
terrigena Creative Commons License 2004.12.21 0 0 2
Hinnye, nem szeretném elrontani a monológodat (remélem, azóta rájöttél a helyes megoldásra), viszont szakértőnek nézel ki a témában: Tegnapelőtt futottam bele életemben először a Bisonba, le kellett töltenem és telepítenem, hogy az xHarbour fordító buildjét lefuttathassam. Néhány órát ugyan eltöltöttem a dokumentációk értelmezésével, de a kulcsproblémára nem jöttem rá: mi a túrót is csinál még pluszban, miért nem elég a Borland C fordító? Ha néhány keresetlen mondatban felvilágosítnál a lényegről...
Előzmény: NevemTeve (1)
NevemTeve Creative Commons License 2004.11.10 0 0 1
Igényesebb esetben (tehát ha %union-t használunk):

%type type type
%type name var

dekl: type { $<type>$ = lasttype /* save old value */; lasttype = $1}
vars { lasttype = $<type>2 /* restore old value */}

vars: var more_vars {CreateVar($1,lasttype);}
'(' dekl ')' more_vars;
Előzmény: NevemTeve (0)
NevemTeve Creative Commons License 2004.11.10 0 0 0
Naná hogy 0 (azaz $0) sikerem volt... viszont a következő működik:

dekl: type { $$.type = lasttype /* save old value */; lasttype = $1.type}
  vars { lasttype = $2.value; /* restore old value */}

közben a vars-t teszteléshez kibővítettem:

vars: var more_vars {CreateVar($1.name,lasttype);}
  '(' dekl ')' more_vars;

more_vars: | ',' vars;

tesztadat:

NUMBER I,(STRING S,T,(NUMBER K,L)),J;

Mondjuk azt nem állítom, hogy ennek a beágyazott deklarációnak így lenne értelme,
de tesztelésre jó... egyébként C-ben van valami hasonló: int i,j,f(int (*g)(int k)))
NevemTeve Creative Commons License 2004.11.10 0 0 topiknyitó
Például a következőn törpölök:

dekl: type vars ';'

type: NUMBER {lasttype= P_NUMBER} | STRING {lasttype=P_STRING};

vars: var {CreateVar($1.name,lasttype)} | var ',' vars {CreateVar($1.name,lasttype)}

tehát változókat akarok deklarálni,
"NUMBER i,j,k;" avagy "STRING s,t;" formában.
Az egyes változókat a CreateVar hozza létre, paramétere a név és a típus.
Itt a gondom: honnan tudom hogy mi volt a tipus? Azt találtam ki, hogy beleteszem
a globalis 'lasttype' valtozóba, de ez nem igazán elegáns, inkább egy vermet kellene használni erre... csakhogy már amúgy is az elemzőnek verme... kérdés, hogy hozzáférek-e a kérdéses elemhez $0 vagy $-1 vagy valami ilyesmi módszerrel?

type: NUMBER {$$.type= P_NUMBER} | STRING {$$.type=P_STRING};

vars: var {CreateVar($1.name,$-1.type)} | var ',' vars {CreateVar($1.name,$-1.type)}

Talán legjobb lesz ha mindjárt ki is próbálom...

Ha kedveled azért, ha nem azért nyomj egy lájkot a Fórumért!