当前位置: 首页 > article >正文

表达式翻译 一

在工作中会经常碰到,在一个框中由用户输入表达式,然后算出一个结果的情形,例如3 + 5 * (10 - 4);如何分析这个表达式呢?这其实涉及到一个常用的思路叫解释器.
它包括词法分析, 语法分析, 语义分析.

本章节只讲词法分析
词法分析就是将输入的字符串符号(例如关键字,常数,运算符等),分解成一系列的标记(Tokens)
既然是分析,那表达式中是否有错误, 在什么位置都能精确的定位
词法分析的任务:

  1. 过滤:空格、换行符、制表符、注释等
  2. 识别:根据构词规则,词法分析器识别出单词。这些单词包括标识符、关键字(保留字)、常数、运算符和界符等
  3. 将编译器生成的错误信息与源程序的位置联系起来

字符串中的加,减,乘,除,括号,关键字,数字,参数名等被称为标记

    // 标记类型,这里只列举了部分
    public enum TokenType
    {
        //数字
        Number,
        //+
        Plus,
        //-
        Minus,
        //*
        Multiply,
        //(
        LeftParen,
        //)
        RightParen,
        //结束
        EOF // End Of File
    }
    
	// 标记类
	public class Token
	{
	    public TokenType Type { get; }
	    public string Value { get; }
	
	    public Token(TokenType type, string value = "")
	    {
	        Type = type;
	        Value = value;
	    }
	}

下面我们添加词法分析类

    public class Lexer
    {
        private readonly string _text;
        private int _pos;
        private char _currentChar;

        public Lexer(string text)
        {
            _text = text;
            _pos = 0;
            _currentChar = _text[_pos];
        }
     }

词法分析时要一个字符一个字符的分析,所以我们增加一个读取下一个字符的方法

        // 读取下一个字符
        private void ReadNextChar()
        {
            _pos++;
            if (_pos >= _text.Length)
            {
                _currentChar = '\0'; // 表示EOF
            }
            else
            {
                _currentChar = _text[_pos];
            }
        }

如果表达式中有空格,我们要跳过空格

                // 跳过空白字符
        private void SkipWhitespace()
        {
            while (_currentChar != '\0' && char.IsWhiteSpace(_currentChar))
            {
                ReadNextChar();
            }
        }

下面就要开始形成标记Token,以数字为例
读取数字标记

        // 读取数字标记
        private Token Number()
        {
            string result = "";
            while (_currentChar != '\0' && char.IsDigit(_currentChar))
            {
                result += _currentChar;
                ReadNextChar();
            }
            return new Token(TokenType.Number, result);
        }

读取所有标记

// 读取标记
public Token GetNextToken()
{
    SkipWhitespace();

    if (_currentChar == '+')
    {
        ReadNextChar();
        return new Token(TokenType.Plus);
    }
    else if (_currentChar == '-')
    {
        ReadNextChar();
        return new Token(TokenType.Minus);
    }
    else if (_currentChar == '*')
    {
        ReadNextChar();
        return new Token(TokenType.Multiply);
    }
    else if (_currentChar == '(')
    {
        ReadNextChar();
        return new Token(TokenType.LeftParen);
    }
    else if (_currentChar == ')')
    {
        ReadNextChar();
        return new Token(TokenType.RightParen);
    }
    else if (char.IsDigit(_currentChar))
    {
        return Number();
    }
    else if (_currentChar == '\0')
    {
        return new Token(TokenType.EOF);
    }
    else
    {
        throw new Exception("Invalid character");
    }
}

http://www.kler.cn/a/473101.html

相关文章:

  • 数据结构(1~10)
  • Ubuntu上安装Apache Spark
  • ADO.NET知识总结3---SqlCommand命令对象
  • 行情系统用什么数据库好
  • arcgisPro加载CGCS2000天地图后,如何转成米单位
  • 机器人技术:ModbusTCP转CCLINKIE网关应用
  • Agentic AI 深度剖析
  • Spark创建多种数据格式的DataFrame
  • 消息队列:原理、问题与设计全解析
  • BERT模型详解及代码复现
  • JAVA学习记录3
  • vue之element-ui文件上传(二)
  • Blockly 二次封装
  • 沁恒CH32V208GBU6定时器:开启定时器读取RSSI并且定时器单位为广播间隔单位一样;自动重装载定时器与关闭定时器
  • Elasticsearch(三)
  • 解决SSH连接时遇到的“远程主机身份验证已更改 (WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!)”警告
  • 八万字Java面试高频题目汇总(冲刺春招!)
  • Lua语言的函数实现
  • Objective-C语言的文件操作
  • wireshark抓包工具新手使用教程
  • .NET Core + Kafka 开发指南
  • MySQL 数据库分片技术指南
  • 数据库中锁与ETL的故障排除和性能优化
  • 【微服务】8、分布式事务 ( XA 和 AT )
  • Perl语言的文件操作
  • DeviceNet转Profinet网关如何革新污水处理行业!