Я пишу лексический анализатор c/c++ на python.
Есть над чем поработать, но пока я застрял. Я хочу проверить имена переменных с помощью шаблона RegEx:
(?:\w+\s+)([a-zA-Z_][a-zA-Z0-9]+)/g
Хотя на регулярное выражение паттерн работает нормально
Мой код для этого:
Код для проверки соответствия строки шаблону:
regex = re.compile(r'(?:\w+\s+)([a-zA-Z_][a-zA-Z0-9]+)\b')
if re.search(regex, token) == True: #if token matches the pattern
print(token + ' : Variable Name')
import re
#dictionaries:
#1 operators
operators = {'=': 'Assignment',
'+': 'Additon',
'-' : 'Substraction',
'/' : 'Division',
'*': 'Multiplication',
'++' : 'increment',
'--' : 'Decrement',
'<': 'Lower Than',
'>': 'Greater Than'}
optr_keys = operators.keys()
#2 keywords
keywords = {'int': 'Integer Datatype Indicator',
'float': 'Floating Point Datatype Indicator',
'char': 'Character Datatype Indicator',
'long': 'Long Int Datatype Indicator',
'double': 'Double Datatype Indicator',
'short': 'Short Integer Datatype Indicator',
'unsigned': 'Unsigned Integer Datatype Indicator',
'void': 'Void Datatype Indicator',
'struct': 'Structure Datatype Indicator',
'return': 'Return',
'if': 'Condition If Keyword',
'else': 'Condition Else Keyword',
'while': 'While Loop Indicator',
'do': 'Do While Loop Indicator',
'break': 'Break Out Keyword',
'continue': 'Continue Keyword',
'switch': 'Switch Keyword',
'case': 'Case Keyword',
'sizeof': 'Variable Size Indicator',
'typedef': 'Function Type Indicator',
'static': 'Static Type Keyword',
'goto': 'Go To line Keyword',
'#include': 'Header Include Indicator'
}
keyword_keys = keywords.keys()
#3 delimiters
delimiters = {';':'Line Terminator (Semicolon)',
' ': 'Single Empty Space'}
delimiter_keys = delimiters.keys()
#4 comment indicators
comments = {r'//' : 'Single Line Comment',
r'/*' : 'Multiline Comment Start',
r'*/' : 'Multiline Comment End',
'/**/' : 'Empty Multiline comment'}
comment_keys = comments.keys()
#5 builtin header files
header_files = {'<stdio.h>': 'Standard Input Output Header',
'<string.h>':'String Manipulation Library'}
header_keys = header_files.keys()
#6 blocks
blocks = {'{' : 'Blocked Statement Body Open',
'}':'Blocked Statement Body Closed'}
blocks_keys = blocks.keys()
#7 predefined functions
builtin_functions = {'printf':'Prints To Console',
'cout': 'Standard Output Function',
'cin': 'Standard Input Function'}
builtinfunc_keys = builtin_functions.keys()
#8 numbers
numbers = {'0': 'Zero',
'1': 'One',
'2': 'Two',
'3': 'Three',
'4': 'Four',
'5': 'Five',
'6': 'Six',
'7': 'Se7en',
'8': 'Eight',
'9': 'Nine'}
numbers_keys = numbers.keys()
count = 0
cfile = '/some/path/to/sample/file.c'
f = open(cfile, 'r').read()
lines = f.split('\n')
regex = re.compile(r'(?:\w+\s+)([a-zA-Z_][a-zA-Z0-9]+)\b')
for line in lines:
count = count + 1
print('\n\n###Line Number', str(count) + '\n')
tokens = line.split(' ')
print('Tokens Are ', tokens)
for token in tokens:
if '\n' in token:
position = token.find('\n')
token=token[:position]
if token in optr_keys:
print(token, ' : Operator => ', operators[token])
elif token in keyword_keys:
print(token, ' : Keyword => ', keywords[token])
elif token in comment_keys:
print(token + ' : Comment => ', comments[token])
elif '.h' in token:
print(token + ' : Header File => ', header_files[token])
elif token in blocks_keys:
print(token + ' : Block Indicator => ', blocks[token])
elif token in builtinfunc_keys:
print(token + ' : Built-in Function => ', builtin_functions[token])
elif token in numbers:
print(token + ' : Numbers => ', numbers_keys[token])
else:
if bool(re.search(regex, token)) == True: #if token matches the pattern
print(token + ' : Variable Name')
образец вывода:
###Line Number 1
Tokens Are ['#include', '<stdio.h>', '//', 'This', 'is', 'a', 'header', 'file']
#include : Keyword => Header Include Indicator <stdio.h> : Header File => Standard Input Output Header // : Comment => Single Line Comment
###Line Number 2
Tokens Are ['int', 'main()'] int : Keyword => Integer Datatype Indicator
###Line Number 3
Tokens Are ['{'] { : Block Indicator => Blocked Statement Body Open
###Line Number 4
Tokens Are ['', '', '', '', 'int', 'a;'] int : Keyword => Integer Datatype Indicator
###Line Number 5
Tokens Are ['', '', '', '', 'a', '=', '10;']
= : Operator => Assignment
###Line Number 6
Tokens Are ['', '', '', '', 'printf("The', 'value', 'of', 'a', 'is', '%d', '",a);']
###Line Number 7
Tokens Are ['', '', '', '', 'return', '0;'] return : Keyword => Return
###Line Number 8
Tokens Are ['}'] } : Block Indicator => Blocked Statement Body Closed
###Line Number 9
Tokens Are ['']
Я ожидаю, что код будет включать имена переменных в вывод, но он просто игнорирует их, поскольку процесс сопоставления не выполняется. Я предполагаю, что что-то не так в том, как я пытаюсь сопоставить токены/строки.
Также будет ли re.search() когда-нибудь ==True? search() возвращает объект соответствия.
@ 9769953 верно. удален re.IGNORECASE
@MarkMeyer отредактировал. bool(re.search()) приводит к тому же результату.
Вы можете просто использовать if re.search():
@MarkMeyer так и есть. но все еще говорит Нет. не может соответствовать
@ 9769953 пробовал нет, я не могу использовать if-elif-elif-else, потому что в этом случае все пробелы и разделители считаются именами переменных. это работает, если я не использую дополнительный if в последнем else, что совпадает с elif.
@ 9769953 на основе документов они эквивалентны. docs.python.org/2/library/re.html#module-contents
@JonGuiton, спасибо, Джон. это решило это. Я собираюсь переписать это как ответ.






Проблема была с самим моим регулярным выражением.
Работает следующий шаблон:
[a-zA-Z_][a-zA-Z0-9_]
Кредиты: Джон Гитон
Ваше регулярное выражение [a-zA-Z_][a-zA-Z0-9]+, кажется, запрещает символы подчеркивания, кроме первого символа имени. У вас также может быть однобуквенное имя переменной, поэтому вместо «+» должно быть «', чтобы указать ноль или более вхождений. Я бы предложил [a-zA-Z_][a-zA-Z0-9_]».