A parser turns the flat token stream into a tree that captures structure. Today you lay the tree's foundation - the node interfaces and the program root - and parse the two simplest leaves, integer and identifier expressions.
Parse a single integer or identifier into an expression statement whose printed form is the value itself.
Where the lexer produced a flat list, the parser produces a tree that
captures how the pieces nest. Set up just the scaffolding now - every later
lesson adds one more kind of node to it: a Node interface whose one requirement
is that a node can print itself back as source (String), a Program that holds
a list of statements, and an ExpressionStatement wrapper for a statement that is
just an expression. Keep the parser itself minimal - a loop over statements and a
simple dispatch that reads today’s two leaves by token type. The precedence
machinery that makes + and * bind correctly arrives in the next few lessons,
with the operators that need it; don’t build it yet.
Today’s leaves are the smallest expressions: an integer literal (parse the
digit text into a real number) and an identifier (carry the name). Both are
trivial, but wiring them through the Program → ExpressionStatement → Expression
path proves the skeleton holds. Making every node print itself is the trick that
keeps the rest of this chapter concrete - you can always check a parse by reading
its printed form.
// every node can print itself back as source (String)type Node interface { String() string }type Statement interface { Node }type Expression interface { Node }type Program struct { Statements []Statement }type IntegerLiteral struct { Value int64 }func (il *IntegerLiteral) String() string { return fmt.Sprint(il.Value) }// Identifier{Value string} is the same shape - String returns the name