Difference between revisions of "Gold"
m (fix code format) |
m (code update) |
||
Line 205: | Line 205: | ||
<ExpressionList> ::= <Expression> | <ExpressionList> ::= <Expression> | ||
| <Expression> ',' <ExpressionList> | | <Expression> ',' <ExpressionList> | ||
+ | | | ||
<Variable> ::= id | <Variable> ::= id |
Revision as of 04:49, 11 September 2018
Gold is a free parsing system compatible with FreePascal that you can use to develop your own programming languages, scripting languages and interpreters. It uses LALR parsing, and a mix of BNF notation, character sets and regular expressions for terminals to define language grammars. Code and grammar are separated, so grammar is not tied to implementation language. This means that the same grammar can be loaded into engines made in different programming languages.
There is a feature comparison table of several parsers on Gold site, with special attention to Gold vs Yacc comparison.
Gold Parser Builder
GOLD Parser Builder can be used to create, modify and test languages in Windows IDE which can also run on Wine. Command line tools are also available.
Features:
- Grammar editor with syntax highlighting.
- Grammar-generating wizard.
- Test window to step through parsing of a sample source.
- Templating system that can generate lexers/parsers or skeleton programs for various languages (including Delphi and FreePascal).
- Importing/exporting YACC/Bison format. Exporting XML and HTML format.
- Interactive inspection of the compiled DFA and LALR tables.
Gold Engines
Goldie
Although Goldie is not originaly made for use with Pascal, it has many command line tools which can be useful to manipulate CGT files (Gold compiled grammar). You can show CGT file in human readable format, compile grammar to CGT file without Gold Parser Builder executable, and parse source according to some CGT file to save the resulting tokens and parsed tree to JSON file.
Examples
We will load pascal grammar into Gold Parser Builder 5.2, compile grammar to produce CGT file, load that CGT file into Lazarus Gold Engine (version compatible with Gold 5.20), and parse our pascal sample source code.
Calculator example
Grammar
Sample Source Code
Pascal example
Grammar
Pascal grammar is big, so you will need to expand it with the shown linked button on the right.
! ---------------------------------------------------------------------------------
! Standard Pascal Grammar
!
! modified by Avra (Zeljko Avramovic) for compatibility with latest version of Gold
! ---------------------------------------------------------------------------------
"Name" = 'Pascal'
"Version" = '1973'
"Author" = 'Niklaus Wirth'
"About" = 'PASCAL was developed by NIKLAUS WIRTH of the ETH Technical Institute of Zuerich in 1970-1971.(published in 1973)'
"Case Sensitive" = False
"Start Symbol" = <Program>
Comment Start = '{'
Comment End = '}'
Comment Line = '//'
{Hex Digit} = {Digit} + [ABCDEF]
{Id Head} = {Letter} + [_]
{Id Tail} = {Id Head} + {Digit}
{String Ch} = {Printable} - ['']
{Char Ch} = {Printable} - ['']
DecLiteral = [123456789]{digit}*
HexLiteral = '$'{Hex Digit}+
FloatLiteral = {Digit}*'.'{Digit}+
StringLiteral = ''( {String Ch} | '\'{Printable} )* ''
CharLiteral = '' ( {Char Ch} | '\'{Printable} )''
id = {Id Head}{Id Tail}*
<constant> ::= DecLiteral
| StringLiteral
| FloatLiteral
| HexLiteral
| CharLiteral
!=========================================== Program
<Program> ::= <ProgramHeader> <Declarations> <CompoundStatement> '.'
<ProgramHeader> ::= PROGRAM id ';'
| PROGRAM id '(' <IdList> ')' ';'
<Declarations> ::= <ConstantDefinitions> <TypeDefinitions> <VariableDeclarations> <ProcedureDeclarations>
<ConstantDefinitions> ::= CONST <ConstantDefinitionList>
|
<ConstantDefinitionList> ::= <ConstantDef>
| <ConstantDef> <ConstantDefinitionList>
<ConstantDef> ::= id '=' <constant> ';'
<TypeDefinitions> ::= TYPE <TypeDefinitionList>
|
<TypeDefinitionList> ::= <TypeDef>
| <TypeDef> <TypeDefinitionList>
<TypeDef> ::= id '=' <TypeSpecifier> ';'
<VariableDeclarations> ::= VAR <VariableDeclarationList>
|
<VariableDeclarationList> ::= <VariableDec>
| <VariableDec> <VariableDeclarationList>
<VariableDec> ::= <IdList> ':' <TypeSpecifier> ';'
<ProcedureDeclarations> ::= <ProcedureDec> <ProcedureDeclarations>
|
<ProcedureDec> ::= <ProcedureHeader> FORWARD ';'
| <ProcedureHeader> <Declarations> <CompoundStatement> ';'
| <FunctionHeader> FORWARD ';'
| <FunctionHeader> <Declarations> <CompoundStatement> ';'
<ProcedureHeader> ::= PROCEDURE id <Arguments> ';'
<FunctionHeader> ::= FUNCTION id <Arguments> ':' <TypeSpecifier> ';'
<Arguments> ::= '(' <ArgumentList> ')'
|
<ArgumentList> ::= <Arg>
| <Arg> ';' <ArgumentList>
<Arg> ::= <IdList> ':' <TypeSpecifier>
| VAR <IdList> ':' <TypeSpecifier>
<CompoundStatement> ::= BEGIN <StatementList> END
<StatementList> ::= <Statement>
| <Statement> ';' <StatementList>
<Statement> ::= <CompoundStatement>
| <AssignmentStatement>
| <ProcedureCall>
| <ForStatement>
| <WhileStatement>
| <IfStatement>
| <CaseStatement>
| <RepeatStatement>
|
<AssignmentStatement> ::= <Variable> ':=' <Expression>
! | <Variable> ':=' <FunctionCall>
<ProcedureCall> ::= id <Actuals>
<ForStatement> ::= FOR id ':=' <Expression> TO <Expression> DO <Statement>
| FOR id ':=' <Expression> DOWNTO <Expression> DO <Statement>
<WhileStatement> ::= WHILE <Expression> DO <Statement>
<IfStatement> ::= IF <Expression> THEN <Statement> ELSE <Statement>
<RepeatStatement> ::= REPEAT <StatementList> UNTIL <Expression>
<CaseStatement> ::= CASE <Expression> OF <CaseList> END
<CaseList> ::= <Case>
| <Case> ';' <CaseList>
<Case> ::= <ConstantList> ':' <Statement>
<ConstantList> ::= <constant>
| <constant> ',' <ConstantList>
<Expression> ::= <SimpleExpression>
| <SimpleExpression> '=' <SimpleExpression>
| <SimpleExpression> '<>' <SimpleExpression>
| <SimpleExpression> '<' <SimpleExpression>
| <SimpleExpression> '<=' <SimpleExpression>
| <SimpleExpression> '>' <SimpleExpression>
| <SimpleExpression> '>=' <SimpleExpression>
| <FunctionCall>
<SimpleExpression> ::= <Term>
| <SimpleExpression> '+' <Term>
| <SimpleExpression> '-' <Term>
| <SimpleExpression> OR <Term>
<Term> ::= <Factor>
| <Term> '*' <Factor>
| <Term> '/' <Factor>
| <Term> 'DIV' <Factor>
| <Term> 'MOD' <Factor>
| <Term> 'AND' <Factor>
<Factor> ::= '(' <Expression> ')'
| '+' <Factor>
| '-' <Factor>
| NOT <Factor>
| <constant>
| <Variable>
<FunctionCall> ::= id <Actuals>
<Actuals> ::= '(' <ExpressionList> ')'
<ExpressionList> ::= <Expression>
| <Expression> ',' <ExpressionList>
|
<Variable> ::= id
| <Variable> '.' id
| <Variable> '^'
| <Variable> '[' <ExpressionList> ']'
<TypeSpecifier> ::= id
| '^' <TypeSpecifier>
| '(' <IdList> ')'
| <constant> '..' <constant>
| ARRAY '[' <DimensionList> ']' OF <TypeSpecifier>
| RECORD <FieldList> END
| FILE OF <TypeSpecifier>
<DimensionList> ::= <Dimension>
| <Dimension> ',' <DimensionList>
<Dimension> ::= <constant> '..' <constant>
| id
<FieldList> ::= <Field>
| <Field> ';' <FieldList>
<Field> ::= <IdList> ':' <TypeSpecifier>
<IdList> ::= id
| id ',' <IdList>
Sample Source Code
program test; // simple pascal code for testing parser
const
PI = 3.1415;
var
a, b, c: real;
procedure hello(s: string; b, c: real);
begin
writeln(s);
writeln(b);
writeln(c);
end;
function square(a: real): real;
begin
result := a * a;
end;
function gethalf(a: real): real;
begin
result := a / 2;
end;
function twopi: real;
begin
result := pi * 2;
end;
begin
a := PI;
b := a * 10;
c := square(gethalf(twopi()));
hello('Hello World!', b, c);
end.