Linguaggi di markup comuni e linguaggi di programmazione comuni sono indistinguibili in quanto hanno sia la sintassi che la semantica. Differiscono solo nel fatto che lo scopo di un linguaggio di programmazione è generare codice eseguibile per un processore, mentre lo scopo di un linguaggio di markup è generare dati dichiarativi per un motore di visualizzazione.
Entrambi hanno una struttura lessicale. Sono costituiti da token come parole, numeri e punteggiatura.
Entrambi hanno una struttura sintattica. I token possono essere organizzati in molti modi diversi e alcune disposizioni sono valide mentre altre no.
Entrambi hanno una struttura semantica. I token hanno un significato, alcuni sono predefiniti e alcuni definiti dall'utente, e il modo in cui i token sono disposti ha un significato.
Se prendiamo il seguente frammento di codice:
<div class="yolo">Hello world</div>
I token div, classe e parentesi angolari hanno significati predefiniti. Il token "yolo" è una stringa che fornisce un nome definito dall'utente per il div. Le parentesi angolari separano il markup dal testo. Queste sono osservazioni semantiche.
Per entrambi, la fase parser del compilatore si ferma nello stesso punto, quando ha generato una rappresentazione interna adatta (come un AST).
La fase successiva per un linguaggio di programmazione è generare codice. La fase successiva per un linguaggio di markup potrebbe essere quella di generare un DOM. Quella fase dipende dalla semantica, ma non parte di essa.