package parser import ( "log" "asciigoat.org/core/lexer" ) // Run parses the source func (p *Parser) Run() error { p.pos.Reset() return lexer.Run(p.lexStart) } func (p *Parser) lexStart() (lexer.StateFn, error) { for { r, _, err := p.src.ReadRune() switch { case err != nil: // read error log.Printf("%s: %s: %s", p.pos, "error", err) return nil, err case IsNewLine(r): // new line p.lexNewLine(r) p.src.Discard() p.pos.StepLine() case IsSpace(r): // whitespace p.src.Discard() p.pos.Step() default: // token p.src.UnreadRune() return p.lexToken, nil } } } func (p *Parser) lexToken() (lexer.StateFn, error) { p.src.AcceptAll(IsNotSpace) s := p.src.Emit() log.Printf("%s: %s: %q", p.pos, "token", s) p.pos.StepN(len(s)) return p.lexStart, nil } func (p *Parser) lexNewLine(r1 rune) { // r1 is warrantied to be either \n or \r r2, _, err := p.src.ReadRune() switch { case r1 == '\r' && r2 == '\n': // CR LN case r1 == '\r' && err == nil: // CR p.src.UnreadRune() case r2 == '\r': // LN CR case err == nil: // LN p.src.UnreadRune() } }