diff --git a/.gitignore b/.gitignore index 7fe8cde2..94ef3889 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ gocc sm_* -.vscode \ No newline at end of file +build/ +*.debug +.vscode + diff --git a/example/astx/ast.bnf b/example/astx/ast.bnf index d5d77fb1..6bf87601 100644 --- a/example/astx/ast.bnf +++ b/example/astx/ast.bnf @@ -12,13 +12,13 @@ id : (_letter | '_') {_idchar} ; /* Syntax elements */ -<< import "github.com/goccmack/gocc/example/astx/ast" >> +<< import "github.com/maxcalandrelli/gocc/example/astx/ast" >> -StmtList : +StmtList : Stmt << ast.NewStmtList($0) >> | StmtList Stmt << ast.AppendStmt($0, $1) >> ; -Stmt : +Stmt : id << ast.NewStmt($0) >> ; \ No newline at end of file diff --git a/example/astx/ast.grammar/ast/ast.go b/example/astx/ast.grammar/ast/ast.go new file mode 100644 index 00000000..a132b0f0 --- /dev/null +++ b/example/astx/ast.grammar/ast/ast.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package ast + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/errors" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/lexer" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/parser" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/astx/ast.grammar/ast/iface/ast.go b/example/astx/ast.grammar/ast/iface/ast.go new file mode 100644 index 00000000..d41fb7c5 --- /dev/null +++ b/example/astx/ast.grammar/ast/iface/ast.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/errors" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/errorrecovery/errors/errors.go b/example/astx/ast.grammar/ast/internal/errors/errors.go old mode 100755 new mode 100644 similarity index 94% rename from example/errorrecovery/errors/errors.go rename to example/astx/ast.grammar/ast/internal/errors/errors.go index bd6f871a..40f47a5b --- a/example/errorrecovery/errors/errors.go +++ b/example/astx/ast.grammar/ast/internal/errors/errors.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/example/errorrecovery/token" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/token" ) type ErrorSymbol interface { diff --git a/example/astx/ast.grammar/ast/internal/io/stream/internal/stream_impl.go b/example/astx/ast.grammar/ast/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/astx/ast.grammar/ast/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/astx/ast.grammar/ast/internal/io/stream/internal/stream_public.go b/example/astx/ast.grammar/ast/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/astx/ast.grammar/ast/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/astx/ast.grammar/ast/internal/io/stream/stream.go b/example/astx/ast.grammar/ast/internal/io/stream/stream.go new file mode 100644 index 00000000..601690af --- /dev/null +++ b/example/astx/ast.grammar/ast/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/astx/lexer/acttab.go b/example/astx/ast.grammar/ast/internal/lexer/acttab.go old mode 100755 new mode 100644 similarity index 64% rename from example/astx/lexer/acttab.go rename to example/astx/ast.grammar/ast/internal/lexer/acttab.go index 6f9994fb..a2318bb6 --- a/example/astx/lexer/acttab.go +++ b/example/astx/ast.grammar/ast/internal/lexer/acttab.go @@ -5,7 +5,7 @@ package lexer import ( "fmt" - "github.com/goccmack/gocc/example/astx/token" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/token" ) type ActionTable [NumStates]ActionRow @@ -20,31 +20,31 @@ func (a ActionRow) String() string { } var ActTab = ActionTable{ - ActionRow{ // S0 + ActionRow{ // S0, Accept: 0, Ignore: "", }, - ActionRow{ // S1 + ActionRow{ // S1, Ignore("!whitespace") Accept: -1, Ignore: "!whitespace", }, - ActionRow{ // S2 + ActionRow{ // S2, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S3 + ActionRow{ // S3, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S4 + ActionRow{ // S4, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S5 + ActionRow{ // S5, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S6 + ActionRow{ // S6, Accept("id") Accept: 2, Ignore: "", }, diff --git a/example/astx/ast.grammar/ast/internal/lexer/lexer.go b/example/astx/ast.grammar/ast/internal/lexer/lexer.go new file mode 100644 index 00000000..5d39573b --- /dev/null +++ b/example/astx/ast.grammar/ast/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/iface" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/token" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 7 + NumSymbols = 10 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/astx/lexer/transitiontable.go b/example/astx/ast.grammar/ast/internal/lexer/transitiontable.go old mode 100755 new mode 100644 similarity index 100% rename from example/astx/lexer/transitiontable.go rename to example/astx/ast.grammar/ast/internal/lexer/transitiontable.go diff --git a/example/astx/parser/action.go b/example/astx/ast.grammar/ast/internal/parser/action.go old mode 100755 new mode 100644 similarity index 100% rename from example/astx/parser/action.go rename to example/astx/ast.grammar/ast/internal/parser/action.go diff --git a/example/astx/ast.grammar/ast/internal/parser/actiontable.go b/example/astx/ast.grammar/ast/internal/parser/actiontable.go new file mode 100644 index 00000000..9c8071d3 --- /dev/null +++ b/example/astx/ast.grammar/ast/internal/parser/actiontable.go @@ -0,0 +1,70 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(3), // id + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + shift(3), // id + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: StmtList + reduce(1), // id, reduce: StmtList + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt + reduce(3), // id, reduce: Stmt + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: StmtList + reduce(2), // id, reduce: StmtList + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/astx/parser/gototable.go b/example/astx/ast.grammar/ast/internal/parser/gototable.go old mode 100755 new mode 100644 similarity index 50% rename from example/astx/parser/gototable.go rename to example/astx/ast.grammar/ast/internal/parser/gototable.go index 365a4be8..3fc118e2 --- a/example/astx/parser/gototable.go +++ b/example/astx/ast.grammar/ast/internal/parser/gototable.go @@ -11,28 +11,28 @@ type ( var gotoTab = gotoTable{ gotoRow{ // S0 - -1, // S' - 1, // StmtList - 2, // Stmt + -1, // Π + 1, // Π + 2, // Π }, gotoRow{ // S1 - -1, // S' - -1, // StmtList - 4, // Stmt + -1, // Π + -1, // Π + 4, // Π }, gotoRow{ // S2 - -1, // S' - -1, // StmtList - -1, // Stmt + -1, // Π + -1, // Π + -1, // Π }, gotoRow{ // S3 - -1, // S' - -1, // StmtList - -1, // Stmt + -1, // Π + -1, // Π + -1, // Π }, gotoRow{ // S4 - -1, // S' - -1, // StmtList - -1, // Stmt + -1, // Π + -1, // Π + -1, // Π }, } diff --git a/example/astx/ast.grammar/ast/internal/parser/parser.go b/example/astx/ast.grammar/ast/internal/parser/parser.go new file mode 100644 index 00000000..22bed2cb --- /dev/null +++ b/example/astx/ast.grammar/ast/internal/parser/parser.go @@ -0,0 +1,353 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/iface" + parseError "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/errors" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/token" +) + +const ( + numProductions = 4 + numStates = 5 + numSymbols = 6 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = longest + p.isNonDeterministic = false + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/astx/ast.grammar/ast/internal/parser/productionstable.go b/example/astx/ast.grammar/ast/internal/parser/productionstable.go new file mode 100644 index 00000000..241d7d56 --- /dev/null +++ b/example/astx/ast.grammar/ast/internal/parser/productionstable.go @@ -0,0 +1,97 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import "github.com/maxcalandrelli/gocc/example/astx/ast" + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/token" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtList : Π << ast.NewStmtList($0) >>`, + Id: "StmtList", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmtList(X[0]) + }, + }, + ProdTabEntry{ + String: `StmtList : Π Π << ast.AppendStmt($0, $1) >>`, + Id: "StmtList", + NTType: 1, + Index: 2, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AppendStmt(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Stmt : id << ast.NewStmt($0) >>`, + Id: "Stmt", + NTType: 2, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmt(X[0]) + }, + }, +} diff --git a/example/errorrecovery/token/token.go b/example/astx/ast.grammar/ast/internal/token/token.go old mode 100755 new mode 100644 similarity index 67% rename from example/errorrecovery/token/token.go rename to example/astx/ast.grammar/ast/internal/token/token.go index 4b15584d..6bbf99ec --- a/example/errorrecovery/token/token.go +++ b/example/astx/ast.grammar/ast/internal/token/token.go @@ -8,8 +8,11 @@ import ( type Token struct { Type - Lit []byte + Lit []byte + IgnoredPrefix []byte Pos + ForeignAstNode interface{} + Foreign bool } type Type int @@ -29,9 +32,24 @@ func (p Pos) String() string { return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) } +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + type TokenMap struct { typeMap []string idMap map[string]Type + litMap map[string]Type } func (m TokenMap) Id(tok Type) string { @@ -49,8 +67,7 @@ func (m TokenMap) Type(tok string) Type { } func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) } func (m TokenMap) StringType(typ Type) string { @@ -60,15 +77,15 @@ func (m TokenMap) StringType(typ Type) string { var TokMap = TokenMap{ typeMap: []string{ "INVALID", - "$", + "Ω", "id", - "error", }, idMap: map[string]Type{ "INVALID": 0, - "$": 1, + "Ω": 1, "id": 2, - "error": 3, }, + + litMap: map[string]Type{}, } diff --git a/example/astx/util/litconv.go b/example/astx/ast.grammar/ast/internal/util/litconv.go old mode 100755 new mode 100644 similarity index 100% rename from example/astx/util/litconv.go rename to example/astx/ast.grammar/ast/internal/util/litconv.go diff --git a/example/astx/ast.grammar/ast/internal/util/rune.go b/example/astx/ast.grammar/ast/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/astx/ast.grammar/ast/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/astx/ast.grammar/ast/main/ast.go b/example/astx/ast.grammar/ast/main/ast.go new file mode 100644 index 00000000..f8e22fc6 --- /dev/null +++ b/example/astx/ast.grammar/ast/main/ast.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + ast "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *ast.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return ast.NewParser().ParseLongestPrefix(lex) + } else { + res, err = ast.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, ast.NewLexerString(Text))) + } + if File > "" { + l, e := ast.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, ast.NewLexerString(str))) + } +} diff --git a/example/astx/ast.grammar/ast/util.go b/example/astx/ast.grammar/ast/util.go new file mode 100644 index 00000000..69965c9b --- /dev/null +++ b/example/astx/ast.grammar/ast/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package ast + +import ( + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/astx/ast/ast.go b/example/astx/ast/ast.go index de638d91..8b9d8f42 100644 --- a/example/astx/ast/ast.go +++ b/example/astx/ast/ast.go @@ -1,7 +1,7 @@ package ast import ( - "github.com/goccmack/gocc/example/astx/token" + "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast/iface" ) type ( @@ -18,5 +18,5 @@ func AppendStmt(stmtList, stmt interface{}) (StmtList, error) { } func NewStmt(stmtList interface{}) (Stmt, error) { - return Stmt(stmtList.(*token.Token).Lit), nil + return Stmt(stmtList.(*iface.Token).Lit), nil } diff --git a/example/astx/ast_test.go b/example/astx/ast_test.go index 7f13766b..1f71c18b 100644 --- a/example/astx/ast_test.go +++ b/example/astx/ast_test.go @@ -4,9 +4,8 @@ import ( "fmt" "testing" - "github.com/goccmack/gocc/example/astx/ast" - "github.com/goccmack/gocc/example/astx/lexer" - "github.com/goccmack/gocc/example/astx/parser" + "github.com/maxcalandrelli/gocc/example/astx/ast" + grammar "github.com/maxcalandrelli/gocc/example/astx/ast.grammar/ast" ) func TestPass(t *testing.T) { @@ -28,8 +27,8 @@ func TestFail(t *testing.T) { func test(src []byte) (astree ast.StmtList, err error) { fmt.Printf("input: %s\n", src) - s := lexer.NewLexer(src) - p := parser.NewParser() + s := grammar.NewLexerBytes(src) + p := grammar.NewParser() a, err := p.Parse(s) if err == nil { astree = a.(ast.StmtList) diff --git a/example/astx/lexer/lexer.go b/example/astx/lexer/lexer.go deleted file mode 100755 index acc0bda1..00000000 --- a/example/astx/lexer/lexer.go +++ /dev/null @@ -1,126 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package lexer - -import ( - "io/ioutil" - "unicode/utf8" - - "github.com/goccmack/gocc/example/astx/token" -) - -const ( - NoState = -1 - NumStates = 7 - NumSymbols = 10 -) - -type Lexer struct { - src []byte - pos int - line int - column int -} - -func NewLexer(src []byte) *Lexer { - lexer := &Lexer{ - src: src, - pos: 0, - line: 1, - column: 1, - } - return lexer -} - -func NewLexerFile(fpath string) (*Lexer, error) { - src, err := ioutil.ReadFile(fpath) - if err != nil { - return nil, err - } - return NewLexer(src), nil -} - -func (l *Lexer) Scan() (tok *token.Token) { - tok = new(token.Token) - if l.pos >= len(l.src) { - tok.Type = token.EOF - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column - return - } - start, startLine, startColumn, end := l.pos, l.line, l.column, 0 - tok.Type = token.INVALID - state, rune1, size := 0, rune(-1), 0 - for state != -1 { - if l.pos >= len(l.src) { - rune1 = -1 - } else { - rune1, size = utf8.DecodeRune(l.src[l.pos:]) - l.pos += size - } - - nextState := -1 - if rune1 != -1 { - nextState = TransTab[state](rune1) - } - state = nextState - - if state != -1 { - - switch rune1 { - case '\n': - l.line++ - l.column = 1 - case '\r': - l.column = 1 - case '\t': - l.column += 4 - default: - l.column++ - } - - switch { - case ActTab[state].Accept != -1: - tok.Type = ActTab[state].Accept - end = l.pos - case ActTab[state].Ignore != "": - start, startLine, startColumn = l.pos, l.line, l.column - state = 0 - if start >= len(l.src) { - tok.Type = token.EOF - } - - } - } else { - if tok.Type == token.INVALID { - end = l.pos - } - } - } - if end > start { - l.pos = end - tok.Lit = l.src[start:end] - } else { - tok.Lit = []byte{} - } - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn - - return -} - -func (l *Lexer) Reset() { - l.pos = 0 -} - -/* -Lexer symbols: -0: '_' -1: '_' -2: ' ' -3: '\t' -4: '\n' -5: '\r' -6: 'a'-'z' -7: 'A'-'Z' -8: '0'-'9' -9: . -*/ diff --git a/example/astx/parser/actiontable.go b/example/astx/parser/actiontable.go deleted file mode 100755 index 5a87c2d9..00000000 --- a/example/astx/parser/actiontable.go +++ /dev/null @@ -1,54 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - actionTable [numStates]actionRow - actionRow struct { - canRecover bool - actions [numSymbols]action - } -) - -var actionTab = actionTable{ - actionRow{ // S0 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(3), // id - }, - }, - actionRow{ // S1 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - accept(true), // $ - shift(3), // id - }, - }, - actionRow{ // S2 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(1), // $, reduce: StmtList - reduce(1), // id, reduce: StmtList - }, - }, - actionRow{ // S3 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(3), // $, reduce: Stmt - reduce(3), // id, reduce: Stmt - }, - }, - actionRow{ // S4 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(2), // $, reduce: StmtList - reduce(2), // id, reduce: StmtList - }, - }, -} diff --git a/example/astx/parser/parser.go b/example/astx/parser/parser.go deleted file mode 100755 index e02ff1f9..00000000 --- a/example/astx/parser/parser.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "fmt" - "strings" - - parseError "github.com/goccmack/gocc/example/astx/errors" - "github.com/goccmack/gocc/example/astx/token" -) - -const ( - numProductions = 4 - numStates = 5 - numSymbols = 6 -) - -// Stack - -type stack struct { - state []int - attrib []Attrib -} - -const iNITIAL_STACK_SIZE = 100 - -func newStack() *stack { - return &stack{ - state: make([]int, 0, iNITIAL_STACK_SIZE), - attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), - } -} - -func (s *stack) reset() { - s.state = s.state[:0] - s.attrib = s.attrib[:0] -} - -func (s *stack) push(state int, a Attrib) { - s.state = append(s.state, state) - s.attrib = append(s.attrib, a) -} - -func (s *stack) top() int { - return s.state[len(s.state)-1] -} - -func (s *stack) peek(pos int) int { - return s.state[pos] -} - -func (s *stack) topIndex() int { - return len(s.state) - 1 -} - -func (s *stack) popN(items int) []Attrib { - lo, hi := len(s.state)-items, len(s.state) - - attrib := s.attrib[lo:hi] - - s.state = s.state[:lo] - s.attrib = s.attrib[:lo] - - return attrib -} - -func (s *stack) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "stack:\n") - for i, st := range s.state { - fmt.Fprintf(w, "\t%d: %d , ", i, st) - if s.attrib[i] == nil { - fmt.Fprintf(w, "nil") - } else { - switch attr := s.attrib[i].(type) { - case *token.Token: - fmt.Fprintf(w, "%s", attr.Lit) - default: - fmt.Fprintf(w, "%v", attr) - } - } - fmt.Fprintf(w, "\n") - } - return w.String() -} - -// Parser - -type Parser struct { - stack *stack - nextToken *token.Token - pos int -} - -type Scanner interface { - Scan() (tok *token.Token) -} - -func NewParser() *Parser { - p := &Parser{stack: newStack()} - p.Reset() - return p -} - -func (p *Parser) Reset() { - p.stack.reset() - p.stack.push(0, nil) -} - -func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { - errorAttrib = &parseError.Error{ - Err: err, - ErrorToken: p.nextToken, - ErrorSymbols: p.popNonRecoveryStates(), - ExpectedTokens: make([]string, 0, 8), - } - for t, action := range actionTab[p.stack.top()].actions { - if action != nil { - errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) - } - } - - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { - p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift - } else { - return - } - - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - for !recovered && p.nextToken.Type != token.EOF { - p.nextToken = scanner.Scan() - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - } - - return -} - -func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { - if rs, ok := p.firstRecoveryState(); ok { - errorSymbols := p.stack.popN(p.stack.topIndex() - rs) - removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) - for i, e := range errorSymbols { - removedAttribs[i] = e - } - } else { - removedAttribs = []parseError.ErrorSymbol{} - } - return -} - -// recoveryState points to the highest state on the stack, which can recover -func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { - recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover - for recoveryState > 0 && !canRecover { - recoveryState-- - canRecover = actionTab[p.stack.peek(recoveryState)].canRecover - } - return -} - -func (p *Parser) newError(err error) error { - e := &parseError.Error{ - Err: err, - StackTop: p.stack.top(), - ErrorToken: p.nextToken, - } - actRow := actionTab[p.stack.top()] - for i, t := range actRow.actions { - if t != nil { - e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) - } - } - return e -} - -func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { - p.Reset() - p.nextToken = scanner.Scan() - for acc := false; !acc; { - action := actionTab[p.stack.top()].actions[p.nextToken.Type] - if action == nil { - if recovered, errAttrib := p.Error(nil, scanner); !recovered { - p.nextToken = errAttrib.ErrorToken - return nil, p.newError(nil) - } - if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { - panic("Error recovery led to invalid action") - } - } - - switch act := action.(type) { - case accept: - res = p.stack.popN(1)[0] - acc = true - case shift: - p.stack.push(int(act), p.nextToken) - p.nextToken = scanner.Scan() - case reduce: - prod := productionsTable[int(act)] - attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) - if err != nil { - return nil, p.newError(err) - } else { - p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) - } - default: - panic("unknown action: " + action.String()) - } - } - return res, nil -} diff --git a/example/astx/parser/productionstable.go b/example/astx/parser/productionstable.go deleted file mode 100755 index 7ee72c4e..00000000 --- a/example/astx/parser/productionstable.go +++ /dev/null @@ -1,63 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import "github.com/goccmack/gocc/example/astx/ast" - -type ( - //TODO: change type and variable names to be consistent with other tables - ProdTab [numProductions]ProdTabEntry - ProdTabEntry struct { - String string - Id string - NTType int - Index int - NumSymbols int - ReduceFunc func([]Attrib) (Attrib, error) - } - Attrib interface { - } -) - -var productionsTable = ProdTab{ - ProdTabEntry{ - String: `S' : StmtList << >>`, - Id: "S'", - NTType: 0, - Index: 0, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `StmtList : Stmt << ast.NewStmtList(X[0]) >>`, - Id: "StmtList", - NTType: 1, - Index: 1, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewStmtList(X[0]) - }, - }, - ProdTabEntry{ - String: `StmtList : StmtList Stmt << ast.AppendStmt(X[0], X[1]) >>`, - Id: "StmtList", - NTType: 1, - Index: 2, - NumSymbols: 2, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.AppendStmt(X[0], X[1]) - }, - }, - ProdTabEntry{ - String: `Stmt : id << ast.NewStmt(X[0]) >>`, - Id: "Stmt", - NTType: 2, - Index: 3, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewStmt(X[0]) - }, - }, -} diff --git a/example/astx/util/rune.go b/example/astx/util/rune.go deleted file mode 100755 index bd8523a4..00000000 --- a/example/astx/util/rune.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package util - -import ( - "fmt" -) - -func RuneToString(r rune) string { - if r >= 0x20 && r < 0x7f { - return fmt.Sprintf("'%c'", r) - } - switch r { - case 0x07: - return "'\\a'" - case 0x08: - return "'\\b'" - case 0x0C: - return "'\\f'" - case 0x0A: - return "'\\n'" - case 0x0D: - return "'\\r'" - case 0x09: - return "'\\t'" - case 0x0b: - return "'\\v'" - case 0x5c: - return "'\\\\\\'" - case 0x27: - return "'\\''" - case 0x22: - return "'\\\"'" - } - if r < 0x10000 { - return fmt.Sprintf("\\u%04x", r) - } - return fmt.Sprintf("\\U%08x", r) -} diff --git a/example/bools/Makefile b/example/bools/Makefile index 5a3f73ed..e46e6f3e 100644 --- a/example/bools/Makefile +++ b/example/bools/Makefile @@ -1,2 +1,2 @@ regenerate: - gocc -a example.bnf \ No newline at end of file + gocc -a bools.bnf diff --git a/example/bools/ast/ast.go b/example/bools/ast/ast.go index ac4e6b00..12698fa5 100644 --- a/example/bools/ast/ast.go +++ b/example/bools/ast/ast.go @@ -18,8 +18,7 @@ import ( "strconv" "strings" - "github.com/goccmack/gocc/example/bools/token" - "github.com/goccmack/gocc/example/bools/util" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/iface" ) type Attrib interface{} @@ -103,12 +102,17 @@ type LessThanExpr struct { B int64 } +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + + func NewLessThanExpr(a, b Attrib) (*LessThanExpr, error) { - aint, err := util.IntValue(a.(*token.Token).Lit) + aint, err := IntValue(a.(*iface.Token).Lit) if err != nil { return nil, err } - bint, err := util.IntValue(b.(*token.Token).Lit) + bint, err := IntValue(b.(*iface.Token).Lit) if err != nil { return nil, err } @@ -129,11 +133,11 @@ type SubStringExpr struct { } func NewSubStringExpr(a, b Attrib) (*SubStringExpr, error) { - astr, err := strconv.Unquote(string(a.(*token.Token).Lit)) + astr, err := strconv.Unquote(string(a.(*iface.Token).Lit)) if err != nil { return nil, err } - bstr, err := strconv.Unquote(string(b.(*token.Token).Lit)) + bstr, err := strconv.Unquote(string(b.(*iface.Token).Lit)) if err != nil { return nil, err } diff --git a/example/bools/example.bnf b/example/bools/bools.bnf similarity index 95% rename from example/bools/example.bnf rename to example/bools/bools.bnf index b800d3f9..f020ed1a 100644 --- a/example/bools/example.bnf +++ b/example/bools/bools.bnf @@ -20,7 +20,7 @@ string_lit : '"' {.} '"' ; !whitespace : ' ' | '\t' | '\n' | '\r' ; -<> +<> BoolExpr : BoolExpr1 << $0, nil >> diff --git a/example/bools/bools.grammar/bools/bools.go b/example/bools/bools.grammar/bools/bools.go new file mode 100644 index 00000000..8a84cb36 --- /dev/null +++ b/example/bools/bools.grammar/bools/bools.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package bools + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/errors" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/lexer" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/parser" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/bools/bools.grammar/bools/iface/bools.go b/example/bools/bools.grammar/bools/iface/bools.go new file mode 100644 index 00000000..46e8fe25 --- /dev/null +++ b/example/bools/bools.grammar/bools/iface/bools.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/errors" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/bools/bools.grammar/bools/internal/errors/errors.go b/example/bools/bools.grammar/bools/internal/errors/errors.go new file mode 100644 index 00000000..158778b3 --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/bools/bools.grammar/bools/internal/io/stream/internal/stream_impl.go b/example/bools/bools.grammar/bools/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/bools/bools.grammar/bools/internal/io/stream/internal/stream_public.go b/example/bools/bools.grammar/bools/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/bools/bools.grammar/bools/internal/io/stream/stream.go b/example/bools/bools.grammar/bools/internal/io/stream/stream.go new file mode 100644 index 00000000..99295ee6 --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/bools/lexer/acttab.go b/example/bools/bools.grammar/bools/internal/lexer/acttab.go old mode 100755 new mode 100644 similarity index 57% rename from example/bools/lexer/acttab.go rename to example/bools/bools.grammar/bools/internal/lexer/acttab.go index 0ad87756..8925225f --- a/example/bools/lexer/acttab.go +++ b/example/bools/bools.grammar/bools/internal/lexer/acttab.go @@ -5,7 +5,7 @@ package lexer import ( "fmt" - "github.com/goccmack/gocc/example/bools/token" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/token" ) type ActionTable [NumStates]ActionRow @@ -20,91 +20,91 @@ func (a ActionRow) String() string { } var ActTab = ActionTable{ - ActionRow{ // S0 + ActionRow{ // S0, Accept: 0, Ignore: "", }, - ActionRow{ // S1 + ActionRow{ // S1, Ignore("!whitespace") Accept: -1, Ignore: "!whitespace", }, - ActionRow{ // S2 + ActionRow{ // S2, Accept: 0, Ignore: "", }, - ActionRow{ // S3 + ActionRow{ // S3, Accept("Λ<&>") Accept: 2, Ignore: "", }, - ActionRow{ // S4 + ActionRow{ // S4, Accept("Λ<(>") Accept: 4, Ignore: "", }, - ActionRow{ // S5 + ActionRow{ // S5, Accept("Λ<)>") Accept: 5, Ignore: "", }, - ActionRow{ // S6 + ActionRow{ // S6, Accept("int_lit") Accept: 8, Ignore: "", }, - ActionRow{ // S7 + ActionRow{ // S7, Accept("Λ<<>") Accept: 9, Ignore: "", }, - ActionRow{ // S8 + ActionRow{ // S8, Accept("Λ<>>") Accept: 10, Ignore: "", }, - ActionRow{ // S9 + ActionRow{ // S9, Accept: 0, Ignore: "", }, - ActionRow{ // S10 + ActionRow{ // S10, Accept: 0, Ignore: "", }, - ActionRow{ // S11 + ActionRow{ // S11, Accept: 0, Ignore: "", }, - ActionRow{ // S12 + ActionRow{ // S12, Accept("Λ<|>") Accept: 3, Ignore: "", }, - ActionRow{ // S13 + ActionRow{ // S13, Accept("string_lit") Accept: 11, Ignore: "", }, - ActionRow{ // S14 + ActionRow{ // S14, Accept: 0, Ignore: "", }, - ActionRow{ // S15 + ActionRow{ // S15, Accept("Λ") Accept: 12, Ignore: "", }, - ActionRow{ // S16 + ActionRow{ // S16, Accept: 0, Ignore: "", }, - ActionRow{ // S17 + ActionRow{ // S17, Accept: 0, Ignore: "", }, - ActionRow{ // S18 + ActionRow{ // S18, Accept: 0, Ignore: "", }, - ActionRow{ // S19 + ActionRow{ // S19, Accept: 0, Ignore: "", }, - ActionRow{ // S20 + ActionRow{ // S20, Accept("Λ") Accept: 6, Ignore: "", }, - ActionRow{ // S21 + ActionRow{ // S21, Accept("Λ") Accept: 7, Ignore: "", }, diff --git a/example/bools/bools.grammar/bools/internal/lexer/lexer.go b/example/bools/bools.grammar/bools/internal/lexer/lexer.go new file mode 100644 index 00000000..e196f1e7 --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/iface" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/token" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 22 + NumSymbols = 25 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/bools/lexer/transitiontable.go b/example/bools/bools.grammar/bools/internal/lexer/transitiontable.go old mode 100755 new mode 100644 similarity index 100% rename from example/bools/lexer/transitiontable.go rename to example/bools/bools.grammar/bools/internal/lexer/transitiontable.go diff --git a/example/bools/parser/action.go b/example/bools/bools.grammar/bools/internal/parser/action.go old mode 100755 new mode 100644 similarity index 100% rename from example/bools/parser/action.go rename to example/bools/bools.grammar/bools/internal/parser/action.go diff --git a/example/bools/bools.grammar/bools/internal/parser/actiontable.go b/example/bools/bools.grammar/bools/internal/parser/actiontable.go new file mode 100644 index 00000000..2e06d3a0 --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/parser/actiontable.go @@ -0,0 +1,899 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + shift(6), // "(" + nil, // ")" + shift(7), // "true" + shift(8), // "false" + shift(9), // int_lit + nil, // "<" + nil, // ">" + shift(10), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + shift(11), // "&" + shift(12), // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: BoolExpr + reduce(1), // "&", reduce: BoolExpr + reduce(1), // "|", reduce: BoolExpr + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: BoolExpr1 + reduce(2), // "&", reduce: BoolExpr1 + reduce(2), // "|", reduce: BoolExpr1 + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(8), // Ω, reduce: Val + reduce(8), // "&", reduce: Val + reduce(8), // "|", reduce: Val + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(9), // Ω, reduce: Val + reduce(9), // "&", reduce: Val + reduce(9), // "|", reduce: Val + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + shift(18), // "(" + nil, // ")" + shift(19), // "true" + shift(20), // "false" + shift(21), // int_lit + nil, // "<" + nil, // ">" + shift(22), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S7 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(6), // Ω, reduce: Val + reduce(6), // "&", reduce: Val + reduce(6), // "|", reduce: Val + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S8 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(7), // Ω, reduce: Val + reduce(7), // "&", reduce: Val + reduce(7), // "|", reduce: Val + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S9 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + shift(23), // "<" + shift(24), // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S10 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + shift(25), // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S11 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + shift(6), // "(" + nil, // ")" + shift(7), // "true" + shift(8), // "false" + shift(9), // int_lit + nil, // "<" + nil, // ">" + shift(10), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S12 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + shift(6), // "(" + nil, // ")" + shift(7), // "true" + shift(8), // "false" + shift(9), // int_lit + nil, // "<" + nil, // ">" + shift(10), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S13 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(29), // "&" + shift(30), // "|" + nil, // "(" + shift(31), // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S14 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(1), // "&", reduce: BoolExpr + reduce(1), // "|", reduce: BoolExpr + nil, // "(" + reduce(1), // ")", reduce: BoolExpr + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S15 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(2), // "&", reduce: BoolExpr1 + reduce(2), // "|", reduce: BoolExpr1 + nil, // "(" + reduce(2), // ")", reduce: BoolExpr1 + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S16 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(8), // "&", reduce: Val + reduce(8), // "|", reduce: Val + nil, // "(" + reduce(8), // ")", reduce: Val + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S17 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(9), // "&", reduce: Val + reduce(9), // "|", reduce: Val + nil, // "(" + reduce(9), // ")", reduce: Val + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S18 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + shift(18), // "(" + nil, // ")" + shift(19), // "true" + shift(20), // "false" + shift(21), // int_lit + nil, // "<" + nil, // ">" + shift(22), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S19 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(6), // "&", reduce: Val + reduce(6), // "|", reduce: Val + nil, // "(" + reduce(6), // ")", reduce: Val + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S20 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(7), // "&", reduce: Val + reduce(7), // "|", reduce: Val + nil, // "(" + reduce(7), // ")", reduce: Val + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S21 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + shift(33), // "<" + shift(34), // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S22 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + shift(35), // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S23 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + shift(36), // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S24 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + shift(37), // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S25 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + shift(38), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S26 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(11), // "&" + shift(12), // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S27 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: BoolExpr1 + reduce(1), // "&", reduce: BoolExpr + reduce(1), // "|", reduce: BoolExpr + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S28 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(4), // Ω, reduce: BoolExpr1 + reduce(1), // "&", reduce: BoolExpr + reduce(1), // "|", reduce: BoolExpr + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S29 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + shift(18), // "(" + nil, // ")" + shift(19), // "true" + shift(20), // "false" + shift(21), // int_lit + nil, // "<" + nil, // ">" + shift(22), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S30 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + shift(18), // "(" + nil, // ")" + shift(19), // "true" + shift(20), // "false" + shift(21), // int_lit + nil, // "<" + nil, // ">" + shift(22), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S31 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(5), // Ω, reduce: BoolExpr1 + reduce(5), // "&", reduce: BoolExpr1 + reduce(5), // "|", reduce: BoolExpr1 + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S32 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(29), // "&" + shift(30), // "|" + nil, // "(" + shift(42), // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S33 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + shift(43), // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S34 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + shift(44), // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S35 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "&" + nil, // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + shift(45), // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S36 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(10), // Ω, reduce: CompareExpr + reduce(10), // "&", reduce: CompareExpr + reduce(10), // "|", reduce: CompareExpr + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S37 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(11), // Ω, reduce: CompareExpr + reduce(11), // "&", reduce: CompareExpr + reduce(11), // "|", reduce: CompareExpr + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S38 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(12), // Ω, reduce: SubStringExpr + reduce(12), // "&", reduce: SubStringExpr + reduce(12), // "|", reduce: SubStringExpr + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S39 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(29), // "&" + shift(30), // "|" + nil, // "(" + nil, // ")" + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S40 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(1), // "&", reduce: BoolExpr + reduce(1), // "|", reduce: BoolExpr + nil, // "(" + reduce(3), // ")", reduce: BoolExpr1 + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S41 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(1), // "&", reduce: BoolExpr + reduce(1), // "|", reduce: BoolExpr + nil, // "(" + reduce(4), // ")", reduce: BoolExpr1 + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S42 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(5), // "&", reduce: BoolExpr1 + reduce(5), // "|", reduce: BoolExpr1 + nil, // "(" + reduce(5), // ")", reduce: BoolExpr1 + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S43 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(10), // "&", reduce: CompareExpr + reduce(10), // "|", reduce: CompareExpr + nil, // "(" + reduce(10), // ")", reduce: CompareExpr + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S44 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(11), // "&", reduce: CompareExpr + reduce(11), // "|", reduce: CompareExpr + nil, // "(" + reduce(11), // ")", reduce: CompareExpr + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S45 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(12), // "&", reduce: SubStringExpr + reduce(12), // "|", reduce: SubStringExpr + nil, // "(" + reduce(12), // ")", reduce: SubStringExpr + nil, // "true" + nil, // "false" + nil, // int_lit + nil, // "<" + nil, // ">" + nil, // string_lit + nil, // "in" + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/bools/bools.grammar/bools/internal/parser/gototable.go b/example/bools/bools.grammar/bools/internal/parser/gototable.go new file mode 100644 index 00000000..83b8ddba --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/parser/gototable.go @@ -0,0 +1,381 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 6 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + 3, // Π + 4, // Π + 5, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S6 + -1, // Π + 13, // Π + 14, // Π + 15, // Π + 16, // Π + 17, // Π + }, + gotoRow{ // S7 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S8 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S9 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S10 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S11 + -1, // Π + 26, // Π + 27, // Π + 3, // Π + 4, // Π + 5, // Π + }, + gotoRow{ // S12 + -1, // Π + 26, // Π + 28, // Π + 3, // Π + 4, // Π + 5, // Π + }, + gotoRow{ // S13 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S14 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S15 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S16 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S17 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S18 + -1, // Π + 32, // Π + 14, // Π + 15, // Π + 16, // Π + 17, // Π + }, + gotoRow{ // S19 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S20 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S21 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S22 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S23 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S24 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S25 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S26 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S27 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S28 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S29 + -1, // Π + 39, // Π + 40, // Π + 15, // Π + 16, // Π + 17, // Π + }, + gotoRow{ // S30 + -1, // Π + 39, // Π + 41, // Π + 15, // Π + 16, // Π + 17, // Π + }, + gotoRow{ // S31 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S32 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S33 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S34 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S35 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S36 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S37 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S38 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S39 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S40 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S41 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S42 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S43 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S44 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S45 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/bools/bools.grammar/bools/internal/parser/parser.go b/example/bools/bools.grammar/bools/internal/parser/parser.go new file mode 100644 index 00000000..5a7b204a --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/parser/parser.go @@ -0,0 +1,353 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/iface" + parseError "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/errors" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/token" +) + +const ( + numProductions = 13 + numStates = 46 + numSymbols = 19 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = longest + p.isNonDeterministic = false + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/bools/bools.grammar/bools/internal/parser/productionstable.go b/example/bools/bools.grammar/bools/internal/parser/productionstable.go new file mode 100644 index 00000000..b8825689 --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/parser/productionstable.go @@ -0,0 +1,189 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "github.com/maxcalandrelli/gocc/example/bools/ast" +) + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/token" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `BoolExpr : Π << $0, nil >>`, + Id: "BoolExpr", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `BoolExpr1 : Π << $0, nil >>`, + Id: "BoolExpr1", + NTType: 2, + Index: 2, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `BoolExpr1 : Π Λ<&> Π << ast.NewBoolAndExpr($0, $2) >>`, + Id: "BoolExpr1", + NTType: 2, + Index: 3, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewBoolAndExpr(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `BoolExpr1 : Π Λ<|> Π << ast.NewBoolOrExpr($0, $2) >>`, + Id: "BoolExpr1", + NTType: 2, + Index: 4, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewBoolOrExpr(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `BoolExpr1 : Λ<(> Π Λ<)> << ast.NewBoolGroupExpr($1) >>`, + Id: "BoolExpr1", + NTType: 2, + Index: 5, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewBoolGroupExpr(X[1]) + }, + }, + ProdTabEntry{ + String: `Val : Λ << ast.TRUE, nil >>`, + Id: "Val", + NTType: 3, + Index: 6, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.TRUE, nil + }, + }, + ProdTabEntry{ + String: `Val : Λ << ast.FALSE, nil >>`, + Id: "Val", + NTType: 3, + Index: 7, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.FALSE, nil + }, + }, + ProdTabEntry{ + String: `Val : Π << $0, nil >>`, + Id: "Val", + NTType: 3, + Index: 8, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Val : Π << $0, nil >>`, + Id: "Val", + NTType: 3, + Index: 9, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `CompareExpr : int_lit Λ<<> int_lit << ast.NewLessThanExpr($0, $2) >>`, + Id: "CompareExpr", + NTType: 4, + Index: 10, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLessThanExpr(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `CompareExpr : int_lit Λ<>> int_lit << ast.NewLessThanExpr($2, $0) >>`, + Id: "CompareExpr", + NTType: 4, + Index: 11, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLessThanExpr(X[2], X[0]) + }, + }, + ProdTabEntry{ + String: `SubStringExpr : string_lit Λ string_lit << ast.NewSubStringExpr($0, $2) >>`, + Id: "SubStringExpr", + NTType: 5, + Index: 12, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSubStringExpr(X[0], X[2]) + }, + }, +} diff --git a/example/bools/bools.grammar/bools/internal/token/token.go b/example/bools/bools.grammar/bools/internal/token/token.go new file mode 100644 index 00000000..97d497d8 --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/token/token.go @@ -0,0 +1,121 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +import ( + "fmt" +) + +type Token struct { + Type + Lit []byte + IgnoredPrefix []byte + Pos + ForeignAstNode interface{} + Foreign bool +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (p Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) +} + +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type + litMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "Ω", + "Λ<&>", + "Λ<|>", + "Λ<(>", + "Λ<)>", + "Λ", + "Λ", + "int_lit", + "Λ<<>", + "Λ<>>", + "string_lit", + "Λ", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "Ω": 1, + "Λ<&>": 2, + "Λ<|>": 3, + "Λ<(>": 4, + "Λ<)>": 5, + "Λ": 6, + "Λ": 7, + "int_lit": 8, + "Λ<<>": 9, + "Λ<>>": 10, + "string_lit": 11, + "Λ": 12, + }, + + litMap: map[string]Type{ + "&": 2, + "|": 3, + "(": 4, + ")": 5, + "true": 6, + "false": 7, + "<": 9, + ">": 10, + "in": 12, + }, +} diff --git a/example/bools/util/litconv.go b/example/bools/bools.grammar/bools/internal/util/litconv.go old mode 100755 new mode 100644 similarity index 100% rename from example/bools/util/litconv.go rename to example/bools/bools.grammar/bools/internal/util/litconv.go diff --git a/example/bools/bools.grammar/bools/internal/util/rune.go b/example/bools/bools.grammar/bools/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/bools/bools.grammar/bools/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/bools/bools.grammar/bools/main/bools.go b/example/bools/bools.grammar/bools/main/bools.go new file mode 100644 index 00000000..acd02169 --- /dev/null +++ b/example/bools/bools.grammar/bools/main/bools.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + bools "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *bools.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return bools.NewParser().ParseLongestPrefix(lex) + } else { + res, err = bools.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, bools.NewLexerString(Text))) + } + if File > "" { + l, e := bools.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, bools.NewLexerString(str))) + } +} diff --git a/example/bools/bools.grammar/bools/util.go b/example/bools/bools.grammar/bools/util.go new file mode 100644 index 00000000..d27bb434 --- /dev/null +++ b/example/bools/bools.grammar/bools/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package bools + +import ( + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/bools/example_test.go b/example/bools/example_test.go index 64a16345..7af78e8d 100644 --- a/example/bools/example_test.go +++ b/example/bools/example_test.go @@ -17,14 +17,13 @@ package example import ( "testing" - "github.com/goccmack/gocc/example/bools/ast" - "github.com/goccmack/gocc/example/bools/lexer" - "github.com/goccmack/gocc/example/bools/parser" + "github.com/maxcalandrelli/gocc/example/bools/ast" + "github.com/maxcalandrelli/gocc/example/bools/bools.grammar/bools" ) func testEval(t *testing.T, exampleStr string, output bool) { - lex := lexer.NewLexer([]byte(exampleStr)) - p := parser.NewParser() + lex := bools.NewLexerString(exampleStr) + p := bools.NewParser() st, err := p.Parse(lex) if err != nil { panic(err) diff --git a/example/bools/lexer/lexer.go b/example/bools/lexer/lexer.go deleted file mode 100755 index 7a9808e9..00000000 --- a/example/bools/lexer/lexer.go +++ /dev/null @@ -1,141 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package lexer - -import ( - "io/ioutil" - "unicode/utf8" - - "github.com/goccmack/gocc/example/bools/token" -) - -const ( - NoState = -1 - NumStates = 22 - NumSymbols = 25 -) - -type Lexer struct { - src []byte - pos int - line int - column int -} - -func NewLexer(src []byte) *Lexer { - lexer := &Lexer{ - src: src, - pos: 0, - line: 1, - column: 1, - } - return lexer -} - -func NewLexerFile(fpath string) (*Lexer, error) { - src, err := ioutil.ReadFile(fpath) - if err != nil { - return nil, err - } - return NewLexer(src), nil -} - -func (l *Lexer) Scan() (tok *token.Token) { - tok = new(token.Token) - if l.pos >= len(l.src) { - tok.Type = token.EOF - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column - return - } - start, startLine, startColumn, end := l.pos, l.line, l.column, 0 - tok.Type = token.INVALID - state, rune1, size := 0, rune(-1), 0 - for state != -1 { - if l.pos >= len(l.src) { - rune1 = -1 - } else { - rune1, size = utf8.DecodeRune(l.src[l.pos:]) - l.pos += size - } - - nextState := -1 - if rune1 != -1 { - nextState = TransTab[state](rune1) - } - state = nextState - - if state != -1 { - - switch rune1 { - case '\n': - l.line++ - l.column = 1 - case '\r': - l.column = 1 - case '\t': - l.column += 4 - default: - l.column++ - } - - switch { - case ActTab[state].Accept != -1: - tok.Type = ActTab[state].Accept - end = l.pos - case ActTab[state].Ignore != "": - start, startLine, startColumn = l.pos, l.line, l.column - state = 0 - if start >= len(l.src) { - tok.Type = token.EOF - } - - } - } else { - if tok.Type == token.INVALID { - end = l.pos - } - } - } - if end > start { - l.pos = end - tok.Lit = l.src[start:end] - } else { - tok.Lit = []byte{} - } - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn - - return -} - -func (l *Lexer) Reset() { - l.pos = 0 -} - -/* -Lexer symbols: -0: '"' -1: '"' -2: '&' -3: '|' -4: '(' -5: ')' -6: 't' -7: 'r' -8: 'u' -9: 'e' -10: 'f' -11: 'a' -12: 'l' -13: 's' -14: 'e' -15: '<' -16: '>' -17: 'i' -18: 'n' -19: ' ' -20: '\t' -21: '\n' -22: '\r' -23: '0'-'9' -24: . -*/ diff --git a/example/bools/parser/actiontable.go b/example/bools/parser/actiontable.go deleted file mode 100755 index b55e6f90..00000000 --- a/example/bools/parser/actiontable.go +++ /dev/null @@ -1,842 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - actionTable [numStates]actionRow - actionRow struct { - canRecover bool - actions [numSymbols]action - } -) - -var actionTab = actionTable{ - actionRow{ // S0 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - shift(4), // ( - nil, // ) - shift(5), // true - shift(6), // false - shift(9), // int_lit - nil, // < - nil, // > - shift(10), // string_lit - nil, // in - }, - }, - actionRow{ // S1 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - accept(true), // $ - shift(11), // & - shift(12), // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S2 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(1), // $, reduce: BoolExpr - reduce(1), // &, reduce: BoolExpr - reduce(1), // |, reduce: BoolExpr - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S3 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(2), // $, reduce: BoolExpr1 - reduce(2), // &, reduce: BoolExpr1 - reduce(2), // |, reduce: BoolExpr1 - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S4 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - shift(16), // ( - nil, // ) - shift(17), // true - shift(18), // false - shift(21), // int_lit - nil, // < - nil, // > - shift(22), // string_lit - nil, // in - }, - }, - actionRow{ // S5 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(6), // $, reduce: Val - reduce(6), // &, reduce: Val - reduce(6), // |, reduce: Val - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S6 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(7), // $, reduce: Val - reduce(7), // &, reduce: Val - reduce(7), // |, reduce: Val - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S7 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(8), // $, reduce: Val - reduce(8), // &, reduce: Val - reduce(8), // |, reduce: Val - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S8 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(9), // $, reduce: Val - reduce(9), // &, reduce: Val - reduce(9), // |, reduce: Val - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S9 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - shift(23), // < - shift(24), // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S10 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - shift(25), // in - }, - }, - actionRow{ // S11 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - shift(4), // ( - nil, // ) - shift(5), // true - shift(6), // false - shift(9), // int_lit - nil, // < - nil, // > - shift(10), // string_lit - nil, // in - }, - }, - actionRow{ // S12 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - shift(4), // ( - nil, // ) - shift(5), // true - shift(6), // false - shift(9), // int_lit - nil, // < - nil, // > - shift(10), // string_lit - nil, // in - }, - }, - actionRow{ // S13 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(29), // & - shift(30), // | - nil, // ( - shift(31), // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S14 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(1), // &, reduce: BoolExpr - reduce(1), // |, reduce: BoolExpr - nil, // ( - reduce(1), // ), reduce: BoolExpr - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S15 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(2), // &, reduce: BoolExpr1 - reduce(2), // |, reduce: BoolExpr1 - nil, // ( - reduce(2), // ), reduce: BoolExpr1 - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S16 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - shift(16), // ( - nil, // ) - shift(17), // true - shift(18), // false - shift(21), // int_lit - nil, // < - nil, // > - shift(22), // string_lit - nil, // in - }, - }, - actionRow{ // S17 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(6), // &, reduce: Val - reduce(6), // |, reduce: Val - nil, // ( - reduce(6), // ), reduce: Val - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S18 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(7), // &, reduce: Val - reduce(7), // |, reduce: Val - nil, // ( - reduce(7), // ), reduce: Val - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S19 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(8), // &, reduce: Val - reduce(8), // |, reduce: Val - nil, // ( - reduce(8), // ), reduce: Val - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S20 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(9), // &, reduce: Val - reduce(9), // |, reduce: Val - nil, // ( - reduce(9), // ), reduce: Val - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S21 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - shift(33), // < - shift(34), // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S22 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - shift(35), // in - }, - }, - actionRow{ // S23 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - shift(36), // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S24 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - shift(37), // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S25 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - shift(38), // string_lit - nil, // in - }, - }, - actionRow{ // S26 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(11), // & - shift(12), // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S27 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(3), // $, reduce: BoolExpr1 - reduce(1), // &, reduce: BoolExpr - reduce(1), // |, reduce: BoolExpr - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S28 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(4), // $, reduce: BoolExpr1 - reduce(1), // &, reduce: BoolExpr - reduce(1), // |, reduce: BoolExpr - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S29 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - shift(16), // ( - nil, // ) - shift(17), // true - shift(18), // false - shift(21), // int_lit - nil, // < - nil, // > - shift(22), // string_lit - nil, // in - }, - }, - actionRow{ // S30 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - shift(16), // ( - nil, // ) - shift(17), // true - shift(18), // false - shift(21), // int_lit - nil, // < - nil, // > - shift(22), // string_lit - nil, // in - }, - }, - actionRow{ // S31 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(5), // $, reduce: BoolExpr1 - reduce(5), // &, reduce: BoolExpr1 - reduce(5), // |, reduce: BoolExpr1 - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S32 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(29), // & - shift(30), // | - nil, // ( - shift(42), // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S33 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - shift(43), // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S34 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - shift(44), // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S35 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // & - nil, // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - shift(45), // string_lit - nil, // in - }, - }, - actionRow{ // S36 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(10), // $, reduce: CompareExpr - reduce(10), // &, reduce: CompareExpr - reduce(10), // |, reduce: CompareExpr - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S37 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(11), // $, reduce: CompareExpr - reduce(11), // &, reduce: CompareExpr - reduce(11), // |, reduce: CompareExpr - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S38 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(12), // $, reduce: SubStringExpr - reduce(12), // &, reduce: SubStringExpr - reduce(12), // |, reduce: SubStringExpr - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S39 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(29), // & - shift(30), // | - nil, // ( - nil, // ) - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S40 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(1), // &, reduce: BoolExpr - reduce(1), // |, reduce: BoolExpr - nil, // ( - reduce(3), // ), reduce: BoolExpr1 - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S41 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(1), // &, reduce: BoolExpr - reduce(1), // |, reduce: BoolExpr - nil, // ( - reduce(4), // ), reduce: BoolExpr1 - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S42 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(5), // &, reduce: BoolExpr1 - reduce(5), // |, reduce: BoolExpr1 - nil, // ( - reduce(5), // ), reduce: BoolExpr1 - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S43 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(10), // &, reduce: CompareExpr - reduce(10), // |, reduce: CompareExpr - nil, // ( - reduce(10), // ), reduce: CompareExpr - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S44 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(11), // &, reduce: CompareExpr - reduce(11), // |, reduce: CompareExpr - nil, // ( - reduce(11), // ), reduce: CompareExpr - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, - actionRow{ // S45 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(12), // &, reduce: SubStringExpr - reduce(12), // |, reduce: SubStringExpr - nil, // ( - reduce(12), // ), reduce: SubStringExpr - nil, // true - nil, // false - nil, // int_lit - nil, // < - nil, // > - nil, // string_lit - nil, // in - }, - }, -} diff --git a/example/bools/parser/gototable.go b/example/bools/parser/gototable.go deleted file mode 100755 index d8853cb9..00000000 --- a/example/bools/parser/gototable.go +++ /dev/null @@ -1,381 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -const numNTSymbols = 6 - -type ( - gotoTable [numStates]gotoRow - gotoRow [numNTSymbols]int -) - -var gotoTab = gotoTable{ - gotoRow{ // S0 - -1, // S' - 1, // BoolExpr - 2, // BoolExpr1 - 3, // Val - 7, // CompareExpr - 8, // SubStringExpr - }, - gotoRow{ // S1 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S2 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S3 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S4 - -1, // S' - 13, // BoolExpr - 14, // BoolExpr1 - 15, // Val - 19, // CompareExpr - 20, // SubStringExpr - }, - gotoRow{ // S5 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S6 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S7 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S8 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S9 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S10 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S11 - -1, // S' - 26, // BoolExpr - 27, // BoolExpr1 - 3, // Val - 7, // CompareExpr - 8, // SubStringExpr - }, - gotoRow{ // S12 - -1, // S' - 26, // BoolExpr - 28, // BoolExpr1 - 3, // Val - 7, // CompareExpr - 8, // SubStringExpr - }, - gotoRow{ // S13 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S14 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S15 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S16 - -1, // S' - 32, // BoolExpr - 14, // BoolExpr1 - 15, // Val - 19, // CompareExpr - 20, // SubStringExpr - }, - gotoRow{ // S17 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S18 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S19 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S20 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S21 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S22 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S23 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S24 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S25 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S26 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S27 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S28 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S29 - -1, // S' - 39, // BoolExpr - 40, // BoolExpr1 - 15, // Val - 19, // CompareExpr - 20, // SubStringExpr - }, - gotoRow{ // S30 - -1, // S' - 39, // BoolExpr - 41, // BoolExpr1 - 15, // Val - 19, // CompareExpr - 20, // SubStringExpr - }, - gotoRow{ // S31 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S32 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S33 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S34 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S35 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S36 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S37 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S38 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S39 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S40 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S41 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S42 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S43 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S44 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, - gotoRow{ // S45 - -1, // S' - -1, // BoolExpr - -1, // BoolExpr1 - -1, // Val - -1, // CompareExpr - -1, // SubStringExpr - }, -} diff --git a/example/bools/parser/parser.go b/example/bools/parser/parser.go deleted file mode 100755 index e2074579..00000000 --- a/example/bools/parser/parser.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "fmt" - "strings" - - parseError "github.com/goccmack/gocc/example/bools/errors" - "github.com/goccmack/gocc/example/bools/token" -) - -const ( - numProductions = 13 - numStates = 46 - numSymbols = 19 -) - -// Stack - -type stack struct { - state []int - attrib []Attrib -} - -const iNITIAL_STACK_SIZE = 100 - -func newStack() *stack { - return &stack{ - state: make([]int, 0, iNITIAL_STACK_SIZE), - attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), - } -} - -func (s *stack) reset() { - s.state = s.state[:0] - s.attrib = s.attrib[:0] -} - -func (s *stack) push(state int, a Attrib) { - s.state = append(s.state, state) - s.attrib = append(s.attrib, a) -} - -func (s *stack) top() int { - return s.state[len(s.state)-1] -} - -func (s *stack) peek(pos int) int { - return s.state[pos] -} - -func (s *stack) topIndex() int { - return len(s.state) - 1 -} - -func (s *stack) popN(items int) []Attrib { - lo, hi := len(s.state)-items, len(s.state) - - attrib := s.attrib[lo:hi] - - s.state = s.state[:lo] - s.attrib = s.attrib[:lo] - - return attrib -} - -func (s *stack) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "stack:\n") - for i, st := range s.state { - fmt.Fprintf(w, "\t%d: %d , ", i, st) - if s.attrib[i] == nil { - fmt.Fprintf(w, "nil") - } else { - switch attr := s.attrib[i].(type) { - case *token.Token: - fmt.Fprintf(w, "%s", attr.Lit) - default: - fmt.Fprintf(w, "%v", attr) - } - } - fmt.Fprintf(w, "\n") - } - return w.String() -} - -// Parser - -type Parser struct { - stack *stack - nextToken *token.Token - pos int -} - -type Scanner interface { - Scan() (tok *token.Token) -} - -func NewParser() *Parser { - p := &Parser{stack: newStack()} - p.Reset() - return p -} - -func (p *Parser) Reset() { - p.stack.reset() - p.stack.push(0, nil) -} - -func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { - errorAttrib = &parseError.Error{ - Err: err, - ErrorToken: p.nextToken, - ErrorSymbols: p.popNonRecoveryStates(), - ExpectedTokens: make([]string, 0, 8), - } - for t, action := range actionTab[p.stack.top()].actions { - if action != nil { - errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) - } - } - - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { - p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift - } else { - return - } - - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - for !recovered && p.nextToken.Type != token.EOF { - p.nextToken = scanner.Scan() - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - } - - return -} - -func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { - if rs, ok := p.firstRecoveryState(); ok { - errorSymbols := p.stack.popN(p.stack.topIndex() - rs) - removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) - for i, e := range errorSymbols { - removedAttribs[i] = e - } - } else { - removedAttribs = []parseError.ErrorSymbol{} - } - return -} - -// recoveryState points to the highest state on the stack, which can recover -func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { - recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover - for recoveryState > 0 && !canRecover { - recoveryState-- - canRecover = actionTab[p.stack.peek(recoveryState)].canRecover - } - return -} - -func (p *Parser) newError(err error) error { - e := &parseError.Error{ - Err: err, - StackTop: p.stack.top(), - ErrorToken: p.nextToken, - } - actRow := actionTab[p.stack.top()] - for i, t := range actRow.actions { - if t != nil { - e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) - } - } - return e -} - -func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { - p.Reset() - p.nextToken = scanner.Scan() - for acc := false; !acc; { - action := actionTab[p.stack.top()].actions[p.nextToken.Type] - if action == nil { - if recovered, errAttrib := p.Error(nil, scanner); !recovered { - p.nextToken = errAttrib.ErrorToken - return nil, p.newError(nil) - } - if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { - panic("Error recovery led to invalid action") - } - } - - switch act := action.(type) { - case accept: - res = p.stack.popN(1)[0] - acc = true - case shift: - p.stack.push(int(act), p.nextToken) - p.nextToken = scanner.Scan() - case reduce: - prod := productionsTable[int(act)] - attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) - if err != nil { - return nil, p.newError(err) - } else { - p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) - } - default: - panic("unknown action: " + action.String()) - } - } - return res, nil -} diff --git a/example/bools/parser/productionstable.go b/example/bools/parser/productionstable.go deleted file mode 100755 index 70d32f6a..00000000 --- a/example/bools/parser/productionstable.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "github.com/goccmack/gocc/example/bools/ast" -) - -type ( - //TODO: change type and variable names to be consistent with other tables - ProdTab [numProductions]ProdTabEntry - ProdTabEntry struct { - String string - Id string - NTType int - Index int - NumSymbols int - ReduceFunc func([]Attrib) (Attrib, error) - } - Attrib interface { - } -) - -var productionsTable = ProdTab{ - ProdTabEntry{ - String: `S' : BoolExpr << >>`, - Id: "S'", - NTType: 0, - Index: 0, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `BoolExpr : BoolExpr1 << X[0], nil >>`, - Id: "BoolExpr", - NTType: 1, - Index: 1, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `BoolExpr1 : Val << X[0], nil >>`, - Id: "BoolExpr1", - NTType: 2, - Index: 2, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `BoolExpr1 : BoolExpr "&" BoolExpr1 << ast.NewBoolAndExpr(X[0], X[2]) >>`, - Id: "BoolExpr1", - NTType: 2, - Index: 3, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewBoolAndExpr(X[0], X[2]) - }, - }, - ProdTabEntry{ - String: `BoolExpr1 : BoolExpr "|" BoolExpr1 << ast.NewBoolOrExpr(X[0], X[2]) >>`, - Id: "BoolExpr1", - NTType: 2, - Index: 4, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewBoolOrExpr(X[0], X[2]) - }, - }, - ProdTabEntry{ - String: `BoolExpr1 : "(" BoolExpr ")" << ast.NewBoolGroupExpr(X[1]) >>`, - Id: "BoolExpr1", - NTType: 2, - Index: 5, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewBoolGroupExpr(X[1]) - }, - }, - ProdTabEntry{ - String: `Val : "true" << ast.TRUE, nil >>`, - Id: "Val", - NTType: 3, - Index: 6, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.TRUE, nil - }, - }, - ProdTabEntry{ - String: `Val : "false" << ast.FALSE, nil >>`, - Id: "Val", - NTType: 3, - Index: 7, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.FALSE, nil - }, - }, - ProdTabEntry{ - String: `Val : CompareExpr << X[0], nil >>`, - Id: "Val", - NTType: 3, - Index: 8, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `Val : SubStringExpr << X[0], nil >>`, - Id: "Val", - NTType: 3, - Index: 9, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `CompareExpr : int_lit "<" int_lit << ast.NewLessThanExpr(X[0], X[2]) >>`, - Id: "CompareExpr", - NTType: 4, - Index: 10, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewLessThanExpr(X[0], X[2]) - }, - }, - ProdTabEntry{ - String: `CompareExpr : int_lit ">" int_lit << ast.NewLessThanExpr(X[2], X[0]) >>`, - Id: "CompareExpr", - NTType: 4, - Index: 11, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewLessThanExpr(X[2], X[0]) - }, - }, - ProdTabEntry{ - String: `SubStringExpr : string_lit "in" string_lit << ast.NewSubStringExpr(X[0], X[2]) >>`, - Id: "SubStringExpr", - NTType: 5, - Index: 12, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewSubStringExpr(X[0], X[2]) - }, - }, -} diff --git a/example/bools/util/rune.go b/example/bools/util/rune.go deleted file mode 100755 index bd8523a4..00000000 --- a/example/bools/util/rune.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package util - -import ( - "fmt" -) - -func RuneToString(r rune) string { - if r >= 0x20 && r < 0x7f { - return fmt.Sprintf("'%c'", r) - } - switch r { - case 0x07: - return "'\\a'" - case 0x08: - return "'\\b'" - case 0x0C: - return "'\\f'" - case 0x0A: - return "'\\n'" - case 0x0D: - return "'\\r'" - case 0x09: - return "'\\t'" - case 0x0b: - return "'\\v'" - case 0x5c: - return "'\\\\\\'" - case 0x27: - return "'\\''" - case 0x22: - return "'\\\"'" - } - if r < 0x10000 { - return fmt.Sprintf("\\u%04x", r) - } - return fmt.Sprintf("\\U%08x", r) -} diff --git a/example/calc/Makefile b/example/calc/Makefile index fbe8769e..9e88a6ad 100644 --- a/example/calc/Makefile +++ b/example/calc/Makefile @@ -1,2 +1,2 @@ regenerate: - gocc calc.bnf \ No newline at end of file + gocc -a calc.bnf \ No newline at end of file diff --git a/example/calc/calc.bnf b/example/calc/calc.bnf index d9469b05..eac97693 100644 --- a/example/calc/calc.bnf +++ b/example/calc/calc.bnf @@ -2,29 +2,29 @@ _digit : '0'-'9' ; -int64 : '1'-'9' {_digit} ; +int64 : '0'-'9' {_digit} ; !whitespace : ' ' | '\t' | '\n' | '\r' ; /* Syntax part */ -<< -import( - "github.com/goccmack/gocc/example/calc/token" - "github.com/goccmack/gocc/example/calc/util" -) +<< >> Calc : Expr; Expr : - Expr "+" Term << $0.(int64) + $2.(int64), nil >> - | Term + Term "+" Term << $0.(int64) + $2.(int64), nil >> + | Term "-" Term << $0.(int64) - $2.(int64), nil >> + | "-" Term << -$1.(int64), nil >> + | Term "*" Factor << $0.(int64) * $2.(int64), nil >> + | Term "/" Factor << $0.(int64) / $2.(int64), nil >> + | Term << $0.(int64), nil >> ; Term : Term "*" Factor << $0.(int64) * $2.(int64), nil >> - | Factor + | Factor ; Factor : diff --git a/example/calc/calc.grammar/calc/calc.go b/example/calc/calc.grammar/calc/calc.go new file mode 100644 index 00000000..1eb9671f --- /dev/null +++ b/example/calc/calc.grammar/calc/calc.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package calc + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/errors" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/lexer" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/parser" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/calc/calc.grammar/calc/iface/calc.go b/example/calc/calc.grammar/calc/iface/calc.go new file mode 100644 index 00000000..02547669 --- /dev/null +++ b/example/calc/calc.grammar/calc/iface/calc.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/errors" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/calc/calc.grammar/calc/internal/errors/errors.go b/example/calc/calc.grammar/calc/internal/errors/errors.go new file mode 100644 index 00000000..169169ed --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/calc/calc.grammar/calc/internal/io/stream/internal/stream_impl.go b/example/calc/calc.grammar/calc/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/calc/calc.grammar/calc/internal/io/stream/internal/stream_public.go b/example/calc/calc.grammar/calc/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/calc/calc.grammar/calc/internal/io/stream/stream.go b/example/calc/calc.grammar/calc/internal/io/stream/stream.go new file mode 100644 index 00000000..7ac9fc98 --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/calc/calc.grammar/calc/internal/lexer/acttab.go b/example/calc/calc.grammar/calc/internal/lexer/acttab.go new file mode 100644 index 00000000..28f284a0 --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/lexer/acttab.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + "fmt" + + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (a ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1, Ignore("!whitespace") + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2, Accept("Λ<(>") + Accept: 6, + Ignore: "", + }, + ActionRow{ // S3, Accept("Λ<)>") + Accept: 7, + Ignore: "", + }, + ActionRow{ // S4, Accept("Λ<*>") + Accept: 4, + Ignore: "", + }, + ActionRow{ // S5, Accept("Λ<+>") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S6, Accept("Λ<->") + Accept: 3, + Ignore: "", + }, + ActionRow{ // S7, Accept("Λ") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S8, Accept("int64") + Accept: 8, + Ignore: "", + }, + ActionRow{ // S9, Accept("int64") + Accept: 8, + Ignore: "", + }, +} diff --git a/example/calc/calc.grammar/calc/internal/lexer/lexer.go b/example/calc/calc.grammar/calc/internal/lexer/lexer.go new file mode 100644 index 00000000..6169b0d0 --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/iface" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/token" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 10 + NumSymbols = 13 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/calc/lexer/transitiontable.go b/example/calc/calc.grammar/calc/internal/lexer/transitiontable.go old mode 100755 new mode 100644 similarity index 82% rename from example/calc/lexer/transitiontable.go rename to example/calc/calc.grammar/calc/internal/lexer/transitiontable.go index 9edc0aec..f649e498 --- a/example/calc/lexer/transitiontable.go +++ b/example/calc/calc.grammar/calc/internal/lexer/transitiontable.go @@ -29,8 +29,12 @@ var TransTab = TransitionTable{ return 4 case r == 43: // ['+','+'] return 5 - case 49 <= r && r <= 57: // ['1','9'] + case r == 45: // ['-','-'] return 6 + case r == 47: // ['/','/'] + return 7 + case 48 <= r && r <= 57: // ['0','9'] + return 8 } return NoState }, @@ -67,16 +71,28 @@ var TransTab = TransitionTable{ // S6 func(r rune) int { switch { - case 48 <= r && r <= 57: // ['0','9'] - return 7 } return NoState }, // S7 + func(r rune) int { + switch { + } + return NoState + }, + // S8 func(r rune) int { switch { case 48 <= r && r <= 57: // ['0','9'] - return 7 + return 9 + } + return NoState + }, + // S9 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 9 } return NoState }, diff --git a/example/calc/parser/action.go b/example/calc/calc.grammar/calc/internal/parser/action.go old mode 100755 new mode 100644 similarity index 100% rename from example/calc/parser/action.go rename to example/calc/calc.grammar/calc/internal/parser/action.go diff --git a/example/calc/calc.grammar/calc/internal/parser/actiontable.go b/example/calc/calc.grammar/calc/internal/parser/actiontable.go new file mode 100644 index 00000000..29361f5b --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/parser/actiontable.go @@ -0,0 +1,880 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + shift(5), // "-" + nil, // "*" + nil, // "/" + shift(6), // "(" + nil, // ")" + shift(7), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: Calc + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(7), // Ω, reduce: Expr + shift(8), // "+" + shift(9), // "-" + shift(10), // "*" + shift(11), // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(9), // Ω, reduce: Term + reduce(9), // "+", reduce: Term + reduce(9), // "-", reduce: Term + reduce(9), // "*", reduce: Term + reduce(9), // "/", reduce: Term + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(14), // "(" + nil, // ")" + shift(15), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + shift(19), // "-" + nil, // "*" + nil, // "/" + shift(20), // "(" + nil, // ")" + shift(21), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S7 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(11), // Ω, reduce: Factor + reduce(11), // "+", reduce: Factor + reduce(11), // "-", reduce: Factor + reduce(11), // "*", reduce: Factor + reduce(11), // "/", reduce: Factor + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S8 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(14), // "(" + nil, // ")" + shift(15), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S9 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(14), // "(" + nil, // ")" + shift(15), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S10 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(6), // "(" + nil, // ")" + shift(7), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S11 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(26), // "(" + nil, // ")" + shift(27), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S12 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(4), // Ω, reduce: Expr + nil, // "+" + nil, // "-" + shift(28), // "*" + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S13 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(9), // Ω, reduce: Term + nil, // "+" + nil, // "-" + reduce(9), // "*", reduce: Term + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S14 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + shift(19), // "-" + nil, // "*" + nil, // "/" + shift(20), // "(" + nil, // ")" + shift(21), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S15 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(11), // Ω, reduce: Factor + nil, // "+" + nil, // "-" + reduce(11), // "*", reduce: Factor + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S16 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + shift(30), // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S17 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(31), // "+" + shift(32), // "-" + shift(33), // "*" + shift(34), // "/" + nil, // "(" + reduce(7), // ")", reduce: Expr + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S18 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(9), // "+", reduce: Term + reduce(9), // "-", reduce: Term + reduce(9), // "*", reduce: Term + reduce(9), // "/", reduce: Term + nil, // "(" + reduce(9), // ")", reduce: Term + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S19 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(37), // "(" + nil, // ")" + shift(38), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S20 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + shift(19), // "-" + nil, // "*" + nil, // "/" + shift(20), // "(" + nil, // ")" + shift(21), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S21 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(11), // "+", reduce: Factor + reduce(11), // "-", reduce: Factor + reduce(11), // "*", reduce: Factor + reduce(11), // "/", reduce: Factor + nil, // "(" + reduce(11), // ")", reduce: Factor + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S22 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: Expr + nil, // "+" + nil, // "-" + shift(28), // "*" + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S23 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Expr + nil, // "+" + nil, // "-" + shift(28), // "*" + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S24 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(5), // Ω, reduce: Expr + reduce(8), // "+", reduce: Term + reduce(8), // "-", reduce: Term + reduce(8), // "*", reduce: Term + reduce(8), // "/", reduce: Term + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S25 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(6), // Ω, reduce: Expr + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S26 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + shift(19), // "-" + nil, // "*" + nil, // "/" + shift(20), // "(" + nil, // ")" + shift(21), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S27 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(11), // Ω, reduce: Factor + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S28 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(14), // "(" + nil, // ")" + shift(15), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S29 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + shift(42), // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S30 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(10), // Ω, reduce: Factor + reduce(10), // "+", reduce: Factor + reduce(10), // "-", reduce: Factor + reduce(10), // "*", reduce: Factor + reduce(10), // "/", reduce: Factor + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S31 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(37), // "(" + nil, // ")" + shift(38), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S32 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(37), // "(" + nil, // ")" + shift(38), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S33 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(20), // "(" + nil, // ")" + shift(21), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S34 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(47), // "(" + nil, // ")" + shift(48), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S35 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + shift(49), // "*" + nil, // "/" + nil, // "(" + reduce(4), // ")", reduce: Expr + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S36 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + reduce(9), // "*", reduce: Term + nil, // "/" + nil, // "(" + reduce(9), // ")", reduce: Term + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S37 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + shift(19), // "-" + nil, // "*" + nil, // "/" + shift(20), // "(" + nil, // ")" + shift(21), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S38 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + reduce(11), // "*", reduce: Factor + nil, // "/" + nil, // "(" + reduce(11), // ")", reduce: Factor + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S39 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + shift(51), // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S40 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + shift(52), // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S41 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(8), // Ω, reduce: Term + nil, // "+" + nil, // "-" + reduce(8), // "*", reduce: Term + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S42 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(10), // Ω, reduce: Factor + nil, // "+" + nil, // "-" + reduce(10), // "*", reduce: Factor + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S43 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + shift(49), // "*" + nil, // "/" + nil, // "(" + reduce(2), // ")", reduce: Expr + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S44 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + shift(49), // "*" + nil, // "/" + nil, // "(" + reduce(3), // ")", reduce: Expr + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S45 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(8), // "+", reduce: Term + reduce(8), // "-", reduce: Term + reduce(8), // "*", reduce: Term + reduce(8), // "/", reduce: Term + nil, // "(" + reduce(5), // ")", reduce: Expr + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S46 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + reduce(6), // ")", reduce: Expr + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S47 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + shift(19), // "-" + nil, // "*" + nil, // "/" + shift(20), // "(" + nil, // ")" + shift(21), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S48 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + reduce(11), // ")", reduce: Factor + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S49 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + shift(37), // "(" + nil, // ")" + shift(38), // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S50 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + shift(55), // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S51 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(10), // "+", reduce: Factor + reduce(10), // "-", reduce: Factor + reduce(10), // "*", reduce: Factor + reduce(10), // "/", reduce: Factor + nil, // "(" + reduce(10), // ")", reduce: Factor + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S52 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(10), // Ω, reduce: Factor + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + nil, // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S53 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + shift(56), // ")" + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S54 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + reduce(8), // "*", reduce: Term + nil, // "/" + nil, // "(" + reduce(8), // ")", reduce: Term + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S55 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + reduce(10), // "*", reduce: Factor + nil, // "/" + nil, // "(" + reduce(10), // ")", reduce: Factor + nil, // int64 + }, + cdActions: []cdAction{}, + }, + actionRow{ // S56 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "+" + nil, // "-" + nil, // "*" + nil, // "/" + nil, // "(" + reduce(10), // ")", reduce: Factor + nil, // int64 + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/calc/calc.grammar/calc/internal/parser/gototable.go b/example/calc/calc.grammar/calc/internal/parser/gototable.go new file mode 100644 index 00000000..5987b86c --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/parser/gototable.go @@ -0,0 +1,412 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 5 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + 3, // Π + 4, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + 12, // Π + 13, // Π + }, + gotoRow{ // S6 + -1, // Π + -1, // Π + 16, // Π + 17, // Π + 18, // Π + }, + gotoRow{ // S7 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S8 + -1, // Π + -1, // Π + -1, // Π + 22, // Π + 13, // Π + }, + gotoRow{ // S9 + -1, // Π + -1, // Π + -1, // Π + 23, // Π + 13, // Π + }, + gotoRow{ // S10 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 24, // Π + }, + gotoRow{ // S11 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 25, // Π + }, + gotoRow{ // S12 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S13 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S14 + -1, // Π + -1, // Π + 29, // Π + 17, // Π + 18, // Π + }, + gotoRow{ // S15 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S16 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S17 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S18 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S19 + -1, // Π + -1, // Π + -1, // Π + 35, // Π + 36, // Π + }, + gotoRow{ // S20 + -1, // Π + -1, // Π + 39, // Π + 17, // Π + 18, // Π + }, + gotoRow{ // S21 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S22 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S23 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S24 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S25 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S26 + -1, // Π + -1, // Π + 40, // Π + 17, // Π + 18, // Π + }, + gotoRow{ // S27 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S28 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 41, // Π + }, + gotoRow{ // S29 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S30 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S31 + -1, // Π + -1, // Π + -1, // Π + 43, // Π + 36, // Π + }, + gotoRow{ // S32 + -1, // Π + -1, // Π + -1, // Π + 44, // Π + 36, // Π + }, + gotoRow{ // S33 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 45, // Π + }, + gotoRow{ // S34 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 46, // Π + }, + gotoRow{ // S35 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S36 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S37 + -1, // Π + -1, // Π + 50, // Π + 17, // Π + 18, // Π + }, + gotoRow{ // S38 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S39 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S40 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S41 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S42 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S43 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S44 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S45 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S46 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S47 + -1, // Π + -1, // Π + 53, // Π + 17, // Π + 18, // Π + }, + gotoRow{ // S48 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S49 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 54, // Π + }, + gotoRow{ // S50 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S51 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S52 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S53 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S54 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S55 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S56 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/calc/calc.grammar/calc/internal/parser/parser.go b/example/calc/calc.grammar/calc/internal/parser/parser.go new file mode 100644 index 00000000..4b8a0a94 --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/parser/parser.go @@ -0,0 +1,353 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/iface" + parseError "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/errors" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/token" +) + +const ( + numProductions = 12 + numStates = 57 + numSymbols = 14 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = longest + p.isNonDeterministic = false + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/calc/calc.grammar/calc/internal/parser/productionstable.go b/example/calc/calc.grammar/calc/internal/parser/productionstable.go new file mode 100644 index 00000000..c64aca0e --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/parser/productionstable.go @@ -0,0 +1,175 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/token" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Calc : Π << >>`, + Id: "Calc", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Expr : Π Λ<+> Π << $0.(int64) + $2.(int64), nil >>`, + Id: "Expr", + NTType: 2, + Index: 2, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0].(int64) + X[2].(int64), nil + }, + }, + ProdTabEntry{ + String: `Expr : Π Λ<-> Π << $0.(int64) - $2.(int64), nil >>`, + Id: "Expr", + NTType: 2, + Index: 3, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0].(int64) - X[2].(int64), nil + }, + }, + ProdTabEntry{ + String: `Expr : Λ<-> Π << -$1.(int64), nil >>`, + Id: "Expr", + NTType: 2, + Index: 4, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return -X[1].(int64), nil + }, + }, + ProdTabEntry{ + String: `Expr : Π Λ<*> Π << $0.(int64) * $2.(int64), nil >>`, + Id: "Expr", + NTType: 2, + Index: 5, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0].(int64) * X[2].(int64), nil + }, + }, + ProdTabEntry{ + String: `Expr : Π Λ Π << $0.(int64) / $2.(int64), nil >>`, + Id: "Expr", + NTType: 2, + Index: 6, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0].(int64) / X[2].(int64), nil + }, + }, + ProdTabEntry{ + String: `Expr : Π << $0.(int64), nil >>`, + Id: "Expr", + NTType: 2, + Index: 7, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0].(int64), nil + }, + }, + ProdTabEntry{ + String: `Term : Π Λ<*> Π << $0.(int64) * $2.(int64), nil >>`, + Id: "Term", + NTType: 3, + Index: 8, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0].(int64) * X[2].(int64), nil + }, + }, + ProdTabEntry{ + String: `Term : Π << >>`, + Id: "Term", + NTType: 3, + Index: 9, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Factor : Λ<(> Π Λ<)> << $1, nil >>`, + Id: "Factor", + NTType: 4, + Index: 10, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[1], nil + }, + }, + ProdTabEntry{ + String: `Factor : int64 << util.IntValue($0.(*token.Token).Lit) >>`, + Id: "Factor", + NTType: 4, + Index: 11, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return util.IntValue(X[0].(*token.Token).Lit) + }, + }, +} diff --git a/example/calc/calc.grammar/calc/internal/token/token.go b/example/calc/calc.grammar/calc/internal/token/token.go new file mode 100644 index 00000000..263d8e59 --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/token/token.go @@ -0,0 +1,170 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +import ( + "fmt" + "strconv" + "unicode/utf8" +) + +type Token struct { + Type + Lit []byte + IgnoredPrefix []byte + Pos + ForeignAstNode interface{} + Foreign bool +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (p Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) +} + +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type + litMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +// CharLiteralValue returns the string value of the char literal. +func (t *Token) CharLiteralValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +// Float32Value returns the float32 value of the token or an error if the token literal does not +// denote a valid float32. +func (t *Token) Float32Value() (float32, error) { + if v, err := strconv.ParseFloat(string(t.Lit), 32); err != nil { + return 0, err + } else { + return float32(v), nil + } +} + +// Float64Value returns the float64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Float64Value() (float64, error) { + return strconv.ParseFloat(string(t.Lit), 64) +} + +// IDValue returns the string representation of an identifier token. +func (t *Token) IDValue() string { + return string(t.Lit) +} + +// Int32Value returns the int32 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int32Value() (int32, error) { + if v, err := strconv.ParseInt(string(t.Lit), 10, 64); err != nil { + return 0, err + } else { + return int32(v), nil + } +} + +// Int64Value returns the int64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int64Value() (int64, error) { + return strconv.ParseInt(string(t.Lit), 10, 64) +} + +// UTF8Rune decodes the UTF8 rune in the token literal. It returns utf8.RuneError if +// the token literal contains an invalid rune. +func (t *Token) UTF8Rune() (rune, error) { + r, _ := utf8.DecodeRune(t.Lit) + if r == utf8.RuneError { + err := fmt.Errorf("Invalid rune") + return r, err + } + return r, nil +} + +// StringValue returns the string value of the token literal. +func (t *Token) StringValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "Ω", + "Λ<+>", + "Λ<->", + "Λ<*>", + "Λ", + "Λ<(>", + "Λ<)>", + "int64", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "Ω": 1, + "Λ<+>": 2, + "Λ<->": 3, + "Λ<*>": 4, + "Λ": 5, + "Λ<(>": 6, + "Λ<)>": 7, + "int64": 8, + }, + + litMap: map[string]Type{ + "+": 2, + "-": 3, + "*": 4, + "/": 5, + "(": 6, + ")": 7, + }, +} diff --git a/example/calc/util/litconv.go b/example/calc/calc.grammar/calc/internal/util/litconv.go old mode 100755 new mode 100644 similarity index 100% rename from example/calc/util/litconv.go rename to example/calc/calc.grammar/calc/internal/util/litconv.go diff --git a/example/calc/calc.grammar/calc/internal/util/rune.go b/example/calc/calc.grammar/calc/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/calc/calc.grammar/calc/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/calc/calc.grammar/calc/main/calc.go b/example/calc/calc.grammar/calc/main/calc.go new file mode 100644 index 00000000..bdd46e6c --- /dev/null +++ b/example/calc/calc.grammar/calc/main/calc.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + calc "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *calc.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return calc.NewParser().ParseLongestPrefix(lex) + } else { + res, err = calc.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, calc.NewLexerString(Text))) + } + if File > "" { + l, e := calc.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, calc.NewLexerString(str))) + } +} diff --git a/example/calc/calc.grammar/calc/util.go b/example/calc/calc.grammar/calc/util.go new file mode 100644 index 00000000..0f0ee972 --- /dev/null +++ b/example/calc/calc.grammar/calc/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package calc + +import ( + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/calc/calc_test.go b/example/calc/calc_test.go index cc0288f4..f917e938 100644 --- a/example/calc/calc_test.go +++ b/example/calc/calc_test.go @@ -3,8 +3,7 @@ package calc import ( "testing" - "github.com/goccmack/gocc/example/calc/lexer" - "github.com/goccmack/gocc/example/calc/parser" + "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" ) type TI struct { @@ -19,9 +18,9 @@ var testData = []*TI{ } func Test1(t *testing.T) { - p := parser.NewParser() + p := calc.NewParser() for _, ts := range testData { - s := lexer.NewLexer([]byte(ts.src)) + s := calc.NewLexerString(ts.src) sum, err := p.Parse(s) if err != nil { t.Error(err) diff --git a/example/calc/lexer/lexer.go b/example/calc/lexer/lexer.go deleted file mode 100755 index 44fabe83..00000000 --- a/example/calc/lexer/lexer.go +++ /dev/null @@ -1,127 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package lexer - -import ( - "io/ioutil" - "unicode/utf8" - - "github.com/goccmack/gocc/example/calc/token" -) - -const ( - NoState = -1 - NumStates = 8 - NumSymbols = 11 -) - -type Lexer struct { - src []byte - pos int - line int - column int -} - -func NewLexer(src []byte) *Lexer { - lexer := &Lexer{ - src: src, - pos: 0, - line: 1, - column: 1, - } - return lexer -} - -func NewLexerFile(fpath string) (*Lexer, error) { - src, err := ioutil.ReadFile(fpath) - if err != nil { - return nil, err - } - return NewLexer(src), nil -} - -func (l *Lexer) Scan() (tok *token.Token) { - tok = new(token.Token) - if l.pos >= len(l.src) { - tok.Type = token.EOF - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column - return - } - start, startLine, startColumn, end := l.pos, l.line, l.column, 0 - tok.Type = token.INVALID - state, rune1, size := 0, rune(-1), 0 - for state != -1 { - if l.pos >= len(l.src) { - rune1 = -1 - } else { - rune1, size = utf8.DecodeRune(l.src[l.pos:]) - l.pos += size - } - - nextState := -1 - if rune1 != -1 { - nextState = TransTab[state](rune1) - } - state = nextState - - if state != -1 { - - switch rune1 { - case '\n': - l.line++ - l.column = 1 - case '\r': - l.column = 1 - case '\t': - l.column += 4 - default: - l.column++ - } - - switch { - case ActTab[state].Accept != -1: - tok.Type = ActTab[state].Accept - end = l.pos - case ActTab[state].Ignore != "": - start, startLine, startColumn = l.pos, l.line, l.column - state = 0 - if start >= len(l.src) { - tok.Type = token.EOF - } - - } - } else { - if tok.Type == token.INVALID { - end = l.pos - } - } - } - if end > start { - l.pos = end - tok.Lit = l.src[start:end] - } else { - tok.Lit = []byte{} - } - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn - - return -} - -func (l *Lexer) Reset() { - l.pos = 0 -} - -/* -Lexer symbols: -0: '+' -1: '*' -2: '(' -3: ')' -4: ' ' -5: '\t' -6: '\n' -7: '\r' -8: '1'-'9' -9: '0'-'9' -10: . -*/ diff --git a/example/calc/parser/actiontable.go b/example/calc/parser/actiontable.go deleted file mode 100755 index 190f9dd6..00000000 --- a/example/calc/parser/actiontable.go +++ /dev/null @@ -1,290 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - actionTable [numStates]actionRow - actionRow struct { - canRecover bool - actions [numSymbols]action - } -) - -var actionTab = actionTable{ - actionRow{ // S0 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // + - nil, // * - shift(5), // ( - nil, // ) - shift(6), // int64 - }, - }, - actionRow{ // S1 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - accept(true), // $ - nil, // + - nil, // * - nil, // ( - nil, // ) - nil, // int64 - }, - }, - actionRow{ // S2 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(1), // $, reduce: Calc - shift(7), // + - nil, // * - nil, // ( - nil, // ) - nil, // int64 - }, - }, - actionRow{ // S3 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(3), // $, reduce: Expr - reduce(3), // +, reduce: Expr - shift(8), // * - nil, // ( - nil, // ) - nil, // int64 - }, - }, - actionRow{ // S4 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(5), // $, reduce: Term - reduce(5), // +, reduce: Term - reduce(5), // *, reduce: Term - nil, // ( - nil, // ) - nil, // int64 - }, - }, - actionRow{ // S5 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // + - nil, // * - shift(12), // ( - nil, // ) - shift(13), // int64 - }, - }, - actionRow{ // S6 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(7), // $, reduce: Factor - reduce(7), // +, reduce: Factor - reduce(7), // *, reduce: Factor - nil, // ( - nil, // ) - nil, // int64 - }, - }, - actionRow{ // S7 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // + - nil, // * - shift(5), // ( - nil, // ) - shift(6), // int64 - }, - }, - actionRow{ // S8 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // + - nil, // * - shift(5), // ( - nil, // ) - shift(6), // int64 - }, - }, - actionRow{ // S9 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(16), // + - nil, // * - nil, // ( - shift(17), // ) - nil, // int64 - }, - }, - actionRow{ // S10 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(3), // +, reduce: Expr - shift(18), // * - nil, // ( - reduce(3), // ), reduce: Expr - nil, // int64 - }, - }, - actionRow{ // S11 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(5), // +, reduce: Term - reduce(5), // *, reduce: Term - nil, // ( - reduce(5), // ), reduce: Term - nil, // int64 - }, - }, - actionRow{ // S12 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // + - nil, // * - shift(12), // ( - nil, // ) - shift(13), // int64 - }, - }, - actionRow{ // S13 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(7), // +, reduce: Factor - reduce(7), // *, reduce: Factor - nil, // ( - reduce(7), // ), reduce: Factor - nil, // int64 - }, - }, - actionRow{ // S14 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(2), // $, reduce: Expr - reduce(2), // +, reduce: Expr - shift(8), // * - nil, // ( - nil, // ) - nil, // int64 - }, - }, - actionRow{ // S15 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(4), // $, reduce: Term - reduce(4), // +, reduce: Term - reduce(4), // *, reduce: Term - nil, // ( - nil, // ) - nil, // int64 - }, - }, - actionRow{ // S16 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // + - nil, // * - shift(12), // ( - nil, // ) - shift(13), // int64 - }, - }, - actionRow{ // S17 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(6), // $, reduce: Factor - reduce(6), // +, reduce: Factor - reduce(6), // *, reduce: Factor - nil, // ( - nil, // ) - nil, // int64 - }, - }, - actionRow{ // S18 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // + - nil, // * - shift(12), // ( - nil, // ) - shift(13), // int64 - }, - }, - actionRow{ // S19 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(16), // + - nil, // * - nil, // ( - shift(22), // ) - nil, // int64 - }, - }, - actionRow{ // S20 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(2), // +, reduce: Expr - shift(18), // * - nil, // ( - reduce(2), // ), reduce: Expr - nil, // int64 - }, - }, - actionRow{ // S21 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(4), // +, reduce: Term - reduce(4), // *, reduce: Term - nil, // ( - reduce(4), // ), reduce: Term - nil, // int64 - }, - }, - actionRow{ // S22 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(6), // +, reduce: Factor - reduce(6), // *, reduce: Factor - nil, // ( - reduce(6), // ), reduce: Factor - nil, // int64 - }, - }, -} diff --git a/example/calc/parser/gototable.go b/example/calc/parser/gototable.go deleted file mode 100755 index 8c87d854..00000000 --- a/example/calc/parser/gototable.go +++ /dev/null @@ -1,174 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -const numNTSymbols = 5 - -type ( - gotoTable [numStates]gotoRow - gotoRow [numNTSymbols]int -) - -var gotoTab = gotoTable{ - gotoRow{ // S0 - -1, // S' - 1, // Calc - 2, // Expr - 3, // Term - 4, // Factor - }, - gotoRow{ // S1 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S2 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S3 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S4 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S5 - -1, // S' - -1, // Calc - 9, // Expr - 10, // Term - 11, // Factor - }, - gotoRow{ // S6 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S7 - -1, // S' - -1, // Calc - -1, // Expr - 14, // Term - 4, // Factor - }, - gotoRow{ // S8 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - 15, // Factor - }, - gotoRow{ // S9 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S10 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S11 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S12 - -1, // S' - -1, // Calc - 19, // Expr - 10, // Term - 11, // Factor - }, - gotoRow{ // S13 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S14 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S15 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S16 - -1, // S' - -1, // Calc - -1, // Expr - 20, // Term - 11, // Factor - }, - gotoRow{ // S17 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S18 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - 21, // Factor - }, - gotoRow{ // S19 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S20 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S21 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, - gotoRow{ // S22 - -1, // S' - -1, // Calc - -1, // Expr - -1, // Term - -1, // Factor - }, -} diff --git a/example/calc/parser/parser.go b/example/calc/parser/parser.go deleted file mode 100755 index dd2ca3e4..00000000 --- a/example/calc/parser/parser.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "fmt" - "strings" - - parseError "github.com/goccmack/gocc/example/calc/errors" - "github.com/goccmack/gocc/example/calc/token" -) - -const ( - numProductions = 8 - numStates = 23 - numSymbols = 12 -) - -// Stack - -type stack struct { - state []int - attrib []Attrib -} - -const iNITIAL_STACK_SIZE = 100 - -func newStack() *stack { - return &stack{ - state: make([]int, 0, iNITIAL_STACK_SIZE), - attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), - } -} - -func (s *stack) reset() { - s.state = s.state[:0] - s.attrib = s.attrib[:0] -} - -func (s *stack) push(state int, a Attrib) { - s.state = append(s.state, state) - s.attrib = append(s.attrib, a) -} - -func (s *stack) top() int { - return s.state[len(s.state)-1] -} - -func (s *stack) peek(pos int) int { - return s.state[pos] -} - -func (s *stack) topIndex() int { - return len(s.state) - 1 -} - -func (s *stack) popN(items int) []Attrib { - lo, hi := len(s.state)-items, len(s.state) - - attrib := s.attrib[lo:hi] - - s.state = s.state[:lo] - s.attrib = s.attrib[:lo] - - return attrib -} - -func (s *stack) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "stack:\n") - for i, st := range s.state { - fmt.Fprintf(w, "\t%d: %d , ", i, st) - if s.attrib[i] == nil { - fmt.Fprintf(w, "nil") - } else { - switch attr := s.attrib[i].(type) { - case *token.Token: - fmt.Fprintf(w, "%s", attr.Lit) - default: - fmt.Fprintf(w, "%v", attr) - } - } - fmt.Fprintf(w, "\n") - } - return w.String() -} - -// Parser - -type Parser struct { - stack *stack - nextToken *token.Token - pos int -} - -type Scanner interface { - Scan() (tok *token.Token) -} - -func NewParser() *Parser { - p := &Parser{stack: newStack()} - p.Reset() - return p -} - -func (p *Parser) Reset() { - p.stack.reset() - p.stack.push(0, nil) -} - -func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { - errorAttrib = &parseError.Error{ - Err: err, - ErrorToken: p.nextToken, - ErrorSymbols: p.popNonRecoveryStates(), - ExpectedTokens: make([]string, 0, 8), - } - for t, action := range actionTab[p.stack.top()].actions { - if action != nil { - errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) - } - } - - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { - p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift - } else { - return - } - - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - for !recovered && p.nextToken.Type != token.EOF { - p.nextToken = scanner.Scan() - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - } - - return -} - -func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { - if rs, ok := p.firstRecoveryState(); ok { - errorSymbols := p.stack.popN(p.stack.topIndex() - rs) - removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) - for i, e := range errorSymbols { - removedAttribs[i] = e - } - } else { - removedAttribs = []parseError.ErrorSymbol{} - } - return -} - -// recoveryState points to the highest state on the stack, which can recover -func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { - recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover - for recoveryState > 0 && !canRecover { - recoveryState-- - canRecover = actionTab[p.stack.peek(recoveryState)].canRecover - } - return -} - -func (p *Parser) newError(err error) error { - e := &parseError.Error{ - Err: err, - StackTop: p.stack.top(), - ErrorToken: p.nextToken, - } - actRow := actionTab[p.stack.top()] - for i, t := range actRow.actions { - if t != nil { - e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) - } - } - return e -} - -func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { - p.Reset() - p.nextToken = scanner.Scan() - for acc := false; !acc; { - action := actionTab[p.stack.top()].actions[p.nextToken.Type] - if action == nil { - if recovered, errAttrib := p.Error(nil, scanner); !recovered { - p.nextToken = errAttrib.ErrorToken - return nil, p.newError(nil) - } - if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { - panic("Error recovery led to invalid action") - } - } - - switch act := action.(type) { - case accept: - res = p.stack.popN(1)[0] - acc = true - case shift: - p.stack.push(int(act), p.nextToken) - p.nextToken = scanner.Scan() - case reduce: - prod := productionsTable[int(act)] - attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) - if err != nil { - return nil, p.newError(err) - } else { - p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) - } - default: - panic("unknown action: " + action.String()) - } - } - return res, nil -} diff --git a/example/calc/parser/productionstable.go b/example/calc/parser/productionstable.go deleted file mode 100755 index cb7194ae..00000000 --- a/example/calc/parser/productionstable.go +++ /dev/null @@ -1,106 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "github.com/goccmack/gocc/example/calc/token" - "github.com/goccmack/gocc/example/calc/util" -) - -type ( - //TODO: change type and variable names to be consistent with other tables - ProdTab [numProductions]ProdTabEntry - ProdTabEntry struct { - String string - Id string - NTType int - Index int - NumSymbols int - ReduceFunc func([]Attrib) (Attrib, error) - } - Attrib interface { - } -) - -var productionsTable = ProdTab{ - ProdTabEntry{ - String: `S' : Calc << >>`, - Id: "S'", - NTType: 0, - Index: 0, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `Calc : Expr << >>`, - Id: "Calc", - NTType: 1, - Index: 1, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `Expr : Expr "+" Term << X[0].(int64) + X[2].(int64), nil >>`, - Id: "Expr", - NTType: 2, - Index: 2, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0].(int64) + X[2].(int64), nil - }, - }, - ProdTabEntry{ - String: `Expr : Term << >>`, - Id: "Expr", - NTType: 2, - Index: 3, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `Term : Term "*" Factor << X[0].(int64) * X[2].(int64), nil >>`, - Id: "Term", - NTType: 3, - Index: 4, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0].(int64) * X[2].(int64), nil - }, - }, - ProdTabEntry{ - String: `Term : Factor << >>`, - Id: "Term", - NTType: 3, - Index: 5, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `Factor : "(" Expr ")" << X[1], nil >>`, - Id: "Factor", - NTType: 4, - Index: 6, - NumSymbols: 3, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[1], nil - }, - }, - ProdTabEntry{ - String: `Factor : int64 << util.IntValue(X[0].(*token.Token).Lit) >>`, - Id: "Factor", - NTType: 4, - Index: 7, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return util.IntValue(X[0].(*token.Token).Lit) - }, - }, -} diff --git a/example/calc/token/token.go b/example/calc/token/token.go deleted file mode 100755 index 947cc338..00000000 --- a/example/calc/token/token.go +++ /dev/null @@ -1,80 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package token - -import ( - "fmt" -) - -type Token struct { - Type - Lit []byte - Pos -} - -type Type int - -const ( - INVALID Type = iota - EOF -) - -type Pos struct { - Offset int - Line int - Column int -} - -func (p Pos) String() string { - return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) -} - -type TokenMap struct { - typeMap []string - idMap map[string]Type -} - -func (m TokenMap) Id(tok Type) string { - if int(tok) < len(m.typeMap) { - return m.typeMap[tok] - } - return "unknown" -} - -func (m TokenMap) Type(tok string) Type { - if typ, exist := m.idMap[tok]; exist { - return typ - } - return INVALID -} - -func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) -} - -func (m TokenMap) StringType(typ Type) string { - return fmt.Sprintf("%s(%d)", m.Id(typ), typ) -} - -var TokMap = TokenMap{ - typeMap: []string{ - "INVALID", - "$", - "+", - "*", - "(", - ")", - "int64", - }, - - idMap: map[string]Type{ - "INVALID": 0, - "$": 1, - "+": 2, - "*": 3, - "(": 4, - ")": 5, - "int64": 6, - }, -} diff --git a/example/calc/util/rune.go b/example/calc/util/rune.go deleted file mode 100755 index bd8523a4..00000000 --- a/example/calc/util/rune.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package util - -import ( - "fmt" -) - -func RuneToString(r rune) string { - if r >= 0x20 && r < 0x7f { - return fmt.Sprintf("'%c'", r) - } - switch r { - case 0x07: - return "'\\a'" - case 0x08: - return "'\\b'" - case 0x0C: - return "'\\f'" - case 0x0A: - return "'\\n'" - case 0x0D: - return "'\\r'" - case 0x09: - return "'\\t'" - case 0x0b: - return "'\\v'" - case 0x5c: - return "'\\\\\\'" - case 0x27: - return "'\\''" - case 0x22: - return "'\\\"'" - } - if r < 0x10000 { - return fmt.Sprintf("\\u%04x", r) - } - return fmt.Sprintf("\\U%08x", r) -} diff --git a/example/ctx/Makefile b/example/ctx/Makefile new file mode 100644 index 00000000..03ef6b15 --- /dev/null +++ b/example/ctx/Makefile @@ -0,0 +1,4 @@ +regenerate: + gocc -a -v -o ctx0.grammar/ctx0 ctx.bnf >ctx0.log 2>&1 + gocc -a -v -o ctx1.grammar/ctx1 ctx1.bnf >ctx1.log 2>&1 + gocc -a -v -o ctx2.grammar/ctx2 -bugs=lexer_regdefs:ignore ctx.bnf >ctx2.log 2>&1 diff --git a/example/ctx/ast/ast.go b/example/ctx/ast/ast.go new file mode 100644 index 00000000..3236cfd4 --- /dev/null +++ b/example/ctx/ast/ast.go @@ -0,0 +1,29 @@ +package ast + +import ( + "fmt" +) + +type ( + StmtList []Stmt + Stmt string +) + +func NewStmtList(stmt string) (StmtList, error) { + return StmtList{Stmt(stmt)}, nil +} + +func AppendStmt(stmtList StmtList, stmt string) (StmtList, error) { + return append(stmtList, Stmt(stmt)), nil +} + +func NewStmt(stmt string) (Stmt, error) { + return Stmt(stmt), nil +} + +func CalcResult(result interface{}) (Stmt, error) { + res := result.(int64) + rstr := fmt.Sprintf("%d", res) + fmt.Printf("result: %s\n", rstr) + return Stmt(rstr), nil +} diff --git a/example/ctx/ctx.bnf b/example/ctx/ctx.bnf new file mode 100644 index 00000000..69c6073b --- /dev/null +++ b/example/ctx/ctx.bnf @@ -0,0 +1,45 @@ +/* Lexical elements */ + +_digit : '0'-'9' ; +_letter : 'a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) ; +_hex : _digit | ( 'a'-'f' ) | ('A' - 'F') ; +_idchar : _letter | _digit | '_'; + +_x0 : 'α' ; +_x1 : 'β' _digit { _digit } ; +_x : 'α' | ( 'β' _digit { _digit } ); +_test : _x { _x | 'γ' } ; + +//id : (_letter | '_') {_idchar} ; + +id: +/* + (_letter | '_') {_idchar} + ('a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) | '_') + { ('a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) | '_') | _digit } +*/ + _x { _x0 | _x1 | 'γ' } +; + +!whitespace : ' ' | '\t' | '\n' | '\r' ; + +/* Syntax elements */ + +<< + import ( + "github.com/maxcalandrelli/gocc/example/ctx/ast" + ) +>> + +StmtList : + Stmt << ast.NewStmtList($0s) >> + | StmtList Stmt << ast.AppendStmt($0.(ast.StmtList), $1s) >> +; + +Stmt : + id << ast.NewStmt($0e) >> + | + @ "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + << ast.CalcResult($1) >> + +; diff --git a/example/ctx/ctx0.grammar/ctx0/ctx.go b/example/ctx/ctx0.grammar/ctx0/ctx.go new file mode 100644 index 00000000..84d88a0f --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/ctx.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package ctx + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/lexer" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/parser" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/ctx/ctx0.grammar/ctx0/iface/ctx.go b/example/ctx/ctx0.grammar/ctx0/iface/ctx.go new file mode 100644 index 00000000..4f5c6d67 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/iface/ctx.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/errors/errors.go b/example/ctx/ctx0.grammar/ctx0/internal/errors/errors.go new file mode 100644 index 00000000..e3b59c2e --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/io/stream/internal/stream_impl.go b/example/ctx/ctx0.grammar/ctx0/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/io/stream/internal/stream_public.go b/example/ctx/ctx0.grammar/ctx0/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/io/stream/stream.go b/example/ctx/ctx0.grammar/ctx0/internal/io/stream/stream.go new file mode 100644 index 00000000..d3d5cbfb --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/lexer/acttab.go b/example/ctx/ctx0.grammar/ctx0/internal/lexer/acttab.go new file mode 100644 index 00000000..2199bccf --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/lexer/acttab.go @@ -0,0 +1,71 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + "fmt" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (a ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1, Ignore("!whitespace") + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S3, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S4, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S5, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S6, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S7, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S8, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S9, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S10, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S11, Accept("id") + Accept: 2, + Ignore: "", + }, +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/lexer/lexer.go b/example/ctx/ctx0.grammar/ctx0/internal/lexer/lexer.go new file mode 100644 index 00000000..73eafd3c --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/iface" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/token" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 12 + NumSymbols = 19 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/lexer/transitiontable.go b/example/ctx/ctx0.grammar/ctx0/internal/lexer/transitiontable.go new file mode 100644 index 00000000..5a483049 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/lexer/transitiontable.go @@ -0,0 +1,151 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 945: // [\u03b1,\u03b1] + return 2 + case r == 946: // [\u03b2,\u03b2] + return 3 + } + return NoState + }, + // S1 + func(r rune) int { + switch { + } + return NoState + }, + // S2 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S3 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 7 + } + return NoState + }, + // S4 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S5 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 8 + } + return NoState + }, + // S6 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S7 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 7 + case r == 945: // [\u03b1,\u03b1] + return 9 + case r == 946: // [\u03b2,\u03b2] + return 10 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S8 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 8 + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S9 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S10 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 11 + } + return NoState + }, + // S11 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 11 + case r == 945: // [\u03b1,\u03b1] + return 9 + case r == 946: // [\u03b2,\u03b2] + return 10 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, +} diff --git a/example/errorrecovery/parser/action.go b/example/ctx/ctx0.grammar/ctx0/internal/parser/action.go old mode 100755 new mode 100644 similarity index 100% rename from example/errorrecovery/parser/action.go rename to example/ctx/ctx0.grammar/ctx0/internal/parser/action.go diff --git a/example/ctx/ctx0.grammar/ctx0/internal/parser/actiontable.go b/example/ctx/ctx0.grammar/ctx0/internal/parser/actiontable.go new file mode 100644 index 00000000..10941d48 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/parser/actiontable.go @@ -0,0 +1,97 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(3), // id + shift(4), // μ + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + shift(3), // id + shift(4), // μ + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: StmtList + reduce(1), // id, reduce: StmtList + reduce(1), // μ, reduce: StmtList + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt + reduce(3), // id, reduce: Stmt + reduce(3), // μ, reduce: Stmt + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(4), // Ω, reduce: Stmt + reduce(4), // id, reduce: Stmt + reduce(4), // μ, reduce: Stmt + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: StmtList + reduce(2), // id, reduce: StmtList + reduce(2), // μ, reduce: StmtList + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + }, +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/parser/gototable.go b/example/ctx/ctx0.grammar/ctx0/internal/parser/gototable.go new file mode 100644 index 00000000..443ec029 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/parser/gototable.go @@ -0,0 +1,43 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 3 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + 5, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/parser/parser.go b/example/ctx/ctx0.grammar/ctx0/internal/parser/parser.go new file mode 100644 index 00000000..a99acc91 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/parser/parser.go @@ -0,0 +1,359 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/iface" + parseError "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/token" + + calc "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" +) + +const ( + numProductions = 5 + numStates = 6 + numSymbols = 7 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func cdFunc_calc_0(Stream TokenStream, Context interface{}) (interface{}, error, []byte) { + return calc.ParseWithDataPartial(Stream, Context) +} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = true + p.isNonDeterministic = true + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/ctx/ctx0.grammar/ctx0/internal/parser/productionstable.go b/example/ctx/ctx0.grammar/ctx0/internal/parser/productionstable.go new file mode 100644 index 00000000..62031511 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/parser/productionstable.go @@ -0,0 +1,109 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ast" +) + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/token" + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtList : Π << ast.NewStmtList($0s) >>`, + Id: "StmtList", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmtList(getString(X[0])) + }, + }, + ProdTabEntry{ + String: `StmtList : Π Π << ast.AppendStmt($0.(ast.StmtList), $1s) >>`, + Id: "StmtList", + NTType: 1, + Index: 2, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AppendStmt(X[0].(ast.StmtList), getString(X[1])) + }, + }, + ProdTabEntry{ + String: `Stmt : id << ast.NewStmt($0e) >>`, + Id: "Stmt", + NTType: 2, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmt(unescape(getString(X[0]))) + }, + }, + ProdTabEntry{ + String: `Stmt : μ << ast.CalcResult($1) >>`, + Id: "Stmt", + NTType: 2, + Index: 4, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.CalcResult(X[1]) + }, + }, +} diff --git a/example/sr/token/token.go b/example/ctx/ctx0.grammar/ctx0/internal/token/token.go old mode 100755 new mode 100644 similarity index 62% rename from example/sr/token/token.go rename to example/ctx/ctx0.grammar/ctx0/internal/token/token.go index e6c12d19..90eeb929 --- a/example/sr/token/token.go +++ b/example/ctx/ctx0.grammar/ctx0/internal/token/token.go @@ -8,8 +8,11 @@ import ( type Token struct { Type - Lit []byte + Lit []byte + IgnoredPrefix []byte Pos + ForeignAstNode interface{} + Foreign bool } type Type int @@ -29,9 +32,24 @@ func (p Pos) String() string { return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) } +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + type TokenMap struct { typeMap []string idMap map[string]Type + litMap map[string]Type } func (m TokenMap) Id(tok Type) string { @@ -49,8 +67,7 @@ func (m TokenMap) Type(tok string) Type { } func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) } func (m TokenMap) StringType(typ Type) string { @@ -60,19 +77,17 @@ func (m TokenMap) StringType(typ Type) string { var TokMap = TokenMap{ typeMap: []string{ "INVALID", - "$", - "if", + "Ω", "id", - "then", - "else", + "μ", }, idMap: map[string]Type{ - "INVALID": 0, - "$": 1, - "if": 2, - "id": 3, - "then": 4, - "else": 5, + "INVALID": 0, + "Ω": 1, + "id": 2, + "μ": 3, }, + + litMap: map[string]Type{}, } diff --git a/example/errorrecovery/util/litconv.go b/example/ctx/ctx0.grammar/ctx0/internal/util/litconv.go old mode 100755 new mode 100644 similarity index 100% rename from example/errorrecovery/util/litconv.go rename to example/ctx/ctx0.grammar/ctx0/internal/util/litconv.go diff --git a/example/ctx/ctx0.grammar/ctx0/internal/util/rune.go b/example/ctx/ctx0.grammar/ctx0/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/ctx/ctx0.grammar/ctx0/log/LR1_sets.txt b/example/ctx/ctx0.grammar/ctx0/log/LR1_sets.txt new file mode 100644 index 00000000..b1d9f119 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/log/LR1_sets.txt @@ -0,0 +1,72 @@ +S0{ + S' : •Π «Ω» + StmtList : •Π «Ω» + StmtList : •Π Π «Ω» + Stmt : •id «Ω» + Stmt : •μ «Ω» + StmtList : •Π «μ» + StmtList : •Π «id» + StmtList : •Π Π «μ» + StmtList : •Π Π «id» + Stmt : •id «μ» + Stmt : •μ «μ» + Stmt : •id «id» + Stmt : •μ «id» +} +Transitions: + Π -> 1 + Π -> 2 + id -> 3 + μ -> 4 + + +S1{ + S' : Π• «Ω» + StmtList : Π •Π «Ω» + StmtList : Π •Π «μ» + StmtList : Π •Π «id» + Stmt : •id «Ω» + Stmt : •μ «Ω» + Stmt : •id «μ» + Stmt : •μ «μ» + Stmt : •id «id» + Stmt : •μ «id» +} +Transitions: + id -> 3 + μ -> 4 + Π -> 5 + + +S2{ + StmtList : Π• «Ω» + StmtList : Π• «μ» + StmtList : Π• «id» +} +Transitions: + + +S3{ + Stmt : id• «Ω» + Stmt : id• «μ» + Stmt : id• «id» +} +Transitions: + + +S4{ + Stmt : μ• «Ω» + Stmt : μ• «μ» + Stmt : μ• «id» +} +Transitions: + + +S5{ + StmtList : Π Π• «Ω» + StmtList : Π Π• «μ» + StmtList : Π Π• «id» +} +Transitions: + + diff --git a/example/ctx/ctx0.grammar/ctx0/log/first.txt b/example/ctx/ctx0.grammar/ctx0/log/first.txt new file mode 100644 index 00000000..e7b13952 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/log/first.txt @@ -0,0 +1,12 @@ +Π: { + id + μ +} +Π: { + id + μ +} +Π: { + id + μ +} diff --git a/example/ctx/ctx0.grammar/ctx0/log/lexer_sets.txt b/example/ctx/ctx0.grammar/ctx0/log/lexer_sets.txt new file mode 100644 index 00000000..8043a58f --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/log/lexer_sets.txt @@ -0,0 +1,191 @@ +Item sets: +S0{ + !whitespace : ' ' | '\t' | '\n' | • '\r' + !whitespace : ' ' | '\t' | • '\n' | '\r' + !whitespace : ' ' | • '\t' | '\n' | '\r' + !whitespace : • ' ' | '\t' | '\n' | '\r' + _x : \u03b1 | (• \u03b2 _digit {_digit}) + _x : • \u03b1 | (\u03b2 _digit {_digit}) + id : • _x {_x0 | _x1 | \u03b3} +} +Transitions: + ['\t','\t'] -> S1 + ['\n','\n'] -> S1 + ['\r','\r'] -> S1 + [' ',' '] -> S1 + [\u03b1,\u03b1] -> S2 + [\u03b2,\u03b2] -> S3 +Action: nil +Symbols classes: {['\t','\t'], ['\n','\n'], ['\r','\r'], [' ',' '], [\u03b1,\u03b1], [\u03b2,\u03b2]} + +S1{ + !whitespace : (' ' | '\t' | '\n' | '\r') • +} +Transitions: +Action: Ignore("!whitespace") +Symbols classes: {} + +S2{ + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S3{ + _digit : • '0'-'9' + _x : \u03b1 | (\u03b2 • _digit {_digit}) + id : • _x {_x0 | _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S7 +Action: nil +Symbols classes: {['0','9']} + +S4{ + _x0 : \u03b1 • + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S5{ + _digit : • '0'-'9' + _x1 : \u03b2 • _digit {_digit} + id : _x {_x0 | • _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S8 +Action: nil +Symbols classes: {['0','9']} + +S6{ + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S7{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x : \u03b1 | (\u03b2 _digit {• _digit}) + _x : \u03b1 | (• \u03b2 _digit {_digit}) + _x : • \u03b1 | (\u03b2 _digit {_digit}) + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} + id : • _x {_x0 | _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S7 + [\u03b1,\u03b1] -> S9 + [\u03b2,\u03b2] -> S10 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {['0','9'], [\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S8{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _x0 : • \u03b1 + _x1 : \u03b2 _digit {_digit} • + _x1 : \u03b2 _digit {• _digit} + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S8 + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {['0','9'], [\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S9{ + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x0 : \u03b1 • + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S10{ + _digit : • '0'-'9' + _x : \u03b1 | (\u03b2 • _digit {_digit}) + _x1 : \u03b2 • _digit {_digit} + id : _x {_x0 | • _x1 | \u03b3} + id : • _x {_x0 | _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S11 +Action: nil +Symbols classes: {['0','9']} + +S11{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x : \u03b1 | (\u03b2 _digit {• _digit}) + _x : \u03b1 | (• \u03b2 _digit {_digit}) + _x : • \u03b1 | (\u03b2 _digit {_digit}) + _x0 : • \u03b1 + _x1 : \u03b2 _digit {_digit} • + _x1 : \u03b2 _digit {• _digit} + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} + id : • _x {_x0 | _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S11 + [\u03b1,\u03b1] -> S9 + [\u03b2,\u03b2] -> S10 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {['0','9'], [\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + diff --git a/example/ctx/ctx0.grammar/ctx0/log/terminals.txt b/example/ctx/ctx0.grammar/ctx0/log/terminals.txt new file mode 100644 index 00000000..bc6b9081 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/log/terminals.txt @@ -0,0 +1,4 @@ +ά +id +μ diff --git a/example/ctx/ctx0.grammar/ctx0/main/ctx.go b/example/ctx/ctx0.grammar/ctx0/main/ctx.go new file mode 100644 index 00000000..2eef3ba5 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/main/ctx.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + ctx "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *ctx.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return ctx.NewParser().ParseLongestPrefix(lex) + } else { + res, err = ctx.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, ctx.NewLexerString(Text))) + } + if File > "" { + l, e := ctx.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, ctx.NewLexerString(str))) + } +} diff --git a/example/ctx/ctx0.grammar/ctx0/util.go b/example/ctx/ctx0.grammar/ctx0/util.go new file mode 100644 index 00000000..4acdc237 --- /dev/null +++ b/example/ctx/ctx0.grammar/ctx0/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package ctx + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/ctx/ctx0.log b/example/ctx/ctx0.log new file mode 100644 index 00000000..205fe1de --- /dev/null +++ b/example/ctx/ctx0.log @@ -0,0 +1,12 @@ +gocc version 2.1.0001 +-a = true +-debug_lexer = false +-debug_parser = false +-h = false +-no_lexer = false +-o = /home/max/go/src/github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0 +-p = github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0 +-u = false +-v = true +-internal = internal +-bugs = lexer_dots:fix,lexer_regdefs:fix diff --git a/example/ctx/ctx1.bnf b/example/ctx/ctx1.bnf new file mode 100644 index 00000000..5ebf3116 --- /dev/null +++ b/example/ctx/ctx1.bnf @@ -0,0 +1,45 @@ +/* Lexical elements */ + +_digit : '0'-'9' ; +_letter : 'a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) ; +_hex : _digit | ( 'a'-'f' ) | ('A' - 'F') ; +_idchar : _letter | _digit | '_'; + +_x0 : 'α' ; +_x1 : 'β' _digit { _digit } ; +_x : 'α' | ( 'β' _digit { _digit } ); +_test : _x { _x | 'γ' } ; + +//id : (_letter | '_') {_idchar} ; + +id: +/* + (_letter | '_') {_idchar} + ('a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) | '_') + { ('a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) | '_') | _digit } +*/ + _x { _x0 | ( 'β' _digit { _digit } ) | 'γ' } +; + +!whitespace : ' ' | '\t' | '\n' | '\r' ; + +/* Syntax elements */ + +<< + import ( + "github.com/maxcalandrelli/gocc/example/ctx/ast" + ) +>> + +StmtList : + Stmt << ast.NewStmtList($0s) >> + | StmtList Stmt << ast.AppendStmt($0.(ast.StmtList), $1s) >> +; + +Stmt : + id << ast.NewStmt($0e) >> + | + @ "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + << ast.CalcResult($1) >> + +; diff --git a/example/ctx/ctx1.grammar/ctx1/ctx1.go b/example/ctx/ctx1.grammar/ctx1/ctx1.go new file mode 100644 index 00000000..3d02c074 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/ctx1.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package ctx1 + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/lexer" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/parser" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/ctx/ctx1.grammar/ctx1/iface/ctx1.go b/example/ctx/ctx1.grammar/ctx1/iface/ctx1.go new file mode 100644 index 00000000..a64bdf9f --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/iface/ctx1.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/errors/errors.go b/example/ctx/ctx1.grammar/ctx1/internal/errors/errors.go new file mode 100644 index 00000000..5e554168 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/io/stream/internal/stream_impl.go b/example/ctx/ctx1.grammar/ctx1/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/io/stream/internal/stream_public.go b/example/ctx/ctx1.grammar/ctx1/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/io/stream/stream.go b/example/ctx/ctx1.grammar/ctx1/internal/io/stream/stream.go new file mode 100644 index 00000000..59cfe77d --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/lexer/acttab.go b/example/ctx/ctx1.grammar/ctx1/internal/lexer/acttab.go new file mode 100644 index 00000000..1fd95a3b --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/lexer/acttab.go @@ -0,0 +1,71 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + "fmt" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (a ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1, Ignore("!whitespace") + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S3, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S4, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S5, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S6, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S7, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S8, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S9, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S10, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S11, Accept("id") + Accept: 2, + Ignore: "", + }, +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/lexer/lexer.go b/example/ctx/ctx1.grammar/ctx1/internal/lexer/lexer.go new file mode 100644 index 00000000..e8534677 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/iface" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/token" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 12 + NumSymbols = 20 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/lexer/transitiontable.go b/example/ctx/ctx1.grammar/ctx1/internal/lexer/transitiontable.go new file mode 100644 index 00000000..5a483049 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/lexer/transitiontable.go @@ -0,0 +1,151 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 945: // [\u03b1,\u03b1] + return 2 + case r == 946: // [\u03b2,\u03b2] + return 3 + } + return NoState + }, + // S1 + func(r rune) int { + switch { + } + return NoState + }, + // S2 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S3 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 7 + } + return NoState + }, + // S4 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S5 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 8 + } + return NoState + }, + // S6 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S7 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 7 + case r == 945: // [\u03b1,\u03b1] + return 9 + case r == 946: // [\u03b2,\u03b2] + return 10 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S8 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 8 + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S9 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S10 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 11 + } + return NoState + }, + // S11 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 11 + case r == 945: // [\u03b1,\u03b1] + return 9 + case r == 946: // [\u03b2,\u03b2] + return 10 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, +} diff --git a/example/nolexer/parser/action.go b/example/ctx/ctx1.grammar/ctx1/internal/parser/action.go old mode 100755 new mode 100644 similarity index 100% rename from example/nolexer/parser/action.go rename to example/ctx/ctx1.grammar/ctx1/internal/parser/action.go diff --git a/example/ctx/ctx1.grammar/ctx1/internal/parser/actiontable.go b/example/ctx/ctx1.grammar/ctx1/internal/parser/actiontable.go new file mode 100644 index 00000000..10941d48 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/parser/actiontable.go @@ -0,0 +1,97 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(3), // id + shift(4), // μ + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + shift(3), // id + shift(4), // μ + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: StmtList + reduce(1), // id, reduce: StmtList + reduce(1), // μ, reduce: StmtList + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt + reduce(3), // id, reduce: Stmt + reduce(3), // μ, reduce: Stmt + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(4), // Ω, reduce: Stmt + reduce(4), // id, reduce: Stmt + reduce(4), // μ, reduce: Stmt + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: StmtList + reduce(2), // id, reduce: StmtList + reduce(2), // μ, reduce: StmtList + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + }, +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/parser/gototable.go b/example/ctx/ctx1.grammar/ctx1/internal/parser/gototable.go new file mode 100644 index 00000000..443ec029 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/parser/gototable.go @@ -0,0 +1,43 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 3 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + 5, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/parser/parser.go b/example/ctx/ctx1.grammar/ctx1/internal/parser/parser.go new file mode 100644 index 00000000..5a677a80 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/parser/parser.go @@ -0,0 +1,359 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/iface" + parseError "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/token" + + calc "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" +) + +const ( + numProductions = 5 + numStates = 6 + numSymbols = 7 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func cdFunc_calc_0(Stream TokenStream, Context interface{}) (interface{}, error, []byte) { + return calc.ParseWithDataPartial(Stream, Context) +} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = true + p.isNonDeterministic = true + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/ctx/ctx1.grammar/ctx1/internal/parser/productionstable.go b/example/ctx/ctx1.grammar/ctx1/internal/parser/productionstable.go new file mode 100644 index 00000000..8c41014c --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/parser/productionstable.go @@ -0,0 +1,109 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ast" +) + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/token" + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtList : Π << ast.NewStmtList($0s) >>`, + Id: "StmtList", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmtList(getString(X[0])) + }, + }, + ProdTabEntry{ + String: `StmtList : Π Π << ast.AppendStmt($0.(ast.StmtList), $1s) >>`, + Id: "StmtList", + NTType: 1, + Index: 2, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AppendStmt(X[0].(ast.StmtList), getString(X[1])) + }, + }, + ProdTabEntry{ + String: `Stmt : id << ast.NewStmt($0e) >>`, + Id: "Stmt", + NTType: 2, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmt(unescape(getString(X[0]))) + }, + }, + ProdTabEntry{ + String: `Stmt : μ << ast.CalcResult($1) >>`, + Id: "Stmt", + NTType: 2, + Index: 4, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.CalcResult(X[1]) + }, + }, +} diff --git a/example/bools/token/token.go b/example/ctx/ctx1.grammar/ctx1/internal/token/token.go old mode 100755 new mode 100644 similarity index 62% rename from example/bools/token/token.go rename to example/ctx/ctx1.grammar/ctx1/internal/token/token.go index 548c16a3..90eeb929 --- a/example/bools/token/token.go +++ b/example/ctx/ctx1.grammar/ctx1/internal/token/token.go @@ -8,8 +8,11 @@ import ( type Token struct { Type - Lit []byte + Lit []byte + IgnoredPrefix []byte Pos + ForeignAstNode interface{} + Foreign bool } type Type int @@ -29,9 +32,24 @@ func (p Pos) String() string { return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) } +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + type TokenMap struct { typeMap []string idMap map[string]Type + litMap map[string]Type } func (m TokenMap) Id(tok Type) string { @@ -49,8 +67,7 @@ func (m TokenMap) Type(tok string) Type { } func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) } func (m TokenMap) StringType(typ Type) string { @@ -60,33 +77,17 @@ func (m TokenMap) StringType(typ Type) string { var TokMap = TokenMap{ typeMap: []string{ "INVALID", - "$", - "&", - "|", - "(", - ")", - "true", - "false", - "int_lit", - "<", - ">", - "string_lit", - "in", + "Ω", + "id", + "μ", }, idMap: map[string]Type{ - "INVALID": 0, - "$": 1, - "&": 2, - "|": 3, - "(": 4, - ")": 5, - "true": 6, - "false": 7, - "int_lit": 8, - "<": 9, - ">": 10, - "string_lit": 11, - "in": 12, + "INVALID": 0, + "Ω": 1, + "id": 2, + "μ": 3, }, + + litMap: map[string]Type{}, } diff --git a/example/mail/util/litconv.go b/example/ctx/ctx1.grammar/ctx1/internal/util/litconv.go old mode 100755 new mode 100644 similarity index 100% rename from example/mail/util/litconv.go rename to example/ctx/ctx1.grammar/ctx1/internal/util/litconv.go diff --git a/example/ctx/ctx1.grammar/ctx1/internal/util/rune.go b/example/ctx/ctx1.grammar/ctx1/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/ctx/ctx1.grammar/ctx1/log/LR1_sets.txt b/example/ctx/ctx1.grammar/ctx1/log/LR1_sets.txt new file mode 100644 index 00000000..b1d9f119 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/log/LR1_sets.txt @@ -0,0 +1,72 @@ +S0{ + S' : •Π «Ω» + StmtList : •Π «Ω» + StmtList : •Π Π «Ω» + Stmt : •id «Ω» + Stmt : •μ «Ω» + StmtList : •Π «μ» + StmtList : •Π «id» + StmtList : •Π Π «μ» + StmtList : •Π Π «id» + Stmt : •id «μ» + Stmt : •μ «μ» + Stmt : •id «id» + Stmt : •μ «id» +} +Transitions: + Π -> 1 + Π -> 2 + id -> 3 + μ -> 4 + + +S1{ + S' : Π• «Ω» + StmtList : Π •Π «Ω» + StmtList : Π •Π «μ» + StmtList : Π •Π «id» + Stmt : •id «Ω» + Stmt : •μ «Ω» + Stmt : •id «μ» + Stmt : •μ «μ» + Stmt : •id «id» + Stmt : •μ «id» +} +Transitions: + id -> 3 + μ -> 4 + Π -> 5 + + +S2{ + StmtList : Π• «Ω» + StmtList : Π• «μ» + StmtList : Π• «id» +} +Transitions: + + +S3{ + Stmt : id• «Ω» + Stmt : id• «μ» + Stmt : id• «id» +} +Transitions: + + +S4{ + Stmt : μ• «Ω» + Stmt : μ• «μ» + Stmt : μ• «id» +} +Transitions: + + +S5{ + StmtList : Π Π• «Ω» + StmtList : Π Π• «μ» + StmtList : Π Π• «id» +} +Transitions: + + diff --git a/example/ctx/ctx1.grammar/ctx1/log/first.txt b/example/ctx/ctx1.grammar/ctx1/log/first.txt new file mode 100644 index 00000000..e7b13952 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/log/first.txt @@ -0,0 +1,12 @@ +Π: { + id + μ +} +Π: { + id + μ +} +Π: { + id + μ +} diff --git a/example/ctx/ctx1.grammar/ctx1/log/lexer_sets.txt b/example/ctx/ctx1.grammar/ctx1/log/lexer_sets.txt new file mode 100644 index 00000000..05967fdb --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/log/lexer_sets.txt @@ -0,0 +1,180 @@ +Item sets: +S0{ + !whitespace : ' ' | '\t' | '\n' | • '\r' + !whitespace : ' ' | '\t' | • '\n' | '\r' + !whitespace : ' ' | • '\t' | '\n' | '\r' + !whitespace : • ' ' | '\t' | '\n' | '\r' + _x : \u03b1 | (• \u03b2 _digit {_digit}) + _x : • \u03b1 | (\u03b2 _digit {_digit}) + id : • _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + ['\t','\t'] -> S1 + ['\n','\n'] -> S1 + ['\r','\r'] -> S1 + [' ',' '] -> S1 + [\u03b1,\u03b1] -> S2 + [\u03b2,\u03b2] -> S3 +Action: nil +Symbols classes: {['\t','\t'], ['\n','\n'], ['\r','\r'], [' ',' '], [\u03b1,\u03b1], [\u03b2,\u03b2]} + +S1{ + !whitespace : (' ' | '\t' | '\n' | '\r') • +} +Transitions: +Action: Ignore("!whitespace") +Symbols classes: {} + +S2{ + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x0 : • \u03b1 + id : _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} • + id : _x {_x0 | (\u03b2 _digit {_digit}) | • \u03b3} + id : _x {_x0 | (• \u03b2 _digit {_digit}) | \u03b3} + id : _x {• _x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S3{ + _digit : • '0'-'9' + _x : \u03b1 | (\u03b2 • _digit {_digit}) + id : • _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + ['0','9'] -> S7 +Action: nil +Symbols classes: {['0','9']} + +S4{ + _x0 : \u03b1 • + _x0 : • \u03b1 + id : _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} • + id : _x {_x0 | (\u03b2 _digit {_digit}) | • \u03b3} + id : _x {_x0 | (• \u03b2 _digit {_digit}) | \u03b3} + id : _x {• _x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S5{ + _digit : • '0'-'9' + id : _x {_x0 | (\u03b2 • _digit {_digit}) | \u03b3} +} +Transitions: + ['0','9'] -> S8 +Action: nil +Symbols classes: {['0','9']} + +S6{ + _x0 : • \u03b1 + id : _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} • + id : _x {_x0 | (\u03b2 _digit {_digit}) | • \u03b3} + id : _x {_x0 | (• \u03b2 _digit {_digit}) | \u03b3} + id : _x {• _x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S7{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x : \u03b1 | (\u03b2 _digit {• _digit}) + _x : \u03b1 | (• \u03b2 _digit {_digit}) + _x : • \u03b1 | (\u03b2 _digit {_digit}) + _x0 : • \u03b1 + id : _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} • + id : _x {_x0 | (\u03b2 _digit {_digit}) | • \u03b3} + id : _x {_x0 | (• \u03b2 _digit {_digit}) | \u03b3} + id : _x {• _x0 | (\u03b2 _digit {_digit}) | \u03b3} + id : • _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + ['0','9'] -> S7 + [\u03b1,\u03b1] -> S9 + [\u03b2,\u03b2] -> S10 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {['0','9'], [\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S8{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _x0 : • \u03b1 + id : _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} • + id : _x {_x0 | (\u03b2 _digit {_digit}) | • \u03b3} + id : _x {_x0 | (\u03b2 _digit {• _digit}) | \u03b3} + id : _x {_x0 | (• \u03b2 _digit {_digit}) | \u03b3} + id : _x {• _x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + ['0','9'] -> S8 + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {['0','9'], [\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S9{ + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x0 : \u03b1 • + _x0 : • \u03b1 + id : _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} • + id : _x {_x0 | (\u03b2 _digit {_digit}) | • \u03b3} + id : _x {_x0 | (• \u03b2 _digit {_digit}) | \u03b3} + id : _x {• _x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S10{ + _digit : • '0'-'9' + _x : \u03b1 | (\u03b2 • _digit {_digit}) + id : _x {_x0 | (\u03b2 • _digit {_digit}) | \u03b3} + id : • _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + ['0','9'] -> S11 +Action: nil +Symbols classes: {['0','9']} + +S11{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x : \u03b1 | (\u03b2 _digit {• _digit}) + _x : \u03b1 | (• \u03b2 _digit {_digit}) + _x : • \u03b1 | (\u03b2 _digit {_digit}) + _x0 : • \u03b1 + id : _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} • + id : _x {_x0 | (\u03b2 _digit {_digit}) | • \u03b3} + id : _x {_x0 | (\u03b2 _digit {• _digit}) | \u03b3} + id : _x {_x0 | (• \u03b2 _digit {_digit}) | \u03b3} + id : _x {• _x0 | (\u03b2 _digit {_digit}) | \u03b3} + id : • _x {_x0 | (\u03b2 _digit {_digit}) | \u03b3} +} +Transitions: + ['0','9'] -> S11 + [\u03b1,\u03b1] -> S9 + [\u03b2,\u03b2] -> S10 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {['0','9'], [\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + diff --git a/example/ctx/ctx1.grammar/ctx1/log/terminals.txt b/example/ctx/ctx1.grammar/ctx1/log/terminals.txt new file mode 100644 index 00000000..bc6b9081 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/log/terminals.txt @@ -0,0 +1,4 @@ +ά +id +μ diff --git a/example/ctx/ctx1.grammar/ctx1/main/ctx1.go b/example/ctx/ctx1.grammar/ctx1/main/ctx1.go new file mode 100644 index 00000000..82792675 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/main/ctx1.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + ctx1 "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *ctx1.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return ctx1.NewParser().ParseLongestPrefix(lex) + } else { + res, err = ctx1.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, ctx1.NewLexerString(Text))) + } + if File > "" { + l, e := ctx1.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, ctx1.NewLexerString(str))) + } +} diff --git a/example/ctx/ctx1.grammar/ctx1/util.go b/example/ctx/ctx1.grammar/ctx1/util.go new file mode 100644 index 00000000..638246b9 --- /dev/null +++ b/example/ctx/ctx1.grammar/ctx1/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package ctx1 + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/ctx/ctx1.log b/example/ctx/ctx1.log new file mode 100644 index 00000000..4e4170a5 --- /dev/null +++ b/example/ctx/ctx1.log @@ -0,0 +1,12 @@ +gocc version 2.1.0001 +-a = true +-debug_lexer = false +-debug_parser = false +-h = false +-no_lexer = false +-o = /home/max/go/src/github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1 +-p = github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1 +-u = false +-v = true +-internal = internal +-bugs = lexer_dots:fix,lexer_regdefs:fix diff --git a/example/ctx/ctx2.grammar/ctx2/ctx.go b/example/ctx/ctx2.grammar/ctx2/ctx.go new file mode 100644 index 00000000..d7625c2a --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/ctx.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package ctx + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/lexer" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/parser" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/ctx/ctx2.grammar/ctx2/iface/ctx.go b/example/ctx/ctx2.grammar/ctx2/iface/ctx.go new file mode 100644 index 00000000..c8f03732 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/iface/ctx.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/errors/errors.go b/example/ctx/ctx2.grammar/ctx2/internal/errors/errors.go new file mode 100644 index 00000000..412bfe65 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/io/stream/internal/stream_impl.go b/example/ctx/ctx2.grammar/ctx2/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/io/stream/internal/stream_public.go b/example/ctx/ctx2.grammar/ctx2/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/io/stream/stream.go b/example/ctx/ctx2.grammar/ctx2/internal/io/stream/stream.go new file mode 100644 index 00000000..b6009b32 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/calc/lexer/acttab.go b/example/ctx/ctx2.grammar/ctx2/internal/lexer/acttab.go old mode 100755 new mode 100644 similarity index 53% rename from example/calc/lexer/acttab.go rename to example/ctx/ctx2.grammar/ctx2/internal/lexer/acttab.go index 1068fb15..826e9f95 --- a/example/calc/lexer/acttab.go +++ b/example/ctx/ctx2.grammar/ctx2/internal/lexer/acttab.go @@ -5,7 +5,7 @@ package lexer import ( "fmt" - "github.com/goccmack/gocc/example/calc/token" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/token" ) type ActionTable [NumStates]ActionRow @@ -20,36 +20,40 @@ func (a ActionRow) String() string { } var ActTab = ActionTable{ - ActionRow{ // S0 + ActionRow{ // S0, Accept: 0, Ignore: "", }, - ActionRow{ // S1 + ActionRow{ // S1, Ignore("!whitespace") Accept: -1, Ignore: "!whitespace", }, - ActionRow{ // S2 - Accept: 4, + ActionRow{ // S2, Accept("id") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S3, + Accept: 0, Ignore: "", }, - ActionRow{ // S3 - Accept: 5, + ActionRow{ // S4, Accept("id") + Accept: 2, Ignore: "", }, - ActionRow{ // S4 - Accept: 3, + ActionRow{ // S5, + Accept: 0, Ignore: "", }, - ActionRow{ // S5 + ActionRow{ // S6, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S6 - Accept: 6, + ActionRow{ // S7, Accept("id") + Accept: 2, Ignore: "", }, - ActionRow{ // S7 - Accept: 6, + ActionRow{ // S8, Accept("id") + Accept: 2, Ignore: "", }, } diff --git a/example/ctx/ctx2.grammar/ctx2/internal/lexer/lexer.go b/example/ctx/ctx2.grammar/ctx2/internal/lexer/lexer.go new file mode 100644 index 00000000..f5094232 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/iface" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/token" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 9 + NumSymbols = 19 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/lexer/transitiontable.go b/example/ctx/ctx2.grammar/ctx2/internal/lexer/transitiontable.go new file mode 100644 index 00000000..ed1b1d58 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/lexer/transitiontable.go @@ -0,0 +1,115 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 945: // [\u03b1,\u03b1] + return 2 + case r == 946: // [\u03b2,\u03b2] + return 3 + } + return NoState + }, + // S1 + func(r rune) int { + switch { + } + return NoState + }, + // S2 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S3 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 7 + } + return NoState + }, + // S4 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S5 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 8 + } + return NoState + }, + // S6 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S7 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 7 + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 946: // [\u03b2,\u03b2] + return 5 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, + // S8 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 8 + case r == 945: // [\u03b1,\u03b1] + return 4 + case r == 947: // [\u03b3,\u03b3] + return 6 + } + return NoState + }, +} diff --git a/example/rr/parser/action.go b/example/ctx/ctx2.grammar/ctx2/internal/parser/action.go old mode 100755 new mode 100644 similarity index 100% rename from example/rr/parser/action.go rename to example/ctx/ctx2.grammar/ctx2/internal/parser/action.go diff --git a/example/ctx/ctx2.grammar/ctx2/internal/parser/actiontable.go b/example/ctx/ctx2.grammar/ctx2/internal/parser/actiontable.go new file mode 100644 index 00000000..10941d48 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/parser/actiontable.go @@ -0,0 +1,97 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(3), // id + shift(4), // μ + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + shift(3), // id + shift(4), // μ + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: StmtList + reduce(1), // id, reduce: StmtList + reduce(1), // μ, reduce: StmtList + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt + reduce(3), // id, reduce: Stmt + reduce(3), // μ, reduce: Stmt + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(4), // Ω, reduce: Stmt + reduce(4), // id, reduce: Stmt + reduce(4), // μ, reduce: Stmt + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: StmtList + reduce(2), // id, reduce: StmtList + reduce(2), // μ, reduce: StmtList + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 3, tokenScanner: cdFunc_calc_0}, + }, + }, + }, +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/parser/gototable.go b/example/ctx/ctx2.grammar/ctx2/internal/parser/gototable.go new file mode 100644 index 00000000..443ec029 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/parser/gototable.go @@ -0,0 +1,43 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 3 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + 5, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/parser/parser.go b/example/ctx/ctx2.grammar/ctx2/internal/parser/parser.go new file mode 100644 index 00000000..5350cd74 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/parser/parser.go @@ -0,0 +1,359 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/iface" + parseError "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/errors" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/token" + + calc "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" +) + +const ( + numProductions = 5 + numStates = 6 + numSymbols = 7 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func cdFunc_calc_0(Stream TokenStream, Context interface{}) (interface{}, error, []byte) { + return calc.ParseWithDataPartial(Stream, Context) +} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = true + p.isNonDeterministic = true + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/parser/productionstable.go b/example/ctx/ctx2.grammar/ctx2/internal/parser/productionstable.go new file mode 100644 index 00000000..abd67e54 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/parser/productionstable.go @@ -0,0 +1,109 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ast" +) + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/token" + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtList : Π << ast.NewStmtList($0s) >>`, + Id: "StmtList", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmtList(getString(X[0])) + }, + }, + ProdTabEntry{ + String: `StmtList : Π Π << ast.AppendStmt($0.(ast.StmtList), $1s) >>`, + Id: "StmtList", + NTType: 1, + Index: 2, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AppendStmt(X[0].(ast.StmtList), getString(X[1])) + }, + }, + ProdTabEntry{ + String: `Stmt : id << ast.NewStmt($0e) >>`, + Id: "Stmt", + NTType: 2, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmt(unescape(getString(X[0]))) + }, + }, + ProdTabEntry{ + String: `Stmt : μ << ast.CalcResult($1) >>`, + Id: "Stmt", + NTType: 2, + Index: 4, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.CalcResult(X[1]) + }, + }, +} diff --git a/example/ctx/ctx2.grammar/ctx2/internal/token/token.go b/example/ctx/ctx2.grammar/ctx2/internal/token/token.go new file mode 100644 index 00000000..90eeb929 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/token/token.go @@ -0,0 +1,93 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +import ( + "fmt" +) + +type Token struct { + Type + Lit []byte + IgnoredPrefix []byte + Pos + ForeignAstNode interface{} + Foreign bool +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (p Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) +} + +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type + litMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "Ω", + "id", + "μ", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "Ω": 1, + "id": 2, + "μ": 3, + }, + + litMap: map[string]Type{}, +} diff --git a/example/nolexer/util/litconv.go b/example/ctx/ctx2.grammar/ctx2/internal/util/litconv.go old mode 100755 new mode 100644 similarity index 100% rename from example/nolexer/util/litconv.go rename to example/ctx/ctx2.grammar/ctx2/internal/util/litconv.go diff --git a/example/ctx/ctx2.grammar/ctx2/internal/util/rune.go b/example/ctx/ctx2.grammar/ctx2/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/ctx/ctx2.grammar/ctx2/log/LR1_sets.txt b/example/ctx/ctx2.grammar/ctx2/log/LR1_sets.txt new file mode 100644 index 00000000..b1d9f119 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/log/LR1_sets.txt @@ -0,0 +1,72 @@ +S0{ + S' : •Π «Ω» + StmtList : •Π «Ω» + StmtList : •Π Π «Ω» + Stmt : •id «Ω» + Stmt : •μ «Ω» + StmtList : •Π «μ» + StmtList : •Π «id» + StmtList : •Π Π «μ» + StmtList : •Π Π «id» + Stmt : •id «μ» + Stmt : •μ «μ» + Stmt : •id «id» + Stmt : •μ «id» +} +Transitions: + Π -> 1 + Π -> 2 + id -> 3 + μ -> 4 + + +S1{ + S' : Π• «Ω» + StmtList : Π •Π «Ω» + StmtList : Π •Π «μ» + StmtList : Π •Π «id» + Stmt : •id «Ω» + Stmt : •μ «Ω» + Stmt : •id «μ» + Stmt : •μ «μ» + Stmt : •id «id» + Stmt : •μ «id» +} +Transitions: + id -> 3 + μ -> 4 + Π -> 5 + + +S2{ + StmtList : Π• «Ω» + StmtList : Π• «μ» + StmtList : Π• «id» +} +Transitions: + + +S3{ + Stmt : id• «Ω» + Stmt : id• «μ» + Stmt : id• «id» +} +Transitions: + + +S4{ + Stmt : μ• «Ω» + Stmt : μ• «μ» + Stmt : μ• «id» +} +Transitions: + + +S5{ + StmtList : Π Π• «Ω» + StmtList : Π Π• «μ» + StmtList : Π Π• «id» +} +Transitions: + + diff --git a/example/ctx/ctx2.grammar/ctx2/log/first.txt b/example/ctx/ctx2.grammar/ctx2/log/first.txt new file mode 100644 index 00000000..e7b13952 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/log/first.txt @@ -0,0 +1,12 @@ +Π: { + id + μ +} +Π: { + id + μ +} +Π: { + id + μ +} diff --git a/example/ctx/ctx2.grammar/ctx2/log/lexer_sets.txt b/example/ctx/ctx2.grammar/ctx2/log/lexer_sets.txt new file mode 100644 index 00000000..47526066 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/log/lexer_sets.txt @@ -0,0 +1,133 @@ +Item sets: +S0{ + !whitespace : ' ' | '\t' | '\n' | • '\r' + !whitespace : ' ' | '\t' | • '\n' | '\r' + !whitespace : ' ' | • '\t' | '\n' | '\r' + !whitespace : • ' ' | '\t' | '\n' | '\r' + _x : \u03b1 | (• \u03b2 _digit {_digit}) + _x : • \u03b1 | (\u03b2 _digit {_digit}) + id : • _x {_x0 | _x1 | \u03b3} +} +Transitions: + ['\t','\t'] -> S1 + ['\n','\n'] -> S1 + ['\r','\r'] -> S1 + [' ',' '] -> S1 + [\u03b1,\u03b1] -> S2 + [\u03b2,\u03b2] -> S3 +Action: nil +Symbols classes: {['\t','\t'], ['\n','\n'], ['\r','\r'], [' ',' '], [\u03b1,\u03b1], [\u03b2,\u03b2]} + +S1{ + !whitespace : (' ' | '\t' | '\n' | '\r') • +} +Transitions: +Action: Ignore("!whitespace") +Symbols classes: {} + +S2{ + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S3{ + _digit : • '0'-'9' + _x : \u03b1 | (\u03b2 • _digit {_digit}) + id : • _x {_x0 | _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S7 +Action: nil +Symbols classes: {['0','9']} + +S4{ + _x0 : \u03b1 • + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S5{ + _digit : • '0'-'9' + _x1 : \u03b2 • _digit {_digit} + id : _x {_x0 | • _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S8 +Action: nil +Symbols classes: {['0','9']} + +S6{ + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {[\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S7{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _x : (\u03b1 | (\u03b2 _digit {_digit})) • + _x : \u03b1 | (\u03b2 _digit {• _digit}) + _x0 : • \u03b1 + _x1 : • \u03b2 _digit {_digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} + id : • _x {_x0 | _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S7 + [\u03b1,\u03b1] -> S4 + [\u03b2,\u03b2] -> S5 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {['0','9'], [\u03b1,\u03b1], [\u03b2,\u03b2], [\u03b3,\u03b3]} + +S8{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _x0 : • \u03b1 + _x1 : \u03b2 _digit {_digit} • + _x1 : \u03b2 _digit {• _digit} + id : _x {_x0 | _x1 | \u03b3} • + id : _x {_x0 | _x1 | • \u03b3} + id : _x {_x0 | • _x1 | \u03b3} + id : _x {• _x0 | _x1 | \u03b3} +} +Transitions: + ['0','9'] -> S8 + [\u03b1,\u03b1] -> S4 + [\u03b3,\u03b3] -> S6 +Action: Accept("id") +Symbols classes: {['0','9'], [\u03b1,\u03b1], [\u03b3,\u03b3]} + diff --git a/example/ctx/ctx2.grammar/ctx2/log/terminals.txt b/example/ctx/ctx2.grammar/ctx2/log/terminals.txt new file mode 100644 index 00000000..bc6b9081 --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/log/terminals.txt @@ -0,0 +1,4 @@ +ά +id +μ diff --git a/example/ctx/ctx2.grammar/ctx2/main/ctx.go b/example/ctx/ctx2.grammar/ctx2/main/ctx.go new file mode 100644 index 00000000..a653f83c --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/main/ctx.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + ctx "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *ctx.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return ctx.NewParser().ParseLongestPrefix(lex) + } else { + res, err = ctx.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, ctx.NewLexerString(Text))) + } + if File > "" { + l, e := ctx.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, ctx.NewLexerString(str))) + } +} diff --git a/example/ctx/ctx2.grammar/ctx2/util.go b/example/ctx/ctx2.grammar/ctx2/util.go new file mode 100644 index 00000000..5b0fd71e --- /dev/null +++ b/example/ctx/ctx2.grammar/ctx2/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package ctx + +import ( + "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/ctx/ctx2.log b/example/ctx/ctx2.log new file mode 100644 index 00000000..268a96ff --- /dev/null +++ b/example/ctx/ctx2.log @@ -0,0 +1,12 @@ +gocc version 2.1.0001 +-a = true +-debug_lexer = false +-debug_parser = false +-h = false +-no_lexer = false +-o = /home/max/go/src/github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2 +-p = github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2 +-u = false +-v = true +-internal = internal +-bugs = lexer_dots:fix,lexer_regdefs:ignore diff --git a/example/ctx/ctx_test.go b/example/ctx/ctx_test.go new file mode 100644 index 00000000..90eb9c39 --- /dev/null +++ b/example/ctx/ctx_test.go @@ -0,0 +1,49 @@ +package ctx + +import ( + "fmt" + "testing" + + "github.com/maxcalandrelli/gocc/example/ctx/ast" + ctx0 "github.com/maxcalandrelli/gocc/example/ctx/ctx0.grammar/ctx0" + ctx1 "github.com/maxcalandrelli/gocc/example/ctx/ctx1.grammar/ctx1" + ctx2 "github.com/maxcalandrelli/gocc/example/ctx/ctx2.grammar/ctx2" +) + +func TestPass(t *testing.T) { + //sml, err := test("\\u0022AA\\u0022 other a b c calc 12 * 6 + 4 \\u03b3k\\u03b5 d e \\u03b3_\\u03b5 \\u03b3\\u03b5 f") + sml, err := test("β1α αβ1α 6 + 4 β11β1β11 αβ33 αβ0β9 ") + for _ix := 0; _ix < len(sml); _ix++ { + if err[_ix] != nil { + t.Log(err[_ix].Error()) + t.Fail() + } + fmt.Printf("output #%d: %s\n", _ix+1, sml[_ix]) + } +} + +func TestFail(t *testing.T) { + _, err := test("αβ1α β0 22 β9 α a α") + for _ix := 0; _ix < len(err); _ix++ { + if err[_ix] == nil { + t.Fatal("expected parse error") + } else { + fmt.Printf("Parsing failed as expected: %v\n", err[_ix]) + } + } +} + +func test1(src string, astree []ast.StmtList, errors []error, p func(string) (interface{}, error)) ([]ast.StmtList, []error) { + at := ast.StmtList(nil) + a, err := p(src) + at, _ = a.(ast.StmtList) + return append(astree, at), append(errors, err) +} + +func test(src string) (astree []ast.StmtList, err []error) { + fmt.Printf("input: %s\n", src) + astree, err = test1(src, astree, err, ctx0.ParseText) + astree, err = test1(src, astree, err, ctx1.ParseText) + astree, err = test1(src, astree, err, ctx2.ParseText) + return +} diff --git a/example/ctx/doc.go b/example/ctx/doc.go new file mode 100644 index 00000000..d061274b --- /dev/null +++ b/example/ctx/doc.go @@ -0,0 +1 @@ +package ctx diff --git a/example/errorrecovery/ast/ast.go b/example/errorrecovery/ast/ast.go index df23f297..49fc98e9 100644 --- a/example/errorrecovery/ast/ast.go +++ b/example/errorrecovery/ast/ast.go @@ -1,7 +1,7 @@ package ast import ( - "github.com/goccmack/gocc/example/errorrecovery/token" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/iface" ) type ( @@ -18,5 +18,5 @@ func AppendStmt(stmtList, stmt interface{}) (StmtList, error) { } func NewStmt(stmtList interface{}) (Stmt, error) { - return Stmt(stmtList.(*token.Token).Lit), nil + return Stmt(stmtList.(*iface.Token).Lit), nil } diff --git a/example/errorrecovery/doc.go b/example/errorrecovery/doc.go index d42ebcab..861c091d 100644 --- a/example/errorrecovery/doc.go +++ b/example/errorrecovery/doc.go @@ -1 +1 @@ -package astx +package er diff --git a/example/errorrecovery/er.bnf b/example/errorrecovery/er.bnf index 47ec84b6..f3aea36c 100644 --- a/example/errorrecovery/er.bnf +++ b/example/errorrecovery/er.bnf @@ -12,7 +12,7 @@ id : (_letter | '_') {_idchar} ; /* Syntax elements */ -<< import "github.com/goccmack/gocc/example/errorrecovery/ast" >> +<< import "github.com/maxcalandrelli/gocc/example/errorrecovery/ast" >> StmtList : Stmt << ast.NewStmtList($0) >> diff --git a/example/errorrecovery/er.grammar/er/er.go b/example/errorrecovery/er.grammar/er/er.go new file mode 100644 index 00000000..ed2c0165 --- /dev/null +++ b/example/errorrecovery/er.grammar/er/er.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package er + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/errors" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/lexer" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/parser" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/errorrecovery/er.grammar/er/iface/er.go b/example/errorrecovery/er.grammar/er/iface/er.go new file mode 100644 index 00000000..a7631a52 --- /dev/null +++ b/example/errorrecovery/er.grammar/er/iface/er.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/errors" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/errorrecovery/er.grammar/er/internal/errors/errors.go b/example/errorrecovery/er.grammar/er/internal/errors/errors.go new file mode 100644 index 00000000..4f697864 --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/errorrecovery/er.grammar/er/internal/io/stream/internal/stream_impl.go b/example/errorrecovery/er.grammar/er/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/errorrecovery/er.grammar/er/internal/io/stream/internal/stream_public.go b/example/errorrecovery/er.grammar/er/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/errorrecovery/er.grammar/er/internal/io/stream/stream.go b/example/errorrecovery/er.grammar/er/internal/io/stream/stream.go new file mode 100644 index 00000000..cd9c46eb --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/errorrecovery/lexer/acttab.go b/example/errorrecovery/er.grammar/er/internal/lexer/acttab.go old mode 100755 new mode 100644 similarity index 63% rename from example/errorrecovery/lexer/acttab.go rename to example/errorrecovery/er.grammar/er/internal/lexer/acttab.go index 833036b1..482f67a3 --- a/example/errorrecovery/lexer/acttab.go +++ b/example/errorrecovery/er.grammar/er/internal/lexer/acttab.go @@ -5,7 +5,7 @@ package lexer import ( "fmt" - "github.com/goccmack/gocc/example/errorrecovery/token" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/token" ) type ActionTable [NumStates]ActionRow @@ -20,31 +20,31 @@ func (a ActionRow) String() string { } var ActTab = ActionTable{ - ActionRow{ // S0 + ActionRow{ // S0, Accept: 0, Ignore: "", }, - ActionRow{ // S1 + ActionRow{ // S1, Ignore("!whitespace") Accept: -1, Ignore: "!whitespace", }, - ActionRow{ // S2 + ActionRow{ // S2, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S3 + ActionRow{ // S3, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S4 + ActionRow{ // S4, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S5 + ActionRow{ // S5, Accept("id") Accept: 2, Ignore: "", }, - ActionRow{ // S6 + ActionRow{ // S6, Accept("id") Accept: 2, Ignore: "", }, diff --git a/example/errorrecovery/er.grammar/er/internal/lexer/lexer.go b/example/errorrecovery/er.grammar/er/internal/lexer/lexer.go new file mode 100644 index 00000000..16301c92 --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/iface" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/token" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 7 + NumSymbols = 10 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/errorrecovery/lexer/transitiontable.go b/example/errorrecovery/er.grammar/er/internal/lexer/transitiontable.go old mode 100755 new mode 100644 similarity index 100% rename from example/errorrecovery/lexer/transitiontable.go rename to example/errorrecovery/er.grammar/er/internal/lexer/transitiontable.go diff --git a/example/sr/parser/action.go b/example/errorrecovery/er.grammar/er/internal/parser/action.go old mode 100755 new mode 100644 similarity index 100% rename from example/sr/parser/action.go rename to example/errorrecovery/er.grammar/er/internal/parser/action.go diff --git a/example/errorrecovery/er.grammar/er/internal/parser/actiontable.go b/example/errorrecovery/er.grammar/er/internal/parser/actiontable.go new file mode 100644 index 00000000..5575ca5e --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/parser/actiontable.go @@ -0,0 +1,85 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: true, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(3), // id + shift(4), // λ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: true, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + shift(3), // id + shift(4), // λ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: StmtList + reduce(1), // id, reduce: StmtList + reduce(1), // λ, reduce: StmtList + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt + reduce(3), // id, reduce: Stmt + reduce(3), // λ, reduce: Stmt + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: true, + actions: [numSymbols]action{ + nil, // ά + reduce(4), // Ω, reduce: Stmt + reduce(4), // id, reduce: Stmt + reduce(4), // λ, reduce: Stmt + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: StmtList + reduce(2), // id, reduce: StmtList + reduce(2), // λ, reduce: StmtList + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/errorrecovery/er.grammar/er/internal/parser/gototable.go b/example/errorrecovery/er.grammar/er/internal/parser/gototable.go new file mode 100644 index 00000000..443ec029 --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/parser/gototable.go @@ -0,0 +1,43 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 3 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + 5, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/errorrecovery/er.grammar/er/internal/parser/parser.go b/example/errorrecovery/er.grammar/er/internal/parser/parser.go new file mode 100644 index 00000000..d3c41857 --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/parser/parser.go @@ -0,0 +1,353 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/iface" + parseError "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/errors" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/token" +) + +const ( + numProductions = 5 + numStates = 6 + numSymbols = 7 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = longest + p.isNonDeterministic = false + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/errorrecovery/er.grammar/er/internal/parser/productionstable.go b/example/errorrecovery/er.grammar/er/internal/parser/productionstable.go new file mode 100644 index 00000000..95517242 --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/parser/productionstable.go @@ -0,0 +1,107 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import "github.com/maxcalandrelli/gocc/example/errorrecovery/ast" + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/token" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtList : Π << ast.NewStmtList($0) >>`, + Id: "StmtList", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmtList(X[0]) + }, + }, + ProdTabEntry{ + String: `StmtList : Π Π << ast.AppendStmt($0, $1) >>`, + Id: "StmtList", + NTType: 1, + Index: 2, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AppendStmt(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Stmt : id << ast.NewStmt($0) >>`, + Id: "Stmt", + NTType: 2, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStmt(X[0]) + }, + }, + ProdTabEntry{ + String: `Stmt : λ << >>`, + Id: "Stmt", + NTType: 2, + Index: 4, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, +} diff --git a/example/astx/token/token.go b/example/errorrecovery/er.grammar/er/internal/token/token.go old mode 100755 new mode 100644 similarity index 65% rename from example/astx/token/token.go rename to example/errorrecovery/er.grammar/er/internal/token/token.go index 501b01ac..e045e520 --- a/example/astx/token/token.go +++ b/example/errorrecovery/er.grammar/er/internal/token/token.go @@ -8,8 +8,11 @@ import ( type Token struct { Type - Lit []byte + Lit []byte + IgnoredPrefix []byte Pos + ForeignAstNode interface{} + Foreign bool } type Type int @@ -29,9 +32,24 @@ func (p Pos) String() string { return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) } +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + type TokenMap struct { typeMap []string idMap map[string]Type + litMap map[string]Type } func (m TokenMap) Id(tok Type) string { @@ -49,8 +67,7 @@ func (m TokenMap) Type(tok string) Type { } func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) } func (m TokenMap) StringType(typ Type) string { @@ -60,13 +77,17 @@ func (m TokenMap) StringType(typ Type) string { var TokMap = TokenMap{ typeMap: []string{ "INVALID", - "$", + "Ω", "id", + "λ", }, idMap: map[string]Type{ "INVALID": 0, - "$": 1, + "Ω": 1, "id": 2, + "λ": 3, }, + + litMap: map[string]Type{}, } diff --git a/example/rr/util/litconv.go b/example/errorrecovery/er.grammar/er/internal/util/litconv.go old mode 100755 new mode 100644 similarity index 100% rename from example/rr/util/litconv.go rename to example/errorrecovery/er.grammar/er/internal/util/litconv.go diff --git a/example/errorrecovery/er.grammar/er/internal/util/rune.go b/example/errorrecovery/er.grammar/er/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/errorrecovery/er.grammar/er/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/errorrecovery/er.grammar/er/main/er.go b/example/errorrecovery/er.grammar/er/main/er.go new file mode 100644 index 00000000..74e84e4e --- /dev/null +++ b/example/errorrecovery/er.grammar/er/main/er.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + er "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *er.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return er.NewParser().ParseLongestPrefix(lex) + } else { + res, err = er.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, er.NewLexerString(Text))) + } + if File > "" { + l, e := er.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, er.NewLexerString(str))) + } +} diff --git a/example/errorrecovery/er.grammar/er/util.go b/example/errorrecovery/er.grammar/er/util.go new file mode 100644 index 00000000..0428d95a --- /dev/null +++ b/example/errorrecovery/er.grammar/er/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package er + +import ( + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/errorrecovery/er_test.go b/example/errorrecovery/er_test.go index 8af87bb3..83fba0a9 100644 --- a/example/errorrecovery/er_test.go +++ b/example/errorrecovery/er_test.go @@ -1,13 +1,11 @@ -package astx +package er import ( "fmt" "testing" - "github.com/goccmack/gocc/example/errorrecovery/ast" - "github.com/goccmack/gocc/example/errorrecovery/errors" - "github.com/goccmack/gocc/example/errorrecovery/lexer" - "github.com/goccmack/gocc/example/errorrecovery/parser" + "github.com/maxcalandrelli/gocc/example/errorrecovery/ast" + "github.com/maxcalandrelli/gocc/example/errorrecovery/er.grammar/er" ) func TestFail(t *testing.T) { @@ -18,7 +16,7 @@ func TestFail(t *testing.T) { fmt.Print("output: [\n") for _, s := range sml { switch sym := s.(type) { - case *errors.Error: + case *er.Error: fmt.Printf("%s\n", sym) default: fmt.Printf("\t%v\n", sym) @@ -29,8 +27,8 @@ func TestFail(t *testing.T) { func test(src []byte) (astree ast.StmtList, err error) { fmt.Printf("input: %s\n", src) - s := lexer.NewLexer([]byte(src)) - p := parser.NewParser() + s := er.NewLexerBytes(src) + p := er.NewParser() a, err := p.Parse(s) if err == nil { astree = a.(ast.StmtList) diff --git a/example/errorrecovery/lexer/lexer.go b/example/errorrecovery/lexer/lexer.go deleted file mode 100755 index ea5244fb..00000000 --- a/example/errorrecovery/lexer/lexer.go +++ /dev/null @@ -1,126 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package lexer - -import ( - "io/ioutil" - "unicode/utf8" - - "github.com/goccmack/gocc/example/errorrecovery/token" -) - -const ( - NoState = -1 - NumStates = 7 - NumSymbols = 10 -) - -type Lexer struct { - src []byte - pos int - line int - column int -} - -func NewLexer(src []byte) *Lexer { - lexer := &Lexer{ - src: src, - pos: 0, - line: 1, - column: 1, - } - return lexer -} - -func NewLexerFile(fpath string) (*Lexer, error) { - src, err := ioutil.ReadFile(fpath) - if err != nil { - return nil, err - } - return NewLexer(src), nil -} - -func (l *Lexer) Scan() (tok *token.Token) { - tok = new(token.Token) - if l.pos >= len(l.src) { - tok.Type = token.EOF - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column - return - } - start, startLine, startColumn, end := l.pos, l.line, l.column, 0 - tok.Type = token.INVALID - state, rune1, size := 0, rune(-1), 0 - for state != -1 { - if l.pos >= len(l.src) { - rune1 = -1 - } else { - rune1, size = utf8.DecodeRune(l.src[l.pos:]) - l.pos += size - } - - nextState := -1 - if rune1 != -1 { - nextState = TransTab[state](rune1) - } - state = nextState - - if state != -1 { - - switch rune1 { - case '\n': - l.line++ - l.column = 1 - case '\r': - l.column = 1 - case '\t': - l.column += 4 - default: - l.column++ - } - - switch { - case ActTab[state].Accept != -1: - tok.Type = ActTab[state].Accept - end = l.pos - case ActTab[state].Ignore != "": - start, startLine, startColumn = l.pos, l.line, l.column - state = 0 - if start >= len(l.src) { - tok.Type = token.EOF - } - - } - } else { - if tok.Type == token.INVALID { - end = l.pos - } - } - } - if end > start { - l.pos = end - tok.Lit = l.src[start:end] - } else { - tok.Lit = []byte{} - } - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn - - return -} - -func (l *Lexer) Reset() { - l.pos = 0 -} - -/* -Lexer symbols: -0: '_' -1: '_' -2: ' ' -3: '\t' -4: '\n' -5: '\r' -6: 'a'-'z' -7: 'A'-'Z' -8: '0'-'9' -9: . -*/ diff --git a/example/errorrecovery/parser/actiontable.go b/example/errorrecovery/parser/actiontable.go deleted file mode 100755 index 58496c7f..00000000 --- a/example/errorrecovery/parser/actiontable.go +++ /dev/null @@ -1,68 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - actionTable [numStates]actionRow - actionRow struct { - canRecover bool - actions [numSymbols]action - } -) - -var actionTab = actionTable{ - actionRow{ // S0 - canRecover: true, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(3), // id - shift(4), // error - }, - }, - actionRow{ // S1 - canRecover: true, - actions: [numSymbols]action{ - nil, // INVALID - accept(true), // $ - shift(3), // id - shift(4), // error - }, - }, - actionRow{ // S2 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(1), // $, reduce: StmtList - reduce(1), // id, reduce: StmtList - reduce(1), // error, reduce: StmtList - }, - }, - actionRow{ // S3 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(3), // $, reduce: Stmt - reduce(3), // id, reduce: Stmt - reduce(3), // error, reduce: Stmt - }, - }, - actionRow{ // S4 - canRecover: true, - actions: [numSymbols]action{ - nil, // INVALID - reduce(4), // $, reduce: Stmt - reduce(4), // id, reduce: Stmt - reduce(4), // error, reduce: Stmt - }, - }, - actionRow{ // S5 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(2), // $, reduce: StmtList - reduce(2), // id, reduce: StmtList - reduce(2), // error, reduce: StmtList - }, - }, -} diff --git a/example/errorrecovery/parser/gototable.go b/example/errorrecovery/parser/gototable.go deleted file mode 100755 index 2b3a2108..00000000 --- a/example/errorrecovery/parser/gototable.go +++ /dev/null @@ -1,43 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -const numNTSymbols = 3 - -type ( - gotoTable [numStates]gotoRow - gotoRow [numNTSymbols]int -) - -var gotoTab = gotoTable{ - gotoRow{ // S0 - -1, // S' - 1, // StmtList - 2, // Stmt - }, - gotoRow{ // S1 - -1, // S' - -1, // StmtList - 5, // Stmt - }, - gotoRow{ // S2 - -1, // S' - -1, // StmtList - -1, // Stmt - }, - gotoRow{ // S3 - -1, // S' - -1, // StmtList - -1, // Stmt - }, - gotoRow{ // S4 - -1, // S' - -1, // StmtList - -1, // Stmt - }, - gotoRow{ // S5 - -1, // S' - -1, // StmtList - -1, // Stmt - }, -} diff --git a/example/errorrecovery/parser/parser.go b/example/errorrecovery/parser/parser.go deleted file mode 100755 index 1b50bcb6..00000000 --- a/example/errorrecovery/parser/parser.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "fmt" - "strings" - - parseError "github.com/goccmack/gocc/example/errorrecovery/errors" - "github.com/goccmack/gocc/example/errorrecovery/token" -) - -const ( - numProductions = 5 - numStates = 6 - numSymbols = 7 -) - -// Stack - -type stack struct { - state []int - attrib []Attrib -} - -const iNITIAL_STACK_SIZE = 100 - -func newStack() *stack { - return &stack{ - state: make([]int, 0, iNITIAL_STACK_SIZE), - attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), - } -} - -func (s *stack) reset() { - s.state = s.state[:0] - s.attrib = s.attrib[:0] -} - -func (s *stack) push(state int, a Attrib) { - s.state = append(s.state, state) - s.attrib = append(s.attrib, a) -} - -func (s *stack) top() int { - return s.state[len(s.state)-1] -} - -func (s *stack) peek(pos int) int { - return s.state[pos] -} - -func (s *stack) topIndex() int { - return len(s.state) - 1 -} - -func (s *stack) popN(items int) []Attrib { - lo, hi := len(s.state)-items, len(s.state) - - attrib := s.attrib[lo:hi] - - s.state = s.state[:lo] - s.attrib = s.attrib[:lo] - - return attrib -} - -func (s *stack) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "stack:\n") - for i, st := range s.state { - fmt.Fprintf(w, "\t%d: %d , ", i, st) - if s.attrib[i] == nil { - fmt.Fprintf(w, "nil") - } else { - switch attr := s.attrib[i].(type) { - case *token.Token: - fmt.Fprintf(w, "%s", attr.Lit) - default: - fmt.Fprintf(w, "%v", attr) - } - } - fmt.Fprintf(w, "\n") - } - return w.String() -} - -// Parser - -type Parser struct { - stack *stack - nextToken *token.Token - pos int -} - -type Scanner interface { - Scan() (tok *token.Token) -} - -func NewParser() *Parser { - p := &Parser{stack: newStack()} - p.Reset() - return p -} - -func (p *Parser) Reset() { - p.stack.reset() - p.stack.push(0, nil) -} - -func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { - errorAttrib = &parseError.Error{ - Err: err, - ErrorToken: p.nextToken, - ErrorSymbols: p.popNonRecoveryStates(), - ExpectedTokens: make([]string, 0, 8), - } - for t, action := range actionTab[p.stack.top()].actions { - if action != nil { - errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) - } - } - - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { - p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift - } else { - return - } - - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - for !recovered && p.nextToken.Type != token.EOF { - p.nextToken = scanner.Scan() - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - } - - return -} - -func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { - if rs, ok := p.firstRecoveryState(); ok { - errorSymbols := p.stack.popN(p.stack.topIndex() - rs) - removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) - for i, e := range errorSymbols { - removedAttribs[i] = e - } - } else { - removedAttribs = []parseError.ErrorSymbol{} - } - return -} - -// recoveryState points to the highest state on the stack, which can recover -func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { - recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover - for recoveryState > 0 && !canRecover { - recoveryState-- - canRecover = actionTab[p.stack.peek(recoveryState)].canRecover - } - return -} - -func (p *Parser) newError(err error) error { - e := &parseError.Error{ - Err: err, - StackTop: p.stack.top(), - ErrorToken: p.nextToken, - } - actRow := actionTab[p.stack.top()] - for i, t := range actRow.actions { - if t != nil { - e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) - } - } - return e -} - -func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { - p.Reset() - p.nextToken = scanner.Scan() - for acc := false; !acc; { - action := actionTab[p.stack.top()].actions[p.nextToken.Type] - if action == nil { - if recovered, errAttrib := p.Error(nil, scanner); !recovered { - p.nextToken = errAttrib.ErrorToken - return nil, p.newError(nil) - } - if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { - panic("Error recovery led to invalid action") - } - } - - switch act := action.(type) { - case accept: - res = p.stack.popN(1)[0] - acc = true - case shift: - p.stack.push(int(act), p.nextToken) - p.nextToken = scanner.Scan() - case reduce: - prod := productionsTable[int(act)] - attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) - if err != nil { - return nil, p.newError(err) - } else { - p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) - } - default: - panic("unknown action: " + action.String()) - } - } - return res, nil -} diff --git a/example/errorrecovery/parser/productionstable.go b/example/errorrecovery/parser/productionstable.go deleted file mode 100755 index e4b8ddb6..00000000 --- a/example/errorrecovery/parser/productionstable.go +++ /dev/null @@ -1,73 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import "github.com/goccmack/gocc/example/errorrecovery/ast" - -type ( - //TODO: change type and variable names to be consistent with other tables - ProdTab [numProductions]ProdTabEntry - ProdTabEntry struct { - String string - Id string - NTType int - Index int - NumSymbols int - ReduceFunc func([]Attrib) (Attrib, error) - } - Attrib interface { - } -) - -var productionsTable = ProdTab{ - ProdTabEntry{ - String: `S' : StmtList << >>`, - Id: "S'", - NTType: 0, - Index: 0, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `StmtList : Stmt << ast.NewStmtList(X[0]) >>`, - Id: "StmtList", - NTType: 1, - Index: 1, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewStmtList(X[0]) - }, - }, - ProdTabEntry{ - String: `StmtList : StmtList Stmt << ast.AppendStmt(X[0], X[1]) >>`, - Id: "StmtList", - NTType: 1, - Index: 2, - NumSymbols: 2, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.AppendStmt(X[0], X[1]) - }, - }, - ProdTabEntry{ - String: `Stmt : id << ast.NewStmt(X[0]) >>`, - Id: "Stmt", - NTType: 2, - Index: 3, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewStmt(X[0]) - }, - }, - ProdTabEntry{ - String: `Stmt : error << >>`, - Id: "Stmt", - NTType: 2, - Index: 4, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, -} diff --git a/example/errorrecovery/parser/symbols.go b/example/errorrecovery/parser/symbols.go deleted file mode 100755 index 478177ee..00000000 --- a/example/errorrecovery/parser/symbols.go +++ /dev/null @@ -1,44 +0,0 @@ -package parser - -type symbol struct { - Name string - IsTerminal bool -} - -var symbols = [numSymbols]symbol{ - - { - Name: "INVALID", - IsTerminal: true, - }, - - { - Name: "$", - IsTerminal: true, - }, - - { - Name: "S'", - IsTerminal: false, - }, - - { - Name: "StmtList", - IsTerminal: false, - }, - - { - Name: "Stmt", - IsTerminal: false, - }, - - { - Name: "id", - IsTerminal: true, - }, - - { - Name: "error", - IsTerminal: true, - }, -} diff --git a/example/errorrecovery/util/rune.go b/example/errorrecovery/util/rune.go deleted file mode 100755 index bd8523a4..00000000 --- a/example/errorrecovery/util/rune.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package util - -import ( - "fmt" -) - -func RuneToString(r rune) string { - if r >= 0x20 && r < 0x7f { - return fmt.Sprintf("'%c'", r) - } - switch r { - case 0x07: - return "'\\a'" - case 0x08: - return "'\\b'" - case 0x0C: - return "'\\f'" - case 0x0A: - return "'\\n'" - case 0x0D: - return "'\\r'" - case 0x09: - return "'\\t'" - case 0x0b: - return "'\\v'" - case 0x5c: - return "'\\\\\\'" - case 0x27: - return "'\\''" - case 0x22: - return "'\\\"'" - } - if r < 0x10000 { - return fmt.Sprintf("\\u%04x", r) - } - return fmt.Sprintf("\\U%08x", r) -} diff --git a/example/examples.sh b/example/examples.sh new file mode 100755 index 00000000..51998d7a --- /dev/null +++ b/example/examples.sh @@ -0,0 +1,2 @@ +#!/bin/bash +for dir in $(find . -mindepth 1 -maxdepth 1 -type d) ; do ( echo -e "\n\n\n******\nTest: $(basename $dir)\n******" ;cd $dir ; rm -rf *.grammar ; make ; go test -v ) ; done \ No newline at end of file diff --git a/example/macro/Makefile b/example/macro/Makefile new file mode 100644 index 00000000..fb38f7f7 --- /dev/null +++ b/example/macro/Makefile @@ -0,0 +1,4 @@ +regenerate: + gocc -preprocessor="cpp -P @in @out" macro1.bnf + gocc -preprocessor="internal" macro2.bnf + diff --git a/example/macro/macro1.bnf b/example/macro/macro1.bnf new file mode 100644 index 00000000..37702058 --- /dev/null +++ b/example/macro/macro1.bnf @@ -0,0 +1,73 @@ +!whitespace : ' ' | '\t' | '\n' | '\r' ; +_digit : '0'-'9' ; +_letter : 'a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) ; +_hex : _digit | ( 'a'-'f' ) | ('A' - 'F') ; +_idchar : _letter | _digit | '_'; + +_x0 : 'α' ; +_x1 : 'β' _digit { _digit } ; +_x : 'α' | ( 'β' _digit { _digit } ); + +id: + _x { _x0 | _x1 | 'γ' } +; + +<< + + +func first_one(x string) []string { + fmt.Printf("start with this this one: %s\n", x) + return []string{x} +} + +func add_one(c []string, x string) []string { + fmt.Printf("add to %q that %s\n", c, x) + return append([]string{x},c...) +} + +func summary(v interface{}) string { + return fmt.Sprintf("ok, so we got <%q> as a final result.\n", v) +} + +func definition(deftype, defname string, defval int64) (interface{}, error) { + fmt.Printf("Definition of variable <%s> with '%s' as %d\n", defname, deftype, defval) + return fmt.Sprintf("%s <- %d", defname, defval), nil +} + +>> + +#define DEFREPEATABLE(x, action_1, action_n, type)\ +x##_s : \ + x \ + << action_1($0.(type)),nil >>\ + |\ + x##_s \ + ";"\ + x \ + << action_n($0.([]type),$2.(type)),nil >>\ +;\ + + + +StmtList : + Stmt_s + << + func() (interface{}, error) {fmt.Printf("%s", summary($0)); return 42, nil}() + >> +; + +DEFREPEATABLE(Stmt, first_one, add_one, string) + +StmtPref: + "let"| "define" +; + +Stmt : + StmtPref + id + "=" + @ "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + << + definition($0s,$1s,$4.(int64)) + >> +; diff --git a/example/macro/macro1.grammar/macro1/iface/macro1.go b/example/macro/macro1.grammar/macro1/iface/macro1.go new file mode 100644 index 00000000..d9a165bc --- /dev/null +++ b/example/macro/macro1.grammar/macro1/iface/macro1.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/errors" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/macro/macro1.grammar/macro1/internal/errors/errors.go b/example/macro/macro1.grammar/macro1/internal/errors/errors.go new file mode 100644 index 00000000..9e0b23d0 --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/macro/macro1.grammar/macro1/internal/io/stream/internal/stream_impl.go b/example/macro/macro1.grammar/macro1/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/macro/macro1.grammar/macro1/internal/io/stream/internal/stream_public.go b/example/macro/macro1.grammar/macro1/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/macro/macro1.grammar/macro1/internal/io/stream/stream.go b/example/macro/macro1.grammar/macro1/internal/io/stream/stream.go new file mode 100644 index 00000000..5f8e95fa --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/macro/macro1.grammar/macro1/internal/lexer/acttab.go b/example/macro/macro1.grammar/macro1/internal/lexer/acttab.go new file mode 100644 index 00000000..326ec40f --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/lexer/acttab.go @@ -0,0 +1,115 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + "fmt" + + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (a ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1, Ignore("!whitespace") + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2, Accept("Λ<;>") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S3, Accept("Λ<=>") + Accept: 6, + Ignore: "", + }, + ActionRow{ // S4, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S5, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S6, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S7, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S8, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S9, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S10, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S11, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S12, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S13, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S14, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S15, Accept("Λ") + Accept: 3, + Ignore: "", + }, + ActionRow{ // S16, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S17, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S18, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S19, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S20, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S21, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S22, Accept("Λ") + Accept: 4, + Ignore: "", + }, +} diff --git a/example/macro/macro1.grammar/macro1/internal/lexer/lexer.go b/example/macro/macro1.grammar/macro1/internal/lexer/lexer.go new file mode 100644 index 00000000..19bb91be --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/iface" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/token" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 23 + NumSymbols = 29 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/macro/macro1.grammar/macro1/internal/lexer/transitiontable.go b/example/macro/macro1.grammar/macro1/internal/lexer/transitiontable.go new file mode 100644 index 00000000..c5b6686a --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/lexer/transitiontable.go @@ -0,0 +1,239 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 59: // [';',';'] + return 2 + case r == 61: // ['=','='] + return 3 + case r == 100: // ['d','d'] + return 4 + case r == 108: // ['l','l'] + return 5 + case r == 945: // [\u03b1,\u03b1] + return 6 + case r == 946: // [\u03b2,\u03b2] + return 7 + } + return NoState + }, + // S1 + func(r rune) int { + switch { + } + return NoState + }, + // S2 + func(r rune) int { + switch { + } + return NoState + }, + // S3 + func(r rune) int { + switch { + } + return NoState + }, + // S4 + func(r rune) int { + switch { + case r == 101: // ['e','e'] + return 8 + } + return NoState + }, + // S5 + func(r rune) int { + switch { + case r == 101: // ['e','e'] + return 9 + } + return NoState + }, + // S6 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S7 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 13 + } + return NoState + }, + // S8 + func(r rune) int { + switch { + case r == 102: // ['f','f'] + return 14 + } + return NoState + }, + // S9 + func(r rune) int { + switch { + case r == 116: // ['t','t'] + return 15 + } + return NoState + }, + // S10 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S11 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 16 + } + return NoState + }, + // S12 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S13 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 13 + case r == 945: // [\u03b1,\u03b1] + return 17 + case r == 946: // [\u03b2,\u03b2] + return 18 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S14 + func(r rune) int { + switch { + case r == 105: // ['i','i'] + return 19 + } + return NoState + }, + // S15 + func(r rune) int { + switch { + } + return NoState + }, + // S16 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 16 + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S17 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S18 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 20 + } + return NoState + }, + // S19 + func(r rune) int { + switch { + case r == 110: // ['n','n'] + return 21 + } + return NoState + }, + // S20 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 20 + case r == 945: // [\u03b1,\u03b1] + return 17 + case r == 946: // [\u03b2,\u03b2] + return 18 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S21 + func(r rune) int { + switch { + case r == 101: // ['e','e'] + return 22 + } + return NoState + }, + // S22 + func(r rune) int { + switch { + } + return NoState + }, +} diff --git a/example/macro/macro1.grammar/macro1/internal/parser/action.go b/example/macro/macro1.grammar/macro1/internal/parser/action.go new file mode 100644 index 00000000..54bc55e9 --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/parser/action.go @@ -0,0 +1,51 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" +) + +type action interface { + act() + String() string +} + +type ( + accept bool + shift int // value is next state index + reduce int // value is production index +) + +func (this accept) act() {} +func (this shift) act() {} +func (this reduce) act() {} + +func (this accept) Equal(that action) bool { + if _, ok := that.(accept); ok { + return true + } + return false +} + +func (this reduce) Equal(that action) bool { + that1, ok := that.(reduce) + if !ok { + return false + } + return this == that1 +} + +func (this shift) Equal(that action) bool { + that1, ok := that.(shift) + if !ok { + return false + } + return this == that1 +} + +func (this accept) String() string { return "accept(0)" } +func (this shift) String() string { return fmt.Sprintf("shift:%d", this) } +func (this reduce) String() string { + return fmt.Sprintf("reduce:%d(%s)", this, productionsTable[this].String) +} diff --git a/example/macro/macro1.grammar/macro1/internal/parser/actiontable.go b/example/macro/macro1.grammar/macro1/internal/parser/actiontable.go new file mode 100644 index 00000000..5cf42646 --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/parser/actiontable.go @@ -0,0 +1,195 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + shift(5), // "let" + shift(6), // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + nil, // ";" + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: StmtList + shift(7), // ";" + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: Stmt_s + reduce(2), // ";", reduce: Stmt_s + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + shift(8), // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + reduce(4), // id, reduce: StmtPref + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + reduce(5), // id, reduce: StmtPref + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S7 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + shift(5), // "let" + shift(6), // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S8 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + nil, // id + shift(10), // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S9 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt_s + reduce(3), // ";", reduce: Stmt_s + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S10 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + shift(11), // μ + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 7, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S11 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(6), // Ω, reduce: Stmt + reduce(6), // ";", reduce: Stmt + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/macro/macro1.grammar/macro1/internal/parser/gototable.go b/example/macro/macro1.grammar/macro1/internal/parser/gototable.go new file mode 100644 index 00000000..bb84cbfe --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/parser/gototable.go @@ -0,0 +1,97 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 5 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + 3, // Π + 4, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S6 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S7 + -1, // Π + -1, // Π + -1, // Π + 9, // Π + 4, // Π + }, + gotoRow{ // S8 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S9 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S10 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S11 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/macro/macro1.grammar/macro1/internal/parser/parser.go b/example/macro/macro1.grammar/macro1/internal/parser/parser.go new file mode 100644 index 00000000..a629f54c --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/parser/parser.go @@ -0,0 +1,359 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/iface" + parseError "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/errors" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/token" + + calc "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" +) + +const ( + numProductions = 7 + numStates = 12 + numSymbols = 13 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func cdFunc_calc_0(Stream TokenStream, Context interface{}) (interface{}, error, []byte) { + return calc.ParseWithDataPartial(Stream, Context) +} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = true + p.isNonDeterministic = true + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/macro/macro1.grammar/macro1/internal/parser/productionstable.go b/example/macro/macro1.grammar/macro1/internal/parser/productionstable.go new file mode 100644 index 00000000..c49ed063 --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/parser/productionstable.go @@ -0,0 +1,141 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/token" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/util" + "strings" +) + +func first_one(x string) []string { + fmt.Printf("start with this this one: %s\n", x) + return []string{x} +} +func add_one(c []string, x string) []string { + fmt.Printf("add to %q that %s\n", c, x) + return append([]string{x}, c...) +} +func summary(v interface{}) string { + return fmt.Sprintf("ok, so we got <%q> as a final result.\n", v) +} +func definition(deftype, defname string, defval int64) (interface{}, error) { + fmt.Printf("Definition of variable <%s> with '%s' as %d\n", defname, deftype, defval) + return fmt.Sprintf("%s <- %d", defname, defval), nil +} + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtList : Π << func() (interface{}, error) {fmt.Printf("%s", summary($0)); return 42, nil}() >>`, + Id: "StmtList", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return func() (interface{}, error) { fmt.Printf("%s", summary(X[0])); return 42, nil }() + }, + }, + ProdTabEntry{ + String: `Stmt_s : Π << first_one($0.(string)),nil >>`, + Id: "Stmt_s", + NTType: 2, + Index: 2, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return first_one(X[0].(string)), nil + }, + }, + ProdTabEntry{ + String: `Stmt_s : Π Λ<;> Π << add_one($0.([]string),$2.(string)),nil >>`, + Id: "Stmt_s", + NTType: 2, + Index: 3, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return add_one(X[0].([]string), X[2].(string)), nil + }, + }, + ProdTabEntry{ + String: `StmtPref : Λ << >>`, + Id: "StmtPref", + NTType: 4, + Index: 4, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtPref : Λ << >>`, + Id: "StmtPref", + NTType: 4, + Index: 5, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : Π id Λ<=> μ << definition($0s,$1s,$4.(int64)) >>`, + Id: "Stmt", + NTType: 3, + Index: 6, + NumSymbols: 5, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return definition(getString(X[0]), getString(X[1]), X[4].(int64)) + }, + }, +} diff --git a/example/macro/macro1.grammar/macro1/internal/token/token.go b/example/macro/macro1.grammar/macro1/internal/token/token.go new file mode 100644 index 00000000..bd4fc7cf --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/token/token.go @@ -0,0 +1,166 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +import ( + "fmt" + "strconv" + "unicode/utf8" +) + +type Token struct { + Type + Lit []byte + IgnoredPrefix []byte + Pos + ForeignAstNode interface{} + Foreign bool +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (p Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) +} + +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type + litMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +// CharLiteralValue returns the string value of the char literal. +func (t *Token) CharLiteralValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +// Float32Value returns the float32 value of the token or an error if the token literal does not +// denote a valid float32. +func (t *Token) Float32Value() (float32, error) { + if v, err := strconv.ParseFloat(string(t.Lit), 32); err != nil { + return 0, err + } else { + return float32(v), nil + } +} + +// Float64Value returns the float64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Float64Value() (float64, error) { + return strconv.ParseFloat(string(t.Lit), 64) +} + +// IDValue returns the string representation of an identifier token. +func (t *Token) IDValue() string { + return string(t.Lit) +} + +// Int32Value returns the int32 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int32Value() (int32, error) { + if v, err := strconv.ParseInt(string(t.Lit), 10, 64); err != nil { + return 0, err + } else { + return int32(v), nil + } +} + +// Int64Value returns the int64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int64Value() (int64, error) { + return strconv.ParseInt(string(t.Lit), 10, 64) +} + +// UTF8Rune decodes the UTF8 rune in the token literal. It returns utf8.RuneError if +// the token literal contains an invalid rune. +func (t *Token) UTF8Rune() (rune, error) { + r, _ := utf8.DecodeRune(t.Lit) + if r == utf8.RuneError { + err := fmt.Errorf("Invalid rune") + return r, err + } + return r, nil +} + +// StringValue returns the string value of the token literal. +func (t *Token) StringValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "Ω", + "Λ<;>", + "Λ", + "Λ", + "id", + "Λ<=>", + "μ", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "Ω": 1, + "Λ<;>": 2, + "Λ": 3, + "Λ": 4, + "id": 5, + "Λ<=>": 6, + "μ": 7, + }, + + litMap: map[string]Type{ + ";": 2, + "let": 3, + "define": 4, + "=": 6, + }, +} diff --git a/example/sr/util/litconv.go b/example/macro/macro1.grammar/macro1/internal/util/litconv.go old mode 100755 new mode 100644 similarity index 100% rename from example/sr/util/litconv.go rename to example/macro/macro1.grammar/macro1/internal/util/litconv.go diff --git a/example/macro/macro1.grammar/macro1/internal/util/rune.go b/example/macro/macro1.grammar/macro1/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/macro/macro1.grammar/macro1/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/macro/macro1.grammar/macro1/log/macro1.bnf b/example/macro/macro1.grammar/macro1/log/macro1.bnf new file mode 100644 index 00000000..77886cef --- /dev/null +++ b/example/macro/macro1.grammar/macro1/log/macro1.bnf @@ -0,0 +1,47 @@ +!whitespace : ' ' | '\t' | '\n' | '\r' ; +_digit : '0'-'9' ; +_letter : 'a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) ; +_hex : _digit | ( 'a'-'f' ) | ('A' - 'F') ; +_idchar : _letter | _digit | '_'; +_x0 : 'α' ; +_x1 : 'β' _digit { _digit } ; +_x : 'α' | ( 'β' _digit { _digit } ); +id: + _x { _x0 | _x1 | 'γ' } +; +<< +func first_one(x string) []string { + fmt.Printf("start with this this one: %s\n", x) + return []string{x} +} +func add_one(c []string, x string) []string { + fmt.Printf("add to %q that %s\n", c, x) + return append([]string{x},c...) +} +func summary(v interface{}) string { + return fmt.Sprintf("ok, so we got <%q> as a final result.\n", v) +} +func definition(deftype, defname string, defval int64) (interface{}, error) { + fmt.Printf("Definition of variable <%s> with '%s' as %d\n", defname, deftype, defval) + return fmt.Sprintf("%s <- %d", defname, defval), nil +} +>> +StmtList : + Stmt_s + << + func() (interface{}, error) {fmt.Printf("%s", summary($0)); return 42, nil}() + >> +; +Stmt_s : Stmt << first_one($0.(string)),nil >> | Stmt_s ";" Stmt << add_one($0.([]string),$2.(string)),nil >>; +StmtPref: + "let"| "define" +; +Stmt : + StmtPref + id + "=" + @ "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + << + definition($0s,$1s,$4.(int64)) + >> +; diff --git a/example/macro/macro1.grammar/macro1/macro1.go b/example/macro/macro1.grammar/macro1/macro1.go new file mode 100644 index 00000000..1f81f155 --- /dev/null +++ b/example/macro/macro1.grammar/macro1/macro1.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package macro1 + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/errors" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/lexer" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/parser" + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/macro/macro1.grammar/macro1/main/macro1.go b/example/macro/macro1.grammar/macro1/main/macro1.go new file mode 100644 index 00000000..162301a1 --- /dev/null +++ b/example/macro/macro1.grammar/macro1/main/macro1.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + macro1 "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *macro1.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return macro1.NewParser().ParseLongestPrefix(lex) + } else { + res, err = macro1.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, macro1.NewLexerString(Text))) + } + if File > "" { + l, e := macro1.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, macro1.NewLexerString(str))) + } +} diff --git a/example/macro/macro1.grammar/macro1/util.go b/example/macro/macro1.grammar/macro1/util.go new file mode 100644 index 00000000..0af9513c --- /dev/null +++ b/example/macro/macro1.grammar/macro1/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package macro1 + +import ( + "github.com/maxcalandrelli/gocc/example/macro/macro1.grammar/macro1/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/macro/macro2.bnf b/example/macro/macro2.bnf new file mode 100644 index 00000000..eaa66b7c --- /dev/null +++ b/example/macro/macro2.bnf @@ -0,0 +1,85 @@ +!whitespace : ' ' | '\t' | '\n' | '\r' ; +_digit : '0'-'9' ; +_letter : 'a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) ; +_hex : _digit | ( 'a'-'f' ) | ('A' - 'F') ; +_idchar : _letter | _digit | '_'; + +_x0 : 'α' ; +_x1 : 'β' _digit { _digit } ; +_x : 'α' | ( 'β' _digit { _digit } ); + +id: + _x { _x0 | _x1 | 'γ' } +; + +<< + + +func first_one(x string) []string { + fmt.Printf("start with this this one: %s\n", x) + return []string{x} +} + +func add_one(c []string, x string) []string { + fmt.Printf("add to %q that %s\n", c, x) + return append([]string{x},c...) +} + +func summary(v interface{}) string { + return fmt.Sprintf("ok, so we got <%q> as a final result.\n", v) +} + +func definition(deftype, defname string, defval int64) (interface{}, error) { + fmt.Printf("Definition of variable <%s> with '%s' as %d\n", defname, deftype, defval) + return fmt.Sprintf("%s <- %d", defname, defval), nil +} + +>> + +MACRO ONEOF(FIRST,VARGS) + {FIRST} + ? VLEN > 0 | + ? VLEN > 0 ONEOF({VARG0},{VARGS}) +ENDMACRO ONEOF + +MACRO DEFREPEATABLE(x, action_1, action_n) +{x}_s : + {x} + << {action_1} >> + | + {x}_s + ";" + {x} + << {action_n} >> +; +ENDMACRO DEFREPEATABLE + +MACRO ACTION(f) +func() (retval interface{}, err error) { + {f} + return +}() +ENDMACRO ACTION + +StmtList : + Stmt_s + << + ACTION(fmt.Printf("%s"<,> summary($0)); retval<,> err = 42<,> nil) + >> +; + +DEFREPEATABLE(Stmt, first_one($0s)<,>nil, add_one($0.([]string)<,>$2s)<,>nil) + +StmtPref: + ONEOF("let", "define") +; + +Stmt : + StmtPref + id + "=" + @ "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + << + definition($0s,$1s,$4.(int64)) + >> +; diff --git a/example/macro/macro2.grammar/macro2/iface/macro2.go b/example/macro/macro2.grammar/macro2/iface/macro2.go new file mode 100644 index 00000000..1dfe8a9e --- /dev/null +++ b/example/macro/macro2.grammar/macro2/iface/macro2.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/errors" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/macro/macro2.grammar/macro2/internal/errors/errors.go b/example/macro/macro2.grammar/macro2/internal/errors/errors.go new file mode 100644 index 00000000..4f45cc58 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/macro/macro2.grammar/macro2/internal/io/stream/internal/stream_impl.go b/example/macro/macro2.grammar/macro2/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/macro/macro2.grammar/macro2/internal/io/stream/internal/stream_public.go b/example/macro/macro2.grammar/macro2/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/macro/macro2.grammar/macro2/internal/io/stream/stream.go b/example/macro/macro2.grammar/macro2/internal/io/stream/stream.go new file mode 100644 index 00000000..b7284551 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/macro/macro2.grammar/macro2/internal/lexer/acttab.go b/example/macro/macro2.grammar/macro2/internal/lexer/acttab.go new file mode 100644 index 00000000..552fbbda --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/lexer/acttab.go @@ -0,0 +1,115 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + "fmt" + + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (a ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1, Ignore("!whitespace") + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2, Accept("Λ<;>") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S3, Accept("Λ<=>") + Accept: 6, + Ignore: "", + }, + ActionRow{ // S4, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S5, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S6, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S7, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S8, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S9, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S10, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S11, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S12, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S13, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S14, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S15, Accept("Λ") + Accept: 3, + Ignore: "", + }, + ActionRow{ // S16, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S17, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S18, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S19, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S20, Accept("id") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S21, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S22, Accept("Λ") + Accept: 4, + Ignore: "", + }, +} diff --git a/example/macro/macro2.grammar/macro2/internal/lexer/lexer.go b/example/macro/macro2.grammar/macro2/internal/lexer/lexer.go new file mode 100644 index 00000000..89635d2e --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/iface" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/token" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 23 + NumSymbols = 29 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/macro/macro2.grammar/macro2/internal/lexer/transitiontable.go b/example/macro/macro2.grammar/macro2/internal/lexer/transitiontable.go new file mode 100644 index 00000000..c5b6686a --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/lexer/transitiontable.go @@ -0,0 +1,239 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 59: // [';',';'] + return 2 + case r == 61: // ['=','='] + return 3 + case r == 100: // ['d','d'] + return 4 + case r == 108: // ['l','l'] + return 5 + case r == 945: // [\u03b1,\u03b1] + return 6 + case r == 946: // [\u03b2,\u03b2] + return 7 + } + return NoState + }, + // S1 + func(r rune) int { + switch { + } + return NoState + }, + // S2 + func(r rune) int { + switch { + } + return NoState + }, + // S3 + func(r rune) int { + switch { + } + return NoState + }, + // S4 + func(r rune) int { + switch { + case r == 101: // ['e','e'] + return 8 + } + return NoState + }, + // S5 + func(r rune) int { + switch { + case r == 101: // ['e','e'] + return 9 + } + return NoState + }, + // S6 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S7 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 13 + } + return NoState + }, + // S8 + func(r rune) int { + switch { + case r == 102: // ['f','f'] + return 14 + } + return NoState + }, + // S9 + func(r rune) int { + switch { + case r == 116: // ['t','t'] + return 15 + } + return NoState + }, + // S10 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S11 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 16 + } + return NoState + }, + // S12 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S13 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 13 + case r == 945: // [\u03b1,\u03b1] + return 17 + case r == 946: // [\u03b2,\u03b2] + return 18 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S14 + func(r rune) int { + switch { + case r == 105: // ['i','i'] + return 19 + } + return NoState + }, + // S15 + func(r rune) int { + switch { + } + return NoState + }, + // S16 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 16 + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S17 + func(r rune) int { + switch { + case r == 945: // [\u03b1,\u03b1] + return 10 + case r == 946: // [\u03b2,\u03b2] + return 11 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S18 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 20 + } + return NoState + }, + // S19 + func(r rune) int { + switch { + case r == 110: // ['n','n'] + return 21 + } + return NoState + }, + // S20 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 20 + case r == 945: // [\u03b1,\u03b1] + return 17 + case r == 946: // [\u03b2,\u03b2] + return 18 + case r == 947: // [\u03b3,\u03b3] + return 12 + } + return NoState + }, + // S21 + func(r rune) int { + switch { + case r == 101: // ['e','e'] + return 22 + } + return NoState + }, + // S22 + func(r rune) int { + switch { + } + return NoState + }, +} diff --git a/example/macro/macro2.grammar/macro2/internal/parser/action.go b/example/macro/macro2.grammar/macro2/internal/parser/action.go new file mode 100644 index 00000000..54bc55e9 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/parser/action.go @@ -0,0 +1,51 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" +) + +type action interface { + act() + String() string +} + +type ( + accept bool + shift int // value is next state index + reduce int // value is production index +) + +func (this accept) act() {} +func (this shift) act() {} +func (this reduce) act() {} + +func (this accept) Equal(that action) bool { + if _, ok := that.(accept); ok { + return true + } + return false +} + +func (this reduce) Equal(that action) bool { + that1, ok := that.(reduce) + if !ok { + return false + } + return this == that1 +} + +func (this shift) Equal(that action) bool { + that1, ok := that.(shift) + if !ok { + return false + } + return this == that1 +} + +func (this accept) String() string { return "accept(0)" } +func (this shift) String() string { return fmt.Sprintf("shift:%d", this) } +func (this reduce) String() string { + return fmt.Sprintf("reduce:%d(%s)", this, productionsTable[this].String) +} diff --git a/example/macro/macro2.grammar/macro2/internal/parser/actiontable.go b/example/macro/macro2.grammar/macro2/internal/parser/actiontable.go new file mode 100644 index 00000000..5cf42646 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/parser/actiontable.go @@ -0,0 +1,195 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + shift(5), // "let" + shift(6), // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + nil, // ";" + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: StmtList + shift(7), // ";" + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: Stmt_s + reduce(2), // ";", reduce: Stmt_s + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + shift(8), // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + reduce(4), // id, reduce: StmtPref + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + reduce(5), // id, reduce: StmtPref + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S7 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + shift(5), // "let" + shift(6), // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S8 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + nil, // id + shift(10), // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S9 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt_s + reduce(3), // ";", reduce: Stmt_s + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + actionRow{ // S10 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // ";" + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + shift(11), // μ + }, + cdActions: []cdAction{ + cdAction{tokenIndex: 7, tokenScanner: cdFunc_calc_0}, + }, + }, + actionRow{ // S11 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(6), // Ω, reduce: Stmt + reduce(6), // ";", reduce: Stmt + nil, // "let" + nil, // "define" + nil, // id + nil, // "=" + nil, // μ + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/macro/macro2.grammar/macro2/internal/parser/gototable.go b/example/macro/macro2.grammar/macro2/internal/parser/gototable.go new file mode 100644 index 00000000..bb84cbfe --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/parser/gototable.go @@ -0,0 +1,97 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 5 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + 3, // Π + 4, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S6 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S7 + -1, // Π + -1, // Π + -1, // Π + 9, // Π + 4, // Π + }, + gotoRow{ // S8 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S9 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S10 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S11 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/macro/macro2.grammar/macro2/internal/parser/parser.go b/example/macro/macro2.grammar/macro2/internal/parser/parser.go new file mode 100644 index 00000000..49e4b6c4 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/parser/parser.go @@ -0,0 +1,359 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/iface" + parseError "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/errors" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/token" + + calc "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" +) + +const ( + numProductions = 7 + numStates = 12 + numSymbols = 13 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func cdFunc_calc_0(Stream TokenStream, Context interface{}) (interface{}, error, []byte) { + return calc.ParseWithDataPartial(Stream, Context) +} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = true + p.isNonDeterministic = true + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/macro/macro2.grammar/macro2/internal/parser/productionstable.go b/example/macro/macro2.grammar/macro2/internal/parser/productionstable.go new file mode 100644 index 00000000..61d43b14 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/parser/productionstable.go @@ -0,0 +1,148 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/token" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/util" + "strings" +) + +func first_one(x string) []string { + fmt.Printf("start with this this one: %s\n", x) + return []string{x} +} +func add_one(c []string, x string) []string { + fmt.Printf("add to %q that %s\n", c, x) + return append([]string{x}, c...) +} +func summary(v interface{}) string { + return fmt.Sprintf("ok, so we got <%q> as a final result.\n", v) +} +func definition(deftype, defname string, defval int64) (interface{}, error) { + fmt.Printf("Definition of variable <%s> with '%s' as %d\n", defname, deftype, defval) + return fmt.Sprintf("%s <- %d", defname, defval), nil +} + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtList : Π << func() (retval interface{}, err error) { + fmt.Printf("%s", summary($0)); retval, err = 42, nil + return +}() >>`, + Id: "StmtList", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return func() (retval interface{}, err error) { + fmt.Printf("%s", summary(X[0])) + retval, err = 42, nil + return + }() + }, + }, + ProdTabEntry{ + String: `Stmt_s : Π << first_one($0s),nil >>`, + Id: "Stmt_s", + NTType: 2, + Index: 2, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return first_one(getString(X[0])), nil + }, + }, + ProdTabEntry{ + String: `Stmt_s : Π Λ<;> Π << add_one($0.([]string),$2s),nil >>`, + Id: "Stmt_s", + NTType: 2, + Index: 3, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return add_one(X[0].([]string), getString(X[2])), nil + }, + }, + ProdTabEntry{ + String: `StmtPref : Λ << >>`, + Id: "StmtPref", + NTType: 4, + Index: 4, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `StmtPref : Λ << >>`, + Id: "StmtPref", + NTType: 4, + Index: 5, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : Π id Λ<=> μ << definition($0s,$1s,$4.(int64)) >>`, + Id: "Stmt", + NTType: 3, + Index: 6, + NumSymbols: 5, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return definition(getString(X[0]), getString(X[1]), X[4].(int64)) + }, + }, +} diff --git a/example/macro/macro2.grammar/macro2/internal/token/token.go b/example/macro/macro2.grammar/macro2/internal/token/token.go new file mode 100644 index 00000000..bd4fc7cf --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/token/token.go @@ -0,0 +1,166 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +import ( + "fmt" + "strconv" + "unicode/utf8" +) + +type Token struct { + Type + Lit []byte + IgnoredPrefix []byte + Pos + ForeignAstNode interface{} + Foreign bool +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (p Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) +} + +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type + litMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +// CharLiteralValue returns the string value of the char literal. +func (t *Token) CharLiteralValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +// Float32Value returns the float32 value of the token or an error if the token literal does not +// denote a valid float32. +func (t *Token) Float32Value() (float32, error) { + if v, err := strconv.ParseFloat(string(t.Lit), 32); err != nil { + return 0, err + } else { + return float32(v), nil + } +} + +// Float64Value returns the float64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Float64Value() (float64, error) { + return strconv.ParseFloat(string(t.Lit), 64) +} + +// IDValue returns the string representation of an identifier token. +func (t *Token) IDValue() string { + return string(t.Lit) +} + +// Int32Value returns the int32 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int32Value() (int32, error) { + if v, err := strconv.ParseInt(string(t.Lit), 10, 64); err != nil { + return 0, err + } else { + return int32(v), nil + } +} + +// Int64Value returns the int64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int64Value() (int64, error) { + return strconv.ParseInt(string(t.Lit), 10, 64) +} + +// UTF8Rune decodes the UTF8 rune in the token literal. It returns utf8.RuneError if +// the token literal contains an invalid rune. +func (t *Token) UTF8Rune() (rune, error) { + r, _ := utf8.DecodeRune(t.Lit) + if r == utf8.RuneError { + err := fmt.Errorf("Invalid rune") + return r, err + } + return r, nil +} + +// StringValue returns the string value of the token literal. +func (t *Token) StringValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "Ω", + "Λ<;>", + "Λ", + "Λ", + "id", + "Λ<=>", + "μ", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "Ω": 1, + "Λ<;>": 2, + "Λ": 3, + "Λ": 4, + "id": 5, + "Λ<=>": 6, + "μ": 7, + }, + + litMap: map[string]Type{ + ";": 2, + "let": 3, + "define": 4, + "=": 6, + }, +} diff --git a/example/macro/macro2.grammar/macro2/internal/util/litconv.go b/example/macro/macro2.grammar/macro2/internal/util/litconv.go new file mode 100644 index 00000000..1aeb6166 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/util/litconv.go @@ -0,0 +1,108 @@ +// Code generated by gocc; DO NOT EDIT. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +/* Interface */ + +/* +Convert the literal value of a scanned token to rune +*/ +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +/* +Convert the literal value of a scanned token to int64 +*/ +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +/* +Convert the literal value of a scanned token to uint64 +*/ +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +/* Util */ + +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/example/macro/macro2.grammar/macro2/internal/util/rune.go b/example/macro/macro2.grammar/macro2/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/macro/macro2.grammar/macro2/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/macro/macro2.grammar/macro2/log/macro2.bnf b/example/macro/macro2.grammar/macro2/log/macro2.bnf new file mode 100644 index 00000000..dd1f5ce2 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/log/macro2.bnf @@ -0,0 +1,65 @@ +// +// Code generated by gocc preprocessor ; DO NOT EDIT. +// +!whitespace : ' ' | '\t' | '\n' | '\r' ; +_digit : '0'-'9' ; +_letter : 'a'-'z' | 'A'-'Z' | ( '\\' 'u' _hex { _hex } ) ; +_hex : _digit | ( 'a'-'f' ) | ('A' - 'F') ; +_idchar : _letter | _digit | '_'; +_x0 : 'α' ; +_x1 : 'β' _digit { _digit } ; +_x : 'α' | ( 'β' _digit { _digit } ); +id: + _x { _x0 | _x1 | 'γ' } +; +<< +func first_one(x string) []string { + fmt.Printf("start with this this one: %s\n", x) + return []string{x} +} +func add_one(c []string, x string) []string { + fmt.Printf("add to %q that %s\n", c, x) + return append([]string{x},c...) +} +func summary(v interface{}) string { + return fmt.Sprintf("ok, so we got <%q> as a final result.\n", v) +} +func definition(deftype, defname string, defval int64) (interface{}, error) { + fmt.Printf("Definition of variable <%s> with '%s' as %d\n", defname, deftype, defval) + return fmt.Sprintf("%s <- %d", defname, defval), nil +} +>> +StmtList : + Stmt_s + << +func() (retval interface{}, err error) { + fmt.Printf("%s", summary($0)); retval, err = 42, nil + return +}() + + >> +; +Stmt_s : + Stmt + << first_one($0s),nil >> + | + Stmt_s + ";" + Stmt + << add_one($0.([]string),$2s),nil >> +; +StmtPref: + "let" +| + "define" + +; +Stmt : + StmtPref + id + "=" + @ "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + << + definition($0s,$1s,$4.(int64)) + >> +; diff --git a/example/macro/macro2.grammar/macro2/macro2.go b/example/macro/macro2.grammar/macro2/macro2.go new file mode 100644 index 00000000..25aed95f --- /dev/null +++ b/example/macro/macro2.grammar/macro2/macro2.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package macro2 + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/errors" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/lexer" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/parser" + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/macro/macro2.grammar/macro2/main/macro2.go b/example/macro/macro2.grammar/macro2/main/macro2.go new file mode 100644 index 00000000..5d61883d --- /dev/null +++ b/example/macro/macro2.grammar/macro2/main/macro2.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + macro2 "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *macro2.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return macro2.NewParser().ParseLongestPrefix(lex) + } else { + res, err = macro2.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, macro2.NewLexerString(Text))) + } + if File > "" { + l, e := macro2.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, macro2.NewLexerString(str))) + } +} diff --git a/example/macro/macro2.grammar/macro2/util.go b/example/macro/macro2.grammar/macro2/util.go new file mode 100644 index 00000000..f0697f96 --- /dev/null +++ b/example/macro/macro2.grammar/macro2/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package macro2 + +import ( + "github.com/maxcalandrelli/gocc/example/macro/macro2.grammar/macro2/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/mail/lexer/lexer.go b/example/mail/lexer/lexer.go deleted file mode 100755 index c5109165..00000000 --- a/example/mail/lexer/lexer.go +++ /dev/null @@ -1,149 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package lexer - -import ( - "io/ioutil" - "unicode/utf8" - - "github.com/goccmack/gocc/example/mail/token" -) - -const ( - NoState = -1 - NumStates = 15 - NumSymbols = 33 -) - -type Lexer struct { - src []byte - pos int - line int - column int -} - -func NewLexer(src []byte) *Lexer { - lexer := &Lexer{ - src: src, - pos: 0, - line: 1, - column: 1, - } - return lexer -} - -func NewLexerFile(fpath string) (*Lexer, error) { - src, err := ioutil.ReadFile(fpath) - if err != nil { - return nil, err - } - return NewLexer(src), nil -} - -func (l *Lexer) Scan() (tok *token.Token) { - tok = new(token.Token) - if l.pos >= len(l.src) { - tok.Type = token.EOF - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column - return - } - start, startLine, startColumn, end := l.pos, l.line, l.column, 0 - tok.Type = token.INVALID - state, rune1, size := 0, rune(-1), 0 - for state != -1 { - if l.pos >= len(l.src) { - rune1 = -1 - } else { - rune1, size = utf8.DecodeRune(l.src[l.pos:]) - l.pos += size - } - - nextState := -1 - if rune1 != -1 { - nextState = TransTab[state](rune1) - } - state = nextState - - if state != -1 { - - switch rune1 { - case '\n': - l.line++ - l.column = 1 - case '\r': - l.column = 1 - case '\t': - l.column += 4 - default: - l.column++ - } - - switch { - case ActTab[state].Accept != -1: - tok.Type = ActTab[state].Accept - end = l.pos - case ActTab[state].Ignore != "": - start, startLine, startColumn = l.pos, l.line, l.column - state = 0 - if start >= len(l.src) { - tok.Type = token.EOF - } - - } - } else { - if tok.Type == token.INVALID { - end = l.pos - } - } - } - if end > start { - l.pos = end - tok.Lit = l.src[start:end] - } else { - tok.Lit = []byte{} - } - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn - - return -} - -func (l *Lexer) Reset() { - l.pos = 0 -} - -/* -Lexer symbols: -0: '@' -1: '!' -2: '#' -3: '$' -4: '%' -5: '&' -6: ''' -7: '*' -8: '+' -9: '-' -10: '/' -11: '=' -12: '?' -13: '^' -14: '_' -15: '`' -16: '{' -17: '|' -18: '}' -19: '~' -20: '.' -21: '\' -22: '"' -23: '"' -24: '\t' -25: '\n' -26: '\r' -27: ' ' -28: 'A'-'Z' -29: 'a'-'z' -30: '0'-'9' -31: \u0100-\U0010ffff -32: . -*/ diff --git a/example/mail/mail.grammar/mail/iface/mail.go b/example/mail/mail.grammar/mail/iface/mail.go new file mode 100644 index 00000000..8fbde76a --- /dev/null +++ b/example/mail/mail.grammar/mail/iface/mail.go @@ -0,0 +1,60 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/mail/mail.grammar/mail/internal/io/stream/internal/stream_impl.go b/example/mail/mail.grammar/mail/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/mail/mail.grammar/mail/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/mail/mail.grammar/mail/internal/io/stream/internal/stream_public.go b/example/mail/mail.grammar/mail/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/mail/mail.grammar/mail/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/mail/mail.grammar/mail/internal/io/stream/stream.go b/example/mail/mail.grammar/mail/internal/io/stream/stream.go new file mode 100644 index 00000000..5bca95d1 --- /dev/null +++ b/example/mail/mail.grammar/mail/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/mail/lexer/acttab.go b/example/mail/mail.grammar/mail/internal/lexer/acttab.go old mode 100755 new mode 100644 similarity index 63% rename from example/mail/lexer/acttab.go rename to example/mail/mail.grammar/mail/internal/lexer/acttab.go index 18794c88..ca737869 --- a/example/mail/lexer/acttab.go +++ b/example/mail/mail.grammar/mail/internal/lexer/acttab.go @@ -5,7 +5,7 @@ package lexer import ( "fmt" - "github.com/goccmack/gocc/example/mail/token" + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/token" ) type ActionTable [NumStates]ActionRow @@ -20,63 +20,63 @@ func (a ActionRow) String() string { } var ActTab = ActionTable{ - ActionRow{ // S0 + ActionRow{ // S0, Accept: 0, Ignore: "", }, - ActionRow{ // S1 + ActionRow{ // S1, Ignore("!whitespace") Accept: -1, Ignore: "!whitespace", }, - ActionRow{ // S2 + ActionRow{ // S2, Accept: 0, Ignore: "", }, - ActionRow{ // S3 + ActionRow{ // S3, Accept: 0, Ignore: "", }, - ActionRow{ // S4 + ActionRow{ // S4, Accept: 0, Ignore: "", }, - ActionRow{ // S5 + ActionRow{ // S5, Accept: 0, Ignore: "", }, - ActionRow{ // S6 + ActionRow{ // S6, Accept: 0, Ignore: "", }, - ActionRow{ // S7 + ActionRow{ // S7, Accept: 0, Ignore: "", }, - ActionRow{ // S8 + ActionRow{ // S8, Accept: 0, Ignore: "", }, - ActionRow{ // S9 + ActionRow{ // S9, Accept("addrspec") Accept: 2, Ignore: "", }, - ActionRow{ // S10 + ActionRow{ // S10, Accept: 0, Ignore: "", }, - ActionRow{ // S11 + ActionRow{ // S11, Accept: 0, Ignore: "", }, - ActionRow{ // S12 + ActionRow{ // S12, Accept: 0, Ignore: "", }, - ActionRow{ // S13 + ActionRow{ // S13, Accept: 0, Ignore: "", }, - ActionRow{ // S14 + ActionRow{ // S14, Accept("addrspec") Accept: 2, Ignore: "", }, diff --git a/example/mail/mail.grammar/mail/internal/lexer/lexer.go b/example/mail/mail.grammar/mail/internal/lexer/lexer.go new file mode 100644 index 00000000..941430cc --- /dev/null +++ b/example/mail/mail.grammar/mail/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/iface" + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/token" + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 15 + NumSymbols = 33 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/mail/lexer/transitiontable.go b/example/mail/mail.grammar/mail/internal/lexer/transitiontable.go old mode 100755 new mode 100644 similarity index 99% rename from example/mail/lexer/transitiontable.go rename to example/mail/mail.grammar/mail/internal/lexer/transitiontable.go index d3c1c3a4..349e9ec6 --- a/example/mail/lexer/transitiontable.go +++ b/example/mail/mail.grammar/mail/internal/lexer/transitiontable.go @@ -391,8 +391,9 @@ var TransTab = TransitionTable{ switch { case r == 64: // ['@','@'] return 5 + default: + return 7 } - return NoState }, // S12 func(r rune) int { diff --git a/example/mail/token/token.go b/example/mail/mail.grammar/mail/internal/token/token.go old mode 100755 new mode 100644 similarity index 67% rename from example/mail/token/token.go rename to example/mail/mail.grammar/mail/internal/token/token.go index 507c565f..8f52bb03 --- a/example/mail/token/token.go +++ b/example/mail/mail.grammar/mail/internal/token/token.go @@ -8,8 +8,11 @@ import ( type Token struct { Type - Lit []byte + Lit []byte + IgnoredPrefix []byte Pos + ForeignAstNode interface{} + Foreign bool } type Type int @@ -29,9 +32,24 @@ func (p Pos) String() string { return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) } +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + type TokenMap struct { typeMap []string idMap map[string]Type + litMap map[string]Type } func (m TokenMap) Id(tok Type) string { @@ -49,8 +67,7 @@ func (m TokenMap) Type(tok string) Type { } func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) } func (m TokenMap) StringType(typ Type) string { @@ -60,13 +77,15 @@ func (m TokenMap) StringType(typ Type) string { var TokMap = TokenMap{ typeMap: []string{ "INVALID", - "$", + "Ω", "addrspec", }, idMap: map[string]Type{ "INVALID": 0, - "$": 1, + "Ω": 1, "addrspec": 2, }, + + litMap: map[string]Type{}, } diff --git a/example/mail/mail.grammar/mail/internal/util/litconv.go b/example/mail/mail.grammar/mail/internal/util/litconv.go new file mode 100644 index 00000000..1aeb6166 --- /dev/null +++ b/example/mail/mail.grammar/mail/internal/util/litconv.go @@ -0,0 +1,108 @@ +// Code generated by gocc; DO NOT EDIT. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +/* Interface */ + +/* +Convert the literal value of a scanned token to rune +*/ +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +/* +Convert the literal value of a scanned token to int64 +*/ +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +/* +Convert the literal value of a scanned token to uint64 +*/ +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +/* Util */ + +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/example/mail/mail.grammar/mail/internal/util/rune.go b/example/mail/mail.grammar/mail/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/mail/mail.grammar/mail/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/mail/mail.grammar/mail/mail.go b/example/mail/mail.grammar/mail/mail.go new file mode 100644 index 00000000..f86055e2 --- /dev/null +++ b/example/mail/mail.grammar/mail/mail.go @@ -0,0 +1,42 @@ +// Code generated by gocc; DO NOT EDIT. + +package mail + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/lexer" + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + Lexer = lexer.Lexer +) + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/mail/mail.grammar/mail/util.go b/example/mail/mail.grammar/mail/util.go new file mode 100644 index 00000000..789b9dd1 --- /dev/null +++ b/example/mail/mail.grammar/mail/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package mail + +import ( + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/mail/parser_test.go b/example/mail/parser_test.go index 581b7f6e..5c478df4 100644 --- a/example/mail/parser_test.go +++ b/example/mail/parser_test.go @@ -2,9 +2,7 @@ package mail import ( "testing" - - "github.com/goccmack/gocc/example/mail/lexer" - "github.com/goccmack/gocc/example/mail/token" + "github.com/maxcalandrelli/gocc/example/mail/mail.grammar/mail" ) var testData1 = map[string]bool{ @@ -16,14 +14,14 @@ var testData1 = map[string]bool{ func Test1(t *testing.T) { for input, ok := range testData1 { - l := lexer.NewLexer([]byte(input)) + l := mail.NewLexerString(input) tok := l.Scan() switch { - case tok.Type == token.INVALID: + case tok.Type == mail.INVALID: if ok { t.Errorf("%s", input) } - case tok.Type == token.TokMap.Type("addrspec"): + case tok.Type == mail.GetTokenMap().Type("addrspec"): if !ok { t.Errorf("%s", input) } @@ -46,9 +44,9 @@ var testData2 = ` ` func Test2(t *testing.T) { - l := lexer.NewLexer([]byte(testData2)) + l := mail.NewLexerString(testData2) num := 0 - for tok := l.Scan(); tok.Type == token.TokMap.Type("addrspec"); tok = l.Scan() { + for tok := l.Scan(); tok.Type == mail.GetTokenMap().Type("addrspec"); tok = l.Scan() { if string(tok.Lit) != checkData2[num] { t.Errorf("%s != %s", string(tok.Lit), checkData2[num]) } diff --git a/example/mail/util/rune.go b/example/mail/util/rune.go deleted file mode 100755 index bd8523a4..00000000 --- a/example/mail/util/rune.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package util - -import ( - "fmt" -) - -func RuneToString(r rune) string { - if r >= 0x20 && r < 0x7f { - return fmt.Sprintf("'%c'", r) - } - switch r { - case 0x07: - return "'\\a'" - case 0x08: - return "'\\b'" - case 0x0C: - return "'\\f'" - case 0x0A: - return "'\\n'" - case 0x0D: - return "'\\r'" - case 0x09: - return "'\\t'" - case 0x0b: - return "'\\v'" - case 0x5c: - return "'\\\\\\'" - case 0x27: - return "'\\''" - case 0x22: - return "'\\\"'" - } - if r < 0x10000 { - return fmt.Sprintf("\\u%04x", r) - } - return fmt.Sprintf("\\U%08x", r) -} diff --git a/example/nolexer/errors/errors.go b/example/nolexer/errors/errors.go deleted file mode 100755 index f57f2f03..00000000 --- a/example/nolexer/errors/errors.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package errors - -import ( - "fmt" - "strings" - - "github.com/goccmack/gocc/example/nolexer/token" -) - -type ErrorSymbol interface { -} - -type Error struct { - Err error - ErrorToken *token.Token - ErrorSymbols []ErrorSymbol - ExpectedTokens []string - StackTop int -} - -func (e *Error) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "Error") - if e.Err != nil { - fmt.Fprintf(w, " %s\n", e.Err) - } else { - fmt.Fprintf(w, "\n") - } - fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) - fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) - fmt.Fprintf(w, "Expected one of: ") - for _, sym := range e.ExpectedTokens { - fmt.Fprintf(w, "%s ", sym) - } - fmt.Fprintf(w, "ErrorSymbol:\n") - for _, sym := range e.ErrorSymbols { - fmt.Fprintf(w, "%v\n", sym) - } - return w.String() -} - -func (e *Error) Error() string { - w := new(strings.Builder) - fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) - if e.Err != nil { - fmt.Fprintf(w, ": %+v", e.Err) - } else { - fmt.Fprintf(w, ", expected one of: ") - for _, expected := range e.ExpectedTokens { - fmt.Fprintf(w, "%s ", expected) - } - } - return w.String() -} diff --git a/example/nolexer/nolexer.bnf b/example/nolexer/nolexer.bnf index bf5e1f08..a3b1b1a3 100644 --- a/example/nolexer/nolexer.bnf +++ b/example/nolexer/nolexer.bnf @@ -1,20 +1,15 @@ << -import ( - "fmt" - - "github.com/goccmack/gocc/example/nolexer/token" -) >> Hello : Saying name << func () (Attrib, error) { - fmt.Println(string($1.(*token.Token).Lit)); - return nil, nil} () >> + fmt.Println(string($1.(*token.Token).Lit)); + return nil, nil} () >> ; Saying : "hello" << func () (Attrib, error) { - fmt.Print("hello "); + fmt.Print("hello "); return nil, nil} () >> | "hiya" << func () (Attrib, error) { - fmt.Print("hiya "); + fmt.Print("hiya "); return nil, nil} () >> - ; \ No newline at end of file + ; diff --git a/example/nolexer/nolexer.grammar/nolexer/iface/nolexer.go b/example/nolexer/nolexer.grammar/nolexer/iface/nolexer.go new file mode 100644 index 00000000..efd50a4d --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/iface/nolexer.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/errors" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/errors/errors.go b/example/nolexer/nolexer.grammar/nolexer/internal/errors/errors.go new file mode 100644 index 00000000..49ca2da2 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/errors/errors.go @@ -0,0 +1,56 @@ +// Code generated by gocc; DO NOT EDIT. + +package errors + +import ( + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/token" +) + +type ErrorSymbol interface { +} + +type Error struct { + Err error + ErrorToken *token.Token + ErrorSymbols []ErrorSymbol + ExpectedTokens []string + StackTop int +} + +func (e *Error) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error") + if e.Err != nil { + fmt.Fprintf(w, " %s\n", e.Err) + } else { + fmt.Fprintf(w, "\n") + } + fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) + fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) + fmt.Fprintf(w, "Expected one of: ") + for _, sym := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", sym) + } + fmt.Fprintf(w, "ErrorSymbol:\n") + for _, sym := range e.ErrorSymbols { + fmt.Fprintf(w, "%v\n", sym) + } + return w.String() +} + +func (e *Error) Error() string { + w := new(strings.Builder) + fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) + if e.Err != nil { + fmt.Fprintf(w, ": %+v", e.Err) + } else { + fmt.Fprintf(w, ", expected one of: ") + for _, expected := range e.ExpectedTokens { + fmt.Fprintf(w, "%s ", expected) + } + } + return w.String() +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/internal/stream_impl.go b/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/internal/stream_public.go b/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/stream.go b/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/stream.go new file mode 100644 index 00000000..2ab99c38 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/parser/action.go b/example/nolexer/nolexer.grammar/nolexer/internal/parser/action.go new file mode 100644 index 00000000..54bc55e9 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/parser/action.go @@ -0,0 +1,51 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" +) + +type action interface { + act() + String() string +} + +type ( + accept bool + shift int // value is next state index + reduce int // value is production index +) + +func (this accept) act() {} +func (this shift) act() {} +func (this reduce) act() {} + +func (this accept) Equal(that action) bool { + if _, ok := that.(accept); ok { + return true + } + return false +} + +func (this reduce) Equal(that action) bool { + that1, ok := that.(reduce) + if !ok { + return false + } + return this == that1 +} + +func (this shift) Equal(that action) bool { + that1, ok := that.(shift) + if !ok { + return false + } + return this == that1 +} + +func (this accept) String() string { return "accept(0)" } +func (this shift) String() string { return fmt.Sprintf("shift:%d", this) } +func (this reduce) String() string { + return fmt.Sprintf("reduce:%d(%s)", this, productionsTable[this].String) +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/parser/actiontable.go b/example/nolexer/nolexer.grammar/nolexer/internal/parser/actiontable.go new file mode 100644 index 00000000..eb8558e1 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/parser/actiontable.go @@ -0,0 +1,91 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // name + shift(3), // "hello" + shift(4), // "hiya" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + nil, // name + nil, // "hello" + nil, // "hiya" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(5), // name + nil, // "hello" + nil, // "hiya" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(2), // name, reduce: Saying + nil, // "hello" + nil, // "hiya" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(3), // name, reduce: Saying + nil, // "hello" + nil, // "hiya" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: Hello + nil, // name + nil, // "hello" + nil, // "hiya" + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/parser/gototable.go b/example/nolexer/nolexer.grammar/nolexer/internal/parser/gototable.go new file mode 100644 index 00000000..85887079 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/parser/gototable.go @@ -0,0 +1,43 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 3 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/parser/parser.go b/example/nolexer/nolexer.grammar/nolexer/internal/parser/parser.go new file mode 100644 index 00000000..ec5a2636 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/parser/parser.go @@ -0,0 +1,353 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/iface" + parseError "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/errors" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/token" +) + +const ( + numProductions = 4 + numStates = 6 + numSymbols = 8 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = longest + p.isNonDeterministic = false + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/parser/productionstable.go b/example/nolexer/nolexer.grammar/nolexer/internal/parser/productionstable.go new file mode 100644 index 00000000..c7b63634 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/parser/productionstable.go @@ -0,0 +1,110 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/token" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Hello : Π name << func () (Attrib, error) { + fmt.Println(string($1.(*token.Token).Lit)); + return nil, nil} () >>`, + Id: "Hello", + NTType: 1, + Index: 1, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return func() (Attrib, error) { + fmt.Println(string(X[1].(*token.Token).Lit)) + return nil, nil + }() + }, + }, + ProdTabEntry{ + String: `Saying : Λ << func () (Attrib, error) { + fmt.Print("hello "); + return nil, nil} () >>`, + Id: "Saying", + NTType: 2, + Index: 2, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return func() (Attrib, error) { + fmt.Print("hello ") + return nil, nil + }() + }, + }, + ProdTabEntry{ + String: `Saying : Λ << func () (Attrib, error) { + fmt.Print("hiya "); + return nil, nil} () >>`, + Id: "Saying", + NTType: 2, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return func() (Attrib, error) { + fmt.Print("hiya ") + return nil, nil + }() + }, + }, +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/token/token.go b/example/nolexer/nolexer.grammar/nolexer/internal/token/token.go new file mode 100644 index 00000000..6bec1488 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/token/token.go @@ -0,0 +1,101 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +import ( + "fmt" +) + +type Token struct { + Type + Lit []byte + IgnoredPrefix []byte + Pos + ForeignAstNode interface{} + Foreign bool +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (p Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) +} + +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type + litMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + if typ, exist := m.litMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "Ω", + "name", + "Λ", + "Λ", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "Ω": 1, + "name": 2, + "Λ": 3, + "Λ": 4, + }, + + litMap: map[string]Type{ + "hello": 3, + "hiya": 4, + }, +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/util/litconv.go b/example/nolexer/nolexer.grammar/nolexer/internal/util/litconv.go new file mode 100644 index 00000000..1aeb6166 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/util/litconv.go @@ -0,0 +1,108 @@ +// Code generated by gocc; DO NOT EDIT. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +/* Interface */ + +/* +Convert the literal value of a scanned token to rune +*/ +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +/* +Convert the literal value of a scanned token to int64 +*/ +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +/* +Convert the literal value of a scanned token to uint64 +*/ +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +/* Util */ + +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/example/nolexer/nolexer.grammar/nolexer/internal/util/rune.go b/example/nolexer/nolexer.grammar/nolexer/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/nolexer/nolexer.grammar/nolexer/nolexer.go b/example/nolexer/nolexer.grammar/nolexer/nolexer.go new file mode 100644 index 00000000..73cb5264 --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/nolexer.go @@ -0,0 +1,31 @@ +// Code generated by gocc; DO NOT EDIT. + +package nolexer + +import ( + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/errors" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/parser" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/nolexer/nolexer.grammar/nolexer/util.go b/example/nolexer/nolexer.grammar/nolexer/util.go new file mode 100644 index 00000000..ab8156bf --- /dev/null +++ b/example/nolexer/nolexer.grammar/nolexer/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package nolexer + +import ( + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/nolexer/nolexer_test.go b/example/nolexer/nolexer_test.go index 1504ae14..92b4878f 100644 --- a/example/nolexer/nolexer_test.go +++ b/example/nolexer/nolexer_test.go @@ -3,13 +3,13 @@ package nolexer import ( "testing" - "github.com/goccmack/gocc/example/nolexer/parser" - "github.com/goccmack/gocc/example/nolexer/scanner" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer" + "github.com/maxcalandrelli/gocc/example/nolexer/scanner" ) func Test1(t *testing.T) { S := scanner.NewString("hiya world") - P := parser.NewParser() + P := nolexer.NewParser() if _, e := P.Parse(S); e != nil { t.Error(e.Error()) } @@ -17,7 +17,7 @@ func Test1(t *testing.T) { func Test2(t *testing.T) { S := scanner.NewString("hello world") - P := parser.NewParser() + P := nolexer.NewParser() if _, e := P.Parse(S); e != nil { t.Error(e.Error()) } diff --git a/example/nolexer/parser/actiontable.go b/example/nolexer/parser/actiontable.go deleted file mode 100755 index 12b68618..00000000 --- a/example/nolexer/parser/actiontable.go +++ /dev/null @@ -1,74 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - actionTable [numStates]actionRow - actionRow struct { - canRecover bool - actions [numSymbols]action - } -) - -var actionTab = actionTable{ - actionRow{ // S0 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // name - shift(3), // hello - shift(4), // hiya - }, - }, - actionRow{ // S1 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - accept(true), // $ - nil, // name - nil, // hello - nil, // hiya - }, - }, - actionRow{ // S2 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(5), // name - nil, // hello - nil, // hiya - }, - }, - actionRow{ // S3 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(2), // name, reduce: Saying - nil, // hello - nil, // hiya - }, - }, - actionRow{ // S4 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - reduce(3), // name, reduce: Saying - nil, // hello - nil, // hiya - }, - }, - actionRow{ // S5 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(1), // $, reduce: Hello - nil, // name - nil, // hello - nil, // hiya - }, - }, -} diff --git a/example/nolexer/parser/gototable.go b/example/nolexer/parser/gototable.go deleted file mode 100755 index 4266b515..00000000 --- a/example/nolexer/parser/gototable.go +++ /dev/null @@ -1,43 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -const numNTSymbols = 3 - -type ( - gotoTable [numStates]gotoRow - gotoRow [numNTSymbols]int -) - -var gotoTab = gotoTable{ - gotoRow{ // S0 - -1, // S' - 1, // Hello - 2, // Saying - }, - gotoRow{ // S1 - -1, // S' - -1, // Hello - -1, // Saying - }, - gotoRow{ // S2 - -1, // S' - -1, // Hello - -1, // Saying - }, - gotoRow{ // S3 - -1, // S' - -1, // Hello - -1, // Saying - }, - gotoRow{ // S4 - -1, // S' - -1, // Hello - -1, // Saying - }, - gotoRow{ // S5 - -1, // S' - -1, // Hello - -1, // Saying - }, -} diff --git a/example/nolexer/parser/parser.go b/example/nolexer/parser/parser.go deleted file mode 100755 index 3d8f0a76..00000000 --- a/example/nolexer/parser/parser.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "fmt" - "strings" - - parseError "github.com/goccmack/gocc/example/nolexer/errors" - "github.com/goccmack/gocc/example/nolexer/token" -) - -const ( - numProductions = 4 - numStates = 6 - numSymbols = 8 -) - -// Stack - -type stack struct { - state []int - attrib []Attrib -} - -const iNITIAL_STACK_SIZE = 100 - -func newStack() *stack { - return &stack{ - state: make([]int, 0, iNITIAL_STACK_SIZE), - attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), - } -} - -func (s *stack) reset() { - s.state = s.state[:0] - s.attrib = s.attrib[:0] -} - -func (s *stack) push(state int, a Attrib) { - s.state = append(s.state, state) - s.attrib = append(s.attrib, a) -} - -func (s *stack) top() int { - return s.state[len(s.state)-1] -} - -func (s *stack) peek(pos int) int { - return s.state[pos] -} - -func (s *stack) topIndex() int { - return len(s.state) - 1 -} - -func (s *stack) popN(items int) []Attrib { - lo, hi := len(s.state)-items, len(s.state) - - attrib := s.attrib[lo:hi] - - s.state = s.state[:lo] - s.attrib = s.attrib[:lo] - - return attrib -} - -func (s *stack) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "stack:\n") - for i, st := range s.state { - fmt.Fprintf(w, "\t%d: %d , ", i, st) - if s.attrib[i] == nil { - fmt.Fprintf(w, "nil") - } else { - switch attr := s.attrib[i].(type) { - case *token.Token: - fmt.Fprintf(w, "%s", attr.Lit) - default: - fmt.Fprintf(w, "%v", attr) - } - } - fmt.Fprintf(w, "\n") - } - return w.String() -} - -// Parser - -type Parser struct { - stack *stack - nextToken *token.Token - pos int -} - -type Scanner interface { - Scan() (tok *token.Token) -} - -func NewParser() *Parser { - p := &Parser{stack: newStack()} - p.Reset() - return p -} - -func (p *Parser) Reset() { - p.stack.reset() - p.stack.push(0, nil) -} - -func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { - errorAttrib = &parseError.Error{ - Err: err, - ErrorToken: p.nextToken, - ErrorSymbols: p.popNonRecoveryStates(), - ExpectedTokens: make([]string, 0, 8), - } - for t, action := range actionTab[p.stack.top()].actions { - if action != nil { - errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) - } - } - - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { - p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift - } else { - return - } - - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - for !recovered && p.nextToken.Type != token.EOF { - p.nextToken = scanner.Scan() - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - } - - return -} - -func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { - if rs, ok := p.firstRecoveryState(); ok { - errorSymbols := p.stack.popN(p.stack.topIndex() - rs) - removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) - for i, e := range errorSymbols { - removedAttribs[i] = e - } - } else { - removedAttribs = []parseError.ErrorSymbol{} - } - return -} - -// recoveryState points to the highest state on the stack, which can recover -func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { - recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover - for recoveryState > 0 && !canRecover { - recoveryState-- - canRecover = actionTab[p.stack.peek(recoveryState)].canRecover - } - return -} - -func (p *Parser) newError(err error) error { - e := &parseError.Error{ - Err: err, - StackTop: p.stack.top(), - ErrorToken: p.nextToken, - } - actRow := actionTab[p.stack.top()] - for i, t := range actRow.actions { - if t != nil { - e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) - } - } - return e -} - -func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { - p.Reset() - p.nextToken = scanner.Scan() - for acc := false; !acc; { - action := actionTab[p.stack.top()].actions[p.nextToken.Type] - if action == nil { - if recovered, errAttrib := p.Error(nil, scanner); !recovered { - p.nextToken = errAttrib.ErrorToken - return nil, p.newError(nil) - } - if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { - panic("Error recovery led to invalid action") - } - } - - switch act := action.(type) { - case accept: - res = p.stack.popN(1)[0] - acc = true - case shift: - p.stack.push(int(act), p.nextToken) - p.nextToken = scanner.Scan() - case reduce: - prod := productionsTable[int(act)] - attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) - if err != nil { - return nil, p.newError(err) - } else { - p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) - } - default: - panic("unknown action: " + action.String()) - } - } - return res, nil -} diff --git a/example/nolexer/parser/productionstable.go b/example/nolexer/parser/productionstable.go deleted file mode 100755 index ea99a9ef..00000000 --- a/example/nolexer/parser/productionstable.go +++ /dev/null @@ -1,82 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "fmt" - - "github.com/goccmack/gocc/example/nolexer/token" -) - -type ( - //TODO: change type and variable names to be consistent with other tables - ProdTab [numProductions]ProdTabEntry - ProdTabEntry struct { - String string - Id string - NTType int - Index int - NumSymbols int - ReduceFunc func([]Attrib) (Attrib, error) - } - Attrib interface { - } -) - -var productionsTable = ProdTab{ - ProdTabEntry{ - String: `S' : Hello << >>`, - Id: "S'", - NTType: 0, - Index: 0, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `Hello : Saying name << func () (Attrib, error) { - fmt.Println(string(X[1].(*token.Token).Lit)); - return nil, nil} () >>`, - Id: "Hello", - NTType: 1, - Index: 1, - NumSymbols: 2, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return func() (Attrib, error) { - fmt.Println(string(X[1].(*token.Token).Lit)) - return nil, nil - }() - }, - }, - ProdTabEntry{ - String: `Saying : "hello" << func () (Attrib, error) { - fmt.Print("hello "); - return nil, nil} () >>`, - Id: "Saying", - NTType: 2, - Index: 2, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return func() (Attrib, error) { - fmt.Print("hello ") - return nil, nil - }() - }, - }, - ProdTabEntry{ - String: `Saying : "hiya" << func () (Attrib, error) { - fmt.Print("hiya "); - return nil, nil} () >>`, - Id: "Saying", - NTType: 2, - Index: 3, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return func() (Attrib, error) { - fmt.Print("hiya ") - return nil, nil - }() - }, - }, -} diff --git a/example/nolexer/scanner/scanner.go b/example/nolexer/scanner/scanner.go index 2fe46fd8..e85b2aed 100644 --- a/example/nolexer/scanner/scanner.go +++ b/example/nolexer/scanner/scanner.go @@ -1,7 +1,7 @@ package scanner import ( - "github.com/goccmack/gocc/example/nolexer/token" + "github.com/maxcalandrelli/gocc/example/nolexer/nolexer.grammar/nolexer/iface" ) type Scanner struct { @@ -35,11 +35,11 @@ func (S *Scanner) scanId() string { return string(S.src[pos : S.pos-1]) } -func (S *Scanner) Scan() (tok *token.Token) { +func (S *Scanner) Scan() (tok *iface.Token) { S.skipWhiteSpace() if S.pos >= len(S.src) { - return &token.Token{Type: token.EOF} + return &iface.Token{Type: iface.EOF} } pos := S.pos @@ -47,16 +47,16 @@ func (S *Scanner) Scan() (tok *token.Token) { lit := S.scanId() switch lit { case "hiya": - return &token.Token{Type: token.TokMap.Type("hiya"), + return &iface.Token{Type: iface.GetTokenMap().Type("hiya"), Lit: []byte("hiya"), - Pos: token.Pos{Offset: pos}} + Pos: iface.Pos{Offset: pos}} case "hello": - return &token.Token{Type: token.TokMap.Type("hello"), + return &iface.Token{Type: iface.GetTokenMap().Type("hello"), Lit: []byte("hello"), - Pos: token.Pos{Offset: pos}} + Pos: iface.Pos{Offset: pos}} default: - return &token.Token{Type: token.TokMap.Type("name"), + return &iface.Token{Type: iface.GetTokenMap().Type("name"), Lit: []byte(lit), - Pos: token.Pos{Offset: pos}} + Pos: iface.Pos{Offset: pos}} } } diff --git a/example/nolexer/util/rune.go b/example/nolexer/util/rune.go deleted file mode 100755 index bd8523a4..00000000 --- a/example/nolexer/util/rune.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package util - -import ( - "fmt" -) - -func RuneToString(r rune) string { - if r >= 0x20 && r < 0x7f { - return fmt.Sprintf("'%c'", r) - } - switch r { - case 0x07: - return "'\\a'" - case 0x08: - return "'\\b'" - case 0x0C: - return "'\\f'" - case 0x0A: - return "'\\n'" - case 0x0D: - return "'\\r'" - case 0x09: - return "'\\t'" - case 0x0b: - return "'\\v'" - case 0x5c: - return "'\\\\\\'" - case 0x27: - return "'\\''" - case 0x22: - return "'\\\"'" - } - if r < 0x10000 { - return fmt.Sprintf("\\u%04x", r) - } - return fmt.Sprintf("\\U%08x", r) -} diff --git a/example/rr/errors/errors.go b/example/rr/errors/errors.go deleted file mode 100755 index 998d3b3f..00000000 --- a/example/rr/errors/errors.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package errors - -import ( - "fmt" - "strings" - - "github.com/goccmack/gocc/example/rr/token" -) - -type ErrorSymbol interface { -} - -type Error struct { - Err error - ErrorToken *token.Token - ErrorSymbols []ErrorSymbol - ExpectedTokens []string - StackTop int -} - -func (e *Error) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "Error") - if e.Err != nil { - fmt.Fprintf(w, " %s\n", e.Err) - } else { - fmt.Fprintf(w, "\n") - } - fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) - fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) - fmt.Fprintf(w, "Expected one of: ") - for _, sym := range e.ExpectedTokens { - fmt.Fprintf(w, "%s ", sym) - } - fmt.Fprintf(w, "ErrorSymbol:\n") - for _, sym := range e.ErrorSymbols { - fmt.Fprintf(w, "%v\n", sym) - } - return w.String() -} - -func (e *Error) Error() string { - w := new(strings.Builder) - fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) - if e.Err != nil { - fmt.Fprintf(w, ": %+v", e.Err) - } else { - fmt.Fprintf(w, ", expected one of: ") - for _, expected := range e.ExpectedTokens { - fmt.Fprintf(w, "%s ", expected) - } - } - return w.String() -} diff --git a/example/rr/lexer/lexer.go b/example/rr/lexer/lexer.go deleted file mode 100755 index 68f06ea0..00000000 --- a/example/rr/lexer/lexer.go +++ /dev/null @@ -1,123 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package lexer - -import ( - "io/ioutil" - "unicode/utf8" - - "github.com/goccmack/gocc/example/rr/token" -) - -const ( - NoState = -1 - NumStates = 4 - NumSymbols = 7 -) - -type Lexer struct { - src []byte - pos int - line int - column int -} - -func NewLexer(src []byte) *Lexer { - lexer := &Lexer{ - src: src, - pos: 0, - line: 1, - column: 1, - } - return lexer -} - -func NewLexerFile(fpath string) (*Lexer, error) { - src, err := ioutil.ReadFile(fpath) - if err != nil { - return nil, err - } - return NewLexer(src), nil -} - -func (l *Lexer) Scan() (tok *token.Token) { - tok = new(token.Token) - if l.pos >= len(l.src) { - tok.Type = token.EOF - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column - return - } - start, startLine, startColumn, end := l.pos, l.line, l.column, 0 - tok.Type = token.INVALID - state, rune1, size := 0, rune(-1), 0 - for state != -1 { - if l.pos >= len(l.src) { - rune1 = -1 - } else { - rune1, size = utf8.DecodeRune(l.src[l.pos:]) - l.pos += size - } - - nextState := -1 - if rune1 != -1 { - nextState = TransTab[state](rune1) - } - state = nextState - - if state != -1 { - - switch rune1 { - case '\n': - l.line++ - l.column = 1 - case '\r': - l.column = 1 - case '\t': - l.column += 4 - default: - l.column++ - } - - switch { - case ActTab[state].Accept != -1: - tok.Type = ActTab[state].Accept - end = l.pos - case ActTab[state].Ignore != "": - start, startLine, startColumn = l.pos, l.line, l.column - state = 0 - if start >= len(l.src) { - tok.Type = token.EOF - } - - } - } else { - if tok.Type == token.INVALID { - end = l.pos - } - } - } - if end > start { - l.pos = end - tok.Lit = l.src[start:end] - } else { - tok.Lit = []byte{} - } - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn - - return -} - -func (l *Lexer) Reset() { - l.pos = 0 -} - -/* -Lexer symbols: -0: 'a' -1: 'c' -2: ' ' -3: '\t' -4: '\n' -5: '\r' -6: . -*/ diff --git a/example/rr/parser/actiontable.go b/example/rr/parser/actiontable.go deleted file mode 100755 index c11c48b1..00000000 --- a/example/rr/parser/actiontable.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - actionTable [numStates]actionRow - actionRow struct { - canRecover bool - actions [numSymbols]action - } -) - -var actionTab = actionTable{ - actionRow{ // S0 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(4), // a - shift(5), // c - }, - }, - actionRow{ // S1 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - accept(true), // $ - nil, // a - nil, // c - }, - }, - actionRow{ // S2 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(1), // $, reduce: RR - shift(6), // a - nil, // c - }, - }, - actionRow{ // S3 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(2), // $, reduce: RR - nil, // a - nil, // c - }, - }, - actionRow{ // S4 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(3), // $, reduce: B - reduce(4), // a, reduce: A - nil, // c - }, - }, - actionRow{ // S5 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(6), // $, reduce: A - reduce(6), // a, reduce: A - nil, // c - }, - }, - actionRow{ // S6 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(5), // $, reduce: A - reduce(5), // a, reduce: A - nil, // c - }, - }, -} diff --git a/example/rr/parser/gototable.go b/example/rr/parser/gototable.go deleted file mode 100755 index be09ff64..00000000 --- a/example/rr/parser/gototable.go +++ /dev/null @@ -1,55 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -const numNTSymbols = 4 - -type ( - gotoTable [numStates]gotoRow - gotoRow [numNTSymbols]int -) - -var gotoTab = gotoTable{ - gotoRow{ // S0 - -1, // S' - 1, // RR - 3, // B - 2, // A - }, - gotoRow{ // S1 - -1, // S' - -1, // RR - -1, // B - -1, // A - }, - gotoRow{ // S2 - -1, // S' - -1, // RR - -1, // B - -1, // A - }, - gotoRow{ // S3 - -1, // S' - -1, // RR - -1, // B - -1, // A - }, - gotoRow{ // S4 - -1, // S' - -1, // RR - -1, // B - -1, // A - }, - gotoRow{ // S5 - -1, // S' - -1, // RR - -1, // B - -1, // A - }, - gotoRow{ // S6 - -1, // S' - -1, // RR - -1, // B - -1, // A - }, -} diff --git a/example/rr/parser/parser.go b/example/rr/parser/parser.go deleted file mode 100755 index bab4383a..00000000 --- a/example/rr/parser/parser.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "fmt" - "strings" - - parseError "github.com/goccmack/gocc/example/rr/errors" - "github.com/goccmack/gocc/example/rr/token" -) - -const ( - numProductions = 7 - numStates = 7 - numSymbols = 8 -) - -// Stack - -type stack struct { - state []int - attrib []Attrib -} - -const iNITIAL_STACK_SIZE = 100 - -func newStack() *stack { - return &stack{ - state: make([]int, 0, iNITIAL_STACK_SIZE), - attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), - } -} - -func (s *stack) reset() { - s.state = s.state[:0] - s.attrib = s.attrib[:0] -} - -func (s *stack) push(state int, a Attrib) { - s.state = append(s.state, state) - s.attrib = append(s.attrib, a) -} - -func (s *stack) top() int { - return s.state[len(s.state)-1] -} - -func (s *stack) peek(pos int) int { - return s.state[pos] -} - -func (s *stack) topIndex() int { - return len(s.state) - 1 -} - -func (s *stack) popN(items int) []Attrib { - lo, hi := len(s.state)-items, len(s.state) - - attrib := s.attrib[lo:hi] - - s.state = s.state[:lo] - s.attrib = s.attrib[:lo] - - return attrib -} - -func (s *stack) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "stack:\n") - for i, st := range s.state { - fmt.Fprintf(w, "\t%d: %d , ", i, st) - if s.attrib[i] == nil { - fmt.Fprintf(w, "nil") - } else { - switch attr := s.attrib[i].(type) { - case *token.Token: - fmt.Fprintf(w, "%s", attr.Lit) - default: - fmt.Fprintf(w, "%v", attr) - } - } - fmt.Fprintf(w, "\n") - } - return w.String() -} - -// Parser - -type Parser struct { - stack *stack - nextToken *token.Token - pos int -} - -type Scanner interface { - Scan() (tok *token.Token) -} - -func NewParser() *Parser { - p := &Parser{stack: newStack()} - p.Reset() - return p -} - -func (p *Parser) Reset() { - p.stack.reset() - p.stack.push(0, nil) -} - -func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { - errorAttrib = &parseError.Error{ - Err: err, - ErrorToken: p.nextToken, - ErrorSymbols: p.popNonRecoveryStates(), - ExpectedTokens: make([]string, 0, 8), - } - for t, action := range actionTab[p.stack.top()].actions { - if action != nil { - errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) - } - } - - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { - p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift - } else { - return - } - - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - for !recovered && p.nextToken.Type != token.EOF { - p.nextToken = scanner.Scan() - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - } - - return -} - -func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { - if rs, ok := p.firstRecoveryState(); ok { - errorSymbols := p.stack.popN(p.stack.topIndex() - rs) - removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) - for i, e := range errorSymbols { - removedAttribs[i] = e - } - } else { - removedAttribs = []parseError.ErrorSymbol{} - } - return -} - -// recoveryState points to the highest state on the stack, which can recover -func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { - recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover - for recoveryState > 0 && !canRecover { - recoveryState-- - canRecover = actionTab[p.stack.peek(recoveryState)].canRecover - } - return -} - -func (p *Parser) newError(err error) error { - e := &parseError.Error{ - Err: err, - StackTop: p.stack.top(), - ErrorToken: p.nextToken, - } - actRow := actionTab[p.stack.top()] - for i, t := range actRow.actions { - if t != nil { - e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) - } - } - return e -} - -func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { - p.Reset() - p.nextToken = scanner.Scan() - for acc := false; !acc; { - action := actionTab[p.stack.top()].actions[p.nextToken.Type] - if action == nil { - if recovered, errAttrib := p.Error(nil, scanner); !recovered { - p.nextToken = errAttrib.ErrorToken - return nil, p.newError(nil) - } - if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { - panic("Error recovery led to invalid action") - } - } - - switch act := action.(type) { - case accept: - res = p.stack.popN(1)[0] - acc = true - case shift: - p.stack.push(int(act), p.nextToken) - p.nextToken = scanner.Scan() - case reduce: - prod := productionsTable[int(act)] - attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) - if err != nil { - return nil, p.newError(err) - } else { - p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) - } - default: - panic("unknown action: " + action.String()) - } - } - return res, nil -} diff --git a/example/rr/parser/productionstable.go b/example/rr/parser/productionstable.go deleted file mode 100755 index aa11a461..00000000 --- a/example/rr/parser/productionstable.go +++ /dev/null @@ -1,91 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - //TODO: change type and variable names to be consistent with other tables - ProdTab [numProductions]ProdTabEntry - ProdTabEntry struct { - String string - Id string - NTType int - Index int - NumSymbols int - ReduceFunc func([]Attrib) (Attrib, error) - } - Attrib interface { - } -) - -var productionsTable = ProdTab{ - ProdTabEntry{ - String: `S' : RR << >>`, - Id: "S'", - NTType: 0, - Index: 0, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `RR : A << >>`, - Id: "RR", - NTType: 1, - Index: 1, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `RR : B << >>`, - Id: "RR", - NTType: 1, - Index: 2, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `B : a << "B ", nil >>`, - Id: "B", - NTType: 2, - Index: 3, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return "B ", nil - }, - }, - ProdTabEntry{ - String: `A : a << "A0 ", nil >>`, - Id: "A", - NTType: 3, - Index: 4, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return "A0 ", nil - }, - }, - ProdTabEntry{ - String: `A : A a << "A1 ", nil >>`, - Id: "A", - NTType: 3, - Index: 5, - NumSymbols: 2, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return "A1 ", nil - }, - }, - ProdTabEntry{ - String: `A : c << "A2 ", nil >>`, - Id: "A", - NTType: 3, - Index: 6, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return "A2 ", nil - }, - }, -} diff --git a/example/rr/rr.grammar/rr/iface/rr.go b/example/rr/rr.grammar/rr/iface/rr.go new file mode 100644 index 00000000..45264f7a --- /dev/null +++ b/example/rr/rr.grammar/rr/iface/rr.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/errors" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/astx/errors/errors.go b/example/rr/rr.grammar/rr/internal/errors/errors.go old mode 100755 new mode 100644 similarity index 94% rename from example/astx/errors/errors.go rename to example/rr/rr.grammar/rr/internal/errors/errors.go index 640214b0..2faf2534 --- a/example/astx/errors/errors.go +++ b/example/rr/rr.grammar/rr/internal/errors/errors.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/example/astx/token" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/token" ) type ErrorSymbol interface { diff --git a/example/rr/rr.grammar/rr/internal/io/stream/internal/stream_impl.go b/example/rr/rr.grammar/rr/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/rr/rr.grammar/rr/internal/io/stream/internal/stream_public.go b/example/rr/rr.grammar/rr/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/rr/rr.grammar/rr/internal/io/stream/stream.go b/example/rr/rr.grammar/rr/internal/io/stream/stream.go new file mode 100644 index 00000000..c1d75800 --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/rr/lexer/acttab.go b/example/rr/rr.grammar/rr/internal/lexer/acttab.go old mode 100755 new mode 100644 similarity index 69% rename from example/rr/lexer/acttab.go rename to example/rr/rr.grammar/rr/internal/lexer/acttab.go index c02f6b59..d0a104eb --- a/example/rr/lexer/acttab.go +++ b/example/rr/rr.grammar/rr/internal/lexer/acttab.go @@ -5,7 +5,7 @@ package lexer import ( "fmt" - "github.com/goccmack/gocc/example/rr/token" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/token" ) type ActionTable [NumStates]ActionRow @@ -20,19 +20,19 @@ func (a ActionRow) String() string { } var ActTab = ActionTable{ - ActionRow{ // S0 + ActionRow{ // S0, Accept: 0, Ignore: "", }, - ActionRow{ // S1 + ActionRow{ // S1, Ignore("!whitespace") Accept: -1, Ignore: "!whitespace", }, - ActionRow{ // S2 + ActionRow{ // S2, Accept("a") Accept: 2, Ignore: "", }, - ActionRow{ // S3 + ActionRow{ // S3, Accept("c") Accept: 3, Ignore: "", }, diff --git a/example/rr/rr.grammar/rr/internal/lexer/lexer.go b/example/rr/rr.grammar/rr/internal/lexer/lexer.go new file mode 100644 index 00000000..521eb27e --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/iface" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/token" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 4 + NumSymbols = 7 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/rr/lexer/transitiontable.go b/example/rr/rr.grammar/rr/internal/lexer/transitiontable.go old mode 100755 new mode 100644 similarity index 100% rename from example/rr/lexer/transitiontable.go rename to example/rr/rr.grammar/rr/internal/lexer/transitiontable.go diff --git a/example/rr/rr.grammar/rr/internal/parser/action.go b/example/rr/rr.grammar/rr/internal/parser/action.go new file mode 100644 index 00000000..54bc55e9 --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/parser/action.go @@ -0,0 +1,51 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" +) + +type action interface { + act() + String() string +} + +type ( + accept bool + shift int // value is next state index + reduce int // value is production index +) + +func (this accept) act() {} +func (this shift) act() {} +func (this reduce) act() {} + +func (this accept) Equal(that action) bool { + if _, ok := that.(accept); ok { + return true + } + return false +} + +func (this reduce) Equal(that action) bool { + that1, ok := that.(reduce) + if !ok { + return false + } + return this == that1 +} + +func (this shift) Equal(that action) bool { + that1, ok := that.(shift) + if !ok { + return false + } + return this == that1 +} + +func (this accept) String() string { return "accept(0)" } +func (this shift) String() string { return fmt.Sprintf("shift:%d", this) } +func (this reduce) String() string { + return fmt.Sprintf("reduce:%d(%s)", this, productionsTable[this].String) +} diff --git a/example/rr/rr.grammar/rr/internal/parser/actiontable.go b/example/rr/rr.grammar/rr/internal/parser/actiontable.go new file mode 100644 index 00000000..06641ecc --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/parser/actiontable.go @@ -0,0 +1,95 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(4), // a + shift(5), // c + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + nil, // a + nil, // c + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: RR + shift(6), // a + nil, // c + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: RR + nil, // a + nil, // c + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: B + reduce(4), // a, reduce: A + nil, // c + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(6), // Ω, reduce: A + reduce(6), // a, reduce: A + nil, // c + }, + cdActions: []cdAction{}, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(5), // Ω, reduce: A + reduce(5), // a, reduce: A + nil, // c + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/rr/rr.grammar/rr/internal/parser/gototable.go b/example/rr/rr.grammar/rr/internal/parser/gototable.go new file mode 100644 index 00000000..711398c7 --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/parser/gototable.go @@ -0,0 +1,55 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 4 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + 3, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S6 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/example/rr/rr.grammar/rr/internal/parser/parser.go b/example/rr/rr.grammar/rr/internal/parser/parser.go new file mode 100644 index 00000000..9ef8feaf --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/parser/parser.go @@ -0,0 +1,353 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/iface" + parseError "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/errors" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/token" +) + +const ( + numProductions = 7 + numStates = 7 + numSymbols = 8 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = longest + p.isNonDeterministic = false + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/rr/rr.grammar/rr/internal/parser/productionstable.go b/example/rr/rr.grammar/rr/internal/parser/productionstable.go new file mode 100644 index 00000000..229b1b70 --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/parser/productionstable.go @@ -0,0 +1,125 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/token" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `RR : Π << >>`, + Id: "RR", + NTType: 1, + Index: 1, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `RR : Π << >>`, + Id: "RR", + NTType: 1, + Index: 2, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `B : a << "B ", nil >>`, + Id: "B", + NTType: 3, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return "B ", nil + }, + }, + ProdTabEntry{ + String: `A : a << "A0 ", nil >>`, + Id: "A", + NTType: 2, + Index: 4, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return "A0 ", nil + }, + }, + ProdTabEntry{ + String: `A : Π a << "A1 ", nil >>`, + Id: "A", + NTType: 2, + Index: 5, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return "A1 ", nil + }, + }, + ProdTabEntry{ + String: `A : c << "A2 ", nil >>`, + Id: "A", + NTType: 2, + Index: 6, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return "A2 ", nil + }, + }, +} diff --git a/example/rr/token/token.go b/example/rr/rr.grammar/rr/internal/token/token.go old mode 100755 new mode 100644 similarity index 67% rename from example/rr/token/token.go rename to example/rr/rr.grammar/rr/internal/token/token.go index bdb8a703..11d43771 --- a/example/rr/token/token.go +++ b/example/rr/rr.grammar/rr/internal/token/token.go @@ -8,8 +8,11 @@ import ( type Token struct { Type - Lit []byte + Lit []byte + IgnoredPrefix []byte Pos + ForeignAstNode interface{} + Foreign bool } type Type int @@ -29,9 +32,24 @@ func (p Pos) String() string { return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) } +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + type TokenMap struct { typeMap []string idMap map[string]Type + litMap map[string]Type } func (m TokenMap) Id(tok Type) string { @@ -49,8 +67,7 @@ func (m TokenMap) Type(tok string) Type { } func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) } func (m TokenMap) StringType(typ Type) string { @@ -60,15 +77,17 @@ func (m TokenMap) StringType(typ Type) string { var TokMap = TokenMap{ typeMap: []string{ "INVALID", - "$", + "Ω", "a", "c", }, idMap: map[string]Type{ "INVALID": 0, - "$": 1, + "Ω": 1, "a": 2, "c": 3, }, + + litMap: map[string]Type{}, } diff --git a/example/rr/rr.grammar/rr/internal/util/litconv.go b/example/rr/rr.grammar/rr/internal/util/litconv.go new file mode 100644 index 00000000..1aeb6166 --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/util/litconv.go @@ -0,0 +1,108 @@ +// Code generated by gocc; DO NOT EDIT. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +/* Interface */ + +/* +Convert the literal value of a scanned token to rune +*/ +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +/* +Convert the literal value of a scanned token to int64 +*/ +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +/* +Convert the literal value of a scanned token to uint64 +*/ +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +/* Util */ + +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/example/rr/rr.grammar/rr/internal/util/rune.go b/example/rr/rr.grammar/rr/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/rr/rr.grammar/rr/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/rr/rr.grammar/rr/main/rr.go b/example/rr/rr.grammar/rr/main/rr.go new file mode 100644 index 00000000..b8810a6c --- /dev/null +++ b/example/rr/rr.grammar/rr/main/rr.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + rr "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *rr.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return rr.NewParser().ParseLongestPrefix(lex) + } else { + res, err = rr.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, rr.NewLexerString(Text))) + } + if File > "" { + l, e := rr.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, rr.NewLexerString(str))) + } +} diff --git a/example/rr/rr.grammar/rr/rr.go b/example/rr/rr.grammar/rr/rr.go new file mode 100644 index 00000000..f4500d70 --- /dev/null +++ b/example/rr/rr.grammar/rr/rr.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package rr + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/errors" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/lexer" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/parser" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/rr/rr.grammar/rr/util.go b/example/rr/rr.grammar/rr/util.go new file mode 100644 index 00000000..7fe4c499 --- /dev/null +++ b/example/rr/rr.grammar/rr/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package rr + +import ( + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/rr/rr_test.go b/example/rr/rr_test.go index ce6d7ab9..906e4c74 100644 --- a/example/rr/rr_test.go +++ b/example/rr/rr_test.go @@ -18,13 +18,12 @@ import ( "fmt" "testing" - "github.com/goccmack/gocc/example/rr/lexer" - "github.com/goccmack/gocc/example/rr/parser" + "github.com/maxcalandrelli/gocc/example/rr/rr.grammar/rr" ) func parse(src string) (ast string, err error) { - l := lexer.NewLexer([]byte(src)) - p := parser.NewParser() + l := rr.NewLexerString(src) + p := rr.NewParser() res, err := p.Parse(l) if err == nil { ast = res.(string) diff --git a/example/rr/util/rune.go b/example/rr/util/rune.go deleted file mode 100755 index bd8523a4..00000000 --- a/example/rr/util/rune.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package util - -import ( - "fmt" -) - -func RuneToString(r rune) string { - if r >= 0x20 && r < 0x7f { - return fmt.Sprintf("'%c'", r) - } - switch r { - case 0x07: - return "'\\a'" - case 0x08: - return "'\\b'" - case 0x0C: - return "'\\f'" - case 0x0A: - return "'\\n'" - case 0x0D: - return "'\\r'" - case 0x09: - return "'\\t'" - case 0x0b: - return "'\\v'" - case 0x5c: - return "'\\\\\\'" - case 0x27: - return "'\\''" - case 0x22: - return "'\\\"'" - } - if r < 0x10000 { - return fmt.Sprintf("\\u%04x", r) - } - return fmt.Sprintf("\\U%08x", r) -} diff --git a/example/sr/ast/ast.go b/example/sr/ast/ast.go index b7472982..6fb9b210 100644 --- a/example/sr/ast/ast.go +++ b/example/sr/ast/ast.go @@ -1,7 +1,7 @@ package ast import ( - "github.com/goccmack/gocc/example/sr/token" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/iface" ) type ( @@ -30,7 +30,7 @@ type ( func NewIf(cnd, stmt Attrib) (ifs *If) { ifs = &If{ - C: string(cnd.(*token.Token).Lit), + C: string(cnd.(*iface.Token).Lit), S: stmt.(Stmt), } return @@ -38,7 +38,7 @@ func NewIf(cnd, stmt Attrib) (ifs *If) { func NewIfElse(cnd, stmt1, stmt2 Attrib) (ies *IfElse) { ies = &IfElse{ - C: string(cnd.(*token.Token).Lit), + C: string(cnd.(*iface.Token).Lit), S1: stmt1.(Stmt), S2: stmt2.(Stmt), } @@ -46,7 +46,7 @@ func NewIfElse(cnd, stmt1, stmt2 Attrib) (ies *IfElse) { } func NewIdStmt(s Attrib) (is IdStmt) { - is = IdStmt(string(s.(*token.Token).Lit)) + is = IdStmt(string(s.(*iface.Token).Lit)) return } diff --git a/example/sr/errors/errors.go b/example/sr/errors/errors.go deleted file mode 100755 index 7567b55c..00000000 --- a/example/sr/errors/errors.go +++ /dev/null @@ -1,56 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package errors - -import ( - "fmt" - "strings" - - "github.com/goccmack/gocc/example/sr/token" -) - -type ErrorSymbol interface { -} - -type Error struct { - Err error - ErrorToken *token.Token - ErrorSymbols []ErrorSymbol - ExpectedTokens []string - StackTop int -} - -func (e *Error) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "Error") - if e.Err != nil { - fmt.Fprintf(w, " %s\n", e.Err) - } else { - fmt.Fprintf(w, "\n") - } - fmt.Fprintf(w, "Token: type=%d, lit=%s\n", e.ErrorToken.Type, e.ErrorToken.Lit) - fmt.Fprintf(w, "Pos: offset=%d, line=%d, column=%d\n", e.ErrorToken.Pos.Offset, e.ErrorToken.Pos.Line, e.ErrorToken.Pos.Column) - fmt.Fprintf(w, "Expected one of: ") - for _, sym := range e.ExpectedTokens { - fmt.Fprintf(w, "%s ", sym) - } - fmt.Fprintf(w, "ErrorSymbol:\n") - for _, sym := range e.ErrorSymbols { - fmt.Fprintf(w, "%v\n", sym) - } - return w.String() -} - -func (e *Error) Error() string { - w := new(strings.Builder) - fmt.Fprintf(w, "Error in S%d: %s, %s", e.StackTop, token.TokMap.TokenString(e.ErrorToken), e.ErrorToken.Pos.String()) - if e.Err != nil { - fmt.Fprintf(w, ": %+v", e.Err) - } else { - fmt.Fprintf(w, ", expected one of: ") - for _, expected := range e.ExpectedTokens { - fmt.Fprintf(w, "%s ", expected) - } - } - return w.String() -} diff --git a/example/sr/lexer/lexer.go b/example/sr/lexer/lexer.go deleted file mode 100755 index 65849251..00000000 --- a/example/sr/lexer/lexer.go +++ /dev/null @@ -1,136 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package lexer - -import ( - "io/ioutil" - "unicode/utf8" - - "github.com/goccmack/gocc/example/sr/token" -) - -const ( - NoState = -1 - NumStates = 17 - NumSymbols = 20 -) - -type Lexer struct { - src []byte - pos int - line int - column int -} - -func NewLexer(src []byte) *Lexer { - lexer := &Lexer{ - src: src, - pos: 0, - line: 1, - column: 1, - } - return lexer -} - -func NewLexerFile(fpath string) (*Lexer, error) { - src, err := ioutil.ReadFile(fpath) - if err != nil { - return nil, err - } - return NewLexer(src), nil -} - -func (l *Lexer) Scan() (tok *token.Token) { - tok = new(token.Token) - if l.pos >= len(l.src) { - tok.Type = token.EOF - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column - return - } - start, startLine, startColumn, end := l.pos, l.line, l.column, 0 - tok.Type = token.INVALID - state, rune1, size := 0, rune(-1), 0 - for state != -1 { - if l.pos >= len(l.src) { - rune1 = -1 - } else { - rune1, size = utf8.DecodeRune(l.src[l.pos:]) - l.pos += size - } - - nextState := -1 - if rune1 != -1 { - nextState = TransTab[state](rune1) - } - state = nextState - - if state != -1 { - - switch rune1 { - case '\n': - l.line++ - l.column = 1 - case '\r': - l.column = 1 - case '\t': - l.column += 4 - default: - l.column++ - } - - switch { - case ActTab[state].Accept != -1: - tok.Type = ActTab[state].Accept - end = l.pos - case ActTab[state].Ignore != "": - start, startLine, startColumn = l.pos, l.line, l.column - state = 0 - if start >= len(l.src) { - tok.Type = token.EOF - } - - } - } else { - if tok.Type == token.INVALID { - end = l.pos - } - } - } - if end > start { - l.pos = end - tok.Lit = l.src[start:end] - } else { - tok.Lit = []byte{} - } - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn - - return -} - -func (l *Lexer) Reset() { - l.pos = 0 -} - -/* -Lexer symbols: -0: '_' -1: 'i' -2: 'f' -3: 't' -4: 'h' -5: 'e' -6: 'n' -7: 'e' -8: 'l' -9: 's' -10: 'e' -11: '_' -12: ' ' -13: '\t' -14: '\n' -15: '\r' -16: 'a'-'z' -17: 'A'-'Z' -18: '0'-'9' -19: . -*/ diff --git a/example/sr/parser/actiontable.go b/example/sr/parser/actiontable.go deleted file mode 100755 index fa0bc033..00000000 --- a/example/sr/parser/actiontable.go +++ /dev/null @@ -1,190 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - actionTable [numStates]actionRow - actionRow struct { - canRecover bool - actions [numSymbols]action - } -) - -var actionTab = actionTable{ - actionRow{ // S0 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(2), // if - shift(3), // id - nil, // then - nil, // else - }, - }, - actionRow{ // S1 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - accept(true), // $ - nil, // if - nil, // id - nil, // then - nil, // else - }, - }, - actionRow{ // S2 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // if - shift(4), // id - nil, // then - nil, // else - }, - }, - actionRow{ // S3 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(3), // $, reduce: Stmt - nil, // if - nil, // id - nil, // then - nil, // else - }, - }, - actionRow{ // S4 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // if - nil, // id - shift(5), // then - nil, // else - }, - }, - actionRow{ // S5 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(7), // if - shift(8), // id - nil, // then - nil, // else - }, - }, - actionRow{ // S6 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(1), // $, reduce: Stmt - nil, // if - nil, // id - nil, // then - shift(9), // else - }, - }, - actionRow{ // S7 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // if - shift(10), // id - nil, // then - nil, // else - }, - }, - actionRow{ // S8 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(3), // $, reduce: Stmt - nil, // if - nil, // id - nil, // then - reduce(3), // else, reduce: Stmt - }, - }, - actionRow{ // S9 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(2), // if - shift(3), // id - nil, // then - nil, // else - }, - }, - actionRow{ // S10 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - nil, // if - nil, // id - shift(12), // then - nil, // else - }, - }, - actionRow{ // S11 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(2), // $, reduce: Stmt - nil, // if - nil, // id - nil, // then - nil, // else - }, - }, - actionRow{ // S12 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(7), // if - shift(8), // id - nil, // then - nil, // else - }, - }, - actionRow{ // S13 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(1), // $, reduce: Stmt - nil, // if - nil, // id - nil, // then - shift(14), // else - }, - }, - actionRow{ // S14 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - nil, // $ - shift(7), // if - shift(8), // id - nil, // then - nil, // else - }, - }, - actionRow{ // S15 - canRecover: false, - actions: [numSymbols]action{ - nil, // INVALID - reduce(2), // $, reduce: Stmt - nil, // if - nil, // id - nil, // then - reduce(2), // else, reduce: Stmt - }, - }, -} diff --git a/example/sr/parser/gototable.go b/example/sr/parser/gototable.go deleted file mode 100755 index a33711b5..00000000 --- a/example/sr/parser/gototable.go +++ /dev/null @@ -1,77 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -const numNTSymbols = 2 - -type ( - gotoTable [numStates]gotoRow - gotoRow [numNTSymbols]int -) - -var gotoTab = gotoTable{ - gotoRow{ // S0 - -1, // S' - 1, // Stmt - }, - gotoRow{ // S1 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S2 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S3 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S4 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S5 - -1, // S' - 6, // Stmt - }, - gotoRow{ // S6 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S7 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S8 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S9 - -1, // S' - 11, // Stmt - }, - gotoRow{ // S10 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S11 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S12 - -1, // S' - 13, // Stmt - }, - gotoRow{ // S13 - -1, // S' - -1, // Stmt - }, - gotoRow{ // S14 - -1, // S' - 15, // Stmt - }, - gotoRow{ // S15 - -1, // S' - -1, // Stmt - }, -} diff --git a/example/sr/parser/parser.go b/example/sr/parser/parser.go deleted file mode 100755 index 5bbc8063..00000000 --- a/example/sr/parser/parser.go +++ /dev/null @@ -1,216 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "fmt" - "strings" - - parseError "github.com/goccmack/gocc/example/sr/errors" - "github.com/goccmack/gocc/example/sr/token" -) - -const ( - numProductions = 4 - numStates = 16 - numSymbols = 8 -) - -// Stack - -type stack struct { - state []int - attrib []Attrib -} - -const iNITIAL_STACK_SIZE = 100 - -func newStack() *stack { - return &stack{ - state: make([]int, 0, iNITIAL_STACK_SIZE), - attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), - } -} - -func (s *stack) reset() { - s.state = s.state[:0] - s.attrib = s.attrib[:0] -} - -func (s *stack) push(state int, a Attrib) { - s.state = append(s.state, state) - s.attrib = append(s.attrib, a) -} - -func (s *stack) top() int { - return s.state[len(s.state)-1] -} - -func (s *stack) peek(pos int) int { - return s.state[pos] -} - -func (s *stack) topIndex() int { - return len(s.state) - 1 -} - -func (s *stack) popN(items int) []Attrib { - lo, hi := len(s.state)-items, len(s.state) - - attrib := s.attrib[lo:hi] - - s.state = s.state[:lo] - s.attrib = s.attrib[:lo] - - return attrib -} - -func (s *stack) String() string { - w := new(strings.Builder) - fmt.Fprintf(w, "stack:\n") - for i, st := range s.state { - fmt.Fprintf(w, "\t%d: %d , ", i, st) - if s.attrib[i] == nil { - fmt.Fprintf(w, "nil") - } else { - switch attr := s.attrib[i].(type) { - case *token.Token: - fmt.Fprintf(w, "%s", attr.Lit) - default: - fmt.Fprintf(w, "%v", attr) - } - } - fmt.Fprintf(w, "\n") - } - return w.String() -} - -// Parser - -type Parser struct { - stack *stack - nextToken *token.Token - pos int -} - -type Scanner interface { - Scan() (tok *token.Token) -} - -func NewParser() *Parser { - p := &Parser{stack: newStack()} - p.Reset() - return p -} - -func (p *Parser) Reset() { - p.stack.reset() - p.stack.push(0, nil) -} - -func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { - errorAttrib = &parseError.Error{ - Err: err, - ErrorToken: p.nextToken, - ErrorSymbols: p.popNonRecoveryStates(), - ExpectedTokens: make([]string, 0, 8), - } - for t, action := range actionTab[p.stack.top()].actions { - if action != nil { - errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) - } - } - - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { - p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift - } else { - return - } - - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - for !recovered && p.nextToken.Type != token.EOF { - p.nextToken = scanner.Scan() - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { - recovered = true - } - } - - return -} - -func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { - if rs, ok := p.firstRecoveryState(); ok { - errorSymbols := p.stack.popN(p.stack.topIndex() - rs) - removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) - for i, e := range errorSymbols { - removedAttribs[i] = e - } - } else { - removedAttribs = []parseError.ErrorSymbol{} - } - return -} - -// recoveryState points to the highest state on the stack, which can recover -func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { - recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover - for recoveryState > 0 && !canRecover { - recoveryState-- - canRecover = actionTab[p.stack.peek(recoveryState)].canRecover - } - return -} - -func (p *Parser) newError(err error) error { - e := &parseError.Error{ - Err: err, - StackTop: p.stack.top(), - ErrorToken: p.nextToken, - } - actRow := actionTab[p.stack.top()] - for i, t := range actRow.actions { - if t != nil { - e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) - } - } - return e -} - -func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { - p.Reset() - p.nextToken = scanner.Scan() - for acc := false; !acc; { - action := actionTab[p.stack.top()].actions[p.nextToken.Type] - if action == nil { - if recovered, errAttrib := p.Error(nil, scanner); !recovered { - p.nextToken = errAttrib.ErrorToken - return nil, p.newError(nil) - } - if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { - panic("Error recovery led to invalid action") - } - } - - switch act := action.(type) { - case accept: - res = p.stack.popN(1)[0] - acc = true - case shift: - p.stack.push(int(act), p.nextToken) - p.nextToken = scanner.Scan() - case reduce: - prod := productionsTable[int(act)] - attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) - if err != nil { - return nil, p.newError(err) - } else { - p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) - } - default: - panic("unknown action: " + action.String()) - } - } - return res, nil -} diff --git a/example/sr/parser/productionstable.go b/example/sr/parser/productionstable.go deleted file mode 100755 index 602f53ec..00000000 --- a/example/sr/parser/productionstable.go +++ /dev/null @@ -1,63 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package parser - -import "github.com/goccmack/gocc/example/sr/ast" - -type ( - //TODO: change type and variable names to be consistent with other tables - ProdTab [numProductions]ProdTabEntry - ProdTabEntry struct { - String string - Id string - NTType int - Index int - NumSymbols int - ReduceFunc func([]Attrib) (Attrib, error) - } - Attrib interface { - } -) - -var productionsTable = ProdTab{ - ProdTabEntry{ - String: `S' : Stmt << >>`, - Id: "S'", - NTType: 0, - Index: 0, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return X[0], nil - }, - }, - ProdTabEntry{ - String: `Stmt : "if" id "then" Stmt << ast.NewIf(X[1], X[3]), nil >>`, - Id: "Stmt", - NTType: 1, - Index: 1, - NumSymbols: 4, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewIf(X[1], X[3]), nil - }, - }, - ProdTabEntry{ - String: `Stmt : "if" id "then" Stmt "else" Stmt << ast.NewIfElse(X[1], X[3], X[5]), nil >>`, - Id: "Stmt", - NTType: 1, - Index: 2, - NumSymbols: 6, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewIfElse(X[1], X[3], X[5]), nil - }, - }, - ProdTabEntry{ - String: `Stmt : id << ast.NewIdStmt(X[0]), nil >>`, - Id: "Stmt", - NTType: 1, - Index: 3, - NumSymbols: 1, - ReduceFunc: func(X []Attrib) (Attrib, error) { - return ast.NewIdStmt(X[0]), nil - }, - }, -} diff --git a/example/sr/sr.bnf b/example/sr/sr.bnf index 7228fc3b..ff9fbcef 100644 --- a/example/sr/sr.bnf +++ b/example/sr/sr.bnf @@ -26,7 +26,7 @@ id : (_letter | '_') {_idchar} ; /* Syntax elements */ -<< import "github.com/goccmack/gocc/example/sr/ast" >> +<< import "github.com/maxcalandrelli/gocc/example/sr/ast" >> Stmt : "if" id "then" Stmt << ast.NewIf($1, $3), nil >> diff --git a/example/sr/sr.grammar/sr/iface/sr.go b/example/sr/sr.grammar/sr/iface/sr.go new file mode 100644 index 00000000..6158aab8 --- /dev/null +++ b/example/sr/sr.grammar/sr/iface/sr.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/errors" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/io/stream" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/calc/errors/errors.go b/example/sr/sr.grammar/sr/internal/errors/errors.go old mode 100755 new mode 100644 similarity index 94% rename from example/calc/errors/errors.go rename to example/sr/sr.grammar/sr/internal/errors/errors.go index 44b2ffc7..bfee4741 --- a/example/calc/errors/errors.go +++ b/example/sr/sr.grammar/sr/internal/errors/errors.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/example/calc/token" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/token" ) type ErrorSymbol interface { diff --git a/example/sr/sr.grammar/sr/internal/io/stream/internal/stream_impl.go b/example/sr/sr.grammar/sr/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/example/sr/sr.grammar/sr/internal/io/stream/internal/stream_public.go b/example/sr/sr.grammar/sr/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/example/sr/sr.grammar/sr/internal/io/stream/stream.go b/example/sr/sr.grammar/sr/internal/io/stream/stream.go new file mode 100644 index 00000000..672d6370 --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/example/sr/lexer/acttab.go b/example/sr/sr.grammar/sr/internal/lexer/acttab.go old mode 100755 new mode 100644 similarity index 57% rename from example/sr/lexer/acttab.go rename to example/sr/sr.grammar/sr/internal/lexer/acttab.go index 860bcbf1..7fd1dc0c --- a/example/sr/lexer/acttab.go +++ b/example/sr/sr.grammar/sr/internal/lexer/acttab.go @@ -5,7 +5,7 @@ package lexer import ( "fmt" - "github.com/goccmack/gocc/example/sr/token" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/token" ) type ActionTable [NumStates]ActionRow @@ -20,71 +20,71 @@ func (a ActionRow) String() string { } var ActTab = ActionTable{ - ActionRow{ // S0 + ActionRow{ // S0, Accept: 0, Ignore: "", }, - ActionRow{ // S1 + ActionRow{ // S1, Ignore("!whitespace") Accept: -1, Ignore: "!whitespace", }, - ActionRow{ // S2 + ActionRow{ // S2, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S3 + ActionRow{ // S3, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S4 + ActionRow{ // S4, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S5 + ActionRow{ // S5, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S6 + ActionRow{ // S6, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S7 + ActionRow{ // S7, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S8 + ActionRow{ // S8, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S9 + ActionRow{ // S9, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S10 + ActionRow{ // S10, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S11 + ActionRow{ // S11, Accept("Λ") Accept: 2, Ignore: "", }, - ActionRow{ // S12 + ActionRow{ // S12, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S13 + ActionRow{ // S13, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S14 + ActionRow{ // S14, Accept("id") Accept: 3, Ignore: "", }, - ActionRow{ // S15 + ActionRow{ // S15, Accept("Λ") Accept: 5, Ignore: "", }, - ActionRow{ // S16 + ActionRow{ // S16, Accept("Λ") Accept: 4, Ignore: "", }, diff --git a/example/sr/sr.grammar/sr/internal/lexer/lexer.go b/example/sr/sr.grammar/sr/internal/lexer/lexer.go new file mode 100644 index 00000000..d1175fe8 --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/iface" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/token" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 17 + NumSymbols = 20 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/example/sr/lexer/transitiontable.go b/example/sr/sr.grammar/sr/internal/lexer/transitiontable.go old mode 100755 new mode 100644 similarity index 100% rename from example/sr/lexer/transitiontable.go rename to example/sr/sr.grammar/sr/internal/lexer/transitiontable.go diff --git a/example/sr/sr.grammar/sr/internal/parser/action.go b/example/sr/sr.grammar/sr/internal/parser/action.go new file mode 100644 index 00000000..54bc55e9 --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/parser/action.go @@ -0,0 +1,51 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" +) + +type action interface { + act() + String() string +} + +type ( + accept bool + shift int // value is next state index + reduce int // value is production index +) + +func (this accept) act() {} +func (this shift) act() {} +func (this reduce) act() {} + +func (this accept) Equal(that action) bool { + if _, ok := that.(accept); ok { + return true + } + return false +} + +func (this reduce) Equal(that action) bool { + that1, ok := that.(reduce) + if !ok { + return false + } + return this == that1 +} + +func (this shift) Equal(that action) bool { + that1, ok := that.(shift) + if !ok { + return false + } + return this == that1 +} + +func (this accept) String() string { return "accept(0)" } +func (this shift) String() string { return fmt.Sprintf("shift:%d", this) } +func (this reduce) String() string { + return fmt.Sprintf("reduce:%d(%s)", this, productionsTable[this].String) +} diff --git a/example/sr/sr.grammar/sr/internal/parser/actiontable.go b/example/sr/sr.grammar/sr/internal/parser/actiontable.go new file mode 100644 index 00000000..1ff4a333 --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/parser/actiontable.go @@ -0,0 +1,217 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(2), // "if" + shift(3), // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + nil, // "if" + nil, // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "if" + shift(4), // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt + nil, // "if" + nil, // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "if" + nil, // id + shift(5), // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(7), // "if" + shift(8), // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: Stmt + nil, // "if" + nil, // id + nil, // "then" + shift(9), // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S7 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "if" + shift(10), // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S8 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Stmt + nil, // "if" + nil, // id + nil, // "then" + reduce(3), // "else", reduce: Stmt + }, + cdActions: []cdAction{}, + }, + actionRow{ // S9 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(2), // "if" + shift(3), // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S10 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // "if" + nil, // id + shift(12), // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S11 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: Stmt + nil, // "if" + nil, // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S12 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(7), // "if" + shift(8), // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S13 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: Stmt + nil, // "if" + nil, // id + nil, // "then" + shift(14), // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S14 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(7), // "if" + shift(8), // id + nil, // "then" + nil, // "else" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S15 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: Stmt + nil, // "if" + nil, // id + nil, // "then" + reduce(2), // "else", reduce: Stmt + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/example/sr/sr.grammar/sr/internal/parser/gototable.go b/example/sr/sr.grammar/sr/internal/parser/gototable.go new file mode 100644 index 00000000..593dc1fd --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/parser/gototable.go @@ -0,0 +1,77 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 2 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + 6, // Π + }, + gotoRow{ // S6 + -1, // Π + -1, // Π + }, + gotoRow{ // S7 + -1, // Π + -1, // Π + }, + gotoRow{ // S8 + -1, // Π + -1, // Π + }, + gotoRow{ // S9 + -1, // Π + 11, // Π + }, + gotoRow{ // S10 + -1, // Π + -1, // Π + }, + gotoRow{ // S11 + -1, // Π + -1, // Π + }, + gotoRow{ // S12 + -1, // Π + 13, // Π + }, + gotoRow{ // S13 + -1, // Π + -1, // Π + }, + gotoRow{ // S14 + -1, // Π + 15, // Π + }, + gotoRow{ // S15 + -1, // Π + -1, // Π + }, +} diff --git a/example/sr/sr.grammar/sr/internal/parser/parser.go b/example/sr/sr.grammar/sr/internal/parser/parser.go new file mode 100644 index 00000000..b8734524 --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/parser/parser.go @@ -0,0 +1,353 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/iface" + parseError "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/errors" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/token" +) + +const ( + numProductions = 4 + numStates = 16 + numSymbols = 8 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = longest + p.isNonDeterministic = false + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/example/sr/sr.grammar/sr/internal/parser/productionstable.go b/example/sr/sr.grammar/sr/internal/parser/productionstable.go new file mode 100644 index 00000000..bb6cab6a --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/parser/productionstable.go @@ -0,0 +1,97 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import "github.com/maxcalandrelli/gocc/example/sr/ast" + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/token" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/util" + "strings" +) + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Stmt : Λ id Λ Π << ast.NewIf($1, $3), nil >>`, + Id: "Stmt", + NTType: 1, + Index: 1, + NumSymbols: 4, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewIf(X[1], X[3]), nil + }, + }, + ProdTabEntry{ + String: `Stmt : Λ id Λ Π Λ Π << ast.NewIfElse($1, $3, $5), nil >>`, + Id: "Stmt", + NTType: 1, + Index: 2, + NumSymbols: 6, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewIfElse(X[1], X[3], X[5]), nil + }, + }, + ProdTabEntry{ + String: `Stmt : id << ast.NewIdStmt($0), nil >>`, + Id: "Stmt", + NTType: 1, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewIdStmt(X[0]), nil + }, + }, +} diff --git a/example/nolexer/token/token.go b/example/sr/sr.grammar/sr/internal/token/token.go old mode 100755 new mode 100644 similarity index 59% rename from example/nolexer/token/token.go rename to example/sr/sr.grammar/sr/internal/token/token.go index 634aaeac..8268086c --- a/example/nolexer/token/token.go +++ b/example/sr/sr.grammar/sr/internal/token/token.go @@ -8,8 +8,11 @@ import ( type Token struct { Type - Lit []byte + Lit []byte + IgnoredPrefix []byte Pos + ForeignAstNode interface{} + Foreign bool } type Type int @@ -29,9 +32,24 @@ func (p Pos) String() string { return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) } +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + type TokenMap struct { typeMap []string idMap map[string]Type + litMap map[string]Type } func (m TokenMap) Id(tok Type) string { @@ -49,8 +67,7 @@ func (m TokenMap) Type(tok string) Type { } func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) } func (m TokenMap) StringType(typ Type) string { @@ -60,17 +77,25 @@ func (m TokenMap) StringType(typ Type) string { var TokMap = TokenMap{ typeMap: []string{ "INVALID", - "$", - "name", - "hello", - "hiya", + "Ω", + "Λ", + "id", + "Λ", + "Λ", }, idMap: map[string]Type{ "INVALID": 0, - "$": 1, - "name": 2, - "hello": 3, - "hiya": 4, + "Ω": 1, + "Λ": 2, + "id": 3, + "Λ": 4, + "Λ": 5, + }, + + litMap: map[string]Type{ + "if": 2, + "then": 4, + "else": 5, }, } diff --git a/example/sr/sr.grammar/sr/internal/util/litconv.go b/example/sr/sr.grammar/sr/internal/util/litconv.go new file mode 100644 index 00000000..1aeb6166 --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/util/litconv.go @@ -0,0 +1,108 @@ +// Code generated by gocc; DO NOT EDIT. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +/* Interface */ + +/* +Convert the literal value of a scanned token to rune +*/ +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +/* +Convert the literal value of a scanned token to int64 +*/ +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +/* +Convert the literal value of a scanned token to uint64 +*/ +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +/* Util */ + +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/example/sr/sr.grammar/sr/internal/util/rune.go b/example/sr/sr.grammar/sr/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/example/sr/sr.grammar/sr/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/example/sr/sr.grammar/sr/main/sr.go b/example/sr/sr.grammar/sr/main/sr.go new file mode 100644 index 00000000..80b8f1e4 --- /dev/null +++ b/example/sr/sr.grammar/sr/main/sr.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + sr "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *sr.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return sr.NewParser().ParseLongestPrefix(lex) + } else { + res, err = sr.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, sr.NewLexerString(Text))) + } + if File > "" { + l, e := sr.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, sr.NewLexerString(str))) + } +} diff --git a/example/sr/sr.grammar/sr/sr.go b/example/sr/sr.grammar/sr/sr.go new file mode 100644 index 00000000..225fd475 --- /dev/null +++ b/example/sr/sr.grammar/sr/sr.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package sr + +import ( + "io" + + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/errors" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/lexer" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/parser" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/example/sr/sr.grammar/sr/util.go b/example/sr/sr.grammar/sr/util.go new file mode 100644 index 00000000..216010f9 --- /dev/null +++ b/example/sr/sr.grammar/sr/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package sr + +import ( + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/example/sr/sr_test.go b/example/sr/sr_test.go index 461b8d12..98dea3ef 100644 --- a/example/sr/sr_test.go +++ b/example/sr/sr_test.go @@ -3,14 +3,13 @@ package sr import ( "testing" - "github.com/goccmack/gocc/example/sr/ast" - "github.com/goccmack/gocc/example/sr/lexer" - "github.com/goccmack/gocc/example/sr/parser" + "github.com/maxcalandrelli/gocc/example/sr/ast" + "github.com/maxcalandrelli/gocc/example/sr/sr.grammar/sr" ) func parse(src string) (stmt ast.Stmt, err error) { - lex := lexer.NewLexer([]byte(src)) - p := parser.NewParser() + lex := sr.NewLexerString(src) + p := sr.NewParser() if res, err := p.Parse(lex); err == nil { stmt = res.(ast.Stmt) } diff --git a/example/sr/util/rune.go b/example/sr/util/rune.go deleted file mode 100755 index bd8523a4..00000000 --- a/example/sr/util/rune.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by gocc; DO NOT EDIT. - -package util - -import ( - "fmt" -) - -func RuneToString(r rune) string { - if r >= 0x20 && r < 0x7f { - return fmt.Sprintf("'%c'", r) - } - switch r { - case 0x07: - return "'\\a'" - case 0x08: - return "'\\b'" - case 0x0C: - return "'\\f'" - case 0x0A: - return "'\\n'" - case 0x0D: - return "'\\r'" - case 0x09: - return "'\\t'" - case 0x0b: - return "'\\v'" - case 0x5c: - return "'\\\\\\'" - case 0x27: - return "'\\''" - case 0x22: - return "'\\\"'" - } - if r < 0x10000 { - return fmt.Sprintf("\\u%04x", r) - } - return fmt.Sprintf("\\U%08x", r) -} diff --git a/example/test.ebnf b/example/test.ebnf new file mode 100644 index 00000000..ca705e1d --- /dev/null +++ b/example/test.ebnf @@ -0,0 +1,81 @@ +!comment : _lineComment | _blockComment ; +!whitespace : ' ' | '\t' | '\n' | '\r' ; + +_lineComment : '$' '/' '/' {.} '\n' ; +_blockComment : '/' '*' {. | '*'} '*' '/' ; +_tokId : _lowcase {_id_char} ; +_lowcase : 'a'-'z' ; +_id_char : _upcase | _lowcase | '_' | _digit ; +_upcase : 'A'-'Z' ; +_digit : '0'-'9' ; +_all_but_star : . | ~'*' ; + +!space : ' ' | '\t' ; +hexdigit : '0'-'F' | ~(':'-'@') ; +qhexdigit : '"' ('0'-'F' | ~(':'-'@')) '"' ; +//quote: '"' ; + +<< +import( +) +>> + +Test : + Test1 +; + +Test1: + "try" Test2 << $1, nil >> +; + +Test2 : Test3 | Test1; + +Test3 : +"not" "empty" << []interface{}{"very well"}, nil >> +| +T +; + +T : "a" | "X" | ProdX | "λ1" | X; + +ProdX : "empty" | "ε" | "λ" | empty | ε ; + +Quoted : + qhexdigit + | + "\"" hexdigit "\"" +; + +X: + altro + @@ + func () (interface {}, error, []byte) { + slashes := []byte{} + for r, _, _ := Stream.ReadRune(); r == '/' || r == '\\' || r == '\u2215' || r == '\u29f5'; r, _, _ = Stream.ReadRune() { + slashes = append(slashes, string(r)...) + } + Stream.UnreadRune() + return len(string(slashes)), nil, slashes + }() + @@ + Test2 + << + append(append([]interface{}{},$1),$2.([]interface{})...), nil + >> + | + @ "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + Test2 + << + func () interface{} { + fmt.Printf("computed: %s=%d\n", $s0, $1) + return append(append([]interface{}{},$1),$2.([]interface{})...) + }() , nil + >> + | + Quoted + Test2 + << + append([]interface{}{fmt.Sprintf("string: %s", $u0)},$1), nil + >> +; + diff --git a/example/test2.ebnf b/example/test2.ebnf new file mode 100644 index 00000000..cd77c144 --- /dev/null +++ b/example/test2.ebnf @@ -0,0 +1,6 @@ +_blockComment : '/' '*' { . } '*' '/' ; +g_sdt_lit : '<' '<' . { . } '>' '>' ; +t : 'a' . 'b'; + + +Grammar : blockComment | g_sdt_lit ; diff --git a/example/test3.ebnf b/example/test3.ebnf new file mode 100644 index 00000000..a7b969db --- /dev/null +++ b/example/test3.ebnf @@ -0,0 +1,6 @@ +_blockComment : '/' '*' { . } '*' '/' ; +_g_sdt_lit : '<' '<' . { . } '.' '>' ; + +g_sdt_lit: _g_sdt_lit ; + +Grammar : blockComment | g_sdt_lit ; diff --git a/internal/ast/fileheader.go b/internal/ast/fileheader.go index bde65038..a7a8ee84 100644 --- a/internal/ast/fileheader.go +++ b/internal/ast/fileheader.go @@ -16,8 +16,6 @@ package ast import ( "fmt" - - "github.com/goccmack/gocc/internal/frontend/token" ) type FileHeader struct { @@ -27,7 +25,7 @@ type FileHeader struct { func NewFileHeader(sdtLit interface{}) (*FileHeader, error) { sh := &FileHeader{ - SDTLit: sdtLit.(*token.Token).SDTVal(), + SDTLit: SDTVal(getString(sdtLit)), } sh.str = fmt.Sprintf("<< %s >>", sh.SDTLit) return sh, nil diff --git a/internal/ast/grammar.go b/internal/ast/grammar.go index 2a886855..f38101de 100644 --- a/internal/ast/grammar.go +++ b/internal/ast/grammar.go @@ -49,26 +49,26 @@ func consistent(g *Grammar) (err error) { return } - defs := make(map[string]bool) - used := make(map[string][]string) + defs := make(map[SyntaxSymbol]struct{}) + used := make(map[SyntaxSymbol]SyntaxSymbols) for _, tok := range g.LexPart.TokDefsList { - defs[tok.id] = true + defs[SyntaxTokId{tok.id, StdSyntaxSymbol{}}] = struct{}{} } for _, prod := range g.SyntaxPart.ProdList { - if len(prod.Body.Symbols) == 0 { + if prod.Body.Missing() { return fmt.Errorf("empty production alternative: Maybe you are missing the \"empty\" keyword in %q", prod) } - defs[prod.Id] = true + defs[prod.Id] = struct{}{} for _, s := range prod.Body.Symbols { if s.String()[0] == '"' { continue } - used[s.String()] = append(used[s.String()], prod.Id) + used[s] = append(used[s], prod.Id) } } for s := range defs { - if s == "S'" { + if s.SymbolString() == "S'" { continue } if _, ok := used[s]; !ok { @@ -77,14 +77,15 @@ func consistent(g *Grammar) (err error) { } for s, in := range used { if _, ok := defs[s]; !ok { - if s == "empty" || s == "error" { + switch s.(type) { + case SyntaxEmpty, SyntaxError, SyntaxContextDependentTokId, SyntaxSubParser: continue } - if s[0] >= 'A' && s[0] <= 'Z' { - fmt.Fprintf(os.Stderr, "error: undefined symbol %q used in productions %q\n", s, in) + if !s.IsTerminal() { + fmt.Fprintf(os.Stderr, "error: undefined symbol %T{%q} used in productions %q\n", s, s, in) err = errUndefined } else { - fmt.Fprintf(os.Stderr, "warning: undefined symbol %q used in productions %q\n", s, in) + fmt.Fprintf(os.Stderr, "warning: undefined symbol %T{%q} used in productions %q\n", s, s, in) } } } diff --git a/internal/ast/lexcharlit.go b/internal/ast/lexcharlit.go index ba0c42f9..b8282069 100644 --- a/internal/ast/lexcharlit.go +++ b/internal/ast/lexcharlit.go @@ -15,27 +15,31 @@ package ast import ( - "github.com/goccmack/gocc/internal/frontend/token" - "github.com/goccmack/gocc/internal/util" + "github.com/maxcalandrelli/gocc/internal/util" ) type LexCharLit struct { - Val rune - Lit []byte - s string + Val rune + Lit []byte + s string + Negate bool } func NewLexCharLit(tok interface{}) (*LexCharLit, error) { - return newLexCharLit(tok), nil + return newLexCharLit(tok, false), nil } -func newLexCharLit(tok interface{}) *LexCharLit { - c := new(LexCharLit) - t := tok.(*token.Token) +func NewLexCharLitExt(tok interface{}, negate bool) (*LexCharLit, error) { + return newLexCharLit(tok, negate), nil +} - c.Val = util.LitToRune(t.Lit) - c.Lit = t.Lit +func newLexCharLit(tok interface{}, negate bool) *LexCharLit { + c := new(LexCharLit) + lit := []byte(getString(tok)) + c.Val = util.LitToRune(lit) + c.Lit = lit c.s = util.RuneToString(c.Val) + c.Negate = negate return c } diff --git a/internal/ast/lexcharrange.go b/internal/ast/lexcharrange.go index ee736ec3..0e5fbb65 100644 --- a/internal/ast/lexcharrange.go +++ b/internal/ast/lexcharrange.go @@ -19,17 +19,27 @@ import ( ) type LexCharRange struct { - From *LexCharLit - To *LexCharLit - s string + From *LexCharLit + To *LexCharLit + s string + Negate bool } func NewLexCharRange(from, to interface{}) (*LexCharRange, error) { + return NewLexCharRangeExt(from, to, false) +} + +func NewLexCharRangeExt(from, to interface{}, negate bool) (*LexCharRange, error) { cr := &LexCharRange{ - From: newLexCharLit(from), - To: newLexCharLit(to), + From: newLexCharLit(from, negate), + To: newLexCharLit(to, negate), + Negate: negate, + } + if cr.From.Val > cr.To.Val { + t := cr.From + cr.From = cr.To + cr.To = t } - return cr, nil } diff --git a/internal/ast/lexignoredtokdef.go b/internal/ast/lexignoredtokdef.go index d667f3b2..015c95f9 100644 --- a/internal/ast/lexignoredtokdef.go +++ b/internal/ast/lexignoredtokdef.go @@ -17,8 +17,6 @@ package ast import ( "fmt" "strings" - - "github.com/goccmack/gocc/internal/frontend/token" ) type LexIgnoredTokDef struct { @@ -28,7 +26,7 @@ type LexIgnoredTokDef struct { func NewLexIgnoredTokDef(tokId, lexPattern interface{}) (*LexIgnoredTokDef, error) { tokDef := &LexIgnoredTokDef{ - id: string(tokId.(*token.Token).Lit), + id: getString(tokId), pattern: lexPattern.(*LexPattern), } return tokDef, nil diff --git a/internal/ast/leximport.go b/internal/ast/leximport.go index 055879ec..61a2ee1f 100644 --- a/internal/ast/leximport.go +++ b/internal/ast/leximport.go @@ -16,8 +16,6 @@ package ast import ( "fmt" - - "github.com/goccmack/gocc/internal/frontend/token" ) type LexImport struct { @@ -27,7 +25,7 @@ type LexImport struct { func NewLexImport(regDefId, extFunc interface{}) (*LexImport, error) { return &LexImport{ - Id: string(regDefId.(*token.Token).Lit), + Id: getString(regDefId), ExtFunc: getExtFunc(extFunc), }, nil } @@ -41,6 +39,6 @@ func (this *LexImport) String() string { } func getExtFunc(strLit interface{}) string { - lit := strLit.(*token.Token).Lit + lit := getString(strLit) return string(lit[1 : len(lit)-1]) } diff --git a/internal/ast/lexnodewalker.go b/internal/ast/lexnodewalker.go index 5037c724..ba590bf0 100644 --- a/internal/ast/lexnodewalker.go +++ b/internal/ast/lexnodewalker.go @@ -83,6 +83,7 @@ func (this *LexGroupPattern) Walk(visitor LexNodeVisitor) LexNodeVisitor { } func (this *LexIgnoredTokDef) Walk(visitor LexNodeVisitor) LexNodeVisitor { + fmt.Printf(" walk on: %s\n", this.Id()) return visitor.Visit(this) } diff --git a/internal/ast/lexpart.go b/internal/ast/lexpart.go index 89a29a6b..311f7e3f 100644 --- a/internal/ast/lexpart.go +++ b/internal/ast/lexpart.go @@ -113,22 +113,22 @@ func (this *LexPart) ProdIndex(id string) LexProdIndex { return idx } -func (this *LexPart) TokenIds() []string { - tids := make([]string, 0, len(this.TokDefs)) - for tid := range this.TokDefs { - tids = append(tids, tid) +func (this *LexPart) TokenIds() SyntaxSymbols { + tids := make(SyntaxSymbolsByName, 0, len(this.TokDefs)) + for _, tid := range this.TokDefs { + tids = append(tids, NewTokIdFromString(tid.Id())) } - sort.Strings(tids) - return tids + sort.Sort(&tids) + return SyntaxSymbols(tids) } -func (this *LexPart) UpdateStringLitTokens(tokens []string) { +func (this *LexPart) UpdateStringLitTokens(tokens SyntaxSymbols) { for _, strLit := range tokens { tokDef := NewLexStringLitTokDef(strLit) this.ProdMap.Add(tokDef) this.TokDefsList = append(this.TokDefsList, tokDef) - this.TokDefs[strLit] = tokDef - this.stringLitToks[strLit] = tokDef + this.TokDefs[strLit.SymbolName()] = tokDef + this.stringLitToks[strLit.SymbolName()] = tokDef this.ProdList.Productions = append(this.ProdList.Productions, tokDef) } } diff --git a/internal/ast/lexregdef.go b/internal/ast/lexregdef.go index 48855428..d320352e 100644 --- a/internal/ast/lexregdef.go +++ b/internal/ast/lexregdef.go @@ -17,8 +17,6 @@ package ast import ( "fmt" "strings" - - "github.com/goccmack/gocc/internal/frontend/token" ) type LexRegDef struct { @@ -28,7 +26,7 @@ type LexRegDef struct { func NewLexRegDef(regDefId, lexPattern interface{}) (*LexRegDef, error) { regDef := &LexRegDef{ - id: string(regDefId.(*token.Token).Lit), + id: getString(regDefId), pattern: lexPattern.(*LexPattern), } return regDef, nil diff --git a/internal/ast/lexregdefid.go b/internal/ast/lexregdefid.go index a3a518fa..5b94e7f8 100644 --- a/internal/ast/lexregdefid.go +++ b/internal/ast/lexregdefid.go @@ -14,17 +14,13 @@ package ast -import ( - "github.com/goccmack/gocc/internal/frontend/token" -) - type LexRegDefId struct { Id string } func NewLexRegDefId(regDefId interface{}) (*LexRegDefId, error) { return &LexRegDefId{ - Id: string(regDefId.(*token.Token).Lit), + Id: getString(regDefId), }, nil } diff --git a/internal/ast/lextokdef.go b/internal/ast/lextokdef.go index 45a229d4..b5baa469 100644 --- a/internal/ast/lextokdef.go +++ b/internal/ast/lextokdef.go @@ -18,8 +18,6 @@ import ( "bytes" "fmt" "strings" - - "github.com/goccmack/gocc/internal/frontend/token" ) type LexTokDef struct { @@ -29,21 +27,22 @@ type LexTokDef struct { func NewLexTokDef(tokId, lexPattern interface{}) (*LexTokDef, error) { tokDef := &LexTokDef{ - id: string(tokId.(*token.Token).Lit), + id: getString(tokId), pattern: lexPattern.(*LexPattern), } return tokDef, nil } -func NewLexStringLitTokDef(tokId string) *LexTokDef { - runes := bytes.Runes([]byte(tokId)) +func NewLexStringLitTokDef(tok SyntaxSymbol) *LexTokDef { + runes := bytes.Runes([]byte(tok.SymbolString())) alt, _ := NewLexAlt(newLexCharLitFromRune(runes[0])) for i := 1; i < len(runes); i++ { alt, _ = AppendLexTerm(alt, newLexCharLitFromRune(runes[i])) } ptrn, _ := NewLexPattern(alt) + id := tok.SymbolName() return &LexTokDef{ - id: tokId, + id: id, pattern: ptrn, } } diff --git a/internal/ast/reconcile.go b/internal/ast/reconcile.go new file mode 100644 index 00000000..1f511b08 --- /dev/null +++ b/internal/ast/reconcile.go @@ -0,0 +1,21 @@ +package ast + +import ( + "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" +) + +var ( + StringGetter func(interface{}) string +) + +func getString(v interface{}) string { + if StringGetter == nil { + if str, ok := v.(string); ok { + return str + } + if tok, _ := v.(*token.Token); tok != nil { + return string(tok.Lit) + } + } + return StringGetter(v) +} diff --git a/internal/ast/sdthlp.go b/internal/ast/sdthlp.go new file mode 100644 index 00000000..fc4e4ea0 --- /dev/null +++ b/internal/ast/sdthlp.go @@ -0,0 +1,17 @@ +// +// Syntax Directed Translation helper +// + +package ast + +import ( + "regexp" +) + +var ( + sdtAstSubst = regexp.MustCompile("(?ms)<<(?:\\s|\\n|\\r)*(.+?)(?:\\s|\\n|\\r)*>>") +) + +func SDTVal(sdt string) string { + return sdtAstSubst.ReplaceAllString(sdt, "$1") +} diff --git a/internal/ast/syntaxalts.go b/internal/ast/syntaxalts.go index 69ebf026..316ce46e 100644 --- a/internal/ast/syntaxalts.go +++ b/internal/ast/syntaxalts.go @@ -14,12 +14,19 @@ package ast +import ( + "fmt" +) + type SyntaxAlts []*SyntaxBody +type stringer fmt.GoStringer func NewSyntaxAlts(body interface{}) (SyntaxAlts, error) { + //fmt.Printf(" NewFirstAlt(%v)\n", body) return SyntaxAlts{(body.(*SyntaxBody))}, nil } func AddSyntaxAlt(alts, body interface{}) (SyntaxAlts, error) { + //fmt.Printf(" NewAlt(%v)\n", body) return append(alts.(SyntaxAlts), body.(*SyntaxBody)), nil } diff --git a/internal/ast/syntaxbody.go b/internal/ast/syntaxbody.go index 90609d1a..ce786fbc 100644 --- a/internal/ast/syntaxbody.go +++ b/internal/ast/syntaxbody.go @@ -16,17 +16,52 @@ package ast import ( "fmt" + "runtime/debug" - "github.com/goccmack/gocc/internal/frontend/token" + "github.com/maxcalandrelli/gocc/internal/config" ) type SyntaxBody struct { Error bool Symbols SyntaxSymbols SDT string + _x debug.GCStats +} + +func checkSymbols(symbols interface{}) interface{} { + if syms, _ := symbols.(SyntaxSymbols); syms != nil { + for i, s := range syms { + switch s.(type) { + case SyntaxEmpty: + syms[i] = EmptySymbol + case SyntaxError: + syms[i] = ErrorSymbol + case SyntaxTokId: + switch s.SymbolString() { + case config.SYMBOL_EMPTY: + syms[i] = EmptySymbol + case config.SYMBOL_ERROR: + syms[i] = ErrorSymbol + } + } + } + return syms + } + return symbols } func NewSyntaxBody(symbols, sdtLit interface{}) (*SyntaxBody, error) { + checkSymbols(symbols) + if syms, _ := symbols.(SyntaxSymbols); syms != nil { + for i, s := range syms { + switch { + case s.IsEpsilon(): + syms[i] = EmptySymbol + case s.IsError(): + syms[i] = ErrorSymbol + } + } + } syntaxBody := &SyntaxBody{ Error: false, } @@ -34,25 +69,92 @@ func NewSyntaxBody(symbols, sdtLit interface{}) (*SyntaxBody, error) { syntaxBody.Symbols = symbols.(SyntaxSymbols) } if sdtLit != nil { - syntaxBody.SDT = sdtLit.(*token.Token).SDTVal() + syntaxBody.SDT = SDTVal(getString(sdtLit)) + } + if symbols == nil { + return nil, fmt.Errorf("empty production alternative!") + } + if s, _ := symbols.(SyntaxSymbols); len(s) > 0 && s[0] == EmptySymbol { + //fmt.Printf(" NewBody(Empty) Symbols=%#v(%s)\n", syntaxBody.Symbols, syntaxBody.Symbols.String()) + } else if s, _ := symbols.(SyntaxSymbols); len(s) > 0 && s[0] == ErrorSymbol { + //fmt.Printf(" NewBody(Error) Symbols=%#v(%s)\n", syntaxBody.Symbols, syntaxBody.Symbols.String()) + } else { + //fmt.Printf(" NewBody() Symbols=%#v(%s)\n", syntaxBody.Symbols, syntaxBody.Symbols.String()) + } + return syntaxBody, nil +} + +func NewSyntaxBodyGen(symbols, sdtLit interface{}) (*SyntaxBody, error) { + checkSymbols(symbols) + syntaxBody := &SyntaxBody{ + Error: false, + } + if symbols != nil { + syntaxBody.Symbols = symbols.(SyntaxSymbols) + } + if sdtLit != nil { + syntaxBody.SDT = SDTVal(getString(sdtLit)) + } + if symbols == nil { + return nil, fmt.Errorf("empty production alternative!") + } + if s, _ := symbols.(SyntaxSymbols); len(s) > 0 && s[0] == EmptySymbol { + //fmt.Printf(" NewBodyGen(Empty) Symbols=%#v(%s)\n", syntaxBody.Symbols, syntaxBody.Symbols.String()) + } else if s, _ := symbols.(SyntaxSymbols); len(s) > 0 && s[0] == ErrorSymbol { + //fmt.Printf(" NewBodyGen(Error) Symbols=%#v(%s)\n", syntaxBody.Symbols, syntaxBody.Symbols.String()) + } else { + //fmt.Printf(" NewBodyGen() Symbols=%#v(%s)\n", syntaxBody.Symbols, syntaxBody.Symbols.String()) } return syntaxBody, nil } func NewErrorBody(symbols, sdtLit interface{}) (*SyntaxBody, error) { - body, _ := NewSyntaxBody(symbols, sdtLit) - body.Error = true - return body, nil + if symbols == nil { + return nil, fmt.Errorf("empty production alternative") + } else { + symbols.(SyntaxSymbols)[0] = ErrorSymbol + } + //fmt.Printf(" NewErrorBody()\n") + if body, err := NewSyntaxBody(symbols, sdtLit); err != nil { + return nil, err + } else { + body.Error = true + return body, nil + } +} + +func NewErrorBodyGen(symbols, sdtLit interface{}) (*SyntaxBody, error) { + syms, _ := symbols.(SyntaxSymbols) + if syms == nil { + syms = SyntaxSymbols{} + } + //fmt.Printf(" NewErrorBodyGen()\n") + if body, err := NewSyntaxBodyGen(append(SyntaxSymbols{ErrorSymbol}, syms...), sdtLit); err != nil { + return nil, err + } else { + body.Error = true + return body, nil + } } func NewEmptyBody() (*SyntaxBody, error) { - return NewSyntaxBody(nil, nil) + //fmt.Printf(" NewEmptyBody()\n") + return NewSyntaxBody(SyntaxSymbols{EmptySymbol}, nil) } -func (this *SyntaxBody) Empty() bool { +func NewEmptyBodyGen() (*SyntaxBody, error) { + //fmt.Printf(" NewEmptyBodyGen()\n") + return NewSyntaxBodyGen(SyntaxSymbols{EmptySymbol}, nil) +} + +func (this *SyntaxBody) Missing() bool { return len(this.Symbols) == 0 } +func (this *SyntaxBody) Empty() bool { + return len(this.Symbols) == 1 && (this.Symbols[0] == EmptySymbol) +} + func (this *SyntaxBody) String() string { return fmt.Sprintf("%s\t<< %s >>", this.Symbols.String(), this.SDT) } diff --git a/internal/ast/syntaxcontextdependenttokenid.go b/internal/ast/syntaxcontextdependenttokenid.go new file mode 100644 index 00000000..7af3eb44 --- /dev/null +++ b/internal/ast/syntaxcontextdependenttokenid.go @@ -0,0 +1,61 @@ +//Copyright 2013 Vastech SA (PTY) LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import ( + "fmt" + "regexp" + + "github.com/maxcalandrelli/gocc/internal/config" +) + +type SyntaxContextDependentTokId struct { + string + StdSyntaxSymbol + ContexDependentParseFunctionCall string +} + +var ( + tokenIdCount = 0 +) + +func NewContextDependentTokId(tokId, ctxdeplit interface{}) (SyntaxContextDependentTokId, error) { + return NewNewContextDependentTokIdFromString(getString(tokId), getString(ctxdeplit)), nil +} + +func NewNewContextDependentTokIdFromString(tokId, ctxdeplit string) SyntaxContextDependentTokId { + tokenIdCount++ + return SyntaxContextDependentTokId{ + fmt.Sprintf("%s_%d", tokId, tokenIdCount), + StdSyntaxSymbol{}, + regexp.MustCompile("^(?ms:@@\\s*(.*)\\s*@@)$").ReplaceAllString(ctxdeplit, "${1}"), + } +} + +func (this SyntaxContextDependentTokId) SymbolString() string { + return this.string +} + +func (this SyntaxContextDependentTokId) String() string { + return fmt.Sprintf("%s<%s>", config.INTERNAL_SYMBOL_CDTOK, this.string) +} + +func (this SyntaxContextDependentTokId) SymbolName() string { + return fmt.Sprintf("%s<%s>", config.INTERNAL_SYMBOL_CDTOK, this.string) +} + +func (this SyntaxContextDependentTokId) IsTerminal() bool { + return true +} diff --git a/internal/ast/syntaxempty.go b/internal/ast/syntaxempty.go index 80d78c66..328cb3da 100644 --- a/internal/ast/syntaxempty.go +++ b/internal/ast/syntaxempty.go @@ -14,14 +14,27 @@ package ast -type SyntaxEmpty int +import ( + "github.com/maxcalandrelli/gocc/internal/config" +) -const EMPTY SyntaxEmpty = 0 +type SyntaxEmpty struct { + string + StdSyntaxSymbol +} + +var EmptySymbol = SyntaxEmpty{config.SYMBOL_EMPTY, StdSyntaxSymbol{}} func (SyntaxEmpty) SymbolString() string { - return "empty" + return EmptySymbol.string } func (SyntaxEmpty) String() string { - return "empty" + return EmptySymbol.string +} + +func (SyntaxEmpty) IsEpsilon() bool { return true } + +func (SyntaxEmpty) SymbolName() string { + return config.INTERNAL_SYMBOL_EMPTY } diff --git a/internal/ast/syntaxeof.go b/internal/ast/syntaxeof.go index 7aeb6918..a756d122 100644 --- a/internal/ast/syntaxeof.go +++ b/internal/ast/syntaxeof.go @@ -14,14 +14,29 @@ package ast -type SyntaxEof int +import ( + "github.com/maxcalandrelli/gocc/internal/config" +) -var EOF SyntaxEof = 0 +type SyntaxEof struct { + string + StdSyntaxSymbol +} + +var EofSymbol = SyntaxEof{config.SYMBOL_EOF, StdSyntaxSymbol{}} -func (SyntaxEof) SymbolsString() string { - return "$" +func (SyntaxEof) SymbolString() string { + return EofSymbol.string } func (SyntaxEof) String() string { - return "$" + return EofSymbol.string +} + +func (SyntaxEof) SymbolName() string { + return config.INTERNAL_SYMBOL_EOF +} + +func (SyntaxEof) IsTerminal() bool { + return true } diff --git a/internal/ast/syntaxerror.go b/internal/ast/syntaxerror.go index f653132f..b4305bee 100644 --- a/internal/ast/syntaxerror.go +++ b/internal/ast/syntaxerror.go @@ -14,14 +14,29 @@ package ast -type SyntaxError int +import ( + "github.com/maxcalandrelli/gocc/internal/config" +) -const errorConst = SyntaxError(-1) +type SyntaxError struct { + string + StdSyntaxSymbol +} + +var ErrorSymbol = SyntaxError{config.SYMBOL_ERROR, StdSyntaxSymbol{}} func (SyntaxError) SymbolString() string { - return "error" + return ErrorSymbol.string } func (SyntaxError) String() string { - return "error" + return ErrorSymbol.string +} + +func (SyntaxError) IsError() bool { return true } + +func (SyntaxError) IsTerminal() bool { return true } + +func (SyntaxError) SymbolName() string { + return config.INTERNAL_SYMBOL_ERROR } diff --git a/internal/ast/syntaxpart.go b/internal/ast/syntaxpart.go index cdb88b43..0052a6f8 100644 --- a/internal/ast/syntaxpart.go +++ b/internal/ast/syntaxpart.go @@ -35,9 +35,9 @@ func NewSyntaxPart(header, prodList interface{}) (*SyntaxPart, error) { func (this *SyntaxPart) augment() *SyntaxPart { startProd := &SyntaxProd{ - Id: "S'", + Id: SyntaxProdId{"S'", StdSyntaxSymbol{}}, Body: &SyntaxBody{ - Symbols: []SyntaxSymbol{SyntaxProdId(this.ProdList[0].Id)}, + Symbols: SyntaxSymbols{SyntaxProdId{this.ProdList[0].Id.SymbolString(), StdSyntaxSymbol{}}}, }, } newProdList := SyntaxProdList{startProd} diff --git a/internal/ast/syntaxprod.go b/internal/ast/syntaxprod.go index ed255225..17659e51 100644 --- a/internal/ast/syntaxprod.go +++ b/internal/ast/syntaxprod.go @@ -16,22 +16,20 @@ package ast import ( "fmt" - - "github.com/goccmack/gocc/internal/frontend/token" ) type SyntaxProd struct { - Id string + Id SyntaxProdId Body *SyntaxBody } func NewSyntaxProd(prodId, alts interface{}) ([]*SyntaxProd, error) { - pid := string(prodId.(*token.Token).Lit) + pid := getString(prodId) alts1 := alts.(SyntaxAlts) prods := make([]*SyntaxProd, len(alts1)) for i, body := range alts1 { prods[i] = &SyntaxProd{ - Id: pid, + Id: NewSyntaxProdIdFromString(pid), Body: body, } } diff --git a/internal/ast/syntaxprodid.go b/internal/ast/syntaxprodid.go index 59b6980b..18892839 100644 --- a/internal/ast/syntaxprodid.go +++ b/internal/ast/syntaxprodid.go @@ -15,20 +15,41 @@ package ast import ( - "github.com/goccmack/gocc/internal/frontend/token" + "fmt" + + "github.com/maxcalandrelli/gocc/internal/config" ) // Id or name of a grammar(syntax) production -type SyntaxProdId string +type SyntaxProdId struct { + string + StdSyntaxSymbol +} func NewSyntaxProdId(tok interface{}) (SyntaxProdId, error) { - return SyntaxProdId(string(tok.(*token.Token).Lit)), nil + return SyntaxProdId{getString(tok), StdSyntaxSymbol{}}, nil +} + +func NewSyntaxProdIdFromString(str string) SyntaxProdId { + return SyntaxProdId{str, StdSyntaxSymbol{}} } func (this SyntaxProdId) SymbolString() string { - return string(this) + return this.string } func (this SyntaxProdId) String() string { - return string(this) + return this.string +} + +func (this SyntaxProdId) SymbolName() string { + return fmt.Sprintf("%s<%s>", config.INTERNAL_SYMBOL_PROD, this.string) +} + +func (this SyntaxProdId) IsTerminal() bool { + return false +} + +func (this SyntaxProdId) IsNonTerminal() bool { + return true } diff --git a/internal/ast/syntaxstringlit.go b/internal/ast/syntaxstringlit.go index fd2d1383..7f538376 100644 --- a/internal/ast/syntaxstringlit.go +++ b/internal/ast/syntaxstringlit.go @@ -17,24 +17,39 @@ package ast import ( "fmt" - "github.com/goccmack/gocc/internal/frontend/token" + "github.com/maxcalandrelli/gocc/internal/config" ) -type SyntaxStringLit string +type SyntaxStringLit struct { + string + StdSyntaxSymbol +} func NewStringLit(tok interface{}) (SyntaxStringLit, error) { - lit := tok.(*token.Token).Lit - return SyntaxStringLit(lit[1 : len(lit)-1]), nil + lit := getString(tok) + return SyntaxStringLit{lit[1 : len(lit)-1], StdSyntaxSymbol{}}, nil +} + +func NewStringLitFromString(str string) SyntaxStringLit { + return SyntaxStringLit{str, StdSyntaxSymbol{}} } func (this SyntaxStringLit) SymbolString() string { - return string(this) + return this.string } func (this SyntaxStringLit) String() string { - return fmt.Sprintf("\"%s\"", string(this)) + return fmt.Sprintf("\"%s\"", this.string) } func (this SyntaxStringLit) Bytes() []byte { - return []byte(this) + return []byte(this.string) +} + +func (this SyntaxStringLit) SymbolName() string { + return fmt.Sprintf("%s<%s>", config.INTERNAL_SYMBOL_LIT, this.string) +} + +func (this SyntaxStringLit) IsTerminal() bool { + return true } diff --git a/internal/ast/syntaxsubparser.go b/internal/ast/syntaxsubparser.go new file mode 100644 index 00000000..0c44907a --- /dev/null +++ b/internal/ast/syntaxsubparser.go @@ -0,0 +1,69 @@ +//Copyright 2013 Vastech SA (PTY) LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ast + +import ( + "fmt" + "path" + + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/util" +) + +type SyntaxSubParser struct { + string + StdSyntaxSymbol + Alias string + Import string +} + +func NewAliasedSubParser(_alias, _import interface{}) (SyntaxSubParser, error) { + return newSubParser(getString(_alias), getString(_import)) +} + +func NewSubParser(_import interface{}) (SyntaxSubParser, error) { + return newSubParser("", getString(_import)) +} + +func newSubParser(alias, imp string) (SyntaxSubParser, error) { + imp, _, _ = util.EscapedString(imp).Unquote() + if alias == "" { + alias = path.Base(imp) + } else { + alias, _, _ = util.EscapedString(alias).Unquote() + } + return SyntaxSubParser{ + fmt.Sprintf("%s_%d", alias, tokenIdCount), + StdSyntaxSymbol{}, + alias, + imp, + }, nil +} + +func (this SyntaxSubParser) SymbolString() string { + return this.string +} + +func (this SyntaxSubParser) String() string { + return fmt.Sprintf("%s<%s>", config.INTERNAL_SYMBOL_CDTOK, this.string) +} + +func (this SyntaxSubParser) SymbolName() string { + return fmt.Sprintf("%s<%s>", config.INTERNAL_SYMBOL_CDTOK, this.string) +} + +func (this SyntaxSubParser) IsTerminal() bool { + return true +} diff --git a/internal/ast/syntaxsymbol.go b/internal/ast/syntaxsymbol.go index 01571ee5..a524dcaf 100644 --- a/internal/ast/syntaxsymbol.go +++ b/internal/ast/syntaxsymbol.go @@ -14,18 +14,54 @@ package ast +import ( + "github.com/maxcalandrelli/gocc/internal/config" +) + /* All syntax symbols are types of string */ type SyntaxSymbol interface { + SymbolName() string SymbolString() string String() string + IsError() bool + IsEpsilon() bool + IsTerminal() bool + IsNonTerminal() bool gSymbol() } -func (SyntaxEmpty) gSymbol() {} -func (SyntaxEof) gSymbol() {} -func (SyntaxError) gSymbol() {} -func (SyntaxProdId) gSymbol() {} -func (SyntaxTokId) gSymbol() {} -func (SyntaxStringLit) gSymbol() {} +type StdSyntaxSymbol struct{} +type InvalidSyntaxSymbol struct{ StdSyntaxSymbol } + +func (StdSyntaxSymbol) IsError() bool { return false } +func (StdSyntaxSymbol) IsEpsilon() bool { return false } +func (StdSyntaxSymbol) IsTerminal() bool { return false } +func (StdSyntaxSymbol) IsNonTerminal() bool { return false } + +func (SyntaxEmpty) gSymbol() {} +func (SyntaxEof) gSymbol() {} +func (SyntaxError) gSymbol() {} +func (SyntaxProdId) gSymbol() {} +func (SyntaxTokId) gSymbol() {} +func (SyntaxStringLit) gSymbol() {} +func (InvalidSyntaxSymbol) gSymbol() {} +func (SyntaxContextDependentTokId) gSymbol() {} +func (SyntaxSubParser) gSymbol() {} + +func (InvalidSyntaxSymbol) SymbolName() string { + return config.INTERNAL_SYMBOL_INVALID +} + +func (InvalidSyntaxSymbol) SymbolString() string { + return config.INTERNAL_SYMBOL_INVALID +} + +func (InvalidSyntaxSymbol) String() string { + return config.SYMBOL_INVALID +} + +func (InvalidSyntaxSymbol) IsTerminal() bool { + return true +} diff --git a/internal/ast/syntaxsymbols.go b/internal/ast/syntaxsymbols.go index fcb8d84c..c7307517 100644 --- a/internal/ast/syntaxsymbols.go +++ b/internal/ast/syntaxsymbols.go @@ -17,6 +17,8 @@ package ast import ( "fmt" "strings" + + "github.com/maxcalandrelli/gocc/internal/config" ) type SyntaxSymbols []SyntaxSymbol @@ -35,7 +37,35 @@ func (this SyntaxSymbols) String() string { if i > 0 { fmt.Fprintf(w, " ") } - fmt.Fprintf(w, sym.String()) + fmt.Fprintf(w, sym.SymbolName()) } return w.String() } + +func NewSyntaxSymbolsFromToken(tok interface{}) (SyntaxSymbols, error) { + switch getString(tok) { + case config.SYMBOL_EMPTY: + return SyntaxSymbols{EmptySymbol}, nil + case config.SYMBOL_ERROR: + return SyntaxSymbols{ErrorSymbol}, nil + } + sym, err := NewStringLit(tok) + fmt.Printf("LITERAL:<%q>\n", sym) + return SyntaxSymbols{sym}, err +} + +type SyntaxSymbolsByName SyntaxSymbols + +func (s *SyntaxSymbolsByName) Len() int { + return len(*s) +} + +func (s *SyntaxSymbolsByName) Less(i, j int) bool { + return (*s)[i].SymbolString() < (*s)[j].SymbolString() +} + +func (s *SyntaxSymbolsByName) Swap(i, j int) { + t := (*s)[i] + (*s)[i] = (*s)[j] + (*s)[j] = t +} diff --git a/internal/ast/syntaxtokid.go b/internal/ast/syntaxtokid.go index 4d6f75eb..4656cd55 100644 --- a/internal/ast/syntaxtokid.go +++ b/internal/ast/syntaxtokid.go @@ -14,20 +14,31 @@ package ast -import ( - "github.com/goccmack/gocc/internal/frontend/token" -) - -type SyntaxTokId string +type SyntaxTokId struct { + string + StdSyntaxSymbol +} func NewTokId(tokId interface{}) (SyntaxTokId, error) { - return SyntaxTokId(string(tokId.(*token.Token).Lit)), nil + return SyntaxTokId{getString(tokId), StdSyntaxSymbol{}}, nil +} + +func NewTokIdFromString(str string) SyntaxTokId { + return SyntaxTokId{str, StdSyntaxSymbol{}} } func (this SyntaxTokId) SymbolString() string { - return string(this) + return this.string } func (this SyntaxTokId) String() string { - return string(this) + return this.string +} + +func (this SyntaxTokId) SymbolName() string { + return this.string +} + +func (this SyntaxTokId) IsTerminal() bool { + return true } diff --git a/internal/base/gen/gen.go b/internal/base/gen/gen.go new file mode 100644 index 00000000..ea602053 --- /dev/null +++ b/internal/base/gen/gen.go @@ -0,0 +1,24 @@ +//Copyright 2013 Vastech SA (PTY) LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gen + +import ( + "github.com/maxcalandrelli/gocc/internal/base/gen/golang" + "github.com/maxcalandrelli/gocc/internal/config" +) + +func Gen(pkg, outdir, internal, iface string, cfg config.Config, hasSyntax bool) { + golang.Gen(pkg, outdir, internal, iface, cfg, hasSyntax) +} diff --git a/internal/base/gen/golang/base.go b/internal/base/gen/golang/base.go new file mode 100644 index 00000000..4d70c18c --- /dev/null +++ b/internal/base/gen/golang/base.go @@ -0,0 +1,461 @@ +//Copyright 2013 Vastech SA (PTY) LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package golang + +import ( + "bytes" + "fmt" + "go/format" + "path" + "text/template" + + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/io" +) + +type data struct { + MyName string + Pkg string + Outdir string + InternalSubdir string + Config config.Config + HasSyntax bool + IfaceDir string + ExportWindowReader bool +} + +func Gen(pkg, outdir, internal, iface string, cfg config.Config, hasSyntax bool) { + d := data{ + MyName: cfg.ProjectName(), + Pkg: pkg, + Outdir: outdir, + InternalSubdir: internal, + Config: cfg, + HasSyntax: hasSyntax, + IfaceDir: iface, + ExportWindowReader: false, + } + if !cfg.NoLexer() && hasSyntax { + genMain(d) + } + genBase(d) + genUtil(d) + genIface(d) +} + +func genBase(d data) { + basePath := path.Join(d.Outdir, d.MyName+".go") + tmpl, err := template.New(d.MyName).Parse(baseSrc[1:]) + if err != nil { + panic(err) + } + buf := new(bytes.Buffer) + err = tmpl.Execute(buf, d) + source, err := format.Source(buf.Bytes()) + if err != nil { + panic(err) + } + io.WriteFile(basePath, source) +} + +func genUtil(d data) { + basePath := path.Join(d.Outdir, "util.go") + tmpl, err := template.New(d.MyName).Parse(stringUtilSrc[1:]) + if err != nil { + panic(err) + } + buf := new(bytes.Buffer) + err = tmpl.Execute(buf, d) + source, err := format.Source(buf.Bytes()) + if err != nil { + panic(err) + } + io.WriteFile(basePath, source) +} + +func genMain(d data) { + basePath := path.Join(d.Outdir, "main", d.MyName+".go") + tmpl, err := template.New(d.MyName).Parse(mainSrc[1:]) + if err != nil { + panic(err) + } + buf := new(bytes.Buffer) + err = tmpl.Execute(buf, d) + // Use go/format to indent the idMap literal correctly. + source, err := format.Source(buf.Bytes()) + if err != nil { + panic(err) + } + io.WriteFile(basePath, source) +} + +func genIface(d data) { + basePath := path.Join(d.Outdir, d.IfaceDir, fmt.Sprintf("%s.go", d.MyName)) + tmpl, err := template.New(d.MyName).Parse(ifaceSrc[1:]) + if err != nil { + panic(err) + } + buf := new(bytes.Buffer) + err = tmpl.Execute(buf, d) + // Use go/format to indent the idMap literal correctly. + source, err := format.Source(buf.Bytes()) + if err != nil { + panic(err) + } + io.WriteFile(basePath, source) +} + +const baseSrc string = ` +// Code generated by gocc; DO NOT EDIT. + +package {{.MyName}} + +import ( + {{- if not .Config.NoLexer }} + "io" + {{- end}} + + "{{.Pkg}}/{{.InternalSubdir}}/token" + {{- if not .Config.NoLexer }} + "{{.Pkg}}/{{.InternalSubdir}}/lexer" + {{- end}} + {{- if .HasSyntax}} + "{{.Pkg}}/{{.InternalSubdir}}/errors" + "{{.Pkg}}/{{.InternalSubdir}}/parser" + {{- end}} + {{- if .ExportWindowReader }} + "{{.Pkg}}/{{.InternalSubdir}}/io/stream" + {{- end}} +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + {{- if .HasSyntax}} + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + {{- end}} + {{- if not .Config.NoLexer }} + Lexer = lexer.Lexer + {{- end}} + {{- if .ExportWindowReader }} + WindowReader = stream.WindowReader + {{- end}} + {{- if .HasSyntax}} + Parser = parser.Parser + {{- end}} +) + +{{- if .HasSyntax}} +func NewParser() *parser.Parser { + return parser.NewParser() +} + +{{- if not .Config.NoLexer }} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + + +{{- end}} +{{- end}} +{{- if not .Config.NoLexer }} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} +{{- end}} + +{{- if .ExportWindowReader }} +func NewWindowReaderFromBytes(src []byte) WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} +{{- end}} + + +func GetTokenMap() TokenMap { + return token.TokMap +} + +` + +const mainSrc string = ` +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + {{.MyName}} "{{.Pkg}}" +) + +func showResult (r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse (longest bool, lex *{{.MyName}}.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return {{.MyName}}.NewParser().ParseLongestPrefix(lex) + } else { + res, err = {{.MyName}}.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main () { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, {{.MyName}}.NewLexerString(Text))) + } + if File > "" { + l, e := {{.MyName}}.NewLexerFile(File) + if e != nil { panic(e) } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, {{.MyName}}.NewLexerString(str))) + } +} + +` + +const ifaceSrc string = ` +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "io" + "{{.Pkg}}/{{.InternalSubdir}}/token" + {{- if .HasSyntax}} + "{{.Pkg}}/{{.InternalSubdir}}/errors" + {{- end}} + "{{.Pkg}}/{{.InternalSubdir}}/io/stream" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + {{- if .HasSyntax}} + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + {{- end}} + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int)CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } + +) + + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} + + +` + +const stringUtilSrc string = ` +// Code generated by gocc; DO NOT EDIT. + +package {{.MyName}} + +import ( + "{{.Pkg}}/{{.InternalSubdir}}/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} + + + +` diff --git a/internal/config/config.go b/internal/config/config.go index 26d1b88b..4f928db9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -22,49 +22,134 @@ import ( "os" "path" "path/filepath" + "regexp" "strings" ) -type Config interface { - Help() bool - Verbose() bool - Zip() bool - AllowUnreachable() bool - AutoResolveLRConf() bool - SourceFile() string - OutDir() string +const ( + VERSION = "2.1.1001" + + INTERNAL_SYMBOL_EMPTY = "ε" + INTERNAL_SYMBOL_ERROR = "λ" + INTERNAL_SYMBOL_INVALID = "INVALID" + INTERNAL_SYMBOL_EOF = "Ω" + INTERNAL_SYMBOL_PROD = "Π" + INTERNAL_SYMBOL_LIT = "Λ" + INTERNAL_SYMBOL_CDTOK = "μ" + SYMBOL_EMPTY = "ε" + SYMBOL_ERROR = "λ" + SYMBOL_INVALID = "ά" + SYMBOL_EOF = "Ω" + SYMBOL_CDTOK = "μ" +) + +type ( + Config interface { + Help() bool + Verbose() bool + AllowUnreachable() bool + AutoResolveLRConf() bool + SourceFile() string + OutDir() string + InternalSubdir() string + + NoLexer() bool + DebugLexer() bool + DebugParser() bool + + ErrorsDir() string + ParserDir() string + ScannerDir() string + TokenDir() string - NoLexer() bool - DebugLexer() bool - DebugParser() bool + ProjectName() string + Package() string + PreProcessor() string + + PrintParams() + + BugOption(string) bugOption + } - ErrorsDir() string - ParserDir() string - ScannerDir() string - TokenDir() string + bugOption string + bugOptions map[string]bugOption + + ConfigRecord struct { + workingDir string + + allowUnreachable *bool + autoResolveLRConf *bool + debugLexer *bool + debugParser *bool + help *bool + noLexer *bool + outDir string + pkg string + srcFile string + internal string + verbose *bool + bug_options bugOptions + preprocessor string + } +) + +const ( + bugopt_fix = "fix" + bugopt_ignore = "ignore" + bugopt_default = bugopt_fix +) + +func (this bugOption) Fix() bool { + return strings.ToLower(string(this)) != bugopt_ignore +} - ProjectName() string - Package() string +func (this bugOption) Ignore() bool { + return strings.ToLower(string(this)) == bugopt_ignore +} - PrintParams() +func (this bugOptions) String() string { + b := &strings.Builder{} + for k, _ := range bugDescriptions { + v := bugDefaultOption + if _v, _f := this[k]; _f { + v = _v + } + if b.Len() > 0 { + b.WriteByte(',') + } + fmt.Fprintf(b, "%s:%s", k, v) + } + return b.String() } -type ConfigRecord struct { - workingDir string +func (this bugOption) Option() string { + return string(this) +} - allowUnreachable *bool - autoResolveLRConf *bool - debugLexer *bool - debugParser *bool - help *bool - noLexer *bool - outDir string - pkg string - srcFile string - verbose *bool - zip *bool +func (this bugOptions) Set(s string) error { + for _, s1 := range strings.Split(s, ",") { + s1v := strings.Split(s1, ":") + if len(s1v) < 2 { + s1v = append(s1v, bugopt_default) + } + s1v[0] = strings.ToLower(s1v[0]) + if _, found := bugDescriptions[s1v[0]]; !found { + return errors.New("unknown bug name: " + s1v[0]) + } + this[s1v[0]] = bugOption(strings.Join(s1v[1:], "=")) + } + return nil } +var ( + CurrentConfiguration Config + bugDefaultOption = bugOption(bugopt_default) + bugDescriptions = map[string]string{ + "lexer_dots": "dots handling in regexps like \"--.--\" needs propagation of fallback states", + "lexer_regdefs": "incorrect calculation of symbol classes when both a shift and a reduce item exist for the same regdefid", + } +) + func New() (Config, error) { wd, err := os.Getwd() if err != nil { @@ -72,7 +157,8 @@ func New() (Config, error) { } cfg := &ConfigRecord{ - workingDir: wd, + workingDir: wd, + bug_options: map[string]bugOption{}, } if err := cfg.getFlags(); err != nil { @@ -91,10 +177,6 @@ func (this *ConfigRecord) Verbose() bool { return *this.verbose } -func (this *ConfigRecord) Zip() bool { - return *this.zip -} - func (this *ConfigRecord) AllowUnreachable() bool { return *this.allowUnreachable } @@ -139,15 +221,34 @@ func (this *ConfigRecord) TokenDir() string { return path.Join(this.outDir, "token") } +func (this *ConfigRecord) InternalSubdir() string { + return this.internal +} + func (this *ConfigRecord) Package() string { return this.pkg } +func (this *ConfigRecord) PreProcessor() string { + return this.preprocessor +} + func (this *ConfigRecord) ProjectName() string { - _, file := path.Split(this.pkg) + _, file := path.Split(this.srcFile) + file = file[:len(file)-len(path.Ext(file))] return file } +func (this *ConfigRecord) BugOption(name string) bugOption { + if _, exists := bugDescriptions[name]; !exists { + panic("unknown bug name: " + name) + } + if option, exists := this.bug_options[name]; exists { + return option + } + return bugDefaultOption +} + func (this *ConfigRecord) PrintParams() { fmt.Printf("-a = %v\n", *this.autoResolveLRConf) fmt.Printf("-debug_lexer = %v\n", *this.debugLexer) @@ -158,47 +259,89 @@ func (this *ConfigRecord) PrintParams() { fmt.Printf("-p = %v\n", this.pkg) fmt.Printf("-u = %v\n", *this.allowUnreachable) fmt.Printf("-v = %v\n", *this.verbose) - fmt.Printf("-zip = %v\n", *this.zip) + fmt.Printf("-internal = %v\n", this.internal) + fmt.Printf("-bugs = %v\n", this.bug_options.String()) + fmt.Printf("-preprocessor = %v\n", this.preprocessor) } /*** Utility routines ***/ +func bugsHelp(pref string) string { + b := &strings.Builder{} + nl := func() { + b.WriteByte('\n') + b.WriteString(pref) + } + nl() + fmt.Fprintf(b, "use if you suspect that bug fixing strategies are causing other problems") + nl() + fmt.Fprintf(b, "use either --bugs= --bugs= or --bugs=, form") + nl() + fmt.Fprintf(b, "each can be specified as or :") + nl() + fmt.Fprintf(b, " can be either 'fix' or 'ignore'; some bugs will also allow more options") + nl() + fmt.Fprintf(b, "the actually fixable bugs are:") + nl() + for name, descr := range bugDescriptions { + nl() + fmt.Fprintf(b, " %-20s %s", name, descr) + } + nl() + nl() + fmt.Fprintf(b, "example: gocc -v -bugs=lexer_dots:ignore myfile.bnf") + nl() + return b.String() +} + func (this *ConfigRecord) getFlags() error { - this.autoResolveLRConf = flag.Bool("a", false, "automatically resolve LR(1) conflicts") + this.autoResolveLRConf = flag.Bool("a", true, "automatically resolve LR(1) conflicts") this.debugLexer = flag.Bool("debug_lexer", false, "enable debug logging in lexer") this.debugParser = flag.Bool("debug_parser", false, "enable debug logging in parser") this.help = flag.Bool("h", false, "help") this.noLexer = flag.Bool("no_lexer", false, "do not generate a lexer") - flag.StringVar(&this.outDir, "o", this.workingDir, "output dir.") - flag.StringVar(&this.pkg, "p", defaultPackage(this.outDir), "package") + flag.StringVar(&this.outDir, "o", path.Join(this.workingDir, "@f.grammar", "@f"), "output directory format (@f='name' if input file is 'name.bnf')") + flag.StringVar(&this.pkg, "p", "", "package, empty defaults to "+defaultPackage(this.outDir)) + flag.StringVar(&this.internal, "internal", "internal", "internal subdir name") + flag.StringVar(&this.preprocessor, "preprocessor", "none", "preprocessor: 'none','internal', or any command string with placeholders @in and @out") + flag.Var(this.bug_options, "bugs", "handle bugs in original implementation (default: fix all)"+bugsHelp(" ")) this.allowUnreachable = flag.Bool("u", false, "allow unreachable productions") this.verbose = flag.Bool("v", false, "verbose") - this.zip = flag.Bool("zip", false, "zip the actiontable and gototable (experimental)") flag.Parse() if *this.noLexer && *this.debugLexer { return errors.New("no_lexer and debug_lexer cannot both be set") } - - this.outDir = getOutDir(this.outDir, this.workingDir) - if this.outDir != this.workingDir { - this.pkg = defaultPackage(this.outDir) - } - if len(flag.Args()) != 1 && !*this.help { return errors.New("Too few arguments") } this.srcFile = flag.Arg(0) - + this.outDir = getOutDir(this.outDir, this.workingDir, this.srcFile) + if this.pkg == "" { + this.pkg = defaultPackage(this.outDir) + } + this.pkg = actualize(this.pkg, this.srcFile) return nil } -func getOutDir(outDirSpec, wd string) string { - if strings.HasPrefix(outDirSpec, wd) { - return outDirSpec - } - return path.Join(wd, outDirSpec) +func actualize(pattern, src string) string { + _, fname := path.Split(src) + fname = fname[:len(fname)-len(path.Ext(fname))] + return regexp.MustCompile("@f").ReplaceAllString(pattern, fname) +} + +func getOutDir(outDirSpec, wd, src string) string { + pattern := func() string { + if strings.HasPrefix(outDirSpec, wd) { + return outDirSpec + } + if path.IsAbs(outDirSpec) { + return outDirSpec + } + return path.Join(wd, outDirSpec) + }() + return actualize(pattern, src) } func defaultPackage(wd string) string { diff --git a/internal/frontend/reparsed/gocc2.go b/internal/frontend/reparsed/gocc2.go new file mode 100644 index 00000000..9f2b32c7 --- /dev/null +++ b/internal/frontend/reparsed/gocc2.go @@ -0,0 +1,131 @@ +// Code generated by gocc; DO NOT EDIT. + +package gocc2 + +import ( + "io" + + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/errors" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/lexer" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/parser" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/token" +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + Lexer = lexer.Lexer + Parser = parser.Parser +) + +func NewParser() *parser.Parser { + return parser.NewParser() +} + +func ParseFile(fpath string) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().Parse(lexer) + } else { + return nil, err + } +} + +func ParseText(text string) (interface{}, error) { + return NewParser().Parse(NewLexerBytes([]byte(text))) +} + +func Parse(stream io.Reader) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().Parse(lex) +} + +func ParseFileWithData(fpath string, userData interface{}) (interface{}, error) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).Parse(lexer) + } else { + return nil, err + } +} + +func ParseTextWithData(text string, userData interface{}) (interface{}, error) { + return NewParser().SetContext(userData).Parse(NewLexerBytes([]byte(text))) +} + +func ParseWithData(stream io.Reader, userData interface{}) (interface{}, error) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err + } + return NewParser().SetContext(userData).Parse(lex) +} + +func ParseFilePartial(fpath string) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextPartial(text string) (interface{}, error, []byte) { + return NewParser().ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParsePartial(stream io.Reader) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().ParseLongestPrefix(lex) +} + +func ParseFileWithDataPartial(fpath string, userData interface{}) (interface{}, error, []byte) { + if lexer, err := NewLexerFile(fpath); err == nil { + return NewParser().SetContext(userData).ParseLongestPrefix(lexer) + } else { + return nil, err, []byte{} + } +} + +func ParseTextWithDataPartial(text string, userData interface{}) (interface{}, error, []byte) { + return NewParser().SetContext(userData).ParseLongestPrefix(NewLexerBytes([]byte(text))) +} + +func ParseWithDataPartial(stream io.Reader, userData interface{}) (interface{}, error, []byte) { + lex, err := NewLexer(stream) + if lex == nil { + return nil, err, []byte{} + } + return NewParser().SetContext(userData).ParseLongestPrefix(lex) +} + +func NewLexerBytes(src []byte) *lexer.Lexer { + return lexer.NewLexerBytes(src) +} + +func NewLexerString(src string) *lexer.Lexer { + return lexer.NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*lexer.Lexer, error) { + return lexer.NewLexerFile(fpath) +} + +func NewLexer(reader io.Reader) (*lexer.Lexer, error) { + return lexer.NewLexer(reader) +} + +func GetTokenMap() TokenMap { + return token.TokMap +} diff --git a/internal/frontend/reparsed/iface/gocc2.go b/internal/frontend/reparsed/iface/gocc2.go new file mode 100644 index 00000000..c1dc98f3 --- /dev/null +++ b/internal/frontend/reparsed/iface/gocc2.go @@ -0,0 +1,63 @@ +// Code generated by gocc; DO NOT EDIT. + +package iface + +import ( + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/errors" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/io/stream" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/token" + "io" +) + +type ( + Token = token.Token + TokenMap = token.TokenMap + Pos = token.Pos + ErrorSymbol = errors.ErrorSymbol + Error = errors.Error + + Scanner interface { + Scan() (tok *Token) + } + + StreamScanner interface { + GetStream() TokenStream + } + + CheckPoint interface { + DistanceFrom(CheckPoint) int + Advance(int) CheckPoint + } + + CheckPointable interface { + GetCheckPoint() CheckPoint + GotoCheckPoint(CheckPoint) + } + + TokenStream interface { + io.Reader + io.RuneScanner + io.Seeker + } +) + +const ( + INVALID = token.INVALID + EOF = token.EOF +) + +func GetTokenMap() TokenMap { + return token.TokMap +} + +func NewWindowReaderFromBytes(src []byte) stream.WindowReader { + return stream.NewWindowReaderFromBytes(src) +} + +func NewWindowReader(rdr io.Reader) stream.WindowReader { + return stream.NewWindowReader(rdr) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) stream.WindowReader { + return stream.NewLimitedWindowReader(rdr, sizeMin, sizeMax) +} diff --git a/example/bools/errors/errors.go b/internal/frontend/reparsed/internal/errors/errors.go old mode 100755 new mode 100644 similarity index 94% rename from example/bools/errors/errors.go rename to internal/frontend/reparsed/internal/errors/errors.go index f5b52772..0977f1f7 --- a/example/bools/errors/errors.go +++ b/internal/frontend/reparsed/internal/errors/errors.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/example/bools/token" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/token" ) type ErrorSymbol interface { diff --git a/internal/frontend/reparsed/internal/io/stream/internal/stream_impl.go b/internal/frontend/reparsed/internal/io/stream/internal/stream_impl.go new file mode 100644 index 00000000..358aa160 --- /dev/null +++ b/internal/frontend/reparsed/internal/io/stream/internal/stream_impl.go @@ -0,0 +1,275 @@ +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} diff --git a/internal/frontend/reparsed/internal/io/stream/internal/stream_public.go b/internal/frontend/reparsed/internal/io/stream/internal/stream_public.go new file mode 100644 index 00000000..20ed7b5e --- /dev/null +++ b/internal/frontend/reparsed/internal/io/stream/internal/stream_public.go @@ -0,0 +1,101 @@ +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} diff --git a/internal/frontend/reparsed/internal/io/stream/stream.go b/internal/frontend/reparsed/internal/io/stream/stream.go new file mode 100644 index 00000000..7268d341 --- /dev/null +++ b/internal/frontend/reparsed/internal/io/stream/stream.go @@ -0,0 +1,39 @@ +package stream + +import ( + internal "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/io/stream/internal" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} diff --git a/internal/frontend/reparsed/internal/lexer/acttab.go b/internal/frontend/reparsed/internal/lexer/acttab.go new file mode 100644 index 00000000..1dcea7b2 --- /dev/null +++ b/internal/frontend/reparsed/internal/lexer/acttab.go @@ -0,0 +1,479 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + "fmt" + + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/token" +) + +type ActionTable [NumStates]ActionRow + +type ActionRow struct { + Accept token.Type + Ignore string +} + +func (a ActionRow) String() string { + return fmt.Sprintf("Accept=%d, Ignore=%s", a.Accept, a.Ignore) +} + +var ActTab = ActionTable{ + ActionRow{ // S0, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S1, Ignore("!whitespace") + Accept: -1, + Ignore: "!whitespace", + }, + ActionRow{ // S2, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S3, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S4, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S5, Accept("Λ<(>") + Accept: 12, + Ignore: "", + }, + ActionRow{ // S6, Accept("Λ<)>") + Accept: 13, + Ignore: "", + }, + ActionRow{ // S7, Accept("Λ<->") + Accept: 10, + Ignore: "", + }, + ActionRow{ // S8, Accept("Λ<.>") + Accept: 8, + Ignore: "", + }, + ActionRow{ // S9, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S10, Accept("Λ<:>") + Accept: 3, + Ignore: "", + }, + ActionRow{ // S11, Accept("Λ<;>") + Accept: 4, + Ignore: "", + }, + ActionRow{ // S12, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S13, Accept("Λ<@>") + Accept: 22, + Ignore: "", + }, + ActionRow{ // S14, Accept("prodId") + Accept: 19, + Ignore: "", + }, + ActionRow{ // S15, Accept("Λ<[>") + Accept: 14, + Ignore: "", + }, + ActionRow{ // S16, Accept("Λ<]>") + Accept: 15, + Ignore: "", + }, + ActionRow{ // S17, Accept("regDefId") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S18, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S19, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S20, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S21, Accept("Λ<{>") + Accept: 16, + Ignore: "", + }, + ActionRow{ // S22, Accept("Λ<|>") + Accept: 7, + Ignore: "", + }, + ActionRow{ // S23, Accept("Λ<}>") + Accept: 17, + Ignore: "", + }, + ActionRow{ // S24, Accept("Λ<~>") + Accept: 11, + Ignore: "", + }, + ActionRow{ // S25, Accept("Λ<ε>") + Accept: 26, + Ignore: "", + }, + ActionRow{ // S26, Accept("Λ<λ>") + Accept: 24, + Ignore: "", + }, + ActionRow{ // S27, Accept("ignoredTokId") + Accept: 6, + Ignore: "", + }, + ActionRow{ // S28, Accept("string_lit") + Accept: 20, + Ignore: "", + }, + ActionRow{ // S29, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S30, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S31, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S32, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S33, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S34, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S35, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S36, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S37, Accept("prodId") + Accept: 19, + Ignore: "", + }, + ActionRow{ // S38, Accept("prodId") + Accept: 19, + Ignore: "", + }, + ActionRow{ // S39, Accept("prodId") + Accept: 19, + Ignore: "", + }, + ActionRow{ // S40, Accept("prodId") + Accept: 19, + Ignore: "", + }, + ActionRow{ // S41, Accept("regDefId") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S42, Accept("regDefId") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S43, Accept("regDefId") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S44, Accept("regDefId") + Accept: 5, + Ignore: "", + }, + ActionRow{ // S45, Accept("string_lit") + Accept: 20, + Ignore: "", + }, + ActionRow{ // S46, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S47, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S48, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S49, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S50, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S51, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S52, Accept("ignoredTokId") + Accept: 6, + Ignore: "", + }, + ActionRow{ // S53, Accept("ignoredTokId") + Accept: 6, + Ignore: "", + }, + ActionRow{ // S54, Accept("ignoredTokId") + Accept: 6, + Ignore: "", + }, + ActionRow{ // S55, Accept("ignoredTokId") + Accept: 6, + Ignore: "", + }, + ActionRow{ // S56, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S57, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S58, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S59, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S60, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S61, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S62, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S63, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S64, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S65, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S66, Accept("char_lit") + Accept: 9, + Ignore: "", + }, + ActionRow{ // S67, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S68, Ignore("!comment") + Accept: -1, + Ignore: "!comment", + }, + ActionRow{ // S69, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S70, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S71, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S72, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S73, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S74, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S75, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S76, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S77, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S78, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S79, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S80, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S81, Ignore("!comment") + Accept: -1, + Ignore: "!comment", + }, + ActionRow{ // S82, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S83, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S84, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S85, Accept("tokId") + Accept: 2, + Ignore: "", + }, + ActionRow{ // S86, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S87, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S88, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S89, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S90, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S91, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S92, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S93, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S94, Accept("g_sdt_lit") + Accept: 18, + Ignore: "", + }, + ActionRow{ // S95, Accept("g_ctxdep_lit") + Accept: 21, + Ignore: "", + }, + ActionRow{ // S96, Accept("Λ") + Accept: 25, + Ignore: "", + }, + ActionRow{ // S97, Accept("Λ") + Accept: 23, + Ignore: "", + }, + ActionRow{ // S98, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S99, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S100, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S101, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S102, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S103, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S104, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S105, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S106, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S107, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S108, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S109, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S110, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S111, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S112, + Accept: 0, + Ignore: "", + }, + ActionRow{ // S113, + Accept: 0, + Ignore: "", + }, +} diff --git a/internal/frontend/reparsed/internal/lexer/lexer.go b/internal/frontend/reparsed/internal/lexer/lexer.go new file mode 100644 index 00000000..b7007712 --- /dev/null +++ b/internal/frontend/reparsed/internal/lexer/lexer.go @@ -0,0 +1,174 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +import ( + + "io" + "bytes" + "os" + + + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/iface" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/token" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/io/stream" +) + +const ( + NoState = -1 + NumStates = 114 + NumSymbols = 84 + INVALID_RUNE = rune(-1) +) + +type position struct { + token.Pos +} + +type Lexer struct { + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() + return lexer +} + +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + +func NewLexerFile(fpath string) (*Lexer, error) { + s, err := os.Open(fpath) + if err != nil { + return nil, err + } + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) +} + +func (l *Lexer) Scan() (tok *token.Token) { + tok = new(token.Token) + tok.Type = token.INVALID + start := l.position + state := 0 + for state != -1 { + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + if size > 0 { + l.position.Pos.Offset += size + } + nextState := -1 + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) + } + state = nextState + if state != -1 { + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } + switch { + case ActTab[state].Accept != -1: + tok.Type = ActTab[state].Accept + tok.Lit = append(tok.Lit, string(curr)...) + case ActTab[state].Ignore != "": + start = l.position + state = 0 + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) + } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } + } + tok.Pos = start.Pos + return +} + +func (l *Lexer) Reset() { + l.position.Reset() +} + +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} diff --git a/internal/frontend/reparsed/internal/lexer/transitiontable.go b/internal/frontend/reparsed/internal/lexer/transitiontable.go new file mode 100644 index 00000000..d3a6dd33 --- /dev/null +++ b/internal/frontend/reparsed/internal/lexer/transitiontable.go @@ -0,0 +1,1380 @@ +// Code generated by gocc; DO NOT EDIT. + +package lexer + +/* +Let s be the current state +Let r be the current input rune +transitionTable[s](r) returns the next state. +*/ +type TransitionTable [NumStates]func(rune) int + +var TransTab = TransitionTable{ + // S0 + func(r rune) int { + switch { + case r == 9: // ['\t','\t'] + return 1 + case r == 10: // ['\n','\n'] + return 1 + case r == 13: // ['\r','\r'] + return 1 + case r == 32: // [' ',' '] + return 1 + case r == 33: // ['!','!'] + return 2 + case r == 34: // ['"','"'] + return 3 + case r == 39: // [''','''] + return 4 + case r == 40: // ['(','('] + return 5 + case r == 41: // [')',')'] + return 6 + case r == 45: // ['-','-'] + return 7 + case r == 46: // ['.','.'] + return 8 + case r == 47: // ['/','/'] + return 9 + case r == 58: // [':',':'] + return 10 + case r == 59: // [';',';'] + return 11 + case r == 60: // ['<','<'] + return 12 + case r == 64: // ['@','@'] + return 13 + case 65 <= r && r <= 90: // ['A','Z'] + return 14 + case r == 91: // ['[','['] + return 15 + case r == 93: // [']',']'] + return 16 + case r == 95: // ['_','_'] + return 17 + case r == 96: // ['`','`'] + return 18 + case 97 <= r && r <= 100: // ['a','d'] + return 19 + case r == 101: // ['e','e'] + return 20 + case 102 <= r && r <= 122: // ['f','z'] + return 19 + case r == 123: // ['{','{'] + return 21 + case r == 124: // ['|','|'] + return 22 + case r == 125: // ['}','}'] + return 23 + case r == 126: // ['~','~'] + return 24 + case r == 949: // [\u03b5,\u03b5] + return 25 + case r == 955: // [\u03bb,\u03bb] + return 26 + } + return NoState + }, + // S1 + func(r rune) int { + switch { + } + return NoState + }, + // S2 + func(r rune) int { + switch { + case 97 <= r && r <= 122: // ['a','z'] + return 27 + } + return NoState + }, + // S3 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 28 + case r == 92: // ['\','\'] + return 29 + default: + return 30 + } + }, + // S4 + func(r rune) int { + switch { + case r == 92: // ['\','\'] + return 31 + default: + return 32 + } + }, + // S5 + func(r rune) int { + switch { + } + return NoState + }, + // S6 + func(r rune) int { + switch { + } + return NoState + }, + // S7 + func(r rune) int { + switch { + } + return NoState + }, + // S8 + func(r rune) int { + switch { + } + return NoState + }, + // S9 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 33 + case r == 47: // ['/','/'] + return 34 + } + return NoState + }, + // S10 + func(r rune) int { + switch { + } + return NoState + }, + // S11 + func(r rune) int { + switch { + } + return NoState + }, + // S12 + func(r rune) int { + switch { + case r == 60: // ['<','<'] + return 35 + } + return NoState + }, + // S13 + func(r rune) int { + switch { + case r == 64: // ['@','@'] + return 36 + } + return NoState + }, + // S14 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + case 65 <= r && r <= 90: // ['A','Z'] + return 38 + case r == 95: // ['_','_'] + return 39 + case 97 <= r && r <= 122: // ['a','z'] + return 40 + } + return NoState + }, + // S15 + func(r rune) int { + switch { + } + return NoState + }, + // S16 + func(r rune) int { + switch { + } + return NoState + }, + // S17 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 41 + case 65 <= r && r <= 90: // ['A','Z'] + return 42 + case r == 95: // ['_','_'] + return 43 + case 97 <= r && r <= 122: // ['a','z'] + return 44 + } + return NoState + }, + // S18 + func(r rune) int { + switch { + case r == 96: // ['`','`'] + return 45 + default: + return 18 + } + }, + // S19 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 122: // ['a','z'] + return 49 + } + return NoState + }, + // S20 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 108: // ['a','l'] + return 49 + case r == 109: // ['m','m'] + return 50 + case 110 <= r && r <= 113: // ['n','q'] + return 49 + case r == 114: // ['r','r'] + return 51 + case 115 <= r && r <= 122: // ['s','z'] + return 49 + } + return NoState + }, + // S21 + func(r rune) int { + switch { + } + return NoState + }, + // S22 + func(r rune) int { + switch { + } + return NoState + }, + // S23 + func(r rune) int { + switch { + } + return NoState + }, + // S24 + func(r rune) int { + switch { + } + return NoState + }, + // S25 + func(r rune) int { + switch { + } + return NoState + }, + // S26 + func(r rune) int { + switch { + } + return NoState + }, + // S27 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 52 + case 65 <= r && r <= 90: // ['A','Z'] + return 53 + case r == 95: // ['_','_'] + return 54 + case 97 <= r && r <= 122: // ['a','z'] + return 55 + } + return NoState + }, + // S28 + func(r rune) int { + switch { + } + return NoState + }, + // S29 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 56 + case r == 39: // [''','''] + return 56 + case 48 <= r && r <= 55: // ['0','7'] + return 57 + case r == 85: // ['U','U'] + return 58 + case r == 92: // ['\','\'] + return 56 + case r == 97: // ['a','a'] + return 56 + case r == 98: // ['b','b'] + return 56 + case r == 102: // ['f','f'] + return 56 + case r == 110: // ['n','n'] + return 56 + case r == 114: // ['r','r'] + return 56 + case r == 116: // ['t','t'] + return 56 + case r == 117: // ['u','u'] + return 59 + case r == 118: // ['v','v'] + return 56 + case r == 120: // ['x','x'] + return 60 + default: + return 30 + } + }, + // S30 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 28 + case r == 92: // ['\','\'] + return 29 + default: + return 30 + } + }, + // S31 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 61 + case r == 39: // [''','''] + return 61 + case 48 <= r && r <= 55: // ['0','7'] + return 62 + case r == 85: // ['U','U'] + return 63 + case r == 92: // ['\','\'] + return 61 + case r == 97: // ['a','a'] + return 61 + case r == 98: // ['b','b'] + return 61 + case r == 102: // ['f','f'] + return 61 + case r == 110: // ['n','n'] + return 61 + case r == 114: // ['r','r'] + return 61 + case r == 116: // ['t','t'] + return 61 + case r == 117: // ['u','u'] + return 64 + case r == 118: // ['v','v'] + return 61 + case r == 120: // ['x','x'] + return 65 + default: + return 32 + } + }, + // S32 + func(r rune) int { + switch { + case r == 39: // [''','''] + return 66 + } + return NoState + }, + // S33 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 67 + default: + return 33 + } + }, + // S34 + func(r rune) int { + switch { + case r == 10: // ['\n','\n'] + return 68 + default: + return 34 + } + }, + // S35 + func(r rune) int { + switch { + default: + return 69 + } + }, + // S36 + func(r rune) int { + switch { + default: + return 70 + } + }, + // S37 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + case 65 <= r && r <= 90: // ['A','Z'] + return 38 + case r == 95: // ['_','_'] + return 39 + case 97 <= r && r <= 122: // ['a','z'] + return 40 + } + return NoState + }, + // S38 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + case 65 <= r && r <= 90: // ['A','Z'] + return 38 + case r == 95: // ['_','_'] + return 39 + case 97 <= r && r <= 122: // ['a','z'] + return 40 + } + return NoState + }, + // S39 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + case 65 <= r && r <= 90: // ['A','Z'] + return 38 + case r == 95: // ['_','_'] + return 39 + case 97 <= r && r <= 122: // ['a','z'] + return 40 + } + return NoState + }, + // S40 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 37 + case 65 <= r && r <= 90: // ['A','Z'] + return 38 + case r == 95: // ['_','_'] + return 39 + case 97 <= r && r <= 122: // ['a','z'] + return 40 + } + return NoState + }, + // S41 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 41 + case 65 <= r && r <= 90: // ['A','Z'] + return 42 + case r == 95: // ['_','_'] + return 43 + case 97 <= r && r <= 122: // ['a','z'] + return 44 + } + return NoState + }, + // S42 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 41 + case 65 <= r && r <= 90: // ['A','Z'] + return 42 + case r == 95: // ['_','_'] + return 43 + case 97 <= r && r <= 122: // ['a','z'] + return 44 + } + return NoState + }, + // S43 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 41 + case 65 <= r && r <= 90: // ['A','Z'] + return 42 + case r == 95: // ['_','_'] + return 43 + case 97 <= r && r <= 122: // ['a','z'] + return 44 + } + return NoState + }, + // S44 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 41 + case 65 <= r && r <= 90: // ['A','Z'] + return 42 + case r == 95: // ['_','_'] + return 43 + case 97 <= r && r <= 122: // ['a','z'] + return 44 + } + return NoState + }, + // S45 + func(r rune) int { + switch { + } + return NoState + }, + // S46 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 122: // ['a','z'] + return 49 + } + return NoState + }, + // S47 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 122: // ['a','z'] + return 49 + } + return NoState + }, + // S48 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 122: // ['a','z'] + return 49 + } + return NoState + }, + // S49 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 122: // ['a','z'] + return 49 + } + return NoState + }, + // S50 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 111: // ['a','o'] + return 49 + case r == 112: // ['p','p'] + return 71 + case 113 <= r && r <= 122: // ['q','z'] + return 49 + } + return NoState + }, + // S51 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 113: // ['a','q'] + return 49 + case r == 114: // ['r','r'] + return 72 + case 115 <= r && r <= 122: // ['s','z'] + return 49 + } + return NoState + }, + // S52 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 52 + case 65 <= r && r <= 90: // ['A','Z'] + return 53 + case r == 95: // ['_','_'] + return 54 + case 97 <= r && r <= 122: // ['a','z'] + return 55 + } + return NoState + }, + // S53 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 52 + case 65 <= r && r <= 90: // ['A','Z'] + return 53 + case r == 95: // ['_','_'] + return 54 + case 97 <= r && r <= 122: // ['a','z'] + return 55 + } + return NoState + }, + // S54 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 52 + case 65 <= r && r <= 90: // ['A','Z'] + return 53 + case r == 95: // ['_','_'] + return 54 + case 97 <= r && r <= 122: // ['a','z'] + return 55 + } + return NoState + }, + // S55 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 52 + case 65 <= r && r <= 90: // ['A','Z'] + return 53 + case r == 95: // ['_','_'] + return 54 + case 97 <= r && r <= 122: // ['a','z'] + return 55 + } + return NoState + }, + // S56 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 28 + case r == 92: // ['\','\'] + return 29 + default: + return 30 + } + }, + // S57 + func(r rune) int { + switch { + case 48 <= r && r <= 55: // ['0','7'] + return 73 + default: + return 30 + } + }, + // S58 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 74 + case 65 <= r && r <= 70: // ['A','F'] + return 74 + case 97 <= r && r <= 102: // ['a','f'] + return 74 + default: + return 30 + } + }, + // S59 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 75 + case 65 <= r && r <= 70: // ['A','F'] + return 75 + case 97 <= r && r <= 102: // ['a','f'] + return 75 + default: + return 30 + } + }, + // S60 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 76 + case 65 <= r && r <= 70: // ['A','F'] + return 76 + case 97 <= r && r <= 102: // ['a','f'] + return 76 + default: + return 30 + } + }, + // S61 + func(r rune) int { + switch { + case r == 39: // [''','''] + return 66 + default: + return 32 + } + }, + // S62 + func(r rune) int { + switch { + case 48 <= r && r <= 55: // ['0','7'] + return 77 + default: + return 32 + } + }, + // S63 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 78 + case 65 <= r && r <= 70: // ['A','F'] + return 78 + case 97 <= r && r <= 102: // ['a','f'] + return 78 + default: + return 32 + } + }, + // S64 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 79 + case 65 <= r && r <= 70: // ['A','F'] + return 79 + case 97 <= r && r <= 102: // ['a','f'] + return 79 + default: + return 32 + } + }, + // S65 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 80 + case 65 <= r && r <= 70: // ['A','F'] + return 80 + case 97 <= r && r <= 102: // ['a','f'] + return 80 + default: + return 32 + } + }, + // S66 + func(r rune) int { + switch { + } + return NoState + }, + // S67 + func(r rune) int { + switch { + case r == 42: // ['*','*'] + return 67 + case r == 47: // ['/','/'] + return 81 + default: + return 33 + } + }, + // S68 + func(r rune) int { + switch { + } + return NoState + }, + // S69 + func(r rune) int { + switch { + case r == 62: // ['>','>'] + return 82 + default: + return 69 + } + }, + // S70 + func(r rune) int { + switch { + case r == 64: // ['@','@'] + return 83 + default: + return 70 + } + }, + // S71 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 115: // ['a','s'] + return 49 + case r == 116: // ['t','t'] + return 84 + case 117 <= r && r <= 122: // ['u','z'] + return 49 + } + return NoState + }, + // S72 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 110: // ['a','n'] + return 49 + case r == 111: // ['o','o'] + return 85 + case 112 <= r && r <= 122: // ['p','z'] + return 49 + } + return NoState + }, + // S73 + func(r rune) int { + switch { + case 48 <= r && r <= 55: // ['0','7'] + return 86 + default: + return 30 + } + }, + // S74 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 87 + case 65 <= r && r <= 70: // ['A','F'] + return 87 + case 97 <= r && r <= 102: // ['a','f'] + return 87 + default: + return 30 + } + }, + // S75 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 88 + case 65 <= r && r <= 70: // ['A','F'] + return 88 + case 97 <= r && r <= 102: // ['a','f'] + return 88 + default: + return 30 + } + }, + // S76 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 89 + case 65 <= r && r <= 70: // ['A','F'] + return 89 + case 97 <= r && r <= 102: // ['a','f'] + return 89 + default: + return 30 + } + }, + // S77 + func(r rune) int { + switch { + case 48 <= r && r <= 55: // ['0','7'] + return 90 + default: + return 32 + } + }, + // S78 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 91 + case 65 <= r && r <= 70: // ['A','F'] + return 91 + case 97 <= r && r <= 102: // ['a','f'] + return 91 + default: + return 32 + } + }, + // S79 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 92 + case 65 <= r && r <= 70: // ['A','F'] + return 92 + case 97 <= r && r <= 102: // ['a','f'] + return 92 + default: + return 32 + } + }, + // S80 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 93 + case 65 <= r && r <= 70: // ['A','F'] + return 93 + case 97 <= r && r <= 102: // ['a','f'] + return 93 + default: + return 32 + } + }, + // S81 + func(r rune) int { + switch { + } + return NoState + }, + // S82 + func(r rune) int { + switch { + case r == 62: // ['>','>'] + return 94 + default: + return 69 + } + }, + // S83 + func(r rune) int { + switch { + case r == 64: // ['@','@'] + return 95 + default: + return 70 + } + }, + // S84 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 120: // ['a','x'] + return 49 + case r == 121: // ['y','y'] + return 96 + case r == 122: // ['z','z'] + return 49 + } + return NoState + }, + // S85 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 113: // ['a','q'] + return 49 + case r == 114: // ['r','r'] + return 97 + case 115 <= r && r <= 122: // ['s','z'] + return 49 + } + return NoState + }, + // S86 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 28 + case r == 92: // ['\','\'] + return 29 + default: + return 30 + } + }, + // S87 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 98 + case 65 <= r && r <= 70: // ['A','F'] + return 98 + case 97 <= r && r <= 102: // ['a','f'] + return 98 + default: + return 30 + } + }, + // S88 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 99 + case 65 <= r && r <= 70: // ['A','F'] + return 99 + case 97 <= r && r <= 102: // ['a','f'] + return 99 + default: + return 30 + } + }, + // S89 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 28 + case r == 92: // ['\','\'] + return 29 + default: + return 30 + } + }, + // S90 + func(r rune) int { + switch { + case r == 39: // [''','''] + return 66 + default: + return 32 + } + }, + // S91 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 100 + case 65 <= r && r <= 70: // ['A','F'] + return 100 + case 97 <= r && r <= 102: // ['a','f'] + return 100 + default: + return 32 + } + }, + // S92 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 101 + case 65 <= r && r <= 70: // ['A','F'] + return 101 + case 97 <= r && r <= 102: // ['a','f'] + return 101 + default: + return 32 + } + }, + // S93 + func(r rune) int { + switch { + case r == 39: // [''','''] + return 66 + default: + return 32 + } + }, + // S94 + func(r rune) int { + switch { + } + return NoState + }, + // S95 + func(r rune) int { + switch { + } + return NoState + }, + // S96 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 122: // ['a','z'] + return 49 + } + return NoState + }, + // S97 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 46 + case 65 <= r && r <= 90: // ['A','Z'] + return 47 + case r == 95: // ['_','_'] + return 48 + case 97 <= r && r <= 122: // ['a','z'] + return 49 + } + return NoState + }, + // S98 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 102 + case 65 <= r && r <= 70: // ['A','F'] + return 102 + case 97 <= r && r <= 102: // ['a','f'] + return 102 + default: + return 30 + } + }, + // S99 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 103 + case 65 <= r && r <= 70: // ['A','F'] + return 103 + case 97 <= r && r <= 102: // ['a','f'] + return 103 + default: + return 30 + } + }, + // S100 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 104 + case 65 <= r && r <= 70: // ['A','F'] + return 104 + case 97 <= r && r <= 102: // ['a','f'] + return 104 + default: + return 32 + } + }, + // S101 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 105 + case 65 <= r && r <= 70: // ['A','F'] + return 105 + case 97 <= r && r <= 102: // ['a','f'] + return 105 + default: + return 32 + } + }, + // S102 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 106 + case 65 <= r && r <= 70: // ['A','F'] + return 106 + case 97 <= r && r <= 102: // ['a','f'] + return 106 + default: + return 30 + } + }, + // S103 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 28 + case r == 92: // ['\','\'] + return 29 + default: + return 30 + } + }, + // S104 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 107 + case 65 <= r && r <= 70: // ['A','F'] + return 107 + case 97 <= r && r <= 102: // ['a','f'] + return 107 + default: + return 32 + } + }, + // S105 + func(r rune) int { + switch { + case r == 39: // [''','''] + return 66 + default: + return 32 + } + }, + // S106 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 108 + case 65 <= r && r <= 70: // ['A','F'] + return 108 + case 97 <= r && r <= 102: // ['a','f'] + return 108 + default: + return 30 + } + }, + // S107 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 109 + case 65 <= r && r <= 70: // ['A','F'] + return 109 + case 97 <= r && r <= 102: // ['a','f'] + return 109 + default: + return 32 + } + }, + // S108 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 110 + case 65 <= r && r <= 70: // ['A','F'] + return 110 + case 97 <= r && r <= 102: // ['a','f'] + return 110 + default: + return 30 + } + }, + // S109 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 111 + case 65 <= r && r <= 70: // ['A','F'] + return 111 + case 97 <= r && r <= 102: // ['a','f'] + return 111 + default: + return 32 + } + }, + // S110 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 112 + case 65 <= r && r <= 70: // ['A','F'] + return 112 + case 97 <= r && r <= 102: // ['a','f'] + return 112 + default: + return 30 + } + }, + // S111 + func(r rune) int { + switch { + case 48 <= r && r <= 57: // ['0','9'] + return 113 + case 65 <= r && r <= 70: // ['A','F'] + return 113 + case 97 <= r && r <= 102: // ['a','f'] + return 113 + default: + return 32 + } + }, + // S112 + func(r rune) int { + switch { + case r == 34: // ['"','"'] + return 28 + case r == 92: // ['\','\'] + return 29 + default: + return 30 + } + }, + // S113 + func(r rune) int { + switch { + case r == 39: // [''','''] + return 66 + default: + return 32 + } + }, +} diff --git a/internal/frontend/reparsed/internal/parser/action.go b/internal/frontend/reparsed/internal/parser/action.go new file mode 100644 index 00000000..54bc55e9 --- /dev/null +++ b/internal/frontend/reparsed/internal/parser/action.go @@ -0,0 +1,51 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" +) + +type action interface { + act() + String() string +} + +type ( + accept bool + shift int // value is next state index + reduce int // value is production index +) + +func (this accept) act() {} +func (this shift) act() {} +func (this reduce) act() {} + +func (this accept) Equal(that action) bool { + if _, ok := that.(accept); ok { + return true + } + return false +} + +func (this reduce) Equal(that action) bool { + that1, ok := that.(reduce) + if !ok { + return false + } + return this == that1 +} + +func (this shift) Equal(that action) bool { + that1, ok := that.(shift) + if !ok { + return false + } + return this == that1 +} + +func (this accept) String() string { return "accept(0)" } +func (this shift) String() string { return fmt.Sprintf("shift:%d", this) } +func (this reduce) String() string { + return fmt.Sprintf("reduce:%d(%s)", this, productionsTable[this].String) +} diff --git a/internal/frontend/reparsed/internal/parser/actiontable.go b/internal/frontend/reparsed/internal/parser/actiontable.go new file mode 100644 index 00000000..04638d23 --- /dev/null +++ b/internal/frontend/reparsed/internal/parser/actiontable.go @@ -0,0 +1,5272 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +type ( + actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } + actionRow struct { + canRecover bool + actions [numSymbols]action + cdActions []cdAction + } + actions struct { + table actionTable + } +) + +var parserActions = actions{ + table: actionTable{ + actionRow{ // S0 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(9), // tokId + nil, // ":" + nil, // ";" + shift(10), // regDefId + shift(11), // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + shift(12), // g_sdt_lit + shift(13), // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S1 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + accept(true), // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S2 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(2), // Ω, reduce: Grammar + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + shift(12), // g_sdt_lit + shift(13), // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S3 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(3), // Ω, reduce: Grammar + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S4 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(4), // Ω, reduce: LexicalPart + shift(9), // tokId + nil, // ":" + nil, // ";" + shift(10), // regDefId + shift(11), // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(4), // g_sdt_lit, reduce: LexicalPart + reduce(4), // prodId, reduce: LexicalPart + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S5 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(5), // Ω, reduce: LexProductions + reduce(5), // tokId, reduce: LexProductions + nil, // ":" + nil, // ";" + reduce(5), // regDefId, reduce: LexProductions + reduce(5), // ignoredTokId, reduce: LexProductions + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(5), // g_sdt_lit, reduce: LexProductions + reduce(5), // prodId, reduce: LexProductions + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S6 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + shift(13), // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S7 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(24), // Ω, reduce: SyntaxPart + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + shift(13), // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S8 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(26), // Ω, reduce: SyntaxProdList + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + reduce(26), // prodId, reduce: SyntaxProdList + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S9 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + shift(18), // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S10 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + shift(19), // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S11 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + shift(20), // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S12 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + reduce(25), // prodId, reduce: FileHeader + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S13 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + shift(21), // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S14 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(1), // Ω, reduce: Grammar + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S15 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(6), // Ω, reduce: LexProductions + reduce(6), // tokId, reduce: LexProductions + nil, // ":" + nil, // ";" + reduce(6), // regDefId, reduce: LexProductions + reduce(6), // ignoredTokId, reduce: LexProductions + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(6), // g_sdt_lit, reduce: LexProductions + reduce(6), // prodId, reduce: LexProductions + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S16 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(23), // Ω, reduce: SyntaxPart + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + shift(13), // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S17 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(27), // Ω, reduce: SyntaxProdList + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + reduce(27), // prodId, reduce: SyntaxProdList + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S18 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(25), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(26), // "." + shift(27), // char_lit + nil, // "-" + shift(28), // "~" + shift(29), // "(" + nil, // ")" + shift(30), // "[" + nil, // "]" + shift(31), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S19 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(25), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(26), // "." + shift(27), // char_lit + nil, // "-" + shift(28), // "~" + shift(29), // "(" + nil, // ")" + shift(30), // "[" + nil, // "]" + shift(31), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S20 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(25), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(26), // "." + shift(27), // char_lit + nil, // "-" + shift(28), // "~" + shift(29), // "(" + nil, // ")" + shift(30), // "[" + nil, // "]" + shift(31), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S21 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(40), // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + shift(41), // prodId + shift(42), // string_lit + nil, // g_ctxdep_lit + shift(43), // "@" + shift(44), // "error" + shift(45), // "λ" + shift(46), // "empty" + shift(47), // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S22 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + shift(48), // ";" + nil, // regDefId + nil, // ignoredTokId + shift(49), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S23 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(10), // ";", reduce: LexPattern + shift(25), // regDefId + nil, // ignoredTokId + reduce(10), // "|", reduce: LexPattern + shift(26), // "." + shift(27), // char_lit + nil, // "-" + shift(28), // "~" + shift(29), // "(" + nil, // ")" + shift(30), // "[" + nil, // "]" + shift(31), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S24 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(12), // ";", reduce: LexAlt + reduce(12), // regDefId, reduce: LexAlt + nil, // ignoredTokId + reduce(12), // "|", reduce: LexAlt + reduce(12), // ".", reduce: LexAlt + reduce(12), // char_lit, reduce: LexAlt + nil, // "-" + reduce(12), // "~", reduce: LexAlt + reduce(12), // "(", reduce: LexAlt + nil, // ")" + reduce(12), // "[", reduce: LexAlt + nil, // "]" + reduce(12), // "{", reduce: LexAlt + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S25 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(19), // ";", reduce: LexTerm + reduce(19), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(19), // "|", reduce: LexTerm + reduce(19), // ".", reduce: LexTerm + reduce(19), // char_lit, reduce: LexTerm + nil, // "-" + reduce(19), // "~", reduce: LexTerm + reduce(19), // "(", reduce: LexTerm + nil, // ")" + reduce(19), // "[", reduce: LexTerm + nil, // "]" + reduce(19), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S26 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(14), // ";", reduce: LexTerm + reduce(14), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(14), // "|", reduce: LexTerm + reduce(14), // ".", reduce: LexTerm + reduce(14), // char_lit, reduce: LexTerm + nil, // "-" + reduce(14), // "~", reduce: LexTerm + reduce(14), // "(", reduce: LexTerm + nil, // ")" + reduce(14), // "[", reduce: LexTerm + nil, // "]" + reduce(14), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S27 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(15), // ";", reduce: LexTerm + reduce(15), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(15), // "|", reduce: LexTerm + reduce(15), // ".", reduce: LexTerm + reduce(15), // char_lit, reduce: LexTerm + shift(51), // "-" + reduce(15), // "~", reduce: LexTerm + reduce(15), // "(", reduce: LexTerm + nil, // ")" + reduce(15), // "[", reduce: LexTerm + nil, // "]" + reduce(15), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S28 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(52), // char_lit + nil, // "-" + nil, // "~" + shift(53), // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S29 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(57), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(58), // "." + shift(59), // char_lit + nil, // "-" + shift(60), // "~" + shift(61), // "(" + nil, // ")" + shift(62), // "[" + nil, // "]" + shift(63), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S30 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(67), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(68), // "." + shift(69), // char_lit + nil, // "-" + shift(70), // "~" + shift(71), // "(" + nil, // ")" + shift(72), // "[" + nil, // "]" + shift(73), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S31 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(77), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(78), // "." + shift(79), // char_lit + nil, // "-" + shift(80), // "~" + shift(81), // "(" + nil, // ")" + shift(82), // "[" + nil, // "]" + shift(83), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S32 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + shift(84), // ";" + nil, // regDefId + nil, // ignoredTokId + shift(49), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S33 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + shift(85), // ";" + nil, // regDefId + nil, // ignoredTokId + shift(49), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S34 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + shift(86), // ";" + nil, // regDefId + nil, // ignoredTokId + shift(87), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S35 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(29), // ";", reduce: Alternatives + nil, // regDefId + nil, // ignoredTokId + reduce(29), // "|", reduce: Alternatives + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S36 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(40), // tokId + nil, // ":" + reduce(31), // ";", reduce: SyntaxBody + nil, // regDefId + nil, // ignoredTokId + reduce(31), // "|", reduce: SyntaxBody + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + shift(89), // g_sdt_lit + shift(41), // prodId + shift(42), // string_lit + nil, // g_ctxdep_lit + shift(43), // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S37 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(40), // tokId + nil, // ":" + reduce(33), // ";", reduce: SyntaxBody + nil, // regDefId + nil, // ignoredTokId + reduce(33), // "|", reduce: SyntaxBody + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + shift(91), // g_sdt_lit + shift(41), // prodId + shift(42), // string_lit + nil, // g_ctxdep_lit + shift(43), // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S38 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(37), // ";", reduce: SyntaxBody + nil, // regDefId + nil, // ignoredTokId + reduce(37), // "|", reduce: SyntaxBody + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + shift(92), // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S39 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(39), // tokId, reduce: Symbols + nil, // ":" + reduce(39), // ";", reduce: Symbols + nil, // regDefId + nil, // ignoredTokId + reduce(39), // "|", reduce: Symbols + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(39), // g_sdt_lit, reduce: Symbols + reduce(39), // prodId, reduce: Symbols + reduce(39), // string_lit, reduce: Symbols + nil, // g_ctxdep_lit + reduce(39), // "@", reduce: Symbols + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S40 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(42), // tokId, reduce: Symbol + nil, // ":" + reduce(42), // ";", reduce: Symbol + nil, // regDefId + nil, // ignoredTokId + reduce(42), // "|", reduce: Symbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(42), // g_sdt_lit, reduce: Symbol + reduce(42), // prodId, reduce: Symbol + reduce(42), // string_lit, reduce: Symbol + shift(93), // g_ctxdep_lit + reduce(42), // "@", reduce: Symbol + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S41 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(41), // tokId, reduce: Symbol + nil, // ":" + reduce(41), // ";", reduce: Symbol + nil, // regDefId + nil, // ignoredTokId + reduce(41), // "|", reduce: Symbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(41), // g_sdt_lit, reduce: Symbol + reduce(41), // prodId, reduce: Symbol + reduce(41), // string_lit, reduce: Symbol + nil, // g_ctxdep_lit + reduce(41), // "@", reduce: Symbol + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S42 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(43), // tokId, reduce: Symbol + nil, // ":" + reduce(43), // ";", reduce: Symbol + nil, // regDefId + nil, // ignoredTokId + reduce(43), // "|", reduce: Symbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(43), // g_sdt_lit, reduce: Symbol + reduce(43), // prodId, reduce: Symbol + reduce(43), // string_lit, reduce: Symbol + nil, // g_ctxdep_lit + reduce(43), // "@", reduce: Symbol + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S43 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(94), // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + shift(95), // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S44 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(47), // tokId, reduce: ErrorSymbol + nil, // ":" + reduce(47), // ";", reduce: ErrorSymbol + nil, // regDefId + nil, // ignoredTokId + reduce(47), // "|", reduce: ErrorSymbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(47), // g_sdt_lit, reduce: ErrorSymbol + reduce(47), // prodId, reduce: ErrorSymbol + reduce(47), // string_lit, reduce: ErrorSymbol + nil, // g_ctxdep_lit + reduce(47), // "@", reduce: ErrorSymbol + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S45 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(48), // tokId, reduce: ErrorSymbol + nil, // ":" + reduce(48), // ";", reduce: ErrorSymbol + nil, // regDefId + nil, // ignoredTokId + reduce(48), // "|", reduce: ErrorSymbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(48), // g_sdt_lit, reduce: ErrorSymbol + reduce(48), // prodId, reduce: ErrorSymbol + reduce(48), // string_lit, reduce: ErrorSymbol + nil, // g_ctxdep_lit + reduce(48), // "@", reduce: ErrorSymbol + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S46 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(49), // ";", reduce: EpsilonSymbol + nil, // regDefId + nil, // ignoredTokId + reduce(49), // "|", reduce: EpsilonSymbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(49), // g_sdt_lit, reduce: EpsilonSymbol + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S47 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(50), // ";", reduce: EpsilonSymbol + nil, // regDefId + nil, // ignoredTokId + reduce(50), // "|", reduce: EpsilonSymbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(50), // g_sdt_lit, reduce: EpsilonSymbol + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S48 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(7), // Ω, reduce: LexProduction + reduce(7), // tokId, reduce: LexProduction + nil, // ":" + nil, // ";" + reduce(7), // regDefId, reduce: LexProduction + reduce(7), // ignoredTokId, reduce: LexProduction + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(7), // g_sdt_lit, reduce: LexProduction + reduce(7), // prodId, reduce: LexProduction + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S49 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(25), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(26), // "." + shift(27), // char_lit + nil, // "-" + shift(28), // "~" + shift(29), // "(" + nil, // ")" + shift(30), // "[" + nil, // "]" + shift(31), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S50 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(13), // ";", reduce: LexAlt + reduce(13), // regDefId, reduce: LexAlt + nil, // ignoredTokId + reduce(13), // "|", reduce: LexAlt + reduce(13), // ".", reduce: LexAlt + reduce(13), // char_lit, reduce: LexAlt + nil, // "-" + reduce(13), // "~", reduce: LexAlt + reduce(13), // "(", reduce: LexAlt + nil, // ")" + reduce(13), // "[", reduce: LexAlt + nil, // "]" + reduce(13), // "{", reduce: LexAlt + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S51 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(97), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S52 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(17), // ";", reduce: LexTerm + reduce(17), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(17), // "|", reduce: LexTerm + reduce(17), // ".", reduce: LexTerm + reduce(17), // char_lit, reduce: LexTerm + nil, // "-" + reduce(17), // "~", reduce: LexTerm + reduce(17), // "(", reduce: LexTerm + nil, // ")" + reduce(17), // "[", reduce: LexTerm + nil, // "]" + reduce(17), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S53 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(98), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S54 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(99), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + shift(100), // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S55 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(57), // regDefId + nil, // ignoredTokId + reduce(10), // "|", reduce: LexPattern + shift(58), // "." + shift(59), // char_lit + nil, // "-" + shift(60), // "~" + shift(61), // "(" + reduce(10), // ")", reduce: LexPattern + shift(62), // "[" + nil, // "]" + shift(63), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S56 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(12), // regDefId, reduce: LexAlt + nil, // ignoredTokId + reduce(12), // "|", reduce: LexAlt + reduce(12), // ".", reduce: LexAlt + reduce(12), // char_lit, reduce: LexAlt + nil, // "-" + reduce(12), // "~", reduce: LexAlt + reduce(12), // "(", reduce: LexAlt + reduce(12), // ")", reduce: LexAlt + reduce(12), // "[", reduce: LexAlt + nil, // "]" + reduce(12), // "{", reduce: LexAlt + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S57 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(19), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(19), // "|", reduce: LexTerm + reduce(19), // ".", reduce: LexTerm + reduce(19), // char_lit, reduce: LexTerm + nil, // "-" + reduce(19), // "~", reduce: LexTerm + reduce(19), // "(", reduce: LexTerm + reduce(19), // ")", reduce: LexTerm + reduce(19), // "[", reduce: LexTerm + nil, // "]" + reduce(19), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S58 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(14), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(14), // "|", reduce: LexTerm + reduce(14), // ".", reduce: LexTerm + reduce(14), // char_lit, reduce: LexTerm + nil, // "-" + reduce(14), // "~", reduce: LexTerm + reduce(14), // "(", reduce: LexTerm + reduce(14), // ")", reduce: LexTerm + reduce(14), // "[", reduce: LexTerm + nil, // "]" + reduce(14), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S59 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(15), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(15), // "|", reduce: LexTerm + reduce(15), // ".", reduce: LexTerm + reduce(15), // char_lit, reduce: LexTerm + shift(102), // "-" + reduce(15), // "~", reduce: LexTerm + reduce(15), // "(", reduce: LexTerm + reduce(15), // ")", reduce: LexTerm + reduce(15), // "[", reduce: LexTerm + nil, // "]" + reduce(15), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S60 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(103), // char_lit + nil, // "-" + nil, // "~" + shift(104), // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S61 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(57), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(58), // "." + shift(59), // char_lit + nil, // "-" + shift(60), // "~" + shift(61), // "(" + nil, // ")" + shift(62), // "[" + nil, // "]" + shift(63), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S62 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(67), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(68), // "." + shift(69), // char_lit + nil, // "-" + shift(70), // "~" + shift(71), // "(" + nil, // ")" + shift(72), // "[" + nil, // "]" + shift(73), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S63 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(77), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(78), // "." + shift(79), // char_lit + nil, // "-" + shift(80), // "~" + shift(81), // "(" + nil, // ")" + shift(82), // "[" + nil, // "]" + shift(83), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S64 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(108), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + shift(109), // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S65 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(67), // regDefId + nil, // ignoredTokId + reduce(10), // "|", reduce: LexPattern + shift(68), // "." + shift(69), // char_lit + nil, // "-" + shift(70), // "~" + shift(71), // "(" + nil, // ")" + shift(72), // "[" + reduce(10), // "]", reduce: LexPattern + shift(73), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S66 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(12), // regDefId, reduce: LexAlt + nil, // ignoredTokId + reduce(12), // "|", reduce: LexAlt + reduce(12), // ".", reduce: LexAlt + reduce(12), // char_lit, reduce: LexAlt + nil, // "-" + reduce(12), // "~", reduce: LexAlt + reduce(12), // "(", reduce: LexAlt + nil, // ")" + reduce(12), // "[", reduce: LexAlt + reduce(12), // "]", reduce: LexAlt + reduce(12), // "{", reduce: LexAlt + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S67 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(19), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(19), // "|", reduce: LexTerm + reduce(19), // ".", reduce: LexTerm + reduce(19), // char_lit, reduce: LexTerm + nil, // "-" + reduce(19), // "~", reduce: LexTerm + reduce(19), // "(", reduce: LexTerm + nil, // ")" + reduce(19), // "[", reduce: LexTerm + reduce(19), // "]", reduce: LexTerm + reduce(19), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S68 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(14), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(14), // "|", reduce: LexTerm + reduce(14), // ".", reduce: LexTerm + reduce(14), // char_lit, reduce: LexTerm + nil, // "-" + reduce(14), // "~", reduce: LexTerm + reduce(14), // "(", reduce: LexTerm + nil, // ")" + reduce(14), // "[", reduce: LexTerm + reduce(14), // "]", reduce: LexTerm + reduce(14), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S69 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(15), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(15), // "|", reduce: LexTerm + reduce(15), // ".", reduce: LexTerm + reduce(15), // char_lit, reduce: LexTerm + shift(111), // "-" + reduce(15), // "~", reduce: LexTerm + reduce(15), // "(", reduce: LexTerm + nil, // ")" + reduce(15), // "[", reduce: LexTerm + reduce(15), // "]", reduce: LexTerm + reduce(15), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S70 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(112), // char_lit + nil, // "-" + nil, // "~" + shift(113), // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S71 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(57), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(58), // "." + shift(59), // char_lit + nil, // "-" + shift(60), // "~" + shift(61), // "(" + nil, // ")" + shift(62), // "[" + nil, // "]" + shift(63), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S72 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(67), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(68), // "." + shift(69), // char_lit + nil, // "-" + shift(70), // "~" + shift(71), // "(" + nil, // ")" + shift(72), // "[" + nil, // "]" + shift(73), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S73 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(77), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(78), // "." + shift(79), // char_lit + nil, // "-" + shift(80), // "~" + shift(81), // "(" + nil, // ")" + shift(82), // "[" + nil, // "]" + shift(83), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S74 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(117), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + shift(118), // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S75 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(77), // regDefId + nil, // ignoredTokId + reduce(10), // "|", reduce: LexPattern + shift(78), // "." + shift(79), // char_lit + nil, // "-" + shift(80), // "~" + shift(81), // "(" + nil, // ")" + shift(82), // "[" + nil, // "]" + shift(83), // "{" + reduce(10), // "}", reduce: LexPattern + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S76 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(12), // regDefId, reduce: LexAlt + nil, // ignoredTokId + reduce(12), // "|", reduce: LexAlt + reduce(12), // ".", reduce: LexAlt + reduce(12), // char_lit, reduce: LexAlt + nil, // "-" + reduce(12), // "~", reduce: LexAlt + reduce(12), // "(", reduce: LexAlt + nil, // ")" + reduce(12), // "[", reduce: LexAlt + nil, // "]" + reduce(12), // "{", reduce: LexAlt + reduce(12), // "}", reduce: LexAlt + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S77 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(19), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(19), // "|", reduce: LexTerm + reduce(19), // ".", reduce: LexTerm + reduce(19), // char_lit, reduce: LexTerm + nil, // "-" + reduce(19), // "~", reduce: LexTerm + reduce(19), // "(", reduce: LexTerm + nil, // ")" + reduce(19), // "[", reduce: LexTerm + nil, // "]" + reduce(19), // "{", reduce: LexTerm + reduce(19), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S78 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(14), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(14), // "|", reduce: LexTerm + reduce(14), // ".", reduce: LexTerm + reduce(14), // char_lit, reduce: LexTerm + nil, // "-" + reduce(14), // "~", reduce: LexTerm + reduce(14), // "(", reduce: LexTerm + nil, // ")" + reduce(14), // "[", reduce: LexTerm + nil, // "]" + reduce(14), // "{", reduce: LexTerm + reduce(14), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S79 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(15), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(15), // "|", reduce: LexTerm + reduce(15), // ".", reduce: LexTerm + reduce(15), // char_lit, reduce: LexTerm + shift(120), // "-" + reduce(15), // "~", reduce: LexTerm + reduce(15), // "(", reduce: LexTerm + nil, // ")" + reduce(15), // "[", reduce: LexTerm + nil, // "]" + reduce(15), // "{", reduce: LexTerm + reduce(15), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S80 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(121), // char_lit + nil, // "-" + nil, // "~" + shift(122), // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S81 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(57), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(58), // "." + shift(59), // char_lit + nil, // "-" + shift(60), // "~" + shift(61), // "(" + nil, // ")" + shift(62), // "[" + nil, // "]" + shift(63), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S82 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(67), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(68), // "." + shift(69), // char_lit + nil, // "-" + shift(70), // "~" + shift(71), // "(" + nil, // ")" + shift(72), // "[" + nil, // "]" + shift(73), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S83 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(77), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(78), // "." + shift(79), // char_lit + nil, // "-" + shift(80), // "~" + shift(81), // "(" + nil, // ")" + shift(82), // "[" + nil, // "]" + shift(83), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S84 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(8), // Ω, reduce: LexProduction + reduce(8), // tokId, reduce: LexProduction + nil, // ":" + nil, // ";" + reduce(8), // regDefId, reduce: LexProduction + reduce(8), // ignoredTokId, reduce: LexProduction + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(8), // g_sdt_lit, reduce: LexProduction + reduce(8), // prodId, reduce: LexProduction + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S85 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(9), // Ω, reduce: LexProduction + reduce(9), // tokId, reduce: LexProduction + nil, // ":" + nil, // ";" + reduce(9), // regDefId, reduce: LexProduction + reduce(9), // ignoredTokId, reduce: LexProduction + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(9), // g_sdt_lit, reduce: LexProduction + reduce(9), // prodId, reduce: LexProduction + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S86 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + reduce(28), // Ω, reduce: SyntaxProduction + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + reduce(28), // prodId, reduce: SyntaxProduction + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S87 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(40), // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + shift(41), // prodId + shift(42), // string_lit + nil, // g_ctxdep_lit + shift(43), // "@" + shift(44), // "error" + shift(45), // "λ" + shift(46), // "empty" + shift(47), // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S88 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(40), // tokId, reduce: Symbols + nil, // ":" + reduce(40), // ";", reduce: Symbols + nil, // regDefId + nil, // ignoredTokId + reduce(40), // "|", reduce: Symbols + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(40), // g_sdt_lit, reduce: Symbols + reduce(40), // prodId, reduce: Symbols + reduce(40), // string_lit, reduce: Symbols + nil, // g_ctxdep_lit + reduce(40), // "@", reduce: Symbols + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S89 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(32), // ";", reduce: SyntaxBody + nil, // regDefId + nil, // ignoredTokId + reduce(32), // "|", reduce: SyntaxBody + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S90 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + shift(40), // tokId + nil, // ":" + reduce(34), // ";", reduce: SyntaxBody + nil, // regDefId + nil, // ignoredTokId + reduce(34), // "|", reduce: SyntaxBody + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + shift(127), // g_sdt_lit + shift(41), // prodId + shift(42), // string_lit + nil, // g_ctxdep_lit + shift(43), // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S91 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(36), // ";", reduce: SyntaxBody + nil, // regDefId + nil, // ignoredTokId + reduce(36), // "|", reduce: SyntaxBody + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S92 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(38), // ";", reduce: SyntaxBody + nil, // regDefId + nil, // ignoredTokId + reduce(38), // "|", reduce: SyntaxBody + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S93 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(44), // tokId, reduce: Symbol + nil, // ":" + reduce(44), // ";", reduce: Symbol + nil, // regDefId + nil, // ignoredTokId + reduce(44), // "|", reduce: Symbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(44), // g_sdt_lit, reduce: Symbol + reduce(44), // prodId, reduce: Symbol + reduce(44), // string_lit, reduce: Symbol + nil, // g_ctxdep_lit + reduce(44), // "@", reduce: Symbol + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S94 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + shift(128), // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S95 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(46), // tokId, reduce: Symbol + nil, // ":" + reduce(46), // ";", reduce: Symbol + nil, // regDefId + nil, // ignoredTokId + reduce(46), // "|", reduce: Symbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(46), // g_sdt_lit, reduce: Symbol + reduce(46), // prodId, reduce: Symbol + reduce(46), // string_lit, reduce: Symbol + nil, // g_ctxdep_lit + reduce(46), // "@", reduce: Symbol + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S96 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(11), // ";", reduce: LexPattern + shift(25), // regDefId + nil, // ignoredTokId + reduce(11), // "|", reduce: LexPattern + shift(26), // "." + shift(27), // char_lit + nil, // "-" + shift(28), // "~" + shift(29), // "(" + nil, // ")" + shift(30), // "[" + nil, // "]" + shift(31), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S97 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(16), // ";", reduce: LexTerm + reduce(16), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(16), // "|", reduce: LexTerm + reduce(16), // ".", reduce: LexTerm + reduce(16), // char_lit, reduce: LexTerm + nil, // "-" + reduce(16), // "~", reduce: LexTerm + reduce(16), // "(", reduce: LexTerm + nil, // ")" + reduce(16), // "[", reduce: LexTerm + nil, // "]" + reduce(16), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S98 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + shift(129), // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S99 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(57), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(58), // "." + shift(59), // char_lit + nil, // "-" + shift(60), // "~" + shift(61), // "(" + nil, // ")" + shift(62), // "[" + nil, // "]" + shift(63), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S100 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(22), // ";", reduce: LexTerm + reduce(22), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(22), // "|", reduce: LexTerm + reduce(22), // ".", reduce: LexTerm + reduce(22), // char_lit, reduce: LexTerm + nil, // "-" + reduce(22), // "~", reduce: LexTerm + reduce(22), // "(", reduce: LexTerm + nil, // ")" + reduce(22), // "[", reduce: LexTerm + nil, // "]" + reduce(22), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S101 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(13), // regDefId, reduce: LexAlt + nil, // ignoredTokId + reduce(13), // "|", reduce: LexAlt + reduce(13), // ".", reduce: LexAlt + reduce(13), // char_lit, reduce: LexAlt + nil, // "-" + reduce(13), // "~", reduce: LexAlt + reduce(13), // "(", reduce: LexAlt + reduce(13), // ")", reduce: LexAlt + reduce(13), // "[", reduce: LexAlt + nil, // "]" + reduce(13), // "{", reduce: LexAlt + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S102 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(131), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S103 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(17), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(17), // "|", reduce: LexTerm + reduce(17), // ".", reduce: LexTerm + reduce(17), // char_lit, reduce: LexTerm + nil, // "-" + reduce(17), // "~", reduce: LexTerm + reduce(17), // "(", reduce: LexTerm + reduce(17), // ")", reduce: LexTerm + reduce(17), // "[", reduce: LexTerm + nil, // "]" + reduce(17), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S104 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(132), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S105 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(99), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + shift(133), // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S106 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(108), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + shift(134), // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S107 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(117), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + shift(135), // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S108 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(67), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(68), // "." + shift(69), // char_lit + nil, // "-" + shift(70), // "~" + shift(71), // "(" + nil, // ")" + shift(72), // "[" + nil, // "]" + shift(73), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S109 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(20), // ";", reduce: LexTerm + reduce(20), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(20), // "|", reduce: LexTerm + reduce(20), // ".", reduce: LexTerm + reduce(20), // char_lit, reduce: LexTerm + nil, // "-" + reduce(20), // "~", reduce: LexTerm + reduce(20), // "(", reduce: LexTerm + nil, // ")" + reduce(20), // "[", reduce: LexTerm + nil, // "]" + reduce(20), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S110 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(13), // regDefId, reduce: LexAlt + nil, // ignoredTokId + reduce(13), // "|", reduce: LexAlt + reduce(13), // ".", reduce: LexAlt + reduce(13), // char_lit, reduce: LexAlt + nil, // "-" + reduce(13), // "~", reduce: LexAlt + reduce(13), // "(", reduce: LexAlt + nil, // ")" + reduce(13), // "[", reduce: LexAlt + reduce(13), // "]", reduce: LexAlt + reduce(13), // "{", reduce: LexAlt + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S111 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(137), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S112 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(17), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(17), // "|", reduce: LexTerm + reduce(17), // ".", reduce: LexTerm + reduce(17), // char_lit, reduce: LexTerm + nil, // "-" + reduce(17), // "~", reduce: LexTerm + reduce(17), // "(", reduce: LexTerm + nil, // ")" + reduce(17), // "[", reduce: LexTerm + reduce(17), // "]", reduce: LexTerm + reduce(17), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S113 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(138), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S114 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(99), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + shift(139), // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S115 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(108), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + shift(140), // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S116 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(117), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + shift(141), // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S117 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(77), // regDefId + nil, // ignoredTokId + nil, // "|" + shift(78), // "." + shift(79), // char_lit + nil, // "-" + shift(80), // "~" + shift(81), // "(" + nil, // ")" + shift(82), // "[" + nil, // "]" + shift(83), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S118 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(21), // ";", reduce: LexTerm + reduce(21), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(21), // "|", reduce: LexTerm + reduce(21), // ".", reduce: LexTerm + reduce(21), // char_lit, reduce: LexTerm + nil, // "-" + reduce(21), // "~", reduce: LexTerm + reduce(21), // "(", reduce: LexTerm + nil, // ")" + reduce(21), // "[", reduce: LexTerm + nil, // "]" + reduce(21), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S119 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(13), // regDefId, reduce: LexAlt + nil, // ignoredTokId + reduce(13), // "|", reduce: LexAlt + reduce(13), // ".", reduce: LexAlt + reduce(13), // char_lit, reduce: LexAlt + nil, // "-" + reduce(13), // "~", reduce: LexAlt + reduce(13), // "(", reduce: LexAlt + nil, // ")" + reduce(13), // "[", reduce: LexAlt + nil, // "]" + reduce(13), // "{", reduce: LexAlt + reduce(13), // "}", reduce: LexAlt + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S120 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(143), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S121 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(17), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(17), // "|", reduce: LexTerm + reduce(17), // ".", reduce: LexTerm + reduce(17), // char_lit, reduce: LexTerm + nil, // "-" + reduce(17), // "~", reduce: LexTerm + reduce(17), // "(", reduce: LexTerm + nil, // ")" + reduce(17), // "[", reduce: LexTerm + nil, // "]" + reduce(17), // "{", reduce: LexTerm + reduce(17), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S122 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(144), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S123 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(99), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + shift(145), // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S124 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(108), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + shift(146), // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S125 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + shift(117), // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + shift(147), // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S126 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(30), // ";", reduce: Alternatives + nil, // regDefId + nil, // ignoredTokId + reduce(30), // "|", reduce: Alternatives + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S127 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(35), // ";", reduce: SyntaxBody + nil, // regDefId + nil, // ignoredTokId + reduce(35), // "|", reduce: SyntaxBody + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S128 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + reduce(45), // tokId, reduce: Symbol + nil, // ":" + reduce(45), // ";", reduce: Symbol + nil, // regDefId + nil, // ignoredTokId + reduce(45), // "|", reduce: Symbol + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + reduce(45), // g_sdt_lit, reduce: Symbol + reduce(45), // prodId, reduce: Symbol + reduce(45), // string_lit, reduce: Symbol + nil, // g_ctxdep_lit + reduce(45), // "@", reduce: Symbol + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S129 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(148), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S130 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(57), // regDefId + nil, // ignoredTokId + reduce(11), // "|", reduce: LexPattern + shift(58), // "." + shift(59), // char_lit + nil, // "-" + shift(60), // "~" + shift(61), // "(" + reduce(11), // ")", reduce: LexPattern + shift(62), // "[" + nil, // "]" + shift(63), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S131 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(16), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(16), // "|", reduce: LexTerm + reduce(16), // ".", reduce: LexTerm + reduce(16), // char_lit, reduce: LexTerm + nil, // "-" + reduce(16), // "~", reduce: LexTerm + reduce(16), // "(", reduce: LexTerm + reduce(16), // ")", reduce: LexTerm + reduce(16), // "[", reduce: LexTerm + nil, // "]" + reduce(16), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S132 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + shift(149), // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S133 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(22), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(22), // "|", reduce: LexTerm + reduce(22), // ".", reduce: LexTerm + reduce(22), // char_lit, reduce: LexTerm + nil, // "-" + reduce(22), // "~", reduce: LexTerm + reduce(22), // "(", reduce: LexTerm + reduce(22), // ")", reduce: LexTerm + reduce(22), // "[", reduce: LexTerm + nil, // "]" + reduce(22), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S134 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(20), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(20), // "|", reduce: LexTerm + reduce(20), // ".", reduce: LexTerm + reduce(20), // char_lit, reduce: LexTerm + nil, // "-" + reduce(20), // "~", reduce: LexTerm + reduce(20), // "(", reduce: LexTerm + reduce(20), // ")", reduce: LexTerm + reduce(20), // "[", reduce: LexTerm + nil, // "]" + reduce(20), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S135 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(21), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(21), // "|", reduce: LexTerm + reduce(21), // ".", reduce: LexTerm + reduce(21), // char_lit, reduce: LexTerm + nil, // "-" + reduce(21), // "~", reduce: LexTerm + reduce(21), // "(", reduce: LexTerm + reduce(21), // ")", reduce: LexTerm + reduce(21), // "[", reduce: LexTerm + nil, // "]" + reduce(21), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S136 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(67), // regDefId + nil, // ignoredTokId + reduce(11), // "|", reduce: LexPattern + shift(68), // "." + shift(69), // char_lit + nil, // "-" + shift(70), // "~" + shift(71), // "(" + nil, // ")" + shift(72), // "[" + reduce(11), // "]", reduce: LexPattern + shift(73), // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S137 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(16), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(16), // "|", reduce: LexTerm + reduce(16), // ".", reduce: LexTerm + reduce(16), // char_lit, reduce: LexTerm + nil, // "-" + reduce(16), // "~", reduce: LexTerm + reduce(16), // "(", reduce: LexTerm + nil, // ")" + reduce(16), // "[", reduce: LexTerm + reduce(16), // "]", reduce: LexTerm + reduce(16), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S138 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + shift(150), // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S139 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(22), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(22), // "|", reduce: LexTerm + reduce(22), // ".", reduce: LexTerm + reduce(22), // char_lit, reduce: LexTerm + nil, // "-" + reduce(22), // "~", reduce: LexTerm + reduce(22), // "(", reduce: LexTerm + nil, // ")" + reduce(22), // "[", reduce: LexTerm + reduce(22), // "]", reduce: LexTerm + reduce(22), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S140 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(20), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(20), // "|", reduce: LexTerm + reduce(20), // ".", reduce: LexTerm + reduce(20), // char_lit, reduce: LexTerm + nil, // "-" + reduce(20), // "~", reduce: LexTerm + reduce(20), // "(", reduce: LexTerm + nil, // ")" + reduce(20), // "[", reduce: LexTerm + reduce(20), // "]", reduce: LexTerm + reduce(20), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S141 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(21), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(21), // "|", reduce: LexTerm + reduce(21), // ".", reduce: LexTerm + reduce(21), // char_lit, reduce: LexTerm + nil, // "-" + reduce(21), // "~", reduce: LexTerm + reduce(21), // "(", reduce: LexTerm + nil, // ")" + reduce(21), // "[", reduce: LexTerm + reduce(21), // "]", reduce: LexTerm + reduce(21), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S142 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + shift(77), // regDefId + nil, // ignoredTokId + reduce(11), // "|", reduce: LexPattern + shift(78), // "." + shift(79), // char_lit + nil, // "-" + shift(80), // "~" + shift(81), // "(" + nil, // ")" + shift(82), // "[" + nil, // "]" + shift(83), // "{" + reduce(11), // "}", reduce: LexPattern + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S143 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(16), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(16), // "|", reduce: LexTerm + reduce(16), // ".", reduce: LexTerm + reduce(16), // char_lit, reduce: LexTerm + nil, // "-" + reduce(16), // "~", reduce: LexTerm + reduce(16), // "(", reduce: LexTerm + nil, // ")" + reduce(16), // "[", reduce: LexTerm + nil, // "]" + reduce(16), // "{", reduce: LexTerm + reduce(16), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S144 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + shift(151), // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S145 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(22), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(22), // "|", reduce: LexTerm + reduce(22), // ".", reduce: LexTerm + reduce(22), // char_lit, reduce: LexTerm + nil, // "-" + reduce(22), // "~", reduce: LexTerm + reduce(22), // "(", reduce: LexTerm + nil, // ")" + reduce(22), // "[", reduce: LexTerm + nil, // "]" + reduce(22), // "{", reduce: LexTerm + reduce(22), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S146 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(20), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(20), // "|", reduce: LexTerm + reduce(20), // ".", reduce: LexTerm + reduce(20), // char_lit, reduce: LexTerm + nil, // "-" + reduce(20), // "~", reduce: LexTerm + reduce(20), // "(", reduce: LexTerm + nil, // ")" + reduce(20), // "[", reduce: LexTerm + nil, // "]" + reduce(20), // "{", reduce: LexTerm + reduce(20), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S147 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(21), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(21), // "|", reduce: LexTerm + reduce(21), // ".", reduce: LexTerm + reduce(21), // char_lit, reduce: LexTerm + nil, // "-" + reduce(21), // "~", reduce: LexTerm + reduce(21), // "(", reduce: LexTerm + nil, // ")" + reduce(21), // "[", reduce: LexTerm + nil, // "]" + reduce(21), // "{", reduce: LexTerm + reduce(21), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S148 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + shift(152), // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S149 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(153), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S150 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(154), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S151 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + shift(155), // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + nil, // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S152 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + reduce(18), // ";", reduce: LexTerm + reduce(18), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(18), // "|", reduce: LexTerm + reduce(18), // ".", reduce: LexTerm + reduce(18), // char_lit, reduce: LexTerm + nil, // "-" + reduce(18), // "~", reduce: LexTerm + reduce(18), // "(", reduce: LexTerm + nil, // ")" + reduce(18), // "[", reduce: LexTerm + nil, // "]" + reduce(18), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S153 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + shift(156), // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S154 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + shift(157), // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S155 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + nil, // regDefId + nil, // ignoredTokId + nil, // "|" + nil, // "." + nil, // char_lit + nil, // "-" + nil, // "~" + nil, // "(" + shift(158), // ")" + nil, // "[" + nil, // "]" + nil, // "{" + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S156 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(18), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(18), // "|", reduce: LexTerm + reduce(18), // ".", reduce: LexTerm + reduce(18), // char_lit, reduce: LexTerm + nil, // "-" + reduce(18), // "~", reduce: LexTerm + reduce(18), // "(", reduce: LexTerm + reduce(18), // ")", reduce: LexTerm + reduce(18), // "[", reduce: LexTerm + nil, // "]" + reduce(18), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S157 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(18), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(18), // "|", reduce: LexTerm + reduce(18), // ".", reduce: LexTerm + reduce(18), // char_lit, reduce: LexTerm + nil, // "-" + reduce(18), // "~", reduce: LexTerm + reduce(18), // "(", reduce: LexTerm + nil, // ")" + reduce(18), // "[", reduce: LexTerm + reduce(18), // "]", reduce: LexTerm + reduce(18), // "{", reduce: LexTerm + nil, // "}" + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + actionRow{ // S158 + canRecover: false, + actions: [numSymbols]action{ + nil, // ά + nil, // Ω + nil, // tokId + nil, // ":" + nil, // ";" + reduce(18), // regDefId, reduce: LexTerm + nil, // ignoredTokId + reduce(18), // "|", reduce: LexTerm + reduce(18), // ".", reduce: LexTerm + reduce(18), // char_lit, reduce: LexTerm + nil, // "-" + reduce(18), // "~", reduce: LexTerm + reduce(18), // "(", reduce: LexTerm + nil, // ")" + reduce(18), // "[", reduce: LexTerm + nil, // "]" + reduce(18), // "{", reduce: LexTerm + reduce(18), // "}", reduce: LexTerm + nil, // g_sdt_lit + nil, // prodId + nil, // string_lit + nil, // g_ctxdep_lit + nil, // "@" + nil, // "error" + nil, // "λ" + nil, // "empty" + nil, // "ε" + }, + cdActions: []cdAction{}, + }, + }, +} diff --git a/internal/frontend/reparsed/internal/parser/gototable.go b/internal/frontend/reparsed/internal/parser/gototable.go new file mode 100644 index 00000000..2c3f97b4 --- /dev/null +++ b/internal/frontend/reparsed/internal/parser/gototable.go @@ -0,0 +1,3193 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +const numNTSymbols = 18 + +type ( + gotoTable [numStates]gotoRow + gotoRow [numNTSymbols]int +) + +var gotoTab = gotoTable{ + gotoRow{ // S0 + -1, // Π + 1, // Π + 2, // Π + 3, // Π + 4, // Π + 5, // Π + -1, // Π + -1, // Π + -1, // Π + 6, // Π + 7, // Π + 8, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S1 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S2 + -1, // Π + -1, // Π + -1, // Π + 14, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 6, // Π + 7, // Π + 8, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S3 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S4 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 15, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S5 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S6 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 16, // Π + 8, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S7 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 17, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S8 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S9 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S10 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S11 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S12 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S13 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S14 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S15 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S16 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 17, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S17 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S18 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 22, // Π + 23, // Π + 24, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S19 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 32, // Π + 23, // Π + 24, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S20 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 33, // Π + 23, // Π + 24, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S21 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 34, // Π + 35, // Π + 36, // Π + 37, // Π + 38, // Π + 39, // Π + }, + gotoRow{ // S22 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S23 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 50, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S24 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S25 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S26 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S27 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S28 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S29 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 54, // Π + 55, // Π + 56, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S30 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 64, // Π + 65, // Π + 66, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S31 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 74, // Π + 75, // Π + 76, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S32 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S33 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S34 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S35 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S36 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 88, // Π + }, + gotoRow{ // S37 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 90, // Π + -1, // Π + -1, // Π + 39, // Π + }, + gotoRow{ // S38 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S39 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S40 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S41 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S42 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S43 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S44 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S45 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S46 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S47 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S48 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S49 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 96, // Π + 24, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S50 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S51 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S52 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S53 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S54 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S55 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 101, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S56 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S57 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S58 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S59 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S60 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S61 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 105, // Π + 55, // Π + 56, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S62 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 106, // Π + 65, // Π + 66, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S63 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 107, // Π + 75, // Π + 76, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S64 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S65 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 110, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S66 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S67 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S68 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S69 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S70 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S71 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 114, // Π + 55, // Π + 56, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S72 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 115, // Π + 65, // Π + 66, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S73 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 116, // Π + 75, // Π + 76, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S74 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S75 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 119, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S76 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S77 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S78 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S79 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S80 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S81 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 123, // Π + 55, // Π + 56, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S82 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 124, // Π + 65, // Π + 66, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S83 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 125, // Π + 75, // Π + 76, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S84 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S85 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S86 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S87 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 126, // Π + 36, // Π + 37, // Π + 38, // Π + 39, // Π + }, + gotoRow{ // S88 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S89 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S90 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 88, // Π + }, + gotoRow{ // S91 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S92 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S93 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S94 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S95 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S96 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 50, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S97 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S98 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S99 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 130, // Π + 56, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S100 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S101 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S102 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S103 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S104 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S105 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S106 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S107 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S108 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 136, // Π + 66, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S109 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S110 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S111 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S112 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S113 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S114 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S115 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S116 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S117 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 142, // Π + 76, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S118 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S119 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S120 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S121 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S122 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S123 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S124 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S125 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S126 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S127 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S128 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S129 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S130 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 101, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S131 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S132 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S133 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S134 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S135 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S136 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 110, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S137 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S138 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S139 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S140 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S141 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S142 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + 119, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S143 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S144 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S145 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S146 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S147 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S148 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S149 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S150 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S151 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S152 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S153 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S154 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S155 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S156 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S157 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, + gotoRow{ // S158 + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + -1, // Π + }, +} diff --git a/internal/frontend/reparsed/internal/parser/parser.go b/internal/frontend/reparsed/internal/parser/parser.go new file mode 100644 index 00000000..362f3016 --- /dev/null +++ b/internal/frontend/reparsed/internal/parser/parser.go @@ -0,0 +1,353 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "errors" + "fmt" + "strings" + + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/iface" + parseError "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/errors" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/token" +) + +const ( + numProductions = 51 + numStates = 159 + numSymbols = 45 +) + +// Stack + +type stack struct { + state []int + attrib []Attrib +} + +const INITIAL_STACK_SIZE = 100 + +func newStack() *stack { + return &stack{ + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), + } +} + +func (s *stack) reset() { + s.state = s.state[:0] + s.attrib = s.attrib[:0] +} + +func (s *stack) push(state int, a Attrib) { + s.state = append(s.state, state) + s.attrib = append(s.attrib, a) +} + +func (s *stack) top() int { + return s.state[len(s.state)-1] +} + +func (s *stack) peek(pos int) int { + return s.state[pos] +} + +func (s *stack) topIndex() int { + return len(s.state) - 1 +} + +func (s *stack) popN(items int) []Attrib { + lo, hi := len(s.state)-items, len(s.state) + + attrib := s.attrib[lo:hi] + + s.state = s.state[:lo] + s.attrib = s.attrib[:lo] + + return attrib +} + +func (s *stack) String() string { + w := new(strings.Builder) + fmt.Fprintf(w, "stack:\n") + for i, st := range s.state { + fmt.Fprintf(w, "\t%d: %d , ", i, st) + if s.attrib[i] == nil { + fmt.Fprintf(w, "nil") + } else { + switch attr := s.attrib[i].(type) { + case *token.Token: + fmt.Fprintf(w, "%s", attr.Lit) + default: + fmt.Fprintf(w, "%v", attr) + } + } + fmt.Fprintf(w, "\n") + } + return w.String() +} + +// Parser + +type Parser struct { + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance(o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +func NewParser() *Parser { + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u} + p.Reset() + return p +} + +func (p *Parser) Reset() { + p.stack.reset() + p.stack.push(0, nil) +} + +func (p *Parser) SetContext(ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext() interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { + errorAttrib = &parseError.Error{ + Err: err, + ErrorToken: p.nextToken, + ErrorSymbols: p.popNonRecoveryStates(), + ExpectedTokens: make([]string, 0, 8), + } + for t, action := range parserActions.table[p.stack.top()].actions { + if action != nil { + errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) + } + } + + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("λ")]; action != nil { + p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift + } else { + return + } + + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + for !recovered && p.nextToken.Type != token.EOF { + p.nextToken = scanner.Scan() + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { + recovered = true + } + } + + return +} + +func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol) { + if rs, ok := p.firstRecoveryState(); ok { + errorSymbols := p.stack.popN(p.stack.topIndex() - rs) + removedAttribs = make([]parseError.ErrorSymbol, len(errorSymbols)) + for i, e := range errorSymbols { + removedAttribs[i] = e + } + } else { + removedAttribs = []parseError.ErrorSymbol{} + } + return +} + +// recoveryState points to the highest state on the stack, which can recover +func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover + for recoveryState > 0 && !canRecover { + recoveryState-- + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover + } + return +} + +func (p *Parser) newError(err error) error { + e := &parseError.Error{ + Err: err, + StackTop: p.stack.top(), + ErrorToken: p.nextToken, + } + actRow := parserActions.table[p.stack.top()] + for i, t := range actRow.actions { + if t != nil { + e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) + } + } + return e +} + +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { + p.Reset() + p.needsRepositioning = longest + p.isNonDeterministic = false + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner); streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable); p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing(scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing(scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func() { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() + for acc := false; !acc; { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { + if recovered, errAttrib := p.Error(nil, scanner); !recovered { + p.nextToken = errAttrib.ErrorToken + return nil, p.newError(nil) + } + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { + panic("Error recovery led to invalid action") + } + } + + switch act := action.(type) { + case accept: + res = p.stack.popN(1)[0] + acc = true + case shift: + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() + case reduce: + prod := productionsTable[int(act)] + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) + if err != nil { + return nil, p.newError(err) + } else { + p.stack.push(gotoTab[p.stack.top()][prod.NTType], attrib) + } + default: + panic("unknown action: " + action.String()) + } + } + return res, nil +} diff --git a/internal/frontend/reparsed/internal/parser/productionstable.go b/internal/frontend/reparsed/internal/parser/productionstable.go new file mode 100644 index 00000000..08e8e729 --- /dev/null +++ b/internal/frontend/reparsed/internal/parser/productionstable.go @@ -0,0 +1,571 @@ +// Code generated by gocc; DO NOT EDIT. + +package parser + +import ( + "fmt" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/token" + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/util" + "strings" +) + +import ( + "github.com/maxcalandrelli/gocc/internal/ast" +) + +// now a > b should work... + +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: + return string(X.(*token.Token).Lit) + case string: + return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + +type ( + //TODO: change type and variable names to be consistent with other tables + ProdTab [numProductions]ProdTabEntry + ProdTabEntry struct { + String string + Id string + NTType int + Index int + NumSymbols int + ReduceFunc func(interface{}, []Attrib) (Attrib, error) + } + Attrib interface { + } +) + +var productionsTable = ProdTab{ + ProdTabEntry{ + String: `S' : Π << >>`, + Id: "S'", + NTType: 0, + Index: 0, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `Grammar : Π Π << ast.NewGrammar($0, $1) >>`, + Id: "Grammar", + NTType: 1, + Index: 1, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewGrammar(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Grammar : Π << ast.NewGrammar($0, nil) >>`, + Id: "Grammar", + NTType: 1, + Index: 2, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewGrammar(X[0], nil) + }, + }, + ProdTabEntry{ + String: `Grammar : Π << ast.NewGrammar(nil, $0) >>`, + Id: "Grammar", + NTType: 1, + Index: 3, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewGrammar(nil, X[0]) + }, + }, + ProdTabEntry{ + String: `LexicalPart : Π << ast.NewLexPart(nil, nil, $0) >>`, + Id: "LexicalPart", + NTType: 2, + Index: 4, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexPart(nil, nil, X[0]) + }, + }, + ProdTabEntry{ + String: `LexProductions : Π << ast.NewLexProductions($0) >>`, + Id: "LexProductions", + NTType: 4, + Index: 5, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexProductions(X[0]) + }, + }, + ProdTabEntry{ + String: `LexProductions : Π Π << ast.AppendLexProduction($0, $1) >>`, + Id: "LexProductions", + NTType: 4, + Index: 6, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AppendLexProduction(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `LexProduction : tokId Λ<:> Π Λ<;> << ast.NewLexTokDef($0, $2) >>`, + Id: "LexProduction", + NTType: 5, + Index: 7, + NumSymbols: 4, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexTokDef(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `LexProduction : regDefId Λ<:> Π Λ<;> << ast.NewLexRegDef($0, $2) >>`, + Id: "LexProduction", + NTType: 5, + Index: 8, + NumSymbols: 4, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexRegDef(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `LexProduction : ignoredTokId Λ<:> Π Λ<;> << ast.NewLexIgnoredTokDef($0, $2) >>`, + Id: "LexProduction", + NTType: 5, + Index: 9, + NumSymbols: 4, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexIgnoredTokDef(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `LexPattern : Π << ast.NewLexPattern($0) >>`, + Id: "LexPattern", + NTType: 6, + Index: 10, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexPattern(X[0]) + }, + }, + ProdTabEntry{ + String: `LexPattern : Π Λ<|> Π << ast.AppendLexAlt($0, $2) >>`, + Id: "LexPattern", + NTType: 6, + Index: 11, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AppendLexAlt(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `LexAlt : Π << ast.NewLexAlt($0) >>`, + Id: "LexAlt", + NTType: 7, + Index: 12, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexAlt(X[0]) + }, + }, + ProdTabEntry{ + String: `LexAlt : Π Π << ast.AppendLexTerm($0, $1) >>`, + Id: "LexAlt", + NTType: 7, + Index: 13, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AppendLexTerm(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `LexTerm : Λ<.> << ast.LexDOT, nil >>`, + Id: "LexTerm", + NTType: 8, + Index: 14, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.LexDOT, nil + }, + }, + ProdTabEntry{ + String: `LexTerm : char_lit << ast.NewLexCharLitExt($0,false) >>`, + Id: "LexTerm", + NTType: 8, + Index: 15, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexCharLitExt(X[0], false) + }, + }, + ProdTabEntry{ + String: `LexTerm : char_lit Λ<-> char_lit << ast.NewLexCharRangeExt($0, $2,false) >>`, + Id: "LexTerm", + NTType: 8, + Index: 16, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexCharRangeExt(X[0], X[2], false) + }, + }, + ProdTabEntry{ + String: `LexTerm : Λ<~> char_lit << ast.NewLexCharLitExt($1, true) >>`, + Id: "LexTerm", + NTType: 8, + Index: 17, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexCharLitExt(X[1], true) + }, + }, + ProdTabEntry{ + String: `LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> << ast.NewLexCharRangeExt($2, $4, true) >>`, + Id: "LexTerm", + NTType: 8, + Index: 18, + NumSymbols: 6, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexCharRangeExt(X[2], X[4], true) + }, + }, + ProdTabEntry{ + String: `LexTerm : regDefId << ast.NewLexRegDefId($0) >>`, + Id: "LexTerm", + NTType: 8, + Index: 19, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexRegDefId(X[0]) + }, + }, + ProdTabEntry{ + String: `LexTerm : Λ<[> Π Λ<]> << ast.NewLexOptPattern($1) >>`, + Id: "LexTerm", + NTType: 8, + Index: 20, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexOptPattern(X[1]) + }, + }, + ProdTabEntry{ + String: `LexTerm : Λ<{> Π Λ<}> << ast.NewLexRepPattern($1) >>`, + Id: "LexTerm", + NTType: 8, + Index: 21, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexRepPattern(X[1]) + }, + }, + ProdTabEntry{ + String: `LexTerm : Λ<(> Π Λ<)> << ast.NewLexGroupPattern($1) >>`, + Id: "LexTerm", + NTType: 8, + Index: 22, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewLexGroupPattern(X[1]) + }, + }, + ProdTabEntry{ + String: `SyntaxPart : Π Π << ast.NewSyntaxPart($0, $1) >>`, + Id: "SyntaxPart", + NTType: 3, + Index: 23, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxPart(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `SyntaxPart : Π << ast.NewSyntaxPart(nil, $0) >>`, + Id: "SyntaxPart", + NTType: 3, + Index: 24, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxPart(nil, X[0]) + }, + }, + ProdTabEntry{ + String: `FileHeader : g_sdt_lit << ast.NewFileHeader($0) >>`, + Id: "FileHeader", + NTType: 9, + Index: 25, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewFileHeader(X[0]) + }, + }, + ProdTabEntry{ + String: `SyntaxProdList : Π << ast.NewSyntaxProdList($0) >>`, + Id: "SyntaxProdList", + NTType: 10, + Index: 26, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxProdList(X[0]) + }, + }, + ProdTabEntry{ + String: `SyntaxProdList : Π Π << ast.AddSyntaxProds($0, $1) >>`, + Id: "SyntaxProdList", + NTType: 10, + Index: 27, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AddSyntaxProds(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `SyntaxProduction : prodId Λ<:> Π Λ<;> << ast.NewSyntaxProd($0, $2) >>`, + Id: "SyntaxProduction", + NTType: 11, + Index: 28, + NumSymbols: 4, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxProd(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `Alternatives : Π << ast.NewSyntaxAlts($0) >>`, + Id: "Alternatives", + NTType: 12, + Index: 29, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxAlts(X[0]) + }, + }, + ProdTabEntry{ + String: `Alternatives : Π Λ<|> Π << ast.AddSyntaxAlt($0, $2) >>`, + Id: "Alternatives", + NTType: 12, + Index: 30, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AddSyntaxAlt(X[0], X[2]) + }, + }, + ProdTabEntry{ + String: `SyntaxBody : Π << ast.NewSyntaxBodyGen($0, nil) >>`, + Id: "SyntaxBody", + NTType: 13, + Index: 31, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxBodyGen(X[0], nil) + }, + }, + ProdTabEntry{ + String: `SyntaxBody : Π g_sdt_lit << ast.NewSyntaxBodyGen($0, $1) >>`, + Id: "SyntaxBody", + NTType: 13, + Index: 32, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxBodyGen(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `SyntaxBody : Π << ast.NewErrorBodyGen(nil, nil) >>`, + Id: "SyntaxBody", + NTType: 13, + Index: 33, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewErrorBodyGen(nil, nil) + }, + }, + ProdTabEntry{ + String: `SyntaxBody : Π Π << ast.NewErrorBodyGen($1, nil) >>`, + Id: "SyntaxBody", + NTType: 13, + Index: 34, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewErrorBodyGen(X[1], nil) + }, + }, + ProdTabEntry{ + String: `SyntaxBody : Π Π g_sdt_lit << ast.NewErrorBodyGen($1, $2) >>`, + Id: "SyntaxBody", + NTType: 13, + Index: 35, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewErrorBodyGen(X[1], X[2]) + }, + }, + ProdTabEntry{ + String: `SyntaxBody : Π g_sdt_lit << ast.NewErrorBodyGen(nil, $1) >>`, + Id: "SyntaxBody", + NTType: 13, + Index: 36, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewErrorBodyGen(nil, X[1]) + }, + }, + ProdTabEntry{ + String: `SyntaxBody : Π << ast.NewEmptyBodyGen() >>`, + Id: "SyntaxBody", + NTType: 13, + Index: 37, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewEmptyBodyGen() + }, + }, + ProdTabEntry{ + String: `SyntaxBody : Π g_sdt_lit << ast.NewEmptyBodyGen() >>`, + Id: "SyntaxBody", + NTType: 13, + Index: 38, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewEmptyBodyGen() + }, + }, + ProdTabEntry{ + String: `Symbols : Π << ast.NewSyntaxSymbols($0) >>`, + Id: "Symbols", + NTType: 14, + Index: 39, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxSymbols(X[0]) + }, + }, + ProdTabEntry{ + String: `Symbols : Π Π << ast.AddSyntaxSymbol($0, $1) >>`, + Id: "Symbols", + NTType: 14, + Index: 40, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.AddSyntaxSymbol(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Symbol : prodId << ast.NewSyntaxProdId($0) >>`, + Id: "Symbol", + NTType: 17, + Index: 41, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSyntaxProdId(X[0]) + }, + }, + ProdTabEntry{ + String: `Symbol : tokId << ast.NewTokId($0) >>`, + Id: "Symbol", + NTType: 17, + Index: 42, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewTokId(X[0]) + }, + }, + ProdTabEntry{ + String: `Symbol : string_lit << ast.NewStringLit($0) >>`, + Id: "Symbol", + NTType: 17, + Index: 43, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewStringLit(X[0]) + }, + }, + ProdTabEntry{ + String: `Symbol : tokId g_ctxdep_lit << ast.NewContextDependentTokId($0,$1) >>`, + Id: "Symbol", + NTType: 17, + Index: 44, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewContextDependentTokId(X[0], X[1]) + }, + }, + ProdTabEntry{ + String: `Symbol : Λ<@> tokId string_lit << ast.NewAliasedSubParser($1,$2) >>`, + Id: "Symbol", + NTType: 17, + Index: 45, + NumSymbols: 3, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewAliasedSubParser(X[1], X[2]) + }, + }, + ProdTabEntry{ + String: `Symbol : Λ<@> string_lit << ast.NewSubParser($1) >>`, + Id: "Symbol", + NTType: 17, + Index: 46, + NumSymbols: 2, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return ast.NewSubParser(X[1]) + }, + }, + ProdTabEntry{ + String: `ErrorSymbol : Λ << >>`, + Id: "ErrorSymbol", + NTType: 15, + Index: 47, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `ErrorSymbol : Λ<λ> << >>`, + Id: "ErrorSymbol", + NTType: 15, + Index: 48, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `EpsilonSymbol : Λ << >>`, + Id: "EpsilonSymbol", + NTType: 16, + Index: 49, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, + ProdTabEntry{ + String: `EpsilonSymbol : Λ<ε> << >>`, + Id: "EpsilonSymbol", + NTType: 16, + Index: 50, + NumSymbols: 1, + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { + return X[0], nil + }, + }, +} diff --git a/internal/frontend/reparsed/internal/token/token.go b/internal/frontend/reparsed/internal/token/token.go new file mode 100644 index 00000000..9a422007 --- /dev/null +++ b/internal/frontend/reparsed/internal/token/token.go @@ -0,0 +1,217 @@ +// Code generated by gocc; DO NOT EDIT. + +package token + +import ( + "fmt" + "strconv" + "unicode/utf8" +) + +type Token struct { + Type + Lit []byte + IgnoredPrefix []byte + Pos + ForeignAstNode interface{} + Foreign bool +} + +type Type int + +const ( + INVALID Type = iota + EOF +) + +type Pos struct { + Offset int + Line int + Column int +} + +func (p Pos) String() string { + return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) +} + +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + +type TokenMap struct { + typeMap []string + idMap map[string]Type + litMap map[string]Type +} + +func (m TokenMap) Id(tok Type) string { + if int(tok) < len(m.typeMap) { + return m.typeMap[tok] + } + return "unknown" +} + +func (m TokenMap) Type(tok string) Type { + if typ, exist := m.idMap[tok]; exist { + return typ + } + return INVALID +} + +func (m TokenMap) TokenString(tok *Token) string { + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) +} + +func (m TokenMap) StringType(typ Type) string { + return fmt.Sprintf("%s(%d)", m.Id(typ), typ) +} + +// CharLiteralValue returns the string value of the char literal. +func (t *Token) CharLiteralValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +// Float32Value returns the float32 value of the token or an error if the token literal does not +// denote a valid float32. +func (t *Token) Float32Value() (float32, error) { + if v, err := strconv.ParseFloat(string(t.Lit), 32); err != nil { + return 0, err + } else { + return float32(v), nil + } +} + +// Float64Value returns the float64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Float64Value() (float64, error) { + return strconv.ParseFloat(string(t.Lit), 64) +} + +// IDValue returns the string representation of an identifier token. +func (t *Token) IDValue() string { + return string(t.Lit) +} + +// Int32Value returns the int32 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int32Value() (int32, error) { + if v, err := strconv.ParseInt(string(t.Lit), 10, 64); err != nil { + return 0, err + } else { + return int32(v), nil + } +} + +// Int64Value returns the int64 value of the token or an error if the token literal does not +// denote a valid float64. +func (t *Token) Int64Value() (int64, error) { + return strconv.ParseInt(string(t.Lit), 10, 64) +} + +// UTF8Rune decodes the UTF8 rune in the token literal. It returns utf8.RuneError if +// the token literal contains an invalid rune. +func (t *Token) UTF8Rune() (rune, error) { + r, _ := utf8.DecodeRune(t.Lit) + if r == utf8.RuneError { + err := fmt.Errorf("Invalid rune") + return r, err + } + return r, nil +} + +// StringValue returns the string value of the token literal. +func (t *Token) StringValue() string { + return string(t.Lit[1 : len(t.Lit)-1]) +} + +var TokMap = TokenMap{ + typeMap: []string{ + "INVALID", + "Ω", + "tokId", + "Λ<:>", + "Λ<;>", + "regDefId", + "ignoredTokId", + "Λ<|>", + "Λ<.>", + "char_lit", + "Λ<->", + "Λ<~>", + "Λ<(>", + "Λ<)>", + "Λ<[>", + "Λ<]>", + "Λ<{>", + "Λ<}>", + "g_sdt_lit", + "prodId", + "string_lit", + "g_ctxdep_lit", + "Λ<@>", + "Λ", + "Λ<λ>", + "Λ", + "Λ<ε>", + }, + + idMap: map[string]Type{ + "INVALID": 0, + "Ω": 1, + "tokId": 2, + "Λ<:>": 3, + "Λ<;>": 4, + "regDefId": 5, + "ignoredTokId": 6, + "Λ<|>": 7, + "Λ<.>": 8, + "char_lit": 9, + "Λ<->": 10, + "Λ<~>": 11, + "Λ<(>": 12, + "Λ<)>": 13, + "Λ<[>": 14, + "Λ<]>": 15, + "Λ<{>": 16, + "Λ<}>": 17, + "g_sdt_lit": 18, + "prodId": 19, + "string_lit": 20, + "g_ctxdep_lit": 21, + "Λ<@>": 22, + "Λ": 23, + "Λ<λ>": 24, + "Λ": 25, + "Λ<ε>": 26, + }, + + litMap: map[string]Type{ + ":": 3, + ";": 4, + "|": 7, + ".": 8, + "-": 10, + "~": 11, + "(": 12, + ")": 13, + "[": 14, + "]": 15, + "{": 16, + "}": 17, + "@": 22, + "error": 23, + "λ": 24, + "empty": 25, + "ε": 26, + }, +} diff --git a/internal/frontend/reparsed/internal/util/litconv.go b/internal/frontend/reparsed/internal/util/litconv.go new file mode 100644 index 00000000..1aeb6166 --- /dev/null +++ b/internal/frontend/reparsed/internal/util/litconv.go @@ -0,0 +1,108 @@ +// Code generated by gocc; DO NOT EDIT. + +package util + +import ( + "fmt" + "strconv" + "unicode" + "unicode/utf8" +) + +/* Interface */ + +/* +Convert the literal value of a scanned token to rune +*/ +func RuneValue(lit []byte) rune { + if lit[1] == '\\' { + return escapeCharVal(lit) + } + r, size := utf8.DecodeRune(lit[1:]) + if size != len(lit)-2 { + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + } + return r +} + +/* +Convert the literal value of a scanned token to int64 +*/ +func IntValue(lit []byte) (int64, error) { + return strconv.ParseInt(string(lit), 10, 64) +} + +/* +Convert the literal value of a scanned token to uint64 +*/ +func UintValue(lit []byte) (uint64, error) { + return strconv.ParseUint(string(lit), 10, 64) +} + +/* Util */ + +func escapeCharVal(lit []byte) rune { + var i, base, max uint32 + offset := 2 + switch lit[offset] { + case 'a': + return '\a' + case 'b': + return '\b' + case 'f': + return '\f' + case 'n': + return '\n' + case 'r': + return '\r' + case 't': + return '\t' + case 'v': + return '\v' + case '\\': + return '\\' + case '\'': + return '\'' + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 16, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", lit)) + } + + var x uint32 + for ; i > 0 && offset < len(lit)-1; i-- { + ch, size := utf8.DecodeRune(lit[offset:]) + offset += size + d := uint32(digitVal(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", lit, ch, size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", lit, offset)) + } + + return rune(x) +} + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/internal/frontend/reparsed/internal/util/rune.go b/internal/frontend/reparsed/internal/util/rune.go new file mode 100644 index 00000000..788edfde --- /dev/null +++ b/internal/frontend/reparsed/internal/util/rune.go @@ -0,0 +1,140 @@ +// Code generated by gocc; DO NOT EDIT. + + +package util + +import ( + "fmt" + "unicode" + "unicode/utf8" +) + +func RuneToString(r rune) string { + if r >= 0x20 && r < 0x7f { + return fmt.Sprintf("'%c'", r) + } + switch r { + case 0x07: + return "'\\a'" + case 0x08: + return "'\\b'" + case 0x0C: + return "'\\f'" + case 0x0A: + return "'\\n'" + case 0x0D: + return "'\\r'" + case 0x09: + return "'\\t'" + case 0x0b: + return "'\\v'" + case 0x5c: + return "'\\\\\\'" + case 0x27: + return "'\\''" + case 0x22: + return "'\\\"'" + } + if r < 0x10000 { + return fmt.Sprintf("\\u%04x", r) + } + return fmt.Sprintf("\\U%08x", r) +} + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + diff --git a/internal/frontend/reparsed/log/LR1_sets.txt b/internal/frontend/reparsed/log/LR1_sets.txt new file mode 100644 index 00000000..89e5d3ed --- /dev/null +++ b/internal/frontend/reparsed/log/LR1_sets.txt @@ -0,0 +1,5492 @@ +S0{ + S' : •Π «Ω» + Grammar : •Π Π «Ω» + Grammar : •Π «Ω» + Grammar : •Π «Ω» + LexicalPart : •Π «g_sdt_lit» + LexicalPart : •Π «prodId» + LexicalPart : •Π «Ω» + SyntaxPart : •Π Π «Ω» + SyntaxPart : •Π «Ω» + LexProductions : •Π «g_sdt_lit» + LexProductions : •Π Π «g_sdt_lit» + LexProductions : •Π «prodId» + LexProductions : •Π Π «prodId» + LexProductions : •Π «Ω» + LexProductions : •Π Π «Ω» + FileHeader : •g_sdt_lit «prodId» + SyntaxProdList : •Π «Ω» + SyntaxProdList : •Π Π «Ω» + LexProduction : •tokId Λ<:> Π Λ<;> «g_sdt_lit» + LexProduction : •regDefId Λ<:> Π Λ<;> «g_sdt_lit» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «g_sdt_lit» + LexProductions : •Π «ignoredTokId» + LexProductions : •Π «regDefId» + LexProductions : •Π «tokId» + LexProductions : •Π Π «ignoredTokId» + LexProductions : •Π Π «regDefId» + LexProductions : •Π Π «tokId» + LexProduction : •tokId Λ<:> Π Λ<;> «prodId» + LexProduction : •regDefId Λ<:> Π Λ<;> «prodId» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «prodId» + LexProduction : •tokId Λ<:> Π Λ<;> «Ω» + LexProduction : •regDefId Λ<:> Π Λ<;> «Ω» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «Ω» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «Ω» + SyntaxProdList : •Π «prodId» + SyntaxProdList : •Π Π «prodId» + LexProduction : •tokId Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : •regDefId Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : •tokId Λ<:> Π Λ<;> «regDefId» + LexProduction : •regDefId Λ<:> Π Λ<;> «regDefId» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «regDefId» + LexProduction : •tokId Λ<:> Π Λ<;> «tokId» + LexProduction : •regDefId Λ<:> Π Λ<;> «tokId» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «tokId» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «prodId» +} +Transitions: + Π -> 1 + Π -> 2 + Π -> 3 + Π -> 4 + Π -> 5 + Π -> 6 + Π -> 7 + Π -> 8 + tokId -> 9 + regDefId -> 10 + ignoredTokId -> 11 + g_sdt_lit -> 12 + prodId -> 13 + + +S1{ + S' : Π• «Ω» +} +Transitions: + + +S2{ + Grammar : Π •Π «Ω» + Grammar : Π• «Ω» + SyntaxPart : •Π Π «Ω» + SyntaxPart : •Π «Ω» + FileHeader : •g_sdt_lit «prodId» + SyntaxProdList : •Π «Ω» + SyntaxProdList : •Π Π «Ω» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «Ω» + SyntaxProdList : •Π «prodId» + SyntaxProdList : •Π Π «prodId» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «prodId» +} +Transitions: + Π -> 6 + Π -> 7 + Π -> 8 + g_sdt_lit -> 12 + prodId -> 13 + Π -> 14 + + +S3{ + Grammar : Π• «Ω» +} +Transitions: + + +S4{ + LexicalPart : Π• «g_sdt_lit» + LexicalPart : Π• «prodId» + LexicalPart : Π• «Ω» + LexProductions : Π •Π «g_sdt_lit» + LexProductions : Π •Π «prodId» + LexProductions : Π •Π «Ω» + LexProductions : Π •Π «ignoredTokId» + LexProductions : Π •Π «regDefId» + LexProductions : Π •Π «tokId» + LexProduction : •tokId Λ<:> Π Λ<;> «g_sdt_lit» + LexProduction : •regDefId Λ<:> Π Λ<;> «g_sdt_lit» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «g_sdt_lit» + LexProduction : •tokId Λ<:> Π Λ<;> «prodId» + LexProduction : •regDefId Λ<:> Π Λ<;> «prodId» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «prodId» + LexProduction : •tokId Λ<:> Π Λ<;> «Ω» + LexProduction : •regDefId Λ<:> Π Λ<;> «Ω» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «Ω» + LexProduction : •tokId Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : •regDefId Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : •tokId Λ<:> Π Λ<;> «regDefId» + LexProduction : •regDefId Λ<:> Π Λ<;> «regDefId» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «regDefId» + LexProduction : •tokId Λ<:> Π Λ<;> «tokId» + LexProduction : •regDefId Λ<:> Π Λ<;> «tokId» + LexProduction : •ignoredTokId Λ<:> Π Λ<;> «tokId» +} +Transitions: + tokId -> 9 + regDefId -> 10 + ignoredTokId -> 11 + Π -> 15 + + +S5{ + LexProductions : Π• «g_sdt_lit» + LexProductions : Π• «prodId» + LexProductions : Π• «Ω» + LexProductions : Π• «ignoredTokId» + LexProductions : Π• «regDefId» + LexProductions : Π• «tokId» +} +Transitions: + + +S6{ + SyntaxPart : Π •Π «Ω» + SyntaxProdList : •Π «Ω» + SyntaxProdList : •Π Π «Ω» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «Ω» + SyntaxProdList : •Π «prodId» + SyntaxProdList : •Π Π «prodId» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «prodId» +} +Transitions: + Π -> 8 + prodId -> 13 + Π -> 16 + + +S7{ + SyntaxPart : Π• «Ω» + SyntaxProdList : Π •Π «Ω» + SyntaxProdList : Π •Π «prodId» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «Ω» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «prodId» +} +Transitions: + prodId -> 13 + Π -> 17 + + +S8{ + SyntaxProdList : Π• «Ω» + SyntaxProdList : Π• «prodId» +} +Transitions: + + +S9{ + LexProduction : tokId •Λ<:> Π Λ<;> «g_sdt_lit» + LexProduction : tokId •Λ<:> Π Λ<;> «prodId» + LexProduction : tokId •Λ<:> Π Λ<;> «Ω» + LexProduction : tokId •Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : tokId •Λ<:> Π Λ<;> «regDefId» + LexProduction : tokId •Λ<:> Π Λ<;> «tokId» +} +Transitions: + Λ<:> -> 18 + + +S10{ + LexProduction : regDefId •Λ<:> Π Λ<;> «g_sdt_lit» + LexProduction : regDefId •Λ<:> Π Λ<;> «prodId» + LexProduction : regDefId •Λ<:> Π Λ<;> «Ω» + LexProduction : regDefId •Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : regDefId •Λ<:> Π Λ<;> «regDefId» + LexProduction : regDefId •Λ<:> Π Λ<;> «tokId» +} +Transitions: + Λ<:> -> 19 + + +S11{ + LexProduction : ignoredTokId •Λ<:> Π Λ<;> «g_sdt_lit» + LexProduction : ignoredTokId •Λ<:> Π Λ<;> «prodId» + LexProduction : ignoredTokId •Λ<:> Π Λ<;> «Ω» + LexProduction : ignoredTokId •Λ<:> Π Λ<;> «ignoredTokId» + LexProduction : ignoredTokId •Λ<:> Π Λ<;> «regDefId» + LexProduction : ignoredTokId •Λ<:> Π Λ<;> «tokId» +} +Transitions: + Λ<:> -> 20 + + +S12{ + FileHeader : g_sdt_lit• «prodId» +} +Transitions: + + +S13{ + SyntaxProduction : prodId •Λ<:> Π Λ<;> «Ω» + SyntaxProduction : prodId •Λ<:> Π Λ<;> «prodId» +} +Transitions: + Λ<:> -> 21 + + +S14{ + Grammar : Π Π• «Ω» +} +Transitions: + + +S15{ + LexProductions : Π Π• «g_sdt_lit» + LexProductions : Π Π• «prodId» + LexProductions : Π Π• «Ω» + LexProductions : Π Π• «ignoredTokId» + LexProductions : Π Π• «regDefId» + LexProductions : Π Π• «tokId» +} +Transitions: + + +S16{ + SyntaxPart : Π Π• «Ω» + SyntaxProdList : Π •Π «Ω» + SyntaxProdList : Π •Π «prodId» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «Ω» + SyntaxProduction : •prodId Λ<:> Π Λ<;> «prodId» +} +Transitions: + prodId -> 13 + Π -> 17 + + +S17{ + SyntaxProdList : Π Π• «Ω» + SyntaxProdList : Π Π• «prodId» +} +Transitions: + + +S18{ + LexProduction : tokId Λ<:> •Π Λ<;> «g_sdt_lit» + LexProduction : tokId Λ<:> •Π Λ<;> «prodId» + LexProduction : tokId Λ<:> •Π Λ<;> «Ω» + LexProduction : tokId Λ<:> •Π Λ<;> «ignoredTokId» + LexProduction : tokId Λ<:> •Π Λ<;> «regDefId» + LexProduction : tokId Λ<:> •Π Λ<;> «tokId» + LexPattern : •Π «";"» + LexPattern : •Π Λ<|> Π «";"» + LexAlt : •Π «";"» + LexAlt : •Π Π «";"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «";"» + LexTerm : •char_lit «";"» + LexTerm : •char_lit Λ<-> char_lit «";"» + LexTerm : •Λ<~> char_lit «";"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «";"» + LexTerm : •regDefId «";"» + LexTerm : •Λ<[> Π Λ<]> «";"» + LexTerm : •Λ<{> Π Λ<}> «";"» + LexTerm : •Λ<(> Π Λ<)> «";"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 22 + Π -> 23 + Π -> 24 + regDefId -> 25 + Λ<.> -> 26 + char_lit -> 27 + Λ<~> -> 28 + Λ<(> -> 29 + Λ<[> -> 30 + Λ<{> -> 31 + + +S19{ + LexProduction : regDefId Λ<:> •Π Λ<;> «g_sdt_lit» + LexProduction : regDefId Λ<:> •Π Λ<;> «prodId» + LexProduction : regDefId Λ<:> •Π Λ<;> «Ω» + LexProduction : regDefId Λ<:> •Π Λ<;> «ignoredTokId» + LexProduction : regDefId Λ<:> •Π Λ<;> «regDefId» + LexProduction : regDefId Λ<:> •Π Λ<;> «tokId» + LexPattern : •Π «";"» + LexPattern : •Π Λ<|> Π «";"» + LexAlt : •Π «";"» + LexAlt : •Π Π «";"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «";"» + LexTerm : •char_lit «";"» + LexTerm : •char_lit Λ<-> char_lit «";"» + LexTerm : •Λ<~> char_lit «";"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «";"» + LexTerm : •regDefId «";"» + LexTerm : •Λ<[> Π Λ<]> «";"» + LexTerm : •Λ<{> Π Λ<}> «";"» + LexTerm : •Λ<(> Π Λ<)> «";"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 23 + Π -> 24 + regDefId -> 25 + Λ<.> -> 26 + char_lit -> 27 + Λ<~> -> 28 + Λ<(> -> 29 + Λ<[> -> 30 + Λ<{> -> 31 + Π -> 32 + + +S20{ + LexProduction : ignoredTokId Λ<:> •Π Λ<;> «g_sdt_lit» + LexProduction : ignoredTokId Λ<:> •Π Λ<;> «prodId» + LexProduction : ignoredTokId Λ<:> •Π Λ<;> «Ω» + LexProduction : ignoredTokId Λ<:> •Π Λ<;> «ignoredTokId» + LexProduction : ignoredTokId Λ<:> •Π Λ<;> «regDefId» + LexProduction : ignoredTokId Λ<:> •Π Λ<;> «tokId» + LexPattern : •Π «";"» + LexPattern : •Π Λ<|> Π «";"» + LexAlt : •Π «";"» + LexAlt : •Π Π «";"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «";"» + LexTerm : •char_lit «";"» + LexTerm : •char_lit Λ<-> char_lit «";"» + LexTerm : •Λ<~> char_lit «";"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «";"» + LexTerm : •regDefId «";"» + LexTerm : •Λ<[> Π Λ<]> «";"» + LexTerm : •Λ<{> Π Λ<}> «";"» + LexTerm : •Λ<(> Π Λ<)> «";"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 23 + Π -> 24 + regDefId -> 25 + Λ<.> -> 26 + char_lit -> 27 + Λ<~> -> 28 + Λ<(> -> 29 + Λ<[> -> 30 + Λ<{> -> 31 + Π -> 33 + + +S21{ + SyntaxProduction : prodId Λ<:> •Π Λ<;> «Ω» + SyntaxProduction : prodId Λ<:> •Π Λ<;> «prodId» + Alternatives : •Π «";"» + Alternatives : •Π Λ<|> Π «";"» + SyntaxBody : •Π «";"» + SyntaxBody : •Π g_sdt_lit «";"» + SyntaxBody : •Π «";"» + SyntaxBody : •Π Π «";"» + SyntaxBody : •Π Π g_sdt_lit «";"» + SyntaxBody : •Π g_sdt_lit «";"» + SyntaxBody : •Π «";"» + SyntaxBody : •Π g_sdt_lit «";"» + Alternatives : •Π «"|"» + Alternatives : •Π Λ<|> Π «"|"» + Symbols : •Π «";"» + Symbols : •Π Π «";"» + Symbols : •Π «g_sdt_lit» + Symbols : •Π Π «g_sdt_lit» + ErrorSymbol : •Λ «";"» + ErrorSymbol : •Λ<λ> «";"» + ErrorSymbol : •Λ «"@"» + ErrorSymbol : •Λ «prodId» + ErrorSymbol : •Λ «string_lit» + ErrorSymbol : •Λ «tokId» + ErrorSymbol : •Λ<λ> «"@"» + ErrorSymbol : •Λ<λ> «prodId» + ErrorSymbol : •Λ<λ> «string_lit» + ErrorSymbol : •Λ<λ> «tokId» + ErrorSymbol : •Λ «g_sdt_lit» + ErrorSymbol : •Λ<λ> «g_sdt_lit» + EpsilonSymbol : •Λ «";"» + EpsilonSymbol : •Λ<ε> «";"» + EpsilonSymbol : •Λ «g_sdt_lit» + EpsilonSymbol : •Λ<ε> «g_sdt_lit» + SyntaxBody : •Π «"|"» + SyntaxBody : •Π g_sdt_lit «"|"» + SyntaxBody : •Π «"|"» + SyntaxBody : •Π Π «"|"» + SyntaxBody : •Π Π g_sdt_lit «"|"» + SyntaxBody : •Π g_sdt_lit «"|"» + SyntaxBody : •Π «"|"» + SyntaxBody : •Π g_sdt_lit «"|"» + Symbol : •prodId «";"» + Symbol : •tokId «";"» + Symbol : •string_lit «";"» + Symbol : •tokId g_ctxdep_lit «";"» + Symbol : •Λ<@> tokId string_lit «";"» + Symbol : •Λ<@> string_lit «";"» + Symbols : •Π «"@"» + Symbols : •Π «prodId» + Symbols : •Π «string_lit» + Symbols : •Π «tokId» + Symbols : •Π Π «"@"» + Symbols : •Π Π «prodId» + Symbols : •Π Π «string_lit» + Symbols : •Π Π «tokId» + Symbol : •prodId «g_sdt_lit» + Symbol : •tokId «g_sdt_lit» + Symbol : •string_lit «g_sdt_lit» + Symbol : •tokId g_ctxdep_lit «g_sdt_lit» + Symbol : •Λ<@> tokId string_lit «g_sdt_lit» + Symbol : •Λ<@> string_lit «g_sdt_lit» + Symbols : •Π «"|"» + Symbols : •Π Π «"|"» + ErrorSymbol : •Λ «"|"» + ErrorSymbol : •Λ<λ> «"|"» + EpsilonSymbol : •Λ «"|"» + EpsilonSymbol : •Λ<ε> «"|"» + Symbol : •prodId «"@"» + Symbol : •tokId «"@"» + Symbol : •string_lit «"@"» + Symbol : •tokId g_ctxdep_lit «"@"» + Symbol : •Λ<@> tokId string_lit «"@"» + Symbol : •Λ<@> string_lit «"@"» + Symbol : •prodId «prodId» + Symbol : •tokId «prodId» + Symbol : •string_lit «prodId» + Symbol : •tokId g_ctxdep_lit «prodId» + Symbol : •Λ<@> tokId string_lit «prodId» + Symbol : •Λ<@> string_lit «prodId» + Symbol : •prodId «string_lit» + Symbol : •tokId «string_lit» + Symbol : •string_lit «string_lit» + Symbol : •tokId g_ctxdep_lit «string_lit» + Symbol : •Λ<@> tokId string_lit «string_lit» + Symbol : •Λ<@> string_lit «string_lit» + Symbol : •prodId «tokId» + Symbol : •tokId «tokId» + Symbol : •string_lit «tokId» + Symbol : •tokId g_ctxdep_lit «tokId» + Symbol : •Λ<@> tokId string_lit «tokId» + Symbol : •Λ<@> string_lit «tokId» + Symbol : •prodId «"|"» + Symbol : •tokId «"|"» + Symbol : •string_lit «"|"» + Symbol : •tokId g_ctxdep_lit «"|"» + Symbol : •Λ<@> tokId string_lit «"|"» + Symbol : •Λ<@> string_lit «"|"» +} +Transitions: + Π -> 34 + Π -> 35 + Π -> 36 + Π -> 37 + Π -> 38 + Π -> 39 + tokId -> 40 + prodId -> 41 + string_lit -> 42 + Λ<@> -> 43 + Λ -> 44 + Λ<λ> -> 45 + Λ -> 46 + Λ<ε> -> 47 + + +S22{ + LexProduction : tokId Λ<:> Π •Λ<;> «g_sdt_lit» + LexProduction : tokId Λ<:> Π •Λ<;> «prodId» + LexProduction : tokId Λ<:> Π •Λ<;> «Ω» + LexProduction : tokId Λ<:> Π •Λ<;> «ignoredTokId» + LexProduction : tokId Λ<:> Π •Λ<;> «regDefId» + LexProduction : tokId Λ<:> Π •Λ<;> «tokId» + LexPattern : Π •Λ<|> Π «";"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<;> -> 48 + Λ<|> -> 49 + + +S23{ + LexPattern : Π• «";"» + LexAlt : Π •Π «";"» + LexPattern : Π• «"|"» + LexAlt : Π •Π «"("» + LexAlt : Π •Π «"."» + LexAlt : Π •Π «"["» + LexAlt : Π •Π «char_lit» + LexAlt : Π •Π «regDefId» + LexAlt : Π •Π «"{"» + LexAlt : Π •Π «"~"» + LexAlt : Π •Π «"|"» + LexTerm : •Λ<.> «";"» + LexTerm : •char_lit «";"» + LexTerm : •char_lit Λ<-> char_lit «";"» + LexTerm : •Λ<~> char_lit «";"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «";"» + LexTerm : •regDefId «";"» + LexTerm : •Λ<[> Π Λ<]> «";"» + LexTerm : •Λ<{> Π Λ<}> «";"» + LexTerm : •Λ<(> Π Λ<)> «";"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + regDefId -> 25 + Λ<.> -> 26 + char_lit -> 27 + Λ<~> -> 28 + Λ<(> -> 29 + Λ<[> -> 30 + Λ<{> -> 31 + Π -> 50 + + +S24{ + LexAlt : Π• «";"» + LexAlt : Π• «"("» + LexAlt : Π• «"."» + LexAlt : Π• «"["» + LexAlt : Π• «char_lit» + LexAlt : Π• «regDefId» + LexAlt : Π• «"{"» + LexAlt : Π• «"~"» + LexAlt : Π• «"|"» +} +Transitions: + + +S25{ + LexTerm : regDefId• «";"» + LexTerm : regDefId• «"("» + LexTerm : regDefId• «"."» + LexTerm : regDefId• «"["» + LexTerm : regDefId• «char_lit» + LexTerm : regDefId• «regDefId» + LexTerm : regDefId• «"{"» + LexTerm : regDefId• «"~"» + LexTerm : regDefId• «"|"» +} +Transitions: + + +S26{ + LexTerm : Λ<.>• «";"» + LexTerm : Λ<.>• «"("» + LexTerm : Λ<.>• «"."» + LexTerm : Λ<.>• «"["» + LexTerm : Λ<.>• «char_lit» + LexTerm : Λ<.>• «regDefId» + LexTerm : Λ<.>• «"{"» + LexTerm : Λ<.>• «"~"» + LexTerm : Λ<.>• «"|"» +} +Transitions: + + +S27{ + LexTerm : char_lit• «";"» + LexTerm : char_lit •Λ<-> char_lit «";"» + LexTerm : char_lit• «"("» + LexTerm : char_lit •Λ<-> char_lit «"("» + LexTerm : char_lit• «"."» + LexTerm : char_lit •Λ<-> char_lit «"."» + LexTerm : char_lit• «"["» + LexTerm : char_lit •Λ<-> char_lit «"["» + LexTerm : char_lit• «char_lit» + LexTerm : char_lit •Λ<-> char_lit «char_lit» + LexTerm : char_lit• «regDefId» + LexTerm : char_lit •Λ<-> char_lit «regDefId» + LexTerm : char_lit• «"{"» + LexTerm : char_lit •Λ<-> char_lit «"{"» + LexTerm : char_lit• «"~"» + LexTerm : char_lit •Λ<-> char_lit «"~"» + LexTerm : char_lit• «"|"» + LexTerm : char_lit •Λ<-> char_lit «"|"» +} +Transitions: + Λ<-> -> 51 + + +S28{ + LexTerm : Λ<~> •char_lit «";"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «";"» + LexTerm : Λ<~> •char_lit «"("» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> •char_lit «"."» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> •char_lit «"["» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> •char_lit «char_lit» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> •char_lit «regDefId» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> •char_lit «"{"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> •char_lit «"~"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> •char_lit «"|"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 52 + Λ<(> -> 53 + + +S29{ + LexTerm : Λ<(> •Π Λ<)> «";"» + LexTerm : Λ<(> •Π Λ<)> «"("» + LexTerm : Λ<(> •Π Λ<)> «"."» + LexTerm : Λ<(> •Π Λ<)> «"["» + LexTerm : Λ<(> •Π Λ<)> «char_lit» + LexTerm : Λ<(> •Π Λ<)> «regDefId» + LexTerm : Λ<(> •Π Λ<)> «"{"» + LexTerm : Λ<(> •Π Λ<)> «"~"» + LexTerm : Λ<(> •Π Λ<)> «"|"» + LexPattern : •Π «")"» + LexPattern : •Π Λ<|> Π «")"» + LexAlt : •Π «")"» + LexAlt : •Π Π «")"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «")"» + LexTerm : •char_lit «")"» + LexTerm : •char_lit Λ<-> char_lit «")"» + LexTerm : •Λ<~> char_lit «")"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : •regDefId «")"» + LexTerm : •Λ<[> Π Λ<]> «")"» + LexTerm : •Λ<{> Π Λ<}> «")"» + LexTerm : •Λ<(> Π Λ<)> «")"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 54 + Π -> 55 + Π -> 56 + regDefId -> 57 + Λ<.> -> 58 + char_lit -> 59 + Λ<~> -> 60 + Λ<(> -> 61 + Λ<[> -> 62 + Λ<{> -> 63 + + +S30{ + LexTerm : Λ<[> •Π Λ<]> «";"» + LexTerm : Λ<[> •Π Λ<]> «"("» + LexTerm : Λ<[> •Π Λ<]> «"."» + LexTerm : Λ<[> •Π Λ<]> «"["» + LexTerm : Λ<[> •Π Λ<]> «char_lit» + LexTerm : Λ<[> •Π Λ<]> «regDefId» + LexTerm : Λ<[> •Π Λ<]> «"{"» + LexTerm : Λ<[> •Π Λ<]> «"~"» + LexTerm : Λ<[> •Π Λ<]> «"|"» + LexPattern : •Π «"]"» + LexPattern : •Π Λ<|> Π «"]"» + LexAlt : •Π «"]"» + LexAlt : •Π Π «"]"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «"]"» + LexTerm : •char_lit «"]"» + LexTerm : •char_lit Λ<-> char_lit «"]"» + LexTerm : •Λ<~> char_lit «"]"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : •regDefId «"]"» + LexTerm : •Λ<[> Π Λ<]> «"]"» + LexTerm : •Λ<{> Π Λ<}> «"]"» + LexTerm : •Λ<(> Π Λ<)> «"]"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 64 + Π -> 65 + Π -> 66 + regDefId -> 67 + Λ<.> -> 68 + char_lit -> 69 + Λ<~> -> 70 + Λ<(> -> 71 + Λ<[> -> 72 + Λ<{> -> 73 + + +S31{ + LexTerm : Λ<{> •Π Λ<}> «";"» + LexTerm : Λ<{> •Π Λ<}> «"("» + LexTerm : Λ<{> •Π Λ<}> «"."» + LexTerm : Λ<{> •Π Λ<}> «"["» + LexTerm : Λ<{> •Π Λ<}> «char_lit» + LexTerm : Λ<{> •Π Λ<}> «regDefId» + LexTerm : Λ<{> •Π Λ<}> «"{"» + LexTerm : Λ<{> •Π Λ<}> «"~"» + LexTerm : Λ<{> •Π Λ<}> «"|"» + LexPattern : •Π «"}"» + LexPattern : •Π Λ<|> Π «"}"» + LexAlt : •Π «"}"» + LexAlt : •Π Π «"}"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «"}"» + LexTerm : •char_lit «"}"» + LexTerm : •char_lit Λ<-> char_lit «"}"» + LexTerm : •Λ<~> char_lit «"}"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : •regDefId «"}"» + LexTerm : •Λ<[> Π Λ<]> «"}"» + LexTerm : •Λ<{> Π Λ<}> «"}"» + LexTerm : •Λ<(> Π Λ<)> «"}"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 74 + Π -> 75 + Π -> 76 + regDefId -> 77 + Λ<.> -> 78 + char_lit -> 79 + Λ<~> -> 80 + Λ<(> -> 81 + Λ<[> -> 82 + Λ<{> -> 83 + + +S32{ + LexProduction : regDefId Λ<:> Π •Λ<;> «g_sdt_lit» + LexProduction : regDefId Λ<:> Π •Λ<;> «prodId» + LexProduction : regDefId Λ<:> Π •Λ<;> «Ω» + LexProduction : regDefId Λ<:> Π •Λ<;> «ignoredTokId» + LexProduction : regDefId Λ<:> Π •Λ<;> «regDefId» + LexProduction : regDefId Λ<:> Π •Λ<;> «tokId» + LexPattern : Π •Λ<|> Π «";"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 49 + Λ<;> -> 84 + + +S33{ + LexProduction : ignoredTokId Λ<:> Π •Λ<;> «g_sdt_lit» + LexProduction : ignoredTokId Λ<:> Π •Λ<;> «prodId» + LexProduction : ignoredTokId Λ<:> Π •Λ<;> «Ω» + LexProduction : ignoredTokId Λ<:> Π •Λ<;> «ignoredTokId» + LexProduction : ignoredTokId Λ<:> Π •Λ<;> «regDefId» + LexProduction : ignoredTokId Λ<:> Π •Λ<;> «tokId» + LexPattern : Π •Λ<|> Π «";"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 49 + Λ<;> -> 85 + + +S34{ + SyntaxProduction : prodId Λ<:> Π •Λ<;> «Ω» + SyntaxProduction : prodId Λ<:> Π •Λ<;> «prodId» + Alternatives : Π •Λ<|> Π «";"» + Alternatives : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<;> -> 86 + Λ<|> -> 87 + + +S35{ + Alternatives : Π• «";"» + Alternatives : Π• «"|"» +} +Transitions: + + +S36{ + SyntaxBody : Π• «";"» + SyntaxBody : Π •g_sdt_lit «";"» + Symbols : Π •Π «";"» + Symbols : Π •Π «g_sdt_lit» + SyntaxBody : Π• «"|"» + SyntaxBody : Π •g_sdt_lit «"|"» + Symbols : Π •Π «"@"» + Symbols : Π •Π «prodId» + Symbols : Π •Π «string_lit» + Symbols : Π •Π «tokId» + Symbols : Π •Π «"|"» + Symbol : •prodId «";"» + Symbol : •tokId «";"» + Symbol : •string_lit «";"» + Symbol : •tokId g_ctxdep_lit «";"» + Symbol : •Λ<@> tokId string_lit «";"» + Symbol : •Λ<@> string_lit «";"» + Symbol : •prodId «g_sdt_lit» + Symbol : •tokId «g_sdt_lit» + Symbol : •string_lit «g_sdt_lit» + Symbol : •tokId g_ctxdep_lit «g_sdt_lit» + Symbol : •Λ<@> tokId string_lit «g_sdt_lit» + Symbol : •Λ<@> string_lit «g_sdt_lit» + Symbol : •prodId «"@"» + Symbol : •tokId «"@"» + Symbol : •string_lit «"@"» + Symbol : •tokId g_ctxdep_lit «"@"» + Symbol : •Λ<@> tokId string_lit «"@"» + Symbol : •Λ<@> string_lit «"@"» + Symbol : •prodId «prodId» + Symbol : •tokId «prodId» + Symbol : •string_lit «prodId» + Symbol : •tokId g_ctxdep_lit «prodId» + Symbol : •Λ<@> tokId string_lit «prodId» + Symbol : •Λ<@> string_lit «prodId» + Symbol : •prodId «string_lit» + Symbol : •tokId «string_lit» + Symbol : •string_lit «string_lit» + Symbol : •tokId g_ctxdep_lit «string_lit» + Symbol : •Λ<@> tokId string_lit «string_lit» + Symbol : •Λ<@> string_lit «string_lit» + Symbol : •prodId «tokId» + Symbol : •tokId «tokId» + Symbol : •string_lit «tokId» + Symbol : •tokId g_ctxdep_lit «tokId» + Symbol : •Λ<@> tokId string_lit «tokId» + Symbol : •Λ<@> string_lit «tokId» + Symbol : •prodId «"|"» + Symbol : •tokId «"|"» + Symbol : •string_lit «"|"» + Symbol : •tokId g_ctxdep_lit «"|"» + Symbol : •Λ<@> tokId string_lit «"|"» + Symbol : •Λ<@> string_lit «"|"» +} +Transitions: + tokId -> 40 + prodId -> 41 + string_lit -> 42 + Λ<@> -> 43 + Π -> 88 + g_sdt_lit -> 89 + + +S37{ + SyntaxBody : Π• «";"» + SyntaxBody : Π •Π «";"» + SyntaxBody : Π •Π g_sdt_lit «";"» + SyntaxBody : Π •g_sdt_lit «";"» + SyntaxBody : Π• «"|"» + SyntaxBody : Π •Π «"|"» + SyntaxBody : Π •Π g_sdt_lit «"|"» + SyntaxBody : Π •g_sdt_lit «"|"» + Symbols : •Π «";"» + Symbols : •Π Π «";"» + Symbols : •Π «g_sdt_lit» + Symbols : •Π Π «g_sdt_lit» + Symbols : •Π «"|"» + Symbols : •Π Π «"|"» + Symbol : •prodId «";"» + Symbol : •tokId «";"» + Symbol : •string_lit «";"» + Symbol : •tokId g_ctxdep_lit «";"» + Symbol : •Λ<@> tokId string_lit «";"» + Symbol : •Λ<@> string_lit «";"» + Symbols : •Π «"@"» + Symbols : •Π «prodId» + Symbols : •Π «string_lit» + Symbols : •Π «tokId» + Symbols : •Π Π «"@"» + Symbols : •Π Π «prodId» + Symbols : •Π Π «string_lit» + Symbols : •Π Π «tokId» + Symbol : •prodId «g_sdt_lit» + Symbol : •tokId «g_sdt_lit» + Symbol : •string_lit «g_sdt_lit» + Symbol : •tokId g_ctxdep_lit «g_sdt_lit» + Symbol : •Λ<@> tokId string_lit «g_sdt_lit» + Symbol : •Λ<@> string_lit «g_sdt_lit» + Symbol : •prodId «"|"» + Symbol : •tokId «"|"» + Symbol : •string_lit «"|"» + Symbol : •tokId g_ctxdep_lit «"|"» + Symbol : •Λ<@> tokId string_lit «"|"» + Symbol : •Λ<@> string_lit «"|"» + Symbol : •prodId «"@"» + Symbol : •tokId «"@"» + Symbol : •string_lit «"@"» + Symbol : •tokId g_ctxdep_lit «"@"» + Symbol : •Λ<@> tokId string_lit «"@"» + Symbol : •Λ<@> string_lit «"@"» + Symbol : •prodId «prodId» + Symbol : •tokId «prodId» + Symbol : •string_lit «prodId» + Symbol : •tokId g_ctxdep_lit «prodId» + Symbol : •Λ<@> tokId string_lit «prodId» + Symbol : •Λ<@> string_lit «prodId» + Symbol : •prodId «string_lit» + Symbol : •tokId «string_lit» + Symbol : •string_lit «string_lit» + Symbol : •tokId g_ctxdep_lit «string_lit» + Symbol : •Λ<@> tokId string_lit «string_lit» + Symbol : •Λ<@> string_lit «string_lit» + Symbol : •prodId «tokId» + Symbol : •tokId «tokId» + Symbol : •string_lit «tokId» + Symbol : •tokId g_ctxdep_lit «tokId» + Symbol : •Λ<@> tokId string_lit «tokId» + Symbol : •Λ<@> string_lit «tokId» +} +Transitions: + Π -> 39 + tokId -> 40 + prodId -> 41 + string_lit -> 42 + Λ<@> -> 43 + Π -> 90 + g_sdt_lit -> 91 + + +S38{ + SyntaxBody : Π• «";"» + SyntaxBody : Π •g_sdt_lit «";"» + SyntaxBody : Π• «"|"» + SyntaxBody : Π •g_sdt_lit «"|"» +} +Transitions: + g_sdt_lit -> 92 + + +S39{ + Symbols : Π• «";"» + Symbols : Π• «g_sdt_lit» + Symbols : Π• «"@"» + Symbols : Π• «prodId» + Symbols : Π• «string_lit» + Symbols : Π• «tokId» + Symbols : Π• «"|"» +} +Transitions: + + +S40{ + Symbol : tokId• «";"» + Symbol : tokId •g_ctxdep_lit «";"» + Symbol : tokId• «g_sdt_lit» + Symbol : tokId •g_ctxdep_lit «g_sdt_lit» + Symbol : tokId• «"@"» + Symbol : tokId •g_ctxdep_lit «"@"» + Symbol : tokId• «prodId» + Symbol : tokId •g_ctxdep_lit «prodId» + Symbol : tokId• «string_lit» + Symbol : tokId •g_ctxdep_lit «string_lit» + Symbol : tokId• «tokId» + Symbol : tokId •g_ctxdep_lit «tokId» + Symbol : tokId• «"|"» + Symbol : tokId •g_ctxdep_lit «"|"» +} +Transitions: + g_ctxdep_lit -> 93 + + +S41{ + Symbol : prodId• «";"» + Symbol : prodId• «g_sdt_lit» + Symbol : prodId• «"@"» + Symbol : prodId• «prodId» + Symbol : prodId• «string_lit» + Symbol : prodId• «tokId» + Symbol : prodId• «"|"» +} +Transitions: + + +S42{ + Symbol : string_lit• «";"» + Symbol : string_lit• «g_sdt_lit» + Symbol : string_lit• «"@"» + Symbol : string_lit• «prodId» + Symbol : string_lit• «string_lit» + Symbol : string_lit• «tokId» + Symbol : string_lit• «"|"» +} +Transitions: + + +S43{ + Symbol : Λ<@> •tokId string_lit «";"» + Symbol : Λ<@> •string_lit «";"» + Symbol : Λ<@> •tokId string_lit «g_sdt_lit» + Symbol : Λ<@> •string_lit «g_sdt_lit» + Symbol : Λ<@> •tokId string_lit «"@"» + Symbol : Λ<@> •string_lit «"@"» + Symbol : Λ<@> •tokId string_lit «prodId» + Symbol : Λ<@> •string_lit «prodId» + Symbol : Λ<@> •tokId string_lit «string_lit» + Symbol : Λ<@> •string_lit «string_lit» + Symbol : Λ<@> •tokId string_lit «tokId» + Symbol : Λ<@> •string_lit «tokId» + Symbol : Λ<@> •tokId string_lit «"|"» + Symbol : Λ<@> •string_lit «"|"» +} +Transitions: + tokId -> 94 + string_lit -> 95 + + +S44{ + ErrorSymbol : Λ• «";"» + ErrorSymbol : Λ• «"@"» + ErrorSymbol : Λ• «prodId» + ErrorSymbol : Λ• «string_lit» + ErrorSymbol : Λ• «tokId» + ErrorSymbol : Λ• «g_sdt_lit» + ErrorSymbol : Λ• «"|"» +} +Transitions: + + +S45{ + ErrorSymbol : Λ<λ>• «";"» + ErrorSymbol : Λ<λ>• «"@"» + ErrorSymbol : Λ<λ>• «prodId» + ErrorSymbol : Λ<λ>• «string_lit» + ErrorSymbol : Λ<λ>• «tokId» + ErrorSymbol : Λ<λ>• «g_sdt_lit» + ErrorSymbol : Λ<λ>• «"|"» +} +Transitions: + + +S46{ + EpsilonSymbol : Λ• «";"» + EpsilonSymbol : Λ• «g_sdt_lit» + EpsilonSymbol : Λ• «"|"» +} +Transitions: + + +S47{ + EpsilonSymbol : Λ<ε>• «";"» + EpsilonSymbol : Λ<ε>• «g_sdt_lit» + EpsilonSymbol : Λ<ε>• «"|"» +} +Transitions: + + +S48{ + LexProduction : tokId Λ<:> Π Λ<;>• «g_sdt_lit» + LexProduction : tokId Λ<:> Π Λ<;>• «prodId» + LexProduction : tokId Λ<:> Π Λ<;>• «Ω» + LexProduction : tokId Λ<:> Π Λ<;>• «ignoredTokId» + LexProduction : tokId Λ<:> Π Λ<;>• «regDefId» + LexProduction : tokId Λ<:> Π Λ<;>• «tokId» +} +Transitions: + + +S49{ + LexPattern : Π Λ<|> •Π «";"» + LexPattern : Π Λ<|> •Π «"|"» + LexAlt : •Π «";"» + LexAlt : •Π Π «";"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «";"» + LexTerm : •char_lit «";"» + LexTerm : •char_lit Λ<-> char_lit «";"» + LexTerm : •Λ<~> char_lit «";"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «";"» + LexTerm : •regDefId «";"» + LexTerm : •Λ<[> Π Λ<]> «";"» + LexTerm : •Λ<{> Π Λ<}> «";"» + LexTerm : •Λ<(> Π Λ<)> «";"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» +} +Transitions: + Π -> 24 + regDefId -> 25 + Λ<.> -> 26 + char_lit -> 27 + Λ<~> -> 28 + Λ<(> -> 29 + Λ<[> -> 30 + Λ<{> -> 31 + Π -> 96 + + +S50{ + LexAlt : Π Π• «";"» + LexAlt : Π Π• «"("» + LexAlt : Π Π• «"."» + LexAlt : Π Π• «"["» + LexAlt : Π Π• «char_lit» + LexAlt : Π Π• «regDefId» + LexAlt : Π Π• «"{"» + LexAlt : Π Π• «"~"» + LexAlt : Π Π• «"|"» +} +Transitions: + + +S51{ + LexTerm : char_lit Λ<-> •char_lit «";"» + LexTerm : char_lit Λ<-> •char_lit «"("» + LexTerm : char_lit Λ<-> •char_lit «"."» + LexTerm : char_lit Λ<-> •char_lit «"["» + LexTerm : char_lit Λ<-> •char_lit «char_lit» + LexTerm : char_lit Λ<-> •char_lit «regDefId» + LexTerm : char_lit Λ<-> •char_lit «"{"» + LexTerm : char_lit Λ<-> •char_lit «"~"» + LexTerm : char_lit Λ<-> •char_lit «"|"» +} +Transitions: + char_lit -> 97 + + +S52{ + LexTerm : Λ<~> char_lit• «";"» + LexTerm : Λ<~> char_lit• «"("» + LexTerm : Λ<~> char_lit• «"."» + LexTerm : Λ<~> char_lit• «"["» + LexTerm : Λ<~> char_lit• «char_lit» + LexTerm : Λ<~> char_lit• «regDefId» + LexTerm : Λ<~> char_lit• «"{"» + LexTerm : Λ<~> char_lit• «"~"» + LexTerm : Λ<~> char_lit• «"|"» +} +Transitions: + + +S53{ + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «";"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 98 + + +S54{ + LexTerm : Λ<(> Π •Λ<)> «";"» + LexTerm : Λ<(> Π •Λ<)> «"("» + LexTerm : Λ<(> Π •Λ<)> «"."» + LexTerm : Λ<(> Π •Λ<)> «"["» + LexTerm : Λ<(> Π •Λ<)> «char_lit» + LexTerm : Λ<(> Π •Λ<)> «regDefId» + LexTerm : Λ<(> Π •Λ<)> «"{"» + LexTerm : Λ<(> Π •Λ<)> «"~"» + LexTerm : Λ<(> Π •Λ<)> «"|"» + LexPattern : Π •Λ<|> Π «")"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 99 + Λ<)> -> 100 + + +S55{ + LexPattern : Π• «")"» + LexAlt : Π •Π «")"» + LexPattern : Π• «"|"» + LexAlt : Π •Π «"("» + LexAlt : Π •Π «"."» + LexAlt : Π •Π «"["» + LexAlt : Π •Π «char_lit» + LexAlt : Π •Π «regDefId» + LexAlt : Π •Π «"{"» + LexAlt : Π •Π «"~"» + LexAlt : Π •Π «"|"» + LexTerm : •Λ<.> «")"» + LexTerm : •char_lit «")"» + LexTerm : •char_lit Λ<-> char_lit «")"» + LexTerm : •Λ<~> char_lit «")"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : •regDefId «")"» + LexTerm : •Λ<[> Π Λ<]> «")"» + LexTerm : •Λ<{> Π Λ<}> «")"» + LexTerm : •Λ<(> Π Λ<)> «")"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + regDefId -> 57 + Λ<.> -> 58 + char_lit -> 59 + Λ<~> -> 60 + Λ<(> -> 61 + Λ<[> -> 62 + Λ<{> -> 63 + Π -> 101 + + +S56{ + LexAlt : Π• «")"» + LexAlt : Π• «"("» + LexAlt : Π• «"."» + LexAlt : Π• «"["» + LexAlt : Π• «char_lit» + LexAlt : Π• «regDefId» + LexAlt : Π• «"{"» + LexAlt : Π• «"~"» + LexAlt : Π• «"|"» +} +Transitions: + + +S57{ + LexTerm : regDefId• «")"» + LexTerm : regDefId• «"("» + LexTerm : regDefId• «"."» + LexTerm : regDefId• «"["» + LexTerm : regDefId• «char_lit» + LexTerm : regDefId• «regDefId» + LexTerm : regDefId• «"{"» + LexTerm : regDefId• «"~"» + LexTerm : regDefId• «"|"» +} +Transitions: + + +S58{ + LexTerm : Λ<.>• «")"» + LexTerm : Λ<.>• «"("» + LexTerm : Λ<.>• «"."» + LexTerm : Λ<.>• «"["» + LexTerm : Λ<.>• «char_lit» + LexTerm : Λ<.>• «regDefId» + LexTerm : Λ<.>• «"{"» + LexTerm : Λ<.>• «"~"» + LexTerm : Λ<.>• «"|"» +} +Transitions: + + +S59{ + LexTerm : char_lit• «")"» + LexTerm : char_lit •Λ<-> char_lit «")"» + LexTerm : char_lit• «"("» + LexTerm : char_lit •Λ<-> char_lit «"("» + LexTerm : char_lit• «"."» + LexTerm : char_lit •Λ<-> char_lit «"."» + LexTerm : char_lit• «"["» + LexTerm : char_lit •Λ<-> char_lit «"["» + LexTerm : char_lit• «char_lit» + LexTerm : char_lit •Λ<-> char_lit «char_lit» + LexTerm : char_lit• «regDefId» + LexTerm : char_lit •Λ<-> char_lit «regDefId» + LexTerm : char_lit• «"{"» + LexTerm : char_lit •Λ<-> char_lit «"{"» + LexTerm : char_lit• «"~"» + LexTerm : char_lit •Λ<-> char_lit «"~"» + LexTerm : char_lit• «"|"» + LexTerm : char_lit •Λ<-> char_lit «"|"» +} +Transitions: + Λ<-> -> 102 + + +S60{ + LexTerm : Λ<~> •char_lit «")"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : Λ<~> •char_lit «"("» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> •char_lit «"."» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> •char_lit «"["» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> •char_lit «char_lit» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> •char_lit «regDefId» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> •char_lit «"{"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> •char_lit «"~"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> •char_lit «"|"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 103 + Λ<(> -> 104 + + +S61{ + LexTerm : Λ<(> •Π Λ<)> «")"» + LexTerm : Λ<(> •Π Λ<)> «"("» + LexTerm : Λ<(> •Π Λ<)> «"."» + LexTerm : Λ<(> •Π Λ<)> «"["» + LexTerm : Λ<(> •Π Λ<)> «char_lit» + LexTerm : Λ<(> •Π Λ<)> «regDefId» + LexTerm : Λ<(> •Π Λ<)> «"{"» + LexTerm : Λ<(> •Π Λ<)> «"~"» + LexTerm : Λ<(> •Π Λ<)> «"|"» + LexPattern : •Π «")"» + LexPattern : •Π Λ<|> Π «")"» + LexAlt : •Π «")"» + LexAlt : •Π Π «")"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «")"» + LexTerm : •char_lit «")"» + LexTerm : •char_lit Λ<-> char_lit «")"» + LexTerm : •Λ<~> char_lit «")"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : •regDefId «")"» + LexTerm : •Λ<[> Π Λ<]> «")"» + LexTerm : •Λ<{> Π Λ<}> «")"» + LexTerm : •Λ<(> Π Λ<)> «")"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 55 + Π -> 56 + regDefId -> 57 + Λ<.> -> 58 + char_lit -> 59 + Λ<~> -> 60 + Λ<(> -> 61 + Λ<[> -> 62 + Λ<{> -> 63 + Π -> 105 + + +S62{ + LexTerm : Λ<[> •Π Λ<]> «")"» + LexTerm : Λ<[> •Π Λ<]> «"("» + LexTerm : Λ<[> •Π Λ<]> «"."» + LexTerm : Λ<[> •Π Λ<]> «"["» + LexTerm : Λ<[> •Π Λ<]> «char_lit» + LexTerm : Λ<[> •Π Λ<]> «regDefId» + LexTerm : Λ<[> •Π Λ<]> «"{"» + LexTerm : Λ<[> •Π Λ<]> «"~"» + LexTerm : Λ<[> •Π Λ<]> «"|"» + LexPattern : •Π «"]"» + LexPattern : •Π Λ<|> Π «"]"» + LexAlt : •Π «"]"» + LexAlt : •Π Π «"]"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «"]"» + LexTerm : •char_lit «"]"» + LexTerm : •char_lit Λ<-> char_lit «"]"» + LexTerm : •Λ<~> char_lit «"]"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : •regDefId «"]"» + LexTerm : •Λ<[> Π Λ<]> «"]"» + LexTerm : •Λ<{> Π Λ<}> «"]"» + LexTerm : •Λ<(> Π Λ<)> «"]"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 65 + Π -> 66 + regDefId -> 67 + Λ<.> -> 68 + char_lit -> 69 + Λ<~> -> 70 + Λ<(> -> 71 + Λ<[> -> 72 + Λ<{> -> 73 + Π -> 106 + + +S63{ + LexTerm : Λ<{> •Π Λ<}> «")"» + LexTerm : Λ<{> •Π Λ<}> «"("» + LexTerm : Λ<{> •Π Λ<}> «"."» + LexTerm : Λ<{> •Π Λ<}> «"["» + LexTerm : Λ<{> •Π Λ<}> «char_lit» + LexTerm : Λ<{> •Π Λ<}> «regDefId» + LexTerm : Λ<{> •Π Λ<}> «"{"» + LexTerm : Λ<{> •Π Λ<}> «"~"» + LexTerm : Λ<{> •Π Λ<}> «"|"» + LexPattern : •Π «"}"» + LexPattern : •Π Λ<|> Π «"}"» + LexAlt : •Π «"}"» + LexAlt : •Π Π «"}"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «"}"» + LexTerm : •char_lit «"}"» + LexTerm : •char_lit Λ<-> char_lit «"}"» + LexTerm : •Λ<~> char_lit «"}"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : •regDefId «"}"» + LexTerm : •Λ<[> Π Λ<]> «"}"» + LexTerm : •Λ<{> Π Λ<}> «"}"» + LexTerm : •Λ<(> Π Λ<)> «"}"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 75 + Π -> 76 + regDefId -> 77 + Λ<.> -> 78 + char_lit -> 79 + Λ<~> -> 80 + Λ<(> -> 81 + Λ<[> -> 82 + Λ<{> -> 83 + Π -> 107 + + +S64{ + LexTerm : Λ<[> Π •Λ<]> «";"» + LexTerm : Λ<[> Π •Λ<]> «"("» + LexTerm : Λ<[> Π •Λ<]> «"."» + LexTerm : Λ<[> Π •Λ<]> «"["» + LexTerm : Λ<[> Π •Λ<]> «char_lit» + LexTerm : Λ<[> Π •Λ<]> «regDefId» + LexTerm : Λ<[> Π •Λ<]> «"{"» + LexTerm : Λ<[> Π •Λ<]> «"~"» + LexTerm : Λ<[> Π •Λ<]> «"|"» + LexPattern : Π •Λ<|> Π «"]"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 108 + Λ<]> -> 109 + + +S65{ + LexPattern : Π• «"]"» + LexAlt : Π •Π «"]"» + LexPattern : Π• «"|"» + LexAlt : Π •Π «"("» + LexAlt : Π •Π «"."» + LexAlt : Π •Π «"["» + LexAlt : Π •Π «char_lit» + LexAlt : Π •Π «regDefId» + LexAlt : Π •Π «"{"» + LexAlt : Π •Π «"~"» + LexAlt : Π •Π «"|"» + LexTerm : •Λ<.> «"]"» + LexTerm : •char_lit «"]"» + LexTerm : •char_lit Λ<-> char_lit «"]"» + LexTerm : •Λ<~> char_lit «"]"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : •regDefId «"]"» + LexTerm : •Λ<[> Π Λ<]> «"]"» + LexTerm : •Λ<{> Π Λ<}> «"]"» + LexTerm : •Λ<(> Π Λ<)> «"]"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + regDefId -> 67 + Λ<.> -> 68 + char_lit -> 69 + Λ<~> -> 70 + Λ<(> -> 71 + Λ<[> -> 72 + Λ<{> -> 73 + Π -> 110 + + +S66{ + LexAlt : Π• «"]"» + LexAlt : Π• «"("» + LexAlt : Π• «"."» + LexAlt : Π• «"["» + LexAlt : Π• «char_lit» + LexAlt : Π• «regDefId» + LexAlt : Π• «"{"» + LexAlt : Π• «"~"» + LexAlt : Π• «"|"» +} +Transitions: + + +S67{ + LexTerm : regDefId• «"]"» + LexTerm : regDefId• «"("» + LexTerm : regDefId• «"."» + LexTerm : regDefId• «"["» + LexTerm : regDefId• «char_lit» + LexTerm : regDefId• «regDefId» + LexTerm : regDefId• «"{"» + LexTerm : regDefId• «"~"» + LexTerm : regDefId• «"|"» +} +Transitions: + + +S68{ + LexTerm : Λ<.>• «"]"» + LexTerm : Λ<.>• «"("» + LexTerm : Λ<.>• «"."» + LexTerm : Λ<.>• «"["» + LexTerm : Λ<.>• «char_lit» + LexTerm : Λ<.>• «regDefId» + LexTerm : Λ<.>• «"{"» + LexTerm : Λ<.>• «"~"» + LexTerm : Λ<.>• «"|"» +} +Transitions: + + +S69{ + LexTerm : char_lit• «"]"» + LexTerm : char_lit •Λ<-> char_lit «"]"» + LexTerm : char_lit• «"("» + LexTerm : char_lit •Λ<-> char_lit «"("» + LexTerm : char_lit• «"."» + LexTerm : char_lit •Λ<-> char_lit «"."» + LexTerm : char_lit• «"["» + LexTerm : char_lit •Λ<-> char_lit «"["» + LexTerm : char_lit• «char_lit» + LexTerm : char_lit •Λ<-> char_lit «char_lit» + LexTerm : char_lit• «regDefId» + LexTerm : char_lit •Λ<-> char_lit «regDefId» + LexTerm : char_lit• «"{"» + LexTerm : char_lit •Λ<-> char_lit «"{"» + LexTerm : char_lit• «"~"» + LexTerm : char_lit •Λ<-> char_lit «"~"» + LexTerm : char_lit• «"|"» + LexTerm : char_lit •Λ<-> char_lit «"|"» +} +Transitions: + Λ<-> -> 111 + + +S70{ + LexTerm : Λ<~> •char_lit «"]"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : Λ<~> •char_lit «"("» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> •char_lit «"."» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> •char_lit «"["» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> •char_lit «char_lit» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> •char_lit «regDefId» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> •char_lit «"{"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> •char_lit «"~"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> •char_lit «"|"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 112 + Λ<(> -> 113 + + +S71{ + LexTerm : Λ<(> •Π Λ<)> «"]"» + LexTerm : Λ<(> •Π Λ<)> «"("» + LexTerm : Λ<(> •Π Λ<)> «"."» + LexTerm : Λ<(> •Π Λ<)> «"["» + LexTerm : Λ<(> •Π Λ<)> «char_lit» + LexTerm : Λ<(> •Π Λ<)> «regDefId» + LexTerm : Λ<(> •Π Λ<)> «"{"» + LexTerm : Λ<(> •Π Λ<)> «"~"» + LexTerm : Λ<(> •Π Λ<)> «"|"» + LexPattern : •Π «")"» + LexPattern : •Π Λ<|> Π «")"» + LexAlt : •Π «")"» + LexAlt : •Π Π «")"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «")"» + LexTerm : •char_lit «")"» + LexTerm : •char_lit Λ<-> char_lit «")"» + LexTerm : •Λ<~> char_lit «")"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : •regDefId «")"» + LexTerm : •Λ<[> Π Λ<]> «")"» + LexTerm : •Λ<{> Π Λ<}> «")"» + LexTerm : •Λ<(> Π Λ<)> «")"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 55 + Π -> 56 + regDefId -> 57 + Λ<.> -> 58 + char_lit -> 59 + Λ<~> -> 60 + Λ<(> -> 61 + Λ<[> -> 62 + Λ<{> -> 63 + Π -> 114 + + +S72{ + LexTerm : Λ<[> •Π Λ<]> «"]"» + LexTerm : Λ<[> •Π Λ<]> «"("» + LexTerm : Λ<[> •Π Λ<]> «"."» + LexTerm : Λ<[> •Π Λ<]> «"["» + LexTerm : Λ<[> •Π Λ<]> «char_lit» + LexTerm : Λ<[> •Π Λ<]> «regDefId» + LexTerm : Λ<[> •Π Λ<]> «"{"» + LexTerm : Λ<[> •Π Λ<]> «"~"» + LexTerm : Λ<[> •Π Λ<]> «"|"» + LexPattern : •Π «"]"» + LexPattern : •Π Λ<|> Π «"]"» + LexAlt : •Π «"]"» + LexAlt : •Π Π «"]"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «"]"» + LexTerm : •char_lit «"]"» + LexTerm : •char_lit Λ<-> char_lit «"]"» + LexTerm : •Λ<~> char_lit «"]"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : •regDefId «"]"» + LexTerm : •Λ<[> Π Λ<]> «"]"» + LexTerm : •Λ<{> Π Λ<}> «"]"» + LexTerm : •Λ<(> Π Λ<)> «"]"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 65 + Π -> 66 + regDefId -> 67 + Λ<.> -> 68 + char_lit -> 69 + Λ<~> -> 70 + Λ<(> -> 71 + Λ<[> -> 72 + Λ<{> -> 73 + Π -> 115 + + +S73{ + LexTerm : Λ<{> •Π Λ<}> «"]"» + LexTerm : Λ<{> •Π Λ<}> «"("» + LexTerm : Λ<{> •Π Λ<}> «"."» + LexTerm : Λ<{> •Π Λ<}> «"["» + LexTerm : Λ<{> •Π Λ<}> «char_lit» + LexTerm : Λ<{> •Π Λ<}> «regDefId» + LexTerm : Λ<{> •Π Λ<}> «"{"» + LexTerm : Λ<{> •Π Λ<}> «"~"» + LexTerm : Λ<{> •Π Λ<}> «"|"» + LexPattern : •Π «"}"» + LexPattern : •Π Λ<|> Π «"}"» + LexAlt : •Π «"}"» + LexAlt : •Π Π «"}"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «"}"» + LexTerm : •char_lit «"}"» + LexTerm : •char_lit Λ<-> char_lit «"}"» + LexTerm : •Λ<~> char_lit «"}"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : •regDefId «"}"» + LexTerm : •Λ<[> Π Λ<]> «"}"» + LexTerm : •Λ<{> Π Λ<}> «"}"» + LexTerm : •Λ<(> Π Λ<)> «"}"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 75 + Π -> 76 + regDefId -> 77 + Λ<.> -> 78 + char_lit -> 79 + Λ<~> -> 80 + Λ<(> -> 81 + Λ<[> -> 82 + Λ<{> -> 83 + Π -> 116 + + +S74{ + LexTerm : Λ<{> Π •Λ<}> «";"» + LexTerm : Λ<{> Π •Λ<}> «"("» + LexTerm : Λ<{> Π •Λ<}> «"."» + LexTerm : Λ<{> Π •Λ<}> «"["» + LexTerm : Λ<{> Π •Λ<}> «char_lit» + LexTerm : Λ<{> Π •Λ<}> «regDefId» + LexTerm : Λ<{> Π •Λ<}> «"{"» + LexTerm : Λ<{> Π •Λ<}> «"~"» + LexTerm : Λ<{> Π •Λ<}> «"|"» + LexPattern : Π •Λ<|> Π «"}"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 117 + Λ<}> -> 118 + + +S75{ + LexPattern : Π• «"}"» + LexAlt : Π •Π «"}"» + LexPattern : Π• «"|"» + LexAlt : Π •Π «"("» + LexAlt : Π •Π «"."» + LexAlt : Π •Π «"["» + LexAlt : Π •Π «char_lit» + LexAlt : Π •Π «regDefId» + LexAlt : Π •Π «"{"» + LexAlt : Π •Π «"~"» + LexAlt : Π •Π «"|"» + LexTerm : •Λ<.> «"}"» + LexTerm : •char_lit «"}"» + LexTerm : •char_lit Λ<-> char_lit «"}"» + LexTerm : •Λ<~> char_lit «"}"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : •regDefId «"}"» + LexTerm : •Λ<[> Π Λ<]> «"}"» + LexTerm : •Λ<{> Π Λ<}> «"}"» + LexTerm : •Λ<(> Π Λ<)> «"}"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + regDefId -> 77 + Λ<.> -> 78 + char_lit -> 79 + Λ<~> -> 80 + Λ<(> -> 81 + Λ<[> -> 82 + Λ<{> -> 83 + Π -> 119 + + +S76{ + LexAlt : Π• «"}"» + LexAlt : Π• «"("» + LexAlt : Π• «"."» + LexAlt : Π• «"["» + LexAlt : Π• «char_lit» + LexAlt : Π• «regDefId» + LexAlt : Π• «"{"» + LexAlt : Π• «"~"» + LexAlt : Π• «"|"» +} +Transitions: + + +S77{ + LexTerm : regDefId• «"}"» + LexTerm : regDefId• «"("» + LexTerm : regDefId• «"."» + LexTerm : regDefId• «"["» + LexTerm : regDefId• «char_lit» + LexTerm : regDefId• «regDefId» + LexTerm : regDefId• «"{"» + LexTerm : regDefId• «"~"» + LexTerm : regDefId• «"|"» +} +Transitions: + + +S78{ + LexTerm : Λ<.>• «"}"» + LexTerm : Λ<.>• «"("» + LexTerm : Λ<.>• «"."» + LexTerm : Λ<.>• «"["» + LexTerm : Λ<.>• «char_lit» + LexTerm : Λ<.>• «regDefId» + LexTerm : Λ<.>• «"{"» + LexTerm : Λ<.>• «"~"» + LexTerm : Λ<.>• «"|"» +} +Transitions: + + +S79{ + LexTerm : char_lit• «"}"» + LexTerm : char_lit •Λ<-> char_lit «"}"» + LexTerm : char_lit• «"("» + LexTerm : char_lit •Λ<-> char_lit «"("» + LexTerm : char_lit• «"."» + LexTerm : char_lit •Λ<-> char_lit «"."» + LexTerm : char_lit• «"["» + LexTerm : char_lit •Λ<-> char_lit «"["» + LexTerm : char_lit• «char_lit» + LexTerm : char_lit •Λ<-> char_lit «char_lit» + LexTerm : char_lit• «regDefId» + LexTerm : char_lit •Λ<-> char_lit «regDefId» + LexTerm : char_lit• «"{"» + LexTerm : char_lit •Λ<-> char_lit «"{"» + LexTerm : char_lit• «"~"» + LexTerm : char_lit •Λ<-> char_lit «"~"» + LexTerm : char_lit• «"|"» + LexTerm : char_lit •Λ<-> char_lit «"|"» +} +Transitions: + Λ<-> -> 120 + + +S80{ + LexTerm : Λ<~> •char_lit «"}"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : Λ<~> •char_lit «"("» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> •char_lit «"."» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> •char_lit «"["» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> •char_lit «char_lit» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> •char_lit «regDefId» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> •char_lit «"{"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> •char_lit «"~"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> •char_lit «"|"» + LexTerm : Λ<~> •Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 121 + Λ<(> -> 122 + + +S81{ + LexTerm : Λ<(> •Π Λ<)> «"}"» + LexTerm : Λ<(> •Π Λ<)> «"("» + LexTerm : Λ<(> •Π Λ<)> «"."» + LexTerm : Λ<(> •Π Λ<)> «"["» + LexTerm : Λ<(> •Π Λ<)> «char_lit» + LexTerm : Λ<(> •Π Λ<)> «regDefId» + LexTerm : Λ<(> •Π Λ<)> «"{"» + LexTerm : Λ<(> •Π Λ<)> «"~"» + LexTerm : Λ<(> •Π Λ<)> «"|"» + LexPattern : •Π «")"» + LexPattern : •Π Λ<|> Π «")"» + LexAlt : •Π «")"» + LexAlt : •Π Π «")"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «")"» + LexTerm : •char_lit «")"» + LexTerm : •char_lit Λ<-> char_lit «")"» + LexTerm : •Λ<~> char_lit «")"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : •regDefId «")"» + LexTerm : •Λ<[> Π Λ<]> «")"» + LexTerm : •Λ<{> Π Λ<}> «")"» + LexTerm : •Λ<(> Π Λ<)> «")"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 55 + Π -> 56 + regDefId -> 57 + Λ<.> -> 58 + char_lit -> 59 + Λ<~> -> 60 + Λ<(> -> 61 + Λ<[> -> 62 + Λ<{> -> 63 + Π -> 123 + + +S82{ + LexTerm : Λ<[> •Π Λ<]> «"}"» + LexTerm : Λ<[> •Π Λ<]> «"("» + LexTerm : Λ<[> •Π Λ<]> «"."» + LexTerm : Λ<[> •Π Λ<]> «"["» + LexTerm : Λ<[> •Π Λ<]> «char_lit» + LexTerm : Λ<[> •Π Λ<]> «regDefId» + LexTerm : Λ<[> •Π Λ<]> «"{"» + LexTerm : Λ<[> •Π Λ<]> «"~"» + LexTerm : Λ<[> •Π Λ<]> «"|"» + LexPattern : •Π «"]"» + LexPattern : •Π Λ<|> Π «"]"» + LexAlt : •Π «"]"» + LexAlt : •Π Π «"]"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «"]"» + LexTerm : •char_lit «"]"» + LexTerm : •char_lit Λ<-> char_lit «"]"» + LexTerm : •Λ<~> char_lit «"]"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : •regDefId «"]"» + LexTerm : •Λ<[> Π Λ<]> «"]"» + LexTerm : •Λ<{> Π Λ<}> «"]"» + LexTerm : •Λ<(> Π Λ<)> «"]"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 65 + Π -> 66 + regDefId -> 67 + Λ<.> -> 68 + char_lit -> 69 + Λ<~> -> 70 + Λ<(> -> 71 + Λ<[> -> 72 + Λ<{> -> 73 + Π -> 124 + + +S83{ + LexTerm : Λ<{> •Π Λ<}> «"}"» + LexTerm : Λ<{> •Π Λ<}> «"("» + LexTerm : Λ<{> •Π Λ<}> «"."» + LexTerm : Λ<{> •Π Λ<}> «"["» + LexTerm : Λ<{> •Π Λ<}> «char_lit» + LexTerm : Λ<{> •Π Λ<}> «regDefId» + LexTerm : Λ<{> •Π Λ<}> «"{"» + LexTerm : Λ<{> •Π Λ<}> «"~"» + LexTerm : Λ<{> •Π Λ<}> «"|"» + LexPattern : •Π «"}"» + LexPattern : •Π Λ<|> Π «"}"» + LexAlt : •Π «"}"» + LexAlt : •Π Π «"}"» + LexPattern : •Π «"|"» + LexPattern : •Π Λ<|> Π «"|"» + LexTerm : •Λ<.> «"}"» + LexTerm : •char_lit «"}"» + LexTerm : •char_lit Λ<-> char_lit «"}"» + LexTerm : •Λ<~> char_lit «"}"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : •regDefId «"}"» + LexTerm : •Λ<[> Π Λ<]> «"}"» + LexTerm : •Λ<{> Π Λ<}> «"}"» + LexTerm : •Λ<(> Π Λ<)> «"}"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» +} +Transitions: + Π -> 75 + Π -> 76 + regDefId -> 77 + Λ<.> -> 78 + char_lit -> 79 + Λ<~> -> 80 + Λ<(> -> 81 + Λ<[> -> 82 + Λ<{> -> 83 + Π -> 125 + + +S84{ + LexProduction : regDefId Λ<:> Π Λ<;>• «g_sdt_lit» + LexProduction : regDefId Λ<:> Π Λ<;>• «prodId» + LexProduction : regDefId Λ<:> Π Λ<;>• «Ω» + LexProduction : regDefId Λ<:> Π Λ<;>• «ignoredTokId» + LexProduction : regDefId Λ<:> Π Λ<;>• «regDefId» + LexProduction : regDefId Λ<:> Π Λ<;>• «tokId» +} +Transitions: + + +S85{ + LexProduction : ignoredTokId Λ<:> Π Λ<;>• «g_sdt_lit» + LexProduction : ignoredTokId Λ<:> Π Λ<;>• «prodId» + LexProduction : ignoredTokId Λ<:> Π Λ<;>• «Ω» + LexProduction : ignoredTokId Λ<:> Π Λ<;>• «ignoredTokId» + LexProduction : ignoredTokId Λ<:> Π Λ<;>• «regDefId» + LexProduction : ignoredTokId Λ<:> Π Λ<;>• «tokId» +} +Transitions: + + +S86{ + SyntaxProduction : prodId Λ<:> Π Λ<;>• «Ω» + SyntaxProduction : prodId Λ<:> Π Λ<;>• «prodId» +} +Transitions: + + +S87{ + Alternatives : Π Λ<|> •Π «";"» + Alternatives : Π Λ<|> •Π «"|"» + SyntaxBody : •Π «";"» + SyntaxBody : •Π g_sdt_lit «";"» + SyntaxBody : •Π «";"» + SyntaxBody : •Π Π «";"» + SyntaxBody : •Π Π g_sdt_lit «";"» + SyntaxBody : •Π g_sdt_lit «";"» + SyntaxBody : •Π «";"» + SyntaxBody : •Π g_sdt_lit «";"» + SyntaxBody : •Π «"|"» + SyntaxBody : •Π g_sdt_lit «"|"» + SyntaxBody : •Π «"|"» + SyntaxBody : •Π Π «"|"» + SyntaxBody : •Π Π g_sdt_lit «"|"» + SyntaxBody : •Π g_sdt_lit «"|"» + SyntaxBody : •Π «"|"» + SyntaxBody : •Π g_sdt_lit «"|"» + Symbols : •Π «";"» + Symbols : •Π Π «";"» + Symbols : •Π «g_sdt_lit» + Symbols : •Π Π «g_sdt_lit» + ErrorSymbol : •Λ «";"» + ErrorSymbol : •Λ<λ> «";"» + ErrorSymbol : •Λ «"@"» + ErrorSymbol : •Λ «prodId» + ErrorSymbol : •Λ «string_lit» + ErrorSymbol : •Λ «tokId» + ErrorSymbol : •Λ<λ> «"@"» + ErrorSymbol : •Λ<λ> «prodId» + ErrorSymbol : •Λ<λ> «string_lit» + ErrorSymbol : •Λ<λ> «tokId» + ErrorSymbol : •Λ «g_sdt_lit» + ErrorSymbol : •Λ<λ> «g_sdt_lit» + EpsilonSymbol : •Λ «";"» + EpsilonSymbol : •Λ<ε> «";"» + EpsilonSymbol : •Λ «g_sdt_lit» + EpsilonSymbol : •Λ<ε> «g_sdt_lit» + Symbols : •Π «"|"» + Symbols : •Π Π «"|"» + ErrorSymbol : •Λ «"|"» + ErrorSymbol : •Λ<λ> «"|"» + EpsilonSymbol : •Λ «"|"» + EpsilonSymbol : •Λ<ε> «"|"» + Symbol : •prodId «";"» + Symbol : •tokId «";"» + Symbol : •string_lit «";"» + Symbol : •tokId g_ctxdep_lit «";"» + Symbol : •Λ<@> tokId string_lit «";"» + Symbol : •Λ<@> string_lit «";"» + Symbols : •Π «"@"» + Symbols : •Π «prodId» + Symbols : •Π «string_lit» + Symbols : •Π «tokId» + Symbols : •Π Π «"@"» + Symbols : •Π Π «prodId» + Symbols : •Π Π «string_lit» + Symbols : •Π Π «tokId» + Symbol : •prodId «g_sdt_lit» + Symbol : •tokId «g_sdt_lit» + Symbol : •string_lit «g_sdt_lit» + Symbol : •tokId g_ctxdep_lit «g_sdt_lit» + Symbol : •Λ<@> tokId string_lit «g_sdt_lit» + Symbol : •Λ<@> string_lit «g_sdt_lit» + Symbol : •prodId «"|"» + Symbol : •tokId «"|"» + Symbol : •string_lit «"|"» + Symbol : •tokId g_ctxdep_lit «"|"» + Symbol : •Λ<@> tokId string_lit «"|"» + Symbol : •Λ<@> string_lit «"|"» + Symbol : •prodId «"@"» + Symbol : •tokId «"@"» + Symbol : •string_lit «"@"» + Symbol : •tokId g_ctxdep_lit «"@"» + Symbol : •Λ<@> tokId string_lit «"@"» + Symbol : •Λ<@> string_lit «"@"» + Symbol : •prodId «prodId» + Symbol : •tokId «prodId» + Symbol : •string_lit «prodId» + Symbol : •tokId g_ctxdep_lit «prodId» + Symbol : •Λ<@> tokId string_lit «prodId» + Symbol : •Λ<@> string_lit «prodId» + Symbol : •prodId «string_lit» + Symbol : •tokId «string_lit» + Symbol : •string_lit «string_lit» + Symbol : •tokId g_ctxdep_lit «string_lit» + Symbol : •Λ<@> tokId string_lit «string_lit» + Symbol : •Λ<@> string_lit «string_lit» + Symbol : •prodId «tokId» + Symbol : •tokId «tokId» + Symbol : •string_lit «tokId» + Symbol : •tokId g_ctxdep_lit «tokId» + Symbol : •Λ<@> tokId string_lit «tokId» + Symbol : •Λ<@> string_lit «tokId» +} +Transitions: + Π -> 36 + Π -> 37 + Π -> 38 + Π -> 39 + tokId -> 40 + prodId -> 41 + string_lit -> 42 + Λ<@> -> 43 + Λ -> 44 + Λ<λ> -> 45 + Λ -> 46 + Λ<ε> -> 47 + Π -> 126 + + +S88{ + Symbols : Π Π• «";"» + Symbols : Π Π• «g_sdt_lit» + Symbols : Π Π• «"@"» + Symbols : Π Π• «prodId» + Symbols : Π Π• «string_lit» + Symbols : Π Π• «tokId» + Symbols : Π Π• «"|"» +} +Transitions: + + +S89{ + SyntaxBody : Π g_sdt_lit• «";"» + SyntaxBody : Π g_sdt_lit• «"|"» +} +Transitions: + + +S90{ + SyntaxBody : Π Π• «";"» + SyntaxBody : Π Π •g_sdt_lit «";"» + SyntaxBody : Π Π• «"|"» + SyntaxBody : Π Π •g_sdt_lit «"|"» + Symbols : Π •Π «";"» + Symbols : Π •Π «g_sdt_lit» + Symbols : Π •Π «"|"» + Symbols : Π •Π «"@"» + Symbols : Π •Π «prodId» + Symbols : Π •Π «string_lit» + Symbols : Π •Π «tokId» + Symbol : •prodId «";"» + Symbol : •tokId «";"» + Symbol : •string_lit «";"» + Symbol : •tokId g_ctxdep_lit «";"» + Symbol : •Λ<@> tokId string_lit «";"» + Symbol : •Λ<@> string_lit «";"» + Symbol : •prodId «g_sdt_lit» + Symbol : •tokId «g_sdt_lit» + Symbol : •string_lit «g_sdt_lit» + Symbol : •tokId g_ctxdep_lit «g_sdt_lit» + Symbol : •Λ<@> tokId string_lit «g_sdt_lit» + Symbol : •Λ<@> string_lit «g_sdt_lit» + Symbol : •prodId «"|"» + Symbol : •tokId «"|"» + Symbol : •string_lit «"|"» + Symbol : •tokId g_ctxdep_lit «"|"» + Symbol : •Λ<@> tokId string_lit «"|"» + Symbol : •Λ<@> string_lit «"|"» + Symbol : •prodId «"@"» + Symbol : •tokId «"@"» + Symbol : •string_lit «"@"» + Symbol : •tokId g_ctxdep_lit «"@"» + Symbol : •Λ<@> tokId string_lit «"@"» + Symbol : •Λ<@> string_lit «"@"» + Symbol : •prodId «prodId» + Symbol : •tokId «prodId» + Symbol : •string_lit «prodId» + Symbol : •tokId g_ctxdep_lit «prodId» + Symbol : •Λ<@> tokId string_lit «prodId» + Symbol : •Λ<@> string_lit «prodId» + Symbol : •prodId «string_lit» + Symbol : •tokId «string_lit» + Symbol : •string_lit «string_lit» + Symbol : •tokId g_ctxdep_lit «string_lit» + Symbol : •Λ<@> tokId string_lit «string_lit» + Symbol : •Λ<@> string_lit «string_lit» + Symbol : •prodId «tokId» + Symbol : •tokId «tokId» + Symbol : •string_lit «tokId» + Symbol : •tokId g_ctxdep_lit «tokId» + Symbol : •Λ<@> tokId string_lit «tokId» + Symbol : •Λ<@> string_lit «tokId» +} +Transitions: + tokId -> 40 + prodId -> 41 + string_lit -> 42 + Λ<@> -> 43 + Π -> 88 + g_sdt_lit -> 127 + + +S91{ + SyntaxBody : Π g_sdt_lit• «";"» + SyntaxBody : Π g_sdt_lit• «"|"» +} +Transitions: + + +S92{ + SyntaxBody : Π g_sdt_lit• «";"» + SyntaxBody : Π g_sdt_lit• «"|"» +} +Transitions: + + +S93{ + Symbol : tokId g_ctxdep_lit• «";"» + Symbol : tokId g_ctxdep_lit• «g_sdt_lit» + Symbol : tokId g_ctxdep_lit• «"@"» + Symbol : tokId g_ctxdep_lit• «prodId» + Symbol : tokId g_ctxdep_lit• «string_lit» + Symbol : tokId g_ctxdep_lit• «tokId» + Symbol : tokId g_ctxdep_lit• «"|"» +} +Transitions: + + +S94{ + Symbol : Λ<@> tokId •string_lit «";"» + Symbol : Λ<@> tokId •string_lit «g_sdt_lit» + Symbol : Λ<@> tokId •string_lit «"@"» + Symbol : Λ<@> tokId •string_lit «prodId» + Symbol : Λ<@> tokId •string_lit «string_lit» + Symbol : Λ<@> tokId •string_lit «tokId» + Symbol : Λ<@> tokId •string_lit «"|"» +} +Transitions: + string_lit -> 128 + + +S95{ + Symbol : Λ<@> string_lit• «";"» + Symbol : Λ<@> string_lit• «g_sdt_lit» + Symbol : Λ<@> string_lit• «"@"» + Symbol : Λ<@> string_lit• «prodId» + Symbol : Λ<@> string_lit• «string_lit» + Symbol : Λ<@> string_lit• «tokId» + Symbol : Λ<@> string_lit• «"|"» +} +Transitions: + + +S96{ + LexPattern : Π Λ<|> Π• «";"» + LexPattern : Π Λ<|> Π• «"|"» + LexAlt : Π •Π «";"» + LexAlt : Π •Π «"|"» + LexAlt : Π •Π «"("» + LexAlt : Π •Π «"."» + LexAlt : Π •Π «"["» + LexAlt : Π •Π «char_lit» + LexAlt : Π •Π «regDefId» + LexAlt : Π •Π «"{"» + LexAlt : Π •Π «"~"» + LexTerm : •Λ<.> «";"» + LexTerm : •char_lit «";"» + LexTerm : •char_lit Λ<-> char_lit «";"» + LexTerm : •Λ<~> char_lit «";"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «";"» + LexTerm : •regDefId «";"» + LexTerm : •Λ<[> Π Λ<]> «";"» + LexTerm : •Λ<{> Π Λ<}> «";"» + LexTerm : •Λ<(> Π Λ<)> «";"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» +} +Transitions: + regDefId -> 25 + Λ<.> -> 26 + char_lit -> 27 + Λ<~> -> 28 + Λ<(> -> 29 + Λ<[> -> 30 + Λ<{> -> 31 + Π -> 50 + + +S97{ + LexTerm : char_lit Λ<-> char_lit• «";"» + LexTerm : char_lit Λ<-> char_lit• «"("» + LexTerm : char_lit Λ<-> char_lit• «"."» + LexTerm : char_lit Λ<-> char_lit• «"["» + LexTerm : char_lit Λ<-> char_lit• «char_lit» + LexTerm : char_lit Λ<-> char_lit• «regDefId» + LexTerm : char_lit Λ<-> char_lit• «"{"» + LexTerm : char_lit Λ<-> char_lit• «"~"» + LexTerm : char_lit Λ<-> char_lit• «"|"» +} +Transitions: + + +S98{ + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «";"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + Λ<-> -> 129 + + +S99{ + LexPattern : Π Λ<|> •Π «")"» + LexPattern : Π Λ<|> •Π «"|"» + LexAlt : •Π «")"» + LexAlt : •Π Π «")"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «")"» + LexTerm : •char_lit «")"» + LexTerm : •char_lit Λ<-> char_lit «")"» + LexTerm : •Λ<~> char_lit «")"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : •regDefId «")"» + LexTerm : •Λ<[> Π Λ<]> «")"» + LexTerm : •Λ<{> Π Λ<}> «")"» + LexTerm : •Λ<(> Π Λ<)> «")"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» +} +Transitions: + Π -> 56 + regDefId -> 57 + Λ<.> -> 58 + char_lit -> 59 + Λ<~> -> 60 + Λ<(> -> 61 + Λ<[> -> 62 + Λ<{> -> 63 + Π -> 130 + + +S100{ + LexTerm : Λ<(> Π Λ<)>• «";"» + LexTerm : Λ<(> Π Λ<)>• «"("» + LexTerm : Λ<(> Π Λ<)>• «"."» + LexTerm : Λ<(> Π Λ<)>• «"["» + LexTerm : Λ<(> Π Λ<)>• «char_lit» + LexTerm : Λ<(> Π Λ<)>• «regDefId» + LexTerm : Λ<(> Π Λ<)>• «"{"» + LexTerm : Λ<(> Π Λ<)>• «"~"» + LexTerm : Λ<(> Π Λ<)>• «"|"» +} +Transitions: + + +S101{ + LexAlt : Π Π• «")"» + LexAlt : Π Π• «"("» + LexAlt : Π Π• «"."» + LexAlt : Π Π• «"["» + LexAlt : Π Π• «char_lit» + LexAlt : Π Π• «regDefId» + LexAlt : Π Π• «"{"» + LexAlt : Π Π• «"~"» + LexAlt : Π Π• «"|"» +} +Transitions: + + +S102{ + LexTerm : char_lit Λ<-> •char_lit «")"» + LexTerm : char_lit Λ<-> •char_lit «"("» + LexTerm : char_lit Λ<-> •char_lit «"."» + LexTerm : char_lit Λ<-> •char_lit «"["» + LexTerm : char_lit Λ<-> •char_lit «char_lit» + LexTerm : char_lit Λ<-> •char_lit «regDefId» + LexTerm : char_lit Λ<-> •char_lit «"{"» + LexTerm : char_lit Λ<-> •char_lit «"~"» + LexTerm : char_lit Λ<-> •char_lit «"|"» +} +Transitions: + char_lit -> 131 + + +S103{ + LexTerm : Λ<~> char_lit• «")"» + LexTerm : Λ<~> char_lit• «"("» + LexTerm : Λ<~> char_lit• «"."» + LexTerm : Λ<~> char_lit• «"["» + LexTerm : Λ<~> char_lit• «char_lit» + LexTerm : Λ<~> char_lit• «regDefId» + LexTerm : Λ<~> char_lit• «"{"» + LexTerm : Λ<~> char_lit• «"~"» + LexTerm : Λ<~> char_lit• «"|"» +} +Transitions: + + +S104{ + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 132 + + +S105{ + LexTerm : Λ<(> Π •Λ<)> «")"» + LexTerm : Λ<(> Π •Λ<)> «"("» + LexTerm : Λ<(> Π •Λ<)> «"."» + LexTerm : Λ<(> Π •Λ<)> «"["» + LexTerm : Λ<(> Π •Λ<)> «char_lit» + LexTerm : Λ<(> Π •Λ<)> «regDefId» + LexTerm : Λ<(> Π •Λ<)> «"{"» + LexTerm : Λ<(> Π •Λ<)> «"~"» + LexTerm : Λ<(> Π •Λ<)> «"|"» + LexPattern : Π •Λ<|> Π «")"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 99 + Λ<)> -> 133 + + +S106{ + LexTerm : Λ<[> Π •Λ<]> «")"» + LexTerm : Λ<[> Π •Λ<]> «"("» + LexTerm : Λ<[> Π •Λ<]> «"."» + LexTerm : Λ<[> Π •Λ<]> «"["» + LexTerm : Λ<[> Π •Λ<]> «char_lit» + LexTerm : Λ<[> Π •Λ<]> «regDefId» + LexTerm : Λ<[> Π •Λ<]> «"{"» + LexTerm : Λ<[> Π •Λ<]> «"~"» + LexTerm : Λ<[> Π •Λ<]> «"|"» + LexPattern : Π •Λ<|> Π «"]"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 108 + Λ<]> -> 134 + + +S107{ + LexTerm : Λ<{> Π •Λ<}> «")"» + LexTerm : Λ<{> Π •Λ<}> «"("» + LexTerm : Λ<{> Π •Λ<}> «"."» + LexTerm : Λ<{> Π •Λ<}> «"["» + LexTerm : Λ<{> Π •Λ<}> «char_lit» + LexTerm : Λ<{> Π •Λ<}> «regDefId» + LexTerm : Λ<{> Π •Λ<}> «"{"» + LexTerm : Λ<{> Π •Λ<}> «"~"» + LexTerm : Λ<{> Π •Λ<}> «"|"» + LexPattern : Π •Λ<|> Π «"}"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 117 + Λ<}> -> 135 + + +S108{ + LexPattern : Π Λ<|> •Π «"]"» + LexPattern : Π Λ<|> •Π «"|"» + LexAlt : •Π «"]"» + LexAlt : •Π Π «"]"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"]"» + LexTerm : •char_lit «"]"» + LexTerm : •char_lit Λ<-> char_lit «"]"» + LexTerm : •Λ<~> char_lit «"]"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : •regDefId «"]"» + LexTerm : •Λ<[> Π Λ<]> «"]"» + LexTerm : •Λ<{> Π Λ<}> «"]"» + LexTerm : •Λ<(> Π Λ<)> «"]"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» +} +Transitions: + Π -> 66 + regDefId -> 67 + Λ<.> -> 68 + char_lit -> 69 + Λ<~> -> 70 + Λ<(> -> 71 + Λ<[> -> 72 + Λ<{> -> 73 + Π -> 136 + + +S109{ + LexTerm : Λ<[> Π Λ<]>• «";"» + LexTerm : Λ<[> Π Λ<]>• «"("» + LexTerm : Λ<[> Π Λ<]>• «"."» + LexTerm : Λ<[> Π Λ<]>• «"["» + LexTerm : Λ<[> Π Λ<]>• «char_lit» + LexTerm : Λ<[> Π Λ<]>• «regDefId» + LexTerm : Λ<[> Π Λ<]>• «"{"» + LexTerm : Λ<[> Π Λ<]>• «"~"» + LexTerm : Λ<[> Π Λ<]>• «"|"» +} +Transitions: + + +S110{ + LexAlt : Π Π• «"]"» + LexAlt : Π Π• «"("» + LexAlt : Π Π• «"."» + LexAlt : Π Π• «"["» + LexAlt : Π Π• «char_lit» + LexAlt : Π Π• «regDefId» + LexAlt : Π Π• «"{"» + LexAlt : Π Π• «"~"» + LexAlt : Π Π• «"|"» +} +Transitions: + + +S111{ + LexTerm : char_lit Λ<-> •char_lit «"]"» + LexTerm : char_lit Λ<-> •char_lit «"("» + LexTerm : char_lit Λ<-> •char_lit «"."» + LexTerm : char_lit Λ<-> •char_lit «"["» + LexTerm : char_lit Λ<-> •char_lit «char_lit» + LexTerm : char_lit Λ<-> •char_lit «regDefId» + LexTerm : char_lit Λ<-> •char_lit «"{"» + LexTerm : char_lit Λ<-> •char_lit «"~"» + LexTerm : char_lit Λ<-> •char_lit «"|"» +} +Transitions: + char_lit -> 137 + + +S112{ + LexTerm : Λ<~> char_lit• «"]"» + LexTerm : Λ<~> char_lit• «"("» + LexTerm : Λ<~> char_lit• «"."» + LexTerm : Λ<~> char_lit• «"["» + LexTerm : Λ<~> char_lit• «char_lit» + LexTerm : Λ<~> char_lit• «regDefId» + LexTerm : Λ<~> char_lit• «"{"» + LexTerm : Λ<~> char_lit• «"~"» + LexTerm : Λ<~> char_lit• «"|"» +} +Transitions: + + +S113{ + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 138 + + +S114{ + LexTerm : Λ<(> Π •Λ<)> «"]"» + LexTerm : Λ<(> Π •Λ<)> «"("» + LexTerm : Λ<(> Π •Λ<)> «"."» + LexTerm : Λ<(> Π •Λ<)> «"["» + LexTerm : Λ<(> Π •Λ<)> «char_lit» + LexTerm : Λ<(> Π •Λ<)> «regDefId» + LexTerm : Λ<(> Π •Λ<)> «"{"» + LexTerm : Λ<(> Π •Λ<)> «"~"» + LexTerm : Λ<(> Π •Λ<)> «"|"» + LexPattern : Π •Λ<|> Π «")"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 99 + Λ<)> -> 139 + + +S115{ + LexTerm : Λ<[> Π •Λ<]> «"]"» + LexTerm : Λ<[> Π •Λ<]> «"("» + LexTerm : Λ<[> Π •Λ<]> «"."» + LexTerm : Λ<[> Π •Λ<]> «"["» + LexTerm : Λ<[> Π •Λ<]> «char_lit» + LexTerm : Λ<[> Π •Λ<]> «regDefId» + LexTerm : Λ<[> Π •Λ<]> «"{"» + LexTerm : Λ<[> Π •Λ<]> «"~"» + LexTerm : Λ<[> Π •Λ<]> «"|"» + LexPattern : Π •Λ<|> Π «"]"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 108 + Λ<]> -> 140 + + +S116{ + LexTerm : Λ<{> Π •Λ<}> «"]"» + LexTerm : Λ<{> Π •Λ<}> «"("» + LexTerm : Λ<{> Π •Λ<}> «"."» + LexTerm : Λ<{> Π •Λ<}> «"["» + LexTerm : Λ<{> Π •Λ<}> «char_lit» + LexTerm : Λ<{> Π •Λ<}> «regDefId» + LexTerm : Λ<{> Π •Λ<}> «"{"» + LexTerm : Λ<{> Π •Λ<}> «"~"» + LexTerm : Λ<{> Π •Λ<}> «"|"» + LexPattern : Π •Λ<|> Π «"}"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 117 + Λ<}> -> 141 + + +S117{ + LexPattern : Π Λ<|> •Π «"}"» + LexPattern : Π Λ<|> •Π «"|"» + LexAlt : •Π «"}"» + LexAlt : •Π Π «"}"» + LexAlt : •Π «"|"» + LexAlt : •Π Π «"|"» + LexTerm : •Λ<.> «"}"» + LexTerm : •char_lit «"}"» + LexTerm : •char_lit Λ<-> char_lit «"}"» + LexTerm : •Λ<~> char_lit «"}"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : •regDefId «"}"» + LexTerm : •Λ<[> Π Λ<]> «"}"» + LexTerm : •Λ<{> Π Λ<}> «"}"» + LexTerm : •Λ<(> Π Λ<)> «"}"» + LexAlt : •Π «"("» + LexAlt : •Π «"."» + LexAlt : •Π «"["» + LexAlt : •Π «char_lit» + LexAlt : •Π «regDefId» + LexAlt : •Π «"{"» + LexAlt : •Π «"~"» + LexAlt : •Π Π «"("» + LexAlt : •Π Π «"."» + LexAlt : •Π Π «"["» + LexAlt : •Π Π «char_lit» + LexAlt : •Π Π «regDefId» + LexAlt : •Π Π «"{"» + LexAlt : •Π Π «"~"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» +} +Transitions: + Π -> 76 + regDefId -> 77 + Λ<.> -> 78 + char_lit -> 79 + Λ<~> -> 80 + Λ<(> -> 81 + Λ<[> -> 82 + Λ<{> -> 83 + Π -> 142 + + +S118{ + LexTerm : Λ<{> Π Λ<}>• «";"» + LexTerm : Λ<{> Π Λ<}>• «"("» + LexTerm : Λ<{> Π Λ<}>• «"."» + LexTerm : Λ<{> Π Λ<}>• «"["» + LexTerm : Λ<{> Π Λ<}>• «char_lit» + LexTerm : Λ<{> Π Λ<}>• «regDefId» + LexTerm : Λ<{> Π Λ<}>• «"{"» + LexTerm : Λ<{> Π Λ<}>• «"~"» + LexTerm : Λ<{> Π Λ<}>• «"|"» +} +Transitions: + + +S119{ + LexAlt : Π Π• «"}"» + LexAlt : Π Π• «"("» + LexAlt : Π Π• «"."» + LexAlt : Π Π• «"["» + LexAlt : Π Π• «char_lit» + LexAlt : Π Π• «regDefId» + LexAlt : Π Π• «"{"» + LexAlt : Π Π• «"~"» + LexAlt : Π Π• «"|"» +} +Transitions: + + +S120{ + LexTerm : char_lit Λ<-> •char_lit «"}"» + LexTerm : char_lit Λ<-> •char_lit «"("» + LexTerm : char_lit Λ<-> •char_lit «"."» + LexTerm : char_lit Λ<-> •char_lit «"["» + LexTerm : char_lit Λ<-> •char_lit «char_lit» + LexTerm : char_lit Λ<-> •char_lit «regDefId» + LexTerm : char_lit Λ<-> •char_lit «"{"» + LexTerm : char_lit Λ<-> •char_lit «"~"» + LexTerm : char_lit Λ<-> •char_lit «"|"» +} +Transitions: + char_lit -> 143 + + +S121{ + LexTerm : Λ<~> char_lit• «"}"» + LexTerm : Λ<~> char_lit• «"("» + LexTerm : Λ<~> char_lit• «"."» + LexTerm : Λ<~> char_lit• «"["» + LexTerm : Λ<~> char_lit• «char_lit» + LexTerm : Λ<~> char_lit• «regDefId» + LexTerm : Λ<~> char_lit• «"{"» + LexTerm : Λ<~> char_lit• «"~"» + LexTerm : Λ<~> char_lit• «"|"» +} +Transitions: + + +S122{ + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> •char_lit Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 144 + + +S123{ + LexTerm : Λ<(> Π •Λ<)> «"}"» + LexTerm : Λ<(> Π •Λ<)> «"("» + LexTerm : Λ<(> Π •Λ<)> «"."» + LexTerm : Λ<(> Π •Λ<)> «"["» + LexTerm : Λ<(> Π •Λ<)> «char_lit» + LexTerm : Λ<(> Π •Λ<)> «regDefId» + LexTerm : Λ<(> Π •Λ<)> «"{"» + LexTerm : Λ<(> Π •Λ<)> «"~"» + LexTerm : Λ<(> Π •Λ<)> «"|"» + LexPattern : Π •Λ<|> Π «")"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 99 + Λ<)> -> 145 + + +S124{ + LexTerm : Λ<[> Π •Λ<]> «"}"» + LexTerm : Λ<[> Π •Λ<]> «"("» + LexTerm : Λ<[> Π •Λ<]> «"."» + LexTerm : Λ<[> Π •Λ<]> «"["» + LexTerm : Λ<[> Π •Λ<]> «char_lit» + LexTerm : Λ<[> Π •Λ<]> «regDefId» + LexTerm : Λ<[> Π •Λ<]> «"{"» + LexTerm : Λ<[> Π •Λ<]> «"~"» + LexTerm : Λ<[> Π •Λ<]> «"|"» + LexPattern : Π •Λ<|> Π «"]"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 108 + Λ<]> -> 146 + + +S125{ + LexTerm : Λ<{> Π •Λ<}> «"}"» + LexTerm : Λ<{> Π •Λ<}> «"("» + LexTerm : Λ<{> Π •Λ<}> «"."» + LexTerm : Λ<{> Π •Λ<}> «"["» + LexTerm : Λ<{> Π •Λ<}> «char_lit» + LexTerm : Λ<{> Π •Λ<}> «regDefId» + LexTerm : Λ<{> Π •Λ<}> «"{"» + LexTerm : Λ<{> Π •Λ<}> «"~"» + LexTerm : Λ<{> Π •Λ<}> «"|"» + LexPattern : Π •Λ<|> Π «"}"» + LexPattern : Π •Λ<|> Π «"|"» +} +Transitions: + Λ<|> -> 117 + Λ<}> -> 147 + + +S126{ + Alternatives : Π Λ<|> Π• «";"» + Alternatives : Π Λ<|> Π• «"|"» +} +Transitions: + + +S127{ + SyntaxBody : Π Π g_sdt_lit• «";"» + SyntaxBody : Π Π g_sdt_lit• «"|"» +} +Transitions: + + +S128{ + Symbol : Λ<@> tokId string_lit• «";"» + Symbol : Λ<@> tokId string_lit• «g_sdt_lit» + Symbol : Λ<@> tokId string_lit• «"@"» + Symbol : Λ<@> tokId string_lit• «prodId» + Symbol : Λ<@> tokId string_lit• «string_lit» + Symbol : Λ<@> tokId string_lit• «tokId» + Symbol : Λ<@> tokId string_lit• «"|"» +} +Transitions: + + +S129{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «";"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 148 + + +S130{ + LexPattern : Π Λ<|> Π• «")"» + LexPattern : Π Λ<|> Π• «"|"» + LexAlt : Π •Π «")"» + LexAlt : Π •Π «"|"» + LexAlt : Π •Π «"("» + LexAlt : Π •Π «"."» + LexAlt : Π •Π «"["» + LexAlt : Π •Π «char_lit» + LexAlt : Π •Π «regDefId» + LexAlt : Π •Π «"{"» + LexAlt : Π •Π «"~"» + LexTerm : •Λ<.> «")"» + LexTerm : •char_lit «")"» + LexTerm : •char_lit Λ<-> char_lit «")"» + LexTerm : •Λ<~> char_lit «")"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «")"» + LexTerm : •regDefId «")"» + LexTerm : •Λ<[> Π Λ<]> «")"» + LexTerm : •Λ<{> Π Λ<}> «")"» + LexTerm : •Λ<(> Π Λ<)> «")"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» +} +Transitions: + regDefId -> 57 + Λ<.> -> 58 + char_lit -> 59 + Λ<~> -> 60 + Λ<(> -> 61 + Λ<[> -> 62 + Λ<{> -> 63 + Π -> 101 + + +S131{ + LexTerm : char_lit Λ<-> char_lit• «")"» + LexTerm : char_lit Λ<-> char_lit• «"("» + LexTerm : char_lit Λ<-> char_lit• «"."» + LexTerm : char_lit Λ<-> char_lit• «"["» + LexTerm : char_lit Λ<-> char_lit• «char_lit» + LexTerm : char_lit Λ<-> char_lit• «regDefId» + LexTerm : char_lit Λ<-> char_lit• «"{"» + LexTerm : char_lit Λ<-> char_lit• «"~"» + LexTerm : char_lit Λ<-> char_lit• «"|"» +} +Transitions: + + +S132{ + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «")"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + Λ<-> -> 149 + + +S133{ + LexTerm : Λ<(> Π Λ<)>• «")"» + LexTerm : Λ<(> Π Λ<)>• «"("» + LexTerm : Λ<(> Π Λ<)>• «"."» + LexTerm : Λ<(> Π Λ<)>• «"["» + LexTerm : Λ<(> Π Λ<)>• «char_lit» + LexTerm : Λ<(> Π Λ<)>• «regDefId» + LexTerm : Λ<(> Π Λ<)>• «"{"» + LexTerm : Λ<(> Π Λ<)>• «"~"» + LexTerm : Λ<(> Π Λ<)>• «"|"» +} +Transitions: + + +S134{ + LexTerm : Λ<[> Π Λ<]>• «")"» + LexTerm : Λ<[> Π Λ<]>• «"("» + LexTerm : Λ<[> Π Λ<]>• «"."» + LexTerm : Λ<[> Π Λ<]>• «"["» + LexTerm : Λ<[> Π Λ<]>• «char_lit» + LexTerm : Λ<[> Π Λ<]>• «regDefId» + LexTerm : Λ<[> Π Λ<]>• «"{"» + LexTerm : Λ<[> Π Λ<]>• «"~"» + LexTerm : Λ<[> Π Λ<]>• «"|"» +} +Transitions: + + +S135{ + LexTerm : Λ<{> Π Λ<}>• «")"» + LexTerm : Λ<{> Π Λ<}>• «"("» + LexTerm : Λ<{> Π Λ<}>• «"."» + LexTerm : Λ<{> Π Λ<}>• «"["» + LexTerm : Λ<{> Π Λ<}>• «char_lit» + LexTerm : Λ<{> Π Λ<}>• «regDefId» + LexTerm : Λ<{> Π Λ<}>• «"{"» + LexTerm : Λ<{> Π Λ<}>• «"~"» + LexTerm : Λ<{> Π Λ<}>• «"|"» +} +Transitions: + + +S136{ + LexPattern : Π Λ<|> Π• «"]"» + LexPattern : Π Λ<|> Π• «"|"» + LexAlt : Π •Π «"]"» + LexAlt : Π •Π «"|"» + LexAlt : Π •Π «"("» + LexAlt : Π •Π «"."» + LexAlt : Π •Π «"["» + LexAlt : Π •Π «char_lit» + LexAlt : Π •Π «regDefId» + LexAlt : Π •Π «"{"» + LexAlt : Π •Π «"~"» + LexTerm : •Λ<.> «"]"» + LexTerm : •char_lit «"]"» + LexTerm : •char_lit Λ<-> char_lit «"]"» + LexTerm : •Λ<~> char_lit «"]"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"]"» + LexTerm : •regDefId «"]"» + LexTerm : •Λ<[> Π Λ<]> «"]"» + LexTerm : •Λ<{> Π Λ<}> «"]"» + LexTerm : •Λ<(> Π Λ<)> «"]"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» +} +Transitions: + regDefId -> 67 + Λ<.> -> 68 + char_lit -> 69 + Λ<~> -> 70 + Λ<(> -> 71 + Λ<[> -> 72 + Λ<{> -> 73 + Π -> 110 + + +S137{ + LexTerm : char_lit Λ<-> char_lit• «"]"» + LexTerm : char_lit Λ<-> char_lit• «"("» + LexTerm : char_lit Λ<-> char_lit• «"."» + LexTerm : char_lit Λ<-> char_lit• «"["» + LexTerm : char_lit Λ<-> char_lit• «char_lit» + LexTerm : char_lit Λ<-> char_lit• «regDefId» + LexTerm : char_lit Λ<-> char_lit• «"{"» + LexTerm : char_lit Λ<-> char_lit• «"~"» + LexTerm : char_lit Λ<-> char_lit• «"|"» +} +Transitions: + + +S138{ + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"]"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + Λ<-> -> 150 + + +S139{ + LexTerm : Λ<(> Π Λ<)>• «"]"» + LexTerm : Λ<(> Π Λ<)>• «"("» + LexTerm : Λ<(> Π Λ<)>• «"."» + LexTerm : Λ<(> Π Λ<)>• «"["» + LexTerm : Λ<(> Π Λ<)>• «char_lit» + LexTerm : Λ<(> Π Λ<)>• «regDefId» + LexTerm : Λ<(> Π Λ<)>• «"{"» + LexTerm : Λ<(> Π Λ<)>• «"~"» + LexTerm : Λ<(> Π Λ<)>• «"|"» +} +Transitions: + + +S140{ + LexTerm : Λ<[> Π Λ<]>• «"]"» + LexTerm : Λ<[> Π Λ<]>• «"("» + LexTerm : Λ<[> Π Λ<]>• «"."» + LexTerm : Λ<[> Π Λ<]>• «"["» + LexTerm : Λ<[> Π Λ<]>• «char_lit» + LexTerm : Λ<[> Π Λ<]>• «regDefId» + LexTerm : Λ<[> Π Λ<]>• «"{"» + LexTerm : Λ<[> Π Λ<]>• «"~"» + LexTerm : Λ<[> Π Λ<]>• «"|"» +} +Transitions: + + +S141{ + LexTerm : Λ<{> Π Λ<}>• «"]"» + LexTerm : Λ<{> Π Λ<}>• «"("» + LexTerm : Λ<{> Π Λ<}>• «"."» + LexTerm : Λ<{> Π Λ<}>• «"["» + LexTerm : Λ<{> Π Λ<}>• «char_lit» + LexTerm : Λ<{> Π Λ<}>• «regDefId» + LexTerm : Λ<{> Π Λ<}>• «"{"» + LexTerm : Λ<{> Π Λ<}>• «"~"» + LexTerm : Λ<{> Π Λ<}>• «"|"» +} +Transitions: + + +S142{ + LexPattern : Π Λ<|> Π• «"}"» + LexPattern : Π Λ<|> Π• «"|"» + LexAlt : Π •Π «"}"» + LexAlt : Π •Π «"|"» + LexAlt : Π •Π «"("» + LexAlt : Π •Π «"."» + LexAlt : Π •Π «"["» + LexAlt : Π •Π «char_lit» + LexAlt : Π •Π «regDefId» + LexAlt : Π •Π «"{"» + LexAlt : Π •Π «"~"» + LexTerm : •Λ<.> «"}"» + LexTerm : •char_lit «"}"» + LexTerm : •char_lit Λ<-> char_lit «"}"» + LexTerm : •Λ<~> char_lit «"}"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"}"» + LexTerm : •regDefId «"}"» + LexTerm : •Λ<[> Π Λ<]> «"}"» + LexTerm : •Λ<{> Π Λ<}> «"}"» + LexTerm : •Λ<(> Π Λ<)> «"}"» + LexTerm : •Λ<.> «"|"» + LexTerm : •char_lit «"|"» + LexTerm : •char_lit Λ<-> char_lit «"|"» + LexTerm : •Λ<~> char_lit «"|"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"|"» + LexTerm : •regDefId «"|"» + LexTerm : •Λ<[> Π Λ<]> «"|"» + LexTerm : •Λ<{> Π Λ<}> «"|"» + LexTerm : •Λ<(> Π Λ<)> «"|"» + LexTerm : •Λ<.> «"("» + LexTerm : •char_lit «"("» + LexTerm : •char_lit Λ<-> char_lit «"("» + LexTerm : •Λ<~> char_lit «"("» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"("» + LexTerm : •regDefId «"("» + LexTerm : •Λ<[> Π Λ<]> «"("» + LexTerm : •Λ<{> Π Λ<}> «"("» + LexTerm : •Λ<(> Π Λ<)> «"("» + LexTerm : •Λ<.> «"."» + LexTerm : •char_lit «"."» + LexTerm : •char_lit Λ<-> char_lit «"."» + LexTerm : •Λ<~> char_lit «"."» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"."» + LexTerm : •regDefId «"."» + LexTerm : •Λ<[> Π Λ<]> «"."» + LexTerm : •Λ<{> Π Λ<}> «"."» + LexTerm : •Λ<(> Π Λ<)> «"."» + LexTerm : •Λ<.> «"["» + LexTerm : •char_lit «"["» + LexTerm : •char_lit Λ<-> char_lit «"["» + LexTerm : •Λ<~> char_lit «"["» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"["» + LexTerm : •regDefId «"["» + LexTerm : •Λ<[> Π Λ<]> «"["» + LexTerm : •Λ<{> Π Λ<}> «"["» + LexTerm : •Λ<(> Π Λ<)> «"["» + LexTerm : •Λ<.> «char_lit» + LexTerm : •char_lit «char_lit» + LexTerm : •char_lit Λ<-> char_lit «char_lit» + LexTerm : •Λ<~> char_lit «char_lit» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «char_lit» + LexTerm : •regDefId «char_lit» + LexTerm : •Λ<[> Π Λ<]> «char_lit» + LexTerm : •Λ<{> Π Λ<}> «char_lit» + LexTerm : •Λ<(> Π Λ<)> «char_lit» + LexTerm : •Λ<.> «regDefId» + LexTerm : •char_lit «regDefId» + LexTerm : •char_lit Λ<-> char_lit «regDefId» + LexTerm : •Λ<~> char_lit «regDefId» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «regDefId» + LexTerm : •regDefId «regDefId» + LexTerm : •Λ<[> Π Λ<]> «regDefId» + LexTerm : •Λ<{> Π Λ<}> «regDefId» + LexTerm : •Λ<(> Π Λ<)> «regDefId» + LexTerm : •Λ<.> «"{"» + LexTerm : •char_lit «"{"» + LexTerm : •char_lit Λ<-> char_lit «"{"» + LexTerm : •Λ<~> char_lit «"{"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"{"» + LexTerm : •regDefId «"{"» + LexTerm : •Λ<[> Π Λ<]> «"{"» + LexTerm : •Λ<{> Π Λ<}> «"{"» + LexTerm : •Λ<(> Π Λ<)> «"{"» + LexTerm : •Λ<.> «"~"» + LexTerm : •char_lit «"~"» + LexTerm : •char_lit Λ<-> char_lit «"~"» + LexTerm : •Λ<~> char_lit «"~"» + LexTerm : •Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)> «"~"» + LexTerm : •regDefId «"~"» + LexTerm : •Λ<[> Π Λ<]> «"~"» + LexTerm : •Λ<{> Π Λ<}> «"~"» + LexTerm : •Λ<(> Π Λ<)> «"~"» +} +Transitions: + regDefId -> 77 + Λ<.> -> 78 + char_lit -> 79 + Λ<~> -> 80 + Λ<(> -> 81 + Λ<[> -> 82 + Λ<{> -> 83 + Π -> 119 + + +S143{ + LexTerm : char_lit Λ<-> char_lit• «"}"» + LexTerm : char_lit Λ<-> char_lit• «"("» + LexTerm : char_lit Λ<-> char_lit• «"."» + LexTerm : char_lit Λ<-> char_lit• «"["» + LexTerm : char_lit Λ<-> char_lit• «char_lit» + LexTerm : char_lit Λ<-> char_lit• «regDefId» + LexTerm : char_lit Λ<-> char_lit• «"{"» + LexTerm : char_lit Λ<-> char_lit• «"~"» + LexTerm : char_lit Λ<-> char_lit• «"|"» +} +Transitions: + + +S144{ + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"}"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit •Λ<-> char_lit Λ<)> «"|"» +} +Transitions: + Λ<-> -> 151 + + +S145{ + LexTerm : Λ<(> Π Λ<)>• «"}"» + LexTerm : Λ<(> Π Λ<)>• «"("» + LexTerm : Λ<(> Π Λ<)>• «"."» + LexTerm : Λ<(> Π Λ<)>• «"["» + LexTerm : Λ<(> Π Λ<)>• «char_lit» + LexTerm : Λ<(> Π Λ<)>• «regDefId» + LexTerm : Λ<(> Π Λ<)>• «"{"» + LexTerm : Λ<(> Π Λ<)>• «"~"» + LexTerm : Λ<(> Π Λ<)>• «"|"» +} +Transitions: + + +S146{ + LexTerm : Λ<[> Π Λ<]>• «"}"» + LexTerm : Λ<[> Π Λ<]>• «"("» + LexTerm : Λ<[> Π Λ<]>• «"."» + LexTerm : Λ<[> Π Λ<]>• «"["» + LexTerm : Λ<[> Π Λ<]>• «char_lit» + LexTerm : Λ<[> Π Λ<]>• «regDefId» + LexTerm : Λ<[> Π Λ<]>• «"{"» + LexTerm : Λ<[> Π Λ<]>• «"~"» + LexTerm : Λ<[> Π Λ<]>• «"|"» +} +Transitions: + + +S147{ + LexTerm : Λ<{> Π Λ<}>• «"}"» + LexTerm : Λ<{> Π Λ<}>• «"("» + LexTerm : Λ<{> Π Λ<}>• «"."» + LexTerm : Λ<{> Π Λ<}>• «"["» + LexTerm : Λ<{> Π Λ<}>• «char_lit» + LexTerm : Λ<{> Π Λ<}>• «regDefId» + LexTerm : Λ<{> Π Λ<}>• «"{"» + LexTerm : Λ<{> Π Λ<}>• «"~"» + LexTerm : Λ<{> Π Λ<}>• «"|"» +} +Transitions: + + +S148{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «";"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"|"» +} +Transitions: + Λ<)> -> 152 + + +S149{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «")"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 153 + + +S150{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"]"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 154 + + +S151{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"}"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> •char_lit Λ<)> «"|"» +} +Transitions: + char_lit -> 155 + + +S152{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «";"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"|"» +} +Transitions: + + +S153{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «")"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"|"» +} +Transitions: + Λ<)> -> 156 + + +S154{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"]"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"|"» +} +Transitions: + Λ<)> -> 157 + + +S155{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"}"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit •Λ<)> «"|"» +} +Transitions: + Λ<)> -> 158 + + +S156{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «")"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"|"» +} +Transitions: + + +S157{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"]"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"|"» +} +Transitions: + + +S158{ + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"}"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"("» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"."» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"["» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «char_lit» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «regDefId» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"{"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"~"» + LexTerm : Λ<~> Λ<(> char_lit Λ<-> char_lit Λ<)>• «"|"» +} +Transitions: + + diff --git a/internal/frontend/reparsed/log/first.txt b/internal/frontend/reparsed/log/first.txt new file mode 100644 index 00000000..76304b0e --- /dev/null +++ b/internal/frontend/reparsed/log/first.txt @@ -0,0 +1,109 @@ +Π: { + g_sdt_lit + ignoredTokId + prodId + regDefId + tokId +} +Π: { + g_sdt_lit + ignoredTokId + prodId + regDefId + tokId +} +Π: { + ignoredTokId + regDefId + tokId +} +Π: { + g_sdt_lit + prodId +} +Π: { + ignoredTokId + regDefId + tokId +} +Π: { + ignoredTokId + regDefId + tokId +} +Π: { + char_lit + regDefId + Λ<(> + Λ<.> + Λ<[> + Λ<{> + Λ<~> +} +Π: { + char_lit + regDefId + Λ<(> + Λ<.> + Λ<[> + Λ<{> + Λ<~> +} +Π: { + char_lit + regDefId + Λ<(> + Λ<.> + Λ<[> + Λ<{> + Λ<~> +} +Π: { + g_sdt_lit +} +Π: { + prodId +} +Π: { + prodId +} +Π: { + prodId + string_lit + tokId + Λ<@> + Λ + Λ + Λ<ε> + Λ<λ> +} +Π: { + prodId + string_lit + tokId + Λ<@> + Λ + Λ + Λ<ε> + Λ<λ> +} +Π: { + prodId + string_lit + tokId + Λ<@> +} +Π: { + Λ + Λ<λ> +} +Π: { + Λ + Λ<ε> +} +Π: { + prodId + string_lit + tokId + Λ<@> +} diff --git a/internal/frontend/reparsed/log/lexer_sets.txt b/internal/frontend/reparsed/log/lexer_sets.txt new file mode 100644 index 00000000..d82f4c4e --- /dev/null +++ b/internal/frontend/reparsed/log/lexer_sets.txt @@ -0,0 +1,1897 @@ +Item sets: +S0{ + !comment : _lineComment | • _blockComment + !comment : • _lineComment | _blockComment + !whitespace : ' ' | '\t' | '\n' | • '\r' + !whitespace : ' ' | '\t' | • '\n' | '\r' + !whitespace : ' ' | • '\t' | '\n' | '\r' + !whitespace : • ' ' | '\t' | '\n' | '\r' + _blockComment : • '/' '*' {. | '*'} '*' '/' + _interpreted_string : • '"' {_unicode_value | _byte_value} '"' + _lineComment : • '/' '/' {.} '\n' + _lowcase : • 'a'-'z' + _raw_string : • '`' {.} '`' + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + char_lit : • ''' (_unicode_value | _byte_value) ''' + g_ctxdep_lit : • '@' '@' . {.} '@' '@' + g_sdt_lit : • '<' '<' . {.} '>' '>' + ignoredTokId : • '!' _tokId + prodId : • _upcase {_id_char} + regDefId : • '_' {_id_char} + string_lit : _raw_string | • _interpreted_string + string_lit : • _raw_string | _interpreted_string + tokId : • _tokId + Λ<(> : • '(' + Λ<)> : • ')' + Λ<-> : • '-' + Λ<.> : • '.' + Λ<:> : • ':' + Λ<;> : • ';' + Λ<@> : • '@' + Λ<[> : • '[' + Λ<]> : • ']' + Λ : • 'e' 'm' 'p' 't' 'y' + Λ : • 'e' 'r' 'r' 'o' 'r' + Λ<{> : • '{' + Λ<|> : • '|' + Λ<}> : • '}' + Λ<~> : • '~' + Λ<ε> : • \u03b5 + Λ<λ> : • \u03bb +} +Transitions: + ['\t','\t'] -> S1 + ['\n','\n'] -> S1 + ['\r','\r'] -> S1 + [' ',' '] -> S1 + ['!','!'] -> S2 + ['"','"'] -> S3 + [''','''] -> S4 + ['(','('] -> S5 + [')',')'] -> S6 + ['-','-'] -> S7 + ['.','.'] -> S8 + ['/','/'] -> S9 + [':',':'] -> S10 + [';',';'] -> S11 + ['<','<'] -> S12 + ['@','@'] -> S13 + ['A','Z'] -> S14 + ['[','['] -> S15 + [']',']'] -> S16 + ['_','_'] -> S17 + ['`','`'] -> S18 + ['a','d'] -> S19 + ['e','e'] -> S20 + ['f','z'] -> S19 + ['{','{'] -> S21 + ['|','|'] -> S22 + ['}','}'] -> S23 + ['~','~'] -> S24 + [\u03b5,\u03b5] -> S25 + [\u03bb,\u03bb] -> S26 +Action: nil +Symbols classes: {['\t','\t'], ['\n','\n'], ['\r','\r'], [' ',' '], ['!','!'], ['"','"'], [''','''], ['(','('], [')',')'], ['-','-'], ['.','.'], ['/','/'], [':',':'], [';',';'], ['<','<'], ['@','@'], ['A','Z'], ['[','['], [']',']'], ['_','_'], ['`','`'], ['a','d'], ['e','e'], ['f','z'], ['{','{'], ['|','|'], ['}','}'], ['~','~'], [\u03b5,\u03b5], [\u03bb,\u03bb]} + +S1{ + !whitespace : (' ' | '\t' | '\n' | '\r') • +} +Transitions: +Action: Ignore("!whitespace") +Symbols classes: {} + +S2{ + _lowcase : • 'a'-'z' + _tokId : • _lowcase {_id_char} + ignoredTokId : '!' • _tokId +} +Transitions: + ['a','z'] -> S27 +Action: nil +Symbols classes: {['a','z']} + +S3{ + _big_u_value : • '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : • '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : • '\' 'x' _hex_digit _hex_digit + _interpreted_string : '"' {_unicode_value | _byte_value} • '"' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : • '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : • '\' _octal_digit _octal_digit _octal_digit + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + _unicode_value : • . | _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['"','"'] -> S28 + ['\','\'] -> S29 +Action: nil +Symbols classes: {['"','"'], ['\','\']} + +S4{ + _big_u_value : • '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : • '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : • '\' 'x' _hex_digit _hex_digit + _little_u_value : • '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : • '\' _octal_digit _octal_digit _octal_digit + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + _unicode_value : • . | _little_u_value | _big_u_value | _escaped_char + char_lit : ''' (_unicode_value | • _byte_value) ''' + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['\','\'] -> S31 +Action: nil +Symbols classes: {['\','\']} + +S5{ + Λ<(> : '(' • +} +Transitions: +Action: Accept("Λ<(>") +Symbols classes: {} + +S6{ + Λ<)> : ')' • +} +Transitions: +Action: Accept("Λ<)>") +Symbols classes: {} + +S7{ + Λ<-> : '-' • +} +Transitions: +Action: Accept("Λ<->") +Symbols classes: {} + +S8{ + Λ<.> : '.' • +} +Transitions: +Action: Accept("Λ<.>") +Symbols classes: {} + +S9{ + !comment : _lineComment | • _blockComment + !comment : • _lineComment | _blockComment + _blockComment : '/' • '*' {. | '*'} '*' '/' + _lineComment : '/' • '/' {.} '\n' +} +Transitions: + ['*','*'] -> S33 + ['/','/'] -> S34 +Action: nil +Symbols classes: {['*','*'], ['/','/']} + +S10{ + Λ<:> : ':' • +} +Transitions: +Action: Accept("Λ<:>") +Symbols classes: {} + +S11{ + Λ<;> : ';' • +} +Transitions: +Action: Accept("Λ<;>") +Symbols classes: {} + +S12{ + g_sdt_lit : '<' • '<' . {.} '>' '>' +} +Transitions: + ['<','<'] -> S35 +Action: nil +Symbols classes: {['<','<']} + +S13{ + g_ctxdep_lit : '@' • '@' . {.} '@' '@' + Λ<@> : '@' • +} +Transitions: + ['@','@'] -> S36 +Action: Accept("Λ<@>") +Symbols classes: {['@','@']} + +S14{ + _digit : • '0'-'9' + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _upcase : 'A'-'Z' • + _upcase : • 'A'-'Z' + prodId : _upcase {_id_char} • + prodId : _upcase {• _id_char} +} +Transitions: + ['0','9'] -> S37 + ['A','Z'] -> S38 + ['_','_'] -> S39 + ['a','z'] -> S40 +Action: Accept("prodId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S15{ + Λ<[> : '[' • +} +Transitions: +Action: Accept("Λ<[>") +Symbols classes: {} + +S16{ + Λ<]> : ']' • +} +Transitions: +Action: Accept("Λ<]>") +Symbols classes: {} + +S17{ + _digit : • '0'-'9' + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _upcase : • 'A'-'Z' + regDefId : '_' {_id_char} • + regDefId : '_' {• _id_char} +} +Transitions: + ['0','9'] -> S41 + ['A','Z'] -> S42 + ['_','_'] -> S43 + ['a','z'] -> S44 +Action: Accept("regDefId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S18{ + _raw_string : '`' {.} • '`' + _raw_string : '`' {• .} '`' + string_lit : • _raw_string | _interpreted_string +} +Transitions: + ['`','`'] -> S45 +Action: nil +Symbols classes: {['`','`']} + +S19{ + _digit : • '0'-'9' + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S20{ + _digit : • '0'-'9' + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' • 'm' 'p' 't' 'y' + Λ : 'e' • 'r' 'r' 'o' 'r' +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','l'] -> S49 + ['m','m'] -> S50 + ['n','q'] -> S49 + ['r','r'] -> S51 + ['s','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','l'], ['m','m'], ['n','q'], ['r','r'], ['s','z']} + +S21{ + Λ<{> : '{' • +} +Transitions: +Action: Accept("Λ<{>") +Symbols classes: {} + +S22{ + Λ<|> : '|' • +} +Transitions: +Action: Accept("Λ<|>") +Symbols classes: {} + +S23{ + Λ<}> : '}' • +} +Transitions: +Action: Accept("Λ<}>") +Symbols classes: {} + +S24{ + Λ<~> : '~' • +} +Transitions: +Action: Accept("Λ<~>") +Symbols classes: {} + +S25{ + Λ<ε> : \u03b5 • +} +Transitions: +Action: Accept("Λ<ε>") +Symbols classes: {} + +S26{ + Λ<λ> : \u03bb • +} +Transitions: +Action: Accept("Λ<λ>") +Symbols classes: {} + +S27{ + _digit : • '0'-'9' + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + ignoredTokId : '!' _tokId • + ignoredTokId : '!' • _tokId +} +Transitions: + ['0','9'] -> S52 + ['A','Z'] -> S53 + ['_','_'] -> S54 + ['a','z'] -> S55 +Action: Accept("ignoredTokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S28{ + _interpreted_string : '"' {_unicode_value | _byte_value} '"' • + string_lit : (_raw_string | _interpreted_string) • +} +Transitions: +Action: Accept("string_lit") +Symbols classes: {} + +S29{ + _big_u_value : '\' • 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | • '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | • ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | • '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | • 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | • 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | • 'r' | 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | • 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | • 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | • 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' (• 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : '\' • 'x' _hex_digit _hex_digit + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : '\' • 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : '\' • _octal_digit _octal_digit _octal_digit + _octal_digit : • '0'-'7' + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['"','"'] -> S56 + [''','''] -> S56 + ['0','7'] -> S57 + ['U','U'] -> S58 + ['\','\'] -> S56 + ['a','a'] -> S56 + ['b','b'] -> S56 + ['f','f'] -> S56 + ['n','n'] -> S56 + ['r','r'] -> S56 + ['t','t'] -> S56 + ['u','u'] -> S59 + ['v','v'] -> S56 + ['x','x'] -> S60 +Action: nil +Symbols classes: {['"','"'], [''','''], ['0','7'], ['U','U'], ['\','\'], ['a','a'], ['b','b'], ['f','f'], ['n','n'], ['r','r'], ['t','t'], ['u','u'], ['v','v'], ['x','x']} + +S30{ + _big_u_value : • '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : • '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : • '\' 'x' _hex_digit _hex_digit + _interpreted_string : '"' {_unicode_value | _byte_value} • '"' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : • '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : • '\' _octal_digit _octal_digit _octal_digit + _unicode_value : (. | _little_u_value | _big_u_value | _escaped_char) • + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + _unicode_value : • . | _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['"','"'] -> S28 + ['\','\'] -> S29 +Action: nil +Symbols classes: {['"','"'], ['\','\']} + +S31{ + _big_u_value : '\' • 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | • '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | • ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | • '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | • 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | • 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | • 'r' | 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | 'f' | • 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | 'b' | • 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' ('a' | • 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _escaped_char : '\' (• 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : '\' • 'x' _hex_digit _hex_digit + _little_u_value : '\' • 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : '\' • _octal_digit _octal_digit _octal_digit + _octal_digit : • '0'-'7' + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + char_lit : ''' (_unicode_value | • _byte_value) ''' + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['"','"'] -> S61 + [''','''] -> S61 + ['0','7'] -> S62 + ['U','U'] -> S63 + ['\','\'] -> S61 + ['a','a'] -> S61 + ['b','b'] -> S61 + ['f','f'] -> S61 + ['n','n'] -> S61 + ['r','r'] -> S61 + ['t','t'] -> S61 + ['u','u'] -> S64 + ['v','v'] -> S61 + ['x','x'] -> S65 +Action: nil +Symbols classes: {['"','"'], [''','''], ['0','7'], ['U','U'], ['\','\'], ['a','a'], ['b','b'], ['f','f'], ['n','n'], ['r','r'], ['t','t'], ['u','u'], ['v','v'], ['x','x']} + +S32{ + _unicode_value : (. | _little_u_value | _big_u_value | _escaped_char) • + char_lit : ''' (_unicode_value | _byte_value) • ''' +} +Transitions: + [''','''] -> S66 +Action: nil +Symbols classes: {[''',''']} + +S33{ + !comment : _lineComment | • _blockComment + _blockComment : '/' '*' {. | '*'} • '*' '/' + _blockComment : '/' '*' {. | • '*'} '*' '/' + _blockComment : '/' '*' {• . | '*'} '*' '/' +} +Transitions: + ['*','*'] -> S67 +Action: nil +Symbols classes: {['*','*']} + +S34{ + !comment : • _lineComment | _blockComment + _lineComment : '/' '/' {.} • '\n' + _lineComment : '/' '/' {• .} '\n' +} +Transitions: + ['\n','\n'] -> S68 +Action: nil +Symbols classes: {['\n','\n']} + +S35{ + g_sdt_lit : '<' '<' • . {.} '>' '>' +} +Transitions: +Action: nil +Symbols classes: {} + +S36{ + g_ctxdep_lit : '@' '@' • . {.} '@' '@' +} +Transitions: +Action: nil +Symbols classes: {} + +S37{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _upcase : • 'A'-'Z' + prodId : _upcase {_id_char} • + prodId : _upcase {• _id_char} +} +Transitions: + ['0','9'] -> S37 + ['A','Z'] -> S38 + ['_','_'] -> S39 + ['a','z'] -> S40 +Action: Accept("prodId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S38{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _upcase : 'A'-'Z' • + _upcase : • 'A'-'Z' + prodId : _upcase {_id_char} • + prodId : _upcase {• _id_char} +} +Transitions: + ['0','9'] -> S37 + ['A','Z'] -> S38 + ['_','_'] -> S39 + ['a','z'] -> S40 +Action: Accept("prodId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S39{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _upcase : • 'A'-'Z' + prodId : _upcase {_id_char} • + prodId : _upcase {• _id_char} +} +Transitions: + ['0','9'] -> S37 + ['A','Z'] -> S38 + ['_','_'] -> S39 + ['a','z'] -> S40 +Action: Accept("prodId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S40{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _upcase : • 'A'-'Z' + prodId : _upcase {_id_char} • + prodId : _upcase {• _id_char} +} +Transitions: + ['0','9'] -> S37 + ['A','Z'] -> S38 + ['_','_'] -> S39 + ['a','z'] -> S40 +Action: Accept("prodId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S41{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _upcase : • 'A'-'Z' + regDefId : '_' {_id_char} • + regDefId : '_' {• _id_char} +} +Transitions: + ['0','9'] -> S41 + ['A','Z'] -> S42 + ['_','_'] -> S43 + ['a','z'] -> S44 +Action: Accept("regDefId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S42{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _upcase : 'A'-'Z' • + _upcase : • 'A'-'Z' + regDefId : '_' {_id_char} • + regDefId : '_' {• _id_char} +} +Transitions: + ['0','9'] -> S41 + ['A','Z'] -> S42 + ['_','_'] -> S43 + ['a','z'] -> S44 +Action: Accept("regDefId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S43{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _upcase : • 'A'-'Z' + regDefId : '_' {_id_char} • + regDefId : '_' {• _id_char} +} +Transitions: + ['0','9'] -> S41 + ['A','Z'] -> S42 + ['_','_'] -> S43 + ['a','z'] -> S44 +Action: Accept("regDefId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S44{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _upcase : • 'A'-'Z' + regDefId : '_' {_id_char} • + regDefId : '_' {• _id_char} +} +Transitions: + ['0','9'] -> S41 + ['A','Z'] -> S42 + ['_','_'] -> S43 + ['a','z'] -> S44 +Action: Accept("regDefId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S45{ + _raw_string : '`' {.} '`' • + string_lit : (_raw_string | _interpreted_string) • +} +Transitions: +Action: Accept("string_lit") +Symbols classes: {} + +S46{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S47{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : 'A'-'Z' • + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S48{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S49{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S50{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' 'm' • 'p' 't' 'y' +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','o'] -> S49 + ['p','p'] -> S71 + ['q','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','o'], ['p','p'], ['q','z']} + +S51{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' 'r' • 'r' 'o' 'r' +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','q'] -> S49 + ['r','r'] -> S72 + ['s','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','q'], ['r','r'], ['s','z']} + +S52{ + _digit : '0'-'9' • + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + ignoredTokId : '!' _tokId • + ignoredTokId : '!' • _tokId +} +Transitions: + ['0','9'] -> S52 + ['A','Z'] -> S53 + ['_','_'] -> S54 + ['a','z'] -> S55 +Action: Accept("ignoredTokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S53{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : 'A'-'Z' • + _upcase : • 'A'-'Z' + ignoredTokId : '!' _tokId • + ignoredTokId : '!' • _tokId +} +Transitions: + ['0','9'] -> S52 + ['A','Z'] -> S53 + ['_','_'] -> S54 + ['a','z'] -> S55 +Action: Accept("ignoredTokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S54{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + ignoredTokId : '!' _tokId • + ignoredTokId : '!' • _tokId +} +Transitions: + ['0','9'] -> S52 + ['A','Z'] -> S53 + ['_','_'] -> S54 + ['a','z'] -> S55 +Action: Accept("ignoredTokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S55{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + ignoredTokId : '!' _tokId • + ignoredTokId : '!' • _tokId +} +Transitions: + ['0','9'] -> S52 + ['A','Z'] -> S53 + ['_','_'] -> S54 + ['a','z'] -> S55 +Action: Accept("ignoredTokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S56{ + _big_u_value : • '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') • + _escaped_char : • '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : • '\' 'x' _hex_digit _hex_digit + _interpreted_string : '"' {_unicode_value | _byte_value} • '"' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : • '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : • '\' _octal_digit _octal_digit _octal_digit + _unicode_value : (. | _little_u_value | _big_u_value | _escaped_char) • + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + _unicode_value : • . | _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['"','"'] -> S28 + ['\','\'] -> S29 +Action: nil +Symbols classes: {['"','"'], ['\','\']} + +S57{ + _byte_value : • _octal_byte_value | _hex_byte_value + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _octal_byte_value : '\' _octal_digit • _octal_digit _octal_digit + _octal_digit : '0'-'7' • + _octal_digit : • '0'-'7' + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','7'] -> S73 +Action: nil +Symbols classes: {['0','7']} + +S58{ + _big_u_value : '\' 'U' • _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S74 + ['A','F'] -> S74 + ['a','f'] -> S74 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S59{ + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : '\' 'u' • _hex_digit _hex_digit _hex_digit _hex_digit + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S75 + ['A','F'] -> S75 + ['a','f'] -> S75 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S60{ + _byte_value : _octal_byte_value | • _hex_byte_value + _hex_byte_value : '\' 'x' • _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S76 + ['A','F'] -> S76 + ['a','f'] -> S76 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S61{ + _escaped_char : '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') • + _unicode_value : (. | _little_u_value | _big_u_value | _escaped_char) • + char_lit : ''' (_unicode_value | _byte_value) • ''' +} +Transitions: + [''','''] -> S66 +Action: nil +Symbols classes: {[''',''']} + +S62{ + _byte_value : • _octal_byte_value | _hex_byte_value + _octal_byte_value : '\' _octal_digit • _octal_digit _octal_digit + _octal_digit : '0'-'7' • + _octal_digit : • '0'-'7' + char_lit : ''' (_unicode_value | • _byte_value) ''' +} +Transitions: + ['0','7'] -> S77 +Action: nil +Symbols classes: {['0','7']} + +S63{ + _big_u_value : '\' 'U' • _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S78 + ['A','F'] -> S78 + ['a','f'] -> S78 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S64{ + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _little_u_value : '\' 'u' • _hex_digit _hex_digit _hex_digit _hex_digit + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S79 + ['A','F'] -> S79 + ['a','f'] -> S79 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S65{ + _byte_value : _octal_byte_value | • _hex_byte_value + _hex_byte_value : '\' 'x' • _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + char_lit : ''' (_unicode_value | • _byte_value) ''' +} +Transitions: + ['0','9'] -> S80 + ['A','F'] -> S80 + ['a','f'] -> S80 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S66{ + char_lit : ''' (_unicode_value | _byte_value) ''' • +} +Transitions: +Action: Accept("char_lit") +Symbols classes: {} + +S67{ + !comment : _lineComment | • _blockComment + _blockComment : '/' '*' {. | '*'} '*' • '/' + _blockComment : '/' '*' {. | '*'} • '*' '/' + _blockComment : '/' '*' {. | • '*'} '*' '/' + _blockComment : '/' '*' {• . | '*'} '*' '/' +} +Transitions: + ['*','*'] -> S67 + ['/','/'] -> S81 +Action: nil +Symbols classes: {['*','*'], ['/','/']} + +S68{ + !comment : (_lineComment | _blockComment) • + _lineComment : '/' '/' {.} '\n' • +} +Transitions: +Action: Ignore("!comment") +Symbols classes: {} + +S69{ + g_sdt_lit : '<' '<' . {.} • '>' '>' + g_sdt_lit : '<' '<' . {• .} '>' '>' +} +Transitions: + ['>','>'] -> S82 +Action: nil +Symbols classes: {['>','>']} + +S70{ + g_ctxdep_lit : '@' '@' . {.} • '@' '@' + g_ctxdep_lit : '@' '@' . {• .} '@' '@' +} +Transitions: + ['@','@'] -> S83 +Action: nil +Symbols classes: {['@','@']} + +S71{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' 'm' 'p' • 't' 'y' +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','s'] -> S49 + ['t','t'] -> S84 + ['u','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','s'], ['t','t'], ['u','z']} + +S72{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' 'r' 'r' • 'o' 'r' +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','n'] -> S49 + ['o','o'] -> S85 + ['p','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','n'], ['o','o'], ['p','z']} + +S73{ + _byte_value : • _octal_byte_value | _hex_byte_value + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _octal_byte_value : '\' _octal_digit _octal_digit • _octal_digit + _octal_digit : '0'-'7' • + _octal_digit : • '0'-'7' + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','7'] -> S86 +Action: nil +Symbols classes: {['0','7']} + +S74{ + _big_u_value : '\' 'U' _hex_digit • _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S87 + ['A','F'] -> S87 + ['a','f'] -> S87 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S75{ + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : '\' 'u' _hex_digit • _hex_digit _hex_digit _hex_digit + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S88 + ['A','F'] -> S88 + ['a','f'] -> S88 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S76{ + _byte_value : _octal_byte_value | • _hex_byte_value + _hex_byte_value : '\' 'x' _hex_digit • _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S89 + ['A','F'] -> S89 + ['a','f'] -> S89 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S77{ + _byte_value : • _octal_byte_value | _hex_byte_value + _octal_byte_value : '\' _octal_digit _octal_digit • _octal_digit + _octal_digit : '0'-'7' • + _octal_digit : • '0'-'7' + char_lit : ''' (_unicode_value | • _byte_value) ''' +} +Transitions: + ['0','7'] -> S90 +Action: nil +Symbols classes: {['0','7']} + +S78{ + _big_u_value : '\' 'U' _hex_digit • _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S91 + ['A','F'] -> S91 + ['a','f'] -> S91 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S79{ + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _little_u_value : '\' 'u' _hex_digit • _hex_digit _hex_digit _hex_digit + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S92 + ['A','F'] -> S92 + ['a','f'] -> S92 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S80{ + _byte_value : _octal_byte_value | • _hex_byte_value + _hex_byte_value : '\' 'x' _hex_digit • _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + char_lit : ''' (_unicode_value | • _byte_value) ''' +} +Transitions: + ['0','9'] -> S93 + ['A','F'] -> S93 + ['a','f'] -> S93 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S81{ + !comment : (_lineComment | _blockComment) • + _blockComment : '/' '*' {. | '*'} '*' '/' • +} +Transitions: +Action: Ignore("!comment") +Symbols classes: {} + +S82{ + g_sdt_lit : '<' '<' . {.} '>' • '>' +} +Transitions: + ['>','>'] -> S94 +Action: nil +Symbols classes: {['>','>']} + +S83{ + g_ctxdep_lit : '@' '@' . {.} '@' • '@' +} +Transitions: + ['@','@'] -> S95 +Action: nil +Symbols classes: {['@','@']} + +S84{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' 'm' 'p' 't' • 'y' +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','x'] -> S49 + ['y','y'] -> S96 + ['z','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','x'], ['y','y'], ['z','z']} + +S85{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' 'r' 'r' 'o' • 'r' +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','q'] -> S49 + ['r','r'] -> S97 + ['s','z'] -> S49 +Action: Accept("tokId") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','q'], ['r','r'], ['s','z']} + +S86{ + _big_u_value : • '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : (_octal_byte_value | _hex_byte_value) • + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : • '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : • '\' 'x' _hex_digit _hex_digit + _interpreted_string : '"' {_unicode_value | _byte_value} • '"' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : • '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : '\' _octal_digit _octal_digit _octal_digit • + _octal_byte_value : • '\' _octal_digit _octal_digit _octal_digit + _octal_digit : '0'-'7' • + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + _unicode_value : • . | _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['"','"'] -> S28 + ['\','\'] -> S29 +Action: nil +Symbols classes: {['"','"'], ['\','\']} + +S87{ + _big_u_value : '\' 'U' _hex_digit _hex_digit • _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S98 + ['A','F'] -> S98 + ['a','f'] -> S98 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S88{ + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : '\' 'u' _hex_digit _hex_digit • _hex_digit _hex_digit + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S99 + ['A','F'] -> S99 + ['a','f'] -> S99 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S89{ + _big_u_value : • '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : (_octal_byte_value | _hex_byte_value) • + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : • '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : '\' 'x' _hex_digit _hex_digit • + _hex_byte_value : • '\' 'x' _hex_digit _hex_digit + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _interpreted_string : '"' {_unicode_value | _byte_value} • '"' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : • '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : • '\' _octal_digit _octal_digit _octal_digit + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + _unicode_value : • . | _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['"','"'] -> S28 + ['\','\'] -> S29 +Action: nil +Symbols classes: {['"','"'], ['\','\']} + +S90{ + _byte_value : (_octal_byte_value | _hex_byte_value) • + _octal_byte_value : '\' _octal_digit _octal_digit _octal_digit • + _octal_digit : '0'-'7' • + char_lit : ''' (_unicode_value | _byte_value) • ''' +} +Transitions: + [''','''] -> S66 +Action: nil +Symbols classes: {[''',''']} + +S91{ + _big_u_value : '\' 'U' _hex_digit _hex_digit • _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S100 + ['A','F'] -> S100 + ['a','f'] -> S100 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S92{ + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _little_u_value : '\' 'u' _hex_digit _hex_digit • _hex_digit _hex_digit + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S101 + ['A','F'] -> S101 + ['a','f'] -> S101 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S93{ + _byte_value : (_octal_byte_value | _hex_byte_value) • + _hex_byte_value : '\' 'x' _hex_digit _hex_digit • + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + char_lit : ''' (_unicode_value | _byte_value) • ''' +} +Transitions: + [''','''] -> S66 +Action: nil +Symbols classes: {[''',''']} + +S94{ + g_sdt_lit : '<' '<' . {.} '>' '>' • +} +Transitions: +Action: Accept("g_sdt_lit") +Symbols classes: {} + +S95{ + g_ctxdep_lit : '@' '@' . {.} '@' '@' • +} +Transitions: +Action: Accept("g_ctxdep_lit") +Symbols classes: {} + +S96{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' 'm' 'p' 't' 'y' • +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','z'] -> S49 +Action: Accept("Λ") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S97{ + _digit : • '0'-'9' + _id_char : (_upcase | _lowcase | '_' | _digit) • + _id_char : _upcase | _lowcase | '_' | • _digit + _id_char : _upcase | _lowcase | • '_' | _digit + _id_char : _upcase | • _lowcase | '_' | _digit + _id_char : • _upcase | _lowcase | '_' | _digit + _lowcase : 'a'-'z' • + _lowcase : • 'a'-'z' + _tokId : _lowcase {_id_char} • + _tokId : _lowcase {• _id_char} + _tokId : • _lowcase {_id_char} + _upcase : • 'A'-'Z' + tokId : _tokId • + tokId : • _tokId + Λ : 'e' 'r' 'r' 'o' 'r' • +} +Transitions: + ['0','9'] -> S46 + ['A','Z'] -> S47 + ['_','_'] -> S48 + ['a','z'] -> S49 +Action: Accept("Λ") +Symbols classes: {['0','9'], ['A','Z'], ['_','_'], ['a','z']} + +S98{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit • _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S102 + ['A','F'] -> S102 + ['a','f'] -> S102 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S99{ + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : '\' 'u' _hex_digit _hex_digit _hex_digit • _hex_digit + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S103 + ['A','F'] -> S103 + ['a','f'] -> S103 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S100{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit • _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S104 + ['A','F'] -> S104 + ['a','f'] -> S104 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S101{ + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _little_u_value : '\' 'u' _hex_digit _hex_digit _hex_digit • _hex_digit + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S105 + ['A','F'] -> S105 + ['a','f'] -> S105 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S102{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit • _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S106 + ['A','F'] -> S106 + ['a','f'] -> S106 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S103{ + _big_u_value : • '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : • '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : • '\' 'x' _hex_digit _hex_digit + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _interpreted_string : '"' {_unicode_value | _byte_value} • '"' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit • + _little_u_value : • '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : • '\' _octal_digit _octal_digit _octal_digit + _unicode_value : (. | _little_u_value | _big_u_value | _escaped_char) • + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + _unicode_value : • . | _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['"','"'] -> S28 + ['\','\'] -> S29 +Action: nil +Symbols classes: {['"','"'], ['\','\']} + +S104{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit • _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S107 + ['A','F'] -> S107 + ['a','f'] -> S107 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S105{ + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _little_u_value : '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit • + _unicode_value : (. | _little_u_value | _big_u_value | _escaped_char) • + char_lit : ''' (_unicode_value | _byte_value) • ''' +} +Transitions: + [''','''] -> S66 +Action: nil +Symbols classes: {[''',''']} + +S106{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit • _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S108 + ['A','F'] -> S108 + ['a','f'] -> S108 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S107{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit • _hex_digit _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S109 + ['A','F'] -> S109 + ['a','f'] -> S109 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S108{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit • _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S110 + ['A','F'] -> S110 + ['a','f'] -> S110 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S109{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit • _hex_digit _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S111 + ['A','F'] -> S111 + ['a','f'] -> S111 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S110{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit • _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['0','9'] -> S112 + ['A','F'] -> S112 + ['a','f'] -> S112 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S111{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit • _hex_digit + _hex_digit : '0'-'9' | 'A'-'F' | • 'a'-'f' + _hex_digit : '0'-'9' | • 'A'-'F' | 'a'-'f' + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _hex_digit : • '0'-'9' | 'A'-'F' | 'a'-'f' + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + char_lit : ''' (• _unicode_value | _byte_value) ''' +} +Transitions: + ['0','9'] -> S113 + ['A','F'] -> S113 + ['a','f'] -> S113 +Action: nil +Symbols classes: {['0','9'], ['A','F'], ['a','f']} + +S112{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit • + _big_u_value : • '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit + _byte_value : _octal_byte_value | • _hex_byte_value + _byte_value : • _octal_byte_value | _hex_byte_value + _escaped_char : • '\' ('a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\' | ''' | '"') + _hex_byte_value : • '\' 'x' _hex_digit _hex_digit + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _interpreted_string : '"' {_unicode_value | _byte_value} • '"' + _interpreted_string : '"' {_unicode_value | • _byte_value} '"' + _interpreted_string : '"' {• _unicode_value | _byte_value} '"' + _little_u_value : • '\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + _octal_byte_value : • '\' _octal_digit _octal_digit _octal_digit + _unicode_value : (. | _little_u_value | _big_u_value | _escaped_char) • + _unicode_value : . | _little_u_value | _big_u_value | • _escaped_char + _unicode_value : . | _little_u_value | • _big_u_value | _escaped_char + _unicode_value : . | • _little_u_value | _big_u_value | _escaped_char + _unicode_value : • . | _little_u_value | _big_u_value | _escaped_char + string_lit : _raw_string | • _interpreted_string +} +Transitions: + ['"','"'] -> S28 + ['\','\'] -> S29 +Action: nil +Symbols classes: {['"','"'], ['\','\']} + +S113{ + _big_u_value : '\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit _hex_digit • + _hex_digit : ( '0'-'9' | 'A'-'F' | 'a'-'f') • + _unicode_value : (. | _little_u_value | _big_u_value | _escaped_char) • + char_lit : ''' (_unicode_value | _byte_value) • ''' +} +Transitions: + [''','''] -> S66 +Action: nil +Symbols classes: {[''',''']} + diff --git a/internal/frontend/reparsed/log/terminals.txt b/internal/frontend/reparsed/log/terminals.txt new file mode 100644 index 00000000..678d8010 --- /dev/null +++ b/internal/frontend/reparsed/log/terminals.txt @@ -0,0 +1,27 @@ +ά +tokId +":" +";" +regDefId +ignoredTokId +"|" +"." +char_lit +"-" +"~" +"(" +")" +"[" +"]" +"{" +"}" +g_sdt_lit +prodId +string_lit +g_ctxdep_lit +"@" +"error" +"λ" +"empty" +"ε" diff --git a/internal/frontend/reparsed/main/gocc2.go b/internal/frontend/reparsed/main/gocc2.go new file mode 100644 index 00000000..45fda21f --- /dev/null +++ b/internal/frontend/reparsed/main/gocc2.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + gocc2 "github.com/maxcalandrelli/gocc/internal/frontend/reparsed" +) + +func showResult(r interface{}, e error, p []byte) { + if e != nil { + fmt.Fprintf(os.Stderr, "parsing returned the following error: %s\n", e.Error()) + } else { + if len(p) > 0 { + fmt.Printf("r=%#v, (%s)\n", r, string(p)) + } else { + fmt.Printf("r=%#v\n", r) + } + } +} + +var ( + File string + Text string + Longest bool +) + +func parse(longest bool, lex *gocc2.Lexer) (res interface{}, err error, parsed []byte) { + if longest { + return gocc2.NewParser().ParseLongestPrefix(lex) + } else { + res, err = gocc2.NewParser().Parse(lex) + parsed = []byte{} + } + return +} + +func main() { + flag.StringVar(&File, "file", "", "parse also text in file") + flag.StringVar(&Text, "text", "", "parse also text given with flag") + flag.BoolVar(&Longest, "longest", false, "parse longest possible part") + flag.Parse() + if Text > "" { + showResult(parse(Longest, gocc2.NewLexerString(Text))) + } + if File > "" { + l, e := gocc2.NewLexerFile(File) + if e != nil { + panic(e) + } + showResult(parse(Longest, l)) + } + if str := strings.Join(flag.Args(), " "); str > "" { + showResult(parse(Longest, gocc2.NewLexerString(str))) + } +} diff --git a/internal/frontend/reparsed/util.go b/internal/frontend/reparsed/util.go new file mode 100644 index 00000000..4d97adb8 --- /dev/null +++ b/internal/frontend/reparsed/util.go @@ -0,0 +1,25 @@ +// Code generated by gocc; DO NOT EDIT. + +package gocc2 + +import ( + "github.com/maxcalandrelli/gocc/internal/frontend/reparsed/internal/util" +) + +type EscapedString = util.EscapedString + +func RuneToString(r rune) string { + return util.RuneToString(r) +} + +func HexDigitValue(ch rune) int { + return util.HexDigitValue(ch) +} + +func IntValue(lit []byte) (int64, error) { + return util.IntValue(lit) +} + +func UintValue(lit []byte) (uint64, error) { + return util.UintValue(lit) +} diff --git a/internal/frontend/errors/errors.go b/internal/frontend/stock/errors/errors.go similarity index 87% rename from internal/frontend/errors/errors.go rename to internal/frontend/stock/errors/errors.go index 7e7f7321..f31a7a20 100644 --- a/internal/frontend/errors/errors.go +++ b/internal/frontend/stock/errors/errors.go @@ -1,6 +1,6 @@ package errors -import "github.com/goccmack/gocc/internal/frontend/token" +import "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" type ErrorSymbol interface { } diff --git a/internal/frontend/parser/parser.go b/internal/frontend/stock/parser/parser.go similarity index 95% rename from internal/frontend/parser/parser.go rename to internal/frontend/stock/parser/parser.go index 4d03962e..984d3b04 100644 --- a/internal/frontend/parser/parser.go +++ b/internal/frontend/stock/parser/parser.go @@ -4,11 +4,13 @@ import ( "errors" "fmt" "strconv" + + "github.com/maxcalandrelli/gocc/internal/config" ) -import errs "github.com/goccmack/gocc/internal/frontend/errors" +import errs "github.com/maxcalandrelli/gocc/internal/frontend/stock/errors" -import "github.com/goccmack/gocc/internal/frontend/token" +import "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" type ( ActionTab []*ActionRow @@ -196,7 +198,7 @@ func (P *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, P.tokenMap.TokenString(t)) } - action, ok := P.actTab[P.stack.Top()].Actions[P.tokenMap.Type("error")] + action, ok := P.actTab[P.stack.Top()].Actions[P.tokenMap.Type(config.SYMBOL_ERROR)] if !ok { return } diff --git a/internal/frontend/parser/parser_ut.go b/internal/frontend/stock/parser/parser_ut.go similarity index 93% rename from internal/frontend/parser/parser_ut.go rename to internal/frontend/stock/parser/parser_ut.go index ddd3dc1d..c1fbee2a 100644 --- a/internal/frontend/parser/parser_ut.go +++ b/internal/frontend/stock/parser/parser_ut.go @@ -3,11 +3,13 @@ package parser import ( "errors" "strconv" + + "github.com/maxcalandrelli/gocc/internal/config" ) -import errs "github.com/goccmack/gocc/internal/frontend/errors" +import errs "github.com/maxcalandrelli/gocc/internal/frontend/stock/errors" -import "github.com/goccmack/gocc/internal/frontend/token" +import "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" // ParserUTab @@ -54,7 +56,7 @@ func (P *ParserUTab) Error(err error, scanner Scanner) (recovered bool, errorAtt } } - action := P.actTab[P.stack.Top()][P.tokenMap.Type("error")] + action := P.actTab[P.stack.Top()][P.tokenMap.Type(config.SYMBOL_ERROR)] if action == nil { return } diff --git a/internal/frontend/parser/tables.go b/internal/frontend/stock/parser/tables.go similarity index 99% rename from internal/frontend/parser/tables.go rename to internal/frontend/stock/parser/tables.go index 1e3bfc83..c9e6fcc7 100644 --- a/internal/frontend/parser/tables.go +++ b/internal/frontend/stock/parser/tables.go @@ -1,6 +1,6 @@ package parser -import "github.com/goccmack/gocc/internal/ast" +import "github.com/maxcalandrelli/gocc/internal/ast" var ProductionsTable = ProdTab{ // [0] diff --git a/internal/frontend/parser/tables_uncompressed.go b/internal/frontend/stock/parser/tables_uncompressed.go similarity index 99% rename from internal/frontend/parser/tables_uncompressed.go rename to internal/frontend/stock/parser/tables_uncompressed.go index 0e9aa778..755ca6a8 100644 --- a/internal/frontend/parser/tables_uncompressed.go +++ b/internal/frontend/stock/parser/tables_uncompressed.go @@ -1,6 +1,6 @@ package parser -import "github.com/goccmack/gocc/internal/ast" +import "github.com/maxcalandrelli/gocc/internal/ast" const ( NUM_STATES = 120 diff --git a/internal/frontend/scanner/scanner.go b/internal/frontend/stock/scanner/scanner.go similarity index 98% rename from internal/frontend/scanner/scanner.go rename to internal/frontend/stock/scanner/scanner.go index cd5d3c72..8f346886 100644 --- a/internal/frontend/scanner/scanner.go +++ b/internal/frontend/stock/scanner/scanner.go @@ -13,8 +13,10 @@ import ( "strconv" "unicode" "unicode/utf8" + + "github.com/maxcalandrelli/gocc/internal/config" ) -import "github.com/goccmack/gocc/internal/frontend/token" +import "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" // A Scanner holds the scanner's internal state while processing // a given text. It can be allocated as part of another data @@ -480,7 +482,7 @@ scanAgain: S.next() // always make progress switch ch { case -1: - tok = S.tokenMap.Type("$") + tok = S.tokenMap.Type(config.SYMBOL_EOF) case '"': tok = S.tokenMap.Type("string_lit") S.scanString(pos) @@ -533,6 +535,8 @@ scanAgain: } case '.': tok = S.tokenMap.Type(".") + case '~': + tok = S.tokenMap.Type("~") default: S.error(pos, "illegal character "+charString(ch)) } diff --git a/internal/frontend/scanner/scanner_test.go b/internal/frontend/stock/scanner/scanner_test.go similarity index 96% rename from internal/frontend/scanner/scanner_test.go rename to internal/frontend/stock/scanner/scanner_test.go index 57d86f79..4898d237 100644 --- a/internal/frontend/scanner/scanner_test.go +++ b/internal/frontend/stock/scanner/scanner_test.go @@ -4,7 +4,7 @@ import ( "fmt" "testing" - "github.com/goccmack/gocc/internal/frontend/token" + "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" ) type testRecord struct { diff --git a/internal/frontend/token/token.go b/internal/frontend/stock/token/token.go similarity index 97% rename from internal/frontend/token/token.go rename to internal/frontend/stock/token/token.go index f30eb7a0..1a75c235 100644 --- a/internal/frontend/token/token.go +++ b/internal/frontend/stock/token/token.go @@ -7,6 +7,8 @@ import ( "regexp" "strconv" "strings" + + "github.com/maxcalandrelli/gocc/internal/config" ) type Token struct { @@ -33,7 +35,7 @@ func (this *Token) Equals(that *Token) bool { func (this *Token) String() string { str := "" if this.Type == EOF { - str += "\"$\"" + str += fmt.Sprintf("\"%s\"", config.SYMBOL_EOF) } else { str += "\"" + string(this.Lit) + "\"" } @@ -130,7 +132,7 @@ type TokenMap struct { func NewMap() *TokenMap { tm := &TokenMap{make([]string, 0, 10), make(map[string]Type)} - tm.AddToken("$") + tm.AddToken(config.SYMBOL_EOF) // tm.AddToken("ε") return tm } diff --git a/internal/frontend/token/tokens.go b/internal/frontend/stock/token/tokens.go similarity index 68% rename from internal/frontend/token/tokens.go rename to internal/frontend/stock/token/tokens.go index 8043d915..6e9426da 100644 --- a/internal/frontend/token/tokens.go +++ b/internal/frontend/stock/token/tokens.go @@ -1,5 +1,9 @@ package token +import ( + "github.com/maxcalandrelli/gocc/internal/config" +) + var FRONTENDTokens = NewMapFromStrings([]string{ "id", "tokId", @@ -19,7 +23,7 @@ var FRONTENDTokens = NewMapFromStrings([]string{ ")", "prodId", "g_sdt_lit", - "error", - "empty", + config.SYMBOL_ERROR, + config.SYMBOL_EMPTY, "string_lit", }) diff --git a/internal/io/gen/gen.go b/internal/io/gen/gen.go new file mode 100644 index 00000000..c79fe71c --- /dev/null +++ b/internal/io/gen/gen.go @@ -0,0 +1,23 @@ +//Copyright 2013 Vastech SA (PTY) LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package gen + +import ( + "github.com/maxcalandrelli/gocc/internal/io/gen/golang" +) + +func Gen(pkg, outdir, subpath string) { + golang.GenIo(pkg, outdir, subpath) +} diff --git a/internal/io/gen/golang/gen.go b/internal/io/gen/golang/gen.go new file mode 100644 index 00000000..7cb75db3 --- /dev/null +++ b/internal/io/gen/golang/gen.go @@ -0,0 +1,490 @@ +package golang + +import ( + "bytes" + "path" + "text/template" + + "github.com/maxcalandrelli/gocc/internal/io" +) + +type data struct { + Pkg string + Outdir string + Subpath string + MyPath string + MyInternal string +} + +func GenIo(pkg, outdir, subpath string) { + myData := data{ + Pkg: pkg, + Outdir: outdir, + Subpath: subpath, + MyPath: "io/stream", + MyInternal: "internal", + } + genIoStream(myData) + genIoStreamImpl(myData) + genIoStreamPublic(myData) +} + +func genIoStream(d data) { + tmpl, err := template.New("io_stream").Parse(streamSrc[1:]) + if err != nil { + panic(err) + } + wr := new(bytes.Buffer) + if err := tmpl.Execute(wr, d); err != nil { + panic(err) + } + io.WriteFile(path.Join(d.Outdir, d.Subpath, d.MyPath, "stream.go"), wr.Bytes()) +} + +func genIoStreamImpl(d data) { + tmpl, err := template.New("io_stream_impl").Parse(streamImplSrc[1:]) + if err != nil { + panic(err) + } + wr := new(bytes.Buffer) + if err := tmpl.Execute(wr, d); err != nil { + panic(err) + } + io.WriteFile(path.Join(d.Outdir, d.Subpath, d.MyPath, d.MyInternal, "stream_impl.go"), wr.Bytes()) +} + +func genIoStreamPublic(d data) { + tmpl, err := template.New("io_stream_public").Parse(streamPublicSrc[1:]) + if err != nil { + panic(err) + } + wr := new(bytes.Buffer) + if err := tmpl.Execute(wr, d); err != nil { + panic(err) + } + io.WriteFile(path.Join(d.Outdir, d.Subpath, d.MyPath, d.MyInternal, "stream_public.go"), wr.Bytes()) +} + +var streamSrc = ` +package stream + +import ( + internal "{{.Pkg}}/{{.Subpath}}/{{.MyPath}}/{{.MyInternal}}" + "io" +) + +type ( + WindowReader interface { + BlockSize() int + Buffered() int + Cap() int + MaxCap() int + Read([]byte) (int, error) + ReadByte() (byte, error) + ReadPosition() int64 + ReadRune() (rune, int, error) + Seek(int64, int) (int64, error) + UnreadByte() error + UnreadRune() error + MaxUnreadSize() int + } +) + +var ( + InfoPrefixRoundUp = false +) + +func NewWindowReaderFromBytes(src []byte) WindowReader { + return internal.NewWindowReader(src, nil, 0, 0, InfoPrefixRoundUp) +} + +func NewWindowReader(rdr io.Reader) WindowReader { + return internal.NewWindowReader(nil, rdr, 0, 0, false) +} + +func NewLimitedWindowReader(rdr io.Reader, sizeMin, sizeMax int) WindowReader { + return internal.NewWindowReader(nil, rdr, sizeMin, sizeMax, InfoPrefixRoundUp) +} +` + +var streamImplSrc = ` +package internal + +import ( + "io" + "sync" + "unicode/utf8" +) + +type ( + impl_WindowReader struct { + bufferBlockSize int + maxBufferSize int + buffers [][]byte + available int + absbase int64 + position int + eof bool + rdr io.Reader + lock *sync.Mutex + } +) + +func (s *impl_WindowReader) lockReader() { + if s.lock != nil { + s.lock.Lock() + } +} + +func (s *impl_WindowReader) unlockReader() { + if s.lock != nil { + s.lock.Unlock() + } +} + +func (s *impl_WindowReader) seek(offset int64, whence int) (offs int64, err error) { + switch whence { + case io.SeekStart: + return s.seek(offset-s.ReadPosition(), io.SeekCurrent) + case io.SeekCurrent: + switch { + case offset == 0: + return s.ReadPosition(), nil + case offset < 0: + if -offset > int64(s.maxBackOffset()) { + err = io.ErrShortBuffer + } else { + s.advanceGet(int(offset)) + } + case offset > 0: + for offset > 0 && !s.eof { + available := s.Buffered() + if offset <= int64(available) { + s.advanceGet(int(offset)) + break + } + if available > 0 { + s.advanceGet(available) + offset -= int64(available) + } + read, _ := s.fetchBytes(int(offset)) + s.advanceGet(read) + offset -= int64(read) + } + if s.eof { + err = io.EOF + } + } + case io.SeekEnd: + for !s.eof { + s.seek(int64(s.MaxCap()), io.SeekCurrent) + } + s.seek(int64(s.Buffered()), io.SeekCurrent) + } + if s.eof && err == nil && s.Buffered() > 0 { + s.eof = false + } + return s.ReadPosition(), err +} + +func (s impl_WindowReader) maxBackOffset() int { + r := s.position + if s.absbase > 0 { + r = s.Cap() - s.Buffered() + } + return r +} + +func (s impl_WindowReader) bufferIndex(pos int) int { + if pos < 0 { + panic("negative position") + } + return pos / s.bufferBlockSize +} + +func (s impl_WindowReader) bufferBytes(pos int) []byte { + return s.buffers[s.bufferIndex(pos)] +} + +func (s impl_WindowReader) bufferByteRange(pos int, length int) []byte { + p := s.bufferOffset(pos) + return s.bufferBytes(pos)[p : p+length] +} + +func (s impl_WindowReader) bufferOffset(pos int) int { + return pos % s.bufferBlockSize +} + +func (s *impl_WindowReader) advanceGet(n int) { + sz := s.Cap() + switch { + case n < 0: + if -n > s.maxBackOffset() { + panic("underflow") + } + s.position += n + if s.position < 0 { + s.position += sz + s.absbase -= int64(sz) + } + case n > 0: + if n > s.Buffered() { + panic("overflow") + } + s.position += n + if s.position >= sz { + s.position -= sz + s.absbase += int64(sz) + } + } + s.available -= n +} + +func (s *impl_WindowReader) copy(to []byte, length int) { + for offs, cp := 0, 0; length > 0; length -= cp { + s.position %= s.MaxCap() + p := s.bufferOffset(s.position) + b := s.bufferBytes(s.position) + r := s.bufferBlockSize - p + if length <= r { + cp = copy(to[offs:], b[p:p+length]) + } else { + cp = copy(to[offs:], b[p:]) + } + s.advanceGet(cp) + offs += cp + } +} + +func (s *impl_WindowReader) fetchBytes(n int) (read int, err error) { + if s.rdr == nil { + s.eof = true + return 0, io.EOF + } + for n > 0 && s.Buffered() < s.MaxCap() && err == nil { + readNow := n + putpos := s.position + s.available + r := s.bufferBlockSize - s.bufferOffset(putpos) + if readNow > r { + readNow = r + } + for s.bufferIndex(putpos) >= len(s.buffers) && s.Cap() < s.MaxCap() { + s.buffers = append(s.buffers, make([]byte, s.bufferBlockSize)) + } + putpos %= s.MaxCap() + offs := s.bufferOffset(putpos) + if r, err = s.rdr.Read(s.bufferBytes(putpos)[offs : offs+readNow]); r > 0 { + s.available += r + read += r + n -= r + } + } + if n > 0 && err == nil { + err = io.ErrShortBuffer + } + return +} + +func (s *impl_WindowReader) read(p []byte) (read int, err error) { + if s.eof { + return 0, io.EOF + } + for read < len(p) && err == nil { + available := s.Buffered() + if len(p)-read <= available { + s.copy(p[read:], len(p)-read) + read = len(p) + } else { + if available == 0 { + available, err = s.fetchBytes(len(p) - read) + } + s.copy(p[read:], available) + read += available + switch err { + case io.ErrShortBuffer: + err = nil + case io.EOF: + s.eof = true + } + } + } + return +} + +func (s impl_WindowReader) peekByte() (byte, error) { + if s.Buffered() < 1 { + return 0, io.ErrShortBuffer + } + return s.bufferBytes(s.position)[s.bufferOffset(s.position)], nil +} + +func (s *impl_WindowReader) unreadByte() error { + _, e := s.seek(-1, io.SeekCurrent) + return e +} + +func (s *impl_WindowReader) readRune() (r rune, size int, err error) { + for i := 1; err == nil && i <= 4; i++ { + if s.Buffered() < i { + if _, err = s.fetchBytes(i); err != nil { + return + } + } + t := s.bufferByteRange(s.position, i) + if r, size = utf8.DecodeRune(t); r != utf8.RuneError { + s.advanceGet(size) + return + } + } + return utf8.RuneError, 0, err +} + +func (s *impl_WindowReader) unreadRune() (err error) { + tmps := *s + tmpb := []byte{} + for { + if _, err = tmps.seek(-1, io.SeekCurrent); err == nil { + b, _ := tmps.peekByte() + tmpb = append([]byte{b}, tmpb...) + switch len(tmpb) { + case 1: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 2: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xE0) != 0xC0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 3: + if (tmpb[0] & 0xC0) == 0x80 { + continue + } + if (tmpb[0] & 0xF0) != 0xE0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + case 4: + if (tmpb[0] & 0xF8) != 0xF0 { + break + } + _, err = s.seek(-int64(len(tmpb)), io.SeekCurrent) + return + } + } + } + _, err = s.seek(-1, io.SeekCurrent) + return +} +` + +var streamPublicSrc = ` +package internal + +import ( + "io" +) + +func NewWindowReader(buf []byte, underlyingReader io.Reader, blksize, smax int, InfoPrefixRoundUp bool) *impl_WindowReader { + if blksize < 0 || smax < blksize { + panic("illegal buffer size") + } + r := &impl_WindowReader{rdr: underlyingReader} + r.bufferBlockSize = blksize + if underlyingReader != nil { + if blksize <= 0 { + r.bufferBlockSize = 1 << 10 + } else if InfoPrefixRoundUp { + for r.bufferBlockSize = 1; blksize > 0; r.bufferBlockSize = r.bufferBlockSize << 1 { + blksize = blksize >> 1 + } + } + if smax > 0 { + r.maxBufferSize = ((smax-1)/r.bufferBlockSize + 1) * r.bufferBlockSize + } + r.buffers = [][]byte{} + } else { + r.buffers = [][]byte{buf} + r.available = len(buf) + r.bufferBlockSize = r.available + r.maxBufferSize = r.available + } + return r +} + +func (s impl_WindowReader) Cap() int { + return len(s.buffers) * s.bufferBlockSize +} + +func (s impl_WindowReader) BlockSize() int { + return s.bufferBlockSize +} + +func (s impl_WindowReader) MaxCap() int { + if s.maxBufferSize > 0 { + return s.maxBufferSize + } + return 1 << 31 +} + +func (s impl_WindowReader) MaxUnreadSize() int { + return s.maxBackOffset() +} + +func (s impl_WindowReader) Buffered() int { + return s.available +} + +func (s impl_WindowReader) ReadPosition() int64 { + return s.absbase + int64(s.position) +} + +func (s *impl_WindowReader) Read(p []byte) (read int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.read(p) +} + +func (s *impl_WindowReader) Seek(offset int64, whence int) (offs int64, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.seek(offset, whence) +} + +func (s *impl_WindowReader) ReadByte() (byte, error) { + b := []byte{0} + _, err := s.Read(b) + return b[0], err +} + +func (s *impl_WindowReader) PeekByte() (byte, error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.peekByte() +} + +func (s *impl_WindowReader) UnreadByte() error { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadByte() +} + +func (s *impl_WindowReader) ReadRune() (r rune, size int, err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.readRune() +} + +func (s *impl_WindowReader) UnreadRune() (err error) { + s.lockReader() + defer func() { s.unlockReader() }() + return s.unreadRune() +} +` diff --git a/internal/lexer/gen/golang/acttab.go b/internal/lexer/gen/golang/acttab.go index b68cc937..df60f248 100644 --- a/internal/lexer/gen/golang/acttab.go +++ b/internal/lexer/gen/golang/acttab.go @@ -19,47 +19,53 @@ import ( "path" "text/template" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/lexer/items" - "github.com/goccmack/gocc/internal/token" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/lexer/items" + "github.com/maxcalandrelli/gocc/internal/token" ) -func genActionTable(pkg, outDir string, itemsets *items.ItemSets, tokMap *token.TokenMap) { - fname := path.Join(outDir, "lexer", "acttab.go") +func genActionTable(pkg, outDir string, itemsets *items.ItemSets, tokMap *token.TokenMap, subpath string) { + fname := path.Join(outDir, subpath, "lexer", "acttab.go") tmpl, err := template.New("action table").Parse(actionTableSrc[1:]) if err != nil { panic(err) } wr := new(bytes.Buffer) - if err := tmpl.Execute(wr, getActTab(pkg, itemsets, tokMap)); err != nil { + if err := tmpl.Execute(wr, getActTab(pkg, subpath, itemsets, tokMap)); err != nil { panic(err) } io.WriteFile(fname, wr.Bytes()) } -func getActTab(pkg string, itemsets *items.ItemSets, tokMap *token.TokenMap) *actTab { +func getActTab(pkg, subpath string, itemsets *items.ItemSets, tokMap *token.TokenMap) *actTab { actab := &actTab{ - TokenImport: path.Join(pkg, "token"), - Actions: make([]action, itemsets.Size()), + TokenImport: path.Join(pkg, subpath, "token"), + Actions: make([]actTabEntry, itemsets.Size()), } for sno, set := range itemsets.List() { if act := set.Action(); act != nil { switch act1 := act.(type) { case items.Accept: - actab.Actions[sno].Accept = tokMap.IdMap[string(act1)] - actab.Actions[sno].Ignore = "" + actab.Actions[sno].Symbol = act1.String() + actab.Actions[sno].Action.Accept = tokMap.IdMap[string(act1)] + actab.Actions[sno].Action.Ignore = "" case items.Ignore: - actab.Actions[sno].Accept = -1 - actab.Actions[sno].Ignore = string(act1) + actab.Actions[sno].Symbol = act1.String() + actab.Actions[sno].Action.Accept = -1 + actab.Actions[sno].Action.Ignore = string(act1) } } } return actab } +type actTabEntry struct { + Action action + Symbol string +} type actTab struct { TokenImport string - Actions []action + Actions []actTabEntry } type action struct { @@ -91,9 +97,9 @@ func (a ActionRow) String() string { var ActTab = ActionTable{ {{- range $s, $act := .Actions}} - ActionRow{ // S{{$s}} - Accept: {{$act.Accept}}, - Ignore: "{{$act.Ignore}}", + ActionRow{ // S{{$s}}, {{$act.Symbol}} + Accept: {{$act.Action.Accept}}, + Ignore: "{{$act.Action.Ignore}}", }, {{- end}} } diff --git a/internal/lexer/gen/golang/asciitable.go b/internal/lexer/gen/golang/asciitable.go index 8ddf2639..bb52e93a 100644 --- a/internal/lexer/gen/golang/asciitable.go +++ b/internal/lexer/gen/golang/asciitable.go @@ -19,8 +19,8 @@ import ( "path" "text/template" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/lexer/symbols" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/lexer/symbols" ) func genAsciiTable(outDir string, symbols *symbols.Symbols) { diff --git a/internal/lexer/gen/golang/chrranges.go b/internal/lexer/gen/golang/chrranges.go index 6a9f9232..fc1dfc4a 100644 --- a/internal/lexer/gen/golang/chrranges.go +++ b/internal/lexer/gen/golang/chrranges.go @@ -15,7 +15,7 @@ package golang import ( - "github.com/goccmack/gocc/internal/lexer/symbols" + "github.com/maxcalandrelli/gocc/internal/lexer/symbols" ) type CharRange struct { diff --git a/internal/lexer/gen/golang/gen.go b/internal/lexer/gen/golang/gen.go index 00009454..9ff76261 100644 --- a/internal/lexer/gen/golang/gen.go +++ b/internal/lexer/gen/golang/gen.go @@ -15,13 +15,13 @@ package golang import ( - "github.com/goccmack/gocc/internal/config" - "github.com/goccmack/gocc/internal/lexer/items" - "github.com/goccmack/gocc/internal/token" + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/lexer/items" + "github.com/maxcalandrelli/gocc/internal/token" ) -func Gen(pkg, outDir string, header string, itemsets *items.ItemSets, tokMap *token.TokenMap, cfg config.Config) { - genLexer(pkg, outDir, itemsets, cfg) - genTransitionTable(pkg, outDir, header, itemsets) - genActionTable(pkg, outDir, itemsets, tokMap) +func Gen(pkg, outDir string, header string, itemsets *items.ItemSets, tokMap *token.TokenMap, cfg config.Config, internal, iface string) { + genLexer(pkg, outDir, itemsets, cfg, internal, iface) + genTransitionTable(pkg, outDir, header, itemsets, internal) + genActionTable(pkg, outDir, itemsets, tokMap, internal) } diff --git a/internal/lexer/gen/golang/imports.go b/internal/lexer/gen/golang/imports.go index 49d9cf50..57b5a1c3 100644 --- a/internal/lexer/gen/golang/imports.go +++ b/internal/lexer/gen/golang/imports.go @@ -15,7 +15,7 @@ package golang import ( - "github.com/goccmack/gocc/internal/lexer/symbols" + "github.com/maxcalandrelli/gocc/internal/lexer/symbols" ) type importType struct { diff --git a/internal/lexer/gen/golang/lexer.go b/internal/lexer/gen/golang/lexer.go index 0a1eec68..0347ad74 100644 --- a/internal/lexer/gen/golang/lexer.go +++ b/internal/lexer/gen/golang/lexer.go @@ -19,44 +19,48 @@ import ( "path" "text/template" - "github.com/goccmack/gocc/internal/config" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/lexer/items" + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/lexer/items" ) -func genLexer(pkg, outDir string, itemsets *items.ItemSets, cfg config.Config) { +func genLexer(pkg, outDir string, itemsets *items.ItemSets, cfg config.Config, internal, iface string) { tmpl, err := template.New("lexer").Parse(lexerSrc[1:]) if err != nil { panic(err) } buf := new(bytes.Buffer) - err = tmpl.Execute(buf, getLexerData(pkg, outDir, itemsets, cfg)) + err = tmpl.Execute(buf, getLexerData(pkg, outDir, itemsets, cfg, internal, iface)) if err != nil { panic(err) } - io.WriteFile(path.Join(outDir, "lexer", "lexer.go"), buf.Bytes()) + io.WriteFile(path.Join(outDir, internal, "lexer", "lexer.go"), buf.Bytes()) } -func getLexerData(pkg, outDir string, itemsets *items.ItemSets, cfg config.Config) *lexerData { +func getLexerData(pkg, outDir string, itemsets *items.ItemSets, cfg config.Config, internal, iface string) *lexerData { lexSymbols := itemsets.Symbols().List() return &lexerData{ - Debug: cfg.DebugLexer(), - TokenImport: path.Join(pkg, "token"), - UtilImport: path.Join(pkg, "util"), - NumStates: itemsets.Size(), - NumSymbols: len(lexSymbols), - Symbols: lexSymbols, + Debug: cfg.DebugLexer(), + PkgPath: pkg, + InternalSubdir: internal, + IfaceSubdir: iface, + NumStates: itemsets.Size(), + NumSymbols: len(lexSymbols), + Symbols: lexSymbols, + MyName: cfg.ProjectName(), } } type lexerData struct { - Debug bool - TokenImport string - UtilImport string - NumStates int - NumSymbols int - NextState []byte - Symbols []string + Debug bool + PkgPath string + InternalSubdir string + IfaceSubdir string + NumStates int + NumSymbols int + NextState []byte + Symbols []string + MyName string } const lexerSrc string = ` @@ -65,137 +69,192 @@ const lexerSrc string = ` package lexer import ( -{{if .Debug}} "fmt" -{{end}} "io/ioutil" - "unicode/utf8" + {{if .Debug}} "fmt" {{end}} + "io" + "bytes" + "os" -{{if .Debug}} "{{.UtilImport}}" -{{end}} "{{.TokenImport}}" + {{if .Debug}} "{{.PkgPath}}/{{.InternalSubdir}}/util" {{end}} + "{{.PkgPath}}/{{.IfaceSubdir}}" + "{{.PkgPath}}/{{.InternalSubdir}}/token" + "{{.PkgPath}}/{{.InternalSubdir}}/io/stream" ) const ( NoState = -1 NumStates = {{.NumStates}} NumSymbols = {{.NumSymbols}} + INVALID_RUNE = rune(-1) ) +type position struct { + token.Pos +} + type Lexer struct { - src []byte - pos int - line int - column int -} - -func NewLexer(src []byte) *Lexer { - lexer := &Lexer{ - src: src, - pos: 0, - line: 1, - column: 1, - } + position + stream iface.TokenStream + eof bool +} + +func NewLexerBytes(src []byte) *Lexer { + lexer := &Lexer{stream: bytes.NewReader(src)} + lexer.reset() return lexer } +func NewLexerString(src string) *Lexer { + return NewLexerBytes([]byte(src)) +} + func NewLexerFile(fpath string) (*Lexer, error) { - src, err := ioutil.ReadFile(fpath) + s, err := os.Open(fpath) if err != nil { return nil, err } - return NewLexer(src), nil + lexer := &Lexer{stream: stream.NewWindowReader(s)} + lexer.reset() + return lexer, nil +} + +func NewLexer(reader io.Reader) (*Lexer, error) { + lexer := &Lexer{} + lexer.reset() + if lexer.stream, _ = reader.(iface.TokenStream); lexer.stream == nil { + lexer.stream = stream.NewWindowReader(reader) + } + return lexer, nil +} + +func (l *Lexer) reset () { + l.position.Reset() +} + +func (l Lexer) GetStream() iface.TokenStream { + return l.stream +} + +type checkPoint int64 + +func (c checkPoint) value () int64 { + return int64(c) +} + +func (c checkPoint) DistanceFrom (o iface.CheckPoint) int { + return int (c.value() - o.(checkPoint).value()) +} + +func (c checkPoint) Advance (o int) iface.CheckPoint { + return checkPoint(c.value() + int64(o)) +} + +func (l *Lexer) GetCheckPoint() iface.CheckPoint { + if l == nil { + return checkPoint(0) + } + pos, _ := l.stream.Seek(0, io.SeekCurrent) + return checkPoint(pos) +} + +func (l Lexer) GotoCheckPoint(cp iface.CheckPoint) { + l.stream.Seek(int64(cp.(checkPoint)), io.SeekStart) } func (l *Lexer) Scan() (tok *token.Token) { {{- if .Debug}} - fmt.Printf("Lexer.Scan() pos=%d\n", l.pos) + fmt.Printf("{{.MyName}}:lexer:Lexer.Scan() pos=%d\n", l.position.Pos.Offset) {{- end}} tok = new(token.Token) - if l.pos >= len(l.src) { - tok.Type = token.EOF - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = l.pos, l.line, l.column - return - } - start, startLine, startColumn, end := l.pos, l.line, l.column, 0 tok.Type = token.INVALID - state, rune1, size := 0, rune(-1), 0 - for state != -1 { + start := l.position + state := 0 + for state != -1 { {{- if .Debug}} - fmt.Printf("\tpos=%d, line=%d, col=%d, state=%d\n", l.pos, l.line, l.column, state) + fmt.Printf("{{.MyName}}:lexer: pos=%d, line=%d, col=%d, state=%d\n", l.position.Pos.Offset, l.position.Pos.Line, l.position.Pos.Column, state) {{- end}} - if l.pos >= len(l.src) { - rune1 = -1 - } else { - rune1, size = utf8.DecodeRune(l.src[l.pos:]) - l.pos += size - } - + savePos := l.position.Pos + curr, size, err := l.stream.ReadRune() + if size < 1 || err != nil { + curr = INVALID_RUNE + } + {{- if .Debug}} + fmt.Printf("{{.MyName}}:lexer: rune=<%c> size=%d err=%v\n", curr, size, err) + {{- end}} + if size > 0 { + l.position.Pos.Offset += size + } nextState := -1 - if rune1 != -1 { - nextState = TransTab[state](rune1) + if curr != INVALID_RUNE { + nextState = TransTab[state](curr) } {{- if .Debug}} - fmt.Printf("\tS%d, : tok=%s, rune == %s(%x), next state == %d\n", state, token.TokMap.Id(tok.Type), util.RuneToString(rune1), rune1, nextState) - fmt.Printf("\t\tpos=%d, size=%d, start=%d, end=%d\n", l.pos, size, start, end) + fmt.Printf("{{.MyName}}:lexer:S%d, : tok=%s, rune == %s(%x), next state == %d\n", state, token.TokMap.Id(tok.Type), util.RuneToString(curr), curr, nextState) + fmt.Printf("{{.MyName}}:lexer: pos=%d, size=%d, start=%d\n", l.position.Pos.Offset, size, start.Pos.Offset) if nextState != -1 { - fmt.Printf("\t\taction:%s\n", ActTab[nextState].String()) + fmt.Printf("{{.MyName}}:lexer: action:%s\n", ActTab[nextState].String()) } {{- end}} state = nextState - if state != -1 { - - switch rune1 { - case '\n': - l.line++ - l.column = 1 - case '\r': - l.column = 1 - case '\t': - l.column += 4 - default: - l.column++ - } - + switch curr { + case '\n': + l.position.Pos.Line++ + l.position.Pos.Column = 1 + case '\r': + l.position.Pos.Column = 1 + case '\t': + l.position.Pos.Column += 4 + default: + l.position.Pos.Column++ + } switch { case ActTab[state].Accept != -1: tok.Type = ActTab[state].Accept - end = l.pos + tok.Lit = append(tok.Lit, string(curr)...) case ActTab[state].Ignore != "": - start, startLine, startColumn = l.pos, l.line, l.column + start = l.position state = 0 - if start >= len(l.src) { - tok.Type = token.EOF - } - - } - } else { - if tok.Type == token.INVALID { - end = l.pos + tok.Lit = []byte{} + tok.IgnoredPrefix=append(tok.IgnoredPrefix,string(curr)...) } - } + } else if curr != INVALID_RUNE{ + if len(tok.Lit) == 0 { + tok.Lit = append(tok.Lit, string(curr)...) + } else { + l.stream.UnreadRune() + l.position.Pos = savePos + } + } + if err == io.EOF && len(tok.Lit)==0 { + tok.Type = token.EOF + tok.Pos = start.Pos + return + } } - if end > start { - l.pos = end - tok.Lit = l.src[start:end] - } else { - tok.Lit = []byte{} - } - tok.Pos.Offset, tok.Pos.Line, tok.Pos.Column = start, startLine, startColumn - + tok.Pos = start.Pos {{- if .Debug}} - fmt.Printf("Token at %s: %s \"%s\"\n", tok.String(), token.TokMap.Id(tok.Type), tok.Lit) + fmt.Printf("{{.MyName}}:lexer:Token at %s: %s \"%s\"\n", tok.String(), token.TokMap.Id(tok.Type), tok.Lit) {{- end}} - return } func (l *Lexer) Reset() { - l.pos = 0 + l.position.Reset() } -/* -Lexer symbols: -{{- range $i, $sym := .Symbols}} -{{- printf "\n%d: %s" $i $sym}} -{{- end}} -*/ +func (l Lexer) CurrentPosition() position { + return l.position +} + +func (p *position) Reset() { + p.Offset = 0 + p.Line = 1 + p.Column = 1 +} + +func (p position) StartingFrom(base position) position { + r := p + r.Pos = p.Pos.StartingFrom(base.Pos) + return r +} ` diff --git a/internal/lexer/gen/golang/transtab.go b/internal/lexer/gen/golang/transtab.go index 9f536d8d..bc8d02d7 100644 --- a/internal/lexer/gen/golang/transtab.go +++ b/internal/lexer/gen/golang/transtab.go @@ -20,12 +20,12 @@ import ( "path" "text/template" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/lexer/items" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/lexer/items" ) -func genTransitionTable(pkg, outDir, header string, itemSets *items.ItemSets) { - fname := path.Join(outDir, "lexer", "transitiontable.go") +func genTransitionTable(pkg, outDir, header string, itemSets *items.ItemSets, subpath string) { + fname := path.Join(outDir, subpath, "lexer", "transitiontable.go") io.WriteFile(fname, getTransitionTable(itemSets, header)) } @@ -54,7 +54,7 @@ type transitionTableData struct { func getTransitionTableData(itemsets *items.ItemSets) []transitionTableRowData { data := make([]transitionTableRowData, itemsets.Size()) for setNo, set := range itemsets.List() { - if set.SymbolClasses.MatchAny { + if set.SymbolClasses.MatchAny || set.DotTransition >= 0 { data[setNo].MatchAny = true data[setNo].MatchAnyState = set.DotTransition } else { diff --git a/internal/lexer/items/charrange.go b/internal/lexer/items/charrange.go index e0ed391b..63c51a98 100644 --- a/internal/lexer/items/charrange.go +++ b/internal/lexer/items/charrange.go @@ -17,7 +17,7 @@ package items import ( "fmt" - "github.com/goccmack/gocc/internal/util" + "github.com/maxcalandrelli/gocc/internal/util" ) type CharRange struct { diff --git a/internal/lexer/items/dbg.go b/internal/lexer/items/dbg.go new file mode 100644 index 00000000..906742e4 --- /dev/null +++ b/internal/lexer/items/dbg.go @@ -0,0 +1,72 @@ +package items + +import ( + "fmt" + "os" + "regexp" + "runtime/debug" + "strings" + + "github.com/maxcalandrelli/gocc/internal/util" +) + +const ( + debug_wrong_regdef_handling = false + debug_deeply = debug_wrong_regdef_handling +) + +var ( + callerRE = regexp.MustCompile("^\\s*(.*)/([^/]+)(\\(.*\\))$") + sourceRE = regexp.MustCompile("^\\s*(.*)/([^/]+:\\d+)\\s*(.*)$") +) + +func dbgr(set int, format string, v ...interface{}) { + if debug_deeply { + if set >= 0 { + fmt.Fprintf(os.Stderr, "S%d:", set) + } + fmt.Fprintf(os.Stderr, format, v...) + } +} + +func printItems(items ItemList) string { + b := strings.Builder{} + for _, i := range items { + b.WriteString(i.String()) + b.WriteByte('\n') + } + return b.String() +} + +func dbg(set int, format string, v ...interface{}) { + if debug_deeply { + args := make([]interface{}, len(v)) + for _i, _v := range v { + switch _v.(type) { + case string: + _v = util.EscapedString(_v.(string)).Unescape() + case ItemList: + _v = printItems(_v.(ItemList)) + case []*Item: + _v = printItems(ItemList(_v.([]*Item))) + } + args[_i] = _v + } + dbgr(set, format, args...) + } +} + +func trace(set int, format string, v ...interface{}) { + if debug_deeply { + stack := strings.Split(string(debug.Stack()), "\n") + fmt.Fprintf(os.Stderr, "\n") + fmt.Fprintf(os.Stderr, "-------------------------------------------\n") + for ix := 5; ix < len(stack)-3; ix += 2 { + caller := callerRE.ReplaceAllString(stack[ix], "$2") + source := sourceRE.ReplaceAllString(stack[ix+1], "$2") + fmt.Fprintf(os.Stderr, "%s in %s\n", caller, source) + } + fmt.Fprintf(os.Stderr, "-------------------------------------------\n") + dbg(set, format, v...) + } +} diff --git a/internal/lexer/items/disjunctrangeset.go b/internal/lexer/items/disjunctrangeset.go index c897782a..6e6125dd 100644 --- a/internal/lexer/items/disjunctrangeset.go +++ b/internal/lexer/items/disjunctrangeset.go @@ -18,7 +18,7 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/ast" ) // set is kept sorted @@ -37,9 +37,17 @@ func NewDisjunctRangeSet() *DisjunctRangeSet { func (this *DisjunctRangeSet) AddLexTNode(sym ast.LexTNode) { switch s := sym.(type) { case *ast.LexCharRange: - this.AddRange(s.From.Val, s.To.Val) + if s.Negate { + this.SubtractRange(s.From.Val, s.To.Val) + } else { + this.AddRange(s.From.Val, s.To.Val) + } case *ast.LexCharLit: - this.AddRange(s.Val, s.Val) + if s.Negate { + this.SubtractRange(s.Val, s.Val) + } else { + this.AddRange(s.Val, s.Val) + } case *ast.LexDot: this.MatchAny = true case *ast.LexRegDefId: @@ -129,6 +137,46 @@ func (this *DisjunctRangeSet) AddRange(from, to rune) { } } +func (this *DisjunctRangeSet) subtractRange(index int, from, to rune) int { + if index < len(this.set) { + rng := this.set[index] + if to >= from && to >= rng.From { + if from > rng.To || to < rng.From { + return index + 1 + } + if from < rng.From { + return this.subtractRange(index, rng.From, to) + } + if to > rng.To { + return this.subtractRange(this.subtractRange(index, from, rng.To), rng.To+1, to) + } + // + // from >= rng.to && to <= rng.to + // + switch { + case from == rng.From && to == rng.To: + copy(this.set[index:], this.set[index+1:]) + this.set = this.set[:len(this.set)-1] + return index + case from == rng.From: + this.set[index].From = to + 1 + case to == rng.To: + this.set[index].To = from - 1 + default: + this.set[index].From = this.set[index].From + this.set[index].To = from - 1 + this.AddRange(to+1, rng.To) + } + } + } + return len(this.set) +} + +func (this *DisjunctRangeSet) SubtractRange(from, to rune) { + for index := 0; index < len(this.set); index = this.subtractRange(index, from, to) { + } +} + func (this *DisjunctRangeSet) Range(i int) CharRange { return this.set[i] } diff --git a/internal/lexer/items/disjunctrangeset_test.go b/internal/lexer/items/disjunctrangeset_test.go index f5f42865..5e3ce8bd 100644 --- a/internal/lexer/items/disjunctrangeset_test.go +++ b/internal/lexer/items/disjunctrangeset_test.go @@ -15,10 +15,11 @@ package items import ( + "fmt" // "fmt" "testing" - "github.com/goccmack/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/ast" // "unicode" ) @@ -412,3 +413,35 @@ func TestDisjunctSets14(t *testing.T) { t.Fatalf("len(set.set) == %d", len(set.set)) } } + +func test15hlp(t *testing.T, set *DisjunctRangeSet, from, to rune, subtract bool, expect string) { + if subtract { + fmt.Printf("current set: %s; subtracting <%c-%c>\n", set.String(), from, to) + set.SubtractRange(from, to) + } else { + fmt.Printf("current set: %s; adding <%c-%c>\n", set.String(), from, to) + set.AddRange(from, to) + } + fmt.Printf("resulting set: %s\n", set.String()) + if expect != set.String() { + fmt.Printf("expected set: %s\n", expect) + t.Fatalf("expected set: %s\n", expect) + t.Fatalf("actual set: %s\n", set.String()) + } +} + +func TestDisjunctSets15(t *testing.T) { + set := NewDisjunctRangeSet() + test15hlp(t, set, 'D', 'F', false, "{['D','F']}") + test15hlp(t, set, 'J', 'L', false, "{['D','F'], ['J','L']}") + test15hlp(t, set, 'Q', 'Z', false, "{['D','F'], ['J','L'], ['Q','Z']}") + test15hlp(t, set, '5', '8', false, "{['5','8'], ['D','F'], ['J','L'], ['Q','Z']}") + test15hlp(t, set, 'a', 'z', false, "{['5','8'], ['D','F'], ['J','L'], ['Q','Z'], ['a','z']}") + test15hlp(t, set, '0', '4', true, "{['5','8'], ['D','F'], ['J','L'], ['Q','Z'], ['a','z']}") + test15hlp(t, set, 'A', 'D', true, "{['5','8'], ['E','F'], ['J','L'], ['Q','Z'], ['a','z']}") + test15hlp(t, set, 'E', 'M', true, "{['5','8'], ['Q','Z'], ['a','z']}") + test15hlp(t, set, 'S', '^', true, "{['5','8'], ['Q','R'], ['a','z']}") + test15hlp(t, set, 'K', 'C', true, "{['5','8'], ['Q','R'], ['a','z']}") + test15hlp(t, set, 'c', 'f', true, "{['5','8'], ['Q','R'], ['a','b'], ['g','z']}") + test15hlp(t, set, 'w', 'w', true, "{['5','8'], ['Q','R'], ['a','b'], ['g','v'], ['x','z']}") +} diff --git a/internal/lexer/items/item.go b/internal/lexer/items/item.go index 1d4634d7..b1002a95 100644 --- a/internal/lexer/items/item.go +++ b/internal/lexer/items/item.go @@ -20,9 +20,9 @@ import ( "io" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/lexer/symbols" - "github.com/goccmack/gocc/internal/util" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/lexer/symbols" + "github.com/maxcalandrelli/gocc/internal/util" ) type Item struct { @@ -104,6 +104,7 @@ For a general description of dotted items (items) and ℇ-moves of items, see: T : x(...|y•|...)z => T : x(...|y|...)•z */ func (this *Item) Emoves() (items []*Item) { + trace(-1, "computing ε-moves of %s\n", this) newItems := util.NewStack(8).Push(this) for newItems.Len() > 0 { item := newItems.Pop().(*Item) @@ -112,9 +113,7 @@ func (this *Item) Emoves() (items []*Item) { items = append(items, item) continue } - nt, pos := item.pos.top() - switch node := nt.(type) { case *ast.LexPattern: newItems.Push(item.eMovesLexPattern(node, pos)...) @@ -134,7 +133,7 @@ func (this *Item) Emoves() (items []*Item) { panic(fmt.Sprintf("Unexpected type in items.Emoves(): %T", nt)) } } - + dbg(-1, "ε-moves:{\n%s\n}\n", items) return } @@ -251,9 +250,15 @@ func (this *Item) newLexPatternBasicItems(nt *ast.LexPattern, pos int) []interfa func (this *Item) nextIsTerminal() bool { nt, pos := this.pos.top() + trace(-1, "<%s>: checking that node %s next to pos %d is terminal: ", this.Id, nt.String(), pos) if pos >= nt.Len() { + dbg(-1, "no, pos is after end\n") return false } + if debug_deeply { + nte := nt.Element(pos) + dbg(-1, "%t [%T:%s]\n", nte.LexTerminal(), nte, nte.String()) + } return nt.Element(pos).LexTerminal() } @@ -305,7 +310,7 @@ func (this *Item) Move(rng CharRange) []*Item { movedItem.getHashKey() items := movedItem.Emoves() - + dbg(-1, " <%q>:move(%q):%q\n", this, rng, items) return items } @@ -326,6 +331,9 @@ func (this *Item) MoveRegDefId(id string) []*Item { movedItem := this.Clone() movedItem.pos.inc() movedItem.getHashKey() + if debug_deeply { + trace(-1, " * moved item:\n%s\nwas:\n%s)\n", movedItem.pos.String(), this.pos.String()) + } items := movedItem.Emoves() return items } diff --git a/internal/lexer/items/item_test.go b/internal/lexer/items/item_test.go index 685b6347..4c2680b7 100644 --- a/internal/lexer/items/item_test.go +++ b/internal/lexer/items/item_test.go @@ -18,7 +18,7 @@ import ( "fmt" "testing" - "github.com/goccmack/gocc/internal/lexer/symbols" + "github.com/maxcalandrelli/gocc/internal/lexer/symbols" ) /* diff --git a/internal/lexer/items/itemlist.go b/internal/lexer/items/itemlist.go index 5f3caf11..844c5747 100644 --- a/internal/lexer/items/itemlist.go +++ b/internal/lexer/items/itemlist.go @@ -19,13 +19,27 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/lexer/symbols" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/lexer/symbols" ) // Each Itemset element is a ItemList type ItemList []*Item +func (l ItemList) Len() int { + return len(l) +} + +func (l ItemList) Less(i, j int) bool { + return l[i].String() < l[j].String() +} + +func (l ItemList) Swap(i, j int) { + t := l[i] + l[i] = l[j] + l[j] = t +} + func NewItemList(len int) ItemList { if len < 8 { len = 8 @@ -48,6 +62,7 @@ func (this ItemList) AddNoDuplicate(items ...*Item) ItemList { for _, item := range items { if !newList.Contain(item) { newList = append(newList, item) + } else { } } return newList @@ -58,10 +73,13 @@ See Algorithm: set.Closure() in package doc */ func (this ItemList) Closure(lexPart *ast.LexPart, symbols *symbols.Symbols) ItemList { closure := this + trace(-1, "calculating closure of <%s>\n", this) for i := 0; i < len(closure); i++ { expSym := closure[i].ExpectedSymbol() if regDefId, isRegDefId := expSym.(*ast.LexRegDefId); isRegDefId { - if !this.ContainShift(expSym.String()) && !symbols.IsImport(regDefId.Id) { + dbg(-1, "found regexp %s examining %s; shift found: %t \n", regDefId.Id, closure[i].String(), this.ContainShift(expSym.String())) + if (!this.ContainShift(expSym.String()) || (fix_regdef_bug && this.ContainReduce(expSym.String()))) && !symbols.IsImport(regDefId.Id) { + dbg(-1, "adding %s to closure with its ε-moves\n", regDefId.Id) closure = closure.AddNoDuplicate(NewItem(regDefId.Id, lexPart, symbols).Emoves()...) } } @@ -87,6 +105,15 @@ func (this ItemList) ContainShift(id string) bool { return false } +func (this ItemList) ContainReduce(id string) bool { + for _, item := range this { + if item.Id == id && item.Reduce() { + return true + } + } + return false +} + func (this ItemList) Equal(that ItemList) bool { if len(this) != len(that) { return false diff --git a/internal/lexer/items/itempos.go b/internal/lexer/items/itempos.go index 3d955039..b0129eb1 100644 --- a/internal/lexer/items/itempos.go +++ b/internal/lexer/items/itempos.go @@ -18,7 +18,7 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/ast" ) type itemPos struct { diff --git a/internal/lexer/items/itempos_test.go b/internal/lexer/items/itempos_test.go index ae672e96..537656f0 100644 --- a/internal/lexer/items/itempos_test.go +++ b/internal/lexer/items/itempos_test.go @@ -16,7 +16,7 @@ package items import ( // "fmt" - // "github.com/goccmack/gocc/internal/ast" + // "github.com/maxcalandrelli/gocc/internal/ast" "testing" ) diff --git a/internal/lexer/items/itemset.go b/internal/lexer/items/itemset.go index 15b62f98..782e9859 100644 --- a/internal/lexer/items/itemset.go +++ b/internal/lexer/items/itemset.go @@ -18,8 +18,8 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/lexer/symbols" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/lexer/symbols" ) /* @@ -39,6 +39,9 @@ type ItemSet struct { } func NewItemSet(setNo int, lexPart *ast.LexPart, symbols *symbols.Symbols, items ItemList) *ItemSet { + if debug_deeply { + trace(setNo, "creating, start items:\n%s", items) + } set := &ItemSet{ setNo: setNo, Items: items.Closure(lexPart, symbols), @@ -46,8 +49,11 @@ func NewItemSet(setNo int, lexPart *ast.LexPart, symbols *symbols.Symbols, items Symbols: symbols, DotTransition: -1, } - set.getSymbolClasses() + set.getSymbolClasses(lexPart, symbols) set.newTransitions() + if debug_deeply { + trace(setNo, "created, items:\n%s\nsymbol classes:\n%s", set.Items, set.SymbolClasses) + } return set } @@ -108,13 +114,35 @@ func (this *ItemSet) Empty() bool { return len(this.Items) == 0 } -func (this *ItemSet) getSymbolClasses() { +func (this *ItemSet) getSymbolClasses(lexPart *ast.LexPart, symbols *symbols.Symbols) { this.SymbolClasses = NewDisjunctRangeSet() for _, item := range this.Items { if !item.Reduce() { - this.SymbolClasses.AddLexTNode(item.ExpectedSymbol()) + this.addToSymbolClasses(lexPart, symbols, item.ExpectedSymbol(), false) + } + } + for _, item := range this.Items { + if !item.Reduce() { + this.addToSymbolClasses(lexPart, symbols, item.ExpectedSymbol(), true) } } + +} + +func (this *ItemSet) addToSymbolClasses(lexPart *ast.LexPart, symbols *symbols.Symbols, node ast.LexNode, negated bool) { + addNow := !negated + tNode := ast.LexTNode(nil) + switch n := node.(type) { + case *ast.LexCharLit: + addNow = (negated == n.Negate) + tNode = node.(ast.LexTNode) + case *ast.LexCharRange: + addNow = (negated == n.Negate) + tNode = node.(ast.LexTNode) + } + if addNow && tNode != nil { + this.SymbolClasses.AddLexTNode(tNode) + } } func (this *ItemSet) newTransitions() { @@ -132,7 +160,7 @@ func (this *ItemSet) newTransitions() { See algorithm: set.Next() in package doc */ func (this *ItemSet) Next(rng CharRange) ItemList { - // fmt.Printf("S%d%s\n", this.setNo, this) + trace(this.setNo, "rng=%q\n", rng) nextItems := NewItemList(16) for _, item := range this.Items { nextItems = nextItems.AddNoDuplicate(item.Move(rng)...) @@ -163,18 +191,19 @@ func (this *ItemSet) dependentsClosure(items ItemList) ItemList { if len(items) == 0 { return items } - // fmt.Printf("dependentsClosure S%d, %s\n", this.setNo, items) + //trace(this.setNo, "dependentsClosure\n actual: %s\n items: %s\n", util.EscapedString(this.String()).Unescape(), util.EscapedString(fmt.Sprintf("%q", items)).Unescape()) + trace(this.setNo, "dependentsClosure\n") for i := 0; i < len(items); i++ { for _, thisItem := range this.Items { if expSym := thisItem.ExpectedSymbol(); expSym != nil && expSym.String() == items[i].Id { if items[i].Reduce() { - // mv := thisItem.MoveRegDefId(items[i].Id) - // for _, mvi := range mv { - // fmt.Printf("\t%s\n", mvi) - // } + mv := thisItem.MoveRegDefId(items[i].Id) + for _, mvi := range mv { + dbg(this.setNo, " ====> %s\n", mvi) + } items = items.AddNoDuplicate(thisItem.MoveRegDefId(items[i].Id)...) } else { - // fmt.Printf("\t%s\n", thisItem) + dbg(this.setNo, " ==> %s\n", thisItem) items = items.AddNoDuplicate(thisItem) } } diff --git a/internal/lexer/items/itemsets.go b/internal/lexer/items/itemsets.go index b461bdff..45279a46 100644 --- a/internal/lexer/items/itemsets.go +++ b/internal/lexer/items/itemsets.go @@ -16,10 +16,11 @@ package items import ( "fmt" + "sort" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/lexer/symbols" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/lexer/symbols" ) type ItemSets struct { @@ -28,15 +29,20 @@ type ItemSets struct { symbols *symbols.Symbols } -func GetItemSets(lexPart *ast.LexPart) *ItemSets { +var ( + fix_dots_bug bool + fix_regdef_bug bool +) + +func GetItemSets(lexPart *ast.LexPart, _fix_dots_bug, _fix_regdefs_bug bool) *ItemSets { + fix_dots_bug = _fix_dots_bug + fix_regdef_bug = _fix_regdefs_bug itemSets := &ItemSets{ sets: make([]*ItemSet, 0, 256), lexPart: lexPart, symbols: symbols.NewSymbols(lexPart), } - itemSets.Add(ItemsSet0(lexPart, itemSets.symbols)) - return itemSets.Closure() } @@ -45,14 +51,23 @@ func (this *ItemSets) Add(items ItemList) (setNo int) { return setNo } setNo = this.Size() + if debug_deeply { + trace(setNo, "Calling NewItemSet, items:\n%s", items) + } this.sets = append(this.sets, NewItemSet(setNo, this.lexPart, this.symbols, items)) return setNo } func (this *ItemSets) Closure() *ItemSets { + if debug_deeply { + trace(-1, "calculating closure of %s", this) + } for i := 0; i < len(this.sets); i++ { for symI, rng := range this.sets[i].SymbolClasses.List() { if items := this.sets[i].Next(rng); len(items) != 0 { + if debug_deeply { + dbg(i, " rng: %q\nitems: %s\n", rng, items) + } setNo, nextState := this.Add(items), this.sets[i].Transitions[symI] if nextState != -1 && nextState != setNo { panic(fmt.Sprintf("Next set conflict in (S%d, %s) -> %d. Existing setNo: %d", i, rng, setNo, nextState)) @@ -74,9 +89,28 @@ func (this *ItemSets) Closure() *ItemSets { this.sets[i].DotTransition = setNo } } + if fix_dots_bug { + for i := 0; i < len(this.sets); i++ { + this.propagateDots(i) + } + } return this } +/* + this will allow to parse a '>' in a SDT construct, just to name a case... +*/ + +func (this *ItemSets) propagateDots(start int) { + if this.sets[start].DotTransition > -1 { + for _, tr := range this.sets[start].Transitions { + if tr > start && this.sets[tr].DotTransition < 0 && len(this.sets[tr].Transitions) > 0 { + this.sets[tr].DotTransition = this.sets[start].DotTransition + } + } + } +} + func (this *ItemSets) Contain(items ItemList) (yes bool, index int) { for i, thisSet := range this.sets { if thisSet.Equal(items) { @@ -103,7 +137,9 @@ func (this *ItemSets) String() string { fmt.Fprintf(buf, "Item sets:\n") for i, s := range this.sets { fmt.Fprintf(buf, "S%d{\n", i) - for _, item := range s.Items { + s_items := s.Items + sort.Sort(s_items) + for _, item := range s_items { fmt.Fprintf(buf, "\t%s\n", item) } fmt.Fprintf(buf, "}\n") diff --git a/internal/lexer/items/itemsets_test.go b/internal/lexer/items/itemsets_test.go index c64cda26..dfe9504f 100644 --- a/internal/lexer/items/itemsets_test.go +++ b/internal/lexer/items/itemsets_test.go @@ -75,7 +75,7 @@ ignoredTokId : '!' _tokId ; func _TestItemSets2(t *testing.T) { g := parse(testItemsets2src, t) - itemSets := GetItemSets(g.LexPart) + itemSets := GetItemSets(g.LexPart, false, false) fmt.Printf("%s\n", itemSets) } @@ -89,7 +89,7 @@ comment : _lineComment | _blockComment ; func _TestItemSets3(t *testing.T) { g := parse(testItemsets3src, t) - itemSets := GetItemSets(g.LexPart) + itemSets := GetItemSets(g.LexPart, false, false) fmt.Printf("%s\n", itemSets) } diff --git a/internal/lexer/items/testutils_test.go b/internal/lexer/items/testutils_test.go index debb62c6..d97a2517 100644 --- a/internal/lexer/items/testutils_test.go +++ b/internal/lexer/items/testutils_test.go @@ -18,10 +18,10 @@ import ( "fmt" "testing" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/frontend/parser" - "github.com/goccmack/gocc/internal/frontend/scanner" - "github.com/goccmack/gocc/internal/frontend/token" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/frontend/stock/parser" + "github.com/maxcalandrelli/gocc/internal/frontend/stock/scanner" + "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" ) func findSet(sets *ItemSets, items []string) *ItemSet { diff --git a/internal/lexer/symbols/charlitsymbols.go b/internal/lexer/symbols/charlitsymbols.go index f9d98da2..5819ab59 100644 --- a/internal/lexer/symbols/charlitsymbols.go +++ b/internal/lexer/symbols/charlitsymbols.go @@ -15,7 +15,7 @@ package symbols import ( - "github.com/goccmack/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/ast" ) // key: string of symbols - string(ast.CharLit.Lit). E.g.: "'a'" diff --git a/internal/lexer/symbols/charrangesymbols.go b/internal/lexer/symbols/charrangesymbols.go index fe43e039..163dea92 100644 --- a/internal/lexer/symbols/charrangesymbols.go +++ b/internal/lexer/symbols/charrangesymbols.go @@ -15,7 +15,7 @@ package symbols import ( - "github.com/goccmack/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/ast" ) // key: string of range, e.g.: 'a'-'z' diff --git a/internal/lexer/symbols/symbols.go b/internal/lexer/symbols/symbols.go index 1be7679c..fb1ff574 100644 --- a/internal/lexer/symbols/symbols.go +++ b/internal/lexer/symbols/symbols.go @@ -18,7 +18,7 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/ast" ) type Symbols struct { diff --git a/internal/macro/preprocess.go b/internal/macro/preprocess.go new file mode 100644 index 00000000..71c35278 --- /dev/null +++ b/internal/macro/preprocess.go @@ -0,0 +1,310 @@ +package macro + +import ( + "bufio" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "regexp" + "strings" +) + +type ( + Macro struct { + Name string + ParametersMap map[string]int + Text []string + EndDelimiter *regexp.Regexp + HasVarArgs bool + } + void struct{} +) + +var ( + NOTHING void = void{} + S_MACRO_ARGS_SEP = "," + S_MACRO_ESCAPE_SEP = fmt.Sprintf("<%s>", S_MACRO_ARGS_SEP) + S_MACRONOTSEP = fmt.Sprintf("(?:(?:%s)|[^%s])*", S_MACRO_ESCAPE_SEP, S_MACRO_ARGS_SEP) + S_MACROPARAMNAME = "\\b(?:(?:[[:alpha:]](?:[\\w_])*)|(?:VARGS))\\b" + S_MACROPARAMVALUE = "\\s*(" + S_MACRONOTSEP + ")\\s*" + S_MACRONAME = S_MACROPARAMNAME + S_MACROARG = S_MACROPARAMVALUE + S_MACROARGS = fmt.Sprintf("(\\s*%s\\s*(?:%s\\s*%s\\s*)*)", S_MACROPARAMNAME, S_MACRO_ARGS_SEP, S_MACROPARAMNAME) + MACROCONDLINE = regexp.MustCompile(fmt.Sprintf("^\\s*\\?\\s*(%s)\\s*(==|!=|>|<|>=|<=)\\s*([^\\s]+)\\s+(.+)$", S_MACROPARAMNAME)) + _MACROCONDLINE = regexp.MustCompile(fmt.Sprintf("^\\s*\\?")) + MACRONAME = regexp.MustCompile(fmt.Sprintf("(%s)", S_MACRONAME)) + MACROPARAM = regexp.MustCompile(fmt.Sprintf("(%s)", S_MACROPARAMNAME)) + MACROARG = regexp.MustCompile(S_MACROARG) + MACROARGS = regexp.MustCompile(S_MACROARGS) + MACROSTART = regexp.MustCompile(fmt.Sprintf("^\\s*MACRO\\s+(%s)\\s*(?:\\(%s\\))?\\s*$", S_MACRONAME, S_MACROARGS)) + MACROINVOCATION = regexp.MustCompile(fmt.Sprintf("\\b(%s)\\s*\\((%s(%s%s)*)\\)\\s*$", S_MACRONAME, S_MACRONOTSEP, S_MACRO_ARGS_SEP, S_MACRONOTSEP)) + MACROVAREXPANSION = regexp.MustCompile(fmt.Sprintf("{(%s)}", S_MACROPARAMNAME)) + SYNKWD = regexp.MustCompile(fmt.Sprintf("\\bKWD\\((%s)((?:,!?%s)*)\\)(\\s|$)", S_MACROPARAMNAME, S_MACROPARAMNAME)) + KWDGRP = regexp.MustCompile(fmt.Sprintf(",(!?%s)*", S_MACROPARAMNAME)) + + Macros = map[string]*Macro{} + Keywords = map[string]map[string]void{} + KeywordGroups = map[string]map[string]void{"ALL": {}} +) + +func (m *Macro) ArgValue(name string, args []string) (string, error) { + if index, found := m.ParametersMap[name]; found { + if index < len(args) { + return args[index], nil + } else { + return "", nil + } + } + if m.HasVarArgs { + switch name { + case "VLEN": + return fmt.Sprintf("%d", len(args)-len(m.ParametersMap)), nil + case "VARG0": + if len(args) > len(m.ParametersMap) { + return args[len(m.ParametersMap)], nil + } + return "", nil + case "VARGS": + if len(args) > len(m.ParametersMap)+1 { + return strings.Join(args[len(m.ParametersMap)+1:], ","), nil + } + return "", nil + } + } + return "", fmt.Errorf("macro <%s> has no parameter named <%s>", m.Name, name) +} + +func (m *Macro) Expand(args []string, out io.Writer) { + for _, line := range m.Text { + fmt.Fprintln(out, MACROVAREXPANSION.ReplaceAllStringFunc(line, func(match string) string { + match = MACROVAREXPANSION.FindStringSubmatch(match)[1] + //fmt.Printf("args: %q match=<%s> =>%d\n", args, match, m.ParametersMap[match]) + if value, err := m.ArgValue(match, args); err == nil { + return value + } else { + panic(fmt.Errorf("macro <%s> has no parameter named <%s>", m.Name, match)) + } + })) + } +} + +func processEbnfStream(expanding *Macro, expargs []string, in io.Reader, out io.Writer) { + currentMacro := (*Macro)(nil) + lineNumber := 0 + for scanner := bufio.NewScanner(in); scanner.Scan(); { + lineNumber++ + line := scanner.Text() + switch { + case currentMacro != nil: + if currentMacro.EndDelimiter.MatchString(line) { + Macros[currentMacro.Name] = currentMacro + currentMacro = nil + } else { + currentMacro.Text = append(currentMacro.Text, line) + //fmt.Printf("<%s>%03d: %s\n", currentMacro.EndDelimiter.String(), lineNumber, line) + } + case currentMacro == nil: + if cond := MACROCONDLINE.FindStringSubmatch(line); cond != nil { + if expanding == nil { + panic(fmt.Errorf("conditional line out of macro")) + } + name := cond[1] + op := cond[2] + cmp := cond[3] + rest := cond[4] + if cmp == "\"\"" || cmp == "''" { + cmp = "" + } + if value, err := expanding.ArgValue(name, expargs); err != nil { + panic(err) + } else { + if func() bool { + switch op { + case "==": + return value == cmp + case "!=": + return value != cmp + case "<": + return value < cmp + case ">": + return value > cmp + case "<=": + return value <= cmp + case ">=": + return value >= cmp + case "~=": + return regexp.MustCompile(cmp).MatchString(value) + } + return false + }() { + line = rest + } else { + line = "" + continue + } + } + } + if m := MACROSTART.FindStringSubmatch(line); m != nil { + macro_name := m[1] + macro_args := m[2] + if _, found := Macros[macro_name]; found { + panic(fmt.Sprintf("macro %s redefined at line %d\n", macro_name, lineNumber)) + } + currentMacro = &Macro{ + Name: macro_name, + ParametersMap: map[string]int{}, + EndDelimiter: regexp.MustCompile(fmt.Sprintf("^\\s*ENDMACRO\\s*%s\\s*$", macro_name)), + } + for _, s := range MACROPARAM.FindAllStringSubmatch(macro_args, -1) { + name := s[1] + if currentMacro.HasVarArgs { + panic(fmt.Errorf("macro <%s>: varargs can only occur as last formal parameter", currentMacro.Name)) + } + if name == "VARGS" { + currentMacro.HasVarArgs = true + } else { + if _, exists := currentMacro.ParametersMap[name]; exists { + panic(fmt.Sprintf("macro <%s>: parameter <%s> specified twice\n", currentMacro.Name, name)) + } + currentMacro.ParametersMap[name] = len(currentMacro.ParametersMap) + } + } + Macros[currentMacro.Name] = currentMacro + //fmt.Printf("%s parmmap: %q\n", macro_name, currentMacro.ParametersMap) + } else { + line = MACROINVOCATION.ReplaceAllStringFunc(line, func(m string) string { + if vars := MACROINVOCATION.FindStringSubmatch(m); vars != nil { + macro_name := vars[1] + macro_args := vars[2] + if macro, found := Macros[macro_name]; found { + var builder strings.Builder + var args []string + for _, v := range MACROARG.FindAllStringSubmatch(macro_args, -1) { + v[1] = strings.ReplaceAll(v[1], S_MACRO_ESCAPE_SEP, S_MACRO_ARGS_SEP) + //fmt.Printf("macro repl: %s vars=%q, v=%q\n", m, vars, v) + args = append(args, v[1]) + } + for len(args) > len(macro.ParametersMap) && args[len(args)-1] == "" { + args = args[:len(args)-1] + } + if len(args) == len(macro.ParametersMap) || macro.HasVarArgs && len(args) > len(macro.ParametersMap) { + macro.Expand(args, &builder) + processEbnfStream(macro, args, strings.NewReader(builder.String()), out) + //return builder.String() + } else { + panic(fmt.Sprintf("macro <%s> wrong args=<%s> (expected length=%d, actual=%d)\n", macro_name, macro_args, len(macro.ParametersMap), len(args))) + } + } else { + //panic(fmt.Sprintf("unknown macro <%s> in match=<%s>\n", macro_name, m)) + return m + } + } else { + panic(fmt.Sprintf("??? match=<%s>\n", m)) + } + return "" + }) + if match := SYNKWD.FindStringSubmatch(line); match != nil { + kwd := match[1] + if Keywords[kwd] == nil { + Keywords[kwd] = map[string]void{"ALL": NOTHING} + KeywordGroups["ALL"][kwd] = NOTHING + } + for _, grp := range KWDGRP.FindAllStringSubmatch(match[2], -1) { + negate := false + grpname := grp[1] + if negate = (grpname[0] == '!'); negate { + grpname = grpname[1:] + } + if KeywordGroups[grpname] == nil { + KeywordGroups[grpname] = map[string]void{} + } + if negate { + delete(Keywords[kwd], grpname) + delete(KeywordGroups[grpname], kwd) + } else { + Keywords[kwd][grpname] = NOTHING + KeywordGroups[grpname][kwd] = NOTHING + } + } + line = SYNKWD.ReplaceAllString(line, "KWD_"+kwd) + } + if len(line) > 0 { + fmt.Fprintln(out, line) + } + } + } + } +} + +func internalPreProcess(fname, outname string) error { + if outf, err := os.Create(outname); err != nil { + panic(fmt.Sprintf("cannot open <%s>: %s\n", outname, err.Error())) + } else { + defer outf.Close() + if inf, err := os.Open(fname); err != nil { + panic(fmt.Sprintf("cannot open <%s>: %s\n", fname, err.Error())) + } else { + fmt.Fprintf(outf, "//\n// Code generated by gocc preprocessor ; DO NOT EDIT.\n//\n") + processEbnfStream(nil, nil, inf, outf) + inf.Close() + if len(Keywords) > 0 { + for kwd, _ := range Keywords { + fmt.Fprintf(outf, "KWD_%s : \"%s\" ;\n", kwd, kwd) + } + for grp, km := range KeywordGroups { + fmt.Fprintf(outf, + "KGRP_%s:\n%s\n;\n", + grp, + strings.Join( + func() (r []string) { + for kwd, _ := range km { + r = append(r, fmt.Sprintf("\t\tKWD_%s\n", kwd)) + } + return + }(), + "\t|\n"), + ) + } + } + } + } + return nil +} + +func matches(filters []*regexp.Regexp, name string) bool { + for _, re := range filters { + if re.MatchString(name) { + return true + } + } + return false +} + +func createPath(outname string) { + dir, _ := filepath.Split(outname) + if err := os.MkdirAll(dir, 0764); err != nil { + panic(fmt.Sprintf("cannot create directory <%s>\n", dir)) + } +} + +func PreProcess(preprocessor, fname, outname string) error { + switch preprocessor { + case "none": + case "internal": + createPath(outname) + return internalPreProcess(fname, outname) + default: + createPath(outname) + if preprocessCmd := strings.Split(strings.ReplaceAll(strings.ReplaceAll(preprocessor, "@in", fname), "@out", outname), " "); len(preprocessCmd) > 0 { + cmd := exec.Command(preprocessCmd[0], preprocessCmd[1:]...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() + } + return fmt.Errorf("cannot run empty preprocessor") + } + return nil +} diff --git a/internal/parser/first/first.go b/internal/parser/first/first.go index 8b6c1379..0330c8fd 100644 --- a/internal/parser/first/first.go +++ b/internal/parser/first/first.go @@ -18,8 +18,8 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/parser/symbols" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" ) /* @@ -30,8 +30,6 @@ type FirstSets struct { symbols *symbols.Symbols } -const EMPTY = "empty" - //Returns the FirstSets of the Grammar. func GetFirstSets(g *ast.Grammar, symbols *symbols.Symbols) *FirstSets { firstSets := &FirstSets{ @@ -47,18 +45,18 @@ func GetFirstSets(g *ast.Grammar, symbols *symbols.Symbols) *FirstSets { again = false for _, prod := range g.SyntaxPart.ProdList { switch { - case len(prod.Body.Symbols) == 0: - if firstSets.AddToken(prod.Id, EMPTY) { + case prod.Body.Empty(): + if firstSets.AddToken(prod.Id.SymbolName(), ast.EmptySymbol) { again = true } - case symbols.IsTerminal(prod.Body.Symbols[0].SymbolString()): - if firstSets.AddToken(prod.Id, prod.Body.Symbols[0].SymbolString()) { + case prod.Body.Symbols[0].IsTerminal(): + if firstSets.AddToken(prod.Id.SymbolName(), prod.Body.Symbols[0]) { again = true } default: - first := FirstS(firstSets, stringList(prod.Body.Symbols)) - if !first.Equal(firstSets.GetSet(prod.Id)) { - if firstSets.AddSet(prod.Id, first) { + first := FirstS(firstSets, prod.Body.Symbols) + if !first.Equal(firstSets.GetSet(prod.Id.SymbolName())) { + if firstSets.AddSet(prod.Id.SymbolName(), first) { again = true } } @@ -69,7 +67,7 @@ func GetFirstSets(g *ast.Grammar, symbols *symbols.Symbols) *FirstSets { return firstSets } -func stringList(symbols []ast.SyntaxSymbol) []string { +func stringList(symbols ast.SyntaxSymbols) []string { sl := make([]string, len(symbols)) for i, sym := range symbols { sl[i] = sym.SymbolString() @@ -86,14 +84,14 @@ func (this *FirstSets) AddSet(prodName string, terminals SymbolSet) (symbolsAdde return } -func (this *FirstSets) AddToken(prodName string, terminal string) (symbolAdded bool) { +func (this *FirstSets) AddToken(prodName string, terminal ast.SyntaxSymbol) (symbolAdded bool) { set, ok := this.firstSets[prodName] if !ok { set = make(SymbolSet) this.firstSets[prodName] = set } if _, contain := set[terminal]; !contain { - set[terminal] = true + set[terminal] = struct{}{} symbolAdded = true } return @@ -111,18 +109,18 @@ func (this *FirstSets) GetSet(prodName string) SymbolSet { func (this *FirstSets) String() string { buf := new(strings.Builder) for _, nt := range this.symbols.NTList() { - set := this.firstSets[nt] - fmt.Fprintf(buf, "%s: %s\n", nt, set) + set := this.firstSets[nt.SymbolName()] + fmt.Fprintf(buf, "%s: %s\n", nt.SymbolName(), set) } return buf.String() } //Returns the First SymbolSet given the ast.SyntaxSymbol. -func First(fs *FirstSets, sym string) SymbolSet { - if fs.symbols.IsTerminal(sym) { - return SymbolSet{sym: true} +func First(fs *FirstSets, sym ast.SyntaxSymbol) SymbolSet { + if sym.IsTerminal() { + return SymbolSet{sym: struct{}{}} } - return fs.GetSet(sym) + return fs.GetSet(sym.SymbolName()) } /* @@ -137,21 +135,21 @@ Returns First of the string, xyz, e.g.: for the item, ... First(x) + First(y) + ... + First(z) */ -func FirstS(firstSets *FirstSets, symbols []string) (first SymbolSet) { +func FirstS(firstSets *FirstSets, symbols ast.SyntaxSymbols) (first SymbolSet) { first = make(SymbolSet) if len(symbols) == 0 { return } fst := First(firstSets, symbols[0]) first.AddSet(fst) - _, containEmpty := fst["empty"] + _, containEmpty := fst[ast.EmptySymbol] for i := 1; i < len(symbols) && containEmpty; i++ { fst = First(firstSets, symbols[i]) first.AddSet(fst) - _, containEmpty = fst["empty"] + _, containEmpty = fst[ast.EmptySymbol] } if !containEmpty { - delete(first, "empty") + delete(first, ast.EmptySymbol) } return } diff --git a/internal/parser/first/symbolset.go b/internal/parser/first/symbolset.go index 78fa6e3e..d35613c5 100644 --- a/internal/parser/first/symbolset.go +++ b/internal/parser/first/symbolset.go @@ -18,16 +18,18 @@ import ( "fmt" "sort" "strings" + + "github.com/maxcalandrelli/gocc/internal/ast" ) /* key: symbol string */ -type SymbolSet map[string]bool +type SymbolSet map[ast.SyntaxSymbol]struct{} func (this SymbolSet) AddSet(that SymbolSet) { for id := range that { - this[id] = true + this[id] = struct{}{} } } @@ -48,7 +50,7 @@ func (this SymbolSet) String() string { fmt.Fprintf(buf, "{\n") var keys []string for key := range this { - keys = append(keys, key) + keys = append(keys, key.SymbolName()) } sort.Strings(keys) for _, str := range keys { diff --git a/internal/parser/gen/gen.go b/internal/parser/gen/gen.go index 1ab300ab..f1497d9c 100644 --- a/internal/parser/gen/gen.go +++ b/internal/parser/gen/gen.go @@ -18,23 +18,22 @@ This package controls the generation of all parser-related code. package gen import ( - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/config" - "github.com/goccmack/gocc/internal/parser/gen/golang" - "github.com/goccmack/gocc/internal/parser/lr1/items" - "github.com/goccmack/gocc/internal/parser/symbols" - "github.com/goccmack/gocc/internal/token" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/parser/gen/golang" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/items" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" + "github.com/maxcalandrelli/gocc/internal/token" ) func Gen(pkg, outDir, header string, prods ast.SyntaxProdList, symbols *symbols.Symbols, - itemsets *items.ItemSets, tokMap *token.TokenMap, cfg config.Config) (conflicts map[int]items.RowConflicts) { - - golang.GenAction(outDir) - conflicts = golang.GenActionTable(outDir, prods, itemsets, tokMap, cfg.Zip()) - golang.GenErrors(pkg, outDir) - golang.GenGotoTable(outDir, itemsets, symbols, cfg.Zip()) - golang.GenParser(pkg, outDir, prods, itemsets, symbols, cfg) - golang.GenProductionsTable(pkg, outDir, header, prods, symbols, itemsets, tokMap) + itemsets *items.ItemSets, tokMap *token.TokenMap, cfg config.Config, internal, iface string) (conflicts map[int]items.RowConflicts) { + golang.GenAction(outDir, internal) + conflicts = golang.GenActionTable(outDir, prods, itemsets, tokMap, internal, header) + golang.GenErrors(pkg, outDir, internal) + golang.GenGotoTable(outDir, itemsets, symbols, internal) + golang.GenParser(pkg, outDir, prods, itemsets, symbols, cfg, internal, iface) + golang.GenProductionsTable(pkg, outDir, header, prods, symbols, itemsets, tokMap, internal, cfg) return } diff --git a/internal/parser/gen/golang/action.go b/internal/parser/gen/golang/action.go index 020bf58b..a66f8ae5 100644 --- a/internal/parser/gen/golang/action.go +++ b/internal/parser/gen/golang/action.go @@ -17,11 +17,11 @@ package golang import ( "path" - "github.com/goccmack/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/io" ) -func GenAction(outDir string) { - io.WriteFileString(path.Join(outDir, "parser", "action.go"), actionSrc[1:]) +func GenAction(outDir, subpath string) { + io.WriteFileString(path.Join(outDir, subpath, "parser", "action.go"), actionSrc[1:]) } const actionSrc = ` diff --git a/internal/parser/gen/golang/actiontable.go b/internal/parser/gen/golang/actiontable.go index feb11c01..3c20961e 100644 --- a/internal/parser/gen/golang/actiontable.go +++ b/internal/parser/gen/golang/actiontable.go @@ -17,43 +17,51 @@ package golang import ( "bytes" "fmt" - "math" + "go/format" "path" "text/template" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/parser/lr1/action" - "github.com/goccmack/gocc/internal/parser/lr1/items" - "github.com/goccmack/gocc/internal/token" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/action" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/items" + "github.com/maxcalandrelli/gocc/internal/token" ) -func GenActionTable(outDir string, prods ast.SyntaxProdList, itemSets *items.ItemSets, tokMap *token.TokenMap, zip bool) map[int]items.RowConflicts { - if zip { - return GenCompActionTable(outDir, prods, itemSets, tokMap) - } +type actionTableData struct { + Rows []*actRow + CdTokenFunctions []string +} + +type tmplData struct { + Header string + Table *actionTableData +} + +func GenActionTable(outDir string, prods ast.SyntaxProdList, itemSets *items.ItemSets, tokMap *token.TokenMap, subpath, header string) map[int]items.RowConflicts { tmpl, err := template.New("parser action table").Parse(actionTableSrc[1:]) if err != nil { panic(err) } wr := new(bytes.Buffer) data, conflicts := getActionTableData(prods, itemSets, tokMap) - if err := tmpl.Execute(wr, data); err != nil { + if err := tmpl.Execute(wr, tmplData{Table: data, Header: header}); err != nil { panic(err) } - io.WriteFile(path.Join(outDir, "parser", "actiontable.go"), wr.Bytes()) + source, err := format.Source(wr.Bytes()) + if err != nil { + panic(fmt.Sprintf("%s in\n%s", err.Error(), wr.String())) + } + io.WriteFile(path.Join(outDir, subpath, "parser", "actiontable.go"), source) return conflicts } -type actionTableData struct { - Rows []*actRow -} - func getActionTableData(prods ast.SyntaxProdList, itemSets *items.ItemSets, tokMap *token.TokenMap) (actTab *actionTableData, conflicts map[int]items.RowConflicts) { actTab = &actionTableData{ - Rows: make([]*actRow, itemSets.Size()), + Rows: make([]*actRow, itemSets.Size()), + CdTokenFunctions: make([]string, len(tokMap.TypeMap)), } conflicts = make(map[int]items.RowConflicts) var row *actRow @@ -67,225 +75,98 @@ func getActionTableData(prods ast.SyntaxProdList, itemSets *items.ItemSets, return } +type cdActionFunc struct { + TokenType int + TokenFunc string +} + type actRow struct { CanRecover bool Actions []string + CdActions []cdActionFunc } func getActionRowData(prods ast.SyntaxProdList, set *items.ItemSet, tokMap *token.TokenMap) (data *actRow, conflicts items.RowConflicts) { data = &actRow{ CanRecover: set.CanRecover(), Actions: make([]string, len(tokMap.TypeMap)), + CdActions: []cdActionFunc{}, } conflicts = make(items.RowConflicts) - var max int // calculate padding. - for _, sym := range tokMap.TypeMap { - act, _ := set.Action(sym) - switch act1 := act.(type) { - case action.Accept: - n := len("accept(true),") - if n > max { - max = n - } - case action.Error: - n := len("nil,") - if n > max { - max = n - } - case action.Reduce: - n := len("reduce(") + nbytes(int(act1)) + len("),") - if n > max { - max = n - } - case action.Shift: - n := len("shift(") + nbytes(int(act1)) + len("),") - if n > max { - max = n - } - default: - panic(fmt.Sprintf("Unknown action type: %T", act1)) - } - } for i, sym := range tokMap.TypeMap { act, symConflicts := set.Action(sym) if len(symConflicts) > 0 { conflicts[sym] = symConflicts } + checkNonDeterministic := false switch act1 := act.(type) { case action.Accept: - pad := max + 1 - len("accept(true),") - data.Actions[i] = fmt.Sprintf("accept(true),%*c// %s", pad, ' ', sym) + data.Actions[i] = fmt.Sprintf("accept(true), // %s", sym) case action.Error: - pad := max + 1 - len("nil,") - data.Actions[i] = fmt.Sprintf("nil,%*c// %s", pad, ' ', sym) + data.Actions[i] = fmt.Sprintf("nil, // %s", sym) case action.Reduce: - pad := max + 1 - (len("reduce(") + nbytes(int(act1)) + len("),")) - data.Actions[i] = fmt.Sprintf("reduce(%d),%*c// %s, reduce: %s", int(act1), pad, ' ', sym, prods[int(act1)].Id) + data.Actions[i] = fmt.Sprintf("reduce(%d), // %s, reduce: %s", int(act1), sym, prods[int(act1)].Id) + checkNonDeterministic = true case action.Shift: - pad := max + 1 - (len("shift(") + nbytes(int(act1)) + len("),")) - data.Actions[i] = fmt.Sprintf("shift(%d),%*c// %s", int(act1), pad, ' ', sym) + data.Actions[i] = fmt.Sprintf("shift(%d), // %s", int(act1), sym) + checkNonDeterministic = true default: panic(fmt.Sprintf("Unknown action type: %T", act1)) } - } - return -} - -const actionTableSrc = ` -// Code generated by gocc; DO NOT EDIT. - -package parser - -type ( - actionTable [numStates]actionRow - actionRow struct { - canRecover bool - actions [numSymbols]action - } -) - -var actionTab = actionTable{ - {{- range $i, $r := .Rows }} - actionRow{ // S{{$i}} - canRecover: {{printf "%t" .CanRecover}}, - actions: [numSymbols]action{ - {{- range $a := .Actions }} - {{$a}} - {{- end }} - }, - }, - {{- end }} -} -` - -func GenCompActionTable(outDir string, prods ast.SyntaxProdList, itemSets *items.ItemSets, tokMap *token.TokenMap) map[int]items.RowConflicts { - tab := make([]struct { - CanRecover bool - Actions []struct { - Index int - Action int - Amount int - } - }, itemSets.Size()) - conflictss := make(map[int]items.RowConflicts) - for i := range tab { - set := itemSets.Set(i) - tab[i].CanRecover = set.CanRecover() - conflicts := make(items.RowConflicts) - for j, sym := range tokMap.TypeMap { - act, symConflicts := set.Action(sym) - if len(symConflicts) > 0 { - conflicts[sym] = symConflicts + if checkNonDeterministic { + switch s := sym.(type) { + case ast.SyntaxContextDependentTokId, ast.SyntaxSubParser: + data.CdActions = append(data.CdActions, cdActionFunc{ + i, + fmt.Sprintf("cdFunc_%s", s.SymbolString()), + }) } - switch act1 := act.(type) { - case action.Accept: - tab[i].Actions = append(tab[i].Actions, struct { - Index int - Action int - Amount int - }{Index: j, Action: 0, Amount: 0}) - case action.Error: - // skip - case action.Reduce: - tab[i].Actions = append(tab[i].Actions, struct { - Index int - Action int - Amount int - }{Index: j, Action: 1, Amount: int(act1)}) - case action.Shift: - tab[i].Actions = append(tab[i].Actions, struct { - Index int - Action int - Amount int - }{Index: j, Action: 2, Amount: int(act1)}) - default: - panic(fmt.Sprintf("Unknown action type: %T", act1)) - } - } - if len(conflicts) > 0 { - conflictss[i] = conflicts } } - bytesStr := genEnc(tab) - tmpl, err := template.New("parser action table").Parse(actionCompTableSrc[1:]) - if err != nil { - panic(err) - } - wr := new(bytes.Buffer) - if err := tmpl.Execute(wr, bytesStr); err != nil { - panic(err) - } - io.WriteFile(path.Join(outDir, "parser", "actiontable.go"), wr.Bytes()) - return conflictss + return } -const actionCompTableSrc = ` +const actionTableSrc = ` // Code generated by gocc; DO NOT EDIT. package parser -import ( - "bytes" - "compress/gzip" - "encoding/gob" -) type ( actionTable [numStates]actionRow + cdFunc func(TokenStream, interface{}) (interface{}, error, []byte) + cdAction struct { + tokenIndex int + tokenScanner cdFunc + } actionRow struct { canRecover bool actions [numSymbols]action + cdActions []cdAction } + actions struct { + table actionTable + } ) - -var actionTab = actionTable{} - -func init() { - tab := []struct { - CanRecover bool - Actions []struct { - Index int - Action int - Amount int - } - }{} - data := {{.}} - buf, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - panic(err) - } - dec := gob.NewDecoder(buf) - if err := dec.Decode(&tab); err != nil { - panic(err) - } - - for i, row := range tab { - actionTab[i].canRecover = row.CanRecover - for _, a := range row.Actions { - switch a.Action { - case 0: - actionTab[i].actions[a.Index] = accept(true) - case 1: - actionTab[i].actions[a.Index] = reduce(a.Amount) - case 2: - actionTab[i].actions[a.Index] = shift(a.Amount) - } - } - } +var parserActions = actions { + table: actionTable{ + {{- range $i, $r := .Table.Rows }} + actionRow{ // S{{$i}} + canRecover: {{printf "%t" .CanRecover}}, + actions: [numSymbols]action{ + {{- range $a := .Actions }} + {{$a}} + {{- end }} + }, + cdActions: []cdAction{ + {{- range $c := .CdActions }} + cdAction{tokenIndex: {{$c.TokenType}}, tokenScanner: {{$c.TokenFunc}} }, + {{- end }} + }, + }, + {{- end }} + }, } -` -// nbytes returns the number of bytes required to output the integer x. -func nbytes(x int) int { - if x == 0 { - return 1 - } - n := 0 - if x < 0 { - x = -x - n++ - } - n += int(math.Log10(float64(x))) + 1 - return n -} +` diff --git a/internal/parser/gen/golang/errors.go b/internal/parser/gen/golang/errors.go index 965ba7cc..5df611d0 100644 --- a/internal/parser/gen/golang/errors.go +++ b/internal/parser/gen/golang/errors.go @@ -18,19 +18,19 @@ import ( "path" "text/template" - "github.com/goccmack/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/io" ) -func GenErrors(pkg, outDir string) { +func GenErrors(pkg, outDir, subpath string) { tmpl, err := template.New("parser errors").Parse(errorsSrc[1:]) if err != nil { panic(err) } wr := new(bytes.Buffer) - if err := tmpl.Execute(wr, path.Join(pkg, "token")); err != nil { + if err := tmpl.Execute(wr, path.Join(pkg, subpath, "token")); err != nil { panic(err) } - io.WriteFile(path.Join(outDir, "errors", "errors.go"), wr.Bytes()) + io.WriteFile(path.Join(outDir, subpath, "errors", "errors.go"), wr.Bytes()) } const errorsSrc = ` diff --git a/internal/parser/gen/golang/gototable.go b/internal/parser/gen/golang/gototable.go index a4af8b93..1eafcc09 100644 --- a/internal/parser/gen/golang/gototable.go +++ b/internal/parser/gen/golang/gototable.go @@ -22,9 +22,9 @@ import ( "path" "text/template" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/parser/lr1/items" - "github.com/goccmack/gocc/internal/parser/symbols" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/items" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" ) type gotoTableData struct { @@ -35,14 +35,9 @@ type gotoTableData struct { type gotoRowElement struct { NT string State int - Pad int } -func GenGotoTable(outDir string, itemSets *items.ItemSets, sym *symbols.Symbols, zip bool) { - if zip { - GenCompGotoTable(outDir, itemSets, sym) - return - } +func GenGotoTable(outDir string, itemSets *items.ItemSets, sym *symbols.Symbols, subpath string) { tmpl, err := template.New("parser goto table").Parse(gotoTableSrc[1:]) if err != nil { panic(err) @@ -51,7 +46,7 @@ func GenGotoTable(outDir string, itemSets *items.ItemSets, sym *symbols.Symbols, if err := tmpl.Execute(wr, getGotoTableData(itemSets, sym)); err != nil { panic(err) } - io.WriteFile(path.Join(outDir, "parser", "gototable.go"), wr.Bytes()) + io.WriteFile(path.Join(outDir, subpath, "parser", "gototable.go"), wr.Bytes()) } func getGotoTableData(itemSets *items.ItemSets, sym *symbols.Symbols) *gotoTableData { @@ -67,18 +62,9 @@ func getGotoTableData(itemSets *items.ItemSets, sym *symbols.Symbols) *gotoTable func getGotoRowData(itemSet *items.ItemSet, sym *symbols.Symbols) []gotoRowElement { row := make([]gotoRowElement, sym.NumNTSymbols()) - var max int for i, nt := range sym.NTList() { - row[i].NT = nt + row[i].NT = nt.SymbolName() row[i].State = itemSet.NextSetIndex(nt) - n := nbytes(row[i].State) - if n > max { - max = n - } - } - // Calculate padding. - for i := range row { - row[i].Pad = max + 1 - nbytes(row[i].State) } return row } @@ -99,7 +85,7 @@ var gotoTab = gotoTable{ {{- range $i, $r := .Rows }} gotoRow{ // S{{$i}} {{- range $j, $gto := . }} - {{ printf "%d,%*c// %s" $gto.State $gto.Pad ' ' $gto.NT }} + {{ printf "%d, // %s" $gto.State $gto.NT }} {{- end }} }, {{- end }} @@ -137,70 +123,3 @@ func genEnc(v interface{}) string { fmt.Fprintf(strBuf, "\t}") return string(strBuf.Bytes()) } - -func GenCompGotoTable(outDir string, itemSets *items.ItemSets, sym *symbols.Symbols) { - numNTSymbols := sym.NumNTSymbols() - rows := make([][]int, itemSets.Size()) - for i, set := range itemSets.List() { - rows[i] = make([]int, numNTSymbols) - for j, nt := range sym.NTList() { - rows[i][j] = set.NextSetIndex(nt) - } - } - bytesStr := genEnc(rows) - v := struct { - NumNTSymbols int - Bytes string - }{ - NumNTSymbols: numNTSymbols, - Bytes: bytesStr, - } - tmpl, err := template.New("parser goto table").Parse(gotoTableCompSrc[1:]) - if err != nil { - panic(err) - } - wr := new(bytes.Buffer) - if err := tmpl.Execute(wr, v); err != nil { - panic(err) - } - io.WriteFile(path.Join(outDir, "parser", "gototable.go"), wr.Bytes()) -} - -const gotoTableCompSrc = ` -// Code generated by gocc; DO NOT EDIT. - -package parser - -import ( - "bytes" - "compress/gzip" - "encoding/gob" -) - -const numNTSymbols = {{.NumNTSymbols}} - -type ( - gotoTable [numStates]gotoRow - gotoRow [numNTSymbols]int -) - -var gotoTab = gotoTable{} - -func init() { - tab := [][]int{} - data := {{.Bytes}} - buf, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - panic(err) - } - dec := gob.NewDecoder(buf) - if err := dec.Decode(&tab); err != nil { - panic(err) - } - for i := 0; i < numStates; i++ { - for j := 0; j < numNTSymbols; j++ { - gotoTab[i][j] = tab[i][j] - } - } -} -` diff --git a/internal/parser/gen/golang/parser.go b/internal/parser/gen/golang/parser.go index f417cd44..0bcafe74 100644 --- a/internal/parser/gen/golang/parser.go +++ b/internal/parser/gen/golang/parser.go @@ -16,46 +16,77 @@ package golang import ( "bytes" + "fmt" + "go/format" "path" "text/template" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/config" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/parser/lr1/items" - "github.com/goccmack/gocc/internal/parser/symbols" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/items" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" ) -func GenParser(pkg, outDir string, prods ast.SyntaxProdList, itemSets *items.ItemSets, symbols *symbols.Symbols, cfg config.Config) { +func GenParser(pkg, outDir string, prods ast.SyntaxProdList, itemSets *items.ItemSets, symbols *symbols.Symbols, cfg config.Config, internal, iface string) { tmpl, err := template.New("parser").Parse(parserSrc[1:]) if err != nil { panic(err) } wr := new(bytes.Buffer) - if err := tmpl.Execute(wr, getParserData(pkg, prods, itemSets, symbols, cfg)); err != nil { + if err := tmpl.Execute(wr, getParserData(pkg, internal, iface, prods, itemSets, symbols, cfg)); err != nil { panic(err) } - io.WriteFile(path.Join(outDir, "parser", "parser.go"), wr.Bytes()) + source, err := format.Source(wr.Bytes()) + if err != nil { + panic(fmt.Sprintf("%s in\n%s", err.Error(), wr.String())) + } + io.WriteFile(path.Join(outDir, internal, "parser", "parser.go"), source) } type parserData struct { Debug bool - ErrorImport string - TokenImport string + PkgPath string + InternalSubdir string + IfaceSubdir string + Config config.Config NumProductions int NumStates int NumSymbols int + CdTokList ast.SyntaxSymbols + CdSubList ast.SyntaxSymbols + CdSubImports map[string]string + ErrorTokenName string + MyName string } -func getParserData(pkg string, prods ast.SyntaxProdList, itemSets *items.ItemSets, symbols *symbols.Symbols, cfg config.Config) *parserData { - return &parserData{ +func getParserData(pkg, internal, iface string, prods ast.SyntaxProdList, itemSets *items.ItemSets, symbols *symbols.Symbols, cfg config.Config) *parserData { + ret := &parserData{ Debug: cfg.DebugParser(), - ErrorImport: path.Join(pkg, "errors"), - TokenImport: path.Join(pkg, "token"), + PkgPath: pkg, + InternalSubdir: internal, + IfaceSubdir: iface, + Config: cfg, NumProductions: len(prods), NumStates: itemSets.Size(), NumSymbols: symbols.NumSymbols(), + CdTokList: symbols.ListContextDependentTokenSymbols(), + CdSubList: symbols.ListSubParserSymbols(), + CdSubImports: map[string]string{}, + ErrorTokenName: config.INTERNAL_SYMBOL_ERROR, + MyName: cfg.ProjectName(), + } + for _, sym := range ret.CdSubList { + sub := sym.(ast.SyntaxSubParser) + if imp, found := ret.CdSubImports[sub.Alias]; found { + if imp != sub.Import { + panic(fmt.Sprintf("alias %s cannot refer to %s, already used by %s", sub.Alias, sub.Import, imp)) + } + } else { + ret.CdSubImports[sub.Alias] = sub.Import + } } + return ret } const parserSrc = ` @@ -66,9 +97,16 @@ package parser import ( "fmt" "strings" + "errors" + + parseError "{{.PkgPath}}/{{.InternalSubdir}}/errors" + "{{.PkgPath}}/{{.InternalSubdir}}/token" + "{{.PkgPath}}/{{.IfaceSubdir}}" + + {{ range $alias, $import := .CdSubImports }} + {{$alias}} "{{$import}}" + {{end}} - parseError "{{.ErrorImport}}" - "{{.TokenImport}}" ) const ( @@ -84,12 +122,12 @@ type stack struct { attrib []Attrib } -const iNITIAL_STACK_SIZE = 100 +const INITIAL_STACK_SIZE = 100 func newStack() *stack { return &stack{ - state: make([]int, 0, iNITIAL_STACK_SIZE), - attrib: make([]Attrib, 0, iNITIAL_STACK_SIZE), + state: make([]int, 0, INITIAL_STACK_SIZE), + attrib: make([]Attrib, 0, INITIAL_STACK_SIZE), } } @@ -149,17 +187,63 @@ func (s *stack) String() string { // Parser type Parser struct { - stack *stack - nextToken *token.Token - pos int + stack *stack + nextToken *token.Token + userContext interface{} + + // + // Working data, should be method parameters/locals + // but putting them here simplifies a bit the code + // Useful only for longest prefix partial parsing + // + needsRepositioning bool + isNonDeterministic bool + tokens iface.CheckPointable + afterPos iface.CheckPoint + checkPoint iface.CheckPoint + underlyingStream iface.TokenStream +} + +type TokenStream = iface.TokenStream + +type ( + fakeCp struct{} + fakeCheckPointable struct{} +) + +func (f fakeCheckPointable) GetCheckPoint() iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCp) DistanceFrom(o iface.CheckPoint) int { + return 0 +} + +func (f fakeCp) Advance (o int) iface.CheckPoint { + return fakeCp{} +} + +func (f fakeCheckPointable) GotoCheckPoint(iface.CheckPoint) {} + +{{ range $c := .CdTokList }} +func {{ printf "cdFunc_%s" $c.SymbolString }} (Stream TokenStream, Context interface{}) (interface{}, error, []byte) { + return {{ $c.ContexDependentParseFunctionCall }} } +{{ end }} -type Scanner interface { - Scan() (tok *token.Token) +{{ range $c := .CdSubList }} +func {{ printf "cdFunc_%s" $c.SymbolString }} (Stream TokenStream, Context interface{}) (interface{}, error, []byte) { + return {{$c.Alias}}.ParseWithDataPartial(Stream, Context) } +{{ end }} + func NewParser() *Parser { - p := &Parser{stack: newStack()} + return NewParserWithContext(nil) +} + +func NewParserWithContext(u interface{}) *Parser { + p := &Parser{stack: newStack(), userContext: u } p.Reset() return p } @@ -169,31 +253,40 @@ func (p *Parser) Reset() { p.stack.push(0, nil) } -func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib *parseError.Error) { +func (p *Parser) SetContext (ctx interface{}) *Parser { + p.userContext = ctx + return p +} + +func (p Parser) GetContext () interface{} { + return p.userContext +} + +func (p *Parser) Error(err error, scanner iface.Scanner) (recovered bool, errorAttrib *parseError.Error) { errorAttrib = &parseError.Error{ Err: err, ErrorToken: p.nextToken, ErrorSymbols: p.popNonRecoveryStates(), ExpectedTokens: make([]string, 0, 8), } - for t, action := range actionTab[p.stack.top()].actions { + for t, action := range parserActions.table[p.stack.top()].actions { if action != nil { errorAttrib.ExpectedTokens = append(errorAttrib.ExpectedTokens, token.TokMap.Id(token.Type(t))) } } - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { + if action := parserActions.table[p.stack.top()].actions[token.TokMap.Type("{{.ErrorTokenName}}")]; action != nil { p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift } else { return } - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { recovered = true } for !recovered && p.nextToken.Type != token.EOF { p.nextToken = scanner.Scan() - if action := actionTab[p.stack.top()].actions[p.nextToken.Type]; action != nil { + if action := parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action != nil { recovered = true } } @@ -216,10 +309,10 @@ func (p *Parser) popNonRecoveryStates() (removedAttribs []parseError.ErrorSymbol // recoveryState points to the highest state on the stack, which can recover func (p *Parser) firstRecoveryState() (recoveryState int, canRecover bool) { - recoveryState, canRecover = p.stack.topIndex(), actionTab[p.stack.top()].canRecover + recoveryState, canRecover = p.stack.topIndex(), parserActions.table[p.stack.top()].canRecover for recoveryState > 0 && !canRecover { recoveryState-- - canRecover = actionTab[p.stack.peek(recoveryState)].canRecover + canRecover = parserActions.table[p.stack.peek(recoveryState)].canRecover } return } @@ -230,7 +323,7 @@ func (p *Parser) newError(err error) error { StackTop: p.stack.top(), ErrorToken: p.nextToken, } - actRow := actionTab[p.stack.top()] + actRow := parserActions.table[p.stack.top()] for i, t := range actRow.actions { if t != nil { e.ExpectedTokens = append(e.ExpectedTokens, token.TokMap.Id(token.Type(i))) @@ -239,22 +332,130 @@ func (p *Parser) newError(err error) error { return e } -func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { +func (p *Parser) prepareParsing(scanner iface.Scanner, longest bool) error { p.Reset() - p.nextToken = scanner.Scan() + {{- if and (eq (len .CdTokList) 0) (eq (len .CdSubList) 0) }} + p.needsRepositioning = longest + p.isNonDeterministic = false + {{- else }} + p.needsRepositioning = true + p.isNonDeterministic = true + {{- end }} + if p.needsRepositioning { + if streamScanner, _ := scanner.(iface.StreamScanner) ; streamScanner != nil { + p.underlyingStream = streamScanner.GetStream() + } + if p.tokens, _ = scanner.(iface.CheckPointable) ; p.tokens == nil || p.underlyingStream == nil { + return errNotRepositionable + } + } else { + if p.tokens, _ = scanner.(iface.CheckPointable) ; p.tokens == nil { + p.tokens = fakeCheckPointable{} + } + } + return nil +} + +func (p *Parser) Parse(scanner iface.Scanner) (res interface{}, err error) { + if err := p.prepareParsing (scanner, false); err != nil { + return nil, err + } + return p.parse(scanner, false) +} + +func (p *Parser) ParseLongestPrefix(scanner iface.Scanner) (res interface{}, err error, parsed []byte) { + if err := p.prepareParsing (scanner, true); err != nil { + return nil, err, []byte{} + } + startPoint := p.tokens.GetCheckPoint() + res, err = p.parse(scanner, true) + if err == nil { + currPoint := p.tokens.GetCheckPoint() + p.tokens.GotoCheckPoint(startPoint) + parsed = make([]byte, currPoint.DistanceFrom(startPoint)) + p.underlyingStream.Read(parsed) + p.tokens.GotoCheckPoint(currPoint) + } + return +} + +var errNotRepositionable = errors.New("scanner not repositionable") + + +func (p *Parser) parse(scanner iface.Scanner, longest bool) (res interface{}, err error) { + readNextToken := func () { + p.checkPoint = p.tokens.GetCheckPoint() + p.nextToken = scanner.Scan() + p.afterPos = p.tokens.GetCheckPoint() + return + } + readNextToken() for acc := false; !acc; { - action := actionTab[p.stack.top()].actions[p.nextToken.Type] - if action == nil { + action := parserActions.table[p.stack.top()].actions[p.nextToken.Type] + if action == nil && p.isNonDeterministic { + // + // If no action, check if we have some context dependent parsing to try + // + p.checkPoint = p.checkPoint.Advance(len(p.nextToken.IgnoredPrefix)) + {{- if .Debug }} + fmt.Printf("{{.MyName}}:parser:S%d advanced %d bytes because of prefix <%s> of token <%s>\n", p.stack.top(), len(p.nextToken.IgnoredPrefix), string(p.nextToken.IgnoredPrefix), string(p.nextToken.Lit)) + {{- end }} + for _, cdAction := range parserActions.table[p.stack.top()].cdActions { + {{- if .Debug }} + fmt.Printf("{{.MyName}}:parser:S%d trying=<%#v> \n", p.stack.top(), cdAction) + {{- end }} + p.tokens.GotoCheckPoint(p.checkPoint) + cd_res, cd_err, cd_parsed := cdAction.tokenScanner(p.underlyingStream, p.userContext) + if cd_err == nil && len(cd_parsed) > 0 { + action = parserActions.table[p.stack.top()].actions[cdAction.tokenIndex] + if action != nil { + p.nextToken.Foreign = true + p.nextToken.ForeignAstNode = cd_res + p.nextToken.Lit = cd_parsed + p.nextToken.Type = token.Type(cdAction.tokenIndex) + {{- if .Debug }} + fmt.Printf("{{.MyName}}:parser:S%d got pseudo token=<%s> \n", p.stack.top(), string(p.nextToken.Lit)) + {{- end }} + break + } + } + } + } + // + // Still no action? If a longest possible parsing is requested in place + // of a full text, we should try to check if an EOF here would have led + // to a successful parsing instead + // Rember that token.EOF is 1, that is the index of SyntaxEof into symbol table + // Dirty, dirty, dirty... but I found it as it is, and I prefer not to touch + // + if action == nil && longest { + p.tokens.GotoCheckPoint(p.checkPoint) + action = parserActions.table[p.stack.top()].actions[token.EOF] + if action == nil { + // + // ok, let's consume the token then + // + {{- if .Debug }} + fmt.Printf("{{.MyName}}:parser:S%d unrecognized=<%#v> restoring checkpoint at %#v => %s\n", p.stack.top(), p.nextToken, p.afterPos, action) + {{- end }} + p.tokens.GotoCheckPoint(p.afterPos) + } + } + + // + // Well, no action is no action after all... + // + if action == nil { if recovered, errAttrib := p.Error(nil, scanner); !recovered { p.nextToken = errAttrib.ErrorToken return nil, p.newError(nil) } - if action = actionTab[p.stack.top()].actions[p.nextToken.Type]; action == nil { + if action = parserActions.table[p.stack.top()].actions[p.nextToken.Type]; action == nil { panic("Error recovery led to invalid action") } - } + } {{- if .Debug }} - fmt.Printf("S%d %s %s\n", p.stack.top(), token.TokMap.TokenString(p.nextToken), action) + fmt.Printf("{{.MyName}}:parser:S%d %s %s\n", p.stack.top(), token.TokMap.TokenString(p.nextToken), action) {{- end }} switch act := action.(type) { @@ -262,11 +463,14 @@ func (p *Parser) Parse(scanner Scanner) (res interface{}, err error) { res = p.stack.popN(1)[0] acc = true case shift: - p.stack.push(int(act), p.nextToken) - p.nextToken = scanner.Scan() + p.stack.push(int(act), p.nextToken) + if p.nextToken.Foreign { + p.stack.push(int(act), p.nextToken.ForeignAstNode) + } + readNextToken() case reduce: prod := productionsTable[int(act)] - attrib, err := prod.ReduceFunc(p.stack.popN(prod.NumSymbols)) + attrib, err := prod.ReduceFunc(p.userContext, p.stack.popN(prod.NumSymbols)) if err != nil { return nil, p.newError(err) } else { diff --git a/internal/parser/gen/golang/productionstable.go b/internal/parser/gen/golang/productionstable.go index cbcce7a4..91670b99 100644 --- a/internal/parser/gen/golang/productionstable.go +++ b/internal/parser/gen/golang/productionstable.go @@ -17,29 +17,43 @@ package golang import ( "bytes" "fmt" + "go/format" "path" + "regexp" "text/template" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/parser/lr1/items" - "github.com/goccmack/gocc/internal/parser/symbols" - "github.com/goccmack/gocc/internal/token" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/items" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" + "github.com/maxcalandrelli/gocc/internal/token" ) func GenProductionsTable(pkg, outDir, header string, prods ast.SyntaxProdList, symbols *symbols.Symbols, - itemsets *items.ItemSets, tokMap *token.TokenMap) { + itemsets *items.ItemSets, tokMap *token.TokenMap, internal string, cfg config.Config) { - fname := path.Join(outDir, "parser", "productionstable.go") + fname := path.Join(outDir, internal, "parser", "productionstable.go") tmpl, err := template.New("parser productions table").Parse(prodsTabSrc[1:]) if err != nil { panic(err) } wr := new(bytes.Buffer) - if err := tmpl.Execute(wr, getProdsTab(header, prods, symbols, itemsets, tokMap)); err != nil { + pTab := getProdsTab(header, prods, symbols, itemsets, tokMap) + pTab.Pkg = pkg + pTab.Outdir = outDir + pTab.InternalDir = internal + pTab.Config = cfg + + if err := tmpl.Execute(wr, pTab); err != nil { panic(err) } - io.WriteFile(fname, wr.Bytes()) + + source, err := format.Source(wr.Bytes()) + if err != nil { + panic(fmt.Sprintf("%s in\n%s", err.Error(), wr.String())) + } + io.WriteFile(fname, source) } func getProdsTab(header string, prods ast.SyntaxProdList, symbols *symbols.Symbols, @@ -51,17 +65,23 @@ func getProdsTab(header string, prods ast.SyntaxProdList, symbols *symbols.Symbo } for i, prod := range prods { data.ProdTab[i].String = fmt.Sprintf("`%s`", prod.String()) - data.ProdTab[i].Id = prod.Id - data.ProdTab[i].NTType = symbols.NTType(prod.Id) - isEmpty := prod.Body.Symbols[0].SymbolString() == "empty" + data.ProdTab[i].Id = prod.Id.SymbolString() + data.ProdTab[i].NTType = symbols.NTType(prod.Id.SymbolString()) + isEmpty := prod.Body.Empty() if isEmpty { data.ProdTab[i].NumSymbols = 0 } else { data.ProdTab[i].NumSymbols = len(prod.Body.Symbols) + for _, s := range prod.Body.Symbols { + switch s.(type) { + case ast.SyntaxContextDependentTokId, ast.SyntaxSubParser: + data.ProdTab[i].NumSymbols++ + } + } } switch { case len(prod.Body.SDT) > 0: - data.ProdTab[i].ReduceFunc = fmt.Sprintf("return %s", prod.Body.SDT) + data.ProdTab[i].ReduceFunc = fmt.Sprintf("return %s", sdtReplacer.ReplaceAllStringFunc(prod.Body.SDT, sdtReplacerFunc)) case isEmpty: // Empty production with no semantic action. data.ProdTab[i].ReduceFunc = "return nil, nil" @@ -73,17 +93,47 @@ func getProdsTab(header string, prods ast.SyntaxProdList, symbols *symbols.Symbo return data } +var ( + sdtReplacer = regexp.MustCompile("\\$[0-9]+[sqeUl]*") + sdtReplacerSplit = regexp.MustCompile("^\\$([0-9]+)([sqeUl]*)$") +) + +func sdtReplacerFunc(match string) string { + result, funcs := func(s []string) (string, string) { return fmt.Sprintf("X[%s]", s[0]), s[1] }(sdtReplacerSplit.FindStringSubmatch(match)[1:]) + if funcs > "" { + result = fmt.Sprintf("getString(%s)", result) + } + for _, op := range funcs { + switch op { + case 'q': + result = fmt.Sprintf("unquote(%s)", result) + case 'U': + result = fmt.Sprintf("uc(%s)", result) + case 'e': + result = fmt.Sprintf("unescape(%s)", result) + case 'l': + result = fmt.Sprintf("lc(%s)", result) + } + } + return result +} + type prodsTabData struct { - Header string - ProdTab []prodTabEntry + Header string + ProdTab []prodTabEntry + Pkg string + Outdir string + InternalDir string + Config config.Config } type prodTabEntry struct { - String string - Id string - NTType int - NumSymbols int - ReduceFunc string + String string + Id string + NTType int + NumSymbols int + ReduceFunc string + TokenImport string } const prodsTabSrc = ` @@ -91,8 +141,42 @@ const prodsTabSrc = ` package parser +import ( + + "fmt" + "strings" + "{{.Config.Package}}/{{.InternalDir}}/token" + "{{.Config.Package}}/{{.InternalDir}}/util" +) + {{.Header}} +func getString(X Attrib) string { + switch X.(type) { + case *token.Token: return string(X.(*token.Token).Lit) + case string: return X.(string) + } + return fmt.Sprintf("%q", X) +} + +func unescape(s string) string { + return util.EscapedString(s).Unescape() +} + +func unquote(s string) string { + r, _, _ := util.EscapedString(s).Unquote() + return r +} + +func lc(s string) string { + return strings.ToLower(s) +} + +func uc(s string) string { + return strings.ToUpper(s) +} + + type ( //TODO: change type and variable names to be consistent with other tables ProdTab [numProductions]ProdTabEntry @@ -102,7 +186,7 @@ type ( NTType int Index int NumSymbols int - ReduceFunc func([]Attrib) (Attrib, error) + ReduceFunc func(interface{}, []Attrib) (Attrib, error) } Attrib interface { } @@ -116,7 +200,7 @@ var productionsTable = ProdTab{ NTType: {{$entry.NTType}}, Index: {{$i}}, NumSymbols: {{$entry.NumSymbols}}, - ReduceFunc: func(X []Attrib) (Attrib, error) { + ReduceFunc: func(Context interface{}, X []Attrib) (Attrib, error) { {{$entry.ReduceFunc}} }, }, diff --git a/internal/parser/lr1/items/item.go b/internal/parser/lr1/items/item.go index e0349cd2..8978c2fc 100644 --- a/internal/parser/lr1/items/item.go +++ b/internal/parser/lr1/items/item.go @@ -18,27 +18,29 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/parser/lr1/action" + "github.com/maxcalandrelli/gocc/internal/config" + + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/action" ) //An LR1 Item. type Item struct { ProdIdx int // index in list of productions in Grammar.Prod Prod *ast.SyntaxProd // The syntax production of this item - Id string - Body []string - Pos int // position of • in the item - ExpectedSymbol string // the next exptect symbol in the item, if this isn't a reduce item. - FollowingSymbol string // The next expected symbol after the item has been recognised - Len int // the number of symbols making up the body + Id ast.SyntaxSymbol + Body ast.SyntaxSymbols + Pos int // position of • in the item + ExpectedSymbol ast.SyntaxSymbol // the next expected symbol in the item, if this isn't a reduce item. + FollowingSymbol ast.SyntaxSymbol // The next expected symbol after the item has been recognised + Len int // the number of symbols making up the body str string } /* following symbol: the symbol expected after this item has been reduced */ -func NewItem(prodIdx int, prod *ast.SyntaxProd, pos int, followingSymbol string) *Item { +func NewItem(prodIdx int, prod *ast.SyntaxProd, pos int, followingSymbol ast.SyntaxSymbol) *Item { item := &Item{ ProdIdx: prodIdx, Prod: prod, @@ -46,7 +48,7 @@ func NewItem(prodIdx int, prod *ast.SyntaxProd, pos int, followingSymbol string) Pos: pos, FollowingSymbol: followingSymbol, } - if prod.Body.Symbols[0].SymbolString() == "empty" { + if prod.Body.Empty() { item.Len = 0 } else { item.Len = len(prod.Body.Symbols) @@ -54,34 +56,31 @@ func NewItem(prodIdx int, prod *ast.SyntaxProd, pos int, followingSymbol string) if pos > item.Len { panic(fmt.Sprintf("%s : %s, pos=%d", item.Id, item.Body, item.Pos)) } - item.Body = make([]string, item.Len) + item.Body = make(ast.SyntaxSymbols, item.Len) if item.Len > 0 { for i, sym := range prod.Body.Symbols { - item.Body[i] = sym.SymbolString() + item.Body[i] = sym } } if item.Len > 0 && item.Pos < item.Len { item.ExpectedSymbol = item.Body[item.Pos] } else { - item.ExpectedSymbol = "" + item.ExpectedSymbol = nil } item.str = item.getString() return item } -func (this *Item) accept(sym string) bool { - return this.ProdIdx == 0 && - this.Pos >= this.Len && - this.FollowingSymbol == "$" && - sym == "$" +func (this *Item) accept(sym ast.SyntaxSymbol) bool { + return this.ProdIdx == 0 && this.Pos >= this.Len && ast.EofSymbol == this.FollowingSymbol && ast.EofSymbol == sym } /* If the action is shift the next state is nextState */ -func (this *Item) action(sym string, nextState int) action.Action { +func (this *Item) action(sym ast.SyntaxSymbol, nextState int) action.Action { switch { - case sym == "INVALID": + case ast.InvalidSyntaxSymbol{} == sym: return action.ERROR case this.accept(sym): return action.ACCEPT @@ -94,7 +93,7 @@ func (this *Item) action(sym string, nextState int) action.Action { } func (this *Item) canRecover() bool { - return this.Len > 0 && this.Body[0] == "error" + return this.Len > 0 && ast.ErrorSymbol == this.Body[0] } //Returns whether two Items are equal based on their ProdIdx, Pos and NextToken. @@ -119,7 +118,7 @@ func (this *Item) reduce() bool { return this.Len == 0 || this.Pos >= this.Len } -func (this *Item) Symbol(i int) string { +func (this *Item) Symbol(i int) ast.SyntaxSymbol { return this.Body[i] } @@ -127,13 +126,13 @@ func (this *Item) getString() string { buf := new(strings.Builder) fmt.Fprintf(buf, "%s : ", this.Id) if this.Len == 0 { - fmt.Fprintf(buf, "empty") + fmt.Fprintf(buf, config.SYMBOL_EMPTY) } else { for i, s := range this.Body { if this.Pos == i { fmt.Fprintf(buf, "•") } - fmt.Fprintf(buf, s) + fmt.Fprintf(buf, s.SymbolName()) if i < this.Len-1 { fmt.Fprintf(buf, " ") } diff --git a/internal/parser/lr1/items/itemset.go b/internal/parser/lr1/items/itemset.go index 44b3c109..de757087 100644 --- a/internal/parser/lr1/items/itemset.go +++ b/internal/parser/lr1/items/itemset.go @@ -19,10 +19,10 @@ import ( "sort" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/parser/first" - "github.com/goccmack/gocc/internal/parser/lr1/action" - "github.com/goccmack/gocc/internal/parser/symbols" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/parser/first" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/action" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" ) type ItemSet struct { @@ -30,7 +30,7 @@ type ItemSet struct { imap map[string]*Item Items []*Item // string: symbol, int: nextState - Transitions map[string]int + Transitions map[ast.SyntaxSymbol]int Symbols *symbols.Symbols Prods ast.SyntaxProdList @@ -43,14 +43,14 @@ func NewItemSet(symbols *symbols.Symbols, prods ast.SyntaxProdList, fs *first.Fi SetNo: -1, imap: make(map[string]*Item), Items: make([]*Item, 0, 16), - Transitions: make(map[string]int), + Transitions: make(map[ast.SyntaxSymbol]int), Symbols: symbols, Prods: prods, FS: fs, } } -func (this *ItemSet) Action(symbol string) (act1 action.Action, conflicts []action.Action) { +func (this *ItemSet) Action(symbol ast.SyntaxSymbol) (act1 action.Action, conflicts []action.Action) { conflictMap := make(map[string]action.Action) act1 = action.ERROR for _, item := range this.Items { @@ -85,7 +85,7 @@ func (this *ItemSet) AddItem(items ...*Item) { } -func (this *ItemSet) AddTransition(symbol string, nextSet int) { +func (this *ItemSet) AddTransition(symbol ast.SyntaxSymbol, nextSet int) { if _, exist := this.Transitions[symbol]; exist { panic(fmt.Sprintf("Transition %s -> %d already exists", symbol, nextSet)) } @@ -101,7 +101,7 @@ func (this *ItemSet) CanRecover() bool { return false } -func (this *ItemSet) NextSetIndex(symbol string) int { +func (this *ItemSet) NextSetIndex(symbol ast.SyntaxSymbol) int { if nextSet, exist := this.Transitions[symbol]; exist { return nextSet } @@ -130,7 +130,7 @@ func (this *ItemSet) Closure() (c *ItemSet) { again = false for idx, i := range c.Items { if idx > included { - if i.Pos >= i.Len || this.Symbols.IsTerminal(i.ExpectedSymbol) { + if i.Pos >= i.Len || i.ExpectedSymbol.IsTerminal() { continue } for pi, prod := range this.Prods { @@ -182,18 +182,18 @@ func (this *ItemSet) Equal(that *ItemSet) bool { // first1 returns the characters contained within the first set, sorted in // alphabetical order. -func first1(firstSets *first.FirstSets, symbols []string, following string) []string { +func first1(firstSets *first.FirstSets, symbols ast.SyntaxSymbols, following ast.SyntaxSymbol) ast.SyntaxSymbols { firsts := first.FirstS(firstSets, append(symbols, following)) - var keys []string + keys := ast.SyntaxSymbolsByName{} for key := range firsts { keys = append(keys, key) } - sort.Strings(keys) - return keys + sort.Sort(&keys) + return ast.SyntaxSymbols(keys) } // Dragon book, 2nd ed, section 4.7.2, p261 -func (I *ItemSet) Goto(X string) *ItemSet { +func (I *ItemSet) Goto(X ast.SyntaxSymbol) *ItemSet { J := NewItemSet(I.Symbols, I.Prods, I.FS) for _, item := range I.Items { if item.Pos < item.Len && X == item.ExpectedSymbol { @@ -224,7 +224,7 @@ func (this *ItemSet) String() string { fmt.Fprintf(buf, "Transitions:\n") var keys transitions for sym, set := range this.Transitions { - key := transition{symbol: sym, nextState: set} + key := transition{symbol: sym.SymbolName(), nextState: set} keys = append(keys, key) } sort.Sort(keys) diff --git a/internal/parser/lr1/items/itemsets.go b/internal/parser/lr1/items/itemsets.go index 21e593ce..ff5e3ea5 100644 --- a/internal/parser/lr1/items/itemsets.go +++ b/internal/parser/lr1/items/itemsets.go @@ -18,9 +18,9 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/parser/first" - "github.com/goccmack/gocc/internal/parser/symbols" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/parser/first" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" ) //A list of a list of Items. @@ -118,6 +118,6 @@ func InitialItemSet(g *ast.Grammar, symbols *symbols.Symbols, fs *first.FirstSet set := NewItemSet(symbols, g.SyntaxPart.ProdList, fs) set.SetNo = 0 prod := g.SyntaxPart.ProdList[0] - set.AddItem(NewItem(0, prod, 0, "$")) + set.AddItem(NewItem(0, prod, 0, ast.EofSymbol)) return set } diff --git a/internal/parser/lr1/items/rowconflicts.go b/internal/parser/lr1/items/rowconflicts.go index 2a6ca010..2af790b5 100644 --- a/internal/parser/lr1/items/rowconflicts.go +++ b/internal/parser/lr1/items/rowconflicts.go @@ -15,11 +15,12 @@ package items import ( - "github.com/goccmack/gocc/internal/parser/lr1/action" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/parser/lr1/action" ) /* key: symbol value: list of actions */ -type RowConflicts map[string][]action.Action +type RowConflicts map[ast.SyntaxSymbol][]action.Action diff --git a/internal/parser/lr1/items/testdata_test.go b/internal/parser/lr1/items/testdata_test.go index 692c6bb1..2dfdfead 100644 --- a/internal/parser/lr1/items/testdata_test.go +++ b/internal/parser/lr1/items/testdata_test.go @@ -17,10 +17,10 @@ package items import ( "testing" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/frontend/parser" - "github.com/goccmack/gocc/internal/frontend/scanner" - "github.com/goccmack/gocc/internal/frontend/token" + "github.com/maxcalandrelli/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/frontend/stock/parser" + "github.com/maxcalandrelli/gocc/internal/frontend/stock/scanner" + "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" ) const G1 = ` diff --git a/internal/parser/symbols/symbols.go b/internal/parser/symbols/symbols.go index 518f268c..7b9ffd07 100644 --- a/internal/parser/symbols/symbols.go +++ b/internal/parser/symbols/symbols.go @@ -21,110 +21,112 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/ast" + "github.com/maxcalandrelli/gocc/internal/ast" ) type Symbols struct { - //key: symbol id - //val: symbol type - idMap map[string]int - - //key: symbol ntTypeMap index - //val: symbol type - ntIdMap map[string]int - ntTypeMap []string - - //key: symbol id - //val: symbol type - stringLitIdMap map[string]int - stringLitList []string - - //key: symbol type - //val: symbol id - typeMap []string + tSymbols ast.SyntaxSymbols + ntSymbols ast.SyntaxSymbols + symbols map[ast.SyntaxSymbol]struct{} + literalType map[string]int + nonTerminalType map[string]int } func NewSymbols(grammar *ast.Grammar) *Symbols { symbols := &Symbols{ - idMap: make(map[string]int), - typeMap: make([]string, 0, 16), - ntIdMap: make(map[string]int), - ntTypeMap: make([]string, 0, 16), - stringLitIdMap: make(map[string]int), - stringLitList: make([]string, 0, 16), + symbols: make(map[ast.SyntaxSymbol]struct{}), + tSymbols: make(ast.SyntaxSymbols, 0, 16), + ntSymbols: make(ast.SyntaxSymbols, 0, 16), + literalType: make(map[string]int), + nonTerminalType: make(map[string]int), } - symbols.Add("INVALID") - symbols.Add("$") + symbols.Add(ast.InvalidSyntaxSymbol{}) + symbols.Add(ast.EofSymbol) if grammar.SyntaxPart == nil { return symbols } for _, p := range grammar.SyntaxPart.ProdList { - if _, exist := symbols.ntIdMap[p.Id]; !exist { - symbols.ntTypeMap = append(symbols.ntTypeMap, p.Id) - symbols.ntIdMap[p.Id] = len(symbols.ntTypeMap) - 1 - } symbols.Add(p.Id) for _, sym := range p.Body.Symbols { - symStr := sym.SymbolString() - symbols.Add(symStr) - if _, ok := sym.(ast.SyntaxStringLit); ok { - if _, exist := symbols.ntIdMap[symStr]; exist { - panic(fmt.Sprintf("string_lit \"%s\" conflicts with production name %s", symStr, symStr)) - } - if _, exist := symbols.stringLitIdMap[symStr]; !exist { - symbols.stringLitIdMap[symStr] = symbols.Type(symStr) - symbols.stringLitList = append(symbols.stringLitList, symStr) - } - } + symbols.Add(sym) } } return symbols } -func (this *Symbols) Add(symbols ...string) { +func (this *Symbols) Add(symbols ...ast.SyntaxSymbol) { for _, sym := range symbols { - if _, exist := this.idMap[sym]; !exist { - this.typeMap = append(this.typeMap, sym) - this.idMap[sym] = len(this.typeMap) - 1 + if _, exist := this.symbols[sym]; !exist { + if sym.IsTerminal() { + id := len(this.tSymbols) + this.symbols[sym] = struct{}{} + this.tSymbols = append(this.tSymbols, sym) + this.literalType[sym.SymbolString()] = id + } else if sym.IsNonTerminal() { + id := len(this.ntSymbols) + this.symbols[sym] = struct{}{} + this.ntSymbols = append(this.ntSymbols, sym) + this.nonTerminalType[sym.SymbolString()] = id + } } } } -func (this *Symbols) Id(typ int) string { - return this.typeMap[typ] +func (this *Symbols) List() ast.SyntaxSymbols { + return append(this.ntSymbols, this.tSymbols...) +} + +func (this *Symbols) listMatchingSymbols(match func(ast.SyntaxSymbol) bool) ast.SyntaxSymbols { + res := make(ast.SyntaxSymbols, 0, 16) + for sym := range this.symbols { + if match(sym) { + res = append(res, sym) + } + } + return res } -func (this *Symbols) IsTerminal(sym string) bool { - _, nt := this.ntIdMap[sym] - return !nt +func (this *Symbols) ListContextDependentTokenSymbols() ast.SyntaxSymbols { + return this.listMatchingSymbols(func(s ast.SyntaxSymbol) bool { + switch s.(type) { + case ast.SyntaxContextDependentTokId: + return true + } + return false + }) } -func (this *Symbols) List() []string { - return this.typeMap +func (this *Symbols) ListSubParserSymbols() ast.SyntaxSymbols { + return this.listMatchingSymbols(func(s ast.SyntaxSymbol) bool { + switch s.(type) { + case ast.SyntaxSubParser: + return true + } + return false + }) } /* Return a slice containing the ids of all symbols declared as string literals in the grammar. */ -func (this *Symbols) ListStringLitSymbols() []string { - return this.stringLitList +func (this *Symbols) ListStringLitSymbols() ast.SyntaxSymbols { + return this.listMatchingSymbols(func(s ast.SyntaxSymbol) bool { + _, r := s.(ast.SyntaxStringLit) + return r + }) } -func (this *Symbols) ListTerminals() []string { - terminals := make([]string, 0, 16) - for _, sym := range this.typeMap { - if this.IsTerminal(sym) { - terminals = append(terminals, sym) - } - } - return terminals +func (this *Symbols) ListTerminals() ast.SyntaxSymbols { + ret := ast.SyntaxSymbolsByName(this.tSymbols) + //sort.Sort(&ret) + return ast.SyntaxSymbols(ret) } func (this *Symbols) StringLitType(id string) int { - if typ, exist := this.stringLitIdMap[id]; exist { + if typ, exist := this.literalType[id]; exist { return typ } return -1 @@ -134,31 +136,33 @@ func (this *Symbols) StringLitType(id string) int { Return the id of the NT with index idx, or "" if there is no NT symbol with index, idx. */ func (this *Symbols) NTId(idx int) string { - if idx < 0 || idx >= len(this.ntTypeMap) { + if idx < 0 || idx >= len(this.nonTerminalType) { return "" } - return this.ntTypeMap[idx] + return this.ntSymbols[idx].SymbolName() } /* Return the number of NT symbols in the grammar */ func (this *Symbols) NumNTSymbols() int { - return len(this.ntTypeMap) + return len(this.ntSymbols) } /* Returns a slice containing all the non-terminal symbols of the grammar. */ -func (this *Symbols) NTList() []string { - return this.ntTypeMap +func (this *Symbols) NTList() ast.SyntaxSymbols { + ret := ast.SyntaxSymbolsByName(this.ntSymbols) + //sort.Sort(&ret) + return ast.SyntaxSymbols(ret) } /* Returns the NT index of a symbol (index in 0..|NT|-1) or -1 if the symbol is not in NT. */ func (this *Symbols) NTType(symbol string) int { - if idx, exist := this.ntIdMap[symbol]; exist { + if idx, exist := this.nonTerminalType[symbol]; exist { return idx } return -1 @@ -168,20 +172,22 @@ func (this *Symbols) NTType(symbol string) int { Returns the total number of symbols in grammar: the sum of the terminals and non-terminals. */ func (this *Symbols) NumSymbols() int { - return len(this.typeMap) + return len(this.symbols) } func (this *Symbols) String() string { w := new(strings.Builder) - for i, sym := range this.typeMap { - fmt.Fprintf(w, "%3d: %s\n", i, sym) + for i, sym := range this.List() { + fmt.Fprintf(w, "%3d: %s\n", i, sym.SymbolName()) } return w.String() } -func (this *Symbols) Type(id string) int { - if typ, ok := this.idMap[id]; ok { +/* +func (this *Symbols) Type(id ast.SyntaxSymbol) int { + if typ, ok := this.idMap[id.SymbolName()]; ok { return typ } return -1 } +*/ diff --git a/internal/test/t1/errors/errors.go b/internal/test/t1/errors/errors.go old mode 100755 new mode 100644 index baa0603d..9d595821 --- a/internal/test/t1/errors/errors.go +++ b/internal/test/t1/errors/errors.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/goccmack/gocc/internal/test/t1/token" + "github.com/maxcalandrelli/gocc/internal/test/t1/token" ) type ErrorSymbol interface { diff --git a/internal/test/t1/lexer/acttab.go b/internal/test/t1/lexer/acttab.go old mode 100755 new mode 100644 index 8e2fcd2c..668b985d --- a/internal/test/t1/lexer/acttab.go +++ b/internal/test/t1/lexer/acttab.go @@ -5,7 +5,7 @@ package lexer import ( "fmt" - "github.com/goccmack/gocc/internal/test/t1/token" + "github.com/maxcalandrelli/gocc/internal/test/t1/token" ) type ActionTable [NumStates]ActionRow diff --git a/internal/test/t1/lexer/lexer.go b/internal/test/t1/lexer/lexer.go old mode 100755 new mode 100644 index 27ea8ec0..7687ed75 --- a/internal/test/t1/lexer/lexer.go +++ b/internal/test/t1/lexer/lexer.go @@ -6,7 +6,7 @@ import ( "io/ioutil" "unicode/utf8" - "github.com/goccmack/gocc/internal/test/t1/token" + "github.com/maxcalandrelli/gocc/internal/test/t1/token" ) const ( diff --git a/internal/test/t1/lexer/transitiontable.go b/internal/test/t1/lexer/transitiontable.go old mode 100755 new mode 100644 diff --git a/internal/test/t1/parser/action.go b/internal/test/t1/parser/action.go old mode 100755 new mode 100644 diff --git a/internal/test/t1/parser/actiontable.go b/internal/test/t1/parser/actiontable.go old mode 100755 new mode 100644 diff --git a/internal/test/t1/parser/gototable.go b/internal/test/t1/parser/gototable.go old mode 100755 new mode 100644 diff --git a/internal/test/t1/parser/parser.go b/internal/test/t1/parser/parser.go old mode 100755 new mode 100644 index c30faef3..d6a60783 --- a/internal/test/t1/parser/parser.go +++ b/internal/test/t1/parser/parser.go @@ -6,8 +6,10 @@ import ( "fmt" "strings" - parseError "github.com/goccmack/gocc/internal/test/t1/errors" - "github.com/goccmack/gocc/internal/test/t1/token" + "github.com/maxcalandrelli/gocc/internal/config" + + parseError "github.com/maxcalandrelli/gocc/internal/test/t1/errors" + "github.com/maxcalandrelli/gocc/internal/test/t1/token" ) const ( @@ -121,7 +123,7 @@ func (p *Parser) Error(err error, scanner Scanner) (recovered bool, errorAttrib } } - if action := actionTab[p.stack.top()].actions[token.TokMap.Type("error")]; action != nil { + if action := actionTab[p.stack.top()].actions[token.TokMap.Type(config.CurrentConfiguration.GetCanonicalSymbols(config.SYMBOL_ERROR)[0])]; action != nil { p.stack.push(int(action.(shift)), errorAttrib) // action can only be shift } else { return diff --git a/internal/test/t1/parser/productionstable.go b/internal/test/t1/parser/productionstable.go old mode 100755 new mode 100644 diff --git a/internal/test/t1/t1_test.go b/internal/test/t1/t1_test.go index 2371d78e..9574b302 100644 --- a/internal/test/t1/t1_test.go +++ b/internal/test/t1/t1_test.go @@ -3,9 +3,9 @@ package t1 import ( "testing" - "github.com/goccmack/gocc/internal/test/t1/errors" - "github.com/goccmack/gocc/internal/test/t1/lexer" - "github.com/goccmack/gocc/internal/test/t1/parser" + "github.com/maxcalandrelli/gocc/internal/test/t1/errors" + "github.com/maxcalandrelli/gocc/internal/test/t1/lexer" + "github.com/maxcalandrelli/gocc/internal/test/t1/parser" ) func Test1(t *testing.T) { diff --git a/internal/test/t1/token/token.go b/internal/test/t1/token/token.go old mode 100755 new mode 100644 diff --git a/internal/test/t1/util/litconv.go b/internal/test/t1/util/litconv.go old mode 100755 new mode 100644 diff --git a/internal/test/t1/util/rune.go b/internal/test/t1/util/rune.go old mode 100755 new mode 100644 diff --git a/internal/token/gen/gen.go b/internal/token/gen/gen.go index eb7f2781..3234db00 100644 --- a/internal/token/gen/gen.go +++ b/internal/token/gen/gen.go @@ -15,10 +15,11 @@ package gen import ( - "github.com/goccmack/gocc/internal/token" - "github.com/goccmack/gocc/internal/token/gen/golang" + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/token" + "github.com/maxcalandrelli/gocc/internal/token/gen/golang" ) -func Gen(pkg, outdir string, tokenMap *token.TokenMap) { - golang.GenToken(pkg, outdir, tokenMap) +func Gen(pkg, outdir string, tokenMap *token.TokenMap, subpath string, cfg config.Config) { + golang.GenToken(pkg, outdir, tokenMap, subpath, cfg) } diff --git a/internal/token/gen/golang/token.go b/internal/token/gen/golang/token.go index 9c9bdd03..c7f51f72 100644 --- a/internal/token/gen/golang/token.go +++ b/internal/token/gen/golang/token.go @@ -21,19 +21,28 @@ import ( "path" "text/template" - "github.com/goccmack/gocc/internal/io" - "github.com/goccmack/gocc/internal/token" + "github.com/maxcalandrelli/gocc/internal/config" + "github.com/maxcalandrelli/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/token" ) -func GenToken(pkg, outdir string, tokMap *token.TokenMap) { - tokenPath := path.Join(outdir, "token", "token.go") +func GenToken(pkg, outdir string, tokMap *token.TokenMap, subpath string, cfg config.Config) { + tokenPath := path.Join(outdir, subpath, "token", "token.go") tmpl, err := template.New("token").Parse(TokenMapSrc[1:]) if err != nil { panic(err) } buf := new(bytes.Buffer) - err = tmpl.Execute(buf, TokenData{TypMap: tokMap.TypeMap, IdMap: typeMap(tokMap)}) - // Use go/format to indent the idMap literal correctly. + data := TokenData{TypMap: make([]string, len(tokMap.TypeMap)), IdMap: make([]string, len(tokMap.TypeMap)), LitMap: []string{}, NoLexer: cfg.NoLexer()} + for i, sym := range tokMap.TypeMap { + data.IdMap[i] = fmt.Sprintf("\"%s\": %d", sym.SymbolName(), i) + data.TypMap[i] = fmt.Sprintf("\"%s\"", sym.SymbolName()) + if lit, found := tokMap.LitMap[i]; found { + data.LitMap = append(data.LitMap, fmt.Sprintf("\"%s\": %d", lit, i)) + } + } + err = tmpl.Execute(buf, data) + //err = tmpl.Execute(buf, TokenData{TypMap: makeTypeMap(tokMap), IdMap: makeIdMap(tokMap), LitMap: makeLitMap(tokMap), NoLexer: cfg.NoLexer()}) source, err := format.Source(buf.Bytes()) if err != nil { println(err.Error()) @@ -42,17 +51,11 @@ func GenToken(pkg, outdir string, tokMap *token.TokenMap) { io.WriteFile(tokenPath, source) } -func typeMap(tokMap *token.TokenMap) []string { - tm := make([]string, len(tokMap.TypeMap)) - for i, sym := range tokMap.TypeMap { - tm[i] = fmt.Sprintf("\"%s\": %d", sym, i) - } - return tm -} - type TokenData struct { - IdMap []string - TypMap []string + IdMap []string + TypMap []string + LitMap []string + NoLexer bool } const TokenMapSrc string = ` @@ -69,7 +72,10 @@ import ( type Token struct { Type Lit []byte + IgnoredPrefix []byte Pos + ForeignAstNode interface{} + Foreign bool } type Type int @@ -89,9 +95,24 @@ func (p Pos) String() string { return fmt.Sprintf("Pos(offset=%d, line=%d, column=%d)", p.Offset, p.Line, p.Column) } +func (p Pos) StartingFrom(base Pos) Pos { + r := base + r.Offset += p.Offset + r.Line += p.Line + r.Column = p.Column + if p.Line > 0 && base.Line > 0 { + r.Line-- + } + if r.Column < 1 { + r.Column = 1 + } + return r +} + type TokenMap struct { typeMap []string idMap map[string]Type + litMap map[string]Type } func (m TokenMap) Id(tok Type) string { @@ -105,12 +126,16 @@ func (m TokenMap) Type(tok string) Type { if typ, exist := m.idMap[tok]; exist { return typ } + {{- if .NoLexer }} + if typ, exist := m.litMap[tok]; exist { + return typ + } + {{- end }} return INVALID } func (m TokenMap) TokenString(tok *Token) string { - //TODO: refactor to print pos & token string properly - return fmt.Sprintf("%s(%d,%s)", m.Id(tok.Type), tok.Type, tok.Lit) + return fmt.Sprintf("%s(%d,<%s>)", m.Id(tok.Type), tok.Type, tok.Lit) } func (m TokenMap) StringType(typ Type) string { @@ -178,7 +203,7 @@ func (t *Token) StringValue() string { var TokMap = TokenMap{ typeMap: []string{ {{- range .TypMap }} - {{printf "%q" .}}, + {{printf "%s" .}}, {{- end }} }, @@ -186,6 +211,14 @@ var TokMap = TokenMap{ {{- range .IdMap }} {{printf "%s" .}}, {{- end }} + + }, + + litMap: map[string]Type{ +{{- range .LitMap }} + {{printf "%s" .}}, +{{- end }} + }, } diff --git a/internal/token/tokenmap.go b/internal/token/tokenmap.go index 1fa15b5a..eae09bee 100644 --- a/internal/token/tokenmap.go +++ b/internal/token/tokenmap.go @@ -14,20 +14,30 @@ package token +import ( + "github.com/maxcalandrelli/gocc/internal/ast" +) + type TokenMap struct { IdMap map[string]int - TypeMap []string + TypeMap []ast.SyntaxSymbol + LitMap map[int]string } -func NewTokenMap(symbols []string) *TokenMap { +func NewTokenMap(symbols ast.SyntaxSymbols) *TokenMap { tm := &TokenMap{ IdMap: make(map[string]int), - TypeMap: make([]string, len(symbols)), + TypeMap: make([]ast.SyntaxSymbol, len(symbols)), + LitMap: make(map[int]string), } for i, sym := range symbols { - tm.IdMap[sym] = i + tm.IdMap[sym.SymbolName()] = i tm.TypeMap[i] = sym + switch lit := sym.(type) { + case ast.SyntaxStringLit: + tm.LitMap[i] = lit.SymbolString() + } } return tm } diff --git a/internal/util/gen/gen.go b/internal/util/gen/gen.go index 39732005..ec84d764 100644 --- a/internal/util/gen/gen.go +++ b/internal/util/gen/gen.go @@ -1,10 +1,10 @@ package gen import ( - "github.com/goccmack/gocc/internal/util/gen/golang" + "github.com/maxcalandrelli/gocc/internal/util/gen/golang" ) -func Gen(outDir string) { - golang.GenRune(outDir) - golang.GenLitConv(outDir) +func Gen(outDir, internal string) { + golang.GenRune(outDir, internal) + golang.GenLitConv(outDir, internal) } diff --git a/internal/util/gen/golang/litconv.go b/internal/util/gen/golang/litconv.go index c5f859ad..f19c11c1 100644 --- a/internal/util/gen/golang/litconv.go +++ b/internal/util/gen/golang/litconv.go @@ -3,11 +3,11 @@ package golang import ( "path" - "github.com/goccmack/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/io" ) -func GenLitConv(outDir string) { - io.WriteFileString(path.Join(outDir, "util", "litconv.go"), litConvSrc[1:]) +func GenLitConv(outDir, internal string) { + io.WriteFileString(path.Join(outDir, internal, "util", "litconv.go"), litConvSrc[1:]) } const litConvSrc = ` diff --git a/internal/util/gen/golang/rune.go b/internal/util/gen/golang/rune.go index 4561801c..80811c39 100644 --- a/internal/util/gen/golang/rune.go +++ b/internal/util/gen/golang/rune.go @@ -3,20 +3,23 @@ package golang import ( "path" - "github.com/goccmack/gocc/internal/io" + "github.com/maxcalandrelli/gocc/internal/io" ) -func GenRune(outDir string) { - io.WriteFileString(path.Join(outDir, "util", "rune.go"), runeSrc[1:]) +func GenRune(outDir, internal string) { + io.WriteFileString(path.Join(outDir, internal, "util", "rune.go"), runeSrc[1:]) } var runeSrc = ` // Code generated by gocc; DO NOT EDIT. + package util import ( "fmt" + "unicode" + "unicode/utf8" ) func RuneToString(r rune) string { @@ -50,4 +53,102 @@ func RuneToString(r rune) string { } return fmt.Sprintf("\\U%08x", r) } + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} + ` diff --git a/internal/util/litconv.go b/internal/util/litconv.go index f75234d6..a278f84a 100644 --- a/internal/util/litconv.go +++ b/internal/util/litconv.go @@ -29,7 +29,7 @@ func LitToRune(lit []byte) rune { } r, size := utf8.DecodeRune(lit[1:]) if size != len(lit)-2 { - panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size%d\n", lit, r, size)) + panic(fmt.Sprintf("Error decoding rune. Lit: %s, rune: %d, size %d\n", lit, r, size)) } return r } diff --git a/internal/util/rune.go b/internal/util/rune.go index 8b72af53..c3b56654 100644 --- a/internal/util/rune.go +++ b/internal/util/rune.go @@ -16,6 +16,8 @@ package util import ( "fmt" + "unicode" + "unicode/utf8" ) func RuneToString(r rune) string { @@ -49,3 +51,100 @@ func RuneToString(r rune) string { } return fmt.Sprintf("\\U%08x", r) } + +type EscapedString string + +func (str EscapedString) Unquote() (unquoted string, wasQuoted bool, quoteType rune) { + if len(str) > 1 { + r := str[0] + if (r == '"' || r == '\x60' || r == '\'') && r == str[len(str)-1] { + str = str[1 : len(str)-1] + } + return string(str), true, rune(r) + } + return string(str), false, 0 +} + +func (str EscapedString) Unescape() string { + var ( + res string + r rune + size int + ) + for s := 0; s < len(str); s += size { + if str[s] == '\\' { + r, size = str[s+1:].EscapedFirstCharValue() + size++ + } else { + r, size = utf8.DecodeRuneInString(string(str)[s:]) + } + res += string(r) + } + return res +} + +func (str EscapedString) EscapedFirstCharValue() (rune, int) { + var i, base, max uint32 + offset := 0 + switch str[offset] { + case '\'', '"': + return rune(str[offset]), 1 + case 'a': + return '\a', 1 + case 'b': + return '\b', 1 + case 'f': + return '\f', 1 + case 'n': + return '\n', 1 + case 'r': + return '\r', 1 + case 't': + return '\t', 1 + case 'v': + return '\v', 1 + case '\\': + return '\\', 1 + case '0', '1', '2', '3', '4', '5', '6', '7': + i, base, max = 3, 8, 255 + case 'x': + i, base, max = 2, 16, 255 + offset++ + case 'u': + i, base, max = 4, 16, unicode.MaxRune + offset++ + case 'U': + i, base, max = 8, 32, unicode.MaxRune + offset++ + default: + panic(fmt.Sprintf("Error decoding character literal: %s\n", str[offset:])) + } + + var x uint32 + for ; i > 0 && offset < len(str); i-- { + ch, size := utf8.DecodeRuneInString(string(str)[offset:]) + offset += size + d := uint32(HexDigitValue(ch)) + if d >= base { + panic(fmt.Sprintf("charVal(%s): illegal character (%c) in escape sequence. size=%d, offset=%d", str, str[offset], size, offset)) + } + x = x*base + d + } + if x > max || 0xD800 <= x && x < 0xE000 { + panic(fmt.Sprintf("Error decoding escape char value. Lit:%s, offset:%d, escape sequence is invalid Unicode code point\n", str, offset)) + } + + return rune(x), offset +} + +func HexDigitValue(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch) - '0' + case 'a' <= ch && ch <= 'f': + return int(ch) - 'a' + 10 + case 'A' <= ch && ch <= 'F': + return int(ch) - 'A' + 10 + } + return 16 // larger than any legal digit val +} diff --git a/main.go b/main.go index a83bdc83..bc1882a4 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,7 @@ +// +//go:generate go run stock/main.go -a -v -o internal/frontend/reparsed spec/gocc2.ebnf +// + //Copyright 2013 Vastech SA (PTY) LTD // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,35 +18,186 @@ //Gocc is LR1 parser generator for go written in go. The generator uses a BNF with very easy to use SDT rules. //Please see https://github.com/goccmack/gocc/ for more documentation. + +/* + Modified by: Massimiliano Calandrelli + + Changes summary: + + 2019-10-21 + Many changes, many new features. Streamed parsing, longest prefix parsing, nondeterministic subparsing. + + - changed all go files using import from + https://github.com/goccmack/gocc + to import from + https://github.com/maxcalandrelli/gocc + + - bugfixes: I discovered and (hopefully) fixed two severe bugs in the generated lexical analyzer. Both + fixes are controllable by a command line option, thus leaving intact the possibility of restoring + original behaviour should the fix cause any other problem. These bugs are explained below + + - BUG #1: state machine generation bug that prevented a regular expression like '<' '<' . { . } '>' '>' + to recognize a string like "<< a > b >>" (this is done in ItemSets.propagateDots and in the generated + lexer/transitiontable.go) + + - BUG #2: state machine generation bug that had the following effect: given the following two alternative + sets of lexical productions: + + 1) _digit : '0'-'9' ; + _x0 : 'α' ; + _x1 : 'β' _digit { _digit } ; + _x : 'α' | ( 'β' _digit { _digit } ); + _test : _x { _x | 'γ' } ; + id: _x { _x0 | _x1 | 'γ' } ; + !whitespace : ' ' | '\t' | '\n' | '\r' ; + + and 2) _digit : '0'-'9' ; + _x0 : 'α' ; + _x : 'α' | ( 'β' _digit { _digit } ); + _test : _x { _x | 'γ' } ; + id: _x { _x0 | ( 'β' _digit { _digit } ) | 'γ' } ; + + they should parse identically (since the only difference is that the single occurrence of regdef _x1 in + set #1 has been replaced by its expansion in set #2), while they don't. As an example (you can test it + in the "ctx" folder under example), the string "β11β1β11 αβ33", when parsed with lexical ruleset 1 gives + the three tokens: "β11β1", "β11" and "αβ33". This result is incorrect, and the correct result is the set + of two tokens "β11β1β11" and "αβ33". This is the result we get when parsing with lexical ruleset #2. + This is because ItemList.Closure fails to add the ε-moves to the closure of a set of items when it contains + both a reduce and a shift for the same regdefid. + + - eliminated ambiguity between literals and labels of lexical or syntaxical productions; "error" can now + be specified as a literal, and a synonym is "λ", while a synonim for "empty" is "ε" + + - used original gocc (https://github.com/goccmack/gocc) to reproduce the initial (handwritten?) parser + + - changed defaults for output directory + + - changed output directory structure + + - added the ability to specify negative char and char ranges to lexer, as in: + + all_but_star : . | ~'*' ; + hexdigit : '0'-'F' | ~(':'-'@') ; + + - added a user defined context to parsing for simpler cases, where an AST is not required. the context is + available as an implicit variable with name "Context" in SDT snippets. a variable named "Stream" contains + the underlying lexer stream + + - added functions shorthand substitutions for SDT placeholders $, with the format + + $[] + + the operations in are applied to the token/ast; ops is a string where every character stays for an unary + function of a string, identified by one of the following: + - s: converts $ to string directly if it is a token in the target grammar; if it is some other object + (i.e. an AST branch returned by a reduce operation), it is converted to a string with a .(string) conversion + and, in case of failure, with a "%q" format string + - q: if the resulting string is enclosed in single o double quotes, it is unwrapped an the quotes are + discarded + - e: unescape the string, replacing control sequences with their corresponding represented values + - U: uppercase conversion + - l: lowercase conversion + for example, if the literal in the token in a terminal symbol in third position in a syntactical production is + <"'value of PI (\u03c0): \"3.14159\"'"> (angular braces used in this text to quote the values), like in: + + ProdX: HeaderPart OptionalPart quoted_string Trailerpart << ast.PrepareWhatever(...) >> ; + + then we will get the following results for quoted_string ($2): + + $2 *token.Token object whose Lit field has the string value <"'value of PI (\u03c0): \"3.14159\"'"> + $2s <"'value of PI (\u03c0): \"3.14159\"'"> + $2e <"'value of PI (π): "3.14159"'"> + $2eq <'value of PI (π): "3.14159"'> + $2eqq + $2eqU + $2eqUq + + - added the ability to parse only the longest possible prefix of data, returning the consumed bytes + + subTree, err, parsed := myParser.ParseLongestPrefix(myScanner) + + - added support for a simple form of context-sensitive (non deterministic) parsing by invoking a different + lexer/parser pair while scanning + + - compact form, using a gocc generated parser for longest prefix sub-parsing: + + NumericValue: + integer + | + @ "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + << + $1, nil + >> + + in compact form, an import alias can be specified (without changes in stack usage)to avoid naming conflicts; + the following example is equivalent to the former: + + NumericValue: + integer + | + @ calculator "github.com/maxcalandrelli/gocc/example/calc/calc.grammar/calc" + << + $1, nil + >> + + - full form, like in the following example, where also the use of "Stream" is shown: + + SlashesOrKeyword: + "no-slashes" + << "no slashes", nil >> + | + somethingelse + @@ + func () (interface {}, error, []byte) { + slashes := []byte{} + for r, _, _ := Stream.ReadRune(); r == '/' || r == '\\' || r == '\u2215' || r == '\u29f5'; r, _, _ = Stream.ReadRune() { + slashes = append(slashes, string(r)...) + } + Stream.UnreadRune() + return len(string(slashes)), nil, slashes + }() + @@ + OtherProduction + << + append(append([]interface{}{},$1),$2.([]interface{})...), nil + >> + + either form of non deterministic parsing pushes two values on the stack: + - the pseudo-token built by taking as literal the longest prefix that the sub-parser recognized + - the corresponding AST returned by the sub-parser + + + +*/ + package main import ( "bytes" "flag" "fmt" - "io/ioutil" "os" "path" "strings" - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/config" - "github.com/goccmack/gocc/internal/frontend/parser" - "github.com/goccmack/gocc/internal/frontend/scanner" - "github.com/goccmack/gocc/internal/frontend/token" - "github.com/goccmack/gocc/internal/io" - genLexer "github.com/goccmack/gocc/internal/lexer/gen/golang" - lexItems "github.com/goccmack/gocc/internal/lexer/items" - "github.com/goccmack/gocc/internal/parser/first" - lr1Action "github.com/goccmack/gocc/internal/parser/lr1/action" - lr1Items "github.com/goccmack/gocc/internal/parser/lr1/items" - "github.com/goccmack/gocc/internal/parser/symbols" - outToken "github.com/goccmack/gocc/internal/token" - genToken "github.com/goccmack/gocc/internal/token/gen" - genUtil "github.com/goccmack/gocc/internal/util/gen" - "github.com/goccmack/gocc/internal/util/md" - - genParser "github.com/goccmack/gocc/internal/parser/gen" + "github.com/maxcalandrelli/gocc/internal/macro" + + "github.com/maxcalandrelli/gocc/internal/ast" + genBase "github.com/maxcalandrelli/gocc/internal/base/gen" + "github.com/maxcalandrelli/gocc/internal/config" + altfe "github.com/maxcalandrelli/gocc/internal/frontend/reparsed" + "github.com/maxcalandrelli/gocc/internal/io" + genIo "github.com/maxcalandrelli/gocc/internal/io/gen" + genLexer "github.com/maxcalandrelli/gocc/internal/lexer/gen/golang" + lexItems "github.com/maxcalandrelli/gocc/internal/lexer/items" + "github.com/maxcalandrelli/gocc/internal/parser/first" + genParser "github.com/maxcalandrelli/gocc/internal/parser/gen" + lr1Action "github.com/maxcalandrelli/gocc/internal/parser/lr1/action" + lr1Items "github.com/maxcalandrelli/gocc/internal/parser/lr1/items" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" + outToken "github.com/maxcalandrelli/gocc/internal/token" + genToken "github.com/maxcalandrelli/gocc/internal/token/gen" + genUtil "github.com/maxcalandrelli/gocc/internal/util/gen" ) func main() { @@ -54,79 +209,79 @@ func main() { } if cfg.Verbose() { + fmt.Fprintf(os.Stderr, "gocc version %s\n", config.VERSION) cfg.PrintParams() } if cfg.Help() { + fmt.Fprintf(os.Stderr, "gocc version %s\n", config.VERSION) flag.Usage() } - scanner := &scanner.Scanner{} - srcBuffer := getSource(cfg) + config.CurrentConfiguration = cfg - scanner.Init(srcBuffer, token.FRONTENDTokens) - parser := parser.NewParser(parser.ActionTable, parser.GotoTable, parser.ProductionsTable, token.FRONTENDTokens) - grammar, err := parser.Parse(scanner) + var ( + grammar interface{} + ) + ast.StringGetter = func(v interface{}) string { return string(v.(*altfe.Token).Lit) } + + outdir_base := cfg.OutDir() + outdir_log := path.Join(outdir_base, "log") + outdir_iface := path.Join("iface") + + source := cfg.SourceFile() + if cfg.PreProcessor() != "none" { + tmpsrc := path.Join(outdir_log, path.Base(source)) + if err := macro.PreProcess(cfg.PreProcessor(), source, tmpsrc); err != nil { + fmt.Printf("Preprocessing error: %s\n", err.Error()) + os.Exit(1) + } + source = tmpsrc + } + grammar, err = altfe.ParseFile(source) if err != nil { fmt.Printf("Parse error: %s\n", err) os.Exit(1) } - g := grammar.(*ast.Grammar) gSymbols := symbols.NewSymbols(g) if cfg.Verbose() { - writeTerminals(gSymbols, cfg) + writeTerminals(gSymbols, cfg, outdir_log) } var tokenMap *outToken.TokenMap gSymbols.Add(g.LexPart.TokenIds()...) g.LexPart.UpdateStringLitTokens(gSymbols.ListStringLitSymbols()) - lexSets := lexItems.GetItemSets(g.LexPart) + lexSets := lexItems.GetItemSets(g.LexPart, cfg.BugOption("lexer_dots").Fix(), cfg.BugOption("lexer_regdefs").Fix()) if cfg.Verbose() { - io.WriteFileString(path.Join(cfg.OutDir(), "lexer_sets.txt"), lexSets.String()) + io.WriteFileString(path.Join(outdir_log, "lexer_sets.txt"), lexSets.String()) } tokenMap = outToken.NewTokenMap(gSymbols.ListTerminals()) if !cfg.NoLexer() { - genLexer.Gen(cfg.Package(), cfg.OutDir(), g.LexPart.Header.SDTLit, lexSets, tokenMap, cfg) + genLexer.Gen(cfg.Package(), outdir_base, g.LexPart.Header.SDTLit, lexSets, tokenMap, cfg, cfg.InternalSubdir(), outdir_iface) } - - if g.SyntaxPart != nil { + hasSyntax := (g.SyntaxPart != nil) + if hasSyntax { firstSets := first.GetFirstSets(g, gSymbols) if cfg.Verbose() { - io.WriteFileString(path.Join(cfg.OutDir(), "first.txt"), firstSets.String()) + io.WriteFileString(path.Join(outdir_log, "first.txt"), firstSets.String()) } lr1Sets := lr1Items.GetItemSets(g, gSymbols, firstSets) if cfg.Verbose() { - io.WriteFileString(path.Join(cfg.OutDir(), "LR1_sets.txt"), lr1Sets.String()) + io.WriteFileString(path.Join(outdir_log, "LR1_sets.txt"), lr1Sets.String()) } - conflicts := genParser.Gen(cfg.Package(), cfg.OutDir(), g.SyntaxPart.Header.SDTLit, g.SyntaxPart.ProdList, gSymbols, lr1Sets, tokenMap, cfg) - handleConflicts(conflicts, lr1Sets.Size(), cfg, g.SyntaxPart.ProdList) + conflicts := genParser.Gen(cfg.Package(), outdir_base, g.SyntaxPart.Header.SDTLit, g.SyntaxPart.ProdList, gSymbols, lr1Sets, tokenMap, cfg, cfg.InternalSubdir(), outdir_iface) + handleConflicts(conflicts, lr1Sets.Size(), cfg, g.SyntaxPart.ProdList, outdir_log) } - genToken.Gen(cfg.Package(), cfg.OutDir(), tokenMap) - genUtil.Gen(cfg.OutDir()) - -} - -func getSource(cfg config.Config) []byte { - if strings.HasSuffix(cfg.SourceFile(), ".md") { - str, err := md.GetSource(cfg.SourceFile()) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return []byte(str) - } - srcBuffer, err := ioutil.ReadFile(cfg.SourceFile()) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return srcBuffer + genToken.Gen(cfg.Package(), outdir_base, tokenMap, cfg.InternalSubdir(), cfg) + genUtil.Gen(outdir_base, cfg.InternalSubdir()) + genBase.Gen(cfg.Package(), outdir_base, cfg.InternalSubdir(), outdir_iface, cfg, hasSyntax) + genIo.Gen(cfg.Package(), outdir_base, cfg.InternalSubdir()) } func usage() { @@ -137,13 +292,13 @@ func usage() { os.Exit(1) } -func handleConflicts(conflicts map[int]lr1Items.RowConflicts, numSets int, cfg config.Config, prods ast.SyntaxProdList) { +func handleConflicts(conflicts map[int]lr1Items.RowConflicts, numSets int, cfg config.Config, prods ast.SyntaxProdList, outdir string) { if len(conflicts) <= 0 { return } fmt.Printf("%d LR-1 conflicts \n", len(conflicts)) - if cfg.Verbose() { - io.WriteFileString(path.Join(cfg.OutDir(), "LR1_conflicts.txt"), conflictString(conflicts, numSets, prods)) + if cfg.Verbose() || !cfg.AutoResolveLRConf() { + io.WriteFileString(path.Join(outdir, "LR1_conflicts.txt"), conflictString(conflicts, numSets, prods)) } if !cfg.AutoResolveLRConf() { os.Exit(1) @@ -174,10 +329,10 @@ func conflictString(conflicts map[int]lr1Items.RowConflicts, numSets int, prods return w.String() } -func writeTerminals(gSymbols *symbols.Symbols, cfg config.Config) { +func writeTerminals(gSymbols *symbols.Symbols, cfg config.Config, outdir string) { buf := new(bytes.Buffer) for _, t := range gSymbols.ListTerminals() { fmt.Fprintf(buf, "%s\n", t) } - io.WriteFile(path.Join(cfg.OutDir(), "terminals.txt"), buf.Bytes()) + io.WriteFile(path.Join(outdir, "terminals.txt"), buf.Bytes()) } diff --git a/main.go.orig b/main.go.orig deleted file mode 100644 index c3bf4d05..00000000 --- a/main.go.orig +++ /dev/null @@ -1,190 +0,0 @@ -//Copyright 2013 Vastech SA (PTY) LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//Gocc is LR1 parser generator for go written in go. The generator uses a BNF with very easy to use SDT rules. -//Please see https://github.com/goccmack/gocc/ for more documentation. -package main - -import ( - "bytes" - "flag" - "fmt" - "io/ioutil" - "os" - "path" - "strings" - - "github.com/goccmack/gocc/internal/ast" - "github.com/goccmack/gocc/internal/config" - "github.com/goccmack/gocc/internal/frontend/parser" - "github.com/goccmack/gocc/internal/frontend/scanner" - "github.com/goccmack/gocc/internal/frontend/token" - "github.com/goccmack/gocc/internal/io" - genLexer "github.com/goccmack/gocc/internal/lexer/gen/golang" - lexItems "github.com/goccmack/gocc/internal/lexer/items" - "github.com/goccmack/gocc/internal/parser/first" - genParser "github.com/goccmack/gocc/internal/parser/gen" - lr1Action "github.com/goccmack/gocc/internal/parser/lr1/action" - lr1Items "github.com/goccmack/gocc/internal/parser/lr1/items" - "github.com/goccmack/gocc/internal/parser/symbols" - outToken "github.com/goccmack/gocc/internal/token" - genToken "github.com/goccmack/gocc/internal/token/gen" - genUtil "github.com/goccmack/gocc/internal/util/gen" -<<<<<<< HEAD - "github.com/goccmack/gocc/internal/util/md" - - // "runtime/pprof" - "time" - - genParser "github.com/goccmack/gocc/internal/parser/gen" -======= ->>>>>>> 7a292ad833c2ba6a29151456d8de06ac9ab2a505 -) - -func main() { - flag.Usage = usage - cfg, err := config.New() - if err != nil { - fmt.Printf("Error reading configuration: %s\n", err) - flag.Usage() - } - - if cfg.Verbose() { - cfg.PrintParams() - } - - if cfg.Help() { - flag.Usage() - } - - scanner := &scanner.Scanner{} - srcBuffer := getSource(cfg) - - scanner.Init(srcBuffer, token.FRONTENDTokens) - parser := parser.NewParser(parser.ActionTable, parser.GotoTable, parser.ProductionsTable, token.FRONTENDTokens) - grammar, err := parser.Parse(scanner) - if err != nil { - fmt.Printf("Parse error: %s\n", err) - os.Exit(1) - } - - g := grammar.(*ast.Grammar) - - gSymbols := symbols.NewSymbols(g) - if cfg.Verbose() { - writeTerminals(gSymbols, cfg) - } - - var tokenMap *outToken.TokenMap - - gSymbols.Add(g.LexPart.TokenIds()...) - g.LexPart.UpdateStringLitTokens(gSymbols.ListStringLitSymbols()) - lexSets := lexItems.GetItemSets(g.LexPart) - if cfg.Verbose() { - io.WriteFileString(path.Join(cfg.OutDir(), "lexer_sets.txt"), lexSets.String()) - } - tokenMap = outToken.NewTokenMap(gSymbols.ListTerminals()) - if !cfg.NoLexer() { - genLexer.Gen(cfg.Package(), cfg.OutDir(), g.LexPart.Header.SDTLit, lexSets, tokenMap, cfg) - } - - if g.SyntaxPart != nil { - firstSets := first.GetFirstSets(g, gSymbols) - if cfg.Verbose() { - io.WriteFileString(path.Join(cfg.OutDir(), "first.txt"), firstSets.String()) - } - - lr1Sets := lr1Items.GetItemSets(g, gSymbols, firstSets) - if cfg.Verbose() { - io.WriteFileString(path.Join(cfg.OutDir(), "LR1_sets.txt"), lr1Sets.String()) - } - - conflicts := genParser.Gen(cfg.Package(), cfg.OutDir(), g.SyntaxPart.Header.SDTLit, g.SyntaxPart.ProdList, gSymbols, lr1Sets, tokenMap, cfg) - handleConflicts(conflicts, lr1Sets.Size(), cfg, g.SyntaxPart.ProdList) - } - - genToken.Gen(cfg.Package(), cfg.OutDir(), tokenMap) - genUtil.Gen(cfg.OutDir()) - -} - -func getSource(cfg config.Config) []byte { - if strings.HasSuffix(cfg.SourceFile(), ".md") { - str, err := md.GetSource(cfg.SourceFile()) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return []byte(str) - } - srcBuffer, err := ioutil.ReadFile(cfg.SourceFile()) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - return srcBuffer -} - -func usage() { - fmt.Fprintf(os.Stderr, "usage: gocc flags bnf_file\n\n") - fmt.Fprintf(os.Stderr, " bnf_file: contains the BNF grammar\n\n") - fmt.Fprintf(os.Stderr, "Flags:\n") - flag.PrintDefaults() - os.Exit(1) -} - -func handleConflicts(conflicts map[int]lr1Items.RowConflicts, numSets int, cfg config.Config, prods ast.SyntaxProdList) { - if len(conflicts) <= 0 { - return - } - fmt.Printf("%d LR-1 conflicts \n", len(conflicts)) - if cfg.Verbose() { - io.WriteFileString(path.Join(cfg.OutDir(), "LR1_conflicts.txt"), conflictString(conflicts, numSets, prods)) - } - if !cfg.AutoResolveLRConf() { - os.Exit(1) - } -} - -func conflictString(conflicts map[int]lr1Items.RowConflicts, numSets int, prods ast.SyntaxProdList) string { - w := new(strings.Builder) - fmt.Fprintf(w, "%d LR-1 conflicts: \n", len(conflicts)) - for i := 0; i < numSets; i++ { - if cnf, exist := conflicts[i]; exist { - fmt.Fprintf(w, "\tS%d\n", i) - for sym, conflicts := range cnf { - fmt.Fprintf(w, "\t\tsymbol: %s\n", sym) - for _, cflct := range conflicts { - switch c := cflct.(type) { - case lr1Action.Reduce: - fmt.Fprintf(w, "\t\t\tReduce(%d:%s)\n", c, prods[c]) - case lr1Action.Shift: - fmt.Fprintf(w, "\t\t\t%s\n", cflct) - default: - panic(fmt.Sprintf("unexpected type of action: %s", cflct)) - } - } - } - } - } - return w.String() -} - -func writeTerminals(gSymbols *symbols.Symbols, cfg config.Config) { - buf := new(bytes.Buffer) - for _, t := range gSymbols.ListTerminals() { - fmt.Fprintf(buf, "%s\n", t) - } - io.WriteFile(path.Join(cfg.OutDir(), "terminals.txt"), buf.Bytes()) -} diff --git a/spec/gocc2.ebnf b/spec/gocc2.ebnf index e9ada3e8..ec3b7bdd 100644 --- a/spec/gocc2.ebnf +++ b/spec/gocc2.ebnf @@ -12,110 +12,317 @@ // See the License for the specific language governing permissions and // limitations under the License. -/*** Syntactic items ***/ +!comment : _lineComment | _blockComment ; +!whitespace : ' ' | '\t' | '\n' | '\r' ; + +_line_Comment : '/' '/' { ' ' } '\n' ; +_lineComment : '/' '/' {.} '\n' ; +_blockComment : '/' '*' { . | '*' } '*' '/' ; +_tokId : _lowcase {_id_char} ; +_lowcase : 'a'-'z' ; +_id_char : _upcase | _lowcase | '_' | _digit ; +_upcase : 'A'-'Z' ; +_digit : '0'-'9' ; + +_unicode_value + : . // Any UTF-8 character literal + | _little_u_value + | _big_u_value + | _escaped_char + ; + +_byte_value + : _octal_byte_value + | _hex_byte_value + ; + +_little_u_value + : '\\' 'u' _hex_digit _hex_digit _hex_digit _hex_digit + ; + +_big_u_value + : '\\' 'U' _hex_digit _hex_digit _hex_digit _hex_digit + _hex_digit _hex_digit _hex_digit _hex_digit + ; + +_escaped_char + : '\\' ( 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' | '\\' | '\'' | '"' ) + ; + +_octal_byte_value + : '\\' _octal_digit _octal_digit _octal_digit + ; + +_hex_byte_value + : '\\' 'x' _hex_digit _hex_digit + ; + +_octal_digit + : '0' - '7' + ; -<< import "github.com/goccmack/gocc/internal/ast" >> +_hex_digit + : '0' - '9' + | 'A' - 'F' + | 'a' - 'f' + ; -Grammar : LexicalPart SyntaxPart << ast.NewGrammar($0, $1) >> - | LexicalPart << ast.NewGrammar($0, nil) >> - | SyntaxPart << ast.NewGrammar(nil, $0) >> - ; +_raw_string + : '`' {.} '`' + ; -LexicalPart : LexProductions << ast.NewLexPart(nil, nil, $0) >> - ; +_interpreted_string + : '"' { _unicode_value | _byte_value } '"' + ; -LexProductions : LexProduction << ast.NewLexProductions($0) >> - | LexProductions LexProduction << ast.AppendLexProduction($0, $1) >> - ; -LexProduction : tokId ":" LexPattern ";" << ast.NewLexTokDef($0, $2) >> - | regDefId ":" LexPattern ";" << ast.NewLexRegDef($0, $2) >> - | ignoredTokId ":" LexPattern ";" << ast.NewLexIgnoredTokDef($0, $2) >> - ; +tokId : _tokId ; -LexPattern : LexAlt << ast.NewLexPattern($0) >> - | LexPattern "|" LexAlt << ast.AppendLexAlt($0, $2) >> - ; +regDefId : '_' {_id_char} ; -LexAlt : LexTerm << ast.NewLexAlt($0) >> - | LexAlt LexTerm << ast.AppendLexTerm($0, $1) >> - ; +ignoredTokId : '!' _tokId ; + +char_lit : '\'' (_unicode_value | _byte_value) '\'' ; + +prodId + : _upcase {_id_char} + ; + +g_sdt_lit + : '<' '<' . {.} '>' '>' + ; + +g_ctxdep_lit + : '@' '@' . {.} '@' '@' + ; + + +string_lit + : _raw_string + | _interpreted_string + ; + + + +/*** Syntactic items ***/ -LexTerm : "." << ast.LexDOT, nil >> - | char_lit << ast.NewLexCharLit($0) >> - | char_lit "-" char_lit << ast.NewLexCharRange($0, $2) >> - | regDefId << ast.NewLexRegDefId($0) >> - | "[" LexPattern "]" << ast.NewLexOptPattern($1) >> - | "{" LexPattern "}" << ast.NewLexRepPattern($1) >> - | "(" LexPattern ")" << ast.NewLexGroupPattern($1) >> - ; +<< + import ( + "github.com/maxcalandrelli/gocc/internal/ast" + ) + // now a > b should work... + >> -SyntaxPart : FileHeader SyntaxProdList << ast.NewSyntaxPart($0, $1) >> - | SyntaxProdList << ast.NewSyntaxPart(nil, $0) >> - ; +Grammar : + LexicalPart + SyntaxPart + << ast.NewGrammar($0, $1) >> + | + LexicalPart + << ast.NewGrammar($0, nil) >> + | + SyntaxPart + << ast.NewGrammar(nil, $0) >> +; -FileHeader : g_sdt_lit << ast.NewFileHeader($0) >> - ; +LexicalPart : + LexProductions + << ast.NewLexPart(nil, nil, $0) >> +; -SyntaxProdList : SyntaxProduction << ast.NewSyntaxProdList($0) >> - | SyntaxProdList SyntaxProduction << ast.AddSyntaxProds($0, $1) >> - ; +LexProductions : + LexProduction + << ast.NewLexProductions($0) >> + | + LexProductions + LexProduction + << ast.AppendLexProduction($0, $1) >> +; -SyntaxProduction : prodId ":" Alternatives ";" << ast.NewSyntaxProd($0, $2) >> - ; +LexProduction : + tokId + ":" + LexPattern + ";" + << ast.NewLexTokDef($0, $2) >> + | + regDefId + ":" + LexPattern + ";" + << ast.NewLexRegDef($0, $2) >> + | + ignoredTokId + ":" + LexPattern + ";" + << ast.NewLexIgnoredTokDef($0, $2) >> +; -Alternatives : SyntaxBody << ast.NewSyntaxAlts($0) >> - | Alternatives "|" SyntaxBody << ast.AddSyntaxAlt($0, $2) >> - ; +LexPattern : + LexAlt + << ast.NewLexPattern($0) >> + | + LexPattern + "|" + LexAlt + << ast.AppendLexAlt($0, $2) >> +; -SyntaxBody : Symbols << ast.NewSyntaxBody($0, nil) >> - | Symbols g_sdt_lit << ast.NewSyntaxBody($0, $1) >> - | "error" << ast.NewErrorBody(nil, nil) >> - | "error" Symbols << ast.NewErrorBody($1, nil) >> - | "error" Symbols g_sdt_lit << ast.NewErrorBody($1, $2) >> - | "empty" << ast.NewEmptyBody() >> - ; +LexAlt : + LexTerm + << ast.NewLexAlt($0) >> + | + LexAlt + LexTerm + << ast.AppendLexTerm($0, $1) >> +; -Symbols : Symbol << ast.NewSyntaxSymbols($0) >> - | Symbols Symbol << ast.AddSyntaxSymbol($0, $1) >> - ; +LexTerm : + "." + << ast.LexDOT, nil >> + | + char_lit + << ast.NewLexCharLitExt($0,false) >> + | + char_lit "-" char_lit + << ast.NewLexCharRangeExt($0, $2,false) >> + | + "~" char_lit + << ast.NewLexCharLitExt($1, true) >> + | + "~" "(" char_lit "-" char_lit ")" + << ast.NewLexCharRangeExt($2, $4, true) >> + | + regDefId + << ast.NewLexRegDefId($0) >> + | + "[" + LexPattern + "]" + << ast.NewLexOptPattern($1) >> + | + "{" + LexPattern + "}" + << ast.NewLexRepPattern($1) >> + | + "(" + LexPattern + ")" + << ast.NewLexGroupPattern($1) >> +; -Symbol : prodId << ast.NewSyntaxProdId($0) >> - | tokId << ast.NewTokId($0) >> - | string_lit << ast.NewStringLit($0) >> - ; +SyntaxPart : + FileHeader + SyntaxProdList + << ast.NewSyntaxPart($0, $1) >> + | + SyntaxProdList + << ast.NewSyntaxPart(nil, $0) >> +; -/******** -Lexical items -The basic unit of input to the lexical analyser is a UTF-8 encoded Unicode code point, defined as: +FileHeader : + g_sdt_lit + << ast.NewFileHeader($0) >> +; -_unicode_char : < any Unicode code point > . +SyntaxProdList : + SyntaxProduction + << ast.NewSyntaxProdList($0) >> + | + SyntaxProdList + SyntaxProduction + << ast.AddSyntaxProds($0, $1) >> +; -_letter : 'A' ... 'Z' | 'a' ... 'z' | '_' ; +SyntaxProduction : + prodId + ":" + Alternatives + ";" + << ast.NewSyntaxProd($0, $2) >> +; -_digit : '0' ... '9' ; +Alternatives : + SyntaxBody + << ast.NewSyntaxAlts($0) >> + | + Alternatives + "|" + SyntaxBody + << ast.AddSyntaxAlt($0, $2) >> +; -char : "'" ( _unicode_value | _byte_value ) "'" ; +SyntaxBody : + Symbols + << ast.NewSyntaxBodyGen($0, nil) >> + | + Symbols g_sdt_lit + << ast.NewSyntaxBodyGen($0, $1) >> + | + ErrorSymbol + << ast.NewErrorBodyGen(nil, nil) >> + | + ErrorSymbol Symbols + << ast.NewErrorBodyGen($1, nil) >> + | + ErrorSymbol Symbols g_sdt_lit + << ast.NewErrorBodyGen($1, $2) >> + | + ErrorSymbol g_sdt_lit + << ast.NewErrorBodyGen(nil, $1) >> + | + EpsilonSymbol + << ast.NewEmptyBodyGen() >> + | + EpsilonSymbol g_sdt_lit + << ast.NewEmptyBodyGen() >> +; -_unicode_value : _unicode_char | _little_u_value | _big_u_value | _escaped_char ; -_byte_value : _octal_byte_value | _hex_byte_value ; -_octal_byte_value : `\` _octal_digit _octal_digit _octal_digit ; -_hex_byte_value : `\` "x" _hex_digit _hex_digit ; -_little_u_value : `\` "u" _hex_digit _hex_digit _hex_digit _hex_digit ; -_big_u_value : `\` "U" _hex_digit _hex_digit _hex_digit _hex_digit - _hex_digit _hex_digit _hex_digit _hex_digit ; -_escaped_char : `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | `'` | `"` ) ; +Symbols : + Symbol + << ast.NewSyntaxSymbols($0) >> + | + Symbols + Symbol + << ast.AddSyntaxSymbol($0, $1) >> +; -id : _letter (_letter | _digit)* ; +Symbol : + prodId + << ast.NewSyntaxProdId($0) >> + | + tokId + << ast.NewTokId($0) >> + | + string_lit + << ast.NewStringLit($0) >> + | + tokId + g_ctxdep_lit + << ast.NewContextDependentTokId($0,$1) >> + | + "@" + tokId + string_lit + << ast.NewAliasedSubParser($1,$2) >> + | + "@" + string_lit + << ast.NewSubParser($1) >> +; -string : _raw_string | _interpreted_string ; -_raw_string : "`" _unicode_char* "`" ; -_interpreted_string : `"` ( _unicode_value | byte_value )* `"` ; +ErrorSymbol : + "error" + | + "λ" +; -g_sdt_lit : '<' '<' _unicode_char+ '>' '>' -**********/ +EpsilonSymbol : + "empty" + | + "ε" +; -/*** TODO: *** -1. Handle reserved words correctly so that user cannot write reserved words in his grammar. E.g.: string_lit, prodId, etc. -***/ diff --git a/stock/main.go b/stock/main.go new file mode 100644 index 00000000..533c53af --- /dev/null +++ b/stock/main.go @@ -0,0 +1,182 @@ +//Copyright 2013 Vastech SA (PTY) LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//Gocc is LR1 parser generator for go written in go. The generator uses a BNF with very easy to use SDT rules. +//Please see https://github.com/goccmack/gocc/ for more documentation. + +package main + +import ( + "bytes" + "flag" + "fmt" + "io/ioutil" + "os" + "path" + "strings" + + "github.com/maxcalandrelli/gocc/internal/ast" + genBase "github.com/maxcalandrelli/gocc/internal/base/gen" + "github.com/maxcalandrelli/gocc/internal/config" + oldparser "github.com/maxcalandrelli/gocc/internal/frontend/stock/parser" + oldscanner "github.com/maxcalandrelli/gocc/internal/frontend/stock/scanner" + oldtoken "github.com/maxcalandrelli/gocc/internal/frontend/stock/token" + "github.com/maxcalandrelli/gocc/internal/io" + genIo "github.com/maxcalandrelli/gocc/internal/io/gen" + genLexer "github.com/maxcalandrelli/gocc/internal/lexer/gen/golang" + lexItems "github.com/maxcalandrelli/gocc/internal/lexer/items" + "github.com/maxcalandrelli/gocc/internal/parser/first" + genParser "github.com/maxcalandrelli/gocc/internal/parser/gen" + lr1Action "github.com/maxcalandrelli/gocc/internal/parser/lr1/action" + lr1Items "github.com/maxcalandrelli/gocc/internal/parser/lr1/items" + "github.com/maxcalandrelli/gocc/internal/parser/symbols" + outToken "github.com/maxcalandrelli/gocc/internal/token" + genToken "github.com/maxcalandrelli/gocc/internal/token/gen" + genUtil "github.com/maxcalandrelli/gocc/internal/util/gen" +) + +func main() { + flag.Usage = usage + cfg, err := config.New() + if err != nil { + fmt.Printf("Error reading configuration: %s\n", err) + flag.Usage() + } + + if cfg.Verbose() { + fmt.Fprintf(os.Stderr, "gocc (stock) version %s\n", config.VERSION) + cfg.PrintParams() + } + + if cfg.Help() { + fmt.Fprintf(os.Stderr, "gocc (stock) version %s\n", config.VERSION) + flag.Usage() + } + + config.CurrentConfiguration = cfg + + srcBuffer, err := ioutil.ReadFile(cfg.SourceFile()) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + var ( + grammar interface{} + ) + ast.StringGetter = func(v interface{}) string { return string(v.(*oldtoken.Token).Lit) } + scanner := &oldscanner.Scanner{} + scanner.Init(srcBuffer, oldtoken.FRONTENDTokens) + parser := oldparser.NewParser(oldparser.ActionTable, oldparser.GotoTable, oldparser.ProductionsTable, oldtoken.FRONTENDTokens) + grammar, err = parser.Parse(scanner) + if err != nil { + fmt.Printf("Parse error: %s\n", err) + os.Exit(1) + } + + outdir_base := cfg.OutDir() + outdir_log := path.Join(outdir_base, "log") + outdir_iface := path.Join("iface") + g := grammar.(*ast.Grammar) + + gSymbols := symbols.NewSymbols(g) + if cfg.Verbose() { + writeTerminals(gSymbols, cfg, outdir_log) + } + + gSymbols.Add(g.LexPart.TokenIds()...) + g.LexPart.UpdateStringLitTokens(gSymbols.ListStringLitSymbols()) + lexSets := lexItems.GetItemSets(g.LexPart, cfg.BugOption("lexer_dots").Fix(), cfg.BugOption("lexer_regdefs").Fix()) + if cfg.Verbose() { + io.WriteFileString(path.Join(outdir_log, "lexer_sets.txt"), lexSets.String()) + } + tokenMap := outToken.NewTokenMap(gSymbols.ListTerminals()) + if !cfg.NoLexer() { + genLexer.Gen(cfg.Package(), outdir_base, g.LexPart.Header.SDTLit, lexSets, tokenMap, cfg, cfg.InternalSubdir(), outdir_iface) + } + + hasSyntax := (g.SyntaxPart != nil) + if hasSyntax { + firstSets := first.GetFirstSets(g, gSymbols) + if cfg.Verbose() { + io.WriteFileString(path.Join(outdir_log, "first.txt"), firstSets.String()) + } + + lr1Sets := lr1Items.GetItemSets(g, gSymbols, firstSets) + if cfg.Verbose() { + io.WriteFileString(path.Join(outdir_log, "LR1_sets.txt"), lr1Sets.String()) + } + + conflicts := genParser.Gen(cfg.Package(), outdir_base, g.SyntaxPart.Header.SDTLit, g.SyntaxPart.ProdList, gSymbols, lr1Sets, tokenMap, cfg, cfg.InternalSubdir(), outdir_iface) + handleConflicts(conflicts, lr1Sets.Size(), cfg, g.SyntaxPart.ProdList, outdir_log) + } + + genToken.Gen(cfg.Package(), outdir_base, tokenMap, cfg.InternalSubdir(), cfg) + genUtil.Gen(outdir_base, cfg.InternalSubdir()) + genBase.Gen(cfg.Package(), outdir_base, cfg.InternalSubdir(), outdir_iface, cfg, hasSyntax) + genIo.Gen(cfg.Package(), outdir_base, cfg.InternalSubdir()) +} + +func usage() { + fmt.Fprintf(os.Stderr, "usage: gocc flags bnf_file\n\n") + fmt.Fprintf(os.Stderr, " bnf_file: contains the BNF grammar\n\n") + fmt.Fprintf(os.Stderr, "Flags:\n") + flag.PrintDefaults() + os.Exit(1) +} + +func handleConflicts(conflicts map[int]lr1Items.RowConflicts, numSets int, cfg config.Config, prods ast.SyntaxProdList, outdir string) { + if len(conflicts) <= 0 { + return + } + fmt.Printf("%d LR-1 conflicts \n", len(conflicts)) + if cfg.Verbose() { + io.WriteFileString(path.Join(outdir, "LR1_conflicts.txt"), conflictString(conflicts, numSets, prods)) + } + if !cfg.AutoResolveLRConf() { + os.Exit(1) + } +} + +func conflictString(conflicts map[int]lr1Items.RowConflicts, numSets int, prods ast.SyntaxProdList) string { + w := new(strings.Builder) + fmt.Fprintf(w, "%d LR-1 conflicts: \n", len(conflicts)) + for i := 0; i < numSets; i++ { + if cnf, exist := conflicts[i]; exist { + fmt.Fprintf(w, "\tS%d\n", i) + for sym, conflicts := range cnf { + fmt.Fprintf(w, "\t\tsymbol: %s\n", sym) + for _, cflct := range conflicts { + switch c := cflct.(type) { + case lr1Action.Reduce: + fmt.Fprintf(w, "\t\t\tReduce(%d:%s)\n", c, prods[c]) + case lr1Action.Shift: + fmt.Fprintf(w, "\t\t\t%s\n", cflct) + default: + panic(fmt.Sprintf("unexpected type of action: %s", cflct)) + } + } + } + } + } + return w.String() +} + +func writeTerminals(gSymbols *symbols.Symbols, cfg config.Config, outdir string) { + buf := new(bytes.Buffer) + for _, t := range gSymbols.ListTerminals() { + fmt.Fprintf(buf, "%s\n", t) + } + io.WriteFile(path.Join(outdir, "terminals.txt"), buf.Bytes()) +}