{"id":26459480,"url":"https://github.com/miottonicola/unive-pel_json-parser","last_synced_at":"2026-05-16T23:17:02.647Z","repository":{"id":182821561,"uuid":"669136658","full_name":"MiottoNicola/UNIVE-PEL_JSON-parser","owner":"MiottoNicola","description":"Class Json with parser (Grammatic Context Free)","archived":false,"fork":false,"pushed_at":"2023-07-21T12:42:53.000Z","size":27,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-19T01:48:40.396Z","etag":null,"topics":["cpp","grammar-parser","json"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MiottoNicola.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-21T12:36:05.000Z","updated_at":"2025-01-30T10:26:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"65110a95-d312-4105-b0d4-ae39addd4269","html_url":"https://github.com/MiottoNicola/UNIVE-PEL_JSON-parser","commit_stats":null,"previous_names":["miottonicola/json_parser","miottonicola/unive-pel_json-parser"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MiottoNicola/UNIVE-PEL_JSON-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiottoNicola%2FUNIVE-PEL_JSON-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiottoNicola%2FUNIVE-PEL_JSON-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiottoNicola%2FUNIVE-PEL_JSON-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiottoNicola%2FUNIVE-PEL_JSON-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MiottoNicola","download_url":"https://codeload.github.com/MiottoNicola/UNIVE-PEL_JSON-parser/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MiottoNicola%2FUNIVE-PEL_JSON-parser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33121910,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T18:38:32.183Z","status":"ssl_error","status_checked_at":"2026-05-16T18:38:29.903Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","grammar-parser","json"],"created_at":"2025-03-19T01:48:17.304Z","updated_at":"2026-05-16T23:17:02.641Z","avatar_url":"https://github.com/MiottoNicola.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# CONSEGNA PROGETTO PEL 2022/2023\n\n\n\nLo scopo del progetto è scrivere un parser (tramite grammatiche context-free) di file in formato json. Il contenuto del file deve essere salvato in un container C++ che permetta l’accesso (tramite iteratori e overloading di operatori) del contenuto letto dal file json.\n\nNelle due sezioni seguenti vengono introdotti il formato json e la descrizione del container da realizzare. \n\n\n**Nota**: se trovate imprecisioni/errori o volete un chiarimento su parti di questo documento o di json.hpp, aprite una GitHub issue (pulsante \"issues\" in alto) citando la linea del file in questione (se il commento riguarda una linea particolare del codice o di questo README). Per citare una particolare linea di README.md, aprite il file (cliccando su README.md in alto), rendete visibili le linee (pulsante `\u003c\u003e` \"display the source blob\"), selezionate i numeri di linea interessati -\u003e cliccate i tre puntini -\u003e \"copy permalink\". A questo punto, potete incollare il link copiato nella issue. Analogo per json.hpp (in questo caso i numeri di linea sono immediatamente visibili).\n\n## 1. Formato json\n\nSi vuole scrivere un parser per una variante _semplificata_ di json – un formato testuale per lo scambio di informazione sul Web. **Importante**: usate la descrizione json fornita di seguito e non quella trovata in rete.\n\nUn file json contiene dati in una struttura ad albero (ricorsiva), simile al formato XML. A differenza di XML, il formato json ammette sia **liste** di valori che **dizionari** (definiti nel dettaglio qui sotto). Globalmente, un file json è una lista, un dizionario, un numero (double), un booleano, una stringa, oppure null.\n\n### Liste\n\nUna lista è una sequenza di valori eterogenei separati da virgola e racchiusa tra due parentesi quadre. I valori contenuti nella lista possono essere di **sei** tipi: una lista (ricorsione), un dizionario (definito sotto), una stringa racchiusa tra doppi apici, un valore di tipo double, bool (true/false), oppure null (che sta ad indicare l’assenza di un valore).\n\nIl seguente è un esempio di un semplice file json di tipo lista (ossia, l’intero file è una lista), contenente due stringhe, un valore di tipo double (34.5), seguito da un valore di tipo bool (true), seguito da null, seguito da una lista.\n\n\n    [\n        \"prima stringa\",\n        \"seconda stringa\",\n        34.5,\n        true,\n        null, \n        [1,2,false,43]\n    ]\n\n\n**Nota.** I separatori (newline, tab, spazi) vanno ignorati. L’unica eccezione sono i separatori racchiusi tra doppi apici  (per esempio, lo spazio in \"prima stringa\"): in questo caso, i separatori devono fare parte della stringa estratta dal file. \n\n\n### Una nota importante sulle stringhe \n\nTutti i caratteri tra le doppie virgolette vanno estratti tali e quali. Tenete presente che le stringhe possono contenere il carattere `\"` preceduto da un carattere di `\\`, i.e., la stringa potrebbe contenere la sotto stringa `\\\"`. In questo caso, quindi, la stringa **non** termina con quella occorrenza di `\"`. Le stringhe terminano solo quando il carattere `\"` **non** è preceduto da `\\`.\n\n**Nota bene**: Fate attenzione a seguire questa regola!\n\nSotto riportiamo alcuni esempi.\n\nPer esempio, considerate il seguente file json: \n\n    [\n        \"una stringa con \\n virgolette \\\"escaped\\\"\",\n        \"seconda stringa senza escape\",\n        \"terza stringa con altri\\\" escape\",\n        \"doppio \\\\\" escape\"\n    ]\n\nNell’esempio sopra, le quattro stringhe da estrarre dal file (ossia, i caratteri da inserire nelle `std::string` che andrete a costruire) sono, rispettivamente: \n\n\tuna stringa con \\n virgolette \\\"escaped\\\"\n\tseconda stringa senza escape\n\tterza stringa con altri\\\" escape\n\tdoppio \\\\\" escape\n\n**Nota**: I caratteri speciali `\\n` (e simili, tipo `\\t`, `\\r`, etc.) non fanno eccezione! Se il file json contiene una stringa in cui compare `\\n`, ad esempio, vanno estratti **due** caratteri: backslash (`\\`) seguito dal carattere `n`, **non** va estratto il singolo carattere `\\n` (che significa newline). Questa è una modifica rispetto al formato originale che abbiamo introdotto per semplificare la scrittura del parser.\n\n### Dizionari \n\nUn dizionario è un insieme (una lista) di coppie\n\n**chiave : valore**\n\nseparate da virgola e racchiuse da due parentesi graffe. Notare che chiave e valore sono separate da un carattere ‘:’ (due punti). Le chiavi possono essere solo stringhe racchiuse tra doppi apici (di nuovo, queste stringhe possono contenere caratteri escape ‘\\\\’). I valori possono essere, come sopra, una lista, un dizionario, una stringa racchiusa tra doppi apici (possibilmente con caratteri escape ‘\\\\’), un valore double o bool, oppure null.\n\nPer esempio, il seguente file json è di tipo dizionario.\n\n    {\n        \"prima chiave\" : 5,\n        \"seconda chiave\" : [4.12,2,true],\n        \"terza chiave\" : \"una stringa\",\n        \"quarta chiave\" : {\"a\" : 4, \"b\" : [4,5]}\n    }\n\nNell’esempio qui sopra, il dizionario contiene quattro coppie **chiave : valore**   :\n\n1. Nella prima, la chiave è la stringa **prima chiave** e il valore è l’intero **5**\n2. Nella seconda, la chiave è la stringa **seconda chiave** e il valore è la lista  **\\[4.12,2,true]**\n3. Nella terza, la chiave è la stringa **terza chiave** e il valore è la stringa **una stringa**\n4. Nella quarta, la chiave è la stringa **quarta chiave** e il valore è di nuovo (ricorsivamente) un dizionario: **{\"a\" : 4, \"b\" : \\[4,5]}**\n\nNotate bene la struttura ricorsiva del formato json: la vostra grammatica deve ammettere annidamenti arbitrari di dizionari e liste. \n\n### Esempi e dataset su cui testare il parser\n\nPotete usare il seguente database di file json per testare il vostro codice: \n\n\u003chttps://github.com/jdorfman/awesome-json-datasets\u003e.\n\nPuò tornarvi utile visualizzare un file json in formato ad albero. Per questo, potete usare uno dei tanti visualizzatori json online, ad esempio il seguente:\n\n\u003chttps://jsonviewer.stack.hu/\u003e.\n\n**Nota.** Il visualizzatore sopra racchiude le stringhe tra doppi apici. Il vostro parser invece non deve estrarre i doppi apici che racchiudono le stringhe (vedi esempi sopra). \n\n  \n\n\n## 2. Container\n\nLo scopo del progetto è scrivere un container\n\n    class json;\n\nche permetta di immagazzinare tutte le informazioni contenute in un file json. Il parser json realizzato verrà usato per estrarre dati da un file json e costruire un oggetto di tipo `json`. Qui sotto trovate una descrizione della dichiarazione della classe json.hpp che trovate in questo repository GitHub.\n\nLa classe json deve essere definita in modo ricorsivo, come segue. Un oggetto di tipo `json` contiene un’unica variabile privata\n\n    impl* pimpl;\n\nDove `json::impl` è una struct (privata) che siete liberi di definire (come visto a lezione del modulo 1: pattern Pimpl). Nel decidere che variabili e metodi definire dentro `json::impl`, tenete conto che ogni istanza di `json` può essere una di queste sei cose:\n\n1. null,\n2. un numero,\n3. un booleano, \n4. una stringa, \n5. una lista (di json), oppure\n6. un dizionario (insieme di coppie \u0026lt;stringa, json\u003e).\n\nUna buona idea potrebbe quindi essere quella di definire, dentro `json::impl`, una variabile double, una variabile `bool`, una variabile `std::string`, una lista di `json`, e una lista di `std::pair\u003cstd::string,json\u003e` per il dizionario (in aggiunta a metodi e altre variabili che ritenete necessarie). Ogni oggetto `json` userà solo una di queste cinque variabili (in modo analogo a come abbiamo fatto con la classe token a lezione) e potreste modellare il valore null controllando che ognuna di queste cinque variabili non sia “in uso”.\n\n  \n  \n  \n### Eccezioni\n\nNel file json.hpp è definita la struct\n\n    struct json_exception {\n        std::string msg;\n    };\n\nche dovete usare per le eccezioni. Usate la stringa `msg` per fornire un messaggio di errore informativo (vi tornerà utile in fase di debugging: nei nostri report che vi forniremo, stamperemo questi messaggi).\n\n### Tipi membri di json\n\n\n    json::impl;\n\nQuesta è la struct (privata in json) che potete utilizzare per definire le variabili e metodi che volete usare nell’implementazione di json (come detto sopra, un oggetto `json` contiene un puntatore `impl*`). \n\nRicordate che `json::impl` ha accesso ai membri privati di `json`, quindi se lo desiderate dentro `json::impl` potete anche definire metodi che prendono in input oggetti `json` e modificano il loro contenuto (accedendo a membri privati di `json`). \n\n\n\n---\n    json::list_iterator;\n    json::dictionary_iterator;\n    json::const_list_iterator;\n    json::const_dictionary_iterator;\n\nQuesti sono dei forward iterator che permettono di navigare le liste e i dizionari contenuti in un oggetto `json` (maggiori dettagli sono descritti sotto, nei metodi `begin_list()`, `end_list()`, `begin_dictionary()`, `end_dictionary()`). Su ognuno di questi iteratori, definire (come visto a lezione) i metodi per modificare gli iteratori ed accedere al loro contenuto (in particolare: `operator++` prefix e postfix, `operator*`, `operator-\u003e`, `operator==`, `operator!=`).\n\n  \n### Metodi pubblici di json\n\n\n#### Costruttori, distruttore e assegnamenti:\n\nCostruttore di default, copy constructor, move constructor, distruttore, copy assignment e move assignment, implementati con la semantica standard come visto a lezione. Il costruttore di default deve costruire un oggetto `json` di tipo null (ossia, la funzione `is_null()` descritta sotto deve restituire `true`).\n\n    json::json();\n    json::json(json const\u0026);\n    json::json(json\u0026\u0026);\n    json::~json();\n    json\u0026 json::operator=(json const\u0026);\n    json\u0026 json::operator=(json\u0026\u0026);\n\n\n\n#### Metodi bool\n\nI seguenti metodi possono essere utilizzati per capire di che tipo è l’oggetto `json` (lista, dizionario, stringa, numero, booleano, oppure null). Nota bene: esattamente **uno** di questi metodi deve restituire true (l’oggetto `json` è esattamente uno di questi sei tipi).\n\n---\n    bool json::is_list() const;\nQuesto metodo restituisce true se e solo se l’oggetto è una lista.\n\n---\n    bool json::is_dictionary() const;\nQuesto metodo restituisce true se e solo se l’oggetto è un dizionario.\n\n---  \n    bool json::is_string() const;\nQuesto metodo restituisce true se e solo se l’oggetto è una stringa.\n\n---\n    bool json::is_number() const;\n\nQuesto metodo restituisce true se e solo se l’oggetto è un numero (double).\n\n---\n    bool json::is_bool() const;\nQuesto metodo restituisce true se e solo se l’oggetto è un booleano.\n\n---\n    bool json::is_null() const;\nQuesto metodo restituisce true se e solo se l’oggetto è null.\n\n\n#### Metodi per accedere (dall’esterno) al contenuto del container\n\n    json const\u0026 json::operator[](std::string const\u0026 key) const;\n    json\u0026 json::operator[](std::string const\u0026 key);\n\nSe l’oggetto è un dizionario (`is_dictionary()` restituisce `true`), questo metodo restituisce una reference all’elemento `json` associato alla chiave `key` (ricordate che un dizionario è un insieme di coppie chiave-valore in cui le chiavi sono di tipo `std::string` e i valori sono di tipo `json`).\n\n**Nota.** Non è un problema se questo metodo scorre tutto il contenuto del dizionario (per esempio, se avete implementato il dizionario tramite una lista). Non ci aspettiamo che questo metodo sia particolarmente efficiente (a differenza del metodo `json::insert`, vedi sotto).\n\nSe il dizionario non contiene nessuna coppia chiave-valore la cui chiave è uguale a `key`, allora:\n\n- il metodo `operator[]` deve inserire nel dizionario una nuova coppia chiave-valore la cui chiave è `key` e il cui valore è un `json` costruito con il costruttore di default (i.e., un `json` il cui contenuto è `null`), ed infine restituire una reference a questo nuovo `json` appena costruito;\n- il metodo `operator[] const` deve lanciare invece un'eccezione non potendo effettuare nessun inserimento.\n\nIn ogni caso, se l’oggetto non è un dizionario, lanciamo un’eccezione `json_exception` (con messaggio `msg` a piacere)\nse il metodo `operator[]` viene invocato.\n\n---\n \nSe l’oggetto è una lista (`is_list()` restituisce `true`), usiamo gli iteratori `list_iterator` e `const_list_iterator` per accedere ai membri della lista (a loro volta, degli oggetti `json`).\n\nI seguenti metodi permettono di ottenere iteratori all’inizio e alla fine della lista. Se `is_list()` restituisce `false`, questi metodi devono lanciare un’eccezione `json_exception` (con messaggio `msg` a piacere). \n\n**Attenzione.** L’ordine degli elementi nella lista deve essere lo stesso del file letto in input. In particolare, gli iteratori devono restituire gli elementi in questo ordine.\n\n    json::list_iterator json::begin_list();\n    json::const_list_iterator json::begin_list() const;\n    json::list_iterator json::end_list();\n    json::const_list_iterator json::end_list() const;\n\n---\n\nIn modo analogo, se l’oggetto è un dizionario (`is_dictionary()` restituisce `true`), usiamo gli iteratori `dictionary_iterator` e `const_dictionary_iterator` per accedere alle coppie contenute nel dizionario (le coppie sono di tipo `std::pair\u003cstd::string,json\u003e`). I seguenti metodi permettono di ottenere iteratori all’inizio e alla fine del dizionario. Se  `is_dictionary()` restituisce `false`, questi metodi devono lanciare un’eccezione `json_exception` (con messaggio `msg` a piacere).\n\n**Attenzione.** A differenza degli iteratori su lista, in questo caso non è importante l’ordine in cui vengono immagazzinati e visitati gli elementi del dizionario.\n\n    json::dictionary_iterator json::begin_dictionary();\n    json::const_dictionary_iterator json::begin_dictionary() const;\n    json::dictionary_iterator json::end_dictionary();\n    json::const_dictionary_iterator json::end_dictionary() const;\n\n  \n---\n\nSe `is_number()` è `true` (l’oggetto è un numero), i metodi qui sotto restituiscono una reference / const reference alla variabile `double` contenuta nel `json` (e che potete salvare in `json::impl`). Se `is_number()` è `false`, questo metodo deve lanciare un’eccezione `json_exception` (con messaggio `msg` a piacere). \n\n    double\u0026 json::get_number();\n    double const\u0026 json::get_number() const;\n\n  \n---\n\nSe `is_bool()` è `true` (l’oggetto è un boolean), questi metodi restituiscono una reference / const reference alla variabile booleana contenuta nel `json` (e che potete salvare in `json::impl`). Altrimenti, viene lanciata un’eccezione `json_exception` (con messaggio `msg` a piacere). \n\n    bool\u0026 json::get_bool();\n    bool const\u0026 json::get_bool() const;\n\n---\n\nSe `is_string()` è `true` (l’oggetto è una stringa), questi metodi restituiscono una reference / const reference alla variabile di tipo stringa stringa contenuta nel `json` (e che potete salvare in `json::impl`). Altrimenti, viene lanciata un’eccezione `json_exception` (con messaggio `msg` a piacere). \n\n    std::string\u0026 json::get_string();\n    std::string const\u0026 json::get_string() const;\n\n \n \n#### Metodi per settare il contenuto del json\n\nQuesto metodo rende il json di tipo stringa, rendendo la sua stringa memorizzata internamente uguale a `x` e cancellando gli eventuali dati precedentemente memorizzati nel json (per esempio, se il json era di tipo lista, questa funzione deve svuotare la lista e poi memorizzare la stringa `x`). Dopo la chiamata di questa funzione, `is_string()` deve restituire `true` (nessun altro metodo booleano deve restituire `true`).\n\n    void json::set_string(std::string const\u0026 x);\n\n--- \n\nQuesto metodo rende il json di tipo bool, rendendo il bool memorizzato internamente uguale a `x` e cancellando gli eventuali dati precedentemente memorizzati nel json (per esempio, se il json era di tipo lista, questa funzione deve svuotare la lista e poi memorizzare il booleano `x`). Dopo la chiamata di questa funzione, `is_bool()` deve restituire `true` (nessun altro metodo booleano deve restituire `true`).\n\n    void json::set_bool(bool x);\n\n---\n\nQuesto metodo rende il json di tipo numero, rendendo il double memorizzato internamente uguale a `x` e cancellando gli eventuali dati precedentemente memorizzati nel json (per esempio, se il json era di tipo lista, questa funzione deve svuotare la lista e poi memorizzare il double `x`). Dopo la chiamata di questa funzione, `is_number()` deve restituire true (nessun altro metodo booleano deve restituire `true`).\n\n    void json::set_number(double x);\n\n---\n\nQuesto metodo rende il json di tipo null, cancellando gli eventuali dati precedentemente memorizzati nel json (per esempio, se il json era di tipo lista, questa funzione deve svuotare la lista e poi memorizzare il fatto che l’oggetto è un json null). Dopo la chiamata di questa funzione, `is_null()` deve restituire `true` (nessun altro metodo booleano deve restituire `true`).\n\n    void json::set_null();\n\n---\n\nQuesto metodo rende il json di tipo lista, rendendo la lista interna uguale alla lista vuota  e cancellando gli eventuali dati precedentemente memorizzati nel json, _anche nel caso il json fosse una lista_ (per esempio, se il json era di tipo lista, questa funzione deve rimpiazzare la lista con la lista vuota). Dopo la chiamata di questa funzione, `is_list()` deve restituire `true` (nessun altro metodo booleano deve restituire `true`).\n\n    void json::set_list();\n\n---\n\n\nQuesto metodo rende il json di tipo dizionario, rendendo il dizionario interno uguale al dizionario vuoto  e cancellando gli eventuali dati precedentemente memorizzati nel json, _anche nel caso il json fosse un dizionario_ (per esempio, se il json era di tipo lista, questa funzione deve svuotare la lista e inizializzare il dizionario a quello vuoto). Dopo la chiamata di questa funzione, `is_dictionary()` deve restituire `true` (nessun altro metodo booleano deve restituire `true`).\n\n    void json::set_dictionary();\n\n---\n\nSe il `json` è di tipo lista (`is_list()` restituisce true), questo metodo aggiunge `x` in testa alla lista. \n\n**Importante:** per motivi di efficienza, il metodo non deve scorrere tutta la lista! implementate il metodo come visto a lezione. \n\nSe il `json` non è di tipo lista, questa funzione deve lanciare un’eccezione `json_exception` (con messaggio `msg` a piacere). \n\n    void json::push_front(json const\u0026 x);\n\n---\n\nSe il `json` è di tipo lista (`is_list()` restituisce `true`), questo metodo aggiunge `x` in fondo alla lista. \n\n**Importante:** per motivi di efficienza, il metodo non deve scorrere tutta la lista! implementate il metodo come visto a lezione. \n\nSe il `json` non è di tipo lista, questa funzione deve lanciare un’eccezione `json_exception` (con messaggio `msg` a piacere). \n\n    void json::push_back(json const\u0026 x);\n\n---\n\nSe il `json` è di tipo dizionario (`is_dictionary()` restituisce `true`), questo metodo aggiunge la coppia chiave-valore `x` nel dizionario. Il metodo non deve verificare se esiste già una coppia nel dizionario la cui chiave è `x.first` (potete assumere che questo non avvenga mai nei test che eseguiremo noi). \n\n**Importante:** per motivi di efficienza, il metodo non deve scorrere il contenuto di tutto il dizionario! \n\nSe il `json` non è di tipo dizionario, questa funzione deve lanciare un’eccezione `json_exception` (con messaggio `msg` a piacere). \n\n    void json::insert(std::pair\u003cstd::string,json\u003e const\u0026 x);\n\n  \n\n### Metodi esterni (non membri di json)\n\n\n    std::ostream\u0026 operator\u003c\u003c(std::ostream\u0026 lhs, json const\u0026 rhs);\n\nQuesto metodo scrive l’oggetto `rhs` sull’output stream `lhs` in formato json valido (vedi descrizione formato json all’inizio del documento). Nota: i separatori (spazi, tab, newlines) sono opzionali nel formato json (potete scegliere se metterli o no: è equivalente). \n\n---\n\n    std::istream\u0026 operator\u003e\u003e(std::istream\u0026 lhs, json\u0026 rhs);\n\nQuesto metodo legge da `lhs` un oggetto `json` e lo salva in `rhs` (sovrascrivendone il contenuto). Questa è la funzione che lancia il parser json realizzato: l’input stream è uno stream di caratteri che contiene un documento in formato json (come descritto all’inizio). L’operatore `\u003e\u003e` deve estrarre i dati dallo stream (usando il parser) e costruire l’oggetto `json` che contiene quei dati (cancellando il contenuto precedente di `rhs`, se questi sono presenti).\n\nSe la funzione riscontra dei problemi durante il parsing, deve venire lanciata un’eccezione `json_exception` (con messaggio `msg` a piacere). Cercate di rilevare il numero più elevato possibile di errori di parsing (testeremo il vostro codice anche su file json in formato errato, verificando che venga lanciata l’eccezione).\n\n  \n\n\n### Suggerimenti sul parser\n\nSuggeriamo di scrivere il parser come segue (come visto a lezione):\n\n1. Definite una grammatica context-free in grado di riconoscere il formato json, seguendo la descrizione fornita all’inizio del documento.\n2. Create una funzione per ogni simbolo non terminale della grammatica. \n3. Ogni funzione creata al punto 2 dovrebbe ricevere in input una reference a `std::istream` e restituire in output un oggetto di tipo `json`. Per esempio, se avete scritto una funzione `LIST` che parsa un’intera lista dal’istream in input, questa funzione costruirà un `json` costruito a partire da quella lista (di oggetti `json`) e la restituirà. Questo vi permetterà di implementare le funzioni in modo ricorsivo: la funzione `LIST`, a sua volta, chiamerà funzioni per estrarre i componenti della lista, le quali a loro volta restituiranno degli oggetti `json`; questi oggetti andranno inseriti all’interno della lista dell’oggetto json restituito da `LIST`.\n\n  \n  \n\n\n## 3. Obiettivo finale ed esempi di come verrà testato il codice\n\nIl container json creato può essere usato come un editor di file in formato json. Una volta caricato, il file può essere manipolato/navigato usando gli operatori definiti. Per esempio, supponiamo che `std::cin` contenga lo stream:\n\n    [\n        1,\n        {\n            \"prima chiave\" : 5,\n            \"seconda chiave\" : [4.12,2,true],\n            \"terza chiave\" : \"una stringa\",\n            \"quarta chiave\" : {\"a\" : 4, \"b\" : [4,5]}\n        },\n        3\n    ]\n\nallora, il seguente codice è valido e deve stampare a schermo “4”: \n\n    json j;\n    std::cin \u003e\u003e j;\n    json\u0026 y = *(++j.begin_list());\n    std::cout \u003c\u003c y[\"quarta chiave\"][\"a\"];\n\n\nInoltre, la classe ci permette di modificare un oggetto `json`. Per esempio, se la variabile \n\n    json z;\n\ncontiene i dati del file json\n\n    {\"c\" : 5, \"d\" : 6}\n\ne `j` è la variabile di tipo `json` definita sopra, allora dopo l’assegnamento\n\n    (*(++j.begin_list()))[\"prima chiave\"] = z\n\n \nLa variabile `j` deve contenere i seguenti dati: \n\n    [\n        1,\n        {\n            \"prima chiave\" : {\"c\" : 5, \"d\" : 6},\n            \"seconda chiave\" : [4.12,2,true],\n            \"terza chiave\" : \"una stringa\",\n            \"quarta chiave\" : {\"a\" : 4, \"b\" : [4,5]}\n        },\n        3\n    ]\n\n \n\n### Timeout\n\nAttenzione: il vostro codice deve essere ragionevolmente veloce. Imposteremo un timeout di qualche minuto (in realtà dovrebbero bastare pochi secondi) per la lettura di file json e costruzione dell’oggetto json corrispondente (vedi link con dataset json fornito sopra). Se il vostro codice impiega troppo tempo ad eseguire il parsing di un file json grosso, probabilmente avete implementato male l’inserimento di dati in liste/dizionari: ricordate che gli inserimenti non devono scorrere tutti gli elementi della lista/dizionario (ma, per esempio, devono solo allocare una nuova cella in memoria e sistemare qualche puntatore - se usate le liste per entrambe queste due strutture).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiottonicola%2Funive-pel_json-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmiottonicola%2Funive-pel_json-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmiottonicola%2Funive-pel_json-parser/lists"}