标签: lexer

创建词法分析器

嘿伙计们,我正在尝试了解有关词法分析器的一些概念。我知道词法分析器在编译器中用于将字符串中的单个字符分成称为标记的形式。但让我困惑的是匹配部分。我不明白为什么我们需要将字符匹配到相应位置的逻辑。

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 循环之后,我不太明白代码要做什么。为什么我们必须将字符与位置匹配?

python lexer

1
推荐指数
1
解决办法
780
查看次数

ANTLR4“+”操作

我正在使用 ANTLR4 来上课,我似乎理解其中的大部分内容,但我不明白“+”的作用。我只能说它通常位于括号中的一组字符之后。

parsing antlr lexer antlr4

1
推荐指数
1
解决办法
2560
查看次数

pushMode、popMode、mode、OPEN 和 CLOSE 在词法分析器语法中是什么意思?

我正在研究词法分析器和解析器语法,并使用 ANTLR 来创建基于 .g4 文件的解析器和词法分析器。但是,我很困惑 pushMode 和 popMode 通常做什么?

OPEN                : '[' -> pushMode(BBCODE) ;
TEXT                : ~('[')+ ;

mode BBCODE;

CLOSE               : ']' -> popMode ; 
Run Code Online (Sandbox Code Playgroud)

词法分析器语法中的 OPEN、pushMode、BBCODE、CLOSE 和 popMode 是什么意思?我尝试搜索这些模式,但没有明确的定义和解释。

parsing antlr lexer antlr4

1
推荐指数
1
解决办法
2343
查看次数

匹配Lua的"长括号"字符串语法

我正在为Lua编写一个jFlex词法分析器,我在设计正则表达式以匹配语言规范的一个特定部分时遇到了问题:

也可以使用长括号括起来的长格式来定义文字字符串.我们将n级的开口长支架定义为开口方括号,后跟n个等号后跟另一个开口方括号.因此,0级的开头长括号写为[[,1级的开头长括号写为[= [,依此类推.结束长括号的定义相似; 例如,级别4的结束长括号写为] ====].一个长字符串以任何级别的开口长括号开始,并在同一级别的第一个关闭长括号结束.这种括号中的文字可以运行多行,不解释任何转义序列,并忽略任何其他级别的长括号.它们可以包含除适当级别的右括号之外的任何内容.

简而言之,我正在尝试设计一个正则表达式,它将匹配一个开头长括号,中间的字符串内容和结束长括号.只有当开口长括号和关闭长括号具有相同数量的等号时才会发生匹配,这些符号可以是零或更多.

regex lua lexer jflex

0
推荐指数
1
解决办法
2100
查看次数

Haskell lexer问题

我在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)

haskell types lexer

0
推荐指数
1
解决办法
2697
查看次数

使用递归正则表达式在Java中进行Lexing

我正在使用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模式并一次匹配.我的问题是当我开始在Type1Type2行中使用递归语法元素时.我显然无法将递归定义提供给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)

我意识到这不是正则表达式的意思 - 现在这是一个无上下文语法(?),因为它是递归的.但是,如果不考虑超级聪明的解析器,我认为这种方法是可以破解的.

思考?

java grammar parsing tokenize lexer

0
推荐指数
1
解决办法
1079
查看次数

我的析构函数需要在这个函数中做什么?

我的程序执行正常,除了最后,当我调试它时,它在调用我的析构函数后得到分段错误.我不确定问题的原因是什么.我发布了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)

c++ lexer segmentation-fault

0
推荐指数
1
解决办法
114
查看次数

Python Lex-Yacc(PLY):无法识别行开头或字符串开头

我对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)

python regex ply tokenize lexer

0
推荐指数
1
解决办法
3246
查看次数

关于Prolog tokenizer

我的一个任务要求我们构建一个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执行替换呢?

prolog lexer

0
推荐指数
1
解决办法
750
查看次数

理解 ANTLR4 代币

我对 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)

java token lexer antlr4

0
推荐指数
1
解决办法
2703
查看次数

错误[E0507]:无法移出借用的内容

我正在尝试用 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)

lexer rust

0
推荐指数
1
解决办法
2898
查看次数

创建词法分析器的最有效方法是什么?

我目前正在尝试学习如何手动创建自己的词法分析器.我一直在使用Flex(和Bison一起)练习并学习它如何在内部工作,但我目前至少看到了3种不同的解决方案来开发我自己的.

  1. 使用RE列表,遍历每个RE,当一个匹配时,只需返回相关的令牌(参见关于RE的python文档)
  2. 从RE创建DFA(例如Flex;基于RE,创建一个大型状态机)
  3. 用很多switch case或if语句创建我自己的'状态机'(我认为Lua就是这样做的)

我相信我可以尝试每种解决方案,但是:

  • 是否存在一种解决方案无法解决的问题?
  • 在什么情况下你会使用一个解决方案而不是另一个?
  • 正如标题所说:哪一个产生最有效的代码?

提前致谢!

compiler-construction finite-automata lexer

0
推荐指数
1
解决办法
215
查看次数