Dependency Parsing

Consider the sentence "The economist who wrote the report resigned yesterday." A reader instantly knows who resigned, what was written, and when. Extracting that structured knowledge automatically is the job of syntactic analysis. Dependency parsing is the dominant modern approach to doing it. Rather than building nested bracketed phrases as in constituency grammar, dependency parsing represents a sentence differently. It uses a set of directed, labeled links between words. Each word points to the single other word it grammatically depends on. The result is a tree that directly exposes "who did what to whom." That is exactly the information downstream systems need. This representation matters because it is close to semantics. It achieves this without requiring a full semantic parser. Information extraction systems read subject-verb-object triples off dependency arcs. Relation extraction in Named-Entity Recognition pipelines uses dependency paths between two entity mentions as features. Machine translation systems historically used dependency structure to reorder phrases. This helped between languages with different word orders. Even modern neural pipelines, which often skip explicit parsing, still rely on dependencies. They are frequently pretrained or evaluated using dependency-annotated treebanks like Universal Dependencies. This happens because the framework generalizes remarkably well across 100+ typologically diverse languages. The big picture is a shift in how syntax is computed. Classical constituency parsers (CKY, chart parsers) require grammars. They run in cubic time in sentence length. Dependency parsing, especially the transition-based family covered here, reformulates parsing differently. It becomes a sequence of greedy decisions — shift a word, or attach it to its head. A classifier makes these decisions. This buys linear-time parsing, a dramatic efficiency gain. It made dependency parsers practical for web-scale text processing. This happened well before large neural language models existed. This article builds the dependency representation from first principles. It derives the classic arc-standard transition system step by step. It proves the system produces exactly the trees we want. The article walks a full worked trace. It also surveys the graph-based alternative, the score-based training regime, and the historical arc from rule-based grammars to today's neural dependency parsers.

Key takeaways
  • Dependency trees connect words directly via labeled head→dependent arcs — no phrase brackets, no nonterminal symbols.
  • Every well-formed tree has exactly one root, is connected, and each non-root word has exactly one head (single-head, acyclic, connected).
  • Transition-based (arc-standard) parsing reduces parsing to a sequence of SHIFT / LEFT-ARC / RIGHT-ARC actions chosen by a classifier, giving O(n) parsing time.
  • Graph-based parsing instead scores all possible arcs and finds the highest-scoring spanning tree in O(n³) or O(n²) time, trading speed for global optimality.
  • Training uses either a static oracle (arc-standard's canonical action sequence) or dynamic oracles / structured losses that tolerate the parser's own mistakes.
  • Modern parsers replace hand-crafted features with contextual embeddings (BiLSTM, Transformer) as input to the same transition or graph-scoring machinery.
The core insight

A dependency parse is a labeled tree over words built by greedily choosing, at each step, whether to attach the top of a stack to the next word, attach the next word to the stack, or read ahead — a decision process that a simple classifier can learn to make in linear time.

The idea

A dependency is an asymmetric grammatical relation between two words: a head and a dependent. In "economist wrote report," wrote is the head of the clause; economist is its subject dependent (`nsubj`), report is its object dependent (`obj`). A dependency tree for a sentence is the set of all such head–dependent arcs, plus one designated root word (typically the main verb) that has no head of its own, connected instead to an artificial ROOT node. Each arc carries a label describing the grammatical relation — `nsubj`, `obj`, `det`, `amod`, `advmod`, and so on, drawn from a fixed label inventory such as the Universal Dependencies tagset. Formally, a dependency tree over a sentence w1,…,wnw_1, \dots, w_n (with an added root token w0w_0) is a directed graph T=(V,A)T = (V, A) where V={w0,w1,…,wn}V = \{w_0, w_1, \dots, w_n\} and AA is a set of labeled arcs (h,d,ℓ)(h, d, \ell) meaning "whw_h is the head of wdw_d with label ℓ\ell." A well-formed dependency tree satisfies three properties: (1) single head — every word except the root has exactly one incoming arc; (2) connectivity — every word is reachable from the root; (3) acyclicity — no cycles. Together these force TT to be a tree rooted at w0w_0 with exactly nn arcs for nn real words. A tree is projective if every arc's span (the words between head and dependent) forms a contiguous interval with no arcs crossing it when drawn above the sentence — equivalently, if you can draw all arcs as arches above the linear sentence without any two arcs crossing. Most English sentences are projective; free-word-order languages (Czech, Latin, Warlpiral) frequently require non-projective trees, which matters for which parsing algorithm applies. This differs fundamentally from constituency-based Syntactic Parsing, which groups words into nested phrases (NP, VP, PP) labeled with nonterminal categories. Dependency structure is lexicalized by construction — every arc is between two actual words, never an abstract phrase — which makes it a more direct scaffold for semantic role labeling, relation extraction, and translation. The two representations are inter-convertible under mild assumptions (a constituency tree with head-marking rules yields a dependency tree, the "head-percolation" construction), but dependency trees are typically far more compact: nn arcs versus O(n)O(n) nonterminal nodes plus brackets.

How it works

The dominant efficient algorithm family is transition-based parsing. The parser maintains an explicit state and repeatedly applies one of a small set of transitions (actions), each predicted by a classifier, until the sentence is fully parsed. The classic system is arc-standard, introduced by Nivre (2003/2004).

State. A configuration is a triple c=(σ,β,A)c = (\sigma, \beta, A):

  • σ\sigma — a stack of partially processed words (top on the right),
  • β\beta — a buffer of remaining input words (front on the left), initialized to the whole sentence,
  • AA — the set of dependency arcs built so far.

The initial configuration is c0=([w0],[w1,…,wn],∅)c_0 = ([w_0], [w_1, \dots, w_n], \emptyset) — the stack holds only ROOT, the buffer holds every word. A configuration is terminal when the buffer is empty and the stack contains only ROOT.

Transitions. Let σ=σ′∣s1∣s0\sigma = \sigma' | s_1 | s_0 (so s0s_0 is the stack top, s1s_1 below it) and β=b0∣β′\beta = b_0 | \beta' (so b0b_0 is the buffer front).

TransitionPreconditionEffect
SHIFTβ≠∅\beta \neq \emptysetmove b0b_0 from buffer onto stack
LEFT-ARC(ℓ\ell)∣σ∣≥2\lvert\sigma\rvert \ge 2, s1≠s_1 \ne ROOTadd arc s0→s1s_0 \to s_1 labeled ℓ\ell; remove s1s_1 from stack
RIGHT-ARC(ℓ\ell)∣σ∣≥2\lvert\sigma\rvert \ge 2add arc s1→s0s_1 \to s_0 labeled ℓ\ell; remove s0s_0 from stack

LEFT-ARC makes s0s_0 the head of s1s_1 (dependent popped); RIGHT-ARC makes s1s_1 the head of s0s_0 (dependent popped, but s0s_0 was on top so it is removed and s1s_1 remains available for further attachments to its right — this is the step that must be taken carefully in implementation, see pseudocode below). Each transition is deterministic given a chosen action, so parsing is reduced to: at each configuration, which of the (up to 2L+12L+1) actions — SHIFT, LEFT-ARC with one of LL labels, RIGHT-ARC with one of LL labels — should fire? A trained classifier answers this using features of the current configuration (traditionally: word/POS identity of s0,s1,b0s_0, s_1, b_0, their children, etc.; in neural parsers, dense embeddings of these same positions). ``` function ARC-STANDARD-PARSE(words w[1..n], classifier CLF): stack ← [ROOT] buffer ← [w[1], w[2], ..., w[n]] arcs ← ∅ while not (buffer is empty and len(stack) == 1): features ← EXTRACT-FEATURES(stack, buffer, arcs) action ← CLF.predict(features) # SHIFT, LEFT-ARC(l), RIGHT-ARC(l)

# Guard against illegal predictions (never remove ROOT, never

# act on an empty stack/buffer) — fall back to a legal action. if action == SHIFT and buffer is empty: action ← best legal LEFT-ARC or RIGHT-ARC if action in {LEFT-ARC, RIGHT-ARC} and len(stack) < 2: action ← SHIFT if action == LEFT-ARC and stack[-2] == ROOT: action ← RIGHT-ARC or SHIFT # ROOT may never be a dependent if action == SHIFT: stack.push(buffer.pop_front()) else if action == LEFT-ARC(l): dependent ← stack.pop_second_from_top() # s1 head ← stack.top() # s0 stays arcs.add( (head, dependent, l) ) else if action == RIGHT-ARC(l): dependent ← stack.pop() # s0 removed head ← stack.top() # s1 stays arcs.add( (head, dependent, l) ) return arcs ```

Why exactly 2n2n steps. Every SHIFT consumes exactly one buffer word (there are nn words to consume, hence exactly nn SHIFTs). Every LEFT-ARC or RIGHT-ARC removes exactly one word from the stack permanently and creates exactly one arc; since every word except ROOT must receive exactly one arc pointing to it (single-head property), there are exactly nn arc-transitions. Total transitions: 2n2n, giving strictly linear-time parsing in the number of transitions, and — since feature extraction and classification are O(1)O(1) per step (bounded window around stack/buffer top) — linear-time parsing overall. The figure below shows the configuration graph as a state machine over (stack, buffer) snapshots for a five-word sentence, and separately the resulting dependency tree.

Figure
Arc-standard transitions turning a stack/buffer state into dependency arcs
Resulting dependency tree ROOT economist wrote report . nsubj obj root punct Selected configurations (stack | buffer) [ROOT] [economist, wrote, report, .] SHIFT [ROOT, economist] [wrote, report, .] SHIFT [ROOT, economist, wrote] [report, .] LEFT-ARC(nsubj): wrote→economist [ROOT, wrote] [report, .] SHIFT, RIGHT-ARC(obj) [ROOT, wrote] [.] (report attached) SHIFT, RIGHT-ARC(punct) [ROOT, wrote] [] (punct attached) RIGHT-ARC(root)

Complexity & correctness

Time complexity. As derived above, arc-standard parsing performs exactly 2n2n transitions for a sentence of nn words (n SHIFTs + n arc-transitions), and each transition requires O(1)O(1) feature extraction (a small fixed window of stack/buffer positions) plus one classifier call. If the classifier itself runs in O(1)O(1) (a fixed-size feed-forward network or linear model over a bounded feature vector), total parsing time is O(n)\boxed{O(n)} — genuinely linear in sentence length, in contrast to O(n3)O(n^3) for CKY-style constituency parsing with a context-free grammar in Chomsky Normal Form. This is the central efficiency argument for transition-based parsing and is why it scales to web-scale corpora.

Space complexity is O(n)O(n): the stack and buffer together hold at most nn words, and the arc set has exactly nn arcs.

Correctness (that the transition system reaches exactly the well-formed projective trees). The proof has two directions. Soundness — every terminal configuration's arc set AA is a well-formed, projective dependency tree. By induction on the number of transitions: initially A=∅A = \emptyset trivially satisfies "each processed word has at most one head." Each LEFT-ARC/RIGHT-ARC adds exactly one arc into a word that is being permanently removed from the stack, and the preconditions guarantee that word had received no prior arc as a dependent (once popped, a word can never reappear on the stack, so it cannot receive a second head). Hence the single-head invariant is maintained throughout. Acyclicity holds because arcs only ever point from a stack element to another stack element created before it was pushed, and the stack is popped monotonically — no back-edges can form a cycle. Connectivity to ROOT follows because the terminal condition requires the stack to contain only ROOT, meaning every other word was popped via some arc-transition, i.e., attached into the tree. Completeness — every projective dependency tree is reachable by some transition sequence. This is shown constructively: given a target projective tree, process the sentence left to right, shifting words onto the stack, and whenever the top two stack elements s1,s0s_1, s_0 have a direct head-dependent relationship in the target tree and s1s_1 (or s0s_0) has already received all of its other dependents from the target tree, fire the corresponding arc transition. Because the tree is projective, dependents always finish attaching to a head before an intervening word finishes attaching to something to its right — this is precisely the definition of projectivity, so the "stack contains an attachable pair" situation is guaranteed to arise at the right moments, and the greedy left-to-right procedure never gets stuck. This is why arc-standard handles projective trees only — a non-projective arc would require attaching a word whose dependents are not yet all resolved because a crossing arc still needs to be built, which the stack discipline cannot express. Non-projective dependency structures require either pseudo-projective transformations (encode crossing as extra labels, then re-decode) or a different transition system (arc-eager with a SWAP transition, or graph-based parsing, see below).

Training and the oracle. The classifier is trained via a static oracle: given a gold tree, generate the unique canonical sequence of transitions that produces it (using the completeness construction above), and train a multiclass classifier to predict, from each intermediate gold configuration, the correct next action. The key subtlety, and a genuine correctness concern, is exposure bias: at test time the parser conditions on its own possibly-wrong past decisions, configurations the static oracle never showed it during training. Dynamic oracles address this by defining, for any reachable configuration (including ones resulting from mistakes), the set of transitions that minimizes the number of gold arcs that are now unreachable — training on a mixture of gold and self-generated (rolled-in) configurations closes this gap and is the technique underlying strong transition-based parsers such as those of Goldberg & Nivre (2012) and the neural parser of Chen & Manning (2014).

Graph-based alternative and its complexity. Instead of greedy local decisions, graph-based parsing (McDonald et al., 2005) scores every candidate arc (h,d)(h,d) with a learned scoring function s(h,d)s(h,d), sums arc scores over a candidate tree, and finds

T∗=arg⁡max⁡T∈T(w)∑(h,d)∈Ts(h,d),T^* = \arg\max_{T \in \mathcal{T}(w)} \sum_{(h,d) \in T} s(h,d),

where T(w)\mathcal{T}(w) is the set of valid spanning trees over the sentence. For unlabeled non-projective trees this is exactly the maximum spanning tree problem on a directed graph, solvable optimally by the Chu–Liu/Edmonds algorithm in O(n2)O(n^2) time (or O(nlog⁡n+m)O(n \log n + m) with efficient priority queues), because any spanning arborescence maximizing arc-sum can be found by greedily picking, per node, its best incoming arc, contracting cycles, and recursing — a correct and efficient combinatorial optimization with no need for greedy local classification. For projective trees, dynamic programming (Eisner's algorithm) finds the optimum in O(n3)O(n^3) time by building "half-tree" spans bottom-up, analogous to CKY. Graph-based parsing is globally optimal given its scores (no exposure-bias issue) but pays a higher time cost and needs arc-factored (or higher-order, e.g. sibling/grandparent) scoring functions, which trade expressiveness for tractability.

Honest tradeoffs. Transition-based parsers are fast (O(n)O(n)) and support rich, non-local features of parsing history, but are greedy — an early mistake can cascade (mitigated by beam search, giving O(bn)O(bn) for beam width bb, or dynamic oracles). Graph-based parsers are globally optimal for their score decomposition and handle non-projectivity cleanly (MST) but scale worse (O(n2)O(n^2)–O(n3)O(n^3)) and their arc-factored scoring can miss genuinely non-local syntactic phenomena unless higher-order factors are added, which increases complexity further (third-order graph parsing can reach O(n4)O(n^4)).

Worked example

Sentence: "Economists predicted a recession ." Gold dependency tree (Universal Dependencies style):

HeadDependentLabel
ROOTpredictedroot
predictedEconomistsnsubj
predictedrecessionobj
recessionadet
predicted.punct

Trace of the arc-standard parser (stack shown left→top-of-stack rightmost; buffer shown front→back):

StepStackBufferActionArc added
0[ROOT][Economists, predicted, a, recession, .]SHIFT—
1[ROOT, Economists][predicted, a, recession, .]SHIFT—
2[ROOT, Economists, predicted][a, recession, .]LEFT-ARC(nsubj)predicted→Economists
3[ROOT, predicted][a, recession, .]SHIFT—
4[ROOT, predicted, a][recession, .]SHIFT—
5[ROOT, predicted, a, recession][.]LEFT-ARC(det)recession→a
6[ROOT, predicted, recession][.]RIGHT-ARC(obj)predicted→recession
7[ROOT, predicted][.]SHIFT—
8[ROOT, predicted, .][]RIGHT-ARC(punct)predicted→.
9[ROOT, predicted][]RIGHT-ARC(root)ROOT→predicted
10[ROOT][]terminal—

Sanity check against the completeness argument: at step 2, LEFT-ARC fires because Economists (the current s1s_1) has no further dependents of its own in the gold tree and its head predicted is on the stack — exactly the condition the completeness proof requires. Ten transitions for five real words confirms the 2n2n count. Note step 6's RIGHT-ARC pops recession but leaves predicted on the stack, available to later attach to punctuation (step 8) and finally to ROOT (step 9) — this is exactly why RIGHT-ARC must retain s1s_1 rather than discard it, the detail flagged in the pseudocode's comment.

Common pitfalls & traps

PitfallWhy it happensFix
Treating LEFT-ARC and RIGHT-ARC as symmetric popsRIGHT-ARC removes s0s_0 but keeps s1s_1; LEFT-ARC removes s1s_1 but keeps s0s_0 — students often pop bothRe-derive from the single-head invariant: whichever word just received a head is removed; the head itself must remain available for further attachments
Forgetting the ROOT guardLEFT-ARC precondition s1≠s_1 \neq ROOT is easy to omit, letting ROOT become a dependentExplicitly forbid; ROOT must remain the unique top-level node
Assuming all trees are projectiveFree-word-order languages routinely need crossing arcsUse arc-eager+SWAP, pseudo-projective transforms, or graph-based MST parsing
Confusing dependency labels with POS tagsLabels describe relations (`nsubj`, `obj`); tags describe word categories (`NOUN`, `VERB`) — easy to conflate in feature engineeringKeep separate feature channels; labels are edge annotations, tags are node annotations
Ignoring exposure bias when trainingStatic oracle only shows gold configurations, never the parser's own errorsUse dynamic oracles / scheduled sampling / beam-search training with early update
Evaluating only with unlabeled attachment scoreUAS ignores label correctness entirely, hiding relation errorsReport Labeled Attachment Score (LAS) alongside UAS

Pioneers & history

Dependency grammar's linguistic roots trace to Lucien Tesnière, whose 1959 Éléments de syntaxe structurale first formalized syntax as a network of head-dependent "connections" (stemmas) rather than nested phrase brackets — a genuinely different foundational choice from the Chomskyan constituency tradition dominant in American linguistics of the era. Computational operationalization came decades later, driven by the need for fast, robust parsers for real text (not just clean grammatical sentences), reaching maturity with Joakim Nivre's transition-based framework, which unified many prior shift-reduce parsing ideas into the arc-standard/arc-eager systems described above and made them trainable with off-the-shelf classifiers.

Origins · 1 minJoakim Nivre and how this was discovered
JN
Joakim Nivre
b. 1962 · Swedish computational linguist; formalized transition-based dependency parsing (arc-standard, arc-eager) and co-led the Universal Dependencies project, which unified dependency annotation across 100+ languages

History
1959
— Tesnière's structural syntax formalizes dependency grammar with head–dependent "connections."
2003
— Nivre introduces deterministic, classifier-driven transition-based dependency parsing (arc-standard).
2005
— McDonald, Crammer & Pereira formalize graph-based dependency parsing via maximum spanning trees.
2014
— Chen & Manning replace hand-crafted sparse features with neural embeddings in a transition-based parser.
2015
— The Universal Dependencies project (Nivre et al.) releases a cross-lingually consistent treebank standard.

Where this matters

Dependency parses feed relation extraction and information extraction pipelines, where the shortest dependency path between two entity mentions is a strong feature for classifying their relation — a technique still used inside large-scale knowledge-base population systems. Semantic role labeling systems historically built directly on dependency arcs to identify predicate-argument structure ("who did what to whom"), a precursor to reasoning about Word Senses and Lexical Semantics since the same surface word can take different argument structures under different senses. Machine translation systems, especially pre-neural statistical MT, used dependency structure to model reordering between languages with different canonical word orders (e.g., SOV versus SVO). Grammar-checking and writing-assistance tools use dependency arcs to detect subject-verb agreement errors and dangling modifiers. Search engines and question-answering systems parse queries to identify the head noun and its modifiers for better query understanding. And the Universal Dependencies treebanks — annotated consistently across more than 100 languages — remain a standard benchmark for evaluating multilingual Syntactic Parsing models and a common source of structured supervision even for neural architectures that otherwise learn syntax only implicitly.

Ask the tutor: Can you walk through how the completeness proof breaks down for a concrete non-projective sentence?

What is the difference between dependency parsing and constituency parsing?

Constituency parsing groups words into nested phrases labeled with nonterminal categories (NP, VP, PP), producing a bracketed tree with internal non-lexical nodes. Dependency parsing instead links words directly to other words via labeled head-dependent arcs, with no phrase-level nodes at all — every node in the tree is an actual word. Dependency trees are typically more compact (nn arcs for nn words) and are lexicalized by construction, which makes them convenient input for semantic tasks like relation extraction. The two are inter-convertible via head-percolation rules applied to a constituency tree, but they encode syntactic information differently and support different downstream algorithms.

Why is arc-standard parsing linear time while CKY-style constituency parsing is cubic?

Arc-standard parsing performs a fixed number of transitions — exactly 2n2n for nn words — because every word is shifted once and receives exactly one head-attachment, and each transition costs constant time given bounded local features. CKY, by contrast, must consider all possible split points for every span of the input to find optimal phrase groupings under a context-free grammar, giving O(n3)O(n^3) time from the three nested loops over span start, span end, and split point. The tradeoff is that CKY (or Eisner's algorithm for dependencies) finds a global optimum, while arc-standard commits to greedy local decisions unless combined with beam search or a dynamic oracle.

What happens when a sentence requires a non-projective dependency tree?

Arc-standard's stack-based transition system can only construct projective trees, because its completeness proof relies on dependents fully attaching before an intervening word finishes attaching further right — exactly the projectivity condition. For non-projective sentences (common in free-word-order languages), three options exist: use the arc-eager transition system augmented with a SWAP transition that reorders stack elements to expose crossing attachments; apply a pseudo-projective transform that encodes the crossing pattern into extra labels, parse projectively, then reverse the transform; or switch to graph-based parsing with Chu–Liu/Edmonds, which finds maximum spanning trees over arbitrary (including non-projective) directed graphs in polynomial time.

How is a dependency parser evaluated?

The two standard metrics are Unlabeled Attachment Score (UAS) and Labeled Attachment Score (LAS), both computed by comparing the parser's output arcs against a gold-annotated treebank. UAS is the percentage of words whose predicted head matches the gold head, ignoring the relation label. LAS additionally requires the predicted label to match the gold label, so it is always less than or equal to UAS and is the stricter, more informative metric. Treebanks such as the Penn Treebank (converted to dependencies) or the multilingual Universal Dependencies collection provide standard train/dev/test splits for comparable evaluation across parsers and languages.

Do modern large language models still use explicit dependency parsers?

Large neural language models rarely invoke an explicit dependency parser as a discrete pipeline stage; they learn distributed representations that implicitly encode syntactic regularities through self-attention and pretraining objectives. However, dependency-annotated treebanks remain valuable: they serve as probing benchmarks to test whether a model's internal representations recover known syntactic structure, and dependency-based features still appear in specialized information-extraction and grammar-checking systems where interpretable, symbolic structure is preferred over an opaque neural score. Some hybrid systems also use predicted dependency arcs as auxiliary input features for downstream tasks such as semantic role labeling or relation classification.

What features does the classifier use in a transition-based parser?

Classical (pre-neural) parsers used sparse indicator features over a fixed template: the word form and part-of-speech tag of the stack top (s0s_0), the word below it (s1s_1), the buffer front (b0b_0), and their already-attached children, plus conjunctions of these — often tens of thousands of feature templates combined via a linear or averaged-perceptron classifier. Neural transition-based parsers (starting with Chen & Manning, 2014) replace this with dense embeddings of the same configuration positions, concatenated and fed into a small feed-forward or recurrent network, which learns feature combinations automatically instead of relying on hand-engineered templates, generally improving accuracy while retaining the same O(n)O(n) transition structure.

Can beam search improve transition-based parsing accuracy, and at what cost?

Yes — instead of committing to the single highest-scoring action at each step, beam search retains the top bb partial transition sequences (hypotheses) at every step, expanding each and pruning back to bb, which reduces the risk that one early greedy mistake locks in a wrong parse. This raises time complexity from O(n)O(n) to O(bn)O(bn) for beam width bb, a modest constant-factor cost that is usually worth the accuracy gain. Beam search also enables training with structured losses (e.g., max-margin or early-update perceptron training) that directly optimize whole-sequence correctness rather than single-step classification accuracy, further narrowing the gap to graph-based parsers' global optimality.

Before this