CD Notes
Understanding patterns that define valid lexemes for each token type, pattern specification using regular expressions, and pattern matching in scanners.
What are Patterns?
In compiler design, a pattern is a rule that describes the set of lexemes that can represent a particular token in the source language. Patterns are the formal specifications that tell the lexical analyzer what character sequences constitute valid tokens. They are typically expressed using regular expressions.
Pattern Specification Notation
Regular Expression Notation
Patterns are most commonly specified using regular expressions with these operations:
| Operation | Notation | Meaning | Example | ||
|---|---|---|---|---|---|
| Concatenation | ab | a followed by b | th matches "th" | ||
| Alternation | a\ | b | a or b | `a\ | b` matches "a" or "b" |
| Kleene closure | a* | zero or more a's | a* matches "", "a", "aa" | ||
| Positive closure | a+ | one or more a's | a+ matches "a", "aa" | ||
| Optional | a? | zero or one a | a? matches "" or "a" | ||
| Character class | [a-z] | any lowercase letter | [0-9] matches any digit | ||
| Wildcard | . | any single character | .+ matches anything | ||
| Escape | \\ | literal special char | \\. matches "." |
Regular Definitions
We can name patterns and use those names in other definitions:
| letter | [A-Za-z_] |
| digit | [0-9] |
| id | letter (letter | digit)* |
| integer | digit+ |
| float | digit+ . digit+ (E [+-]? digit+)? |
| string | " [^"]* " |
Common Token Patterns
Identifiers
| Pattern | letter (letter | digit | _)* |
| Where | letter = [A-Za-z_] |
| Valid | x, count, _temp, MAX_SIZE, camelCase, var123 |
| Invalid | 123abc (starts with digit), my-var (contains -) |
Integer Constants
| Decimal | [1-9][0-9]* | 0 |
| Octal | 0[0-7]+ |
| Hexadecimal | 0[xX][0-9a-fA-F]+ |
| Binary | 0[bB][01]+ |
| Valid | 42, 0, 0xFF, 0b1010, 0o77 |
| Invalid | 09 (invalid octal), 0xGG (invalid hex) |
Floating-Point Constants
| Pattern | digit+ . digit+ (E [+-]? digit+)? |
| Valid | 3.14, 0.5, 1.0e10, 2.5E-3, 1e5 |
| Invalid | .5 (some languages), 1. (some languages) |
String Literals
| Pattern | " ([^"\\] | \\ .)* " |
| - Escape sequences | \n, \t, \\, \" |
| Valid | "hello", "line\nbreak", "she said \"hi\"" |
| Invalid | "unterminated, "bad\escape" (if \e undefined) |
Operators and Punctuation
| Arithmetic | + | - | * | / | % |
| Relational | < | <= | > | >= | == | != |
| Logical | && | || | ! |
| Assignment | = | += | -= | *= | /= |
| Bitwise | & | | | ^ | ~ | << | >> |
| Delimiters | ( | ) | [ | ] | { | } | ; | , |
Comments
| Single-line | // [^\n]* \n |
| Multi-line | /\* ([^*] | \* [^/])* \*/ |
| Python | # [^\n]* \n |
Pattern Matching Strategy
The lexical analyzer uses patterns in a specific order to match input:
1. Priority Rules
2. Maximal Munch (Longest Match)
Implementing Pattern Matching
Transition Diagram Approach
Each pattern can be converted to a transition diagram (finite automaton):
| Pattern: relop | < | <= | > | >= | == | != |
| start ─'<'─ | 1 ──→ 2 (return <=) |
| └──── | 3 (return <, retract) |
| start ─'>'─ | 4 ─'='→ 5 (return >=) |
| └──── | 6 (return >, retract) |
| start ─'='─ | 7 ─'='→ 8 (return ==) |
| start ─'!'─ | 9 ─'='→ 10 (return !=) |
Table-Driven Approach
A transition table implements the pattern matching:
Pattern Design Best Practices
- Unambiguous: Each input should match at most one token
- Complete: Every valid input character sequence should be matchable
- Efficient: Patterns should allow fast matching (avoid backtracking)
- Readable: Use regular definitions for complex patterns
- Maintainable: Organize patterns logically by token category
Interview Questions
- What is a pattern in lexical analysis?
A pattern is a formal rule (typically a regular expression) that describes the set of all valid character sequences (lexemes) that can represent a particular token. For example, the pattern letter(letter|digit)* describes all valid identifiers.
- How are patterns specified in lexical analyzers?
Patterns are specified using regular expressions, which can include concatenation, alternation (|), Kleene closure (*), positive closure (+), optional (?), and character classes ([a-z]). Named regular definitions allow building complex patterns from simpler ones.
- What is the longest match rule and why is it important?
The longest match rule states that when multiple patterns could match the current input, the lexical analyzer always chooses the longest matching lexeme. This prevents incorrect tokenization — e.g., "integer" should be one identifier, not the keyword "int" followed by "eger".
- How do you handle the ambiguity between keywords and identifiers?
Keywords have the same pattern as identifiers. The resolution strategy is: first match using the identifier pattern, then check if the matched string is a keyword in a reserved word table. If it is, return the keyword token; otherwise, return an identifier token.
- Write the pattern for floating-point numbers with optional exponent.
digit+ . digit+ (E [+-]? digit+)? — This matches one or more digits, a dot, one or more digits, and optionally an exponent part (E, optional sign, one or more digits). Examples: 3.14, 1.5e10, 2.0E-3.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Patterns in Lexical Analysis.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Compiler Design topic.
Search Terms
compiler-design, compiler design, compiler, design, lexical, analysis, patterns, patterns in lexical analysis
Related Compiler Design Topics