/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. */ package parser import ( "errors" "fmt" ) func NewUnrecognized(msg string, val rune) error { return &UnrecognizedInputError{msg: msg, val: val} } type UnrecognizedInputError struct { msg string val rune } func (e *UnrecognizedInputError) Error() string { return fmt.Sprintf("%s: unrecognized input: '%s'", e.msg, string(e.val)) } func (e *UnrecognizedInputError) Unwrap() error { return e } type SM struct { stack []*CSTNode line, col int } func (m *SM) Top() *CSTNode { return m.stack[len(m.stack)-1] } func (m *SM) Push(t ASTNode) ASTNode { m.stack = append(m.stack, &CSTNode{ASTNode: t}) return t } func (m *SM) shift(e rune) (err error) { m.col++ for { err = m.Top().ASTNode.Shift(m, e) if !errors.Is(err, &UnrecognizedInputError{}) { break } if !m.reduce() { break } } return err } func (m *SM) reduce() bool { if len(m.stack) < 2 { return false } last := len(m.stack) - 1 nodes := m.stack[last-1].Nodes nodes = append(nodes, m.stack[last]) m.stack[last-1].Nodes = nodes m.stack = m.stack[:last] return true }