aboutsummaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec')
-rw-r--r--spec/lexer.go62
-rw-r--r--spec/lexer_test.go10
-rw-r--r--spec/parser_test.go82
3 files changed, 82 insertions, 72 deletions
diff --git a/spec/lexer.go b/spec/lexer.go
index da0cf74..258faae 100644
--- a/spec/lexer.go
+++ b/spec/lexer.go
@@ -37,11 +37,13 @@ const (
type Position struct {
Row int
+ Col int
}
-func newPosition(row int) Position {
+func newPosition(row, col int) Position {
return Position{
Row: row,
+ Col: col,
}
}
@@ -101,7 +103,6 @@ type lexer struct {
s *mlspec.CompiledLexSpec
d *mldriver.Lexer
buf *token
- row int
}
//go:embed clexspec.json
@@ -118,9 +119,8 @@ func newLexer(src io.Reader) (*lexer, error) {
return nil, err
}
return &lexer{
- s: s,
- d: d,
- row: 1,
+ s: s,
+ d: d,
}, nil
}
@@ -159,7 +159,7 @@ func (l *lexer) lexAndSkipWSs() (*token, error) {
return nil, err
}
if tok.Invalid {
- return newInvalidToken(tok.Text(), newPosition(l.row)), nil
+ return newInvalidToken(tok.Text(), newPosition(tok.Row+1, tok.Col+1)), nil
}
if tok.EOF {
return newEOFToken(), nil
@@ -176,20 +176,19 @@ func (l *lexer) lexAndSkipWSs() (*token, error) {
switch tok.KindName {
case "newline":
- row := l.row
- l.row++
- return newSymbolToken(tokenKindNewline, newPosition(row)), nil
+ return newSymbolToken(tokenKindNewline, newPosition(tok.Row+1, tok.Col+1)), nil
case "kw_fragment":
- return newSymbolToken(tokenKindKWFragment, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindKWFragment, newPosition(tok.Row+1, tok.Col+1)), nil
case "identifier":
if strings.HasPrefix(tok.Text(), "_") {
return nil, &verr.SpecError{
Cause: synErrAutoGenID,
Detail: tok.Text(),
- Row: l.row,
+ Row: tok.Row + 1,
+ Col: tok.Col + 1,
}
}
- return newIDToken(tok.Text(), newPosition(l.row)), nil
+ return newIDToken(tok.Text(), newPosition(tok.Row+1, tok.Col+1)), nil
case "terminal_open":
var b strings.Builder
for {
@@ -200,7 +199,8 @@ func (l *lexer) lexAndSkipWSs() (*token, error) {
if tok.EOF {
return nil, &verr.SpecError{
Cause: synErrUnclosedTerminal,
- Row: l.row,
+ Row: tok.Row + 1,
+ Col: tok.Col + 1,
}
}
switch tok.KindName {
@@ -210,17 +210,19 @@ func (l *lexer) lexAndSkipWSs() (*token, error) {
case "escape_symbol":
return nil, &verr.SpecError{
Cause: synErrIncompletedEscSeq,
- Row: l.row,
+ Row: tok.Row + 1,
+ Col: tok.Col + 1,
}
case "terminal_close":
pat := b.String()
if pat == "" {
return nil, &verr.SpecError{
Cause: synErrEmptyPattern,
- Row: l.row,
+ Row: tok.Row + 1,
+ Col: tok.Col + 1,
}
}
- return newTerminalPatternToken(pat, newPosition(l.row)), nil
+ return newTerminalPatternToken(pat, newPosition(tok.Row+1, tok.Col+1)), nil
}
}
case "literal_pattern":
@@ -228,22 +230,23 @@ func (l *lexer) lexAndSkipWSs() (*token, error) {
if pat == "" {
return nil, &verr.SpecError{
Cause: synErrEmptyPattern,
- Row: l.row,
+ Row: tok.Row + 1,
+ Col: tok.Col + 1,
}
}
- return newTerminalPatternToken(mlspec.EscapePattern(pat), newPosition(l.row)), nil
+ return newTerminalPatternToken(mlspec.EscapePattern(pat), newPosition(tok.Row+1, tok.Col+1)), nil
case "colon":
- return newSymbolToken(tokenKindColon, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindColon, newPosition(tok.Row+1, tok.Col+1)), nil
case "or":
- return newSymbolToken(tokenKindOr, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindOr, newPosition(tok.Row+1, tok.Col+1)), nil
case "semicolon":
- return newSymbolToken(tokenKindSemicolon, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindSemicolon, newPosition(tok.Row+1, tok.Col+1)), nil
case "directive_marker":
- return newSymbolToken(tokenKindDirectiveMarker, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindDirectiveMarker, newPosition(tok.Row+1, tok.Col+1)), nil
case "tree_node_open":
- return newSymbolToken(tokenKindTreeNodeOpen, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindTreeNodeOpen, newPosition(tok.Row+1, tok.Col+1)), nil
case "tree_node_close":
- return newSymbolToken(tokenKindTreeNodeClose, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindTreeNodeClose, newPosition(tok.Row+1, tok.Col+1)), nil
case "position":
// Remove '$' character and convert to an integer.
num, err := strconv.Atoi(tok.Text()[1:])
@@ -253,15 +256,16 @@ func (l *lexer) lexAndSkipWSs() (*token, error) {
if num == 0 {
return nil, &verr.SpecError{
Cause: synErrZeroPos,
- Row: l.row,
+ Row: tok.Row + 1,
+ Col: tok.Col + 1,
}
}
- return newPositionToken(num, newPosition(l.row)), nil
+ return newPositionToken(num, newPosition(tok.Row+1, tok.Col+1)), nil
case "expansion":
- return newSymbolToken(tokenKindExpantion, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindExpantion, newPosition(tok.Row+1, tok.Col+1)), nil
case "metadata_marker":
- return newSymbolToken(tokenKindMetaDataMarker, newPosition(l.row)), nil
+ return newSymbolToken(tokenKindMetaDataMarker, newPosition(tok.Row+1, tok.Col+1)), nil
default:
- return newInvalidToken(tok.Text(), newPosition(l.row)), nil
+ return newInvalidToken(tok.Text(), newPosition(tok.Row+1, tok.Col+1)), nil
}
}
diff --git a/spec/lexer_test.go b/spec/lexer_test.go
index e5d999e..51e5f59 100644
--- a/spec/lexer_test.go
+++ b/spec/lexer_test.go
@@ -9,23 +9,23 @@ import (
func TestLexer_Run(t *testing.T) {
idTok := func(text string) *token {
- return newIDToken(text, newPosition(1))
+ return newIDToken(text, newPosition(1, 0))
}
termPatTok := func(text string) *token {
- return newTerminalPatternToken(text, newPosition(1))
+ return newTerminalPatternToken(text, newPosition(1, 0))
}
symTok := func(kind tokenKind) *token {
- return newSymbolToken(kind, newPosition(1))
+ return newSymbolToken(kind, newPosition(1, 0))
}
posTok := func(num int) *token {
- return newPositionToken(num, newPosition(1))
+ return newPositionToken(num, newPosition(1, 0))
}
invalidTok := func(text string) *token {
- return newInvalidToken(text, newPosition(1))
+ return newInvalidToken(text, newPosition(1, 0))
}
tests := []struct {
diff --git a/spec/parser_test.go b/spec/parser_test.go
index 4821562..d20f6f9 100644
--- a/spec/parser_test.go
+++ b/spec/parser_test.go
@@ -111,6 +111,12 @@ func TestParse(t *testing.T) {
frag.Pos = pos
return frag
}
+ newPos := func(row int) Position {
+ return Position{
+ Row: row,
+ Col: 0,
+ }
+ }
tests := []struct {
caption string
@@ -256,13 +262,13 @@ foo: 'foo';
alt(
withElemPos(
id("foo"),
- newPosition(6),
+ newPos(6),
),
),
- newPosition(6),
+ newPos(6),
),
),
- newPosition(5),
+ newPos(5),
),
},
LexProductions: []*ProductionNode{
@@ -272,13 +278,13 @@ foo: 'foo';
alt(
withElemPos(
pat(`foo`),
- newPosition(13),
+ newPos(13),
),
),
- newPosition(13),
+ newPos(13),
),
),
- newPosition(13),
+ newPos(13),
),
},
},
@@ -463,42 +469,42 @@ fragment number: "[0-9]";
withAltPos(
withAltDir(
alt(
- withElemPos(id("exp"), newPosition(4)),
- withElemPos(pat(`\+`), newPosition(4)),
- withElemPos(id("id"), newPosition(4)),
+ withElemPos(id("exp"), newPos(4)),
+ withElemPos(pat(`\+`), newPos(4)),
+ withElemPos(id("id"), newPos(4)),
),
withDirPos(
dir("ast",
withParamPos(
treeParam("exp",
- withTreeChildPos(pos(1), newPosition(4)),
- withTreeChildPos(pos(2), newPosition(4))),
- newPosition(4),
+ withTreeChildPos(pos(1), newPos(4)),
+ withTreeChildPos(pos(2), newPos(4))),
+ newPos(4),
),
),
- newPosition(4),
+ newPos(4),
),
),
- newPosition(4),
+ newPos(4),
),
withAltPos(
alt(
- withElemPos(id("id"), newPosition(5)),
+ withElemPos(id("id"), newPos(5)),
),
- newPosition(5),
+ newPos(5),
),
),
withDirPos(
dir("mode",
withParamPos(
idParam("default"),
- newPosition(2),
+ newPos(2),
),
),
- newPosition(2),
+ newPos(2),
),
),
- newPosition(3),
+ newPos(3),
),
},
LexProductions: []*ProductionNode{
@@ -509,18 +515,18 @@ fragment number: "[0-9]";
alt(
withElemPos(
pat(`\u{0020}+`),
- newPosition(7),
+ newPos(7),
),
),
withDirPos(
dir("skip"),
- newPosition(7),
+ newPos(7),
),
),
- newPosition(7),
+ newPos(7),
),
),
- newPosition(7),
+ newPos(7),
),
withProdPos(
prod("id",
@@ -528,23 +534,23 @@ fragment number: "[0-9]";
alt(
withElemPos(
pat(`\f{letter}(\f{letter}|\f{number})*`),
- newPosition(8),
+ newPos(8),
),
),
- newPosition(8),
+ newPos(8),
),
),
- newPosition(8),
+ newPos(8),
),
},
Fragments: []*FragmentNode{
withFragmentPos(
frag("letter", "[A-Za-z_]"),
- newPosition(9),
+ newPos(9),
),
withFragmentPos(
frag("number", "[0-9]"),
- newPosition(10),
+ newPos(10),
),
},
},
@@ -575,29 +581,29 @@ id: "[A-Za-z0-9_]+";
MetaData: []*DirectiveNode{
withDirPos(
leftAssoc(
- withParamPos(idParam("l1"), newPosition(2)),
- withParamPos(idParam("l2"), newPosition(2)),
+ withParamPos(idParam("l1"), newPos(2)),
+ withParamPos(idParam("l2"), newPos(2)),
),
- newPosition(2),
+ newPos(2),
),
withDirPos(
leftAssoc(
- withParamPos(idParam("l3"), newPosition(3)),
+ withParamPos(idParam("l3"), newPos(3)),
),
- newPosition(3),
+ newPos(3),
),
withDirPos(
rightAssoc(
- withParamPos(idParam("r1"), newPosition(4)),
- withParamPos(idParam("r2"), newPosition(4)),
+ withParamPos(idParam("r1"), newPos(4)),
+ withParamPos(idParam("r2"), newPos(4)),
),
- newPosition(4),
+ newPos(4),
),
withDirPos(
rightAssoc(
- withParamPos(idParam("r3"), newPosition(5)),
+ withParamPos(idParam("r3"), newPos(5)),
),
- newPosition(5),
+ newPos(5),
),
},
Productions: []*ProductionNode{