Support mapping rules
diff --git a/pkg/parser/grammar_parser.go b/pkg/parser/grammar_parser.go
index 3124b82..6e677b6 100644
--- a/pkg/parser/grammar_parser.go
+++ b/pkg/parser/grammar_parser.go
@@ -13,12 +13,31 @@
type GrammarParser struct {
defaultFoundry string
defaultLayer string
- parser *participle.Parser[Grammar]
+ tokenParser *participle.Parser[TokenGrammar]
+ mappingParser *participle.Parser[MappingGrammar]
}
+// TokenGrammar represents a single token expression
+type TokenGrammar struct {
+ Token *TokenExpr `parser:"@@"`
+}
+
+// MappingGrammar represents a mapping rule
+type MappingGrammar struct {
+ Mapping *MappingRule `parser:"@@"`
+}
+
+/*
// Grammar represents the root of our grammar
type Grammar struct {
- Token *TokenExpr `parser:"@@"`
+ Token *TokenExpr `parser:" @@"`
+ Mapping *MappingRule `parser:"| @@"`
+}*/
+
+// MappingRule represents a mapping between two token expressions
+type MappingRule struct {
+ Upper *TokenExpr `parser:"@@"`
+ Lower *TokenExpr `parser:"'<>' @@"`
}
// TokenExpr represents a token expression in square brackets
@@ -86,27 +105,37 @@
func NewGrammarParser(defaultFoundry, defaultLayer string) (*GrammarParser, error) {
lex := lexer.MustSimple([]lexer.SimpleRule{
{Name: "Ident", Pattern: `[a-zA-Z][a-zA-Z0-9_]*`},
- {Name: "Punct", Pattern: `[\[\]()&\|=:/]`},
+ {Name: "Punct", Pattern: `[\[\]()&\|=:/]|<>`},
{Name: "Whitespace", Pattern: `\s+`},
})
- parser, err := participle.Build[Grammar](
+ tokenParser, err := participle.Build[TokenGrammar](
participle.Lexer(lex),
participle.UseLookahead(2),
participle.Elide("Whitespace"),
)
if err != nil {
- return nil, fmt.Errorf("failed to build parser: %w", err)
+ return nil, fmt.Errorf("failed to build token parser: %w", err)
+ }
+
+ mappingParser, err := participle.Build[MappingGrammar](
+ participle.Lexer(lex),
+ participle.UseLookahead(2),
+ participle.Elide("Whitespace"),
+ )
+ if err != nil {
+ return nil, fmt.Errorf("failed to build mapping parser: %w", err)
}
return &GrammarParser{
defaultFoundry: defaultFoundry,
defaultLayer: defaultLayer,
- parser: parser,
+ tokenParser: tokenParser,
+ mappingParser: mappingParser,
}, nil
}
-// Parse parses a grammar string into an AST node
+// Parse parses a grammar string into an AST node (for backward compatibility)
func (p *GrammarParser) Parse(input string) (ast.Node, error) {
// Remove extra spaces around operators to help the parser
input = strings.ReplaceAll(input, " & ", "&")
@@ -119,11 +148,15 @@
// Remove any extra spaces
input = strings.TrimSpace(input)
- grammar, err := p.parser.ParseString("", input)
+ grammar, err := p.tokenParser.ParseString("", input)
if err != nil {
return nil, fmt.Errorf("failed to parse grammar: %w", err)
}
+ if grammar.Token == nil {
+ return nil, fmt.Errorf("expected token expression, got mapping rule")
+ }
+
wrap, err := p.parseExpr(grammar.Token.Expr)
if err != nil {
return nil, err
@@ -131,6 +164,51 @@
return &ast.Token{Wrap: wrap}, nil
}
+// ParseMapping parses a mapping rule string into a MappingResult
+func (p *GrammarParser) ParseMapping(input string) (*MappingResult, error) {
+ // Remove extra spaces around operators to help the parser
+ input = strings.ReplaceAll(input, " & ", "&")
+ input = strings.ReplaceAll(input, " | ", "|")
+ input = strings.ReplaceAll(input, " <> ", "<>")
+
+ // Add spaces around parentheses to help the parser
+ input = strings.ReplaceAll(input, "(", " ( ")
+ input = strings.ReplaceAll(input, ")", " ) ")
+
+ // Remove any extra spaces
+ input = strings.TrimSpace(input)
+
+ grammar, err := p.mappingParser.ParseString("", input)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse grammar: %w", err)
+ }
+
+ if grammar.Mapping == nil {
+ return nil, fmt.Errorf("expected mapping rule, got token expression")
+ }
+
+ upper, err := p.parseExpr(grammar.Mapping.Upper.Expr)
+ if err != nil {
+ return nil, err
+ }
+
+ lower, err := p.parseExpr(grammar.Mapping.Lower.Expr)
+ if err != nil {
+ return nil, err
+ }
+
+ return &MappingResult{
+ Upper: &ast.Token{Wrap: upper},
+ Lower: &ast.Token{Wrap: lower},
+ }, nil
+}
+
+// MappingResult represents the parsed mapping rule
+type MappingResult struct {
+ Upper *ast.Token
+ Lower *ast.Token
+}
+
// parseExpr builds the AST from the parsed Expr
func (p *GrammarParser) parseExpr(expr *Expr) (ast.Node, error) {
var operands []ast.Node