Skip to content

Commit

Permalink
Add EBNF IR.
Browse files Browse the repository at this point in the history
  • Loading branch information
q-uint committed Jan 20, 2024
1 parent d375f57 commit 4ab1d18
Show file tree
Hide file tree
Showing 3 changed files with 398 additions and 40 deletions.
120 changes: 81 additions & 39 deletions ebnf/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import (
)

var (
Grammar = op.OneOrMore{Value: Definition}
Grammar = op.Capture{
Name: "Grammar",
Value: op.OneOrMore{Value: Definition},
}
Comment = op.Capture{
Name: "Comment",
Value: op.Or{
Expand All @@ -32,51 +35,90 @@ var (
op.RuneRange{Min: 'A', Max: 'Z'},
}
Digit = op.RuneRange{Min: '0', Max: '9'}
String = op.Or{
op.Ignore{Value: op.And{'\'', op.ZeroOrMore{Value: op.AnyBut{Value: '\''}}, '\''}},
op.Ignore{Value: op.And{'"', op.ZeroOrMore{Value: op.AnyBut{Value: '"'}}, '"'}},
op.Ignore{Value: op.And{'’', op.ZeroOrMore{Value: op.AnyBut{Value: '’'}}, '’'}},
String = op.Capture{
Name: "String",
Value: op.Or{
op.Ignore{Value: op.And{'\'', op.ZeroOrMore{Value: op.AnyBut{Value: '\''}}, '\''}},
op.Ignore{Value: op.And{'"', op.ZeroOrMore{Value: op.AnyBut{Value: '"'}}, '"'}},
op.Ignore{Value: op.And{'’', op.ZeroOrMore{Value: op.AnyBut{Value: '’'}}, '’'}},
},
}
Identifier = op.Ignore{Value: op.And{
Letter,
op.ZeroOrMore{Value: op.Or{
Letter, Digit, "_",
op.And{" ", op.Peek{Value: op.Or{Letter, Digit, "_"}}},
Identifier = op.Capture{
Name: "Identifier",
Value: op.Ignore{Value: op.And{
Letter,
op.ZeroOrMore{Value: op.Or{
Letter, Digit, "_",
op.And{" ", op.Peek{Value: op.Or{Letter, Digit, "_"}}},
}},
}},
}}
Alternation = op.And{Concatenation, op.ZeroOrMore{Value: op.And{op.Or{'|', '/', '!'}, Concatenation}}}
Concatenation = op.And{Factor, op.ZeroOrMore{Value: op.And{',', Factor}}}
Optional = op.Or{
op.And{'[', op.Reference{Name: "Alternation"}, ']'},
op.And{"(/", op.Reference{Name: "Alternation"}, "/)"},
}
Repetition = op.Or{
op.And{'{', op.Reference{Name: "Alternation"}, '}'},
op.And{"(:", op.Reference{Name: "Alternation"}, ":)"},
Alternation = op.Capture{
Name: "Alternation",
Value: op.And{Concatenation, op.ZeroOrMore{Value: op.And{op.Or{'|', '/', '!'}, Concatenation}}},
}
Concatenation = op.Capture{
Name: "Concatenation",
Value: op.And{Factor, op.ZeroOrMore{Value: op.And{',', Factor}}},
}
Optional = op.Capture{
Name: "Optional",
Value: op.Or{
op.And{'[', op.Reference{Name: "Alternation"}, ']'},
op.And{"(/", op.Reference{Name: "Alternation"}, "/)"},
},
}
Repetition = op.Capture{
Name: "Repetition",
Value: op.Or{
op.And{'{', op.Reference{Name: "Alternation"}, '}'},
op.And{"(:", op.Reference{Name: "Alternation"}, ":)"},
},
}
Grouping = op.And{'(', op.Reference{Name: "Alternation"}, ')'}
Factor = op.And{
op.Optional{Value: op.And{
op.And{op.RuneRange{Min: '1', Max: '9'}, op.ZeroOrMore{Value: Digit}},
'*',
}},
Term,
op.Optional{Value: op.Or{
'?',
'*',
op.And{'-', op.Optional{Value: Term}},
}},
Factor = op.Capture{
Name: "Factor",
Value: op.And{
op.Optional{Value: op.And{
op.Capture{
Name: "Amount",
Value: op.And{op.RuneRange{Min: '1', Max: '9'}, op.ZeroOrMore{Value: Digit}},
},
'*',
}},
Term,
op.Optional{Value: op.Or{
op.Capture{
Name: "Optional",
Value: '?',
},
op.Capture{
Name: "ZeroOrMore",
Value: '*',
},
op.Capture{
Name: "Except",
Value: op.And{'-', op.Optional{Value: Term}},
},
}},
},
}
Term = op.Or{
Identifier,
String,
Grouping,
Repetition,
Optional,
SpecialSequence,
Term = op.Capture{
Name: "Term",
Value: op.Or{
Identifier,
String,
Grouping,
Repetition,
Optional,
SpecialSequence,
},
}
Empty = ""
SpecialSequence = op.And{'?', op.ZeroOrMore{Value: op.AnyBut{Value: '?'}}, '?'}
Empty = op.Capture{Name: "Empty", Value: ""}
SpecialSequence = op.And{'?', op.Capture{
Name: "SpecialSequence",
Value: op.ZeroOrMore{Value: op.AnyBut{Value: '?'}},
}, '?'}
)

func NewParser(input []rune) (*parser.Parser, error) {
Expand Down
7 changes: 6 additions & 1 deletion ebnf/definition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ebnf

import (
_ "embed"
"github.com/0x51-dev/upeg/ebnf/ir"
"github.com/0x51-dev/upeg/parser/op"
"testing"
)
Expand Down Expand Up @@ -115,7 +116,11 @@ func TestEBNF(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if _, err := p.Parse(op.And{Grammar, op.EOF{}}); err != nil {
n, err := p.Parse(op.And{Grammar, op.EOF{}})
if err != nil {
t.Fatal(err)
}
if _, err := ir.ParseGrammar(n); err != nil {
t.Fatal(err)
}
}
Expand Down
Loading

0 comments on commit 4ab1d18

Please sign in to comment.