簡體   English   中英

正則表達式匹配除“ <-”以外的所有非字母數字字符

[英]Regular Expression to match all non alphanumeric characters except “<--”

我正在嘗試在python中創建一種玩具語言,但是在創建我的詞法分析器時遇到了困難。 用我的語言分配變量的方法是使用箭頭(“ <-”),因此我想為此創建令牌。 我還希望能夠編寫浮點數(3.2、1.0等)。

以下是當前我如何拆分語言的源代碼,但這會拆分到每個非字母數字字符上。

    word_list = re.split('(\W)', self.source_code)
    word_list = [elem for elem in word_list if (elem != '' and elem != ' ')]

例如:

Hi <-- 1.2

前往:

['Hi', '<', '-', '-', '1', '.', '2', '\n']

但我希望它分裂成

['Hi', '<--', '1.2']

我想知道是否可以對每個字母數字字符進行拆分,除非存在“ <-”或浮點數,而當仍拆分為“ <”,“-”,“。”時。 靠自己。

編輯

一個更復雜的示例:

DECLARE Number: INTEGER
DECLARE Hi: REAL
Hi <-- 1.2
INPUT Number

IF Number + Hi > 3
    THEN
        OUTPUT "Hello"

應該去

['DECLARE', 'Number', ':', 'INTEGER','\n' 'DECLARE', 'Hi', ':', 'REAL','\n', 'Hi', '<--', '1.2','\n', 'INPUT', 'Number', '\n', '\n', 'IF', 'Number', '+', 'Hi', '>', '3','\n', '\t', 'THEN', '\n', '\t', '\t', 'OUTPUT', '"Hello"']

通常,用於編程語言的詞法分析器會讓您為要解析的語言所擁有的每種令牌類型定義正則表達式。 然后,它建立一個有限狀態自動機,將輸入作為字符串讀取,並且這樣做,它會在識別各種標記的狀態之間進行轉換。 因此,我采用的方法是嘗試定義每個令牌的外觀,並嘗試在輸入中進行匹配。 現在,老實說,我並沒有花很大的力氣就數字和標識符找到最好的正則表達式(我什至不知道您的規則是什么)。 我只想表明我相信您應該采取的方法是:

s = 'Hi  <--  (1.2)'
word_list = re.findall(r'(\b\d+(?:\.\d*)?\b|\b\.\d+\b|\b\w+\b|<--|\s+|\W+)', s)
print(word_list)

打印:

['Hi', '  ', '<--', '  ', '(', '1.2', ')']

正則表達式'(\\b\\d+(?:\\.\\d*)?\\b|\\b\\.\\d+\\b|\\b\\w+\\b|<--)正在尋找以下選擇:

  1. \\b\\d+(?:\\.\\d*)? \\ b在單詞邊界上全部匹配123、123。,123.45
  2. \\b\\.\\d+\\b在單詞邊界上匹配.45
  3. \\b\\w+\\b在單詞邊界匹配Hi
  4. <--匹配<-(無邊界條件-也許這不是您想要的)
  5. `\\ s +'匹配連續的空格
  6. \\W+匹配上面未匹配的所有其他內容(其他運算符)

您需要確保所有內容都最終匹配。 然后,您可能需要查看已匹配的內容(請參閱上面的項目6),以查看它是否實際上是合法令牌。

因此,例如,如果<--是唯一有效的運算符,則以下將是一種方法:

import re

s = 'Hi  <--  (1.2)'
for m in re.finditer(r'(?P<OK>\b\d+(?:\.\d*)?\b|\b\.\d+\b|\b\w+\b|<--)|(?P<IGNORE>\s+)|(?P<ERROR>\W+)', s):
    if m.group('ERROR') is not None:
        print('Unrecognized token', m.group('ERROR'))
    elif m.group('OK') is not None:
        print(m.group('OK'))

各種匹配項都標記為“確定”,“忽略”(空格)或“錯誤”。 上面的照片:

Hi
<--
Unrecognized token (
1.2
Unrecognized token )

通過稍微修改Elegant Odoo的代碼,我設法找到了解決方案。

    split_pattern = '(<--|[\+\-\*\(\)/%:\{\},\[\]<>=(\n)(\t) ]|(?<!\d)[.](?!\d))'
    word_list = re.split(split_pattern, self.source_code)
    word_list = [elem for elem in word_list if (elem != '' and elem != ' ')]

您可以嘗試以下方法:

匯入

str_code = """
DECLARE Number: INTEGER
DECLARE Hi: REAL
Hi <-- 1.2
INPUT Number

IF Number + Hi > 3
    THEN
        OUTPUT "Hello"
"""

# split when you find group <-- or any arithmetic operator
split_pattern = re.compile('(<--|[\+\-\*\(\)\s\t\:\>\=\<])')

print([x for x in re.split(split_pattern, str_code) if x not in [' ', '']])

輸出:

  ['\n', 'DECLARE', 'Number', ':', 'INTEGER', '\n', 'DECLARE', 'Hi', ':', 'REAL', '\n', 'Hi', '<--', '1.2', '\n', 'INPUT', 'Number', '\n', '\n', 'IF', 'Number', '+', 'Hi', '>', '3', '\n', 'THEN', '\n', 'OUTPUT', '"Hello"', '\n']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM