自然语言式parsing
got NUM(1)
Is NUM(1) an expr?
Is NUM(1) a term?
Is NUM(1) a number?
is_term got -(-)
-(-) was back
is_expr got -(-)
is_expr got NUM(2)
Is NUM(2) an expr?
Is NUM(2) a term?
Is NUM(2) a number?
is_term got *(*)
is_term got NUM(33)
Is NUM(33) a term?
Is NUM(33) a number?
is_term got None
is_expr got None import ply.lex as lex # pip install ply
tokens = ('NUM',); t_NUM = r'\d+'; literals = ['+', '-', '*', '/']
t_ignore = ' \t'
def t_error(t): raise SyntaxError()
lexer = lex.lex()
prev_tk = None
def get_tk(who):
global prev_tk
if prev_tk != None: tk = prev_tk; prev_tk = None
else: tk = lexer.token()
if tk == None: print('\t', who + ' got None')
else: print('\t', who + ' got ' + tk.type + '(' + tk.value + ')')
return tk
def put_token_back(tk):
global prev_tk
prev_tk = tk
print('\t', tk.type + '(' + tk.value + ') was back')
def print_token(tk, what, i): print(i * ' ', 'Is ' + tk.type + '(' + tk.value + ') ' + what + '?', sep='')
def Tk(fn, *args, **kwargs): fn(*args, **kwargs)
def is_NUM(tk, i):
print_token(tk, 'a number', i)
if tk.type != 'NUM': raise SyntaxError()
def is_term(tk, i):
'''t : NUM | NUM '*' t | NUM '/' t'''
print_token(tk, 'a term', i)
Tk(is_NUM, tk, i + 1)
tk = get_tk('is_term')
if tk == None: return
if tk.type == '*' or tk.type == '/': Tk(is_term, get_tk('is_term'), i + 1)
else: put_token_back(tk)
def is_expr(tk, i):
'''e : t | t '+' e | t '-' e'''
if tk == None:
if i == 0: return
raise SyntaxError()
print_token(tk, 'an expr', i)
Tk(is_term, tk, i + 1)
tk = get_tk('is_expr')
if tk == None: return
t = tk.type
if t == '+' or t == '-': Tk(is_expr, get_tk('is_expr'), i + 1)
lexer.input('1 - 2*33')
try: Tk(is_expr, get_tk(''), 0)
except SyntaxError: print('\nAbout what talking you are?')
产生式是一组规则。分析时不是根据规则产生语言去和输入比较,而是检查输入是否符合规则。所以我觉得函数名叫is_expr比expr好理解点。再如:Tom是主语吗?Tom是名词吗?it是代词吗?头一句:token 是 表达式。a)只看了头一个token; b)这个命题是真命题还是假命题,let's try 一 try. 我们并没有分析并生成机器码/中间代码/语法树。分析过程中函数的递归调用关系/顺序靠堆栈表达。它隐藏着一颗动态的、不完整的树。
import ply.lex as lex # pip install ply
import ply.yacc as yacc
from functools import reduce
tokens = ('NUM',); t_NUM = r'\d+'; literals = ['+', '-', '*', '/']
def t_error(t): t.lexer.skip(1)
precedence = (('left', '+', '-'), ('left', '*', '/'))
s = []
def p_1(p): "e : NUM"; s.append(p_1.__doc__); p[0] = int(p[1])
def p_2(p): "e : e '+' e"; s.append(p_2.__doc__); p[0] = p[1] + p[3]
def p_3(p): "e : e '-' e"; s.append(p_3.__doc__); p[0] = p[1] - p[3]
def p_4(p): "e : e '*' e"; s.append(p_4.__doc__); p[0] = p[1] * p[3]
def p_5(p): "e : e '/' e"; s.append(p_5.__doc__); p[0] = p[1] / p[3]
def p_error(p): raise Exception()
lexer = lex.lex()
istr = '3 + 2 * 5'
print(istr, '=', yacc.yacc().parse(istr))
s.reverse(); print(reduce(lambda x,y:x+'\n'+y, s, ''))
上面这样的语法能写出Top down的吗?左递归是什么?请看 https://files.cnblogs.com/files/blogs/714801/topdownparsing.zip search(top down operator precedence parsing)
import ply.lex as lex # pip install ply
import ply.yacc as yacc
from functools import reduce
tokens = ('NUM',); t_NUM = r'\d+'; literals = ['+', '-', '*', '/']
def t_error(t): t.lexer.skip(1)
s = []
def p_1(p): "e : t"; s.append(p_1.__doc__); p[0] = p[1]
def p_2(p): "e : t '+' e"; s.append(p_2.__doc__); p[0] = p[1] + p[3]
def p_3(p): "e : t '-' e"; s.append(p_3.__doc__); p[0] = p[1] - p[3]
def p_4(p): "t : NUM"; s.append(p_4.__doc__ + ' ' + p[1]); p[0] = int(p[1])
def p_5(p): "t : NUM '*' t"; s.append(p_5.__doc__); p[0] = int(p[1]) * p[3]
def p_6(p): "t : NUM '/' t"; s.append(p_6.__doc__); p[0] = int(p[1]) / p[3]
def p_error(p): raise Exception()
lexer = lex.lex()
istr = '1 + 2 * 3 - 4'
print(istr, '=', yacc.yacc().parse(istr))
s.reverse(); print(reduce(lambda x,y:x+'\n'+y, s, ''))
自然语言式parsing的更多相关文章
- F#之旅9 - 正则表达式
今天,cozy群有个群友发了条正则,问正则匹配相关的问题.虽然他的问题用html selector去处理可能更好,但是我也再一次发现:我忘了正则怎么写的了! 忘掉正则是有原因的,这篇文章会简单记录下F ...
- 【论文小综】基于外部知识的VQA(视觉问答)
我们生活在一个多模态的世界中.视觉的捕捉与理解,知识的学习与感知,语言的交流与表达,诸多方面的信息促进着我们对于世界的认知.作为多模态领域的一个典型场景,VQA旨在结合视觉的信息来回答所提出的问题 ...
- NLP | 自然语言处理 - 解析(Parsing, and Context-Free Grammars)
什么是解析? 在自然语言的学习过程,个人一定都学过语法,比如句子能够用主语.谓语.宾语来表示.在自然语言的处理过程中.有很多应用场景都须要考虑句子的语法,因此研究语法解析变得很重要. 语法解析有两个基 ...
- Python自然语言处理笔记【一】文本分类之监督式分类
一.分类问题 分类是为了给那些已经给定的输入选择正确的标签. 在基本的分类任务中,每个输入都被认为与其他的输入是隔离的.每个类别的标签集是预先定义好的(只有把类别划分好了,才能给输入划分类别). 分类 ...
- Python自然语言处理笔记【二】文本分类之监督式分类的细节问题
一.选择正确的特征 1.建立分类器的工作中如何选择相关特征,并且为其编码来表示这些特征是首要问题. 2.特征提取,要避免过拟合或者欠拟合 过拟合,是提供的特征太多,使得算法高度依赖训练数据的特性,而对 ...
- 转-Python自然语言处理入门
Python自然语言处理入门 原文链接:http://python.jobbole.com/85094/ 分享到:20 本文由 伯乐在线 - Ree Ray 翻译,renlytime 校稿.未经许 ...
- python and 我爱自然语言处理
曾经因为NLTK的 缘故开始学习Python,之后渐渐成为我工作中的第一辅助脚本语言,虽然开发语言是C/C++,但平时的很多文本数据处理任务都交给了Python.离 开腾讯创业后,第一个作品课程图谱也 ...
- 自然语言处理(NLP)相关学习资料/资源
自然语言处理(NLP)相关学习资料/资源 1. 书籍推荐 自然语言处理 统计自然语言处理(第2版) 作者:宗成庆 出版社:清华大学出版社:出版年:2013:页数:570 内容简介:系统地描述了神经网络 ...
- NLP 自然语言处理之综述
(1) NLP 介绍 NLP 是什么? NLP (Natural Language Processing) 自然语言处理,是计算机科学.人工智能和语言学的交叉学科,目的是让计算机处理或"理解 ...
随机推荐
- wifi 热点配置最优信道
wifi热点服务hostapd启动需要配置hostad.conf文件,其中有一个参数channel是用来配置信道的,信道的可选参数如下: # channel 1-14 is 2.4 GHz ; cha ...
- 实验8:数据平面可编程实践——P4
一.实验目的 掌握V1Model框架下P4_16的程序结构和基本语法 能够运用 P4 进行简单数据平面编程 二.实验报告 在修改basic_tunnel.p4的内容之后输入make run 验证创建结 ...
- pytest框架+conftest.py配置公共数据的准备和清理
1.pytest介绍:1.自动发现测试模块和测试方法 2.断言使用 assert+表达式即可 3.可以设置会话级.模块级.类级.函数级的fixture 数据准备+清理工作 4.丰富的插件库,==all ...
- java 获得 微信 UserId
.... public String cs() throws Exception{ /*访问页面,服务器会得到 code(request.getParameter("code")) ...
- 菜鸡的Java笔记 - java 线程的同步与死锁 (同步 synchronization,死锁 deadlock)
线程的同步与死锁 (同步 synchronization,死锁 deadlock) 多线程的操作方法 1.线程同步的产生与解决 2.死锁的问题 ...
- 软件分享:网页监测及 IIS 重启工具 IISMonitor
本人以前编写过一款简单的工具软件 IISMonitor,这几天整理完善并补写了使用说明,分享出来,供大家免费使用.使用过程中,遇到什么问题或有什么建议,也可回帖留言,我尽力提供修改支持. 1.工具简介 ...
- 仿Word的支持横轴竖轴的WPF 标尺
最近在 https://mp.weixin.qq.com/s/3dEO0NZQv5YLqK72atG4Wg 官方公众号看到了 用WPF 制作 标尺 在去年项目上也接到了一个需求,用于排版自定义拖 ...
- Maven 源码解析:依赖调解是如何实现的?
系列文章目录(请务必按照顺序阅读): Maven 依赖调解源码解析(一):开篇 Maven 依赖调解源码解析(二):如何调试 Maven 源码和插件源码 Maven 依赖调解源码解析(三):传递依赖, ...
- Study Blazor .NET(三)组件
翻译自:Study Blazor .NET,转载请注明. 关于组件 blazor中组件的基础结构可以分为以下3部分, //Counter.razor //Directives section @pag ...
- PHP绕过MD5比较的各种姿势
1.用==进行弱类型比较时, 可以通过两个0e开头后面纯数字的md5绕过 php在进行弱类型比较时,如果为字符串为纯数字,包括浮点数.科学计数法.十六进制数等,都会转化为数字类型再进行比较,利用这点, ...