Portál AbcLinuxu, 25. dubna 2024 09:04

Jak se píše programovací jazyk 2: Lexer

9.2.2019 23:08 | Přečteno: 3341× | Obecné IT | Výběrový blog | poslední úprava: 11.2.2019 14:13

V předchozí části jsem popsal motivaci, jenž mě zavedla na trnitou cestu vývojářů vlastního jazyka. V dnešní části se podíváme na to jak vlastně má můj jazyk vypadat a taky se na první a pravděpodobně nejjednodušší komponentu: lexer.

Self

Základní syntaxi Selfu dobře popisuje následující obrázek:

Pokud by vás zajímaly podrobnosti, doporučuji anglickou wikipedii, Self handbook, či můj paralelně vycházející seriál Prostředí a programovací jazyk Selfu.

tinySelf

tinySelf, jak jsem se kdysi nerozvážně (ukázalo se, že stejně pojmenovaný projekt už kdysi existoval) rozhodl můj jazyk nazvat, je v podstatě Self, i když trochu „vylepšený“ po stránce syntaxe.

Například jsem přidal podporu pro kaskády (;), jak je používá Smalltalk. Nikdy jsem nechápal, proč v původním Selfu nejsou, když tam dokonale sednou. Taky jsem změnil "komentář" na # komentář, protože uvozovky se podle mého názoru víc hodí na stringy, než na komentáře a také se lépe píšou na české klávesnici, než standardní Selfovské 'stringy' psané jednoduchými uvozovkami. Pro stringy je nyní možné používat obojí, což člověku šetří escapování, pokud zrovna potřebuje napsat string s uvozovkami.

Kromě toho jsem změnil i syntaxi objektů a bloků, kde jsem umožnil vynechání otevíracího |, takže je možné psát (slot |) místo (| slot |). K parsování to stejně není zapotřebí a vždycky mi to přišlo jako zbytečný opruz. Chtěl jsem přidat i (| code), ale ukázalo se, že to už parseru vadí hodně, takže je nutné zapisovat objekty bez slotů jako (|| code).

Oproti Selfu také není podtržítko na začátku zprávy rezervované pro volání primitivních zpráv. _s je normálně použitelná unární zpráva. Primitivní zprávy (volání nativního kódu interpretru) jsou implementované jako zprávy poslané objektu primitive. Primitivních zpráv je stejně v běžném kódu minimum, tak mi nikdy nebylo jasné, proč by pro ně měla být vyhrazená syntaxe.

Repozitář je momentálně hostovaný na githubu:

Lexer

Psaní jazyka začíná lexerem. Ten definuje, z jakých komponent se jazyk skládá rozřezáním zdrojového kódu na tokeny. Ve standardním imperativním jazyce to můžou být různé příkazy, definice funkce, if podmínky, klíčová slova a tak podobně. V tinySelfu je to vesměs definice objektů, slotů, bloků, nebo posílání zpráv mezi nimi.

Lexer vám kód rozřeže na pole jednotlivých elementů. Z kódu jako:

(| asd = 1 | ^asd.)

vám udělá pole ve stylu:

[
  Token("OBJ_START", "("),
  Token("SEPARATOR", "|"),
  Token("IDENTIFIER", "asd"),
  Token("ASSIGNMENT", "="),
  Token("NUMBER", "1"),
  Token("SEPARATOR", "|"),
  Token("RETURN", "^"),
  Token("IDENTIFIER", "asd"),
  Token("OBJ_END", ")")
]

Výstupem je plochá struktura, do které byl rozřezán vstupní řetězec a kde byly ke každé části přiřazeny typy tokenu.

Lexer je možné si napsat ručně, formou stavového automatu, který v cyklu prochází kód znak po znaku a postupně ho rozřezává a analyzuje rozřezané kousky (tokeny), aby jim přisoudil typ. Kdysi jsem něco podobného z neznalosti a z nutnosti udělal (tenkrát v D nebyl žádný lexer), když jsem si psal HTML parser, proto mi věřte, když vám tento přístup DÚRAZNĚ NEDOPORUČÍM.

Jedná o nepružný, k chybám náchylný, na pochopení složitý a těžce udržitelný přístup. Až na některé velmi speciální případy, kdy přesně víte co děláte a proč, se vám vždy vyplatí použít nějakou knihovnu, kterou nakrmíte popisy tokenů a ona vám stavový automat na základě popisu vygeneruje.

V mém případě se jedná o knihovnu rply (podrobnosti přinese příští díl), konkrétně část rply.LexerGenerator.

tinySelfové tokeny

tinySelf je tvořen následujícími tokeny:

SELF

Klíčové slovo self tvoří token Self. Použití je podobné jako třeba v pythonu, či this v javě.

NUMBER

Čísla. 5 je číslo. -5 je číslo. 4.32 je taky číslo, stejně jako 0xFF.

OBJ_START

Začátek definice objektu. Jedná se jednoduše o závorku ( za níž následuje zbytek objektu.

OBJ_END

Ukončovací závorka ) značící konec objektu. Nejkratší (prázdný) objekt v Selfu je ().

BLOCK_START

Začátek bloku [. Bloky jsou objekty, které mají parenta nadefinovaného na lokální scope, takže se chovají podobně jako lambda funkce.

BLOCK_END

Konec bloku ]. Nejkratší blok vypadá takhle; [].

SINGLE_Q_STRING a DOUBLE_Q_STRING

Definice stringů. Jak jsem zmiňoval, bere se 'string' a "string" se standardníma escape sekvencema.

FIRST_KW

V Selfu existují tři druhy zpráv objektům; unární, binární a keyword. Unární nepřijímá žádný parametr. Binární jeden, keyword pak libovolný počet.

Self přinesl oproti Smalltalku drobné vylepšení, kde keyword zprávy jsou jednoznačně parsovatelné prostým okem tím, že vynucuje každé následující klíčové slovo zprávy začínat velkým písmenem.

Ve Smalltalku může zpráva at: 1 put: 2 znamenat buď (at: 1) put: 2, tedy poslání zprávy at: a následné poslání zprávy put: výsledku z prvního volání, nebo poslání zprávy at:put: se dvěma parametry 1 a 2. V Selfu je nutné druhý popsaný případ zapsat jako at: 1 Put: 2, což jednoznačně identifikuje kde keyword zpráva začíná a končí. Proto taky lexer rozlišuje začátek keyword zprávy (string začínající malým písmenem s dvojtečkou na konci) a pokračování.

KEYWORD

Zmiňované pokračování zprávy. String začínající velkým písmenem, s dvojtečkou na konci.

IDENTIFIER

String začínající malým či velkým písmenem, či podtržítkem následující tím samým, či číslicí. asd, BSD, _A či _35 jsou validní identifikátory, respektive unární zprávy.

OPERATOR

Jako operátor (binární zprávu) je možné použít znaky z množiny: !@$%&*-+~/?<>, v libovolném počtu opakování. @ je operátor, stejně jako @@.

Operátory vždy očekávají jeden parametr. a + b je binární zpráva oprerátoru + s parametrem b zaslaná objektu a.

ARGUMENT

Hlavně u bloků je potřeba napsat co za argumenty přijímají. Argumenty se zapisují jako identifikátory začínající dvojtečkou.

Ukázky:

ASSIGNMENT

Speciální operátor přiřazení. Má význam v definici slotů, kde definuje sloty pouze ke čtení. Také je ho možné použít jako běžný operátor (binární zprávu). Zapisuje se jako znak pro rovná se (=).

RW_ASSIGNMENT

Přiřazení do slotu ke čtení i zápisu. Takto jde přiřazovat pouze konstanty, nebo reference na jiné objekty, nikoliv metody.

Zapisuje se jako šipka do leva (<-).

RETURN

Vrácení hodnoty z objektu / bloku. Zapisuje se jako stříška (^).

END_OF_EXPR

Konec výrazu. Odděluje řetězce zpráv. Zapisuje se stejně jako ve Smalltalku tečkou (.).

SEPARATOR

Oddělovač slotů od kódu. Zapisuje se jako svislá čárka (|).

CASCADE

Vyhrazený operátor kaskády. Zapisuje se jako středník (;). Sděluje interpretru, že následující zpráva se posílá stejnému objektu jako předchozí.

COMMENT

Komentář začínající #, končící koncem řádku.

Ještě k lexeru

Může se zdát, že v lexeru je toho spousta, ale ve skutečnosti je celý jazyk dost jednoduchý a ukázka všeho co je v něm možné se vejde tak nějak na pohlednici:

()  # Prázdný objekt.
(| |)  # Taky prázdný objekt, ale s definicí (prázdných) slotů.
(| slot |)  # Objekt obsahující jeden slot (key/val storage, kde slot = nil.).

# Objekt obsahující definice dvou  slotů; read only ‚s‘ a zapisovatelného slotu ‚s2‘.
# Ekvivalentní slovníku {"s": None, "s2": 1}, když pominu zapisovatelnost slotů.
(| s = nil. s2 <- 1 |)

# Objekt obsahující slot ‚s‘, a taky kód, který tomuto slotu pošle unární zprávu ‚printLine‘. Poslední výraz je vždy vrácen, takže bude vrácena hodnota slotu ‚s‘.
(s = 1 | s printLine. s)
(| s = 1. | s printLine. ^s. )  # Totožný kód jako v předchozím případě s alternativní syntaxí slotů a explicitní return.

[ ]  # prázdný blok
[:a | a printLine. a]  # blok přijímající parametr ‚a‘, který vypíše posláním zprávy ‚printLine‘ a vrátí.
[| :a | a printLine. exit: a.]  # totožný kód - return v bloku vrací z nadřazeného scope, nikoliv jen z bloku samotného!.

# Komplexnější objekt obsahující asi všechny elementy jazyka.
( a = 1. b <- 2. c |
  (a + b) > 0
    ifTrue: [c: a+b. ^c]
    False: [self logger log: a; log b.].

  logger log: 'Vsechny zpravy se prvne resolvuji na Self'.
  self logger log: "Toto je tedy totozna zprava".

  ^ (| output = "vysledek". line <- "metody" |)
)

Celý kód lexeru se vejde na 40 řádek a jde jen o definici jednotlivých elementů jazyka pomocí regexpů:

# -*- coding: utf-8 -*-
from rply import LexerGenerator


lg = LexerGenerator()
lg.ignore(r'\s+')

lg.add('SELF', r'self')

lg.add('NUMBER', r'(0x[0-9a-fA-F]+)|((\-)?\d+(\.\d)?)')

lg.add('OBJ_START', r'\(')
lg.add('OBJ_END', r'\)')

lg.add('BLOCK_START', r'\[')
lg.add('BLOCK_END', r'\]')

lg.add('SINGLE_Q_STRING', r"'(?:\\.|[^'\\])*'")
lg.add('DOUBLE_Q_STRING', r'"(?:\\.|[^"\\])*"')

lg.add('FIRST_KW', r'([a-z_][a-zA-Z0-9_]*\.)*[a-z_]+[a-zA-Z0-9_]*:')
lg.add('KEYWORD', r'[A-Z]+[a-zA-Z0-9_]*:')
lg.add('ARGUMENT', r':[a-zA-Z_]*[a-zA-Z0-9_]+')

lg.add('RW_ASSIGNMENT', r'\<-')

lg.add('OPERATOR', r'[!@\$%&\*\-\+~/?<>,]+|==+')
lg.add('RETURN', r'\^')
lg.add('END_OF_EXPR', r'\.')
lg.add('SEPARATOR', r'\|')
lg.add('CASCADE', r'\;')

lg.add('IDENTIFIER', r'([a-zA-Z_][a-zA-Z0-9_]*\.)*[a-zA-Z_]*[a-zA-Z0-9_\*]+')


lg.add('ASSIGNMENT', r'=')

lg.add('COMMENT', r'#.*[\n|$]?')


lexer = lg.build()

Možná se někdo pozastaví, proč je kód psaný v pythonu 2. Důvod je jednoduchý - pypy v době psaní stále ještě nepodporuje nejnovější python3 v rpython translator toolkitu. Jakmile tam bude podpora pythonu 3.6, mám v plánu kód přeportovat.

Pokračování

V příštím díle se podíváme na parser, který tokeny bere a sestavuje z nich AST - abstraktní syntaktický strom.

       

Hodnocení: 100 %

        špatnédobré        

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře. , Tisk

Diskuse byla administrátory uzamčena

9.2.2019 23:44 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Lexer je možné si napsat ručně, formou stavového automatu, který v cyklu prochází kód znak po znaku a postupně ho rozřezává a analyzuje rozřezané kousky (tokeny), aby jim přisoudil typ. Kdysi jsem něco podobného z neznalosti a z nutnosti udělal (tenkrát v D nebyl žádný lexer), když jsem si psal HTML parser, proto mi věřte, když vám tento přístup DÚRAZNĚ NEDOPORUČÍM.
S tímhle teda úplně souhlasit nemůžu. Mám zkušenost s několika lexer- nebo parser-generátory hlavně z prostředí C++ a Rustu a moje zkušenosti je taková, že na jednu stranu sice pomůžou, ale na druhou jsem vždycky musel s tím generátorem nějakým způsobem bojovat, objevovat jeho limitace a překonávat je (kolikrát složitě). (Typicky error handling je problém, ale i jiné věci.)

Naopak se poslední dobou kloním k názoru, že slušně ručně napsaný lexer / parser je kolikrát lepší. Zejména pokud má použitý programovací jazyk třeba pattern matching a/nebo jiné FP prvky, umožňuje to napsat parsery relativně velmi pěkně. Někde v šuplíku mám v Rustu ručně napsaný parser VT-102, se kterým jsem byl co do korektnosti / čitelnosti / mantainability mnohem spokojenější než s přechozími pokusy pomocí parser-generátorů. U toho odkazovaného HTML parseru mi ani tak nepřijde jako problém, že je napsaný ručně, ale spíš že ten state machine a přechody mezi stavy jsou někde ve funkčních scopech a nejsou dostatečně explicitní. Napříkad jedna možnost, jak to zpřehlednit, by mohlo být mít na to objekt, který by držel stav a například by volal pro každý stav nějakou metodu, která by jako návratovou hodnotu vracela následující stav (to je jen nápad, jsou samozřejmě i jiné cesty).

Tím nechci říct, že je potřeba všechno parsovat ručně, nicméně ruční lexer/parser bych určitě nezavrhoval.
What Big Oil knew about climate change
9.2.2019 23:55 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Naopak se poslední dobou kloním k názoru, že slušně ručně napsaný lexer / parser je kolikrát lepší.
Souhlasím, že bude lepší z hlediska toho že ti umožní dělat víc věcí, ale nejsem spíš si nemyslím, že bude lepší z hlediska třeba udržovatelnosti, nebo například modifikovatelnosti. Dejme tomu že chceš přidat nový druh stringů třeba, něco jako raw stringy v pythonu. Jak moc toho najednou musíš přepisovat a upravovat? Nebo jsem možná jen nenašel vhodný pattern jak to dělat čitelně, hm.
10.2.2019 00:47 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Dejme tomu že chceš přidat nový druh stringů třeba, něco jako raw stringy v pythonu. Jak moc toho najednou musíš přepisovat a upravovat?
Myslimže zrovna ten případ přidání raw stringu složitý nebude, ale co se modifikovatelnosti obecně týče, umim si představit, že to problém minimálně v některých případech může být. Na ten ruční parser typicky potřebuješ mít dopředu známmý ten stavový automat a tím můžou změny zahýbat.
Nebo jsem možná jen nenašel vhodný pattern jak to dělat čitelně, hm.
Ten VT parser jsem strukturoval tak, že to byla dvojice interní stav a dispatch objekt. Dispatch objekt byl definovaný jinde a ten dostával 'hotová' data ve chvíli, kdy byly k dispozici (push parsing). Interní stav držel stavový enum parseru + trochu nějaká dodatečná data jako parametry escapů a podobně. Vstupem byla metoda input s parametrem bajt (VT je v podstatě streamovaný binární protokol, který je nutný parsovat bajt po bajtu), ve který se akorát podle aktuálního stavu bajt poslal do nějaké metody, ze které vypadl stav pro následující bajt.

Pro parsování textových non-streaming formátů tohle možná není až tak vhodný přístup. Budu potřebovat v dohledné době napsat parser pro textový markdown-like formát, mám to aktálně napsáno v PEGu, ale saje to, nejsem s tim spokojen. Ještě se nad tím zamyslim, jak to nejlíp strukturovat. Například mě napadá, že by se vstupní data daly rozpadnout na znaky významné pro lexing/parsing, které by parser bral jednotlivě, a shluky znaků nevýznamné (ie. nezpůsobující změnu stavu) by se daly zpracovávat vcelku.

V případě tvého tinySelfu ten rply vypadá IMHO v pohodě. Ačkoli zatím neznám tu interakci s parserem a taky nezmiňuješ, jak dobře reportuje syntaktické chyby.
10.2.2019 01:39 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
V případě tvého tinySelfu ten rply vypadá IMHO v pohodě. Ačkoli zatím neznám tu interakci s parserem a taky nezmiňuješ, jak dobře reportuje syntaktické chyby.
Je to docela v pohodě, ale jak jsem psal, už jsem tam taky narazil, když jsem chtěl parsovat (| code), což prostě asi tenhle druh parseru vůbec nedá. Bude o tom víc příští díl zase za týden.
10.2.2019 11:13 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Je to docela v pohodě, ale jak jsem psal, už jsem tam taky narazil, když jsem chtěl parsovat (| code), což prostě asi tenhle druh parseru vůbec nedá. Bude o tom víc příští díl zase za týden.
Moje intuice je, že tím přidáním toho (| code) se z gramatiky jazyka stává context-sensitive gramatika, protože když budeš mít (| xxx) versus (| xxx | yyy), tak to xxx se parsuje jinými pravidly v závislosti na tom, jestli pak následuje '|', nebo ')'.

rply neznám, ale vypadá to, že je založen na EBNF a (E)BNF ti context-sensitive jazyk skutečně nezparsuje, umí jen context-free gramatiky. Ale dají se dělat všelijaké triky, viz např. co v podobné situaci dělá python.

Disclaimer: Neudělal jsem si rigorózní analýzu té gramatiky a nezkusil aplikovat Pumping lema a/nebo Ogden's lema, takže můžu kecat, jsou to jen dva centy.
10.2.2019 18:53 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
rply neznám, ale vypadá to, že je založen na EBNF a (E)BNF ti context-sensitive jazyk skutečně nezparsuje, umí jen context-free gramatiky. Ale dají se dělat všelijaké triky, viz např. co v podobné situaci dělá python.
Jo, k tomu jsem taky dospěl.
Disclaimer: Neudělal jsem si rigorózní analýzu té gramatiky a nezkusil aplikovat Pumping lema a/nebo Ogden's lema, takže můžu kecat, jsou to jen dva centy.
Já jsem parsery nikdy nestudoval, tak jsem to prostě udělal jak to šlo. Upřímně nemám moc tušení co s tím dělat, mrknu na to co jsi linkoval.

Co se týče chybových hlášek, tak ty jsem zatím neřešil vůbec, s tím že na to bude čas pokud z toho někdy něco bude, neboť nemá smysl zabít rok psaním parseru, když to pak zahodíš jako hračku co tě už omrzela.
10.2.2019 20:55 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Co se týče chybových hlášek, tak ty jsem zatím neřešil vůbec, s tím že na to bude čas pokud z toho někdy něco bude, neboť nemá smysl zabít rok psaním parseru, když to pak zahodíš jako hračku co tě už omrzela.
To je dobrá poznámka a ve stejném duchu bych asi neřešil tu syntaxi (| code) , pokud ti ta syntaxe (|| code) napřijde nějak výrazně debilní. Ono když to člověk s těmi convenience syntaxemi přežene, tak se mu pak taky může stát, že ten jazyk vůbec parsovat nepůjde :-D

No nic, už tě nechám žít a počkám na další díl...
10.2.2019 21:28 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
To je dobrá poznámka a ve stejném duchu bych asi neřešil tu syntaxi (| code) , pokud ti ta syntaxe (|| code) napřijde nějak výrazně debilní.
Ono to má řešení přes (code), což třeba v Selfu funguje. Bohužel jsem se ale rozhodl tuhle syntaxi znásilnit pro prioritizaci zpráv a unfucknout to není úplně triviální. Sice vím jak na to, ale hodina co jsem tomu věnoval nestačila.
No nic, už tě nechám žít a počkám na další díl...
Náhodou super, já to dělám +- naslepo, tzn nečetl jsem žádné knihy jak ‚se to má dělat‘ ani jsem to neměl na VŠ, takže každá rada dobrá.
10.2.2019 23:55 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
rply neznám, ale vypadá to, že je založen na EBNF a (E)BNF ti context-sensitive jazyk skutečně nezparsuje, umí jen context-free gramatiky. Ale dají se dělat všelijaké triky, viz např. co v podobné situaci dělá python.
Tak jsem to četl a je to jedna z těch věcí, co mě taky napadla, tedy udělat z (| samostatný token.

Celkově jsem se nad tím zamýšlel a je možné, že časem ten parser úplně předělám. Teď to má ale nejmenší prioritu, momentálně se snažím zvednout výkon. Milion cyklů (kde podmínka je lambda/blok) mi žere požád před 3.5 vteřin a rád bych to dostal někam ke sto milisekundám; Speedups of the interpreter.
11.2.2019 09:32 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Tak jsem to četl a je to jedna z těch věcí, co mě taky napadla, tedy udělat z (| samostatný token.
IMHO tím si nepomůžeš, neřeší to tu ambiguitu mezi (| xxx | yyy) a (| xxx) ve chvíli, kdy je parser u xxx a neví, jakými pravidly to zparsovat.

Asi bys musel to xxx by default parsovat jako definici slotů a ve chvíli, kdy by parser narazil na konec objektu nebo non-slot syntax (tj. chybu), přidal by uměle na začátek objektu ještě jeden ten separátor a pokusil se to znovu zparsovat jako (|| code) . Ale je to poněkud hack.
10.2.2019 22:45 deda.jabko | skóre: 23 | blog: blog co se jmenuje "každý den jinak" | za new york city dvakrát doleva a pak už se doptáte
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Mám zkušenost s několika lexer- nebo parser-generátory hlavně z prostředí C++ a Rustu a moje zkušenosti je taková, že na jednu stranu sice pomůžou, ale na druhou jsem vždycky musel s tím generátorem nějakým způsobem bojovat, objevovat jeho limitace a překonávat je (kolikrát složitě)
Vidim to podobne, ale hodne se mi osvedcil ANTLR, tam se mi dari vetsina veci udelat docela bezbolestne.
Asi před rokem se dostali hackeři na servry Debianu a ukradli jim zdrojové kódy.
10.2.2019 03:19 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Možná se někdo pozastaví, proč je kód psaný v pythonu 2. Důvod je jednoduchý - pypy v době psaní stále ještě nepodporuje nejnovější python3 v rpython translator toolkitu. Jakmile tam bude podpora pythonu 3.6, mám v plánu kód přeportovat.
Mimochodem zrovna vyšlo Düsseldorf Sprint Report 2019, kde se píše:
Catching up with CPython 3.7/3.8 – we are planning to release 3.6 some time in the next few months and we will continue working on 3.7/3.8.
blog.rfox.eu
10.2.2019 09:50 wamba | skóre: 38 | blog: wamba
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Tohle [a-zA-Z_]*[a-zA-Z0-9_]+ mi nějak nedává smysl, je to totéž, jak [a-zA-Z0-9_]+ ne? Nemělo by to tam být bez té hvězdičky [a-zA-Z_][a-zA-Z0-9_]+.
This would have been so hard to fix when you don't know that there is in fact an easy fix.
10.2.2019 11:24 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Tohle [a-zA-Z_]*[a-zA-Z0-9_]+ mi nějak nedává smysl, je to totéž, jak [a-zA-Z0-9_]+ ne? Nemělo by to tam být bez té hvězdičky [a-zA-Z_][a-zA-Z0-9_]+.
IMHO by to mělo být [a-zA-Z_][a-zA-Z0-9_]*, ten [a-zA-Z_][a-zA-Z0-9_]+ by ti nevzal jednoznakový identifikátor.
10.2.2019 18:33 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
+1, máš pravdu. Testy s tím projdou, takže jsem to změnil na [a-z_][a-zA-Z0-9_] (viz to co psal dole Pavel).
10.2.2019 09:54 pc2005 | skóre: 38 | blog: GardenOfEdenConfiguration | liberec
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Lexer je možné si napsat ručně, formou stavového automatu, který v cyklu prochází kód znak po znaku a postupně ho rozřezává a analyzuje rozřezané kousky (tokeny), aby jim přisoudil typ.
To tak jsem psal FPGA xdlrc parser v perlu :-D. Zároveň jsem se na tom ale učil význam položek toho xdlrc.
Intel meltdown a = arr[x[0]&1]; karma | 帮帮我,我被锁在中国房
10.2.2019 17:10 Pavel Křivánek | skóre: 29 | blog: Kvičet nezávaznou konverzaci
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer

Omezení počátečních písmen následujících částí klíčových slov na velká písmena začíná postrádat původní smysl, jakmile může první část začínat na velké písmeno. Protože pak jde mít zprávu Put: a v uvedeném případe rovněž nevíš, jestli se jedná o novou další zprávu nebo pokračování té předchozí. Přijít ale zase o možnost začínat jména zpráv velkým písmenem, jako to má Self, je hodně velká cena. Je to tedy vlastně jen vynucená konvence (což ovšem také dává smysl).

Překvapuje mě, že nikde nevidím resend (řizený, neřízený) nebo nějakou obdobu. Tvůj jazyk ho nemá?

Používá tvůj jazyk indexování od jedničky nebo od nuly?

I'm sure it crashed in the most type-safe way possible.
10.2.2019 18:29 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Omezení počátečních písmen následujících částí klíčových slov na velká písmena začíná postrádat původní smysl, jakmile může první část začínat na velké písmeno.
Upřímně, poslední dobou mám pocit že občas fetuju, protože jsem to omezit chtěl, ale vůbec nemám tušení proč jsem to neudělal. I tohle je ale dobrý důvod proč tyhle věci publikovat, protože více oči prostě víc vidí.
Překvapuje mě, že nikde nevidím resend (řizený, neřízený) nebo nějakou obdobu. Tvůj jazyk ho nemá?
Má, jen se dopočítává později z identifikátorů.
Používá tvůj jazyk indexování od jedničky nebo od nuly?
Od nuly.
11.2.2019 01:28 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Nedá mi to a musím se vskutku podivit nad anonymem, kterého neustále baví přidávat různé „vtipné“ štítky, jako třeba programování jako záškrt.

Chci jen říct, že je mi tě fakt upřímně líto. V rukou potenciál změnit svět k obrazu svému, a jediné co z tebe leze jsou štítky s „humorem“ na úrovni žáka třetí třídy. Nechtěl bych být v tvé kůži. Aspoň doufám, že tě k tomu snad tlačí okolnosti a ne třeba duševní porucha.
blog.rfox.eu
11.2.2019 11:25 _
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Tak nevím, ale přijde mi lepší dělat si z tvého článku prdel (byť infantilním způsobem), než ho brát vážně...
11.2.2019 04:00 tom11111
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
V popisu tokenu COMMENT máš asi chybku, má začínat #, ne středníkem. A samotné slovo COMMENT není zformátováno jako nadpis. Jinak zajímavé, přečtu si i další díl :)
11.2.2019 13:02 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Díky za upozornění, opraveno.
11.2.2019 08:06 Stanislav Bohm
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
O takovy hybrid Selfu/Io/Pythonu jsem se pred 10 lety take pokousel. Bohuzel vetsina dokumentace je jiz ztracena, zdrojak jsem pred nejakym casem ale zachranil:

https://github.com/spirali/kreatrix

Mel jsem i vetvi s JIT compilerem (nad libjit), ale tu uz jsem nedotlacil do masteru.

Dekuji za clanek, vyvolava to ve mne vzpominky:)

11.2.2019 13:05 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Zajímavé.
11.2.2019 11:12 _
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
To muselo dát příšernou práci. A přitom taklová blbost, co?
11.2.2019 13:05 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
<insert random meme />
11.2.2019 14:36 sad
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Tak tohle je docela vtipné. Jak jsi ty štítky zmínil v diskuzi, tak jsem si je prohlížel a zkoumal, jak vlastně fungují, a najednou vidím, že je máš zobrazené u zápisku. Takže ty štítky od A jsou ode mě. Sorry.

Tuhle zajímavou funkci bych z abíčka asi odstranil.

Jinak zajímavý zápisek, sice Smalltalk neumím a kompilátory se teprve učím, ale mám určitou představu, o čem tu je řeč, a docela se těším na vytvoření a vyhodnocení toho AST.

Za ty štítky se ještě jednou omlouvám, nevěděl jsem, že to tady můžeš tak super naklikat.
11.2.2019 15:41 Bystroushaak | skóre: 36 | blog: Bystroushaakův blog | Praha
Rozbalit Rozbalit vše Re: Jak se píše programovací jazyk 2: Lexer
Tak tohle je docela vtipné. Jak jsi ty štítky zmínil v diskuzi, tak jsem si je prohlížel a zkoumal, jak vlastně fungují, a najednou vidím, že je máš zobrazené u zápisku. Takže ty štítky od A jsou ode mě. Sorry.
V pohodě, já už jsem to hodil do tag manageru a ten to odmázl automaticky, protože jsem je neschválil.
Jinak zajímavý zápisek, sice Smalltalk neumím a kompilátory se teprve učím, ale mám určitou představu, o čem tu je řeč, a docela se těším na vytvoření a vyhodnocení toho AST.
To se ti budou líbit další díly, ten kompilátor je sice neoptimalizovaný a relativně neefektivní (například pořád používám více-bajtové instrukce, místo abych zpackoval časté operandy do jednobajtových), ale zase se dá krásně pochopit a je to na pár řádek.

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.