📄 grammar.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 + -