50 lines
1.2 KiB
Go
50 lines
1.2 KiB
Go
package frontend
|
|
|
|
import "fmt"
|
|
|
|
// DesugarRanges transform all Range nodes into Alternatives with individual characters
|
|
func DesugarRanges(ast AST) AST {
|
|
switch n := ast.(type) {
|
|
case *AltMatch:
|
|
return &AltMatch{A: DesugarRanges(n.A), B: DesugarRanges(n.B)}
|
|
case *Match:
|
|
return &Match{AST: DesugarRanges(n.AST)}
|
|
case *Alternation:
|
|
return &Alternation{A: DesugarRanges(n.A), B: DesugarRanges(n.B)}
|
|
case *Star:
|
|
return &Star{AST: DesugarRanges(n.AST)}
|
|
case *Plus:
|
|
return &Plus{AST: DesugarRanges(n.AST)}
|
|
case *Maybe:
|
|
return &Maybe{AST: DesugarRanges(n.AST)}
|
|
case *Concat:
|
|
items := make([]AST, 0, len(n.Items))
|
|
for _, i := range n.Items {
|
|
items = append(items, DesugarRanges(i))
|
|
}
|
|
return &Concat{Items: items}
|
|
case *Character:
|
|
return n
|
|
case *EOS:
|
|
return n
|
|
case *Range:
|
|
chars := make([]*Character, 0, n.To-n.From+1)
|
|
for i := int(n.From); i <= int(n.To); i++ {
|
|
chars = append(chars, NewCharacter(byte(i)))
|
|
}
|
|
if len(chars) <= 0 {
|
|
panic(fmt.Errorf("Empty, unmatchable range: %v", n))
|
|
}
|
|
if len(chars) == 1 {
|
|
return chars[0]
|
|
}
|
|
alt := NewAlternation(chars[0], chars[1])
|
|
for i := 2; i < len(chars); i++ {
|
|
alt = NewAlternation(alt, chars[i])
|
|
}
|
|
return alt
|
|
default:
|
|
panic(fmt.Errorf("Unexpected node type %T", n))
|
|
}
|
|
}
|