Синтаксическая проверка программ на C, таких как непарные круглые, квадратные и фигурные скобки - C (СИ)
Формулировка задачи:
Задание:
Упражнение 1.24.
Напишите программу для выполнения примитивной синтаксической проверки программ на C, таких как непарные круглые, квадратные и фигурные скобки. Не забудьте об одинарных и двойных кавычках, управляющих символах и комментариях. (Это сложная программа, если пытаться реализовать самый общий случай.) Нужно ли реализовывать проверку для#define
и если да, то насколько это будет сложно? Пример:#include <stdio.h> #define M ( #define N ) int main M void N { printf("Test\n" N; }
Решение задачи: «Синтаксическая проверка программ на C, таких как непарные круглые, квадратные и фигурные скобки»
textual
Листинг программы
#include <stdio.h> #include <string.h> #define MAXSTACK 1000 char pop(char stack[], int size); char push(char stack[], char elem, int size); char peek(char stack[], int size); int is_com(char s); int is_proc(char s); int main(void) { char stack[MAXSTACK] = {0}; int c, last=0; int ec, com, error, tri; com = ec = error = tri = 0; while(!error && (c = getchar()) != EOF) { // trigraphs if(c == '?' && tri < 2) ++tri; else if(tri == 2) { switch(c) { case '?': break; case '<': c = '{'; break; case '>': c = '}'; break; case '(': c = '['; break; case ')': c = ']'; break; case '/': c = '\\'; break; default: tri = 0; break; } } else tri = 0; if(c == '\\') { if(ec) ec = 0; else ec = 2; } // check brackets if(is_proc(last)) { // ( [ { } ] ) switch(c) { case '(': push(stack, '(', MAXSTACK); break; case '[': push(stack, '[', MAXSTACK); break; case '{': push(stack, '{', MAXSTACK); break; case ')': if(pop(stack, MAXSTACK) != '(') error = 1; break; case ']': if(pop(stack, MAXSTACK) != '[') error = 1; break; case '}': if(pop(stack, MAXSTACK) != '{') error = 1; break; } } // check quotes if(!is_com(last)) { switch(c) { case '\'': if(is_proc(last)) push(stack, '\'', MAXSTACK); else if(!ec && last == '\'') pop(stack, MAXSTACK); break; case '"': if(is_proc(last)) push(stack, '"', MAXSTACK); else if(!ec && last == '"') pop(stack, MAXSTACK); } } // Comment open if(!is_com(last)) switch(c) { case '/': if(com > 0 && !ec) { push(stack, 'l', MAXSTACK); com = 0; } else com = 2; break; case '*': if(com > 0 && !ec) push(stack, 'c', MAXSTACK); com = ec = 0; break; } // Comment close if(is_com(last)) switch(c) { case '*': if(last == 'c') com = -2; break; case '/': if(com < 0 && !ec) { pop(stack, MAXSTACK); com = 0; } break; case '\n': if(last == 'l' && !ec) { pop(stack, MAXSTACK); com = 0; } break; } if(com && !ec && c!='\n' && !tri) com += com<0? 1: -1; if(ec==1 && c != '\n') com = ec = 0; else if(ec) --ec; last=peek(stack, MAXSTACK); } if(error || peek(stack, MAXSTACK) != -1) printf("Error\n"); else printf("Valid\n"); return 0; } char pop(char stack[], int size) { int i, c; for(i = 0; i < size && stack[i]; ++i); if(i > 0) { c = stack[--i]; stack[i] = '\0'; return c; } return -1; } char push(char stack[], char elem, int size) { int i, c; for(i = 0; i < size && stack[i]; ++i); if(i < size) return c = stack[i] = elem; return -1; } char peek(char stack[], int size) { int i; for(i = 0; i < size && stack[i]; ++i); if(i > 0) return stack[--i]; return -1; } int is_proc(char s) { if(s == '\'' || s == '"' || is_com(s)) return 0; return 1; } int is_com(char s) { if(s == 'c' || s == 'l' || s == '\\') return 1; return 0; }
Объяснение кода листинга программы
Код проверяет синтаксис программ на C, в частности, парность скобок (круглых, квадратных и фигурных), кавычек (одиночных и двойных) и обратных слешей. Он также обрабатывает триплеры и комментарии. Вот список функций и их описания:
pop(char stack[], int size)
- эта функция удаляет и возвращает последний элемент из стека. Если стек пуст, она возвращает-1
.push(char stack[], char elem, int size)
- эта функция добавляет элемент в стек. Если стек полон (т.е. достиг максимума размера), она возвращает-1
. В противном случае она возвращает0
, что означает успешное добавление элемента.peek(char stack[], int size)
- эта функция возвращает последний элемент в стеке, не удаляя его. Если стек пуст, она возвращает-1
.is_proc(char s)
- эта функция возвращает0
, если символs
является открывающей фигурной скобкой, открывающей квадратной скобкой или апострофом. В противном случае она возвращает1
.is_com(char s)
- эта функция возвращает0
, если символs
является закрывающей фигурной скобкой, закрывающей квадратной скобкой или обратным слешем. В противном случае она возвращает1
. Список символов и их значений:`>
- означает, что символ является закрывающей квадратной скобкой.`>
- означает, что символ является закрывающей фигурной скобкой.`>
- означает, что символ является обратным слешем.`>
- означает, что символ является апострофом.`>
- означает, что символ является открывающей квадратной скобкой.`>
- означает, что символ является открывающей фигурной скобкой. Вот список переменных и их описания:c
- текущий символ ввода.last
- последний символ в стеке.com
- счетчик комментариев.ec
- счетчик прямых слешей.tri
- счетчик тройплеров.stack
- стек, используемый для отслеживания синтаксиса.error
- флаг, устанавливаемый в1
, если обнаружена синтаксическая ошибка. Вот список номеров строк и соответствующих действий:- 3 - начало обработки комментариев.
- 5 - начало обработки скобок.
- 7 - начало обработки кавычек.
- 12 - начало обработки обратных слешей.
- 16 - начало обработки триплеров.
- 18 - начало обработки парных скобок.
- 20 - конец обработки парных скобок. Обратите внимание, что некоторые строки могут иметь несколько действий, разделенных запятыми. Каждое действие обрабатывается последовательно.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д