Как использовать lex с исходным файлом C?

Мне нужно написать простой токенизатор для языка C. Ему не нужно классифицировать вещи, не нужно использовать какую-либо грамматику. Все, что ему нужно сделать, это напечатать отдельно слова, символы, круглые скобки и другие вещи. Я использую lex для этого. Но мне нужно прочитать исходный файл C, а затем разметить его. Ниже вы можете найти мой текущий код. У меня есть три вопроса.

1) Как я могу исправить сообщение об ошибке, которое я получаю при компиляции:

parser.l:47:1: предупреждение: неизвестный символ типа преобразования ‘=’ в формате [-Wformat]

2) Как я могу заставить лексер работать с исходным файлом, который передается в качестве аргумента?

3) Как заставить токенизатор печатать имена переменных и другие неуказанные вещи так, как они есть? Это означает, что если у меня есть int test, он будет печатать int, потому что он указан в лексере, и я также хочу напечатать тест отдельно, потому что он не указан в lex.

Вот мой код:

%{
#include <stdio.h>
#include <stdlib.h>
%}

%%

"auto"          { printf("auto\t"); }
"break"         { printf("break\t"); }
"case"          { printf("case\t"); }
"char"          { printf("char\t"); }
"const"         { printf("const\t"); }
"continue"      { printf("continue\t"); }
"default"       { printf("default\t"); }
"do"            { printf("do\t"); }
"double"        { printf("double\t"); }
"else"          { printf("else\t"); }
"enum"          { printf("enum\t"); }
"extern"        { printf("extern\t"); }
"float"         { printf("float\t"); }
"for"           { printf("for\t"); }
"goto"          { printf("goto\t"); }
"if"            { printf("if\t"); }
"inline"        { printf("inline\t"); }
"int"           { printf("int\t"); }
"long"          { printf("long\t"); }
"printf"        { printf("printf\t"); }
"register"      { printf("register\t"); }
"restrict"      { printf("restrict\t"); }
"return"        { printf("return\t"); }
"short"         { printf("short\t"); }
"signed"        { printf("signed\t"); }
"sizeof"        { printf("sizeof\t"); }
"static"        { printf("static\t"); }
"struct"        { printf("struct\t"); }
"switch"        { printf("switch\t"); }
"typedef"       { printf("typedef\t"); }
"union"         { printf("union\t"); }
"unsigned"      { printf("unsigned\t"); }
"void"          { printf("void\t"); }
"volatile"      { printf("volatile\t"); }
"while"         { printf("while\t"); }
"+="            { printf("+=\t"); }
"-="            { printf("-=\t"); }
"*="            { printf("*=\t"); }
"/="            { printf("/=\t"); }
"%="            { printf("%=\t"); }
"&="            { printf("&=\t"); }
"^="            { printf("^=\t"); }
"|="            { printf("|=\t"); }
"++"            { printf("++\t"); }
"--"            { printf("--\t"); }
"->"            { printf("->\t"); }
"&&"            { printf("&&\t"); }
"||"            { printf("||\t"); }
"<="            { printf("<=\t"); }
">="            { printf(">=\t"); }
"=="            { printf("==\t"); }
"!="            { printf("!=\t"); }
"{"         { printf("{\t"); }
"}"         { printf("}\t"); }
"="         { printf("=\t"); }
"("         { printf("(\t"); }
")"         { printf(")\t"); }
"["         { printf("[\t"); }
"]"         { printf("]\t"); }
"<"         { printf("<\t"); }
">"         { printf(">\t"); }

%%

void main(int argc, char** argv)
{
    if(argc != 2)
    {
        printf("Usage: %s filename\n", argv[0]);
        exit(1);
    }

    char *filename = argv[1];
    FILE *f = fopen(filename, "r");

    if(f == NULL)
    {
        fprintf(stderr, "Unable to open %s\n", filename);
    }
    else
    {
        yylex();
    }
}

person Community    schedule 28.02.2014    source источник


Ответы (3)


Q1. У вас есть предупреждение из этой строки:

"%="            { printf("%=\t"); }

Вы хотите:

"%="            { printf("%%=\t"); }

так как вам нужно избежать «%».

Q2. Чтобы заставить lex читать из данного файла, вам нужно использовать yyin - см. в lex, как заставить yyin указывать на файл с основной функцией в yacc? для более подробной информации.

Q3. Вам нужно будет использовать регулярные выражения, чтобы сопоставить их. См. https://www.cs.princeton.edu/~appel/modern/c/software/flex/flex.html, например.

person abligh    schedule 28.02.2014

Чтобы напечатать идентификаторы, вы можете использовать регулярное выражение ниже

enter[a-zA-Z][_a-zA-Z0-9]*       {printf("identifier\t%s\t",yytext);}

Включите это в конец правил, чтобы оно правильно идентифицировало все другие определенные правила и не всегда печаталось как идентификатор.

person Shree Vignesh    schedule 17.01.2017

person    schedule
comment
Пожалуйста, добавьте текст, чтобы описать, почему это может быть правильным ответом. - person Ken Y-N; 15.07.2015