SHS/ast/token.go

162 lines
3.4 KiB
Go
Raw Normal View History

2019-11-29 12:57:03 -08:00
/* SHS: Syntactically Homogeneous Shell
* Copyright (C) 2019 Aidan Hahn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ast
2019-11-12 12:24:45 -08:00
2020-06-29 00:06:53 -07:00
import "fmt"
2019-11-12 12:24:45 -08:00
type Token_t int
const (
LIST Token_t = iota
STRING Token_t = iota
NUMBER Token_t = iota
SYMBOL Token_t = iota
2020-06-28 20:06:55 -07:00
BOOL Token_t = iota
TRUE string = "T"
FALSE string = "F"
)
2019-11-12 12:24:45 -08:00
type Token struct {
Next *Token
Tag Token_t
Position int
2020-06-29 00:06:53 -07:00
inner interface{}
2019-11-12 12:24:45 -08:00
}
2020-06-29 00:06:53 -07:00
/* Appends another token to the end of this token list
*/
func (t *Token) Append(arg *Token) {
if t.Next != nil {
t.Next.Append(arg)
} else {
t.Next = arg
2019-11-28 22:43:30 -08:00
}
2020-06-29 00:06:53 -07:00
}
2019-11-28 22:43:30 -08:00
2020-06-29 00:06:53 -07:00
/* Print function which is better suited for repl.
* This one prints the SEXPRs as one would write them.
* Does not evaluate tokens.
*/
func (t *Token) String() string {
switch t.Tag {
case STRING:
return "\"" + t.inner.(string) + "\""
case NUMBER, BOOL:
return t.inner.(string)
case LIST:
repr := "("
if t.inner.(*Token) == nil {
return repr + ")"
}
2020-06-29 00:06:53 -07:00
for i := t.inner.(*Token); i != nil; i = i.Next {
repr = repr + i.String() + " "
2019-11-28 22:43:30 -08:00
}
2020-06-29 00:06:53 -07:00
// remove trailing space
return repr[:len(repr)-1] + ")"
2019-11-28 22:43:30 -08:00
2020-06-29 00:06:53 -07:00
case SYMBOL:
return "<" + t.inner.(string) + ">"
2019-11-28 22:43:30 -08:00
}
2020-06-29 00:06:53 -07:00
return "[UNKNOWN CELL TYPE]"
}
2019-11-18 23:24:33 -08:00
2020-06-29 00:06:53 -07:00
/* Returns a list held by a token
* returns nil if token holds no list
*/
func (t *Token) Expand() *Token {
if t.Tag != LIST {
return nil
2019-11-29 19:02:30 -08:00
}
2019-11-16 16:16:05 -08:00
2020-06-29 00:06:53 -07:00
return t.inner.(*Token)
}
2019-11-29 19:02:30 -08:00
2020-06-29 00:06:53 -07:00
/* Sets inner to a Token value
* returns false if parent token is not a list
* otherwise returns true
*/
func (t *Token) Direct(head *Token) bool {
if t.Tag != LIST {
return false
2019-11-28 22:43:30 -08:00
}
2019-11-12 13:09:31 -08:00
2020-06-29 00:06:53 -07:00
t.inner = head
return true
}
2019-11-12 13:09:31 -08:00
2020-06-29 00:06:53 -07:00
/* If token holds an atomic value
* (not a symbol or list)
* will return its value as a string
* else returns ""
*/
func (t *Token) Value() string {
if t.Tag == LIST {
return ""
2019-11-29 19:02:30 -08:00
}
2020-06-29 00:06:53 -07:00
return t.inner.(string)
2019-11-12 13:09:31 -08:00
}
2020-06-29 00:06:53 -07:00
/* returns an ascii representation of a token
*/
func (t *Token) FmtToken() string {
suffix := "->"
if t.Next == nil {
suffix = ""
}
2020-06-29 00:06:53 -07:00
switch t.Tag {
case LIST:
return fmt.Sprintf("(%s, [List])%s", "LIST", suffix)
default:
return fmt.Sprintf("(%s, %s)%s", GetTagAsStr(t.Tag), t.inner.(string), suffix)
}
}
/* Sets the string value for a non-list token
*/
func (t *Token) Set(arg string) bool {
if t.Tag == LIST {
return false
}
t.inner = arg
return true
}
2020-06-29 00:06:53 -07:00
/* Returns a tag in text
*/
func GetTagAsStr(tag Token_t) string {
switch tag {
case LIST:
return "LIST"
case STRING:
return "STRING"
case NUMBER:
return "NUMBER"
case SYMBOL:
return "SYMBOL"
}
return "UNKNOWN"
}