* Basic grammar and parser for the Fix language. We use libsglr and

friends to do the parsing.  The parse table is embedded in the Fix
  executable using bin2c, which converts an arbitrary file into a C
  character array.
This commit is contained in:
Eelco Dolstra 2003-10-29 16:05:03 +00:00
parent 4d728f6a36
commit b95a3dc45b
6 changed files with 298 additions and 7 deletions

View file

@ -1,8 +1,25 @@
bin_PROGRAMS = fix-ng bin_PROGRAMS = fix-ng
fix_ng_SOURCES = fix.cc fix_ng_SOURCES = fix.cc parser.cc
fix_ng_LDADD = ../libmain/libmain.a ../libnix/libnix.a ../boost/format/libformat.a \ fix_ng_LDADD = ../libmain/libmain.a ../libnix/libnix.a ../boost/format/libformat.a \
-L../../externals/inst/lib -ldb_cxx -lATerm -L../../externals/inst/lib -ldb_cxx -lsglr -lATB -lconversion -lasfix2 -lmept -lATerm
AM_CXXFLAGS = \ AM_CXXFLAGS = \
-I.. -I../../externals/inst/include -I../libnix -I../libmain -I.. -I../../externals/inst/include -I../libnix -I../libmain
# Parse table generation.
parser.o: parse-table.h
parse-table.h: fix.tbl bin2c
./bin2c fixParseTable < $< > $@ || (rm $@ && exit 1)
noinst_PROGRAMS = bin2c
bin2c_SOURCES = bin2c.c
%.tbl: %.sdf
../../externals/inst/bin/sdf2table -i $< -o $@
CLEANFILES = parse-table.h fix.tbl

23
src/fix-ng/bin2c.c Normal file
View file

@ -0,0 +1,23 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
void print(const char *format, ...)
{
va_list ap;
va_start(ap, format);
if (vprintf(format, ap) < 0) abort();
va_end(ap);
}
int main(int argc, char * * argv)
{
int c;
if (argc != 2) abort();
print("static unsigned char %s[] = {", argv[1]);
while ((c = getchar()) != EOF) {
print("0x%02x, ", (unsigned char) c);
}
print("};\n");
return 0;
}

View file

@ -1,13 +1,12 @@
#include <map> #include <map>
#include <iostream> #include <iostream>
#include "parser.hh"
#include "globals.hh" #include "globals.hh"
#include "normalise.hh" #include "normalise.hh"
#include "shared.hh" #include "shared.hh"
typedef ATerm Expr;
typedef map<ATerm, ATerm> NormalForms; typedef map<ATerm, ATerm> NormalForms;
typedef map<Path, PathSet> PkgPaths; typedef map<Path, PathSet> PkgPaths;
typedef map<Path, Hash> PkgHashes; typedef map<Path, Hash> PkgHashes;
@ -406,9 +405,7 @@ static Expr evalFile(EvalState & state, const Path & relPath)
{ {
Path path = searchPath(state.searchDirs, relPath); Path path = searchPath(state.searchDirs, relPath);
Nest nest(lvlTalkative, format("evaluating file `%1%'") % path); Nest nest(lvlTalkative, format("evaluating file `%1%'") % path);
Expr e = ATreadFromNamedFile(path.c_str()); Expr e = parseExprFromFile(path);
if (!e)
throw Error(format("unable to read a term from `%1%'") % path);
return evalExpr(state, e); return evalExpr(state, e);
} }

163
src/fix-ng/fix.sdf Normal file
View file

@ -0,0 +1,163 @@
definition
module Main
imports Fix
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Top level syntax.
module Fix
imports Fix-Exprs Fix-Layout
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Expressions.
module Fix-Exprs
imports Fix-Lexicals URI
exports
sorts Expr Bind
context-free syntax
Id
-> Expr {cons("Var")}
Int
-> Expr {cons("Int")}
Str
-> Expr {cons("Str")}
Uri
-> Expr {cons("Uri")}
Path
-> Expr {cons("Path")}
"(" Expr ")"
-> Expr {bracket}
Expr Expr
-> Expr {cons("Call"), left}
"{" {Id ","}* "}" ":" Expr
-> Expr {cons("Function"), right}
"{" {Bind ","}+ "}"
-> Expr {cons("Attrs")}
Id "=" Expr
-> Bind {cons("Bind")}
"[" {Expr ","}* "]"
-> Expr {cons("List")}
context-free priorities
Expr Expr -> Expr
> "{" {Id ","}* "}" ":" Expr -> Expr
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Lexical syntax.
module Fix-Lexicals
exports
sorts Id Path
lexical syntax
[a-zA-Z\_][a-zA-Z0-9\_\']* -> Id
[0-9]+ -> Int
"\"" ~[\n\"]* "\"" -> Str
PathComp ("/" PathComp)+ -> Path
[a-zA-Z0-9\.\_\-]+ -> PathComp
lexical restrictions
Id -/- [a-zA-Z0-9\_\']
Int -/- [0-9]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% URIs (RFC 2396, appendix A).
module URI
exports
sorts Uri
lexical syntax
Uscheme ":" (Uhierpath | Uopaquepath) -> Uri
(Unetpath | Uabspath) ("?" Uquery)? -> Uhierpath
Uuricnoslash Uuric* -> Uopaquepath
Uunreserved | Uescaped | [\;\?\:\@\&\=\+\$\,] -> Uuricnoslash
"//" Uauthority Uabspath? -> Unetpath
"/" Upathsegments -> Uabspath
Urelsegment Uabspath? -> Urelpath
(Uunreserved | Uescaped | [\;\@\&\=\+\$\,])+ -> Urelsegment
Ualpha (Ualpha | Udigit | [\+\-\.])* -> Uscheme
Userver | Uregname -> Uauthority
(Uunreserved | Uescaped | [\$\,\;\:\@\&\=\+])+ -> Uregname
((Uuserinfo "@") Uhostport) -> Userver
(Uunreserved | Uescaped | [\;\:\&\=\+\$\,])* -> Uuserinfo
Uhost (":" Uport)? -> Uhostport
Uhostname | UIPv4address -> Uhost
(Udomainlabel ".")+ Utoplabel "."? -> Uhostname
Ualphanum | Ualphanum (Ualphanum | "-")* Ualphanum -> Udomainlabel
Ualpha | Ualpha (Ualphanum | "-")* Ualphanum -> Utoplabel
Udigit+ "." Udigit+ "." Udigit+ "." Udigit+ -> UIPv4address
Udigit* -> Uport
Uabspath | Uopaquepart -> Upath
Usegment ("/" Usegment)* -> Upathsegments
Upchar* (";" Uparam)* -> Usegment
Upchar* -> Uparam
Uunreserved | Uescaped | [\:\@\&\=\+\$\,] -> Upchar
Uuric* -> Uquery
Uuric* -> Ufragment
Ureserved | Uunreserved | Uescaped -> Uuric
[\;\/\?\:\@\&\=\+\$\,] -> Ureserved
Ualphanum | Umark -> Uunreserved
[\-\_\.\!\~\*\'\(\)] -> Umark
"%" Uhex Uhex -> Uescaped
Udigit | [A-Fa-f] -> Uhex
Ualpha | Udigit -> Ualphanum
Ulowalpha | Uupalpha -> Ualpha
[a-z] -> Ulowalpha
[A-Z] -> Uupalpha
[0-9] -> Udigit
lexical restrictions
Uri -/- [a-zA-Z0-9\-\_\.\!\~\*\'\(\)]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Layout.
module Fix-Layout
exports
lexical syntax
[\ \t\n] -> LAYOUT
HashComment -> LAYOUT
Comment -> LAYOUT
"#" ~[\n]* [\n] -> HashComment
"//" ~[\n]* [\n] -> HashComment
"/*" ( ~[\*] | Asterisk )* "*/" -> Comment
[\*] -> Asterisk
lexical restrictions
Asterisk -/- [\/]
context-free restrictions
LAYOUT? -/- [\ \t\n] | [\#]
syntax
HashComment <START> -> <START>

76
src/fix-ng/parser.cc Normal file
View file

@ -0,0 +1,76 @@
extern "C" {
#include <sglr.h>
#include <asfix2.h>
}
#include "parser.hh"
#include "shared.hh"
#include "expr.hh"
#include "parse-table.h"
Expr parseExprFromFile(const Path & path)
{
/* Perhaps this is already an imploded parse tree? */
Expr e = ATreadFromNamedFile(path.c_str());
if (e) return e;
/* Initialise the SDF libraries. */
static bool initialised = false;
static ATerm parseTable = 0;
static language lang = 0;
if (!initialised) {
PT_initMEPTApi();
PT_initAsFix2Api();
SGinitParser(ATfalse);
ATprotect(&parseTable);
parseTable = ATreadFromBinaryString(
(char *) fixParseTable, sizeof fixParseTable);
if (!parseTable)
throw Error(format("cannot construct parse table term"));
ATprotect(&lang);
lang = ATmake("Fix");
if (!SGopenLanguageFromTerm(
(char *) programId.c_str(), lang, parseTable))
throw Error(format("cannot open language"));
SG_STARTSYMBOL_ON();
SG_OUTPUT_ON();
SG_ASFIX2ME_ON();
SG_AMBIGUITY_ERROR_ON();
initialised = true;
}
ATerm result = SGparseFile((char *) programId.c_str(), lang,
"Expr", (char *) path.c_str());
if (!result)
throw SysError(format("parse failed in `%1%'") % path);
if (SGisParseError(result))
throw Error(format("parse error in `%1%': %2%")
% path % printTerm(result));
PT_ParseTree tree = PT_makeParseTreeFromTerm(result);
if (!tree)
throw Error(format("cannot create parse tree"));
ATerm imploded = PT_implodeParseTree(tree,
ATtrue,
ATtrue,
ATtrue,
ATtrue,
ATtrue,
ATtrue,
ATfalse,
ATtrue,
ATtrue,
ATtrue,
ATfalse);
if (!imploded)
throw Error(format("cannot implode parse tree"));
return imploded;
}

15
src/fix-ng/parser.hh Normal file
View file

@ -0,0 +1,15 @@
#ifndef __PARSER_H
#define __PARSER_H
#include <string>
#include <aterm2.h>
#include "util.hh"
typedef ATerm Expr;
Expr parseExprFromFile(const Path & path);
#endif /* !__PARSER_H */