⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 grammar.cpp

📁 Code for top down parser in C++
💻 CPP
字号:
//---------------------------------------------------------------------------
//
//  Grammar loading and parsing support routines
//  Dmitry Brant, Spr 2004
//
//-----------

#include <vcl.h>
#pragma hdrstop

#include <stdio.h>
#include <stdlib.h>
#include <stdexcept.h>
#include "grammar.h"

using std::runtime_error;


//Damn it, Jim, I tried to save him!
void Grammar::LoadFromFile(String fileName){
    //destroy previous rules
    for(int i=0; i<ruleGroups->Count; i++) delete ((RewriteRuleGroup*)ruleGroups->Items[i]);
    ruleGroups->Clear();
    //load new file
    FILE* f = fopen(fileName.c_str(), "rb");
    if(!f) throw runtime_error("Failed to open grammar file");
    fseek(f, 0, SEEK_END);
    int fileLen = ftell(f);
    fseek(f, 0, SEEK_SET);
    char* buffer = new char[fileLen];
    try{
        fread(buffer, 1, fileLen, f);
        fclose(f);
        int bufPtr=-1, linePtr, lineLength;
        char line[1024];
        while(bufPtr < (fileLen-1)){
            linePtr=0;
            while(1){
                bufPtr++;
                if((bufPtr >= fileLen) || (buffer[bufPtr] == '\n') || (buffer[bufPtr] == '\r')) break;
                line[linePtr++] = buffer[bufPtr];
            }
            line[linePtr] = 0;
            lineLength = linePtr;

            //read the nonterminal
            String nonTerminal;
            linePtr = 0;
            while((line[linePtr] != '<') && (linePtr < lineLength)){
                if(line[linePtr] == '#') break; //it's a comment
                if(line[linePtr] > ' ') throw runtime_error("Grammar is not context-free");
                linePtr++;
            }
            if(line[linePtr] != '<') continue;  //allow for comments
            linePtr++;
            while((line[linePtr] != '>') && (linePtr < lineLength)){
                if(line[linePtr] > ' ') nonTerminal += String(line[linePtr]);
                linePtr++;
            }
            if(line[linePtr] != '>') continue;
            linePtr++;

            //look for the arrow symbol
            while((line[linePtr] != '-') && (linePtr < lineLength)){
                if(line[linePtr] > ' ') throw runtime_error("Grammar syntax error");
                linePtr++;
            }
            if(line[linePtr] != '-') continue;
            linePtr++;
            while((line[linePtr] != '>') && (linePtr < lineLength)){
                if(line[linePtr] > ' ') throw runtime_error("Grammar syntax error");
                linePtr++;
            }
            if(line[linePtr] != '>') continue;
            linePtr++;
            //got the arrow symbol; now read the replacement

            //but first, decide which group this production belongs to
            RewriteRuleGroup* theGroup=NULL;
            for(int i=0; i<ruleGroups->Count; i++){
                RewriteRuleGroup* group = (RewriteRuleGroup*)ruleGroups->Items[i];
                if(group->nonTerminal == nonTerminal){
                    theGroup = group; break;
                }
            }
            if(!theGroup){
                //ok, create a new group
                theGroup = new RewriteRuleGroup();
                ruleGroups->Add(theGroup);
                theGroup->nonTerminal = nonTerminal;
            }

            String rewrite;
            while(1){
                //go to beginning of rewrite
                while((line[linePtr] <= ' ') && (linePtr < lineLength)){
                    linePtr++;
                }
                if(linePtr >= lineLength) break;

                //Add a rule to the list
                RewriteRule* theRule = new RewriteRule();
                theGroup->rules->Add(theRule);

                //read the rewrite
                while((line[linePtr] > ' ') && (line[linePtr] != '|') && (linePtr < lineLength)){

                    rewrite = "";
                    
                    RewriteUnit* theUnit = new RewriteUnit();
                    theRule->units->Add(theUnit);

                    if(line[linePtr] == '<'){
                        //it's a nonterminal
                        theUnit->terminal = false;
                        linePtr++;
                        while((line[linePtr] != '>') && (linePtr < lineLength)){
                            if(line[linePtr] > ' '){
                                rewrite += String(line[linePtr]);
                            }
                            linePtr++;
                        }
                    }
                    else{
                        //it's a terminal
                        theUnit->terminal = true;
                        rewrite += String(line[linePtr]);
                    }
                    if((rewrite == "

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -