lex

package
v0.0.0-...-a214d60 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2024 License: BSD-3-Clause Imports: 7 Imported by: 0

README

U语言词法分析器设计文档

前置描述

本文档描述了u语言词法分析器(以下简称lex),用VS Code + 扩展(Markdown Preview Enhanced)编写

最后更新时间 : 2023/10/30

公开API

lex的实现将n行(n>0)的已经去除换行符的字符串做为接收的输入,输出为按行数升序排列好的每行词法单元

lex进行词法分析的公开的API为

// Lex 进行词法分析
//   - file是文件名
//   - Len是识别行数
//   - value是已经分好行的待识别代码,必须已经去除换行符
//   - errctx是错误处理上下文
//   - EnableSinLineComments 是否启用多行注释,除非为了格式化文件,否则应该为false
func Lex(file string, Len int, value []string, errctx *errcode.ErrCtx, EnableSinLineComments bool) *FileToken

返回值的定义为

// 一个文件的词法分析结果
type FileToken struct {
    // 文件名
    File string
    // 按行数升序排列的每行词法标记
    Value []Line
}
// 一行的单词标记
type Line struct {
    // 行数
    Linenum int
    //从开头到结尾的单词标记
    Value []Token
}
// Token 单词标记 代表一个最小词法单元
type Token struct {
    // 种别码
    TYPE TokenType
    // 属性值
    Value string
}

Token(单词标记) 保存了种别码和属性值<br>{=html} Line(一行的单词标记) 保存了一行从开头到结尾的单词标记和行数<br>{=html} FileToken 保存了一个文件的词法分析结果,包含文件名,n个一行的单词标记(n>=0)<br>{=html}

词法分析的过程是

  1. 创建一个文件的词法分析结果
  2. 调用Scan(一行扫描器)分析出一行的所有单词标记
  3. 将分析出的一行的所有单词标记保存在一个文件的词法分析结果的Value字段的行数-1偏移量里
  4. 重复2-3直到所有行都已经扫描完毕

一行扫描器(Scan)

一行扫描器(Scan)是lex实现词法分析的关键步骤,接收一行的字符串,必须已经去除换行符,输出这一行的所有单词标记

一行扫描器从左到右对字符串进行扫描,按照下列规则进行分析为单词标记

定义下列为分隔符

  • 空格
  • 制表符
  • 有语义的符号指运算符或括号(例如加号,左小括号,小于号)

到扫描发现分隔符时,此时的现状如下图示

对于分隔符,空格和制表符被忽略,有语义的符号除了例外被分析为种别码为有语义的符号对应的种别码,属性值为被分析的值的单词标记

例外是 :

  • // 被视为注释,这个值以及之后的字符串都将被忽略
  • /* 被视为多行注释开头, */ 被视为多行注释结束,之间的字符串都将被忽略
  • &如果后跟着一个标识符,不单独识别,而是和分隔符右一起识别,比如&a被分析为种别码为&对于的种别码,属性值为&a
  • @如果后跟着一个标识符,不单独识别,而是和分隔符右一起识别,比如@a被分析为种别码为&对于的种别码,属性值为@a
  • " 如果前边是 \ ,转义为字符串中的字符
  • 发现一个",不单独识别,而是和分隔符右一起识别,将一组在左边没有转义的"和右边没有转义的"连同之间的内容一起分析为字符串
  • 如果是and,并且右边没有分隔符,不识别为位与操作符
  • 如果是左中括号,不单独识别,而是和后面最近的包括自身左右中括号数量相等的字符串一起识别为,种别码为带中括号的Token,属性值为这个字符串
  • -如果后面是整数,前面是赋值或逗号或左小括号或相等或不等或if或小于或大于,识别为整数
  • -如果后面是浮点数,前面是赋值或逗号或左小括号或相等或不等或if或小于或大于,识别为浮点数

分隔符左和分隔符右可能为空,如果不为空且没有被上述规则处理,则按下列规则识别为单词标记

  • 如果是例如var这种预定义的关键字,分析为种别码为对应关键字的种别码,属性值为关键字的值的单词标记
  • 如果是数字,分析为种别码为整数或浮点数对应的种别码,属性值为被分析的值的单词标记
  • 如果是布尔值,分析为种别码为true或false对应的种别码,属性值为被分析的值的单词标记
  • 如果其他规则不能成功分析出单词标记,分析为符号
  • 如果前面是符号或取地址或不止有中括号的Token,后面是带中括号的Token,合并为不止有中括号的Token
  • 如果前面是带中括号的Token,后面是符号或取地址或不止中括号的Token,合并为不止有中括号的Token

附注

将语言规范描述的索引表达式或数组类型,识别为一个Token是因为构建抽象语法树的解析算法依赖类型或一个值只有一个Token的假设

Documentation

Overview

Package lex 实现了词法分析器

对于大多数使用者, Lex 是唯一一个使用的函数

Index

Constants

This section is empty.

Variables

View Source
var (
	TokenStrMap = [...]string{
		No:                            "no (没有表示)",
		NAME:                          "name (符号)",
		ASSIGN:                        "assign (赋值)",
		VAR:                           "var (变量声明)",
		FUNC:                          "func (函数声明)",
		ADD:                           "add (加号)",
		SUB:                           "sub (减号)",
		MUL:                           "mul (乘号)",
		DIV:                           "dlv (除号)",
		LBRACE:                        "lbrace (左大括号)",
		RBRACE:                        "rbrace (右大括号)",
		NUMBER:                        "number (数字)",
		FLOAT:                         "float (浮点数)",
		NoEqual:                       "no equal (不相等)",
		Equal:                         "equal (相等)",
		Less:                          "less (小于)",
		Greater:                       "greater (大于)",
		TRUE:                          "true",
		FALSE:                         "false",
		IF:                            "if",
		ELSE:                          "else",
		FOR:                           "for",
		Break:                         "break",
		Continue:                      "continue",
		Struct:                        "struct",
		Interface:                     "interface",
		LEA:                           "lea (取地址)",
		OnlyLEA:                       "onlylea (&)",
		MLCStart:                      "multiline comment start (多行注释开头)",
		MLCEnd:                        "multiline comment end (多行注释结束)",
		MLCIn:                         "multiline comment in (多行注释之间)",
		String:                        "string (字符串)",
		SEMICOLON:                     "semicolon(分号)",
		Return:                        "return (返回)",
		LPAREN:                        "lparen (左小括号)",
		RPAREN:                        "rparen (右小括号)",
		Comma:                         "comma (逗号)",
		GOTO:                          "goto",
		Colon:                         "colon (冒号)",
		Remain:                        "remainder (取余数)",
		Deref:                         "dereference (解引用)",
		OnlyDeref:                     "OnlyDeref (@)",
		Const:                         "const (常量)",
		Inc:                           "Increment (自增)",
		Dec:                           "Decrement (自减)",
		Nil:                           "nil (指针的零值)",
		Package:                       "package (包声明)",
		Switch:                        "switch",
		Case:                          "case",
		Default:                       "default",
		Method:                        "method (方法)",
		AutoFree:                      "autofree (自动释放块)",
		SinLineComments:               "Single-Line Comments (单行注释)",
		AND:                           "AND (位与运算)",
		Or:                            "Or (位或运算)",
		Xor:                           "Xor (异或运算)",
		LogicAND:                      "logic and (逻辑与)",
		LogicOr:                       "logic or (逻辑或)",
		Import:                        "import (导入)",
		Enum:                          "enum (枚举)",
		TokenWithBrackets:             "TokenWithBrackets (带中括号的Token)",
		MoreThanJustTokensWithBrackts: "MoreThanJustTokensWithBrackts (不止有中括号的Token)",
	}
)

Functions

This section is empty.

Types

type FileToken

type FileToken struct {
	// 文件名
	File string
	// 按行数升序排列的每行词法标记
	Value []Line
}

一个文件的词法分析结果

func Lex

func Lex(file string, value []string, errctx *errcode.ErrCtx, EnableSinLineComments bool) *FileToken

Lex 进行词法分析

  • file是文件名
  • value是已经分好行的待识别代码,必须已经去除换行符
  • errctx是错误处理上下文
  • EnableSinLineComments 是否启用多行注释,除非为了格式化文件,否则应该为false

func Lex2

func Lex2(file string, value *bufio.Reader, errctx *errcode.ErrCtx, EnableSinLineComments bool) *FileToken

Lex2 进行词法分析

  • file是文件名
  • value是待分析代码
  • errctx是错误处理上下文
  • EnableSinLineComments 是否启用多行注释,除非为了格式化文件,否则应该为false

func NewFileToken

func NewFileToken(file string, Len int) *FileToken

NewFileToken 创建一个文件的词法分析结果

  • file是文件名
  • Len是识别行数
  • Thread是控制是否并发

func (*FileToken) LineAdd

func (ft *FileToken) LineAdd(line int, Value Line)

LineAdd 记录一行的词法分析结果

  • line是行数
  • Value是一行的词法分析结果

func (*FileToken) String

func (ft *FileToken) String() string

type Line

type Line struct {
	//从开头到结尾的单词标记
	Value []Token
	//行号
	Linenum int
}

一行的单词标记

func NewLine

func NewLine(num int, tk []Token) Line

NewLine 创建一行的标记

func (Line) String

func (l Line) String() string

type MoreThanJustTokensWithBracktsS

type MoreThanJustTokensWithBracktsS struct {
	Ptr *[]Token
}

MoreThanJustTokensWithBracktsS 不止有中括号的Token结构体

type Scan

type Scan struct {
	ScanConfig
	// contains filtered or unexported fields
}

Scan 一行扫描器 分析一行的词法单元

func NewScan

func NewScan(s string, cf ScanConfig) Scan

NewScan 创建Scan

  • s要进行分析的一行字符串,必须已经去除换行符
  • cf是一些非必须的参数

func (*Scan) AllScan

func (s *Scan) AllScan() []Token

AllScan 返回所有的词法单元

func (*Scan) Reset

func (s *Scan) Reset(str string, Line int)

Reset 重新设置扫描的行和字符串

type ScanConfig

type ScanConfig struct {
	Errctx                *errcode.ErrCtx
	IsMLC                 *bool
	File                  string
	Line                  int
	EnableSinLineComments bool //是否启用单行注释
}

type Token

type Token struct {
	//属性值
	Value string
	//种别码
	TYPE TokenType
}

Token 单词标记 代表一个最小词法单元

func NewMoreThanJustTokensWithBrackts

func NewMoreThanJustTokensWithBrackts(tks ...Token) Token

NewMoreThanJustTokensWithBrackts 创建不止有中括号的Token

func NewToken

func NewToken(TYPE TokenType, value string) Token

NewToken 创建标记

func (*Token) PtrMoreThanJustTokensWithBracktsS

func (t *Token) PtrMoreThanJustTokensWithBracktsS() *MoreThanJustTokensWithBracktsS

PtrMoreThanJustTokensWithBracktsS 将 Token 的Value字段解释为 MoreThanJustTokensWithBracktsS 并返回指针

func (Token) String

func (t Token) String() string

type TokenType

type TokenType int

标记类型

const (
	No TokenType = iota
	NAME
	ASSIGN
	VAR
	FUNC
	ADD
	SUB
	MUL
	DIV
	LBRACE
	RBRACE
	NUMBER
	FLOAT
	NoEqual
	Equal
	Less
	Greater
	TRUE
	FALSE
	IF
	ELSE
	FOR
	Break
	Continue
	Struct
	Interface
	LEA
	OnlyLEA
	MLCStart //multiline comment
	MLCEnd
	MLCIn
	String
	SEMICOLON //semicolon分号
	Return
	LPAREN //Left parenthesis
	RPAREN //right parenthesis
	Comma
	GOTO
	Colon
	Remain
	Deref //dereference
	OnlyDeref
	Const
	Inc //Increment
	Dec //Decrement
	Nil
	Package
	Switch
	Case
	Default
	Method
	AutoFree
	SinLineComments //Single-Line Comments
	AND
	Or
	Xor
	LogicAND
	LogicOr
	Import
	Enum
	TokenWithBrackets
	MoreThanJustTokensWithBrackts //More than just tokens with brackets
)

func (TokenType) String

func (t TokenType) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL