File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -21,6 +21,7 @@ import (
2121 "errors"
2222 "fmt"
2323 "io"
24+ "os"
2425 "strings"
2526
2627 "github.com/ianlewis/runeio"
@@ -87,25 +88,34 @@ type CustomLexer struct {
8788// NewCustomLexer creates a new Lexer initialized with the given starting
8889// [LexState]. The Lexer takes ownership of the tokens channel and closes it
8990// when lexing is completed.
90- func NewCustomLexer (r io.Reader , startingState LexState ) * CustomLexer {
91+ func NewCustomLexer (reader io.Reader , startingState LexState ) * CustomLexer {
92+ var fileName string
93+
94+ file , isFile := reader .(* os.File )
95+ if isFile {
96+ fileName = file .Name ()
97+ }
98+
9199 customLexer := & CustomLexer {
92100 state : startingState ,
93101 pos : Position {
94- Offset : 0 ,
95- Line : 1 ,
96- Column : 1 ,
102+ Filename : fileName ,
103+ Offset : 0 ,
104+ Line : 1 ,
105+ Column : 1 ,
97106 },
98107 cursor : Position {
99- Offset : 0 ,
100- Line : 1 ,
101- Column : 1 ,
108+ Filename : fileName ,
109+ Offset : 0 ,
110+ Line : 1 ,
111+ Column : 1 ,
102112 },
103113 }
104114
105115 // If already a *bufio.Reader, use it directly.
106- br , ok := r .(* bufio.Reader )
107- if ! ok {
108- br = bufio .NewReader (r )
116+ br , isBufReader := reader .(* bufio.Reader )
117+ if ! isBufReader {
118+ br = bufio .NewReader (reader )
109119 }
110120
111121 customLexer .r = runeio .NewReader (br )
@@ -464,3 +474,9 @@ func (l *CustomLexer) setErr(err error) {
464474 l .err = err
465475 }
466476}
477+
478+ // SetFilename sets the filename in the lexer's positional information.
479+ func (l * CustomLexer ) SetFilename (name string ) {
480+ l .pos .Filename = name
481+ l .cursor .Filename = name
482+ }
Original file line number Diff line number Diff line change @@ -953,3 +953,36 @@ func TestCustomLexer_NextToken(t *testing.T) {
953953 }
954954 })
955955}
956+
957+ func TestCustomLexer_SetFilename (t * testing.T ) {
958+ t .Parallel ()
959+
960+ t .Run ("SetFilename" , func (t * testing.T ) {
961+ t .Parallel ()
962+
963+ customLexer := NewCustomLexer (strings .NewReader ("Hello World!" ), & lexWordState {})
964+ customLexer .SetFilename ("testfile.txt" )
965+
966+ expectedPos := Position {
967+ Offset : 0 ,
968+ Line : 1 ,
969+ Column : 1 ,
970+ Filename : "testfile.txt" ,
971+ }
972+
973+ if diff := cmp .Diff (expectedPos , customLexer .Pos ()); diff != "" {
974+ t .Errorf ("Pos (-want +got):\n %s" , diff )
975+ }
976+
977+ expectedCursor := Position {
978+ Offset : 0 ,
979+ Line : 1 ,
980+ Column : 1 ,
981+ Filename : "testfile.txt" ,
982+ }
983+
984+ if diff := cmp .Diff (expectedCursor , customLexer .Cursor ()); diff != "" {
985+ t .Errorf ("Cursor (-want +got):\n %s" , diff )
986+ }
987+ })
988+ }
Original file line number Diff line number Diff line change @@ -19,6 +19,7 @@ import (
1919 "errors"
2020 "fmt"
2121 "io"
22+ "os"
2223 "text/scanner"
2324)
2425
@@ -62,13 +63,23 @@ type ScanningLexer struct {
6263// NewScanningLexer creates a new ScanningLexer that reads from the given
6364// [io.Reader].
6465func NewScanningLexer (r io.Reader ) * ScanningLexer {
66+ var fileName string
67+
68+ file , ok := r .(* os.File )
69+ if ok {
70+ fileName = file .Name ()
71+ }
72+
6573 l := ScanningLexer {}
6674 l .s = & scanner.Scanner {
6775 Error : func (s * scanner.Scanner , msg string ) {
6876 if l .err == nil {
6977 l .err = fmt .Errorf ("%w: %s: %s" , errScanner , s .Position , msg )
7078 }
7179 },
80+ Position : scanner.Position {
81+ Filename : fileName ,
82+ },
7283 }
7384 l .s = l .s .Init (r )
7485 // Configure the scanner to be more generic and to not skip Go comments.
@@ -102,3 +113,8 @@ func (l *ScanningLexer) newToken(typ TokenType) *Token {
102113 End : Position (l .s .Pos ()),
103114 }
104115}
116+
117+ // SetFilename sets the filename in the lexer's positional information.
118+ func (l * ScanningLexer ) SetFilename (name string ) {
119+ l .s .Filename = name
120+ }
Original file line number Diff line number Diff line change @@ -160,3 +160,37 @@ func TestScannerLexer_NextToken(t *testing.T) {
160160 })
161161 }
162162}
163+
164+ func TestScanningLexer_SetFilename (t * testing.T ) {
165+ t .Parallel ()
166+
167+ t .Run ("SetFilename" , func (t * testing.T ) {
168+ t .Parallel ()
169+
170+ customLexer := NewScanningLexer (strings .NewReader ("Hello World!" ))
171+ customLexer .SetFilename ("testfile.txt" )
172+
173+ expectedToken := & Token {
174+ Type : TokenType (scanner .Ident ),
175+ Value : "Hello" ,
176+ Start : Position {
177+ Offset : 0 ,
178+ Line : 1 ,
179+ Column : 1 ,
180+ Filename : "testfile.txt" ,
181+ },
182+ End : Position {
183+ Offset : 5 ,
184+ Line : 1 ,
185+ Column : 6 ,
186+ Filename : "testfile.txt" ,
187+ },
188+ }
189+
190+ token := customLexer .NextToken (context .Background ())
191+
192+ if diff := cmp .Diff (expectedToken , token ); diff != "" {
193+ t .Errorf ("Pos (-want +got):\n %s" , diff )
194+ }
195+ })
196+ }
You can’t perform that action at this time.
0 commit comments