diff options
| author | Anhgelus Morhtuuzh <william@herges.fr> | 2025-10-02 19:52:38 +0200 |
|---|---|---|
| committer | Anhgelus Morhtuuzh <william@herges.fr> | 2025-10-02 19:52:38 +0200 |
| commit | 94dceb4f7c1740de9215b36ec183f93ca4337ee7 (patch) | |
| tree | 5ad184efb0b74dd3aa4da7585f88a3e3f6cb4ecc /markdown/lexer.go | |
| parent | 8b249c9ce8bd1c351daf80c6c9b095fb1bccafe2 (diff) | |
style(markdown): fix typo in package name
Diffstat (limited to 'markdown/lexer.go')
| -rw-r--r-- | markdown/lexer.go | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/markdown/lexer.go b/markdown/lexer.go new file mode 100644 index 0000000..a02ec54 --- /dev/null +++ b/markdown/lexer.go @@ -0,0 +1,132 @@ +package markdown + +import "fmt" + +type lexerType string + +const ( + lexerBreak lexerType = "break" + + lexerModifier lexerType = "modifier" + + lexerCode lexerType = "code" + + lexerHeader lexerType = "header" + lexerQuote lexerType = "quote" + lexerList lexerType = "list" + + lexerExternal lexerType = "external" + + lexerLiteral lexerType = "literal" +) + +type lexer struct { + Type lexerType + Value string +} + +func (l *lexer) String() string { + return fmt.Sprintf("%s(%s)", l.Type, l.Value) +} + +type lexers struct { + current int + lexers []lexer +} + +func (l *lexers) Next() bool { + l.current++ + return !l.Finished() +} + +func (l *lexers) Current() lexer { + return l.lexers[l.current] +} + +func (l *lexers) Finished() bool { + return l.current >= len(l.lexers) +} + +func (l *lexers) Before() bool { + l.current-- + return l.current >= 0 && !l.Finished() +} + +func (l *lexers) String() string { + s := "Lexers[" + for _, l := range l.lexers { + s += l.String() + " " + } + return s + "]" +} + +func lex(s string) *lexers { + lxs := &lexers{current: -1} + var lexs []lexer + var currentType lexerType + var previous string + fn := func(c rune, t lexerType) { + if currentType != t && len(previous) > 0 { + lexs = append(lexs, lexer{Type: currentType, Value: previous}) + previous = "" + } + currentType = t + previous += string(c) + } + newLine := true + literalNext := false + runes := []rune(s) + for i, c := range runes { + if literalNext { + fn(c, lexerLiteral) + literalNext = false + continue + } + if c == '\\' { + literalNext = true + continue + } + switch c { + case '*', '_': + if c == '*' && newLine && i < len(runes)-1 && runes[i+1] == ' ' { + fn(c, lexerList) + } else { + if (currentType != lexerModifier && len(previous) > 0) || + (len(previous) > 0 && []rune(previous)[0] != c) || + len(previous) >= 3 { + lexs = append(lexs, lexer{Type: currentType, Value: previous}) + previous = "" + } + currentType = lexerModifier + previous += string(c) + } + newLine = false + case '`': + newLine = false + fn(c, lexerCode) + case '\n': + newLine = true + fn(c, lexerBreak) + case '#': + newLine = false + fn(c, lexerHeader) + case '>': + newLine = false + fn(c, lexerQuote) + case '[', ']', '(', ')', '!': + newLine = false + fn(c, lexerExternal) + case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.': + newLine = false + fn(c, lexerList) + default: + newLine = false + fn(c, lexerLiteral) + } + } + if len(previous) > 0 { + lexs = append(lexs, lexer{Type: currentType, Value: previous}) + } + lxs.lexers = lexs + return lxs +} |
