123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- /*
- * Public Domain Software
- *
- * I (Matthias Ladkau) am the author of the source code in this file.
- * I have placed the source code in this file in the public domain.
- *
- * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
- */
- package parser
- import (
- "bytes"
- "fmt"
- "devt.de/krotik/common/datautil"
- "devt.de/krotik/common/stringutil"
- )
- // AST Nodes
- // =========
- /*
- ASTNode models a node in the AST
- */
- type ASTNode struct {
- Name string // Name of the node
- Token *LexToken // Lexer token of this ASTNode
- Children []*ASTNode // Child nodes
- Runtime Runtime // Runtime component for this ASTNode
- binding int // Binding power of this node
- nullDenotation func(p *parser, self *ASTNode) (*ASTNode, error) // Configure token as beginning node
- leftDenotation func(p *parser, self *ASTNode, left *ASTNode) (*ASTNode, error) // Configure token as left node
- }
- /*
- Create a new instance of this ASTNode which is connected to a concrete lexer token.
- */
- func (n *ASTNode) instance(p *parser, t *LexToken) *ASTNode {
- ret := &ASTNode{n.Name, t, make([]*ASTNode, 0, 2), nil, n.binding, n.nullDenotation, n.leftDenotation}
- if p.rp != nil {
- ret.Runtime = p.rp.Runtime(ret)
- }
- return ret
- }
- /*
- String returns a string representation of this token.
- */
- func (n *ASTNode) String() string {
- var buf bytes.Buffer
- n.levelString(0, &buf)
- return buf.String()
- }
- /*
- levelString function to recursively print the tree.
- */
- func (n *ASTNode) levelString(indent int, buf *bytes.Buffer) {
- // Print current level
- buf.WriteString(stringutil.GenerateRollingString(" ", indent*2))
- if n.Name == NodeCOMMENT {
- buf.WriteString(fmt.Sprintf("%v: %20v", n.Name, n.Token.Val))
- } else if n.Name == NodeSTRING {
- buf.WriteString(fmt.Sprintf("%v: '%v'", n.Name, n.Token.Val))
- } else if n.Name == NodeNUMBER {
- buf.WriteString(fmt.Sprintf("%v: %v", n.Name, n.Token.Val))
- } else if n.Name == NodeIDENTIFIER {
- buf.WriteString(fmt.Sprintf("%v: %v", n.Name, n.Token.Val))
- } else {
- buf.WriteString(n.Name)
- }
- buf.WriteString("\n")
- // Print children
- for _, child := range n.Children {
- child.levelString(indent+1, buf)
- }
- }
- // Look ahead buffer
- // =================
- /*
- ASTNode models a node in the AST
- */
- type LABuffer struct {
- tokens chan LexToken
- buffer *datautil.RingBuffer
- }
- /*
- Create a new instance of this ASTNode which is connected to a concrete lexer token.
- */
- func NewLABuffer(c chan LexToken, size int) *LABuffer {
- if size < 1 {
- size = 1
- }
- ret := &LABuffer{c, datautil.NewRingBuffer(size)}
- v, more := <-ret.tokens
- ret.buffer.Add(v)
- for ret.buffer.Size() < size && more && v.ID != TokenEOF {
- v, more = <-ret.tokens
- ret.buffer.Add(v)
- }
- return ret
- }
- /*
- Next returns the next item.
- */
- func (b *LABuffer) Next() (LexToken, bool) {
- ret := b.buffer.Poll()
- if v, more := <-b.tokens; more {
- b.buffer.Add(v)
- }
- if ret == nil {
- return LexToken{ID: TokenEOF}, false
- }
- return ret.(LexToken), true
- }
- /*
- Peek looks inside the buffer starting with 0 as the next item.
- */
- func (b *LABuffer) Peek(pos int) (LexToken, bool) {
- if pos >= b.buffer.Size() {
- return LexToken{ID: TokenEOF}, false
- }
- return b.buffer.Get(pos).(LexToken), true
- }
|