嘿伙计们,我正在尝试了解有关词法分析器的一些概念。我知道词法分析器在编译器中用于将字符串中的单个字符分成称为标记的形式。但让我困惑的是匹配部分。我不明白为什么我们需要将字符匹配到相应位置的逻辑。
import sys
import re
def lex(characters, token_exprs):
pos = 0
tokens = []
while pos < len(characters):
match = None
for token_expr in token_exprs:
pattern, tag = token_expr
regex = re.compile(pattern)
match = regex.match(characters, pos)
if match:
text = match.group(0)
if tag:
token = (text, tag)
tokens.append(token)
break
if not match:
sys.stderr.write('Illegal character: %s\n' % characters[pos])
sys.exit(1)
else:
pos = match.end(0)
return tokens
Run Code Online (Sandbox Code Playgroud)
这是我不完全理解的代码。在 for 循环之后,我不太明白代码要做什么。为什么我们必须将字符与位置匹配?
我正在使用 ANTLR4 来上课,我似乎理解其中的大部分内容,但我不明白“+”的作用。我只能说它通常位于括号中的一组字符之后。
我正在研究词法分析器和解析器语法,并使用 ANTLR 来创建基于 .g4 文件的解析器和词法分析器。但是,我很困惑 pushMode 和 popMode 通常做什么?
OPEN : '[' -> pushMode(BBCODE) ;
TEXT : ~('[')+ ;
mode BBCODE;
CLOSE : ']' -> popMode ;
Run Code Online (Sandbox Code Playgroud)
词法分析器语法中的 OPEN、pushMode、BBCODE、CLOSE 和 popMode 是什么意思?我尝试搜索这些模式,但没有明确的定义和解释。
我正在为Lua编写一个jFlex词法分析器,我在设计正则表达式以匹配语言规范的一个特定部分时遇到了问题:
也可以使用长括号括起来的长格式来定义文字字符串.我们将n级的开口长支架定义为开口方括号,后跟n个等号后跟另一个开口方括号.因此,0级的开头长括号写为[[,1级的开头长括号写为[= [,依此类推.结束长括号的定义相似; 例如,级别4的结束长括号写为] ====].一个长字符串以任何级别的开口长括号开始,并在同一级别的第一个关闭长括号结束.这种括号中的文字可以运行多行,不解释任何转义序列,并忽略任何其他级别的长括号.它们可以包含除适当级别的右括号之外的任何内容.
简而言之,我正在尝试设计一个正则表达式,它将匹配一个开头长括号,中间的字符串内容和结束长括号.只有当开口长括号和关闭长括号具有相同数量的等号时才会发生匹配,这些符号可以是零或更多.
我在haskell写一个词法分析器.这是代码:
lexer :: String -> [Token]
lexer s
| s =~ whitespace :: Bool =
let token = s =~ whitespace :: String in
lex (drop (length token) s)
| s =~ number :: Bool =
let token = s =~ number :: String in
Val (read token) : lex (drop (length token) s)
| s =~ operator :: Bool =
let token = s =~ operator :: String in
Oper token : lex (drop (length token) s)
| otherwise …Run Code Online (Sandbox Code Playgroud) 我正在使用Java解析文本.我在下面定义了一个语法:
Start := "(\\<)"
Stop := "(\\>)"
Var = "(\\w*)";
Cons = "([0-9]*)";
Type1 := Start ((Var | Cons) | TypeParent) (Type1 ((Var | Cons) | TypeParent))* Stop
Type2 := Start ((Var | Cons) | TypeParent) (Type2 ((Var | Cons) | TypeParent))* Stop
TypeParent := Type1 | Type2
...
etc
Run Code Online (Sandbox Code Playgroud)
我想将所有正则表达式组合成一个String模式并一次匹配.我的问题是当我开始在Type1和Type2行中使用递归语法元素时.我显然无法将递归定义提供给Java中的Pattern - 它只是一个带有正则表达式符号的String.
我想要的是,我可以以某种方式有一个逻辑开关,如果在这个块中:
(Type2 ((Var | Cons) | TypeParent)
Run Code Online (Sandbox Code Playgroud)
所有模式都匹配,除了Type2,我可以捕获所有其他组,但然后提取Type2标记应该是的字符串,然后再次递归地将它提供给regexer.最后我会得到一个基本案例:
(Var | Cons) | TypeParent)
Run Code Online (Sandbox Code Playgroud)
我意识到这不是正则表达式的意思 - 现在这是一个无上下文语法(?),因为它是递归的.但是,如果不考虑超级聪明的解析器,我认为这种方法是可以破解的.
思考?
我的程序执行正常,除了最后,当我调试它时,它在调用我的析构函数后得到分段错误.我不确定问题的原因是什么.我发布了2个相关文件.
Breakpoint 1, main () at Prog3.cc:12
12 cout << "Program executed" << endl;
(gdb) s
Program executed
~Lex (this=0x80375c4) at lex.cc:36
36 delete [] str;
(gdb) s
37 }
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0xfef49418 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string () from /usr/sfw/lib/libstdc++.so.6
(gdb) Quit
Run Code Online (Sandbox Code Playgroud)
lex.h如下:
#ifndef LEX_H
#define LEX_H
#include "token.h"
#include <iostream>
#include <stdlib.h>
class Lex {
public:
Lex(istream& in, string fileName);
//Lex();
//Lex(const Lex& l);
~Lex();
static const int INTLIT = 1;
static …Run Code Online (Sandbox Code Playgroud) 我对PLY很陌生,对 Python 也只是个初学者。我正在尝试使用PLY-3.4和 python 2.7 来学习它。请参阅下面的代码。我正在尝试创建一个令牌 QTAG,它是一个由零个或多个空格组成的字符串,后跟“Q”或“q”,后跟“.”。以及一个正整数和一个或多个空格。例如,有效的 QTAG 是
"Q.11 "
" Q.12 "
"q.13 "
'''
Q.14
'''
Run Code Online (Sandbox Code Playgroud)
无效的是
"asdf Q.15 "
"Q. 15 "
Run Code Online (Sandbox Code Playgroud)
这是我的代码:
import ply.lex as lex
class LqbLexer:
# List of token names. This is always required
tokens = [
'QTAG',
'INT'
]
# Regular expression rules for simple tokens
def t_QTAG(self,t):
r'^[ \t]*[Qq]\.[0-9]+\s+'
t.value = int(t.value.strip()[2:])
return t
# A regular expression rule with some action code
# Note addition …Run Code Online (Sandbox Code Playgroud) 我的一个任务要求我们构建一个prolog tokenizer.现在我写了一个可以改变空间并将其换成新行的谓词.但我不知道如何将其实施到主程序中.
替换部件如下所示:
replace(_, _, [], []).
replace(O, R, [O|T], [R|T2]):- replace(O, R, T, T2).
replace(O, R, [H|T], [H|T2]) :- H \= O, replace(O, R, T, T2).
Run Code Online (Sandbox Code Playgroud)
该Main部分有一个谓词removewhite(list1 list2)
那我怎么能让removewhite执行替换呢?
我对 ANTLR 很Token陌生,我试图了解ATNLR4 中到底是什么。考虑以下非常荒谬的语法:
grammar Tst;
init: A token=('+'|'-') B;
A: .+?;
B: .+?;
ADD: '+';
SUB: '-';
Run Code Online (Sandbox Code Playgroud)
ANTLR4 为其生成以下TstParser.InitContext内容:
public static class InitContext extends ParserRuleContext {
public Token token; //<---------------------------- HERE
public TerminalNode A() { return getToken(TstParser.A, 0); }
public TerminalNode B() { return getToken(TstParser.B, 0); }
public InitContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_init; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TstListener …Run Code Online (Sandbox Code Playgroud) 我正在尝试用 Rust 制作一个词法分析器,虽然对它来说相对较新,但具有 C/C++ 背景。我在以下代码中遇到 Rust 如何分配内存的问题,这会生成错误“无法移出借用的内容”。我已经阅读了cargo --explain E0507其中详细介绍了可能的解决方案,但我正在努力理解 Rust 和 C/C++ 管理内存方式之间的根本差异。本质上,我想了解如何在 Rust 中管理动态内存(或者实现我正在做的事情的更好方法)。
错误是:
error[E0507]: cannot move out of borrowed content
--> <anon>:65:16
|
65 | return self.read_tok.unwrap();
| ^^^^ cannot move out of borrowed content
error[E0507]: cannot move out of borrowed content
--> <anon>:73:16
|
73 | return self.peek_tok.unwrap();
| ^^^^ cannot move out of borrowed content
error: aborting due to 2 previous errors
Run Code Online (Sandbox Code Playgroud)
代码是:
use std::fmt;
#[derive(Debug, PartialEq)]
pub enum TokenType {
EndOfFile,
Illegal …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试学习如何手动创建自己的词法分析器.我一直在使用Flex(和Bison一起)练习并学习它如何在内部工作,但我目前至少看到了3种不同的解决方案来开发我自己的.
我相信我可以尝试每种解决方案,但是:
提前致谢!