基于c语言的语法分析器的实现

本文档介绍了基于C语言的语法分析器的实现,主要采用自顶向下的预测分析技术,详细阐述了预测分析法的原理和步骤,包括LL(1)文法的检查、预测分析表的构造以及错误处理机制。同时,还讨论了C语言文法设计,从函数定义到各种语句声明的文法结构。

一. 总体实现思想

  1. 我采用自顶向下的预测分析技术来实现,其基本方法如下:
    从文法开始符号出发,在每一步推导过程中根据当前句型的最左非终结符A和当前输入符号a,选择正确的A-产生式。为保证分析的确定性,选出的候选式必须是唯一的。

  2. 具体的非递归的预测语法分析结构如下所示:
    非递归的预测分析不需要为每个非终结符编写递归下降过程,而是根据预测分析表构造一个自动机,也叫表驱动的预测分析
    预测分析结构图

  3. 表驱动的预测分析法的算法
    3.1输入:一个串w和文法G的分析表 M
    3.2输出:如果w在L(G )中,输出w的最左推导;否则给出错误指示
    3.3方法:最初,语法分析器的格局如下:输入缓冲区中是w G 。下面的程序使用预测分析表M生成了处理这个输入的预测分析过程

设置ip使它指向w的第一个符号,其中ip 是输入指针;
令X=栈顶符号;
while  ( X ≠ $ ){     /   *      栈非空 */ 
            if ( X 等于ip所指向的符号a) 执行栈的弹出操作,将ip向前移动一个位置;
            else  if ( X是一个终结符号)  error ( ) ;
            else  if ( M[X,a]是一个报错条目)  error ( ) ;           
            else  if ( M[X,a] = X →Y1Y2 … Yk  ){ 
                         输出产生式 X →Y1Y2 … Yk  ;
                         弹出栈顶符号;
                        将Yk,Yk-1 …,Yi 压入栈中,其中Y1位于栈顶。
            }
            令X=栈顶符号
}

4.非递归的预测分析法主控程序规模较小,需载入分析表(表较小),直观性较差,分析时间大约正比于待分析程序的长度,但是自动生成较容易
5. 预测分析法的实现步骤
1)构造文法
2)改造文法:消除二义性、消除左递归、消除回溯
3)求每个变量的FIRST集和FOLLOW集,从而求得每个
候选式的SELECT集
4)检查是不是 LL(1) 文法。若是,构造预测分析表
5)对于递归的预测分析,根据预测分析表为每一个非终结
符编写一个过程;对于非递归的预测分析,实现表驱动
的预测分析算法,我们采用的是后面一种

6.预测分析的错误处理
6.1错误检测:
栈顶的终结符和当前输入符号不匹配、
栈顶非终结符与当前输入符号在预测分析表对应项中的信息为空
6.2恐慌模式
6.2.1忽略输入中的一些符号,直到输入中出现由设计者选定的同步词法单元(synchronizing token)集合中的某个词法单元
1)其效果依赖于同步集合的选取。集合的选取应该使得语法分 析器能从实际遇到的错误中快速恢复。例如可以把FOLLOW(A)中的所有终结符放入非终结符A的同步记号集合
6.2.2如果终结符在栈顶而不能匹配,一个简单的办法就是弹出此终结符
6.2.1分析表的使用方法
如果M[A,a]是空,表示检测到错误,根据恐慌模式,忽略输入号a
如果M[A,a]是synch,则弹出栈顶的非终结符A,试图继续分析后面的语法成分
如果栈顶的终结符和输入符号不匹配,则弹出栈顶的终结符

二. C语言文法设计

  1. c语言基本程序主要是由函数定义组成,故定义文法为:
program->function_definition program'
program'->function_definition program'|$  //c语言的程序构造
  1. 而函数定义又包括了类型定义、函数声明、复合声明,故文法定义为
function_definition->type_specifier declarator_func                                  compound_statement 
type_specifier->VOID|CHAR|INT|FLOAT //函数定义
  1. 函数声明又包含函数名字和参数,故文法所以定义为
declarator_func->ID dec'    //declarator_func函数声明
declarator->ID dec
dec->[ DIGIT ]|$
dec'->( declarator'|$
declarator'->parameter_list )|)
parameter_list->parameter_declaration parameter_list'
parameter_list'->, parameter_declaration parameter_list'|$
D:\rujian\pc\python.exe D:/desktop/人/main.py 2025-10-09 00:21:31.659255: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'cudart64_110.dll'; dlerror: cudart64_110.dll not found 2025-10-09 00:21:31.660169: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine. C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\framework\dtypes.py:585: FutureWarning: In the future `np.object` will be defined as the corresponding NumPy scalar. np.object, Traceback (most recent call last): File "D:/desktop/人/main.py", line 6, in <module> import mediapipe as mp File "D:\rujian\pc\lib\site-packages\mediapipe\__init__.py", line 17, in <module> import mediapipe.tasks.python as tasks File "D:\rujian\pc\lib\site-packages\mediapipe\tasks\python\__init__.py", line 17, in <module> from . import audio File "D:\rujian\pc\lib\site-packages\mediapipe\tasks\python\audio\__init__.py", line 18, in <module> import mediapipe.tasks.python.audio.audio_classifier File "D:\rujian\pc\lib\site-packages\mediapipe\tasks\python\audio\audio_classifier.py", line 26, in <module> from mediapipe.tasks.python.audio.core import base_audio_task_api File "D:\rujian\pc\lib\site-packages\mediapipe\tasks\python\audio\core\base_audio_task_api.py", line 25, in <module> from mediapipe.tasks.python.core.optional_dependencies import doc_controls File "D:\rujian\pc\lib\site-packages\mediapipe\tasks\python\core\optional_dependencies.py", line 20, in <module> from tensorflow.tools.docs import doc_controls File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\__init__.py", line 41, in <module> from tensorflow.python.tools import module_util as _module_util File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\__init__.py", line 46, in <module> from tensorflow.python import data File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\data\__init__.py", line 25, in <module> from tensorflow.python.data import experimental File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\data\experimental\__init__.py", line 97, in <module> from tensorflow.python.data.experimental import service File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\data\experimental\service\__init__.py", line 353, in <module> from tensorflow.python.data.experimental.ops.data_service_ops import distribute File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\data\experimental\ops\data_service_ops.py", line 26, in <module> from tensorflow.python.data.experimental.ops import compression_ops File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\data\experimental\ops\compression_ops.py", line 20, in <module> from tensorflow.python.data.util import structure File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\data\util\structure.py", line 26, in <module> from tensorflow.python.data.util import nest File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\data\util\nest.py", line 40, in <module> from tensorflow.python.framework import sparse_tensor as _sparse_tensor File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\framework\sparse_tensor.py", line 28, in <module> from tensorflow.python.framework import constant_op File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\framework\constant_op.py", line 29, in <module> from tensorflow.python.eager import execute File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\eager\execute.py", line 27, in <module> from tensorflow.python.framework import dtypes File "C:\Users\xu\AppData\Roaming\Python\Python38\site-packages\tensorflow\python\framework\dtypes.py", line 585, in <module> np.object, File "D:\rujian\pc\lib\site-packages\numpy\__init__.py", line 305, in __getattr__ raise AttributeError(__former_attrs__[attr]) AttributeError: module 'numpy' has no attribute 'object'. `np.object` was a deprecated alias for the builtin `object`. To avoid this error in existing code, use `object` by itself. Doing this will not modify any behavior and is safe. The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
10-10
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-1-232abbca6849> in <module> 1 import os ----> 2 from keras.datasets import mnist 3 (train_images,train_labels),(test_images,test_labels)=mnist.load_data((os.getcwd())+'/mnist.npz') 4 print(type(train_images)) 5 print(type(train_labels)) D:\rujian\pc\lib\site-packages\keras\__init__.py in <module> 18 [keras.io](https://keras.io). 19 """ ---> 20 from keras import distribute 21 from keras import models 22 from keras.engine.input_layer import Input D:\rujian\pc\lib\site-packages\keras\distribute\__init__.py in <module> 16 17 ---> 18 from keras.distribute import sidecar_evaluator D:\rujian\pc\lib\site-packages\keras\distribute\sidecar_evaluator.py in <module> 15 """Python module for evaluation loop.""" 16 ---> 17 import tensorflow.compat.v2 as tf 18 19 # isort: off D:\rujian\pc\lib\site-packages\tensorflow\__init__.py in <module> 35 import typing as _typing 36 ---> 37 from tensorflow.python.tools import module_util as _module_util 38 from tensorflow.python.util.lazy_loader import LazyLoader as _LazyLoader 39 D:\rujian\pc\lib\site-packages\tensorflow\python\__init__.py in <module> 43 from tensorflow.python import distribute 44 # from tensorflow.python import keras ---> 45 from tensorflow.python.feature_column import feature_column_lib as feature_column 46 # from tensorflow.python.layers import layers 47 from tensorflow.python.module import module D:\rujian\pc\lib\site-packages\tensorflow\python\feature_column\feature_column_lib.py in <module> 16 17 # pylint: disable=unused-import,line-too-long,wildcard-import,g-bad-import-order ---> 18 from tensorflow.python.feature_column.feature_column import * 19 from tensorflow.python.feature_column.feature_column_v2 import * 20 from tensorflow.python.feature_column.sequence_feature_column import * D:\rujian\pc\lib\site-packages\tensorflow\python\feature_column\feature_column.py in <module> 141 from tensorflow.python.framework import sparse_tensor as sparse_tensor_lib 142 from tensorflow.python.framework import tensor_shape --> 143 from tensorflow.python.layers import base 144 from tensorflow.python.ops import array_ops 145 from tensorflow.python.ops import check_ops D:\rujian\pc\lib\site-packages\tensorflow\python\layers\base.py in <module> 14 # ============================================================================= 15 """Contains the base Layer class, from which all layers inherit.""" ---> 16 from tensorflow.python.keras.legacy_tf_layers import base 17 18 InputSpec = base.InputSpec D:\rujian\pc\lib\site-packages\tensorflow\python\keras\__init__.py in <module> 23 24 # See b/110718070#comment18 for more details about this import. ---> 25 from tensorflow.python.keras import models 26 27 from tensorflow.python.keras.engine.input_layer import Input D:\rujian\pc\lib\site-packages\tensorflow\python\keras\models.py in <module> 20 from tensorflow.python.keras import metrics as metrics_module 21 from tensorflow.python.keras import optimizer_v1 ---> 22 from tensorflow.python.keras.engine import functional 23 from tensorflow.python.keras.engine import sequential 24 from tensorflow.python.keras.engine import training D:\rujian\pc\lib\site-packages\tensorflow\python\keras\engine\functional.py in <module> 30 from tensorflow.python.keras.engine import input_spec 31 from tensorflow.python.keras.engine import node as node_module ---> 32 from tensorflow.python.keras.engine import training as training_lib 33 from tensorflow.python.keras.engine import training_utils 34 from tensorflow.python.keras.saving.saved_model import network_serialization D:\rujian\pc\lib\site-packages\tensorflow\python\keras\engine\training.py in <module> 52 from tensorflow.python.keras.mixed_precision import loss_scale_optimizer as lso 53 from tensorflow.python.keras.mixed_precision import policy ---> 54 from tensorflow.python.keras.saving import hdf5_format 55 from tensorflow.python.keras.saving import save 56 from tensorflow.python.keras.saving import saving_utils D:\rujian\pc\lib\site-packages\tensorflow\python\keras\saving\hdf5_format.py in <module> 35 # pylint: disable=g-import-not-at-top 36 try: ---> 37 import h5py 38 HDF5_OBJECT_HEADER_LIMIT = 64512 39 except ImportError: D:\rujian\pc\lib\site-packages\h5py\__init__.py in <module> 44 _errors.silence_errors() 45 ---> 46 from ._conv import register_converters as _register_converters 47 _register_converters() 48 h5py\h5t.pxd in init h5py._conv() h5py\h5t.pyx in init h5py.h5t() ~\AppData\Roaming\Python\Python38\site-packages\numpy\__init__.py in __getattr__(attr) 318 return Tester 319 --> 320 raise AttributeError("module {!r} has no attribute " 321 "{!r}".format(__name__, attr)) 322 AttributeError: module 'numpy' has no attribute 'typeDict'
最新发布
10-24
完整代码怎么修改,import contextlib import copy import functools import pprint import textwrap import typing import blinker # 新版本 blinker 中的等效调用 from blinker import saferef # 替代原 _saferef from seleniumwire.thirdparty.mitmproxy import exceptions from seleniumwire.thirdparty.mitmproxy.utils import typecheck """ The base implementation for Options. """ unset = object() class _Option: __slots__ = ("name", "typespec", "value", "_default", "choices", "help") def __init__( self, name: str, typespec: typing.Union[type, object], # object for Optional[x], which is not a type. default: typing.Any, help: str, choices: typing.Optional[typing.Sequence[str]] ) -> None: typecheck.check_option_type(name, default, typespec) self.name = name self.typespec = typespec self._default = default self.value = unset self.help = textwrap.dedent(help).strip().replace("\n", " ") self.choices = choices def __repr__(self): return "{value} [{type}]".format(value=self.current(), type=self.typespec) @property def default(self): return copy.deepcopy(self._default) def current(self) -> typing.Any: if self.value is unset: v = self.default else: v = self.value return copy.deepcopy(v) def set(self, value: typing.Any) -> None: typecheck.check_option_type(self.name, value, self.typespec) self.value = value def reset(self) -> None: self.value = unset def has_changed(self) -> bool: return self.current() != self.default def __eq__(self, other) -> bool: for i in self.__slots__: if getattr(self, i) != getattr(other, i): return False return True def __deepcopy__(self, _): o = _Option( self.name, self.typespec, self.default, self.help, self.choices ) if self.has_changed(): o.value = self.current() return o class OptManager: """ OptManager is the base class from which Options objects are derived. .changed is a blinker Signal that triggers whenever options are updated. If any handler in the chain raises an exceptions.OptionsError exception, all changes are rolled back, the exception is suppressed, and the .errored signal is notified. Optmanager always returns a deep copy of options to ensure that mutation doesn't change the option state inadvertently. """ def __init__(self): self.deferred: typing.Dict[str, str] = {} self.changed = blinker.Signal() self.errored = blinker.Signal() # Options must be the last attribute here - after that, we raise an # error for attribute assigment to unknown options. self._options: typing.Dict[str, typing.Any] = {} def add_option( self, name: str, typespec: typing.Union[type, object], default: typing.Any, help: str, choices: typing.Optional[typing.Sequence[str]] = None ) -> None: self._options[name] = _Option(name, typespec, default, help, choices) self.changed.send(self, updated={name}) @contextlib.contextmanager def rollback(self, updated, reraise=False): old = copy.deepcopy(self._options) try: yield except exceptions.OptionsError as e: # Notify error handlers self.errored.send(self, exc=e) # Rollback self.__dict__["_options"] = old self.changed.send(self, updated=updated) if reraise: raise e def subscribe(self, func, opts): """ Subscribe a callable to the .changed signal, but only for a specified list of options. The callable should accept arguments (options, updated), and may raise an OptionsError. The event will automatically be unsubscribed if the callable goes out of scope. """ for i in opts: if i not in self._options: raise exceptions.OptionsError("No such option: %s" % i) # We reuse blinker's safe reference functionality to cope with weakrefs # to bound methods. func = blinker._saferef.safe_ref(func) @functools.wraps(func) def _call(options, updated): if updated.intersection(set(opts)): f = func() if f: f(options, updated) else: self.changed.disconnect(_call) # Our wrapper function goes out of scope immediately, so we have to set # weakrefs to false. This means we need to keep our own weakref, and # clean up the hook when it's gone. self.changed.connect(_call, weak=False) def __eq__(self, other): if isinstance(other, OptManager): return self._options == other._options return False def __deepcopy__(self, memodict = None): o = OptManager() o.__dict__["_options"] = copy.deepcopy(self._options, memodict) return o __copy__ = __deepcopy__ def __getattr__(self, attr): if attr in self._options: return self._options[attr].current() else: raise AttributeError("No such option: %s" % attr) def __setattr__(self, attr, value): # This is slightly tricky. We allow attributes to be set on the instance # until we have an _options attribute. After that, assignment is sent to # the update function, and will raise an error for unknown options. opts = self.__dict__.get("_options") if not opts: super().__setattr__(attr, value) else: self.update(**{attr: value}) def keys(self): return set(self._options.keys()) def items(self): return self._options.items() def __contains__(self, k): return k in self._options def reset(self): """ Restore defaults for all options. """ for o in self._options.values(): o.reset() self.changed.send(self, updated=set(self._options.keys())) def update_known(self, **kwargs): """ Update and set all known options from kwargs. Returns a dictionary of unknown options. """ known, unknown = {}, {} for k, v in kwargs.items(): if k in self._options: known[k] = v else: unknown[k] = v updated = set(known.keys()) if updated: with self.rollback(updated, reraise=True): for k, v in known.items(): self._options[k].set(v) self.changed.send(self, updated=updated) return unknown def update_defer(self, **kwargs): unknown = self.update_known(**kwargs) self.deferred.update(unknown) def update(self, **kwargs): u = self.update_known(**kwargs) if u: raise KeyError("Unknown options: %s" % ", ".join(u.keys())) def setter(self, attr): """ Generate a setter for a given attribute. This returns a callable taking a single argument. """ if attr not in self._options: raise KeyError("No such option: %s" % attr) def setter(x): setattr(self, attr, x) return setter def toggler(self, attr): """ Generate a toggler for a boolean attribute. This returns a callable that takes no arguments. """ if attr not in self._options: raise KeyError("No such option: %s" % attr) o = self._options[attr] if o.typespec != bool: raise ValueError("Toggler can only be used with boolean options") def toggle(): setattr(self, attr, not getattr(self, attr)) return toggle def default(self, option: str) -> typing.Any: return self._options[option].default def has_changed(self, option): """ Has the option changed from the default? """ return self._options[option].has_changed() def merge(self, opts): """ Merge a dict of options into this object. Options that have None value are ignored. Lists and tuples are appended to the current option value. """ toset = {} for k, v in opts.items(): if v is not None: if isinstance(v, (list, tuple)): toset[k] = getattr(self, k) + v else: toset[k] = v self.update(**toset) def __repr__(self): options = pprint.pformat(self._options, indent=4).strip(" {}") if "\n" in options: options = "\n " + options + "\n" return "{mod}.{cls}({{{options}}})".format( mod=type(self).__module__, cls=type(self).__name__, options=options ) def set(self, *spec, defer=False): """ Takes a list of set specification in standard form (option=value). Options that are known are updated immediately. If defer is true, options that are not known are deferred, and will be set once they are added. """ vals = {} unknown = {} for i in spec: parts = i.split("=", maxsplit=1) if len(parts) == 1: optname, optval = parts[0], None else: optname, optval = parts[0], parts[1] if optname in self._options: vals[optname] = self.parse_setval(self._options[optname], optval) else: unknown[optname] = optval if defer: self.deferred.update(unknown) elif unknown: raise exceptions.OptionsError("Unknown options: %s" % ", ".join(unknown.keys())) self.update(**vals) def process_deferred(self): """ Processes options that were deferred in previous calls to set, and have since been added. """ update = {} for optname, optval in self.deferred.items(): if optname in self._options: optval = self.parse_setval(self._options[optname], optval) update[optname] = optval self.update(**update) for k in update.keys(): del self.deferred[k] def parse_setval(self, o: _Option, optstr: typing.Optional[str]) -> typing.Any: """ Convert a string to a value appropriate for the option type. """ if o.typespec in (str, typing.Optional[str]): return optstr elif o.typespec in (int, typing.Optional[int]): if optstr: try: return int(optstr) except ValueError: raise exceptions.OptionsError("Not an integer: %s" % optstr) elif o.typespec == int: raise exceptions.OptionsError("Option is required: %s" % o.name) else: return None elif o.typespec == bool: if optstr == "toggle": return not o.current() if not optstr or optstr == "true": return True elif optstr == "false": return False else: raise exceptions.OptionsError( "Boolean must be \"true\", \"false\", or have the value " "omitted (a synonym for \"true\")." ) elif o.typespec == typing.Sequence[str]: if not optstr: return [] else: return getattr(self, o.name) + [optstr] raise NotImplementedError("Unsupported option type: %s", o.typespec) def make_parser(self, parser, optname, metavar=None, short=None): """ Auto-Create a command-line parser entry for a named option. If the option does not exist, it is ignored. """ if optname not in self._options: return o = self._options[optname] def mkf(l, s): l = l.replace("_", "-") f = ["--%s" % l] if s: f.append("-" + s) return f flags = mkf(optname, short) if o.typespec == bool: g = parser.add_mutually_exclusive_group(required=False) onf = mkf(optname, None) offf = mkf("no-" + optname, None) # The short option for a bool goes to whatever is NOT the default if short: if o.default: offf = mkf("no-" + optname, short) else: onf = mkf(optname, short) g.add_argument( *offf, action="store_false", dest=optname, ) g.add_argument( *onf, action="store_true", dest=optname, help=o.help ) parser.set_defaults(**{optname: None}) elif o.typespec in (int, typing.Optional[int]): parser.add_argument( *flags, action="store", type=int, dest=optname, help=o.help, metavar=metavar, ) elif o.typespec in (str, typing.Optional[str]): parser.add_argument( *flags, action="store", type=str, dest=optname, help=o.help, metavar=metavar, choices=o.choices ) elif o.typespec == typing.Sequence[str]: parser.add_argument( *flags, action="append", type=str, dest=optname, help=o.help + " May be passed multiple times.", metavar=metavar, choices=o.choices, ) else: raise ValueError("Unsupported option type: %s", o.typespec) def dump_dicts(opts, keys: typing.List[str]=None): """ Dumps the options into a list of dict object. Return: A list like: { "anticache": { type: "bool", default: false, value: true, help: "help text"} } """ options_dict = {} keys = keys if keys else opts.keys() for k in sorted(keys): o = opts._options[k] t = typecheck.typespec_to_str(o.typespec) option = { 'type': t, 'default': o.default, 'value': o.current(), 'help': o.help, 'choices': o.choices } options_dict[k] = option return options_dict
08-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值