提交 5d44a69c 编写于 作者: chai2010's avatar chai2010

完善 wat 解析包

上级 f1a02f30
// 版权 @2023 凹语言 作者。保留所有权利。
package wat
// 将 wat 转化为 token 列表
func Tokenize(filename, input string) (tokens, comments []Token) {
l := newLexer(filename, input)
tokens = l.Tokens()
comments = l.Comments()
return
}
// 解析模块文件
func ParseFile(filename, input string) (*Module, error) {
panic("TODO")
}
// 版权 @2023 凹语言 作者。保留所有权利。
package wat_test
// 版权 @2023 凹语言 作者。保留所有权利。
package wat
import (
"fmt"
)
func waLex(name, input string) (tokens, comments []Token) {
l := newLexer(name, input)
tokens = l.Tokens()
comments = l.Comments()
return
}
type watLexer struct {
src *watSourceStream
tokens []Token
comments []Token
}
func newLexer(name, input string) *watLexer {
return &watLexer{
src: newSourceStream(name, input),
}
}
func (p *watLexer) Tokens() []Token {
if len(p.tokens) == 0 {
p.run()
}
return p.tokens
}
func (p *watLexer) Comments() []Token {
if len(p.tokens) == 0 {
p.run()
}
return p.comments
}
func (p *watLexer) emit(kind TokenKind) {
lit, pos := p.src.EmitToken()
_ = pos
if kind == EOF {
pos = p.src.Pos()
lit = ""
}
if kind == IDENT {
kind = watLookup(lit)
}
p.tokens = append(p.tokens, Token{
Kind: kind,
Literal: lit,
//Pos: Pos(pos + 1),
})
}
func (p *watLexer) emitComment() {
lit, pos := p.src.EmitToken()
_ = pos
p.comments = append(p.comments, Token{
Kind: COMMENT,
Literal: lit,
// Pos: Pos(pos + 1),
})
}
func (p *watLexer) errorf(format string, args ...interface{}) {
tok := Token{
//Kind: ERROR,
Literal: fmt.Sprintf(format, args...),
//Pos: Pos(p.src.Pos() + 1),
}
p.tokens = append(p.tokens, tok)
panic(tok)
}
func (p *watLexer) run() (tokens []Token) {
defer func() {
tokens = p.tokens
if r := recover(); r != nil {
if _, ok := r.(Token); !ok {
panic(r)
}
}
}()
for {
r := p.src.Read()
if r == rune(EOF) {
p.emit(EOF)
return
}
switch {
// TODO: case xxx
default:
p.errorf("unrecognized character: %#U", r)
return
}
}
}
package wat
import (
"fmt"
)
// Pos 类似一个指针, 表示文件中的位置.
type Pos int
// NoPos 类似指针的 nil 值, 表示一个无效的位置.
const NoPos Pos = 0
func (p Pos) IsValid() bool {
return p != NoPos
}
// Pos 装行列号位置
func (pos Pos) Position(filename, src string) Position {
if !pos.IsValid() {
return Position{
Filename: filename,
}
}
var p = Position{
Filename: filename,
Offset: int(pos) - 1,
Line: 1,
Column: 1,
}
for _, c := range []byte(src[:p.Offset]) {
p.Column++
if c == '\n' {
p.Column = 1
p.Line++
}
}
return p
}
// 行列号位置
type Position struct {
Filename string // 文件名
Offset int // 偏移量, 从 0 开始
Line int // 行号, 从 1 开始
Column int // 列号, 从 1 开始
}
func (pos *Position) IsValid() bool {
return pos.Line > 0
}
// String returns a string in one of several forms:
//
// file:line:column valid position with file name
// file:line valid position with file name but no column (column == 0)
// line:column valid position without file name
// line valid position without file name and no column (column == 0)
// file invalid position with file name
// - invalid position without file name
//
func (pos Position) String() string {
s := pos.Filename
if pos.IsValid() {
if s != "" {
s += ":"
}
s += fmt.Sprintf("%d", pos.Line)
if pos.Column != 0 {
s += fmt.Sprintf(":%d", pos.Column)
}
}
if s == "" {
s = "-"
}
return s
}
// 版权 @2023 凹语言 作者。保留所有权利。
package wat
import (
"strings"
"unicode/utf8"
)
type watSourceStream struct {
name string // 文件名
input string // 输入的源代码
start int // 当前正解析中的记号的开始位置
pos int // 当前读取的位置
width int // 最后一次读取utf8字符的字节宽度, 用于回退
}
func newSourceStream(name, src string) *watSourceStream {
return &watSourceStream{name: name, input: src}
}
func (p *watSourceStream) Name() string {
return p.name
}
func (p *watSourceStream) Input() string {
return p.input
}
func (p *watSourceStream) Pos() int {
return p.pos
}
func (p *watSourceStream) Peek() rune {
x := p.Read()
p.Unread()
return x
}
func (p *watSourceStream) Read() rune {
if p.pos >= len(p.input) {
p.width = 0
return 0
}
r, size := utf8.DecodeRune([]byte(p.input[p.pos:]))
p.width = size
p.pos += p.width
return r
}
func (p *watSourceStream) Unread() {
p.pos -= p.width
return
}
func (p *watSourceStream) Accept(valid string) bool {
if strings.IndexRune(valid, rune(p.Read())) >= 0 {
return true
}
return false
}
func (p *watSourceStream) AcceptRun(valid string) (ok bool) {
for p.Accept(valid) {
ok = true
}
p.Unread()
return
}
func (p *watSourceStream) EmitToken() (lit string, pos int) {
lit, pos = p.input[p.start:p.pos], p.start
p.start = p.pos
return
}
func (p *watSourceStream) IgnoreToken() {
_, _ = p.EmitToken()
}
......@@ -2,18 +2,16 @@
package wat
import (
"fmt"
"strconv"
)
// Token 结构
type Token struct {
Pos TokenPos // 位置
Kind TokenKind // 类型
Value string // 面值
}
// 位置信息
type TokenPos struct {
Offset int // offset, 从 0 开始
Line int // 行号, 从 1 开始
Column int // 列号, 从 1 开始的字节数
Pos Pos // 位置
Kind TokenKind // 类型
Literal string // 程序中原始的字符串
}
// 记号类型
......@@ -69,7 +67,54 @@ const (
keyword_end
)
// 将 wat 转化为 token 列表
func Tokenize(input []byte) []Token {
return nil
var tokens = [...]string{
// TODO
}
func (tok Token) String() string {
return fmt.Sprintf("%v:%q", tok.Kind, tok.Literal)
}
func (tokType TokenKind) String() string {
s := ""
if 0 <= tokType && tokType < TokenKind(len(tokens)) {
s = tokens[tokType]
}
if s == "" {
s = "token(" + strconv.Itoa(int(tokType)) + ")"
}
return s
}
var keywords = map[string]TokenKind{
// TODO
}
func watLookup(ident string) TokenKind {
if tok, isKeyword := keywords[ident]; isKeyword {
return tok
}
return IDENT
}
func (i Token) IntValue() int64 {
x, err := strconv.ParseInt(i.Literal, 10, 64)
if err != nil {
panic(err)
}
return x
}
func (i Token) FloatValue() float64 {
x, err := strconv.ParseFloat(i.Literal, 64)
if err != nil {
panic(err)
}
return x
}
func (i Token) StrValue() string {
x, err := strconv.Unquote(i.Literal)
if err != nil {
panic(err)
}
return x
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册