diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/lexer.go | 62 | ||||
-rw-r--r-- | spec/lexer_test.go | 10 | ||||
-rw-r--r-- | spec/parser_test.go | 82 |
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{ |