Categories
Programming

Att skriva en egen parser och kompilator i Ruby

I Februari bestämde jag mig för att ta en titt på hur parsing och kompilatorer fungerar, jag valde att imlementera en i Ruby och här kan ni se resultatet.

Det påminner väldigt mycket om tankesättet vi hade när vi gjorde en kalkylator i Java för några år sedan i en kurs jag hade på Uppsala Universitet. Jag implementerade allt fram tills dess att jag skulle generera den slutliga koden. Kunde inte riktigt bestämma mig för vilket språk jag ville generera, ren Rubykod, Assembler eller C.

Exempelprogram

Se online på GitHub

/* PROGRAM NAME: nxx1.txt

nxx is a simple programming language that provides:
 numbers
 strings
 assignment statements
 string concatenation
 simple arithmetic operations
 print capability

comments may be enclosed in slash+asterisk .. asterisk+slash
*/
alpha = 16 ;
beta = 2 ;
resultName = "delta" ;
delta = alpha / beta ;
print "Value of " || resultName || " is: " ;
print delta ;
print "\n" ;

Här är syntaxträdet som produceras av ovanstående kod:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is the abstract syntax tree:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ROOT
    =
        alpha
        16
    =
        beta
        2
    =
        resultName
        "delta"
    =
        delta
        alpha
        /
        beta
    print
        "Value of "
        resultName
        " is: "
    print
        delta
    print
        "\n"

Lärdomar

Själva implementeringen av parsern, lexern och scannern gick bra. Dock märkte jag i slutet att jag saknade en del kunskap om teorin bakom, vilket gjorde det svårt att slutföra. Dessutom fick jag annat att göra så det hamnade i skymundan.

I höst kommer jag läsa en kurs i kompilatorteknik, det ska bli roligt eftersom jag har gett mig på en del av begreppen tidigare och kommer förhoppningsvis ha nytta av mina tidigare erfarenheter och på så sätt ha mer nytta av kursen.

Categories
Personal

Dumheter hos E-delegationen

Med det här inlägget vill jag belysa något som irriterar mig oerhört mycket, slöseri med offentliga medel. Joakim Jardenberg länkade häromdagen till E-delegationens beslut om att de ska genomföra en nyutveckling av deras webbplats från Drupal till EPIServer.

Lena Warstrand hos E-delegationen säger följande angående beslutet:

“Eftersom vår huvudsaklige redaktör tidigare arbetat med Episerver känner hon sig inte helt hemma i publiceringsverktyget. Vi blir ofta beroende av hjälp från vår leverantör.”

Jag har svårt att köpa ovanstående argument, eftersom det måste vara billigare att utbilda redaktören till att bli effektiv i Drupal.

“Vi har haft Drupal i cirka två och ett halvt år och den lösning vi har har inte varit helt stabil. Bland annat har filer försvunnit och opublicerade artiklar har gått ut i RSS-flödet. “

De använder sig av version 6 av Drupal, nog måste det bli billigare att åtgärda dessa problem och uppgradera Drupal till version 7 än att byta till en lösning som bygger på EPIserver? För att inte tala om vilka licenskostnader för EPIserver som tillkommer!

Summering

Jag använder rätt verktyg för rätt arbetsuppgift, jag är inte på något sätt någon fanatiker av någon särskild teknik. Det verkar som om de utvärderat ifall de skulle kunna använda sig av WordPress för lösningen, och det verkar inte passa alls. Det tycker jag är helt rätt beslut. Det jag har svårt att förstå är hur de kan försvara ett beslut att nyutveckla en till synes ganska “standard” webbplats i en helt ny plattform.

Joakim bad att få se kostnadsförslag på kalaset, så förhoppningsvis fortsätter denna debatt.

Relevanta länkar

Categories
Programming

Frontend med Node och Express, backend med WordPress och JSON API

I somras så fick jag tillsammans med en kollega i uppdrag att förnya en existerande webbplats. Några av sakerna vi hade i åtanke var att den skulle vara responsiv, intuitiv och byggas med något annat än bara WordPress.

Vi började rota runt i Node.js och Express och tänkte att det var något vi ville använda. En av styrkorna med WordPress är ju däremot att det är väldigt enkelt att administrera innehåll i det, så vi valde att använda tillägget JSON API tillsammans med WordPress. På så sätt kunde innehållet hämtas via JSON och på så sätt kan frontenden bara vara ett skal som slussar information.

Backend

Som backend så rullade som sagt WordPRess och JSON API. Vi upptäckte ganska tidigt att tillägget var utdaterat när det gäller stödet för custom post types och taxonomies. Vi byggde enkelt ut vår plattform med de funktioner vi behövde. Anta att denna sida rullar på http://backend.dev och det aktiva temat i sig genererar ingen utdata.

Frontend

Basen på frontenden byggdes med hjälp av Node.js och Express. Ett av kraven i funktionaliteten var att vi inte ville att sidan skulle laddas om. Därför använde vi:

  • Sammy.js för att hantera URL:er
  • Futures för att hantera callback-röran (enligt mig) som kan uppstå och för att se till att saker och ting sker asynkront
  • Node-dirty för att skapa en lokal cache av JSON anropen som görs mot http://backend.dev
  • Restler för att göra REST-anrop mot http://backend.dev
  • Forever för att se till att servern hålls igång.
  • Cluster för att styra applikationen

Exempel på en modell som representerar en klient:

var Model   = require('./model'),
    API     = require('./api'),
    config  = require(__dirname + '/../conf/' + (global.process.env.NODE_ENV || 'development') + '.js');

function Client(args) {
  Model.prototype.constructor.call(this, args);  
}

Client.prototype = new Model();

Model.extend(Client, API);

Client.singleUrl = function(slug){ return config.wordpress.url + '/api/CustomTheme/get_taxonomy_posts/?taxonomy=client&slug=' + slug + '&custom_fields=service,type'; };
Client.collectionUrl = function(){ return config.wordpress.url + '/api/CustomTheme/get_taxonomy_keys/?taxonomy=client'; };

Client.singleKey = 'posts';
Client.collectionKey = 'posts';
Client.model = Client;

Client.prototype.constructor = Client;
Client.prototype.render = function() {
  return {
    id:         this.data.term_id, 
    title:      this.data.name,
    slug:       this.data.slug
  };
};

module.exports = Client;

API är en generell klass som alla modeller använder sig av, och Client.singleUrl och Client.collectionUrl är den URL som API:t ska använda sig av, göra anropet, cacha resultatet och generera en struktur som controllern sedan använder sig av.

Cachen är satt på väldigt hög timeout. Det är en webbplats som inte besökaren har någon möjlighet att påverka innehållet på. Så därför behövde vi komma på en lösning att varje gång en uppdatering skett i WordPress-backenden så rensades vår cache.

Hela miljön deployas med hjälp av Capistrano. Där användes en Rakefile för att hantera situationer som att starta om servern, stoppa servern och rensa cachen.

Summan av kardemumman

En ganska krånglig lösning men oerhört kul och inspirerande att få genomföra. Tyvärr blev det tidsbrist och jag hade inte tid att slutföra projektet innan jag åkte till San Jose. Projektet gav mig absolut mersmak för Node.js och vi får se vad jag hittar på i framtiden.

Förra terminen här i San Jose så läste jag en kurs där ett delmoment var i Node, så där hade jag absolut försprång på de andra i klassen. Jag ber om ursäkt för att jag inte kan visa mer kod än vad jag har gjort.