A web application for constructing, visualizing, and interpreting Buffalo sentences — the classic linguistic example demonstrating how a single word can function as multiple parts of speech.
"Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo" is a grammatically correct sentence. It works because "buffalo" can be:
- A proper noun (the city in New York) — acts as an adjective
- A noun (the animal, bison)
- A verb (to intimidate or bully)
The famous sentence means: "Bison from Buffalo, NY, that bison from Buffalo, NY intimidate, themselves intimidate bison from Buffalo, NY."
# Install dependencies
npm install
# Run the app
npm run devThen open http://localhost:5173 in your browser.
Grammar Mode (default)
- Specify exact parts of speech for each word
- Starts with the A-N-V pattern (Adjective-Noun-Verb)
- Use presets for common sentence lengths (3, 4, 5, 8 words)
- Add a Golden Buffalo wildcard (tries all POS, limit one per sentence)
Wild Mode
- Explore all possible parses without constraints
- Every buffalo is a wildcard (brown colored)
- Warning when exceeding 5 words (exponential parse complexity)
- Great for discovering valid sentence structures
- Click the colored buttons to add words to the end
- Drag buttons directly into the sentence bar at any position
- Drag words to reorder them within the sentence
- Hover over a word and click the X to remove it
- Drag a word off the sentence bar to remove it (with a poof!)
- Purple (Adjective) = Buffalo (the city)
- Green (Noun) = buffalo (the animal)
- Red (Verb) = buffalo (to intimidate)
- Golden Buffalo = Wildcard that tries all three (limit: one per sentence)
- Parse trees update automatically as you build
- Use ← Previous / Next → to browse multiple valid parses
- Toggle between Tree and Reed-Kellogg diagram styles
- Color-coded interpretation shown with position numbers
- Loading spinner for complex parses
- Invalid combinations show a helpful error message
npm run dev # Start development server
npm run build # Build for production
npm run preview # Preview production build
npm run test # Run tests in watch mode
npm run test:run # Run tests once
npm run typecheck # Check TypeScript types- Two Modes: Grammar Mode (constrained POS) and Wild Mode (explore all parses)
- Sentence Builder: Click or drag to construct Buffalo sentences
- Golden Buffalo Wildcard: Mystery word that tries all parts of speech
- Auto-Parsing: Instant parse tree updates on every change
- Color-Coded Interpreter: Converts parse trees to readable sentences with position markers
- Earley Parser: Handles ambiguous grammars, returns all valid parses
- Tree Deduplication: Filters out identical parse structures
- Visualization: SVG-based tree diagrams with two layout styles
- Drag-and-Drop: Intuitive reordering and removal with animations
- Mobile Responsive: Works on phones and tablets
- Zero Dependencies: Pure TypeScript, no runtime frameworks
- TypeScript (strict mode)
- Vite (build tooling)
- Vitest (58 tests passing)
- Vanilla JS (no UI framework)
BuffaloBuffalo/
├── index.html # Web app entry point
├── package.json
├── tsconfig.json
├── vite.config.ts
├── Taskfile.yml # Task runner commands
├── src/
│ ├── index.ts # Main exports
│ ├── types.ts # Type definitions
│ ├── interpreter.ts # Parse tree to English
│ ├── parser/
│ │ ├── lexicon.ts # Word dictionary
│ │ ├── grammar.ts # CFG rules
│ │ └── earley.ts # Earley parser
│ └── viz/
│ ├── layout.ts # Tree layout algorithms
│ └── renderer.ts # SVG rendering
├── images/
│ ├── logo.svg # Tandem bicycle logo
│ └── BuffaloBuffaloTandemBike.jpeg
├── README.md # This file
├── AGENTS.md # Agent documentation
├── MEMORY.md # Technical decisions
└── PLAN.md # Implementation plan
The app only allows the three linguistically valid parts of speech for "buffalo":
| Button | POS | Meaning |
|---|---|---|
| Adjective (purple) | Proper Noun (PN) | Buffalo, NY — modifies the following noun |
| Noun (green) | Noun (N) | The animal (bison) |
| Verb (red) | Verb (V) | To intimidate, bully, or bewilder |
Note: "Buffalo" is never an adverb or conjunction in English — those were considered but rejected for linguistic accuracy.
Inspired by Professor Stephen Pinker's demonstration in MIT's 9.01 course, showing how syntax and semantics interact in natural language.
