blob: 5cba32663cfbb844f719665000710dc16664810a [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "Common.h"
#include "Grammar.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
typedef struct Rule Rule;
struct Rule {
char *name;
Expression *expr;
Rule *next;
};
struct Grammar {
Rule **nextDef;
Rule *defList;
};
Rule *RuleNew(const char *name, Expression *expr)
{
Rule *def = (Rule *)calloc(1,sizeof(Rule));
def->name = strdup(name);
def->expr = expr;
return def;
}
void RuleFree(Rule *def)
{
free(def->name);
ExpressionFree(def->expr);
free(def);
}
Grammar *GrammarNew(void)
{
Grammar *gram = (Grammar *)calloc(1,sizeof(Grammar));
gram->nextDef = &gram->defList;
return gram;
}
void GrammarFree(Grammar *gram)
{
Rule *next;
for (Rule *def = gram->defList; def != NULL; def = next) {
next = def->next;
RuleFree(def);
}
free(gram);
}
void GrammarDefine(Grammar *gram, const char *name, Expression *expr)
{
Rule *def = RuleNew(name,expr);
*gram->nextDef = def;
gram->nextDef = &def->next;
}
Expression *GrammarLookup(Grammar *gram, const char *name)
{
for (Rule *def = gram->defList; def != NULL; def = def->next) {
if (!strcmp(def->name,name))
return def->expr;
}
return NULL;
}
static void GrammarResolveRecursive(Grammar *gram, Expression *expr, const char *ruleName)
{
if (ExpressionKind(expr) == IdentExpr) {
const char *targetName = ExprIdentValue(expr);
Expression *targetExpr = GrammarLookup(gram,targetName);
if (targetExpr == NULL) {
fprintf(stderr,"%s: Cannot resolve reference %s\n",ruleName,targetName);
exit(1);
}
ExprIdentSetTarget(expr,targetExpr);
}
else {
for (int i = 0; i < ExpressionCount(expr); i++)
GrammarResolveRecursive(gram,ExpressionChildAt(expr,i),ruleName);
}
}
void GrammarResolve(Grammar *gram)
{
for (Rule *def = gram->defList; def != NULL; def = def->next)
GrammarResolveRecursive(gram,def->expr,def->name);
}
void GrammarPrint(Grammar *gram, int exprAsTree)
{
int maxNameLen = 0;
for (Rule *def = gram->defList; def != NULL; def = def->next) {
int nameLen = strlen(def->name);
if (maxNameLen < nameLen)
maxNameLen = nameLen;
}
char *prefix = malloc(maxNameLen+2);
memset(prefix,' ',maxNameLen+1);
prefix[maxNameLen+1] = '\0';
for (Rule *def = gram->defList; def != NULL; def = def->next) {
int nameLen = strlen(def->name);
printf("%s",def->name);
if (exprAsTree) {
// Print the expression in tree format, with one line per node
printf("\n");
printf("\n");
printf(" ");
ExpressionPrintTree(def->expr," ",4);
printf("\n");
}
else {
// Print the expression in compact format, with one line per alternative
for (int i = nameLen; i < maxNameLen+1; i++)
printf(" ");
printf(": ");
ExpressionPrint(def->expr,0,prefix);
printf(";\n");
}
}
free(prefix);
}
const char *GrammarFirstRuleName(Grammar *gram)
{
if (gram->defList == NULL)
return NULL;
else
return gram->defList->name;
}